Serve per l'invio dei solleciti via mail. git-svn-id: svn://10.65.10.50/branches/R_10_00@22869 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			2503 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2503 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | ||
| #include <automask.h>   
 | ||
| #include <config.h>
 | ||
| #include <golem.h>
 | ||
| #include <execp.h>
 | ||
| #include <printer.h>
 | ||
| #include <printwin.h>
 | ||
| #include <toolfld.h>
 | ||
| #include <urldefid.h>
 | ||
| #include <utility.h>
 | ||
| #include <viswin.h>
 | ||
| 
 | ||
| #include <agasys.h>
 | ||
| 
 | ||
| #include <bagn001a.h> 
 | ||
| #include <bagn003.h> 
 | ||
| 
 | ||
| HIDDEN TPrinter* _printer = NULL;
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Maschera impostazione stampante (fatta come si deve dopo 10 anni!)
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TPrinter_setup_mask : public TAutomask
 | ||
| {
 | ||
| private:
 | ||
|   bool _skip_events;
 | ||
| 
 | ||
|   TString _pdev, _font;
 | ||
|   PRINT_RCD* _pcd;
 | ||
|   int _pcd_size;
 | ||
|   bool _pcd_owned;
 | ||
| 
 | ||
| protected:
 | ||
|   virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | ||
| 
 | ||
|   int fill_font_list();
 | ||
|   void fill_size_list();
 | ||
| 
 | ||
| public:
 | ||
|   void set_print_rcd(PRINT_RCD* pcd, int size, bool take_ownership);
 | ||
|   PRINT_RCD* get_print_rcd(int& size);
 | ||
| 
 | ||
|   TPrinter_setup_mask();
 | ||
|   virtual ~TPrinter_setup_mask();
 | ||
| };
 | ||
| 
 | ||
| void TPrinter_setup_mask::set_print_rcd(PRINT_RCD* pcd, int size, bool take_ownership)
 | ||
| {
 | ||
|   if (_pcd != NULL && _pcd_owned)
 | ||
|     xvt_print_destroy(_pcd);
 | ||
| 
 | ||
|   if (pcd == NULL)
 | ||
|   {
 | ||
|     _pcd_owned = true;
 | ||
|     _pcd = xvt_print_create(&_pcd_size);
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     _pcd_owned = take_ownership;
 | ||
|     _pcd = pcd;
 | ||
|     _pcd_size = size;
 | ||
|   }
 | ||
|   xvt_print_get_name(_pcd, _pdev.get_buffer(), _pdev.size());
 | ||
| }
 | ||
| 
 | ||
| PRINT_RCD* TPrinter_setup_mask::get_print_rcd(int& size)
 | ||
| {
 | ||
|   CHECK(_pcd != NULL && _pcd_size > 0, "Invalid PRINT_RCD");
 | ||
|   PRINT_RCD* pcd = _pcd;
 | ||
|   size = _pcd_size;
 | ||
| 
 | ||
|   _pcd_owned = false;
 | ||
|   _pcd = NULL;
 | ||
|   _pcd_size = 0;
 | ||
|   
 | ||
|   return pcd;
 | ||
| }
 | ||
| 
 | ||
| int TPrinter_setup_mask::fill_font_list()
 | ||
| {
 | ||
|   const int MAX_FAMILIES = 256;
 | ||
|   char* family[MAX_FAMILIES];
 | ||
|   const int num_families = (int)xvt_fmap_get_families(_pcd, family, MAX_FAMILIES);
 | ||
| 
 | ||
|   TToken_string fn(num_families * 16);  
 | ||
|   for (int i = 0; i < num_families; i++)
 | ||
|   {
 | ||
|     fn.add(family[i]);
 | ||
|     xvt_mem_free(family[i]);
 | ||
|   }  
 | ||
|   
 | ||
|   TString oldfont = _font; // Memorizzo il font corrente in quanto poi cambia
 | ||
|   TList_field& lst = lfield(MSK_FONT);
 | ||
|   lst.replace_items(fn, fn);  
 | ||
| 
 | ||
|   // Controlla se il font c'e' ancora
 | ||
|   if (fn.get_pos(oldfont) < 0)
 | ||
|     oldfont = fn.get(0);
 | ||
|   set(MSK_FONT, oldfont, 0x1);
 | ||
| 
 | ||
|   return num_families;
 | ||
| }
 | ||
| 
 | ||
| void TPrinter_setup_mask::fill_size_list()
 | ||
| {
 | ||
|   const int MAXSIZES = 128;
 | ||
|   long sizes[MAXSIZES]; 
 | ||
|   BOOLEAN scalable = FALSE;
 | ||
| 
 | ||
|   const int num_sizes = (int)xvt_fmap_get_family_sizes(_pcd, _font.get_buffer(), sizes, &scalable, MAXSIZES);
 | ||
| 
 | ||
|   TToken_string pn1;
 | ||
|   if (scalable)
 | ||
|   {
 | ||
|     for (int i = 4; i <= 32; i++)
 | ||
|       pn1.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()); // semper better than nothing
 | ||
|   }
 | ||
| 
 | ||
|   TList_field& lst = lfield(MSK_SIZE);
 | ||
|   const TString4 old_size = lst.get();
 | ||
|   lst.replace_items(pn1, pn1);
 | ||
|   lst.set(old_size);
 | ||
|   lst.enable(pn1.items() > 1);
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter_setup_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | ||
| {
 | ||
|   if (_skip_events)
 | ||
|     return true;
 | ||
| 
 | ||
|   bool ok = true;
 | ||
|   switch (o.dlg())
 | ||
|   {
 | ||
|   case MSK_DEFAULT:
 | ||
|     if (fe_modify)
 | ||
|     {
 | ||
|       if (o.get().full())
 | ||
|       {
 | ||
|         set_print_rcd(NULL, 0, true);
 | ||
|         set(MSK_PRINTERS, _pdev, 0x1);
 | ||
|       }
 | ||
|     }
 | ||
|     break;
 | ||
|   case MSK_PRINTERS:
 | ||
|     if (fe_modify)
 | ||
|     {             
 | ||
|       const TString& pdev = o.get();          // Nome stampante corrente
 | ||
|       if (pdev != _pdev)
 | ||
|       {
 | ||
|         TWait_cursor hourglass;
 | ||
|         int tmp_size = 0;
 | ||
|         PRINT_RCD* tmp_pcd = xvt_print_create_by_name(&tmp_size, pdev);
 | ||
|         if (tmp_pcd != NULL)
 | ||
|         {
 | ||
|           set_print_rcd(tmp_pcd, tmp_size, true);
 | ||
|           if (fill_font_list() <= 0)
 | ||
|             return error_box(TR("Impossibile inizializzare la stampante %s"), (const char*)pdev);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     break;
 | ||
|   case MSK_FONT:
 | ||
|     if (e == fe_modify)
 | ||
|     {
 | ||
|       const TString& family = o.get();
 | ||
|       if (_font != family)
 | ||
|       {
 | ||
|         TWait_cursor hourglass;
 | ||
|         _font = family;
 | ||
|         fill_size_list();
 | ||
|       }
 | ||
|     }   
 | ||
|     break;
 | ||
|   case MSK_SIZE:
 | ||
|     if (e == fe_modify || e == fe_close)
 | ||
|     {
 | ||
|       const int fs = atoi(o.get());
 | ||
|       const int ls = 72 / get_int(MSK_LINES);
 | ||
|       if (fs < ls/2 || fs > 4*ls/3)
 | ||
|         ok = yesno_box(TR("La dimensione del carattere non e' adeguata all'interlinea\nSi desidera continuare ugualmente?"));
 | ||
|     }
 | ||
|     break;
 | ||
|   case DLG_SETPRINT:
 | ||
|     if (e == fe_button)
 | ||
|     {
 | ||
|       if (xvt_dm_post_page_setup(_pcd))
 | ||
|       {                         
 | ||
|         // see if user has changed printer
 | ||
|         // determine name of currently selected printer 
 | ||
|         TString256 name;
 | ||
|         xvt_print_get_name(_pcd, name.get_buffer(), name.size());
 | ||
|         set(MSK_PRINTERS, name, 0x1);
 | ||
|         on_field_event(lfield(MSK_ORIENTATION), fe_init, 0);
 | ||
|       }
 | ||
|     }
 | ||
|     break;
 | ||
|   case MSK_ORIENTATION:
 | ||
|     if (e == fe_init)
 | ||
|     {
 | ||
|       long ph, pw;
 | ||
|       xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _pcd, &ph, &pw, NULL, NULL);
 | ||
|       o.set(ph > pw ? "1" : "2");
 | ||
|     } else
 | ||
|     if (e == fe_modify || e == fe_close)
 | ||
|     {
 | ||
|       long ph, pw;
 | ||
|       xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _pcd, &ph, &pw, NULL, NULL);
 | ||
|       const int priter_orientation = ph > pw ? 1 : 2;
 | ||
|       const int user_orientation = atoi(o.get());
 | ||
|       if (user_orientation != priter_orientation) // Scambia orientamento della carta
 | ||
|         xvt_app_escape(XVT_ESC_SET_PRINTER_INFO, _pcd, &pw, &ph, NULL, NULL);
 | ||
|     }
 | ||
|     break;
 | ||
|   default:
 | ||
|     break;
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| TPrinter_setup_mask::TPrinter_setup_mask() 
 | ||
|                    : TAutomask("bagn001a"), _pcd(NULL), _pcd_size(0), _pcd_owned(false), _pdev(128)
 | ||
| {
 | ||
|   TPrinter& pr = printer();
 | ||
|   set(MSK_FILENAME, pr.get_printerfile());
 | ||
|   
 | ||
|   const bool can_save = pr._config == "Printer";
 | ||
|   enable(DLG_OK, can_save);
 | ||
| 
 | ||
|   if (pr.forced_default_printer())
 | ||
|     set_print_rcd(NULL, 0, true);
 | ||
|   else
 | ||
|     set_print_rcd(pr._print_rcd, pr._print_rcd_size, false);
 | ||
| 
 | ||
|   // Crea la lista delle stampanti
 | ||
|   TToken_string pn2; 
 | ||
|   SLIST plist = xvt_print_list_devices();             
 | ||
|   for (SLIST_ELT pitem = xvt_slist_get_first(plist);
 | ||
|        pitem != NULL; pitem = xvt_slist_get_next(plist, pitem)) 
 | ||
|   {
 | ||
|     const char* pname = xvt_slist_get(plist, pitem, NULL);
 | ||
|     pn2.add(pname);
 | ||
|   }
 | ||
|   xvt_slist_destroy(plist);
 | ||
|   
 | ||
|   _skip_events = true;
 | ||
|   
 | ||
|   if (pr._printertype == fileprinter)
 | ||
|     set(MSK_TYPE, "1");
 | ||
|   else if (pr._printertype == screenvis)
 | ||
|     set(MSK_TYPE, "2");
 | ||
|   else if (pr._printertype == acrobatprinter)
 | ||
|     set(MSK_TYPE, "4");
 | ||
|   else
 | ||
|     set(MSK_TYPE, "0");
 | ||
| 
 | ||
|   TList_field& plst = lfield(MSK_PRINTERS);
 | ||
|   plst.replace_items(pn2, pn2);                // Genera printer list
 | ||
|   set(MSK_PRINTERS, _pdev);               
 | ||
|   
 | ||
|   _font = pr._fontname;
 | ||
|   fill_font_list();
 | ||
|   fill_size_list();
 | ||
| 
 | ||
|   set(MSK_FONT, _font);       // Fare solo quando la lista e' piena
 | ||
|   set(MSK_SIZE, pr._ch_size); // Fare solo quando la lista e' piena
 | ||
|   set(MSK_LINES, pr._lines_per_inch);
 | ||
| 
 | ||
|   set(MSK_ISGRAPHICS, pr.isgraphics() ? "X" : "");
 | ||
|   set(MSK_DEFAULT, pr.forced_default_printer() ? "X" : "");
 | ||
| 
 | ||
|   TButton_tool& sp = (TButton_tool&)field(DLG_SETPRINT);
 | ||
|   sp.set_exit_key(0); // Evita chiamate ricorsive all'impostazione stampante
 | ||
| 
 | ||
|   _skip_events = false;
 | ||
| }
 | ||
| 
 | ||
| TPrinter_setup_mask::~TPrinter_setup_mask()
 | ||
| {
 | ||
|   if (_pcd_owned && _pcd != NULL)
 | ||
|   {
 | ||
|     xvt_print_destroy(_pcd);
 | ||
|     _pcd_owned = false;
 | ||
|     _pcd = NULL;
 | ||
|     _pcd_size = 0;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TPrinter
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| TPrinter& printer()
 | ||
| {
 | ||
|   if (_printer == NULL)
 | ||
|     _printer = new TPrinter;
 | ||
|   return *_printer;
 | ||
| }
 | ||
| 
 | ||
| void printer_destroy()
 | ||
| {
 | ||
|   if (_printer != NULL)
 | ||
|   {
 | ||
|     delete _printer;
 | ||
|     _printer = NULL;
 | ||
|   }  
 | ||
| }
 | ||
| 
 | ||
| // ----------------------------------------------------------------------
 | ||
| // TPrint_intersector
 | ||
| // ----------------------------------------------------------------------
 | ||
| 
 | ||
| // TPrint_intersector: calcola intersezioni tra elementi grafici e 
 | ||
| // restituisce, riga per riga, i necessari caratteri di fincatura per
 | ||
| // finculare in modo carattere
 | ||
| // usata da viswin e printwin
 | ||
| class TPrint_intersector : public TString_array
 | ||
| {
 | ||
|   const char* _fink;    
 | ||
| 
 | ||
|   char check_intersection(int x, int y, char ch);
 | ||
|   void h_line(int x1, int y1, int len);
 | ||
|   void v_line(int x1, int y1, int len);
 | ||
| 
 | ||
|   // caratteri fincazione: l'ho fatto perche' e' inline                                              
 | ||
|   char f_topleft()      const { return _fink[0];  }                                              
 | ||
|   char f_topmiddle()    const { return _fink[1];  }                                              
 | ||
|   char f_topright()     const { return _fink[2];  }                                              
 | ||
|   char f_botleft()      const { return _fink[3];  }                                              
 | ||
|   char f_botmiddle()    const { return _fink[4];  }                                              
 | ||
|   char f_botright()     const { return _fink[5];  }                                              
 | ||
|   char f_centerleft()   const { return _fink[6];  }                                              
 | ||
|   char f_centermiddle() const { return _fink[7];  }                                              
 | ||
|   char f_centerright()  const { return _fink[8];  }                                              
 | ||
|   char f_horizontal()   const { return _fink[9];  }                                              
 | ||
|   char f_vertical()     const { return _fink[10]; }                                              
 | ||
| 
 | ||
| public:                                                            
 | ||
|   // aggiunge un elemento grafico                                                           
 | ||
|   void add(TGraphic_shape s, int x1, int y1, int x2, int y2);
 | ||
|   // aggiunge alla stringa passata i necessari caratteri, leggendo
 | ||
|   // dalla pagina interna
 | ||
|   const char* get_chars(int line) const;  
 | ||
|   // sbianca tutto
 | ||
|   void clear();
 | ||
|   
 | ||
|   TPrint_intersector(const char* fink, int pagesize) : TString_array(pagesize) , _fink(fink) {}
 | ||
|   virtual ~TPrint_intersector() {}
 | ||
| };
 | ||
| 
 | ||
| char TPrint_intersector::check_intersection(int x, int y, char ch)
 | ||
| { 
 | ||
|   char a = ' ', b = ' ', c = ' ', d = ' ';
 | ||
|   if (y > 0 && objptr(y-1) != NULL)
 | ||
|     b = row(y-1)[x];
 | ||
|   if (objptr(y+1) != NULL)
 | ||
|     d = row(y+1)[x];
 | ||
|   if (x > 0) a = row(y)[x-1];
 | ||
|   if (x < row(y).len()-1) c = row(y)[x+1]; 
 | ||
|   
 | ||
|   if (a == ' ' && b == ' ' && c != ' ' && d != ' ')
 | ||
|     ch = f_topleft();
 | ||
|   else if (a == ' ' && b != ' ' && c != ' ' && d == ' ')
 | ||
|     ch = f_botleft();
 | ||
|   else if (a != ' ' && b != ' ' && c == ' ' && d == ' ')
 | ||
|     ch = f_botright();
 | ||
|   else if (a != ' ' && b == ' ' && c == ' ' && d != ' ')
 | ||
|     ch = f_topright();
 | ||
|   else if (a != ' ' && b != ' ' && c == ' ' && d != ' ')
 | ||
|     ch = f_centerright();
 | ||
|   else if (a == ' ' && b != ' ' && c != ' ' && d != ' ')
 | ||
|     ch = f_centerleft();
 | ||
|   else if (a != ' ' && b != ' ' && c != ' ' && d == ' ')
 | ||
|     ch = f_botmiddle();
 | ||
|   else if (a != ' ' && b == ' ' && c != ' ' && d != ' ')
 | ||
|     ch = f_topmiddle();
 | ||
|   else if ((a != ' ' && b != ' ' && c != ' ' && d != ' ') ||
 | ||
|            ((a != ' ' && b == ' ' && c != ' ' && d == ' ') && ch == f_vertical()) ||
 | ||
|            ((a == ' ' && b != ' ' && c == ' ' && d != ' ') && ch == f_horizontal()))
 | ||
|     ch = f_centermiddle();
 | ||
|      
 | ||
|   return ch;
 | ||
| }
 | ||
| 
 | ||
| void TPrint_intersector::h_line(int x1, int y1, int len)
 | ||
| {          
 | ||
|   if (objptr(y1) == NULL) 
 | ||
|   {
 | ||
|     TString* ss = new TString(256, ' ');
 | ||
|     TArray::add(ss, y1);
 | ||
|   }       
 | ||
|   
 | ||
|   TString& s = row(y1);
 | ||
|   int i;
 | ||
|   for (i = x1; i < x1+len; i++)
 | ||
|     s[i] = f_horizontal();
 | ||
|   for (i = x1; i < x1+len; i++)
 | ||
|     s[i] = check_intersection(i, y1, f_horizontal());
 | ||
| }
 | ||
| 
 | ||
| void TPrint_intersector::v_line(int x1, int y1, int len)
 | ||
| {  
 | ||
| 	int i;
 | ||
|   for (i = y1; i < y1+len; i++)
 | ||
|   {
 | ||
|     if (objptr(i) == NULL) 
 | ||
|     {
 | ||
|       TString* ss = new TString(256, ' ');
 | ||
|       TArray::add(ss, i);
 | ||
|     }
 | ||
|     row(i)[x1] = f_vertical();
 | ||
|   }
 | ||
|   for (i = y1; i < y1+len; i++)
 | ||
|     row(i)[x1] = check_intersection(x1, i, f_vertical());
 | ||
| }
 | ||
| 
 | ||
| void TPrint_intersector::add(TGraphic_shape s, int x1, int y1, int x2, int y2)
 | ||
| {     
 | ||
|   // rows start at 0
 | ||
|   y1 --;  y2 --;
 | ||
|   // columns pure, ma e' possibile che siano gia' 0 se la generazione
 | ||
|   // e' stata automatica (colonna 1. campo - 1)
 | ||
|   if (x1 > 0) x1 --;
 | ||
|   if (x2 > 0) x2 --;
 | ||
| 
 | ||
|   switch (s)
 | ||
|   {
 | ||
|     case line:   
 | ||
|       if (x1 == x2)       // vertical
 | ||
|         v_line(x1, y1, y2-y1+1);
 | ||
|       else if (y1 == y2)  // horizontal
 | ||
|         h_line(x1,y1, x2-x1+1);
 | ||
|       else error_box("Linee oblique non supportate in modalita' testo");
 | ||
|       break;
 | ||
|     case box: 
 | ||
|       h_line(x1, y1, x2-x1+1);
 | ||
|       h_line(x1, y2, x2-x1+1);
 | ||
|       v_line(x1, y1, y2-y1+1);
 | ||
|       v_line(x2, y1, y2-y1+1);
 | ||
|       break;
 | ||
|     default:
 | ||
|       break;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| const char* TPrint_intersector::get_chars(int line) const
 | ||
| {
 | ||
|    if (objptr(line) == NULL)
 | ||
|      return "";
 | ||
|    else
 | ||
|      return row(line);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_intersector::clear()
 | ||
| {  
 | ||
|   for (int i = 0; i < items(); i++)
 | ||
|   {
 | ||
|     TString* s = (TString*)objptr(i);
 | ||
|     if (s != NULL)
 | ||
|       s->spaces();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TPrint_txt_info
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| struct TPrint_txt_info
 | ||
| {
 | ||
|   TTextfile* _txt;
 | ||
|   TFilename _pdf_file;
 | ||
|   word _copies;
 | ||
|   word _pagefrom;
 | ||
|   word _pageto;
 | ||
|   word _lastpage;
 | ||
| 
 | ||
|   bool edit();
 | ||
|   bool editpdf();
 | ||
|   TPrint_txt_info(TTextfile& txt);
 | ||
| };
 | ||
| 
 | ||
| bool TPrint_txt_info::edit()
 | ||
| {
 | ||
|   TPrinter& p = printer();
 | ||
|   TMask msk("bagn003");
 | ||
|   msk.set(F_PRINTER, p.printername());
 | ||
|   msk.set(F_FORM, p.get_form_name());
 | ||
|   msk.set(F_FONT, p.fontname());
 | ||
|   msk.set(F_SIZE, p.get_char_size());
 | ||
|   msk.set(F_LINES, p.get_lines_per_inch());
 | ||
|   msk.set(F_ORIENT, p.is_portrait() ? 1 : 2);
 | ||
|   msk.set(F_ISGRAPHICS, p.isgraphics());
 | ||
|   msk.set(F_FROMPAGE, _pagefrom);
 | ||
|   msk.set(F_TOPAGE, _lastpage);
 | ||
|   msk.set(F_COPIES, _copies);
 | ||
|   const bool ok = msk.run() == K_ENTER;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     _copies = msk.get_int(F_COPIES);
 | ||
|     _pagefrom = msk.get_int(F_FROMPAGE);
 | ||
|     _pageto = msk.get_int(F_TOPAGE);
 | ||
|     if (_pageto < _pagefrom || _pageto >= _lastpage)
 | ||
|       _pageto = 0;
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrint_txt_info::editpdf()
 | ||
| {
 | ||
|   TPrinter& p = printer();
 | ||
|   TMask msk("bagn009");
 | ||
| 
 | ||
|   TFilename f; f.tempdir();
 | ||
|   msk.set(F_PRINTER, f);
 | ||
|   f = p.get_form_name().name(); f.ext("");
 | ||
|   msk.set(F_FORM, f);
 | ||
| 
 | ||
|   const bool ok = msk.run() == K_ENTER;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     _copies = 1;
 | ||
|     _pagefrom = 1;
 | ||
|     _pageto = 0;
 | ||
|     _pdf_file = msk.get(F_PRINTER);
 | ||
|     _pdf_file.add(msk.get(F_FORM));
 | ||
|     _pdf_file.ext(".pdf");
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| TPrint_txt_info::TPrint_txt_info(TTextfile& txt) 
 | ||
|                : _txt(&txt), _copies(1), _pagefrom(1), _pageto(0) 
 | ||
| { 
 | ||
|   const word ps = printer().formlen(); 
 | ||
|   const long li = txt.lines();
 | ||
|   _lastpage = word((li+ps-1) / ps);
 | ||
| }
 | ||
| 
 | ||
| // @cmember Ritorna vero se la stampante e' generica/solo testo
 | ||
| bool TPrinter::is_generic() const
 | ||
| { 
 | ||
|   bool yes = _dots_per_line == 1;
 | ||
|   if (!yes)
 | ||
|     yes = _prname.find("Generic") >= 0;
 | ||
|   return yes; 
 | ||
| }
 | ||
| 
 | ||
| // @cmember Ritorna vero se la stampante e' PDF
 | ||
| bool TPrinter::is_pdf() const
 | ||
| { 
 | ||
|   return xvt_print_is_pdf(_print_rcd) != 0;
 | ||
| }
 | ||
| 
 | ||
| // @cmember Ritorna vero se sono attivati gli elementi grafici
 | ||
| bool TPrinter::isgraphics() const 
 | ||
| { 
 | ||
|   return _isgraphics; 
 | ||
| }
 | ||
| 
 | ||
| // @cmember Attivati gli elementi grafici se possibile
 | ||
| bool TPrinter::set_graphics(bool g) 
 | ||
| { 
 | ||
|   _isgraphics = g && !is_generic(); 
 | ||
|   return _isgraphics;
 | ||
| }
 | ||
| 
 | ||
| BOOLEAN TPrinter::start_print(long data)
 | ||
| {
 | ||
|   const TPrint_txt_info *pd = (TPrint_txt_info *) data;
 | ||
|   TTextfile& txt = *(pd->_txt);
 | ||
|   TPrinter& stampante = printer();
 | ||
|    
 | ||
|   const int vofs = stampante.get_line_offset(); 
 | ||
|   const int hofs = stampante.get_column_offset();
 | ||
|   
 | ||
|   if (stampante.is_generic() && (vofs != 0 || hofs != 0))
 | ||
|   {                  
 | ||
|     TTextfile new_txt;                   
 | ||
|     TString s(256);
 | ||
|     const long last_row = txt.lines();
 | ||
|     long out_row = 0;
 | ||
|     
 | ||
|     for (long row = (vofs < 0 ? -vofs : 0); row < last_row; row++)    
 | ||
|     {                          
 | ||
|        const int pagelen = stampante.formlen();
 | ||
|        const int page_row = (int) (out_row % pagelen);
 | ||
|        
 | ||
|        if (vofs > 0 && page_row == 0)
 | ||
|        {     
 | ||
|          const int page = (int) (out_row / pagelen);
 | ||
| 
 | ||
|          for (int i = vofs; i > 0; i--)
 | ||
|          {
 | ||
|            out_row++;
 | ||
|            if (page > 0)
 | ||
|              row++;
 | ||
|            new_txt.append("");
 | ||
|          }
 | ||
|        }               
 | ||
|        if (vofs < 0 && page_row == pagelen + vofs)
 | ||
|        {
 | ||
|          for (int i = -vofs; i > 0; i--)
 | ||
|          {
 | ||
|            out_row++;                     
 | ||
|            row++;
 | ||
|            new_txt.append("");
 | ||
|          }
 | ||
|        }
 | ||
|        s = txt.line(row);
 | ||
|        if (hofs < 0)
 | ||
|          s.ltrim(-hofs);
 | ||
|        else
 | ||
|          if(hofs > 0)
 | ||
|            s.lpad(s.len() + hofs);
 | ||
|        new_txt.append(s);
 | ||
|        out_row++;
 | ||
|     }
 | ||
|     TPrintwin pw(new_txt);
 | ||
|     pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies);
 | ||
|     return pw.aborted();
 | ||
|   }                 
 | ||
|   else
 | ||
|   {
 | ||
|     TPrintwin pw(txt);
 | ||
|     if (pw.win() != NULL_WIN)
 | ||
|       pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies);
 | ||
|     return pw.aborted();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| BOOLEAN TPrinter::start_print_pdf(long data)
 | ||
| {
 | ||
|   const TPrint_txt_info *pd = (TPrint_txt_info *) data;
 | ||
|   TTextfile& txt = *(pd->_txt);
 | ||
|    
 | ||
|   TPrintwin pw(txt, pd->_pdf_file);
 | ||
|   if (pw.win() != NULL_WIN)
 | ||
|     pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies);
 | ||
|   return pw.aborted();
 | ||
| }
 | ||
| 
 | ||
| // utils del caz
 | ||
| HIDDEN int read_int (const char *s, int &n, int &cnt)
 | ||
| {
 | ||
|   char nbuf[16];
 | ||
|   
 | ||
|   while (!isdigit (s[cnt]))
 | ||
|     cnt++;
 | ||
| 
 | ||
| 	int j;
 | ||
|   for (j = 0; isdigit (s[cnt]); j++)
 | ||
|     nbuf[j] = s[cnt++];
 | ||
|   nbuf[j] = '\0';
 | ||
| 
 | ||
|   return n = atoi (nbuf);
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::parse_background(const char* bg_desc, TString_array& background)
 | ||
| {
 | ||
|   TString_array pix;
 | ||
|   char op, ch;
 | ||
|   int x1, x2, y1, y2;
 | ||
|   int id, cnt = 0; 
 | ||
|   
 | ||
|   TToken_string tt;
 | ||
|   TFilename bmp;
 | ||
| 
 | ||
|   if (!_fink_mode && _finker == NULL)
 | ||
|     _finker = new TPrint_intersector(_fink, _formlen);
 | ||
|   else if (_finker)
 | ||
|     _finker->clear();
 | ||
| 
 | ||
|   while ((ch = bg_desc[cnt++]) != '\0')
 | ||
|   {
 | ||
|     op = ch;
 | ||
|     tt = "";
 | ||
|     char bf[2];
 | ||
|     bf[1] = '\0';
 | ||
|     switch (op)
 | ||
|     {
 | ||
|     case ' ':               
 | ||
|     case '\t':
 | ||
|     case '\n':
 | ||
|       continue;             // ignore whitespace
 | ||
|       break;
 | ||
|     case 'i':
 | ||
|       cnt++;
 | ||
|       for (x1 = 0; bg_desc[cnt] != ','; x1++)
 | ||
|         bmp[x1] = bg_desc[cnt++];
 | ||
|       bmp[x1] = '\0';
 | ||
|       id = _image_names.find(bmp);
 | ||
|       if (id < 0) id = _image_names.add(bmp);
 | ||
|       read_int(bg_desc, x1, cnt); if (x1 <= 0) x1 = 1;
 | ||
|       read_int(bg_desc, y1, cnt); if (y1 <= 0) y1 = 1;
 | ||
|       read_int(bg_desc, x2, cnt); if (x2 <= 0) x2 = formwidth();
 | ||
|       read_int(bg_desc, y2, cnt); if (y2 <= 0) y2 = formlen();
 | ||
|       cnt++;
 | ||
|       if (_isgraphics)
 | ||
|       {
 | ||
|         tt << op;
 | ||
|         tt.add(id);
 | ||
|         tt.add(x1);
 | ||
|         tt.add(y1);
 | ||
|         tt.add(x2);  
 | ||
|         tt.add(y2); 
 | ||
|       } 
 | ||
|       break;  
 | ||
|     case 'l':               // line
 | ||
| 
 | ||
|     case 'b':               // box
 | ||
| 
 | ||
|     case 'r':               // round box
 | ||
|       cnt++;
 | ||
|       read_int (bg_desc, x1, cnt);
 | ||
|       read_int (bg_desc, y1, cnt);
 | ||
|       read_int (bg_desc, x2, cnt);
 | ||
|       read_int (bg_desc, y2, cnt);
 | ||
|       cnt++;                // skip separator
 | ||
|       if (_isgraphics && _fink_mode) 
 | ||
|       {
 | ||
|         tt << op;
 | ||
|         tt.add (x1 - 1);
 | ||
|         tt.add (y1 - 1);
 | ||
|         tt.add (x2 - 1);
 | ||
|         tt.add (y2 - 1); 
 | ||
|       }
 | ||
|       else
 | ||
|       {
 | ||
|         TGraphic_shape s = op == 'b' ? box : line;
 | ||
|         _finker->add(s, x1, y1, x2, y2);
 | ||
|       }
 | ||
|       break;
 | ||
|     case 't':               // text
 | ||
|       cnt++;
 | ||
|       read_int (bg_desc, x1, cnt);
 | ||
|       read_int (bg_desc, y1, cnt);
 | ||
|       cnt++;
 | ||
|       tt << op;
 | ||
|       tt.add (x1-1);
 | ||
|       tt.add (y1-1);
 | ||
|       tt << '|';
 | ||
|       while ((ch = bg_desc[cnt++]) != '}')
 | ||
|         tt << ch;
 | ||
|       break;
 | ||
|       
 | ||
|     case 'P':           // set pen style
 | ||
| 
 | ||
|     case 'B':           // set brush
 | ||
| 
 | ||
|     case 'W':           // set line width 
 | ||
| 
 | ||
|     case 'C':           // set pen color
 | ||
| 
 | ||
|       tt << op;
 | ||
|       bf[0] = bg_desc[cnt++];
 | ||
|       tt.add (bf);
 | ||
|       break;
 | ||
|     default:
 | ||
|       yesnofatal_box ("Unknown background opcode: %c", op);
 | ||
|       break;
 | ||
|     }
 | ||
|     pix.add (tt);
 | ||
|   }
 | ||
|                                
 | ||
|   // now build row descriptions
 | ||
| 
 | ||
|   // colors are listed in printapp:
 | ||
| 
 | ||
|   char curcol = 'n';
 | ||
|   char curpen = 'n';
 | ||
|   char curpat = 'n';
 | ||
|   char curwid = '1';
 | ||
| 
 | ||
|   for (int l = 0; l < _formlen; l++)
 | ||
|   {
 | ||
|     if (background.objptr(l) == NULL)            // Se la riga non esiste creala
 | ||
|     {                                        
 | ||
|       TToken_string* r = new TToken_string(15);           
 | ||
|       if (curcol != 'n') *r << 'C' << curcol;    // Setta valori se diversi da default
 | ||
|       if (curpat != 'n') *r << 'B' << curpat;
 | ||
|       if (curwid != '1') *r << 'W' << curwid;
 | ||
|       if (curpen != 'n') *r << 'P' << curcol;
 | ||
|       background.add(r, l);
 | ||
|     }
 | ||
|     
 | ||
|     TString& rwd = background.row(l);
 | ||
|     for (int j = 0; j < pix.items(); j++)
 | ||
|     {
 | ||
|       TToken_string& tt = pix.row(j);
 | ||
| 
 | ||
|       // la stringa contiene l'opcode piu' i parametri in binario, 
 | ||
|       // incrementati di 1 per evitare lo 0
 | ||
| 
 | ||
|       switch (tt.get_char(0))
 | ||
|       {
 | ||
|       case 'b':
 | ||
|         x1 = tt.get_int (1) + 1;
 | ||
|         y1 = tt.get_int (2) + 1;
 | ||
|         x2 = tt.get_int (3) + 1;
 | ||
|         y2 = tt.get_int (4) + 1;
 | ||
|         if (y1 == l + 1)        // at ze biginnin
 | ||
|         {
 | ||
|           rwd << 'u' << char (x1);
 | ||
|           rwd << 'r' << char (x1) << char (x2);
 | ||
|           rwd << 'u' << char (x2);
 | ||
|         }
 | ||
|         else if (y2 == l + 1)   // at ze end
 | ||
|         {
 | ||
|           rwd << 'o' << char (x1);
 | ||
|           rwd << 'r' << char (x1) << char (x2);
 | ||
|           rwd << 'o' << char (x2);
 | ||
|         }
 | ||
|         else if (y1 < l + 1 && y2 > l + 1)      // in ze middol
 | ||
|         {
 | ||
|           rwd << 'v' << char (x1);
 | ||
|           rwd << 'v' << char (x2);
 | ||
|         }
 | ||
|         break;
 | ||
|       case 'l':
 | ||
|         x1 = tt.get_int (1) + 1;
 | ||
|         y1 = tt.get_int (2) + 1;
 | ||
|         x2 = tt.get_int (3) + 1;
 | ||
|         y2 = tt.get_int (4) + 1;
 | ||
|         if (y1 == y2 && y1 == l + 1)    // orizzontale 
 | ||
|         {
 | ||
|           rwd << 'h' << char (x1) << char (x2);
 | ||
|         }
 | ||
|         else if (y1 <= l + 1 && y2 >= l + 1)    // verticale  
 | ||
| 
 | ||
|         {
 | ||
|           rwd << 'v' << char (x1);
 | ||
|         }
 | ||
|         break;
 | ||
|       case 'r':
 | ||
|         x1 = tt.get_int (1) + 1;
 | ||
|         y1 = tt.get_int (2) + 1;
 | ||
|         x2 = tt.get_int (3) + 1;
 | ||
|         y2 = tt.get_int (4) + 1;
 | ||
|         if (y1 == y2)    // orizzontale 
 | ||
|         {                          
 | ||
|           if (y1 == l+1)
 | ||
|             rwd << 'r' << char (x1) << char (x2);
 | ||
|         }
 | ||
|         else 
 | ||
|         {                  
 | ||
|           const int l1 = l+1;
 | ||
|           if (l1 >= y1 && l1 <= y2)    // verticale  
 | ||
|           {                       
 | ||
|             char code = 'v';
 | ||
|             if (y1 == l1) code = 'u'; else 
 | ||
|             if (y2 == l1) code = 'o';
 | ||
|             rwd << code << char(x1);
 | ||
|           }  
 | ||
|         }
 | ||
|         break;
 | ||
|       case 't':
 | ||
|         x1 = tt.get_int (1) + 1;
 | ||
|         y1 = tt.get_int (2) + 1;        // al gh'e'
 | ||
|         if (y1 == l + 1)
 | ||
|         {}
 | ||
|         break; 
 | ||
|       case 'i':
 | ||
|         id = tt.get_int();
 | ||
|         x1 = tt.get_int();
 | ||
|         y1 = tt.get_int();
 | ||
|         x2 = tt.get_int();
 | ||
|         y2 = tt.get_int();
 | ||
|         if (l+1 >= y1 && l+1 <= y2)                                    
 | ||
|           rwd << 'i' << char(id+1) << char(l-y1+2) << char(x1) 
 | ||
|             << char(x2-x1+1) << char(y2-y1+1);
 | ||
|         break;  
 | ||
|       case 'W':
 | ||
|         curwid = *(tt.get (1));
 | ||
|         rwd << 'W' << curwid;
 | ||
|         break;
 | ||
|       case 'P':
 | ||
|         curpen = *(tt.get (1));
 | ||
|         rwd << 'P' << curpen;
 | ||
|         break;
 | ||
|       case 'B':
 | ||
|         curpat = *(tt.get (1));
 | ||
|         rwd << 'B' << curpat;
 | ||
|         break;
 | ||
|       case 'C':
 | ||
|         curcol = *(tt.get (1));
 | ||
|         rwd << 'C' << curcol;
 | ||
|         break;
 | ||
|       default:
 | ||
|         break;  
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::setbackground(const char* b, int index)
 | ||
| {                       
 | ||
|   CHECK(index >= 0 && index <= 3, "Bad background index");
 | ||
|   _backgrounds.destroy(index);
 | ||
|   if (b && *b)
 | ||
|   {                                               
 | ||
|     TString_array* bg = new TString_array(formlen());
 | ||
|     _backgrounds.add(bg, index);
 | ||
|     parse_background(b, *bg);
 | ||
|   }  
 | ||
| }
 | ||
| 
 | ||
| TString_array& TPrinter::getbgdesc(word page) const
 | ||
| {
 | ||
|   int index = 0;
 | ||
|   if (page == 0 && _backgrounds.objptr(3)) 
 | ||
|     index = 3; 
 | ||
|   if (page == 1 && _backgrounds.objptr(2)) 
 | ||
|     index = 2; 
 | ||
|   if (index == 0 && (page & 0x1) == 0 && _backgrounds.objptr(1))    
 | ||
|     index = 1;
 | ||
|     
 | ||
|   TString_array* bg = (TString_array*)_backgrounds.objptr(index);
 | ||
|   if (bg == NULL)
 | ||
|   {
 | ||
|     bg = new TString_array(formlen());
 | ||
|     ((TPrinter*)this)->_backgrounds.add(bg, index);  // keep const
 | ||
|   }  
 | ||
|    
 | ||
|   return *bg;
 | ||
| }
 | ||
| 
 | ||
| //bool printers_on_key(TMask_field & f, KEY key);
 | ||
| 
 | ||
| ////////// TPRINTROW //////////
 | ||
| 
 | ||
| TPrintrow::TPrintrow()
 | ||
| {
 | ||
|   reset();
 | ||
| }
 | ||
| 
 | ||
| TPrintrow::TPrintrow(const TPrintrow& pr)
 | ||
| {         
 | ||
|   reset();
 | ||
|   _row = pr.row ();
 | ||
|   memcpy (_attr, pr._attr, MAX_PR_WIDTH);
 | ||
|   memcpy (_cols, pr._cols, MAX_PR_WIDTH);
 | ||
|   _tab = pr._tab;
 | ||
|   if (pr._images)
 | ||
|     _images = new TToken_string(*pr._images);
 | ||
|   
 | ||
|   _currentstyle = pr._currentstyle;
 | ||
|   _currentcolor = pr._currentcolor;
 | ||
|   _lastpos = pr._lastpos;
 | ||
| }
 | ||
| 
 | ||
| TPrintrow::~TPrintrow()
 | ||
| {
 | ||
|   if (_images)
 | ||
|     delete _images;
 | ||
| }
 | ||
| 
 | ||
| TObject *TPrintrow::dup () const
 | ||
| {
 | ||
|   return new TPrintrow(*this);
 | ||
| }
 | ||
| 
 | ||
| const char *TPrintrow::class_name () const
 | ||
| { return "Printrow"; }
 | ||
| 
 | ||
| word TPrintrow::class_id() const
 | ||
| { return CLASS_PRINTROW; }
 | ||
| 
 | ||
| TPrintrow& TPrintrow::reset()
 | ||
| {
 | ||
|   _row.spaces (sizeof(_attr));                       // Azzera testo
 | ||
| 
 | ||
|   memset(_attr, normalstyle, sizeof (_attr));        // Azzera stile
 | ||
|   
 | ||
|   _tab.reset();                                       // Azzera tabulazioni
 | ||
|   _images = NULL;
 | ||
|   _currentcolor = 'w';
 | ||
|   _currentcolor <<= 8;
 | ||
|   _currentcolor += 'n';
 | ||
|   for (int i = 0; i < MAX_PR_WIDTH; i++)
 | ||
|     _cols[i] = _currentcolor;                         // Azzera colori
 | ||
|   
 | ||
|   _lastpos = 0;
 | ||
|   _currentstyle = normalstyle;
 | ||
|   return *this;
 | ||
| }
 | ||
| 
 | ||
| const char* TPrintrow::row_codified() const
 | ||
| {
 | ||
|   char last_attr = -1;
 | ||
|   int last_color = -1;
 | ||
|   int k = 0, i = 0, len = 0;     
 | ||
| 
 | ||
|   const int kmax = 1024;
 | ||
|   char* tmp = get_tmp_string(kmax).get_buffer();
 | ||
|   
 | ||
|   // Calcolo lunghezza stringa
 | ||
|   for (i = _row.size()-1; i >= 0; i--)
 | ||
|   {
 | ||
|     if (_row[i] != ' ') 
 | ||
|     {
 | ||
|       len = i+1;
 | ||
|       break;
 | ||
|     }  
 | ||
|   }  
 | ||
| 
 | ||
|   for (i = 0; i < len; i++)
 | ||
|   {
 | ||
|     if (_tab[i])
 | ||
|     {
 | ||
|       tmp[k++] = '@'; 
 | ||
|       tmp[k++] = 't';
 | ||
|     }  
 | ||
|     
 | ||
|     if (_attr[i] != last_attr)
 | ||
|     {
 | ||
|       tmp[k++] = '@';
 | ||
|       switch (_attr[i])
 | ||
|       {
 | ||
|       case normalstyle:
 | ||
|         tmp[k++] = 'r';
 | ||
|         break;
 | ||
|       case boldstyle:
 | ||
|         tmp[k++] = 'b';
 | ||
|         break;
 | ||
|       case italicstyle:
 | ||
|         tmp[k++] = 'i';
 | ||
|         break;
 | ||
|       case underlinedstyle:
 | ||
|         tmp[k++] = 'u';
 | ||
|         break;
 | ||
|       }
 | ||
|       last_attr = _attr[i];
 | ||
|     }
 | ||
|     if (_cols[i] != last_color)
 | ||
|     {
 | ||
|       tmp[k++] = '$';
 | ||
|       tmp[k++] = '[';
 | ||
|       tmp[k++] = (char) (_cols[i] & 0x00ff);
 | ||
|       tmp[k++] = ',';
 | ||
|       tmp[k++] = (char) (_cols[i] >> 8);
 | ||
|       tmp[k++] = ']';
 | ||
|       last_color = _cols[i];
 | ||
|     }   
 | ||
|     if (_row[i] == '@' && strchr("<#>", _row[i+1]) == NULL)
 | ||
|       tmp[k++] = '@';  //  Escape for @
 | ||
|     tmp[k++] = _row[i];
 | ||
|   }
 | ||
|   CHECKD(k < kmax, "Internal buffer overflow ", k);
 | ||
|   tmp[k] = '\0';
 | ||
|   
 | ||
|   if (_images)
 | ||
|   {   
 | ||
|     strcat(tmp, "$[w,w]");   // Bianco su bianco!
 | ||
|     FOR_EACH_TOKEN((*_images), tok)
 | ||
|       strcat(tmp, tok);
 | ||
|   }
 | ||
|   
 | ||
|   return tmp;
 | ||
| }
 | ||
| 
 | ||
| TPrintrow& TPrintrow::put(const char *str, int position, int len)
 | ||
| {
 | ||
|   if (len <= 0)
 | ||
|     len = strlen (str);
 | ||
|   
 | ||
|   if (position < 0)
 | ||
|     position = _lastpos;
 | ||
|   else
 | ||
|     _tab.set(position);  
 | ||
| 
 | ||
|   char bg = 'w', fg = 'n';
 | ||
|   for (int i = 0; i < len; i++)
 | ||
|   {
 | ||
|     char c = str[i];
 | ||
|     if (c == '$' && str[i + 1] == '[')
 | ||
|     {
 | ||
|       ++i;
 | ||
|       fg = str[++i];
 | ||
|       c = str[++i];
 | ||
|       if (c == ']')
 | ||
|         bg = _currentcolor >> 8;
 | ||
|       else if (c == ',')
 | ||
|       {
 | ||
|         bg = str[++i];
 | ||
|         i++;
 | ||
|       }
 | ||
|       else
 | ||
|       {
 | ||
|         CHECK (0, "Error in color specification");
 | ||
|       }
 | ||
|       _currentcolor = (bg << 8) + fg;
 | ||
|     }
 | ||
|     else if (c == '@')
 | ||
|     {
 | ||
|       c = str[++i];
 | ||
|       switch (toupper (c))
 | ||
|       {
 | ||
|       case '@':  // Escape for @
 | ||
|         _row[position] = '@';
 | ||
|         _attr[position] = _currentstyle;
 | ||
|         _cols[position++] = _currentcolor;
 | ||
|         break; 
 | ||
|       case '#':
 | ||
|       case '<':
 | ||
|       case '>':
 | ||
|         // printer MUST handle them
 | ||
|       {
 | ||
|         const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8);
 | ||
|         _row[position] = '@';
 | ||
|         _attr[position] = _currentstyle;  
 | ||
|         _cols[position++] = _currentcolor;
 | ||
|         for (int j = 1; j < n; j++)
 | ||
|         {
 | ||
|           _row[position] = c;
 | ||
|           _attr[position] = _currentstyle;
 | ||
|           _cols[position++] = _currentcolor;
 | ||
|         }
 | ||
|       }
 | ||
|       break; 
 | ||
|       case 'T':
 | ||
|         _tab.set(position);
 | ||
|         break;
 | ||
|       case 'B':
 | ||
|         _currentstyle = boldstyle;
 | ||
|         break;
 | ||
|       case 'I':
 | ||
|         _currentstyle = italicstyle;
 | ||
|         break;
 | ||
|       case 'U':
 | ||
|         _currentstyle = underlinedstyle;
 | ||
|         break;
 | ||
|       case 'R':
 | ||
|         _currentstyle = normalstyle;
 | ||
|         break;
 | ||
|       case 'F':
 | ||
|         {                
 | ||
|           const int f = i;
 | ||
|           for ( ; str[i] && str[i] != ']'; i++);
 | ||
|           TString name = &str[f+2];
 | ||
|           name.cut(i-f-2);
 | ||
|           name.insert("i{"); name << '}';
 | ||
|           if (_images == NULL) _images = new TToken_string;
 | ||
|           _images->add(name);
 | ||
|         }
 | ||
|         break;
 | ||
|       default:
 | ||
|         // should be number followed by skip or jump
 | ||
|         if (isdigit (c))
 | ||
|         {
 | ||
|           // read number
 | ||
|           char digbuf[8];
 | ||
|           int cnt = 0;
 | ||
|           digbuf[cnt++] = c;
 | ||
|           while (isdigit (c = str[++i]))
 | ||
|             digbuf[cnt++] = c;
 | ||
|           digbuf[cnt] = '\0';
 | ||
|           int pp = atoi (digbuf);
 | ||
|           if (toupper (c) == 'G')
 | ||
|           {
 | ||
|             if (pp >= MAX_PR_WIDTH)
 | ||
|               fatal_box ("printrow reaches position %d", pp);
 | ||
|             if (pp > position)
 | ||
|               for (int k = position; k < pp; k++)
 | ||
|               {
 | ||
|                 _attr[k] = _currentstyle;
 | ||
|                 _cols[k] = _currentcolor;
 | ||
|               }
 | ||
|             position = pp;
 | ||
|             _tab.set(position);
 | ||
|           }
 | ||
|           else if (toupper (c) == 'J')
 | ||
|           {
 | ||
|             if (pp + position >= MAX_PR_WIDTH)
 | ||
|               fatal_box ("printrow reaches position %d", pp + position);
 | ||
|             for (int k = 0; k < pp; k++)
 | ||
|             {
 | ||
|               _attr[k + position] = _currentstyle;
 | ||
|               _cols[k + position] = _currentcolor;
 | ||
|             }
 | ||
|             position += pp;
 | ||
|             _tab.set(position);
 | ||
|           }
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           _row[position] = c;
 | ||
|           _attr[position] = _currentstyle;
 | ||
|           _cols[position++] = _currentcolor;
 | ||
|         }
 | ||
|       }                   // switch
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       _row[position] = c;
 | ||
|       _attr[position] = _currentstyle;
 | ||
|       _cols[position++] = _currentcolor;
 | ||
|     }
 | ||
|   }                             // for
 | ||
| 
 | ||
|   _lastpos = position;
 | ||
|   return *this;
 | ||
| }
 | ||
| 
 | ||
| ////////// TPRINTER //////////
 | ||
| 
 | ||
| void TPrinter::set_printrcd()
 | ||
| {
 | ||
|   if (_print_rcd != NULL)
 | ||
|   {
 | ||
|     xvt_print_destroy(_print_rcd);
 | ||
|     _print_rcd = NULL;
 | ||
|     _print_rcd_size = 0;
 | ||
|   }
 | ||
| 
 | ||
|   bool ok = false;
 | ||
|   if (_prname.full() && !forced_default_printer())
 | ||
|   {
 | ||
|     _print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname);
 | ||
|     ok = xvt_print_is_valid(_print_rcd) != 0;
 | ||
|   }
 | ||
|   if (!ok)
 | ||
|   {
 | ||
|     _print_rcd = xvt_print_create(&_print_rcd_size);
 | ||
|     xvt_print_get_name(_print_rcd, _prname.get_buffer(), _prname.size());
 | ||
|     ok = xvt_print_is_valid(_print_rcd) != 0;
 | ||
|   }
 | ||
|   if (!ok)
 | ||
|     error_box(FR("Errore di inizializzazione della stampante %s"), (const char*)_prname);
 | ||
| }
 | ||
| 
 | ||
| PRINT_RCD* TPrinter::get_printrcd(int *size)
 | ||
| {
 | ||
|   if (_print_rcd == NULL)
 | ||
|     set_printrcd();
 | ||
|   if (size != NULL) 
 | ||
|     *size = _print_rcd_size;  
 | ||
|   return _print_rcd;  
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Setta le caratteristiche della stampante leggendole da <p _print_rcd>
 | ||
| void TPrinter::init_formlen(
 | ||
|   WINDOW prwin) // @parm Finestra effettiva di stampa (default NULL_WIN)
 | ||
| 
 | ||
|   // @comm Nel caso <p prwin> sia NULL_WIN vengono solamente aggiornati i valori
 | ||
| {
 | ||
|   long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
 | ||
| 	
 | ||
|   xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, get_printrcd(), &ph, &pw, &pvr, &phr);
 | ||
|   
 | ||
|   if (pvr > 0)
 | ||
|   {
 | ||
|     _formlen       = int(ph * _lines_per_inch / pvr);   // Total number of lines per page
 | ||
|     _dots_per_line = int(pvr / _lines_per_inch);        // Number of point per line
 | ||
|     _vert_offset   = (int)(ph - ((long)_formlen * _dots_per_line)) >> 1;
 | ||
|     _formwidth = int ((pw * 120) / (_ch_size * phr));   // nice guess 
 | ||
| 
 | ||
|     if (prwin != NULL_WIN)
 | ||
|     {
 | ||
|       // Compute maximum number of chars per line
 | ||
|       int mincol = 0,maxcol=MAX_PR_WIDTH;
 | ||
|       TString256 spc; spc.fill('m', maxcol);
 | ||
|         
 | ||
|       _formwidth = maxcol;
 | ||
|       int w = 0;
 | ||
|       while (mincol < maxcol )
 | ||
|       {
 | ||
|         w = xvt_dwin_get_text_width(prwin, (char*)(const char*)spc, _formwidth);
 | ||
|         if (w < pw)
 | ||
|           mincol = _formwidth+1;
 | ||
|         else
 | ||
|           maxcol=_formwidth-1;
 | ||
|         _formwidth=(mincol+maxcol)/2;
 | ||
|       }     
 | ||
| 
 | ||
|       _horz_offset = (_formwidth > 80) ? (int)(pw - w)/2 : 0;         
 | ||
|       if (_horz_offset < 0)
 | ||
|         _horz_offset = 0;
 | ||
|     }
 | ||
|     else 
 | ||
|     {
 | ||
|       // _formwidth = int (pw * (_ch_size * 10 / 12) / phr);  / ca$$ata
 | ||
|       _horz_offset = 0;
 | ||
|     }                      
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| TPrinter::TPrinter()
 | ||
| : _vf(NULL), _ch_size (12), _date (TODAY), _multiple_link (false),
 | ||
|   _isgraphics (true), _frozen (false), _print_rcd(NULL), _lines_per_inch (6),
 | ||
|   _l_offset(0), _c_offset(0), _export_header(false), _export_header_len(0),
 | ||
|   _appendfile(false), _manual_setup(false)
 | ||
| 
 | ||
| {
 | ||
|   _footerhandler = _headerhandler = NULL;
 | ||
|   _linkhandler = NULL;
 | ||
| 
 | ||
|   _formlen = 66;
 | ||
|   _formwidth = 0;
 | ||
| 
 | ||
|   _frompage = 0;
 | ||
|   _topage = 0xffff;
 | ||
|   _hwformfeed = false;
 | ||
|   _currentpage = 1;
 | ||
|   _currentrow = 1;
 | ||
|   _headersize = 0;
 | ||
|   _footersize = 0;
 | ||
|   _isopen = false;
 | ||
|   
 | ||
| 	// read configuration file
 | ||
|   read_configuration ();
 | ||
| 
 | ||
|   init_formlen ();
 | ||
|   
 | ||
|   set_fincatura("+++++++++-|");                
 | ||
| 
 | ||
|   set_fink_mode(true);
 | ||
|   _finker = _isgraphics && _fink_mode ? NULL : new TPrint_intersector(_fink, _formlen);
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Legge la configurazione della stampante
 | ||
| void TPrinter::read_configuration(
 | ||
|   const char* parag)    // parm Nome del file di configurazione della stampante (default NULL)
 | ||
| 
 | ||
|   // @comm Se <p parag> e' NULL viene letta la configurazione della stamapnte di default.
 | ||
| {                  
 | ||
|   TWait_cursor hourglass;
 | ||
| 
 | ||
|   _config = parag;                                            // Inizializza nome configurazione
 | ||
|   if (_config.blank())                                        // Se non specificata ...
 | ||
|     _config = "Printer";                                      // ... usa configurazione standard
 | ||
| 
 | ||
|   TConfig* iniptr = NULL;                         
 | ||
|   if (_config != "Printer")                                   // Cerca configurazione speciale
 | ||
|   {                                                           
 | ||
|     iniptr = new TConfig(CONFIG_STAMPE, _config);
 | ||
|     const int what = iniptr->get_int("Type", NULL, -1, -1);
 | ||
|     if (what < 0)                                             // Se configurazione annullata ...
 | ||
|     { 
 | ||
|       delete iniptr; iniptr = NULL;                            
 | ||
|     }
 | ||
|   }
 | ||
|   if (iniptr == NULL)
 | ||
|     iniptr = new TConfig(CONFIG_GUI, "Printer");
 | ||
| 
 | ||
|   const int what = iniptr->get_int("Type", NULL, -1, 4);      // Tipo stampante
 | ||
|   _prname = iniptr->get("Name");                              // Nome stampante corrente
 | ||
|   _printerfile = iniptr->get("File", NULL, -1, "");           // File di stampa                
 | ||
|   set_fontname(iniptr->get("Font", NULL, -1, XVT_FFN_FIXED)); // Nome del font
 | ||
|   _ch_size = iniptr->get_int("Size", NULL, -1, 10);           // Dimensione del font
 | ||
|   _lines_per_inch = iniptr->get_int("Lines", NULL, -1, 6);    // Linee per pollice
 | ||
|   set_graphics(iniptr->get_bool("Graphic", NULL, -1, true));  // Grafica attiva
 | ||
|   _force_default = iniptr->get_bool("Default", NULL, -1, false); // Forza stampante di default
 | ||
| 
 | ||
| 	bool read_rcd = false;
 | ||
| 	
 | ||
|   if (_prname.full() && !forced_default_printer())  
 | ||
|   {
 | ||
|   	const TString& host = iniptr->get("Host");
 | ||
|   	if (host.full())
 | ||
|   	{
 | ||
|       char hostname[256];
 | ||
|   	  xvt_sys_get_host_name(hostname, sizeof(hostname));
 | ||
|       read_rcd = (host == hostname);  // Safe to read
 | ||
|   		if (!read_rcd)
 | ||
|       {      
 | ||
|         _prname.cut(0); // Forza la lettura parametri della stampante di default
 | ||
|         set_printrcd(); 
 | ||
|       }
 | ||
|   	}
 | ||
|   }
 | ||
|   
 | ||
|   if (read_rcd)
 | ||
|   {              
 | ||
| 	  if (_print_rcd != NULL)
 | ||
|       xvt_print_destroy(_print_rcd);
 | ||
|     _print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname);
 | ||
| 
 | ||
|     if (xvt_print_is_valid(_print_rcd) && iniptr->exist("rcd", 0))
 | ||
| 		{
 | ||
|       TToken_string s(256);         
 | ||
|       int i = 0;
 | ||
| 			for (int index = 0; ; index++)
 | ||
| 			{
 | ||
| 				s = iniptr->get("rcd", NULL, index);
 | ||
| 				if (s.not_empty())
 | ||
| 				{
 | ||
|           byte* rcd = (byte*)_print_rcd;
 | ||
| 					for (const char* n = s.get(0); n != NULL && i < _print_rcd_size; n = s.get())
 | ||
| 						rcd[i++] = (byte)atoi(n);
 | ||
| 				}
 | ||
| 				else
 | ||
| 					break;    
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
|     if (xvt_print_is_valid(_print_rcd))
 | ||
| 		{
 | ||
|       char name[256]; // Recupera nome "lungo" della stampante
 | ||
|       xvt_print_get_name(_print_rcd, name, sizeof(name));
 | ||
|       _prname = name;
 | ||
|       init_formlen();
 | ||
| 		}
 | ||
| 		else
 | ||
|     {
 | ||
|       error_box(TR("Attenzione: la stampante corrente non e' valida. "
 | ||
|                    "Si prega di selezionare e registrare una nuova stampante."));
 | ||
|       set_printrcd();
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     set_printrcd();
 | ||
|   }
 | ||
|   
 | ||
|   delete iniptr; iniptr = NULL;
 | ||
|   
 | ||
|   if (_printerfile.empty())
 | ||
|   {
 | ||
|     _printerfile.tempdir();
 | ||
|     _printerfile << SLASH;
 | ||
|   }                                                 
 | ||
|   
 | ||
|   if (_config == "Printer" || _printertype == winprinter)
 | ||
|   {
 | ||
|     switch (what)
 | ||
|     {
 | ||
|     case  1: _printertype = fileprinter; break;
 | ||
|     case  2: _printertype = screenvis; break;
 | ||
|     case  3: _printertype = exportprinter; break;
 | ||
|     case  4: _printertype = acrobatprinter; break;
 | ||
|     default: _printertype = winprinter; break;
 | ||
|     }                     
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::save_configuration(const char* para)
 | ||
| { 
 | ||
|   TWait_cursor hourglass;
 | ||
| 
 | ||
|   if (para && *para)
 | ||
|     _config = para;
 | ||
|   CHECK(_config.not_empty(), "Invalid printer config");
 | ||
|   TConfig prini(_config == "Printer" ? CONFIG_GUI : CONFIG_STAMPE, _config);
 | ||
|   
 | ||
|   prini.set("Type", _printertype);              // Tipo stampante
 | ||
|   prini.set("Name", _prname);                   // Nome stampante corrente
 | ||
|   prini.set("File", _printerfile);              // File di stampa                
 | ||
|   prini.set("Font", _fontname);                 // Nome del font
 | ||
|   prini.set("Size", _ch_size);                  // Dimensione del font
 | ||
|   prini.set("Lines", _lines_per_inch);          // Linee per pollice
 | ||
|   prini.set("Graphic", _isgraphics ? "X" : ""); // Grafica attiva
 | ||
|   prini.set("Default", _force_default ? "X" : ""); // Forza stampante default
 | ||
| 
 | ||
|   char hostname[256];
 | ||
| 	xvt_sys_get_host_name(hostname, sizeof(hostname));
 | ||
| 	prini.set("Host", hostname);
 | ||
| 	prini.set("User", user());
 | ||
|   
 | ||
| 	int n = 0, index = 0;       
 | ||
|   TToken_string val(256);             
 | ||
|   
 | ||
|   int rcdsize; 
 | ||
|   byte* rcd = (byte*)get_printrcd(&rcdsize);
 | ||
|   
 | ||
|   for (int i = 0; i < rcdsize; i++)
 | ||
|   {             
 | ||
|     val.add((int)rcd[i]);
 | ||
|     n++;
 | ||
|     if (n == 24)
 | ||
|     {
 | ||
|       prini.set("rcd", val, NULL, true, index++);
 | ||
|       val.cut(n = 0);
 | ||
|     }
 | ||
|   }
 | ||
|   if (n > 0)
 | ||
|     prini.set("rcd", val, NULL, true, index);
 | ||
|   
 | ||
|   for (index++; prini.remove("rcd", index); index++);
 | ||
| }
 | ||
| 
 | ||
| TPrinter::~TPrinter ()
 | ||
| {
 | ||
|   if (_print_rcd != NULL)
 | ||
|   {
 | ||
|     xvt_print_destroy(_print_rcd);
 | ||
|     _print_rcd = NULL;
 | ||
|   }                                                     
 | ||
| }
 | ||
| 
 | ||
| const char* TPrinter::class_name() const
 | ||
| {
 | ||
|   return "Printer";
 | ||
| }
 | ||
| 
 | ||
| word TPrinter::class_id() const
 | ||
| {
 | ||
|   return CLASS_PRINTER;
 | ||
| }
 | ||
| 
 | ||
| TPrintrow *TPrinter::getheaderline(int linetoget)
 | ||
| {
 | ||
|   return ((TPrintrow *)_header.objptr (linetoget));
 | ||
| }
 | ||
| 
 | ||
| TPrintrow *TPrinter::getfooterline(int linetoget)
 | ||
| {
 | ||
|   return ((TPrintrow *)_footer.objptr(linetoget));
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Setta il contenuto di una line dell'header
 | ||
| void TPrinter::setheaderline (
 | ||
|   int linetoset,        // @parm Numero della linea da settare
 | ||
|   TPrintrow * line)     // @parm Contenuto della linea dell'header
 | ||
|   // @parm const TPrintrow& | line | Indirizzo con il contenuto della 
 | ||
|   //     linea dell'header
 | ||
| 
 | ||
|   // @syntax void setheaderline (int linetoset, TPrintrow* line);
 | ||
|   // @syntax void setheaderline (int linetoset, const TPrintrow& line);
 | ||
| 
 | ||
| {
 | ||
|   _header.add (line, linetoset);
 | ||
|   if (linetoset >= _headersize)
 | ||
|     _headersize = linetoset + 1;
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::setheaderline (int linetoset, const TPrintrow & line)
 | ||
| {
 | ||
|   TPrintrow *p = new TPrintrow (line);
 | ||
|   setheaderline (linetoset, p);
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Setta il contenuto di una line dell'header
 | ||
| void TPrinter::setfooterline (
 | ||
|   int linetoset,        // @parm Numero della linea da settare
 | ||
|   TPrintrow * line)     // @parm Contenuto della linea del footer
 | ||
|   // @parm const TPrintrow& | line | Indirizzo con il contenuto della 
 | ||
|   //     linea del footer
 | ||
| 
 | ||
|   // @syntax void setfooterline (int linetoset, TPrintrow* line);
 | ||
|   // @syntax void setfooterline (int linetoset, const TPrintrow& line);
 | ||
| 
 | ||
| {
 | ||
|   _footer.add (line, linetoset);
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::setfooterline (int linetoset, const TPrintrow& line)
 | ||
| {
 | ||
|   TPrintrow *p = new TPrintrow (line);
 | ||
|   setfooterline (linetoset, p);
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::resetheader ()
 | ||
| {
 | ||
|   _header.destroy ();
 | ||
|   _headersize = 0;
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::resetfooter ()
 | ||
| {
 | ||
|   _footer.destroy ();
 | ||
|   // _footersize = 0;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Metodo base per la stampa
 | ||
| //
 | ||
| // @rdesc Ritorna il risulato della stampa:
 | ||
| //
 | ||
| // @flag true | Se la stampa ha avuto successo
 | ||
| // @flag false | Se la stampante non e' attiva
 | ||
| bool TPrinter::printrow(
 | ||
|   TPrintrow* rowtoprint) // @parm Riga da stampare
 | ||
| 
 | ||
|   // @comm Se la pagina logica corrente e' precedente alla prima pagina logica o successiva
 | ||
|   //     all'ultima pagina logica viene ritornato true.
 | ||
| {
 | ||
|   if (!isopen ())
 | ||
|     return false;
 | ||
| 
 | ||
|   if (_currentpage < _frompage || _currentpage > _topage)
 | ||
|     return true;
 | ||
| 
 | ||
|   TString rw;
 | ||
|   if (rowtoprint != NULL)
 | ||
|   {
 | ||
|     //rw = (_printertype == fileprinter) ? rowtoprint->row() : rowtoprint->row_codified();
 | ||
|     rw = rowtoprint->row_codified(); // Permetto di salvare anche su fileprinter = pippo.xls
 | ||
|     rw.rtrim();
 | ||
|   }
 | ||
| 
 | ||
|   if (_printertype != exportprinter)
 | ||
|   {
 | ||
|     for (int idx = 0; rw[idx]; idx++)
 | ||
|     {
 | ||
|       if (rw[idx] == '@') // gestione data e n. di pagina      
 | ||
|       {
 | ||
|         switch (rw[idx + 1])
 | ||
|         {
 | ||
|         case '#':
 | ||
|           rw.overwrite (format("%-5u", _currentpage), idx++);
 | ||
|           break;
 | ||
|         case '>':
 | ||
|           rw.overwrite (_date.string(full), idx++);
 | ||
|           break;
 | ||
|         case '<':
 | ||
|           rw.overwrite (_date.string(brief), idx++);
 | ||
|           break;
 | ||
|         default:
 | ||
|           break;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   if (_printertype == screenvis)
 | ||
|   {
 | ||
|     if (!_vf->frozen())
 | ||
|       _vf->add_line(rw);
 | ||
|     else
 | ||
|       _frozen = true;
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     // add line to txt
 | ||
|     if (!_frozen)
 | ||
|       _txt.append(rw);
 | ||
|   }
 | ||
| 
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| word TPrinter::rows_left() const
 | ||
| {
 | ||
|   word left = _formlen - _currentrow - _footersize + 1;
 | ||
|   if (_currentrow < 2)
 | ||
|     left -= _headersize;
 | ||
|   return left;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Permette di stampare una riga
 | ||
| //
 | ||
| // @rdesc Ritorna il risultato della stampa:
 | ||
| //
 | ||
| // @flag true | Se la stampa ha avuto successo
 | ||
| // @flag false | Se non e' riuscito ad effettuare la stampa
 | ||
| bool TPrinter::print(
 | ||
|   TPrintrow& rowtoprint)        // @parm Riga da stampare
 | ||
| 
 | ||
|   // @comm Nel caso la riga non ci stia nella pagina logica corrente vengono stampanti il footer
 | ||
|   //     della pagina corrente e l'header della successiva prima prima della stampa della riga
 | ||
|   //     vera e propria.
 | ||
| {
 | ||
|   bool ok = true;
 | ||
| 
 | ||
|   if (!(_printertype == exportprinter && !_export_header))
 | ||
|   {
 | ||
|     if (_currentrow > _formlen - _footersize)
 | ||
|       ok = printfooter ();
 | ||
| 
 | ||
|     if (ok && _currentrow == 1)
 | ||
|       ok = printheader();
 | ||
|   }
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     ok = printrow(&rowtoprint);
 | ||
|     _currentrow++;
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::printheader()
 | ||
| {
 | ||
|   if (_headerhandler)
 | ||
|     _headerhandler(*this);
 | ||
| 
 | ||
|   bool ok = true;
 | ||
|   int i;
 | ||
|   
 | ||
|   for (i = 0; i < _headersize && ok; i++)
 | ||
|     ok = printrow(getheaderline(i));
 | ||
| 
 | ||
| //  _currentrow = _headersize + 1;
 | ||
|   _currentrow = i+1;
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::printfooter()
 | ||
| {
 | ||
|   if (_footerhandler)
 | ||
|     _footerhandler (*this);
 | ||
| 
 | ||
|   bool ok = true;
 | ||
|   for (int i = 0; i < _footersize && ok; i++)
 | ||
|     ok = printrow(getfooterline(i));
 | ||
| 
 | ||
|   _currentrow = 1;
 | ||
|   _currentpage++;
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Permette di settare il tipo di fincatura
 | ||
| void TPrinter::set_fink_mode(
 | ||
|   bool f)      // @parm Indica il tipo di fincatura:
 | ||
|   //
 | ||
|   // @flag true | Fincatura di tipo grafico
 | ||
|   // @flag false | Fincatura di tipo testo
 | ||
| 
 | ||
|   // @comm Viene prima controllato che la stampante supporti la modalita' grafica,
 | ||
|   //       in tal caso, se viene impostato il flag a true e la stampante e' generica
 | ||
|   //       oppure non ha il flag di stampa elementi grafici attivato, la fincatura sara'
 | ||
|   //       in modo testo.
 | ||
| {
 | ||
|   _fink_mode = f && isgraphics();
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Permette di saltare alcune righe dalla posizione corrente
 | ||
| //
 | ||
| // @rdesc Ritorna il risulato dell'operazione:
 | ||
| //
 | ||
| // @flag true | Se e' riuscito a saltare le righe
 | ||
| // @flag false | Se non e' riuscito a saltare le righe
 | ||
| bool TPrinter::skip(
 | ||
|   int linestoskip)      // @parm Vengono accettati solo valori positivi
 | ||
| 
 | ||
|   // @xref <mf TPrinter::jump>
 | ||
| {
 | ||
|   CHECK (linestoskip >= 0, "Linestoskip can't be negative");
 | ||
|   int jumpline = _currentrow + linestoskip;
 | ||
|   return jump(jumpline);
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Permette di saltare alla riga indicata
 | ||
| //
 | ||
| // @rdesc Ritorna il risultato dell'operazione
 | ||
| //
 | ||
| // @flag true | Se e' riuscito a saltare alla riga
 | ||
| // @flag false | Se non e' riuscito a saltare alla riga o se viene inserito un formfeed
 | ||
| bool TPrinter::jump(
 | ||
|   int jumpline) // @parm Numero della riga a cui saltare nella stampa. Vengono accettai
 | ||
|   //     solo valori positivi
 | ||
| 
 | ||
|   // @comm Nel caso si cerchi di saltare ad una riga superiore alla lunghezza della pagina attiva
 | ||
|   //     viene inserito un formfeed.
 | ||
| 
 | ||
|   // @xref <mf TPrinter::skip>
 | ||
| {
 | ||
|   int i = 0;
 | ||
|   bool ok = true;
 | ||
| 
 | ||
|   CHECK (jumpline >= 0, "Jumpline can't be negative");
 | ||
|   if (jumpline > _formlen - _footersize)
 | ||
|     ok = formfeed();
 | ||
|   else
 | ||
|     for (i = _currentrow; i < jumpline; i++)
 | ||
|       if (!printrow())
 | ||
|         ok = false;
 | ||
|   if (jumpline > _formlen - _footersize)
 | ||
|     ok = false;
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::formfeed()
 | ||
| {
 | ||
|   const int lastrow = _formlen - _footersize;
 | ||
|   for (; _currentrow + _export_header_len <= lastrow; _currentrow++)
 | ||
|     printrow();
 | ||
|   return printfooter();
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::reset()
 | ||
| {
 | ||
|   resetheader();
 | ||
|   resetfooter();
 | ||
|   _currentpage = 1;
 | ||
|   _currentrow  = 1;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::open()
 | ||
| {
 | ||
|   if (_printertype == screenvis)
 | ||
|   { 
 | ||
|     CHECK(_vf == NULL, "Print preview already open");
 | ||
|     _vf = new TViswin (NULL, "Anteprima di stampa", true, true,
 | ||
|                        _linksdescr.items () > 0);
 | ||
|     _vf->open_modal ();
 | ||
|   }
 | ||
|   else 
 | ||
|   {
 | ||
|     // prepare text object for new text
 | ||
|     _txt.destroy();
 | ||
|     _txt.interactive(false);
 | ||
|   }  
 | ||
| 
 | ||
|   _currentrow = 1;
 | ||
|   _currentpage = 1;
 | ||
| 
 | ||
|   return _isopen = true;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::set()
 | ||
| {
 | ||
|   main_app().disable_menu_item(M_FILE_PG_SETUP);
 | ||
| 
 | ||
|   const TString oldprn = _prname;  
 | ||
| 	int old_rcd_size;
 | ||
|   PRINT_RCD* rcd = get_printrcd(&old_rcd_size);
 | ||
|   TString oldrcd(old_rcd_size);
 | ||
|   memcpy(oldrcd.get_buffer(), rcd, old_rcd_size);
 | ||
|                   
 | ||
|   TPrinter_setup_mask mask;
 | ||
|   const KEY k = mask.run();
 | ||
| 
 | ||
|   if (k != K_ESC)
 | ||
|   {
 | ||
|     _manual_setup = true;
 | ||
|     _print_rcd = mask.get_print_rcd(_print_rcd_size);
 | ||
|     xvt_print_get_name(_print_rcd, _prname.get_buffer(128), 128);
 | ||
| 
 | ||
|     switch (mask.get_int(MSK_TYPE))
 | ||
|     {
 | ||
|     case 1:                       // file
 | ||
|       _printertype = fileprinter;
 | ||
|       _printerfile = mask.get (MSK_FILENAME);
 | ||
|       break;
 | ||
|     case 2:                       // video
 | ||
|       _printertype = screenvis; break;
 | ||
|     case 4:                       // acrobat
 | ||
|       _printertype = acrobatprinter; break;
 | ||
|     default:                      // stampante
 | ||
|       _printertype = winprinter; break;
 | ||
|     }
 | ||
| 
 | ||
|     set_fontname(mask.get(MSK_FONT));
 | ||
|   
 | ||
|     const int cs = mask.get_int(MSK_SIZE);
 | ||
|     if (cs > 4) _ch_size = cs;
 | ||
| 
 | ||
|     _lines_per_inch = mask.get_int (MSK_LINES);
 | ||
|     _isgraphics = mask.get_bool (MSK_ISGRAPHICS);
 | ||
|     _force_default = mask.get_bool(MSK_DEFAULT);
 | ||
|     init_formlen ();
 | ||
| 
 | ||
|     if (k == K_INS)
 | ||
|       save_configuration();
 | ||
|   }
 | ||
| 
 | ||
|   main_app().enable_menu_item (M_FILE_PG_SETUP);
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Inserisce un file di export fatto da un'altra printer 
 | ||
| void TPrinter::merge_export_file(
 | ||
|   const char* file, 
 | ||
|   bool header)  // @parm Indica se gli header sono presenti nel file:
 | ||
|   //
 | ||
|   // @flag true | Gli header sono nel file e quindi non vengono stampanti (default)
 | ||
|   // @flag false | Gli header non sono nel file e quindi vengono stampanti
 | ||
| 
 | ||
|   // @comm Vengono inseriti nel file di export i formati e tutto il resto. Vengono ignorati gli
 | ||
|   //     header supponendo che siano gia' presenti nel file
 | ||
| {
 | ||
|   TTextfile txt(file); 
 | ||
|   
 | ||
|   for (long i = 0; i < txt.lines(); i++)
 | ||
|   {
 | ||
|     TPrintrow* p = new TPrintrow();  
 | ||
|     p->put(txt.line_formatted(i));
 | ||
|     if (header) printrow(p);  
 | ||
|     else        print(*p);   
 | ||
|   }              
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Crea un segnalibro
 | ||
| //
 | ||
| // @rdesc Ritorna l'identificatore del segnalibro creato
 | ||
| int TPrinter::set_bookmark(
 | ||
|   const char* txt,      // @parm Nome del segnalibro da creare
 | ||
|   int father)           // @parm Identificatore del segnalibro padre a cui collegare quello 
 | ||
|   //     da creare
 | ||
| {                                                     
 | ||
|   if (_printertype == screenvis)
 | ||
|   {
 | ||
|     BkDef* bkd = new BkDef;
 | ||
|     
 | ||
|     bkd->_row       = (_currentrow + ((_currentpage - 1)*_formlen)) - 1;
 | ||
|     bkd->_father_id = father;
 | ||
|     bkd->_id        = _bookmarks.items() + 1;
 | ||
|     bkd->_txt       = txt;
 | ||
|     
 | ||
|     _bookmarks.add(bkd);
 | ||
|     
 | ||
|     return _bookmarks.items();
 | ||
|   }
 | ||
|   return 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TPrinter::print_txt(TTextfile& txt)
 | ||
| {
 | ||
|   bool ok = txt.lines() > 0;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     TPrint_txt_info what(txt);
 | ||
|     ok = what.edit();
 | ||
|     if (ok)
 | ||
|     {
 | ||
|       xvt_print_open();
 | ||
|       xvt_print_start_thread(start_print, long(&what));
 | ||
|       xvt_print_close();
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::print_pdf(TTextfile& txt, const TFilename& pdf)
 | ||
| {
 | ||
|   bool ok = txt.lines() > 0;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     TPrint_txt_info what(txt);
 | ||
|     if (pdf.blank())
 | ||
|       what.editpdf();
 | ||
|     else
 | ||
|       what._pdf_file = pdf;
 | ||
| 
 | ||
|     ok = what._pdf_file.full();
 | ||
|     if (ok)
 | ||
|     {
 | ||
|       TFilename old_printer; 
 | ||
|       xvt_print_open();
 | ||
|       xvt_print_get_name(_print_rcd, old_printer.get_buffer(), old_printer.size());
 | ||
|       xvt_print_set_name(_print_rcd, XVT_PDF_PRINTER_NAME);
 | ||
|       xvt_print_start_thread(start_print_pdf, long(&what));
 | ||
|       xvt_print_set_name(_print_rcd, old_printer);
 | ||
|       xvt_print_close();
 | ||
|     }
 | ||
|   }  
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::acrobatically_print_pdf(const TFilename& pdf) const
 | ||
| {
 | ||
|   TString cmd(512);
 | ||
|   bool ok = xvt_sys_find_editor(pdf, cmd.get_buffer()) != FALSE;
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     // /s=suppress banner; /t=file name + printer name
 | ||
|     cmd << " /s /t \"" << pdf << "\" \"" << printername() << "\"";
 | ||
|     xvt_sys_execute(cmd, TRUE, FALSE);
 | ||
|   }
 | ||
|   else
 | ||
|     error_box(TR("Adobe Acrobat non installato"));
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::auto_export(const TFilename& n)
 | ||
| {
 | ||
|   TString ext = n.ext();
 | ||
|   if (ext.blank())
 | ||
|     return false;
 | ||
|   ext.lower();
 | ||
|   
 | ||
|   if (ext == "pdf")
 | ||
|   {
 | ||
|     print_pdf(_txt, n);
 | ||
|     return true;
 | ||
|   }
 | ||
| 
 | ||
|   if (ext.starts_with("xls"))
 | ||
|     return _txt.write_xls(n);
 | ||
| 
 | ||
|   if (ext == "txt")
 | ||
|   {
 | ||
|     ofstream txt(n); 
 | ||
|     for (long i = 0; i < _txt.lines(); i++)
 | ||
|       txt << _txt.line(i) << '\n';
 | ||
|     txt.close();
 | ||
|     return true;
 | ||
|   }
 | ||
| 
 | ||
|   return false;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TPrinter::close()
 | ||
| {
 | ||
|   // la stampante era aperta e ho stampato qualcosa c'<27> footer da stampare
 | ||
|   if (isopen() && _currentrow > 1 && _footersize > 0)
 | ||
|     formfeed();
 | ||
| 
 | ||
|   switch (_printertype)
 | ||
|   {
 | ||
|   case winprinter: 
 | ||
|     if (_txt.lines() > 0L)
 | ||
|       print_txt(_txt);
 | ||
|     break;
 | ||
|   case fileprinter:
 | ||
|     if (_printerfile.full() && _txt.lines() > 0L)
 | ||
|     {
 | ||
|       bool done = false;
 | ||
|       if (!_appendfile)
 | ||
|         done = auto_export(_printerfile);
 | ||
|       if (!done)
 | ||
|       {
 | ||
|         FILE* fp = fopen(_printerfile, _appendfile ? "a" : "w"); 
 | ||
|         if (fp != NULL)
 | ||
|         {
 | ||
|           for (long i = 0; i < _txt.lines(); i++)
 | ||
|             fprintf(fp,"%s\n", _txt.line(i));
 | ||
|           fclose(fp);
 | ||
|           done = true;
 | ||
|         }
 | ||
|       }
 | ||
|       if (done)
 | ||
|         message_box(FR("Stampa su file terminata. Nome archivio: %s"),(const char *)_printerfile);
 | ||
|       else
 | ||
|         cantwrite_box(_printerfile);      
 | ||
|     }
 | ||
|     break;
 | ||
|   case exportprinter:
 | ||
|     if (_exportfile.full() && _txt.lines() > 0L)
 | ||
|     {
 | ||
|       ofstream txt(_exportfile); 
 | ||
|       for (long i = 0; i < _txt.lines(); i++)
 | ||
|         txt << _txt.line_formatted(i) << '\n';
 | ||
|       txt.close();
 | ||
|     }
 | ||
|     break;
 | ||
|   case acrobatprinter: 
 | ||
|     {
 | ||
|       TWait_cursor hourglass;
 | ||
|       TFilename fn; fn.tempdir(); fn.add("tmp.pdf");
 | ||
|       if (print_pdf(_txt, fn))
 | ||
|         acrobatically_print_pdf(fn);
 | ||
|       fn.fremove();
 | ||
|     }
 | ||
|     break;
 | ||
|   case screenvis:
 | ||
|   default:
 | ||
|     {
 | ||
|       _vf->close_print();
 | ||
|       const KEY key = _vf->run();
 | ||
|       if (_vf->is_open()) 
 | ||
|         _vf->close_modal();  
 | ||
|       _bookmarks.destroy();   
 | ||
|       
 | ||
|       if (key == K_CTRL+'S')
 | ||
|       {
 | ||
|         _isopen = false;
 | ||
|         _currentrow = _currentpage = 1;
 | ||
|         print_txt(_vf->text());
 | ||
|       }
 | ||
| 
 | ||
|       delete _vf; _vf = NULL;
 | ||
|     }
 | ||
|     break;
 | ||
|   }
 | ||
|   
 | ||
|   if (_finker) 
 | ||
|   {
 | ||
|     delete _finker;
 | ||
|     _finker = NULL;
 | ||
|   }
 | ||
|   
 | ||
|   // Dealloca sfondi ormai inutili
 | ||
|   // _backgrounds.destroy(); // Invece servono per esportazioni successive!
 | ||
|   
 | ||
|   freeze (false);             
 | ||
|   _isopen = false;
 | ||
| }
 | ||
| 
 | ||
| //  
 | ||
| // TFile_printer
 | ||
| // 
 | ||
| 
 | ||
| #include <bagn004.h>
 | ||
| 
 | ||
| const long disk_sizes[] = { 360000L, 1200000L, 720000L, 1400000L, 2880000L };
 | ||
| 
 | ||
| TFile_printer::TFile_printer (const char *ffile, const char *label, int len_rec, int num_rec_inizio, int num_rec_fine, int tipo_disco)
 | ||
| {
 | ||
|   set_printtype (fileprinter);
 | ||
| 
 | ||
|   _num_rec_testa_coda = num_rec_inizio + num_rec_fine;
 | ||
|   _file = ffile;
 | ||
|   _label = label;
 | ||
|   _len_rec = len_rec;
 | ||
|   _volume = 1;
 | ||
|   _size = disk_sizes[tipo_disco];
 | ||
|   _num_rec_volume = int ((_size / len_rec) - _num_rec_testa_coda);
 | ||
|   _nome_file_fissato = true;
 | ||
|   _label_fissata = true;
 | ||
| }
 | ||
| 
 | ||
| void TFile_printer::open()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| void TFile_printer::close ()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| bool TFile_printer::genera_dischetti ()
 | ||
| {
 | ||
|   int r;
 | ||
| 
 | ||
|   for (int i = 0; i < _tmp_files.items (); i++)
 | ||
|   {
 | ||
|     // Avvisa l'utente di inserire un dischetto
 | ||
|     r = yesno_box ("Inserire il dischetto n. %2d di %2d nel drive %2s",
 | ||
|                    i + 1, _volume, _drive);
 | ||
|     if (!r)
 | ||
|       return error_box ("Procedura interrotta!");
 | ||
| 
 | ||
|     // copia il file sul dischetto
 | ||
|     fcopy ((const char *) &_tmp_files[i], (const char *) _drive);
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| TFile_printer::~TFile_printer ()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| bool TFile_printer::set ()
 | ||
| {
 | ||
|   TMask m ("bagn004");
 | ||
|   int f;
 | ||
| 
 | ||
|   //
 | ||
|   // 
 | ||
|   // --------------------------------------------------------------------
 | ||
|   // Qui bisogna inserire la lista dei drive disponibili nella maschera
 | ||
|   // Per ora tale lista e' fissa e contiene solo A: e B:
 | ||
|   // --------------------------------------------------------------------
 | ||
|   // 
 | ||
|   // 
 | ||
| 
 | ||
|   m.set (F_FILE_DESTINAZIONE, _file);
 | ||
|   m.set (F_LABEL, _label);
 | ||
| 
 | ||
|   if (_nome_file_fissato)
 | ||
|     m.disable (F_FILE_DESTINAZIONE);
 | ||
| 
 | ||
|   if (_label_fissata)
 | ||
|     m.disable (F_LABEL);
 | ||
| 
 | ||
|   const bool ok = m.run () == K_ENTER;
 | ||
| 
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     f = atoi(m.get(F_FORMATO_DISCO));
 | ||
|     _drive = m.get(F_DRIVE);
 | ||
|     _file = m.get(F_FILE_DESTINAZIONE);
 | ||
|     _label = m.get(F_LABEL);
 | ||
|     _size = disk_sizes[f];
 | ||
|     _num_rec_volume = int ((_size / _len_rec) - _num_rec_testa_coda);
 | ||
|   } 
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 | ||
|  
 | ||
| const char* TPrinter::background_chars(int l) const 
 | ||
| { 
 | ||
|   return _finker == NULL ? "" : _finker->get_chars(l); 
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Calcolo dimensione font
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| struct font_data
 | ||
| { 
 | ||
|   TString _name;
 | ||
|   int     _size;
 | ||
|   int     _columns;
 | ||
| };
 | ||
| 
 | ||
| HIDDEN BOOLEAN calc_font_callback(long data)
 | ||
| {
 | ||
|   font_data& fd = *(font_data*)data;
 | ||
|   
 | ||
|   // Create print window
 | ||
|   TPrinter& pr = printer();
 | ||
|   WINDOW win = xvt_print_create_win(pr.get_printrcd(), "Calcolo font");
 | ||
|   
 | ||
|   if (win != NULL_WIN)
 | ||
|   {
 | ||
|     long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
 | ||
|     xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, pr.get_printrcd(), &ph, &pw, &pvr, &phr);
 | ||
|     xvtil_set_font(win, pr.fontname(), XVT_FS_NONE, pr.get_char_size());
 | ||
| 
 | ||
|   
 | ||
|     TString test(fd._columns);
 | ||
|     test.fill('M', fd._columns);
 | ||
|     int size;
 | ||
|     
 | ||
|     for (size = fd._size; size > 0; size--)
 | ||
|     {
 | ||
|       // Set print font
 | ||
|       xvtil_set_font(win, fd._name, XVT_FS_NONE, size);
 | ||
| 
 | ||
|       const int w = xvt_dwin_get_text_width(win, test, fd._columns);
 | ||
|       if (w <= pw)
 | ||
|         break;
 | ||
|     }
 | ||
|     
 | ||
|     if (size > 0)
 | ||
|       fd._size = size;  
 | ||
|       
 | ||
|     xvt_vobj_destroy(win);
 | ||
|   } 
 | ||
|   
 | ||
|   return win != NULL_WIN;
 | ||
| }
 | ||
| 
 | ||
| int TPrinter::calc_font_size(int columns) const
 | ||
| { 
 | ||
|   font_data fd;
 | ||
|   fd._name = fontname();
 | ||
|   fd._size = get_char_size();           
 | ||
|   fd._columns = columns;
 | ||
|   
 | ||
|   xvt_print_open();
 | ||
|   xvt_print_start_thread(calc_font_callback, (long)&fd);
 | ||
|   xvt_print_close();
 | ||
|   
 | ||
|   return fd._size;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN BOOLEAN calc_cols_callback(long data)
 | ||
| {
 | ||
|   int &numcols=*(int *)data;
 | ||
| 
 | ||
|   // Create print window
 | ||
|   TPrinter& pr = printer();
 | ||
|   WINDOW win = xvt_print_create_win(pr.get_printrcd(), "Calcolo numero colonne");
 | ||
|   if (win != NULL_WIN)
 | ||
|   {
 | ||
|     long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution
 | ||
|     xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, pr.get_printrcd(), &ph, &pw, &pvr, &phr);
 | ||
|     xvtil_set_font(win, printer().fontname(), XVT_FS_NONE, pr.get_char_size());
 | ||
| 
 | ||
|     // Compute maximum number of chars per line
 | ||
|     int mincol = 1, maxcol = MAX_PR_WIDTH;
 | ||
|     const TString spc(maxcol,'M');  
 | ||
|       
 | ||
|     numcols = (pw * 120) / (pr.get_char_size() * phr);  // Primo guess
 | ||
|     
 | ||
|     while (mincol < maxcol )
 | ||
|     {
 | ||
|       const int w = xvt_dwin_get_text_width(win, spc, numcols);
 | ||
|       if (w < pw)
 | ||
|         mincol = numcols+1;
 | ||
|       else
 | ||
|         maxcol=numcols-1;
 | ||
|       numcols=(mincol+maxcol)/2;
 | ||
|     }     
 | ||
|       
 | ||
|     xvt_vobj_destroy(win);
 | ||
|   } 
 | ||
|   
 | ||
|   return win != NULL_WIN;
 | ||
| }
 | ||
| 
 | ||
| // Funzione chiamata solo da sv1200, ma non si capisce perche' non usi la formwidth()
 | ||
| int TPrinter::calc_num_cols() const
 | ||
| { 
 | ||
|   int numcols = 80; // Default sensato
 | ||
|   xvt_print_open();
 | ||
|   xvt_print_start_thread(calc_cols_callback, (long)&numcols);
 | ||
|   xvt_print_close();
 | ||
|   
 | ||
|   return numcols;
 | ||
| }
 | ||
| 
 | ||
| void TPrinter::set_portrait_orientation(bool portrait)
 | ||
| {
 | ||
|   long pw, ph; // Printer width, height
 | ||
|   PRINT_RCD* rcd = get_printrcd();
 | ||
|   xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, rcd, &ph, &pw, NULL, NULL);
 | ||
|   const bool is_portrait = ph >= pw;
 | ||
|   if (portrait != is_portrait)
 | ||
|     xvt_app_escape(XVT_ESC_SET_PRINTER_INFO, rcd, &pw, &ph, NULL, NULL);
 | ||
| }
 | ||
| 
 | ||
| bool TPrinter::is_landscape() const
 | ||
| {
 | ||
|   long ph = 0, pw = 0;
 | ||
|   xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _print_rcd, &ph, &pw, NULL, NULL);
 | ||
|   return pw > ph;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TTabulator
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TTab_info : public TObject
 | ||
| { 
 | ||
|   int _start, _end; 
 | ||
| 
 | ||
| public:
 | ||
|   int intersection(int s, int e) const;
 | ||
|   int intersection(const TTab_info& i) const { return intersection(i._start, i._end); }
 | ||
|   
 | ||
|   void set_start(int s)  { _start = s; }
 | ||
|   void set_end(int e)    { _end = e; }
 | ||
|   void set(int s, int e) { _start = s; _end = e; }
 | ||
|   int start() const { return _start; }
 | ||
|   int end() const   { return _end; }
 | ||
|   int width() const { return _end - _start + 1; }
 | ||
|   bool operator==(const TTab_info& ti) const { return _start == ti.start() && _end == ti.end(); }
 | ||
|   
 | ||
|   TTab_info(int s, int e) { set(s, e); }
 | ||
| };
 | ||
| 
 | ||
| int TTab_info::intersection(int s, int e) const
 | ||
| {
 | ||
|   int i = 0;
 | ||
|   if (e >= _start && s <= _end)
 | ||
|     i = min(_end, e) - max(_start, s);
 | ||
|   return i;
 | ||
| }
 | ||
| 
 | ||
| void TTabulator::add(int s, int e)
 | ||
| {
 | ||
|   if (e >= s)
 | ||
|     _tab.add(new TTab_info(s, e));
 | ||
| }
 | ||
| 
 | ||
| void TTabulator::split(int s0, int e0, int s1, int e1)
 | ||
| {
 | ||
|   if (s0 >= (s1+e1)/2 && e0 <= e1+1)
 | ||
|   {
 | ||
|     add(s1, s0-1);
 | ||
|     add(s0, max(e1, e0));
 | ||
|     return;
 | ||
|   }
 | ||
|   if (s1 >= (s0+e0)/2 && e1 <= e0+1)
 | ||
|   {
 | ||
|     add(s0, s1-1);
 | ||
|     add(s1, max(e0,e1));
 | ||
|     return;
 | ||
|   }
 | ||
|   add(min(s0,s1), max(e0,e1));
 | ||
| /*
 | ||
|   int a[4] = { s0, e0, s1, e1 };
 | ||
|   
 | ||
|   int i, j;
 | ||
|   for (i = 0; i < 3; i++)
 | ||
|   {
 | ||
|     for (j = i+1; j < 4; j++)
 | ||
|     {
 | ||
|       if (a[i] > a[j])
 | ||
|       { const int tmp = a[i]; a[i] = a[j]; a[j] = tmp; }
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   int t = 3;
 | ||
|   for (i = 0; i < t; i++)
 | ||
|   {
 | ||
|     j = i+1;
 | ||
|     if (abs(a[i]-a[j]) <= 1)
 | ||
|     {
 | ||
|       if (i < 2)
 | ||
|         a[i] = a[j] = min(a[i],a[j]);
 | ||
|       else
 | ||
|         a[i] = a[j] = max(a[i],a[j]);
 | ||
|       t--;
 | ||
|       for (j = i+1; j <= t;  j++)
 | ||
|         a[j] = a[j+1];
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   if (t > 0)
 | ||
|   {
 | ||
|     a[t-1]++;
 | ||
|     for (i = 0; i < t; i++)
 | ||
|       add(a[i], a[i+1]-1);
 | ||
|   }
 | ||
| */
 | ||
| }
 | ||
| 
 | ||
| int TTabulator::find_column(int column, int width) const
 | ||
| {
 | ||
|   int start = column;
 | ||
|   int end = column + width - 1;
 | ||
| 
 | ||
|   int index = -1, inter = 0;
 | ||
|   FOR_EACH_ARRAY_ITEM(_tab, t, obj)
 | ||
|   {
 | ||
|     TTab_info& ti = *(TTab_info*)obj;
 | ||
|     const int i = ti.intersection(start, end);
 | ||
|     if (i > inter)
 | ||
|     {
 | ||
|       inter = i;
 | ||
|       index = t;
 | ||
|     }
 | ||
|   }
 | ||
|   return index;
 | ||
| }
 | ||
| 
 | ||
| static int tab_compare(const TObject** o0, const TObject** o1)
 | ||
| {
 | ||
|   const TTab_info& t0 = *(TTab_info*)*o0;
 | ||
|   const TTab_info& t1 = *(TTab_info*)*o1;
 | ||
|   return t0.start() - t1.start();
 | ||
| }
 | ||
| 
 | ||
| void TTabulator::add_field(int column, int width)
 | ||
| {
 | ||
|   int start = column;
 | ||
|   int end = column + width - 1;
 | ||
|   int index = find_column(column, width);
 | ||
|   if (index >= 0)
 | ||
|   {
 | ||
|     const TTab_info& ti = (const TTab_info&)_tab[index];
 | ||
|     if (ti.intersection(start, end) < width)
 | ||
|     {
 | ||
|       split(start, end, ti.start(), ti.end());
 | ||
|       _tab.destroy(index, true);
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|     add(start, end);
 | ||
| }
 | ||
| 
 | ||
| bool TTabulator::empty() const
 | ||
| {
 | ||
|   return _tab.items() <= 1;
 | ||
| }
 | ||
| 
 | ||
| void TTabulator::sort()
 | ||
| {
 | ||
|   if (empty())
 | ||
|   {
 | ||
|     _tab.destroy();
 | ||
|     for (int i = 0; i < 256; i += 8)
 | ||
|       add(i, i+7);
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     _tab.sort(tab_compare);
 | ||
|     for (int i = _tab.last(); i > 0; i--)
 | ||
|     {
 | ||
|       TTab_info& t0 = (TTab_info&)_tab[i-1];
 | ||
|       TTab_info& t1 = (TTab_info&)_tab[i];
 | ||
|       if (t1 == t0 || t1.width() <= 0)
 | ||
|         _tab.destroy(i);
 | ||
|       else
 | ||
|       {
 | ||
|         if (t1.start() - t0.end() >= 8)
 | ||
|         {
 | ||
|           _tab.insert(new TTab_info(t0.end()+1, t1.start()-1), i);
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           const int center = (t0.end() + t1.start())/2;
 | ||
|           t0.set_end(center);
 | ||
|           t1.set_start(center+1);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 |