Files correlati : bagn009.msk Ricompilazione Demo : [ ] Commento : Aggiunte icone di supporto alla firma digitale git-svn-id: svn://10.65.10.50/trunk@18442 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			2746 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2746 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <automask.h>
 | 
						|
#include <colors.h>
 | 
						|
#include <config.h>
 | 
						|
#include <defmask.h>
 | 
						|
#include <diction.h>
 | 
						|
#include <dongle.h>
 | 
						|
#include <modaut.h>
 | 
						|
#include <printer.h>
 | 
						|
#include <progind.h>
 | 
						|
#include <reprint.h>
 | 
						|
#include <spotlite.h>
 | 
						|
#include <statbar.h>
 | 
						|
#include <treectrl.h>
 | 
						|
#include <urldefid.h>
 | 
						|
#include <utility.h>
 | 
						|
#include <xvtility.h>
 | 
						|
 | 
						|
#include <bagn003.h>
 | 
						|
 | 
						|
static bool _print_aborted = false;
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Utility
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
static void advanced_draw_justified_text_line(WINDOW w, const char* text, short x, short y, short dx)
 | 
						|
{
 | 
						|
  TString256 txt(text); txt.rtrim(); 
 | 
						|
  int spaces = 0;
 | 
						|
  for (int s = 0; txt[s]; s++)
 | 
						|
    if (isspace(txt[s])) spaces++;
 | 
						|
 | 
						|
  // Il testo e' giustificabile se ha degli spazi ed occupa meno della riga
 | 
						|
  if (spaces > 0)
 | 
						|
  {
 | 
						|
    const int tw = xvt_dwin_get_text_width(w, txt, -1);
 | 
						|
    if (tw < dx)
 | 
						|
    {
 | 
						|
      txt << ' '; // Aggiunge spazio finale
 | 
						|
      const double kspc = double(dx - tw) / spaces;
 | 
						|
      int start = 0;
 | 
						|
      double kx = x;
 | 
						|
      for (int i = 0; txt[i]; i++) if (isspace(txt[i]))
 | 
						|
      {
 | 
						|
        const bool last_word = txt[i+1] == '\0';
 | 
						|
        const TString& parola = txt.sub(start, i + (last_word ? 0 : 1));
 | 
						|
        const int lw = xvt_dwin_get_text_width(w, parola, -1);
 | 
						|
        if (last_word) // ultima parola
 | 
						|
          kx = x+dx-lw;
 | 
						|
        xvt_dwin_draw_text(w, int(kx+0.5), y, parola, -1);
 | 
						|
        kx += lw + kspc;
 | 
						|
        start = i+1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      xvt_dwin_draw_text(w, x, y, txt, -1); // Stringa che deborda dalla riga
 | 
						|
  }
 | 
						|
  else
 | 
						|
    xvt_dwin_draw_text(w, x, y, txt, -1); // Stringa senza spazi
 | 
						|
}
 | 
						|
 | 
						|
void advanced_draw_text_line(WINDOW w, const char* text, const RCT& r, char halign, char valign)
 | 
						|
{
 | 
						|
  const short dx = r.right-r.left;
 | 
						|
  const short dy = r.bottom-r.top;
 | 
						|
  short x = r.left;
 | 
						|
  short y = r.bottom;
 | 
						|
  
 | 
						|
  if (halign != 'L')
 | 
						|
  {
 | 
						|
    const int tw = xvt_dwin_get_text_width(w, text, -1);
 | 
						|
    switch (halign)
 | 
						|
    {
 | 
						|
    case 'C': x += (dx - tw)/2; break;
 | 
						|
    case 'R': x = r.right-tw; break;
 | 
						|
    default : break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Text Height
 | 
						|
  int leading, ascent, descent;
 | 
						|
  xvt_dwin_get_font_metrics(w, &leading, &ascent, &descent);
 | 
						|
  switch (valign)
 | 
						|
  {
 | 
						|
  case 'C': y -= (dy - ascent)/2; break;
 | 
						|
  case 'T': y = r.top + leading + ascent; break;
 | 
						|
  default : y -= descent; break;
 | 
						|
  }
 | 
						|
	bool can_draw = true;
 | 
						|
  RCT orig; xvt_dwin_get_clip(w, &orig);
 | 
						|
  bool restore_clip = !xvt_rect_is_empty(&orig);
 | 
						|
 | 
						|
	if (restore_clip)
 | 
						|
  {
 | 
						|
	  RCT clipper;
 | 
						|
		can_draw = xvt_rect_intersect(&clipper, &orig, (RCT*)&r) != 0;
 | 
						|
		if (can_draw)
 | 
						|
			xvt_dwin_set_clip(w, (RCT*)&clipper);
 | 
						|
		else
 | 
						|
			restore_clip = false;
 | 
						|
  }
 | 
						|
  else
 | 
						|
	  xvt_dwin_set_clip(w, (RCT*)&r);
 | 
						|
  
 | 
						|
  if (can_draw)
 | 
						|
	{
 | 
						|
		if (halign == 'J')
 | 
						|
			advanced_draw_justified_text_line(w, text, x, y, dx);
 | 
						|
		else
 | 
						|
			xvt_dwin_draw_text(w, x, y, text, -1);
 | 
						|
		if (restore_clip)
 | 
						|
			xvt_dwin_set_clip(w, &orig);
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
bool finisce_per_punto(const TString& str)
 | 
						|
{
 | 
						|
  bool yes = false;
 | 
						|
  const int len = str.len();
 | 
						|
  if (len > 0)
 | 
						|
  {
 | 
						|
    const char last = str[len-1];
 | 
						|
    yes = strchr(".!?:", last) != NULL;
 | 
						|
  }
 | 
						|
  return yes;
 | 
						|
}
 | 
						|
 | 
						|
void advanced_draw_paragraph(WINDOW win, const TString_array& para, const RCT& rct, 
 | 
						|
                             char halign, char valign, int default_10row_height)
 | 
						|
{
 | 
						|
  const int rows = para.items();
 | 
						|
  if (rows > 1) // Devo scrivere piu' righe?
 | 
						|
  {
 | 
						|
    int leading, ascent, descent;
 | 
						|
    xvt_dwin_get_font_metrics(win, &leading, &ascent, &descent);
 | 
						|
  
 | 
						|
    int ky10 = (leading + ascent + descent) * 10;
 | 
						|
    // Aggiusta l'altezza di una riga standard, se necessario
 | 
						|
    if (ky10 < default_10row_height && ky10 > 75*default_10row_height/100)
 | 
						|
      ky10 = default_10row_height;
 | 
						|
 | 
						|
    const int rct_height = rct.bottom - rct.top;
 | 
						|
 | 
						|
    int ybase = rct.top;
 | 
						|
    switch (valign)
 | 
						|
    {
 | 
						|
    case 'C': ybase += (rct_height - (rows * ky10) / 10) / 2; break;
 | 
						|
    case 'B': ybase += rct_height - (rows * ky10) / 10; break;
 | 
						|
    default : break;
 | 
						|
    }
 | 
						|
    
 | 
						|
    for (int row = 0; row < rows; row++)
 | 
						|
    {
 | 
						|
      const int top = ybase + (ky10 * row) / 10;
 | 
						|
      if (top < rct.bottom)
 | 
						|
      {
 | 
						|
        const TString& line = para.row(row);
 | 
						|
        if (line.full())
 | 
						|
        {
 | 
						|
          RCT rctline = rct;
 | 
						|
          rctline.top = top;
 | 
						|
          rctline.bottom = top + ky10 / 10;
 | 
						|
          char ha = halign;
 | 
						|
          if (ha == 'J' && (row == rows-1 || finisce_per_punto(line)))
 | 
						|
            ha = 'L'; // Le righe finali non vanno giustificate
 | 
						|
          advanced_draw_text_line(win, line, rctline, ha, 'T'); 
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (halign == 'J') halign = 'L'; // Le righe isolate non vanno giustificate
 | 
						|
    advanced_draw_text_line(win, para.row(0), rct, halign, valign); 
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TReport_link
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void TReport_link::set(const char* field, const TString& var)
 | 
						|
{
 | 
						|
  _fields.add(field, var, true);
 | 
						|
}
 | 
						|
 | 
						|
const TString& TReport_link::get(const char* field) const
 | 
						|
{
 | 
						|
  const TString* var = (const TString*)_fields.objptr(field);
 | 
						|
  return var != NULL ? *var : (const TString&)EMPTY_STRING;
 | 
						|
}
 | 
						|
 | 
						|
void TReport_link::add_rect(const RCT& rct)
 | 
						|
{
 | 
						|
  // Non memorizzo tutti i rettangoli del link, ma la loro unione
 | 
						|
  if (xvt_rect_is_empty(&_rct))
 | 
						|
    _rct = rct;
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (rct.left < _rct.left) _rct.left = rct.left;
 | 
						|
    if (rct.top < _rct.top) _rct.top = rct.top;
 | 
						|
    if (rct.right > _rct.right) _rct.right = rct.right;
 | 
						|
    if (rct.bottom > _rct.bottom) _rct.bottom = rct.bottom;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int TReport_link::hit_test(const PNT& p) const
 | 
						|
{
 | 
						|
  if (p.v < _rct.top)
 | 
						|
    return -1;
 | 
						|
  if (p.v > _rct.bottom)
 | 
						|
    return +1;
 | 
						|
  if (p.h < _rct.left)
 | 
						|
    return -1;
 | 
						|
  if (p.h > _rct.right)
 | 
						|
    return +1;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TReport_link::compare(const TSortable& s) const
 | 
						|
{
 | 
						|
  const TReport_link& lnk = (const TReport_link&)s;
 | 
						|
  int cmp = _rct.top - lnk._rct.top;
 | 
						|
  if (cmp == 0)
 | 
						|
    cmp = _rct.left - lnk._rct.left;
 | 
						|
  return cmp;
 | 
						|
}
 | 
						|
  
 | 
						|
TReport_link::TReport_link(const char* table)
 | 
						|
            : _table(table)
 | 
						|
{
 | 
						|
  xvt_rect_set_empty(&_rct);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPrint_preview_window
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TPrint_preview_window : public TField_window
 | 
						|
{
 | 
						|
  TBook* _book;
 | 
						|
  word _page;
 | 
						|
  int _zoom;
 | 
						|
  bool _grid;
 | 
						|
  
 | 
						|
  TAssoc_array _alinks;
 | 
						|
  TPointer_array _plinks;
 | 
						|
 | 
						|
protected:
 | 
						|
  void page_select();
 | 
						|
  void popup_menu(EVENT* ep);
 | 
						|
  const TReport_link* find_link(const PNT& pnt) const;
 | 
						|
  void draw_page(int pg);
 | 
						|
 | 
						|
  virtual void handler(WINDOW win, EVENT* ep);
 | 
						|
  virtual void update();
 | 
						|
  virtual bool on_key(KEY k);
 | 
						|
 | 
						|
  void do_scroll(int kx, int ky);
 | 
						|
 | 
						|
public:
 | 
						|
  virtual PNT log2dev(long lx, long ly) const;
 | 
						|
  void update_scroll_range();
 | 
						|
 | 
						|
  TAssoc_array& alinks() { return _alinks; }
 | 
						|
  TPointer_array& plinks() { return _plinks; }
 | 
						|
 | 
						|
  TPrint_preview_window(int x, int y, int dx, int dy, WINDOW parent, 
 | 
						|
                        TWindowed_field* owner, TBook* book);
 | 
						|
  virtual ~TPrint_preview_window();
 | 
						|
};
 | 
						|
 | 
						|
PNT TPrint_preview_window::log2dev(long lx, long ly) const
 | 
						|
{
 | 
						|
  PNT pnt = { short(ly), short(lx) };
 | 
						|
  
 | 
						|
  const TPoint res = _book->page_res();
 | 
						|
  if (res.x > 0 && res.y > 0) // Should always be true :-)
 | 
						|
  {
 | 
						|
    pnt.h = short(lx * _zoom / res.x);
 | 
						|
    pnt.v = short(ly * _zoom / res.y);
 | 
						|
  }
 | 
						|
 | 
						|
  const TPoint orig = origin();
 | 
						|
  pnt.h -= short(orig.x);
 | 
						|
  pnt.v -= short(orig.y);
 | 
						|
 | 
						|
  return pnt;
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::update_scroll_range()
 | 
						|
{
 | 
						|
  update_thumb(0, 0); // Azzero origine
 | 
						|
 | 
						|
  const TPoint pag = _book->page_size();
 | 
						|
  const PNT pnt = log2dev(pag.x, pag.y);
 | 
						|
 | 
						|
  RCT rct; xvt_vobj_get_client_rect(win(), &rct);
 | 
						|
  const PNT siz = { rct.bottom, rct.right };
 | 
						|
 
 | 
						|
  set_scroll_max(pnt.h, pnt.v);
 | 
						|
  set_thumb_size(siz.h, siz.v);
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::draw_page(int pg)
 | 
						|
{
 | 
						|
  RCT rct; xvt_vobj_get_client_rect(win(), &rct);
 | 
						|
 | 
						|
  const TPoint size = _book->page_size();
 | 
						|
  const PNT pag = log2dev(size.x, size.y);
 | 
						|
  const PNT ori = log2dev(0, 0);
 | 
						|
  if (ori.h > 0) rct.left = ori.h;
 | 
						|
  if (ori.v > 0) rct.top = ori.v;
 | 
						|
  if (pag.h < rct.right) rct.right = pag.h;
 | 
						|
  if (pag.v < rct.bottom) rct.bottom = pag.v;
 | 
						|
  
 | 
						|
  hide_pen(); // Disegna foglio bianco
 | 
						|
  set_brush(COLOR_WHITE);
 | 
						|
  xvt_dwin_draw_rect(win(), &rct); 
 | 
						|
  
 | 
						|
  set_pen(COLOR_GRAY); // Disegna ombra grigia
 | 
						|
  const PNT poly[4] = { {rct.bottom,rct.left+1}, {rct.bottom,rct.right+1}, {rct.top+1,rct.right+1}, {0,0} };
 | 
						|
  xvt_dwin_draw_polyline(win(), poly, 3); // Disegna ombra
 | 
						|
 | 
						|
  if (_grid)
 | 
						|
  {
 | 
						|
    const TPoint res = _book->page_res();
 | 
						|
    const int lpi = _book->lpi();
 | 
						|
    for (int i = 1; lpi > 0; i++)
 | 
						|
    {
 | 
						|
      set_pen(i%lpi ? XVT_MAKE_COLOR(232,232,255) : XVT_MAKE_COLOR(255,192,255));
 | 
						|
      const short y = short(i * res.y / lpi);
 | 
						|
      if (y > size.y)
 | 
						|
        break;
 | 
						|
      line(0, y, (short)size.x, y);
 | 
						|
    }
 | 
						|
    const int cpi = _book->cpi();
 | 
						|
    for (int j = 1; cpi > 0; j++)
 | 
						|
    {
 | 
						|
      set_pen(j%10 ? XVT_MAKE_COLOR(232,232,255) : XVT_MAKE_COLOR(255,192,255));
 | 
						|
      const short x = short(j * res.x / cpi);
 | 
						|
      if (x > size.x)
 | 
						|
        break;
 | 
						|
      line(x, 0, x, (short)size.y);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  _book->print_page(*this, pg);
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::update()
 | 
						|
{
 | 
						|
  clear(MASK_BACK_COLOR);
 | 
						|
 
 | 
						|
  draw_page(_page);
 | 
						|
  size_t last_page = _page;
 | 
						|
  const size_t pages = _book->pages();
 | 
						|
  
 | 
						|
  if (_page < pages)
 | 
						|
  {
 | 
						|
    const TPoint o = origin();
 | 
						|
    set_origin(0, 0);
 | 
						|
    const TPoint size = _book->page_size();
 | 
						|
    const PNT pag = log2dev(size.x, size.y);
 | 
						|
    RCT rct; xvt_vobj_get_client_rect(win(), &rct);
 | 
						|
    const int nh = rct.right / (pag.h+2), nv = rct.bottom / (pag.v+2);
 | 
						|
    if (nh > 1 || nv > 1)
 | 
						|
    {
 | 
						|
      for (int v = 0; v < nv; v++)
 | 
						|
      {
 | 
						|
        for (int h = 0; h < nh; h++)
 | 
						|
        {
 | 
						|
          if ((h > 0 || v > 0) && last_page < pages)
 | 
						|
          {
 | 
						|
            set_origin(o.x - h*rct.right/nh, o.y - v*rct.bottom/nv);
 | 
						|
            draw_page(++last_page);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    set_origin(o.x, o.y);
 | 
						|
  }
 | 
						|
 | 
						|
  TString80 str; 
 | 
						|
  if (last_page > _page)
 | 
						|
    str.format(FR("Pagine da %u a %u di %u"), _page, last_page, pages);
 | 
						|
  else
 | 
						|
    str.format(FR("Pagina %u di %u"), _page, pages);
 | 
						|
  statbar_set_title(TASK_WIN, str);
 | 
						|
 | 
						|
  TMask& m = owner().mask();
 | 
						|
  m.enable(DLG_FIRSTREC, _page > 1);
 | 
						|
  m.enable(DLG_PREVREC, _page > 1);
 | 
						|
  m.enable(DLG_FINDREC, pages > 1);
 | 
						|
  m.enable(DLG_NEXTREC, _page < pages);
 | 
						|
  m.enable(DLG_LASTREC, _page < pages);
 | 
						|
}
 | 
						|
 | 
						|
#define POPUP_FIRST      20883
 | 
						|
#define POPUP_PREV       20884
 | 
						|
#define POPUP_NEXT       20885
 | 
						|
#define POPUP_SEARCH     20886
 | 
						|
#define POPUP_LAST       20887
 | 
						|
#define POPUP_ZOOMIN     20888
 | 
						|
#define POPUP_ZOOMOUT    20889
 | 
						|
#define POPUP_GRID       20890
 | 
						|
 | 
						|
void TPrint_preview_window::popup_menu(EVENT* ep)
 | 
						|
{
 | 
						|
  MENU_ITEM menu[16];  // Stiamo larghi
 | 
						|
  memset(menu, 0, sizeof(menu));
 | 
						|
  menu[0].tag = POPUP_FIRST;   menu[0].text = (char*)PR("Prima");    menu[0].enabled = _page > 1;
 | 
						|
  menu[1].tag = POPUP_PREV;    menu[1].text = (char*)PR("Indietro"); menu[1].enabled = _page > 1;
 | 
						|
  menu[2].tag = POPUP_NEXT;    menu[2].text = (char*)PR("Avanti");   menu[2].enabled = _page < _book->pages();
 | 
						|
  menu[3].tag = POPUP_LAST;    menu[3].text = (char*)PR("Ultima");   menu[3].enabled = _page < _book->pages();
 | 
						|
  menu[4].tag = -1;            menu[4].separator = true;
 | 
						|
  menu[5].tag = POPUP_ZOOMIN;  menu[5].text = (char*)PR("Zoom +");   menu[5].enabled = _zoom < 300;
 | 
						|
  menu[6].tag = POPUP_ZOOMOUT; menu[6].text = (char*)PR("Zoom -");   menu[6].enabled = _zoom > 35;
 | 
						|
  menu[7].tag = -1;            menu[7].separator = true;
 | 
						|
  menu[8].tag = POPUP_GRID;    menu[8].text = (char*)PR("Griglia");  menu[8].enabled = true; 
 | 
						|
                               menu[8].checkable = true;             menu[8].checked = _grid;
 | 
						|
 | 
						|
  const PNT& p = ep->v.mouse.where;
 | 
						|
  xvt_menu_popup(menu, win(), p, XVT_POPUP_CENTER, 0);
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::page_select()
 | 
						|
{
 | 
						|
  TMask m(TR("Ricerca"), 1, 28, 4);
 | 
						|
 | 
						|
  m.add_number(101, 0, PR("Pagina "), 1, 1, 4, "U").check_type(CHECK_REQUIRED);
 | 
						|
  m.add_button(DLG_OK, 0, "", -12, -1, 10, 2); 
 | 
						|
  m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
 | 
						|
  if (m.run())
 | 
						|
  {
 | 
						|
    _page = m.get_int(101);
 | 
						|
    if (_page < 1) _page = 1;
 | 
						|
    if (_page > _book->pages()) 
 | 
						|
      _page = _book->pages();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const TReport_link* TPrint_preview_window::find_link(const PNT& pnt) const
 | 
						|
{
 | 
						|
  int primo = 0, ultimo = _plinks.last();
 | 
						|
  while (primo <= ultimo)
 | 
						|
  {
 | 
						|
    const int in_mezzo = (primo+ultimo)/2;
 | 
						|
    const TReport_link* lnk = (const TReport_link*)_plinks.objptr(in_mezzo);
 | 
						|
    const int cmp = lnk->hit_test(pnt);
 | 
						|
    if (cmp == 0)
 | 
						|
      return lnk;
 | 
						|
    if (cmp < 0)
 | 
						|
      ultimo = in_mezzo-1;
 | 
						|
    else
 | 
						|
      primo = in_mezzo+1;
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::handler(WINDOW win, EVENT* ep)
 | 
						|
{
 | 
						|
  static PNT ptPan;
 | 
						|
  
 | 
						|
  switch (ep->type)
 | 
						|
  {
 | 
						|
  case E_MOUSE_MOVE:
 | 
						|
    switch (ep->v.mouse.button)
 | 
						|
    {
 | 
						|
    case 2:
 | 
						|
      {
 | 
						|
        const PNT& ptCur = ep->v.mouse.where;
 | 
						|
        TPoint orig = origin();
 | 
						|
        orig.x += ptPan.h - ptCur.h;
 | 
						|
        orig.y += ptPan.v - ptCur.v;
 | 
						|
        update_thumb(orig.x, orig.y);
 | 
						|
        force_update();
 | 
						|
        ptPan = ptCur;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      if (find_link(ep->v.mouse.where) != NULL)
 | 
						|
        xvt_win_set_cursor(win, 8004);          // Ditino
 | 
						|
      else
 | 
						|
        xvt_win_set_cursor(win, CURSOR_ARROW);  // Freccia
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case E_MOUSE_DOWN:
 | 
						|
    switch (ep->v.mouse.button)
 | 
						|
    {
 | 
						|
    case 0:
 | 
						|
      {
 | 
						|
        const TReport_link* lnk = find_link(ep->v.mouse.where);
 | 
						|
        if (lnk != NULL && _book != NULL) 
 | 
						|
          _book->on_link(*lnk);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case 1:
 | 
						|
      popup_menu(ep);
 | 
						|
      break;
 | 
						|
    case 2:
 | 
						|
      ptPan = ep->v.mouse.where;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case E_COMMAND:
 | 
						|
    {
 | 
						|
      bool processed = true;
 | 
						|
      switch(ep->v.cmd.tag)
 | 
						|
      {
 | 
						|
      case POPUP_FIRST  : 
 | 
						|
        processed = _page > 1; 
 | 
						|
        if (processed) _page = 1; 
 | 
						|
        break;
 | 
						|
      case POPUP_PREV   : 
 | 
						|
        processed = _page > 1; 
 | 
						|
        if (processed) _page--; 
 | 
						|
        break;
 | 
						|
      case POPUP_SEARCH : page_select(); break;
 | 
						|
      case POPUP_NEXT   : 
 | 
						|
        processed = _page < _book->pages(); 
 | 
						|
        if (processed) _page++; 
 | 
						|
        break;
 | 
						|
      case POPUP_LAST   : 
 | 
						|
        processed = _page < _book->pages(); 
 | 
						|
        if (processed) _page = _book->pages(); 
 | 
						|
        break;
 | 
						|
      case POPUP_ZOOMIN : if (_zoom < 300) { _zoom += 10; update_scroll_range(); } break;
 | 
						|
      case POPUP_ZOOMOUT: if (_zoom >  35) { _zoom -= 10; update_scroll_range(); } break;
 | 
						|
      case POPUP_GRID   : _grid = !_grid; break;
 | 
						|
      default:processed = false; break;
 | 
						|
      }
 | 
						|
      if (processed)
 | 
						|
        force_update();
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case E_HSCROLL:
 | 
						|
  case E_VSCROLL:
 | 
						|
    {
 | 
						|
      int kx = 0, ky = 0;
 | 
						|
      int& k = ep->type == E_HSCROLL ? kx : ky;
 | 
						|
      switch(ep->v.scroll.what)
 | 
						|
      {
 | 
						|
      case SC_PAGE_UP  : k = -3; break;
 | 
						|
      case SC_LINE_UP  : k = -1; break;
 | 
						|
      case SC_PAGE_DOWN: k = +3; break;
 | 
						|
      case SC_LINE_DOWN: k = +1; break;
 | 
						|
      default          : TField_window::handler(win, ep); break;
 | 
						|
      }
 | 
						|
      if (k != 0)
 | 
						|
        do_scroll(kx, ky); break;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    TField_window::handler(win, ep);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TPrint_preview_window::do_scroll(int kx, int ky)
 | 
						|
{
 | 
						|
  const TPoint& r = range();
 | 
						|
  TPoint orig = origin();
 | 
						|
  orig.x += kx * r.x/8;
 | 
						|
  orig.y += ky * r.y/6;
 | 
						|
  if (orig.x < 0) orig.x = 0;
 | 
						|
  if (orig.x > r.x) orig.x = r.x;
 | 
						|
  if (orig.y < 0) orig.y = 0;
 | 
						|
  if (orig.y > r.y) orig.y = r.y;
 | 
						|
  if (orig != origin())
 | 
						|
  {
 | 
						|
    update_thumb(orig.x, orig.y);
 | 
						|
    force_update();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TPrint_preview_window::on_key(KEY k)
 | 
						|
{
 | 
						|
  bool ok = true;
 | 
						|
  switch (k)
 | 
						|
  {
 | 
						|
  case '+'     : dispatch_e_menu(win(), POPUP_ZOOMIN); break; 
 | 
						|
  case '-'     : dispatch_e_menu(win(), POPUP_ZOOMOUT); break;
 | 
						|
  case K_HOME  :
 | 
						|
  case K_LHOME : dispatch_e_menu(win(), POPUP_FIRST); break;
 | 
						|
  case K_PREV  : dispatch_e_menu(win(), POPUP_PREV); break;
 | 
						|
  case K_NEXT  : dispatch_e_menu(win(), POPUP_NEXT); break;
 | 
						|
  case K_END:
 | 
						|
  case K_LEND  : dispatch_e_menu(win(), POPUP_LAST); break;
 | 
						|
  case K_LEFT  : do_scroll(-1, 0); break;
 | 
						|
  case K_RIGHT : do_scroll(+1, 0); break;
 | 
						|
  case K_UP    : do_scroll(0, -1); break;
 | 
						|
  case K_DOWN  : do_scroll(0, +1); break;
 | 
						|
  case 'G'     : 
 | 
						|
  case 'g'     : dispatch_e_menu(win(), POPUP_GRID); break;
 | 
						|
  default      : 
 | 
						|
    if (k > K_CTRL)
 | 
						|
      dispatch_e_char(parent(), k);  // Gestione acceleratori
 | 
						|
    else
 | 
						|
      ok = TField_window::on_key(k); 
 | 
						|
    break;
 | 
						|
  };
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
TPrint_preview_window::TPrint_preview_window(int x, int y, int dx, int dy, WINDOW parent, 
 | 
						|
                                             TWindowed_field* owner, TBook* book)
 | 
						|
                     : TField_window(x, y, dx, dy, parent, owner), _book(book), 
 | 
						|
                       _page(1), _zoom(100), _grid(false)
 | 
						|
{
 | 
						|
  _pixmap = true;
 | 
						|
  TConfig ini(CONFIG_GUI, "Preview");
 | 
						|
  _grid = ini.get_bool("Grid");
 | 
						|
}
 | 
						|
 | 
						|
TPrint_preview_window::~TPrint_preview_window()
 | 
						|
{
 | 
						|
  TConfig ini(CONFIG_GUI, "Preview");
 | 
						|
  ini.set("Grid", _grid ? "X" : "");
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPrint_preview_field
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TPrint_preview_field : public TWindowed_field
 | 
						|
{
 | 
						|
  TBook* _book;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual TField_window* create_window(int x, int y, int dx, int dy, WINDOW parent);
 | 
						|
 | 
						|
public:
 | 
						|
  TPrint_preview_field(TMask* m, TBook* book) : TWindowed_field(m), _book(book) { }
 | 
						|
};
 | 
						|
 | 
						|
TField_window* TPrint_preview_field::create_window(int x, int y, int dx, int dy, WINDOW parent)
 | 
						|
{
 | 
						|
  return new TPrint_preview_window(x, y, dx, dy, parent, this, _book);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPreview_mask
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TPreview_mask : public TAutomask
 | 
						|
{
 | 
						|
  TBook* _book;
 | 
						|
  TPrint_preview_field* _pvf;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual bool on_key(KEY k);
 | 
						|
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | 
						|
  virtual TMask_field* parse_field(TScanner& scanner);
 | 
						|
  virtual void handler(WINDOW win, EVENT* ep);
 | 
						|
  
 | 
						|
public:
 | 
						|
  TPreview_mask(TBook* book);
 | 
						|
};
 | 
						|
 | 
						|
bool TPreview_mask::on_key(KEY k)
 | 
						|
{
 | 
						|
  switch (k)
 | 
						|
  {
 | 
						|
  case '+'    :
 | 
						|
  case '-'    :
 | 
						|
  case K_HOME : 
 | 
						|
  case K_LHOME: 
 | 
						|
  case K_LEFT : 
 | 
						|
  case K_RIGHT:
 | 
						|
  case K_END  :
 | 
						|
  case K_LEND :
 | 
						|
  case K_PREV : 
 | 
						|
  case K_NEXT : 
 | 
						|
  case 'G'    :
 | 
						|
  case 'g'    :
 | 
						|
    if (_pvf != NULL)
 | 
						|
      return _pvf->win().on_key(k);
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return TAutomask::on_key(k);
 | 
						|
}
 | 
						|
 | 
						|
void TPreview_mask::handler(WINDOW win, EVENT* ep)
 | 
						|
{
 | 
						|
  // Riflessione eventi di scroll
 | 
						|
  switch (ep->type)
 | 
						|
  {
 | 
						|
  case E_HSCROLL:
 | 
						|
  case E_VSCROLL:
 | 
						|
    if (_pvf != NULL)
 | 
						|
      ::dispatch_event(_pvf->win().win(), *ep, false);
 | 
						|
    break;
 | 
						|
  case E_SIZE:
 | 
						|
    if (_pvf != NULL)
 | 
						|
    {
 | 
						|
      TPrint_preview_window& ppw = (TPrint_preview_window&)_pvf->win();
 | 
						|
      xvt_vobj_maximize(ppw.win());
 | 
						|
      ppw.update_scroll_range();
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    TAutomask::handler(win, ep);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TPreview_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | 
						|
{
 | 
						|
  if (e == fe_button)
 | 
						|
  {
 | 
						|
    short idm = 0;
 | 
						|
    switch (o.dlg()) 
 | 
						|
    {
 | 
						|
    case DLG_FIRSTREC: idm = POPUP_FIRST;  break;
 | 
						|
    case DLG_PREVREC : idm = POPUP_PREV;   break;
 | 
						|
    case DLG_FINDREC : idm = POPUP_SEARCH; break;
 | 
						|
    case DLG_NEXTREC : idm = POPUP_NEXT;   break;
 | 
						|
    case DLG_LASTREC : idm = POPUP_LAST;   break;
 | 
						|
    default: break;
 | 
						|
    }
 | 
						|
    if (idm > 0 && _pvf != NULL)
 | 
						|
      dispatch_e_menu(_pvf->win().win(), idm);
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
TMask_field* TPreview_mask::parse_field(TScanner& scanner)
 | 
						|
{
 | 
						|
  if (scanner.token().starts_with("PR"))
 | 
						|
  {
 | 
						|
    _pvf = new TPrint_preview_field(this, _book);
 | 
						|
    return _pvf;
 | 
						|
  }
 | 
						|
  return TAutomask::parse_field(scanner);
 | 
						|
}
 | 
						|
 | 
						|
TPreview_mask::TPreview_mask(TBook* book) : _book(book), _pvf(NULL)
 | 
						|
{
 | 
						|
  read_mask("bagn008", 0, -1);
 | 
						|
  set_handlers();
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TWindow_printer
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TWindow_printer : public TWindow
 | 
						|
{
 | 
						|
  long _pvr, _phr;
 | 
						|
	long _ph, _pw;
 | 
						|
 | 
						|
protected:
 | 
						|
  bool is_ok() const { return win() != NULL_WIN; }
 | 
						|
  virtual PNT log2dev(long x, long y) const;
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
  bool print_doc(const TFilename& name);
 | 
						|
 | 
						|
  TWindow_printer(PRINT_RCD* rcd, const char* title);
 | 
						|
 | 
						|
  ~TWindow_printer();
 | 
						|
};
 | 
						|
 | 
						|
PNT TWindow_printer::log2dev(long x, long y) const
 | 
						|
{
 | 
						|
  PNT ptdev;
 | 
						|
  ptdev.h = short((x * _phr) / BOOKDPI);
 | 
						|
  ptdev.v = short((y * _pvr) / BOOKDPI);
 | 
						|
#ifdef DBG
 | 
						|
	if(ptdev.h < 0 || ptdev.h >= _pw)
 | 
						|
		xvtil_statbar_set("Coordinata X errata");
 | 
						|
	if(ptdev.v < 0 || ptdev.v >= _ph)
 | 
						|
		xvtil_statbar_set("Coordinata Y errata");
 | 
						|
#endif
 | 
						|
  return ptdev;
 | 
						|
}
 | 
						|
 | 
						|
bool TWindow_printer::print_doc(const TFilename& name)
 | 
						|
{
 | 
						|
  bool ok = name.exist();
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    const bool printing = is_ok();
 | 
						|
    if (printing)
 | 
						|
      xvt_print_suspend_thread();
 | 
						|
    ok = xvt_sys_goto_url(name, "print") != 0;
 | 
						|
    if (printing)
 | 
						|
      xvt_print_restart_thread();
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
TWindow_printer::TWindow_printer(PRINT_RCD* rcd, const char* title)
 | 
						|
{ 
 | 
						|
  WINDOW prwin = xvt_print_create_win(rcd, title);
 | 
						|
 | 
						|
  set_win(prwin);
 | 
						|
  _pixmap = true;
 | 
						|
  xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, rcd, &_ph, &_pw, &_pvr, &_phr);
 | 
						|
}
 | 
						|
 | 
						|
TWindow_printer::~TWindow_printer()
 | 
						|
{
 | 
						|
  if (is_ok())
 | 
						|
  {
 | 
						|
    xvt_vobj_destroy(win()); 
 | 
						|
    set_win(NULL_WIN);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Writing a page
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// Converte da coordinate logiche (1/100 caratteri) a coordinate di stampa 
 | 
						|
TPoint TBook::log2dev(const TPoint& ptlog) const
 | 
						|
{
 | 
						|
  TPoint ptdev;
 | 
						|
  ptdev.x = (ptlog.x * _phr) / (100 * cpi());
 | 
						|
  ptdev.y = (ptlog.y * _pvr) / (100 * lpi());
 | 
						|
	return ptdev;
 | 
						|
}
 | 
						|
 | 
						|
PNT TBook::log2pix(const TPoint& ptlog) const
 | 
						|
{
 | 
						|
  TPoint ptdev = log2dev(ptlog);
 | 
						|
	return _printwin->log2dev(ptdev.x, ptdev.y);
 | 
						|
}
 | 
						|
 | 
						|
int TBook::compute_text_frame(const TString& tmp, const TReport_font& font, TRectangle& rect, TString_array& para) const
 | 
						|
{
 | 
						|
  // Calcola la larghezza massima e l'altezza di 10 righe
 | 
						|
  const TRectangle rect_riga(0,0,rect.width(),1000);
 | 
						|
  const PNT size = log2pix(rect_riga.size());
 | 
						|
  const int max_row_width = size.h;
 | 
						|
  const int def_10row_height = size.v;
 | 
						|
 | 
						|
  WINDOW w = _printwin->win();
 | 
						|
  CHECK(w == PRINTER_WIN, "Finestra di stampa non valida");
 | 
						|
  xvt_dwin_set_font(w, font.get_xvt_font(*_printwin));
 | 
						|
  int leading, ascent, descent;
 | 
						|
  xvt_dwin_get_font_metrics(w, &leading, &ascent, &descent);
 | 
						|
  int ky10 = (leading + ascent + descent) * 10;
 | 
						|
  // Aggiusta l'altezza di 10 righe standard, se necessario
 | 
						|
  if (ky10 < def_10row_height && ky10 > 75*def_10row_height/100)
 | 
						|
    ky10 = def_10row_height;
 | 
						|
 | 
						|
  TToken_string p(tmp, '\n');
 | 
						|
  FOR_EACH_TOKEN(p, line)
 | 
						|
    para.add(line);
 | 
						|
  for (int i = 0; i < para.items(); i++)
 | 
						|
  {
 | 
						|
    TString& row = para.row(i);
 | 
						|
    int pix = xvt_dwin_get_text_width(w, row, -1);
 | 
						|
    if (pix > max_row_width)
 | 
						|
    {
 | 
						|
      int good_len = 0;
 | 
						|
      const int first_space = row.find(' ');
 | 
						|
      if (first_space >= 0)
 | 
						|
      {
 | 
						|
        // Linea con almeno uno spazio
 | 
						|
        for (int i = first_space; row[i]; i++) if (row[i] == ' ')
 | 
						|
        {
 | 
						|
          pix = xvt_dwin_get_text_width(w, row, i); 
 | 
						|
          if (pix <= max_row_width)
 | 
						|
            good_len = i;
 | 
						|
          else
 | 
						|
            break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (good_len == 0) // Puo' succedere per linee senza spazi o con parole lunghissime
 | 
						|
      {     
 | 
						|
        for (good_len = row.len() * max_row_width / w + 1; good_len > 0; good_len--)
 | 
						|
        {
 | 
						|
          const int pix = xvt_dwin_get_text_width(w, row, good_len); 
 | 
						|
          if (pix < max_row_width)
 | 
						|
            break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      TString next_row = row.mid(good_len);
 | 
						|
      next_row.ltrim();
 | 
						|
      para.insert(next_row, i+1);
 | 
						|
      row.cut(good_len);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  int h = para.items() * ky10 * 100 / def_10row_height;
 | 
						|
  const int resto = h % 100;
 | 
						|
  if (resto != 0)
 | 
						|
    h += 100-resto;
 | 
						|
  rect.set_height(h);
 | 
						|
 | 
						|
  return ky10;
 | 
						|
}
 | 
						|
 | 
						|
TPoint TBook::page_size() const
 | 
						|
{
 | 
						|
  if (_pw <= 0 || _ph <= 0) // Valori nulli: mi invento un A4
 | 
						|
  {
 | 
						|
    TPoint pag = page_res();
 | 
						|
    pag.x *= 8; pag.y *= 11;
 | 
						|
    return pag;
 | 
						|
  }
 | 
						|
  return TPoint(_pw, _ph);
 | 
						|
}
 | 
						|
 | 
						|
TPoint TBook::page_res() const
 | 
						|
{
 | 
						|
  const int resx = _phr > 0 ? _phr : 96;
 | 
						|
  const int resy = _pvr > 0 ? _pvr : 96;
 | 
						|
  return TPoint(resx, resy);
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::open_page()
 | 
						|
{
 | 
						|
  if (_out == NULL)  // Sto per scrivere la prima pagina
 | 
						|
  {
 | 
						|
    _out = new ofstream(_file);
 | 
						|
    _max_frame.x = _max_frame.y = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  _page++;
 | 
						|
  _index.add_long(_out->tellp(), page()); // Scrive alla posizione 1 l'inizio di pagina 1
 | 
						|
 
 | 
						|
  *_out << "<page number=" << page() << '>' << endl;
 | 
						|
 | 
						|
  memset(&_tools, 0, sizeof(_tools));
 | 
						|
  _font.create("", 12, XVT_FA_ALL);
 | 
						|
  _horizontal_alignment = 'L';
 | 
						|
  _vertical_alignment = 'T';
 | 
						|
  _rect.set(-1,-1,0,0);
 | 
						|
 | 
						|
  _print_aborted = false;
 | 
						|
  _page_is_open = true;
 | 
						|
  return _page_is_open;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::close_page()
 | 
						|
{
 | 
						|
  if (!_page_is_open)
 | 
						|
    return false;
 | 
						|
 | 
						|
  *_out << "</page number=" << page() << '>' << endl;
 | 
						|
 | 
						|
  _pages++;
 | 
						|
  _page_is_open = false;
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_font(const TReport_font& f)
 | 
						|
{
 | 
						|
  if (f != _font)
 | 
						|
  {
 | 
						|
    _font = f;
 | 
						|
    *_out << "<font"
 | 
						|
          << " name=\"" << f.name() << '"'
 | 
						|
          << " size=" << f.size()
 | 
						|
          << " style=" << f.style() 
 | 
						|
          << " />" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::define_frame(const TRectangle& rect)
 | 
						|
{
 | 
						|
  if (rect != _rect)
 | 
						|
  {
 | 
						|
    _rect = rect;
 | 
						|
    *_out << "<frame"
 | 
						|
          << " x=" << _rect.x << " y=" << _rect.y
 | 
						|
          << " dx=" << _rect.width() << " dy=" << _rect.height()
 | 
						|
          << " />" << endl;
 | 
						|
 | 
						|
    // Ignora campi malamente copia/incollati a coordinate negative!
 | 
						|
    if (_rect.x > 0 && _rect.y > 0) 
 | 
						|
    {
 | 
						|
      if (_rect.right() > _max_frame.x)
 | 
						|
        _max_frame.x = _rect.right();
 | 
						|
      if (_rect.bottom() > _max_frame.y)
 | 
						|
        _max_frame.y = _rect.bottom();
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_clip(long top, long bottom)
 | 
						|
{
 | 
						|
  if (bottom >= top)
 | 
						|
  {
 | 
						|
    const TRectangle rect(0, top, logical_page_width(), bottom-top);
 | 
						|
    define_frame(rect);
 | 
						|
    *_out << "<clip>" << endl;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    *_out << "</clip>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_text(const TRectangle& r, const char* txt)
 | 
						|
{
 | 
						|
  if (txt && *txt)
 | 
						|
  {
 | 
						|
    const TFixed_string str(txt);
 | 
						|
    if (str.full())
 | 
						|
    {
 | 
						|
      define_frame(r);
 | 
						|
      *_out << "<text>" << endl << str << endl << "</text>" << endl;
 | 
						|
    }
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_text(const TRectangle& r, const TString_array& txt)
 | 
						|
{
 | 
						|
  if (!txt.empty())
 | 
						|
  {
 | 
						|
    define_frame(r);
 | 
						|
    *_out << "<text>" << endl;
 | 
						|
    for (int i = 0; i < txt.items(); i++)
 | 
						|
    {
 | 
						|
      const char* line = txt.row(i);
 | 
						|
      *_out << line << endl; 
 | 
						|
    }
 | 
						|
    *_out << "</text>" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_book_pages(const TRectangle& r)
 | 
						|
{
 | 
						|
  define_frame(r);
 | 
						|
  *_out << "<pages/>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_pen(COLOR color, int width, PEN_STYLE style)
 | 
						|
{
 | 
						|
  if (_tools.pen.color != color || _tools.pen.width != width || _tools.pen.style != style)
 | 
						|
  {
 | 
						|
    _tools.pen.color = color;
 | 
						|
    _tools.pen.width = width;
 | 
						|
    _tools.pen.style = style;
 | 
						|
    *_out << "<pen color=" << color 
 | 
						|
          << " width=" << width 
 | 
						|
          << " style=" << style << " />" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_brush(COLOR color, PAT_STYLE pattern)
 | 
						|
{
 | 
						|
  if (_tools.brush.color != color || _tools.brush.pat != pattern)
 | 
						|
  {
 | 
						|
    _tools.brush.color = color;
 | 
						|
    _tools.brush.pat = pattern;
 | 
						|
    *_out << "<brush color=" << color << " pattern=" << pattern << " />" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_text_color(COLOR fore, COLOR back, bool opaque)
 | 
						|
{
 | 
						|
  if (_tools.fore_color != fore || _tools.back_color != back || _tools.opaque_text != short(opaque))
 | 
						|
  {
 | 
						|
    _tools.fore_color = fore;
 | 
						|
    _tools.back_color = back;
 | 
						|
    _tools.opaque_text = opaque;
 | 
						|
    *_out << "<text_color fore=" << fore 
 | 
						|
          << " back=" << back 
 | 
						|
          << " opaque=" << opaque << " />" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TBook::set_text_align(char halign, char valign)
 | 
						|
{
 | 
						|
  if (_horizontal_alignment != halign || _vertical_alignment != valign)
 | 
						|
  {
 | 
						|
    _horizontal_alignment = halign;
 | 
						|
    _vertical_alignment = valign;
 | 
						|
    *_out << "<text_align horizontal=" << halign << " vertical=" << valign << " />" << endl;
 | 
						|
  }
 | 
						|
}
 | 
						|
 
 | 
						|
void TBook::draw_rectangle(const TRectangle& r)
 | 
						|
{
 | 
						|
  define_frame(r);
 | 
						|
  *_out << "<rectangle/>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_round_rectangle(const TRectangle& r, int radius)
 | 
						|
{
 | 
						|
  define_frame(r);
 | 
						|
  *_out << "<rounded_rectangle radius=" << radius << " />" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_ellipse(const TRectangle& r)
 | 
						|
{
 | 
						|
  define_frame(r);
 | 
						|
  *_out << "<ellipse/>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_line(const TRectangle& r)
 | 
						|
{
 | 
						|
  define_frame(r);
 | 
						|
  *_out << "<line/>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_link(const TRectangle& rect, const char* text, const char* link)
 | 
						|
{
 | 
						|
  define_frame(rect);
 | 
						|
  *_out << "<a href=\"" << link << "\" >" << text << "</a>" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::draw_image(const TRectangle& rect, const char* name)
 | 
						|
{
 | 
						|
  define_frame(rect);
 | 
						|
  *_out << "<image src=\"" << name << "\" />" << endl;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::add_doc(const TString& name)
 | 
						|
{
 | 
						|
  if (name.full())
 | 
						|
  {
 | 
						|
    TBook::open_page();
 | 
						|
    *_out << "<doc url=\"" << name << "\" />"<< endl;
 | 
						|
    TBook::close_page();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Reading a page
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool get_xml_string(const TString& line, const char* attr, TString& value)
 | 
						|
{
 | 
						|
  TString80 str; str << ' ' << attr << '=';
 | 
						|
  const int pos = line.find(str);
 | 
						|
  if (pos >= 0)
 | 
						|
  {
 | 
						|
    const int apicia = pos + strlen(attr) + 2;
 | 
						|
    if (line[apicia] == '"')
 | 
						|
    {
 | 
						|
      const int apicic = line.find('"', apicia+1);
 | 
						|
      if (apicic > apicia)
 | 
						|
      {
 | 
						|
        value = line.sub(apicia+1, apicic);
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      const int space = line.find(' ', apicia);
 | 
						|
      if (space > 0)
 | 
						|
      {
 | 
						|
        value = line.sub(apicia, space);
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
int get_xml_int(const TString& line, const char* attr, int def)
 | 
						|
{
 | 
						|
  TString16 str;
 | 
						|
  if (get_xml_string(line, attr, str))
 | 
						|
    def = atoi(str);
 | 
						|
  return def;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::print_doc(TWindow& win, const TFilename& name)
 | 
						|
{
 | 
						|
  const bool print = win.win() == 883;
 | 
						|
 | 
						|
  if (print)
 | 
						|
  {
 | 
						|
    TWindow_printer& wp = (TWindow_printer&)win;
 | 
						|
    wp.print_doc(name);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    TPoint ps = page_size();
 | 
						|
    TRectangle rect(TPoint(0,0), ps);
 | 
						|
    RCT page; win.log2dev(rect, page);
 | 
						|
    advanced_draw_text_line(win.win(), name, page, 'C', 'T');
 | 
						|
 | 
						|
    TString8 ext = name.ext(); ext.lower();
 | 
						|
    if (ext == "bmp" || ext == "gif" || ext == "jpg" || ext == "jpeg" || ext == "png")
 | 
						|
    {
 | 
						|
      const TImage* img = _images.image(name);
 | 
						|
      if (img != NULL)
 | 
						|
      {
 | 
						|
        const TPoint pr = page_res();
 | 
						|
        rect.deflate(pr.x/2, pr.y/2);
 | 
						|
        win.log2dev(rect, page);
 | 
						|
 | 
						|
        const double sx = double(page.right) / double(img->width());
 | 
						|
        const double sy = double(page.bottom) / double(img->height());
 | 
						|
        const double s = sx < sy ? sx : sy;
 | 
						|
        const int w = int(s * img->width());
 | 
						|
        const int h = int(s * img->height());
 | 
						|
        RCT rct; 
 | 
						|
        rct.left = (page.right+page.left-w)/2; rct.right = rct.left + w;
 | 
						|
        rct.top  = (page.bottom+page.top-h)/2; rct.bottom = rct.top + h;
 | 
						|
        img->draw(win.win(), rct);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TBook::print_page(TWindow& win, size_t page)
 | 
						|
{
 | 
						|
  if (page <= 0 || page > pages()) 
 | 
						|
    return false;
 | 
						|
 | 
						|
  WINDOW w = win.win();
 | 
						|
  const bool preview = w != PRINTER_WIN;
 | 
						|
  RCT visible;
 | 
						|
  if (preview)
 | 
						|
  {
 | 
						|
    xvt_vobj_get_client_rect(w, &visible);
 | 
						|
    TPrint_preview_window& pw = (TPrint_preview_window&)win;
 | 
						|
    pw.alinks().destroy();
 | 
						|
  }
 | 
						|
 
 | 
						|
  TToken_string str(1024, '=');
 | 
						|
 | 
						|
  TString_array paragrafo; // Testo completo di un campo
 | 
						|
 | 
						|
  // Calcolo altezza riga standard
 | 
						|
  const TRectangle rect_riga(0,0,1000,1000);
 | 
						|
  RCT rct_riga; win.log2dev(rect_riga, rct_riga);
 | 
						|
  const int default_10row_height = rct_riga.bottom - rct_riga.top;
 | 
						|
 | 
						|
  const streampos pos = _index.get_long(page);
 | 
						|
  ifstream ifs(_file);
 | 
						|
  ifs.seekg(pos);
 | 
						|
 | 
						|
  _rect.set(-1,-1,0,0); // Reset frame
 | 
						|
  RCT rct = { 0,0,0,0 };
 | 
						|
 | 
						|
  _horizontal_alignment = 'L'; // Reset text alignment
 | 
						|
  _vertical_alignment = 'T';
 | 
						|
 | 
						|
  bool page_is_open = false; // Stato attuale della pagina della stampante
 | 
						|
  
 | 
						|
  while (!ifs.eof())
 | 
						|
  {
 | 
						|
    ifs.getline(str.get_buffer(), str.size());
 | 
						|
    if (str.starts_with("</page"))
 | 
						|
      break;
 | 
						|
 | 
						|
    if (str.starts_with("<page "))
 | 
						|
    {
 | 
						|
      // Non apro ora la pagina sulla stampante perche' potrei incontrare un allegato
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (str.starts_with("<doc")) // Stampa il documento allegato senza aprire la pagina su carta
 | 
						|
    {
 | 
						|
      TFilename name; get_xml_string(str, "url", name);
 | 
						|
      print_doc(win, name);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Per i comandi successivi serve una pagina aperta!
 | 
						|
    if (!page_is_open && !preview)
 | 
						|
    {
 | 
						|
      page_is_open = xvt_print_open_page(_rcd) != 0;
 | 
						|
      if (!page_is_open) 
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    if (str.starts_with("<a "))
 | 
						|
    {
 | 
						|
      if (preview && rct.bottom >= visible.top && rct.top <= visible.bottom)
 | 
						|
      {
 | 
						|
        TString link;
 | 
						|
        if (get_xml_string(str, "href", link))
 | 
						|
        {
 | 
						|
          TPrint_preview_window& pw = (TPrint_preview_window&)win;
 | 
						|
          TAssoc_array& links = pw.alinks();
 | 
						|
 | 
						|
          TToken_string tok(link, '.');
 | 
						|
          TString80 table, field, key;
 | 
						|
          tok.get(0, table); tok.get(1, field);
 | 
						|
 | 
						|
          key << table << ',' << _rect.y;
 | 
						|
          TReport_link* rl = (TReport_link*)links.objptr(key);
 | 
						|
          if (rl == NULL)
 | 
						|
          {
 | 
						|
            rl = new TReport_link(table);
 | 
						|
            links.add(key, rl);
 | 
						|
          }
 | 
						|
 | 
						|
          const int inizio = str.find('>')+1;
 | 
						|
          const int fine = str.rfind('<');
 | 
						|
          const TString& stringona = str.sub(inizio, fine);
 | 
						|
          rl->set(field, stringona);
 | 
						|
          rl->add_rect(rct);
 | 
						|
 | 
						|
          if (stringona.full() && rct.right > rct.left) // Possono esserci campi chiave nascosti
 | 
						|
          {
 | 
						|
            DRAW_CTOOLS dct;
 | 
						|
            xvt_dwin_get_draw_ctools(w, &dct);
 | 
						|
 | 
						|
            XVT_FNTID oldfont = xvt_dwin_get_font(w);
 | 
						|
            XVT_FNTID newfont = xvt_font_create();
 | 
						|
            xvt_font_copy(newfont, oldfont, XVT_FA_ALL);
 | 
						|
            xvt_font_set_style(newfont, xvt_font_get_style(oldfont) | XVT_FS_UNDERLINE);
 | 
						|
            xvt_dwin_set_font(w, newfont);
 | 
						|
            win.set_color(COLOR_BLUE, dct.back_color);
 | 
						|
            advanced_draw_text_line(w, stringona, rct, _horizontal_alignment, _vertical_alignment);
 | 
						|
            win.set_color(dct.fore_color, dct.back_color);
 | 
						|
            xvt_dwin_set_font(w, oldfont);
 | 
						|
            xvt_font_destroy(oldfont);
 | 
						|
            xvt_font_destroy(newfont);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<brush "))
 | 
						|
    {
 | 
						|
      // <brush color=%u pattern=%u />
 | 
						|
      COLOR col = str.get_long(1); 
 | 
						|
      PAT_STYLE pat = (PAT_STYLE)str.get_long();
 | 
						|
      if (pat <= PAT_HOLLOW)
 | 
						|
        win.hide_brush();
 | 
						|
      else
 | 
						|
        win.set_brush(col, pat);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<clip"))
 | 
						|
    {
 | 
						|
      xvt_dwin_set_clip(w, &rct);
 | 
						|
    } else
 | 
						|
    if (str.starts_with("</clip"))
 | 
						|
    {
 | 
						|
      xvt_dwin_set_clip(w, NULL);
 | 
						|
    } else
 | 
						|
    if (str == "<ellipse/>")
 | 
						|
    {
 | 
						|
      xvt_dwin_draw_oval(w, &rct);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<frame "))
 | 
						|
    {
 | 
						|
      // <frame x=ld y=%ld dx=%ld dy=%ld />
 | 
						|
      const long x = str.get_long(1);
 | 
						|
      const long y = str.get_long(); 
 | 
						|
      const long dx= str.get_long(); 
 | 
						|
      const long dy= str.get_long(); 
 | 
						|
      _rect.set(x, y, dx, dy);
 | 
						|
      win.log2dev(_rect, rct);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<font "))
 | 
						|
    {
 | 
						|
      TString80 name = DEFAULT_FONT_NAME; get_xml_string(str, "name", name);
 | 
						|
      const int size = get_xml_int(str, "size", 12);
 | 
						|
      const XVT_FONT_STYLE_MASK style = get_xml_int(str, "style", 0);
 | 
						|
      TReport_font font; font.create(name, size, style);
 | 
						|
      if (preview)
 | 
						|
        xvt_dwin_set_font(w, font.get_preview_font(win, page_res()));
 | 
						|
      else
 | 
						|
        xvt_dwin_set_font(w, font.get_xvt_font(win));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<image "))
 | 
						|
    {
 | 
						|
      TFilename name; get_xml_string(str, "src", name);
 | 
						|
      TImage* img = _images.image(name);
 | 
						|
      if (img != NULL)
 | 
						|
      {
 | 
						|
        if (is_pdf())
 | 
						|
        {
 | 
						|
          name.custom_path();
 | 
						|
          xvt_dwin_draw_image_on_pdf(w, name, &rct);
 | 
						|
        }
 | 
						|
        else
 | 
						|
          img->draw(w, rct);
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str == "<line/>")
 | 
						|
    {
 | 
						|
      const PNT fr = { rct.top, rct.left };
 | 
						|
      const PNT to = { rct.bottom, rct.right };
 | 
						|
      xvt_dwin_draw_set_pos(w, fr);
 | 
						|
      xvt_dwin_draw_line(w, to);
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str == "<pages/>")
 | 
						|
    {
 | 
						|
      TString8 str; str.format("%u", pages());
 | 
						|
      advanced_draw_text_line(w, str, rct, _horizontal_alignment, _vertical_alignment);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<pen "))
 | 
						|
    {
 | 
						|
      // <pen color=%u width=%d style=%u />
 | 
						|
      COLOR col = str.get_long(1); 
 | 
						|
      int width = str.get_int();
 | 
						|
      PEN_STYLE style = (PEN_STYLE)str.get_int();
 | 
						|
      if (width < 0)
 | 
						|
        win.hide_pen();
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (preview)
 | 
						|
          win.set_pen(col, width);
 | 
						|
        else
 | 
						|
          win.set_pen(col, width * _phr / 72); // Converte width in 72' di pollice
 | 
						|
      }
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str == "<rectangle/>")
 | 
						|
    {
 | 
						|
      xvt_dwin_draw_rect(w, &rct);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<rounded_rectangle"))
 | 
						|
    {
 | 
						|
      const int radius = get_xml_int(str, "radius", 0);
 | 
						|
      
 | 
						|
      const TRectangle rr(0,0,radius,radius);
 | 
						|
      RCT re; win.log2dev(rr, re);
 | 
						|
      const int rad = (re.right-re.left) * lpi() / (cpi() * 2);
 | 
						|
      xvt_dwin_draw_roundrect(w, &rct, rad, rad);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<text>"))
 | 
						|
    {
 | 
						|
      paragrafo.destroy();
 | 
						|
      while (!ifs.eof())
 | 
						|
      {
 | 
						|
        ifs.getline(str.get_buffer(), str.size());
 | 
						|
        if (str == "</text>")
 | 
						|
          break;
 | 
						|
        paragrafo.add(str);
 | 
						|
      }
 | 
						|
      advanced_draw_paragraph(win.win(), paragrafo, rct, 
 | 
						|
                              _horizontal_alignment, _vertical_alignment,
 | 
						|
                              default_10row_height);
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<text_align "))
 | 
						|
    {
 | 
						|
      // <text_align horizontal=%c vertical=%c />
 | 
						|
      _horizontal_alignment = str.get_char(1);
 | 
						|
      _vertical_alignment = str.get_char();
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (str.starts_with("<text_color"))
 | 
						|
    {
 | 
						|
      // <text_color fore=%u back=%u opaque=%d />
 | 
						|
      const COLOR fore = str.get_long(1);
 | 
						|
      const COLOR back = str.get_long();
 | 
						|
      const int opaque = str.get_int(); 
 | 
						|
      win.set_color(fore, back);
 | 
						|
      win.set_opaque_text(opaque != 0);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (preview)
 | 
						|
  {
 | 
						|
    TPrint_preview_window& pw = (TPrint_preview_window&)win;
 | 
						|
    TAssoc_array& alinks = pw.alinks();
 | 
						|
    TPointer_array& plinks = pw.plinks();   
 | 
						|
    plinks.destroy();
 | 
						|
    if (alinks.items() > 0)
 | 
						|
    {
 | 
						|
      FOR_EACH_ASSOC_OBJECT(alinks, h, key, l)
 | 
						|
        plinks.add((TReport_link*)l);
 | 
						|
      plinks.sort();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (page_is_open)
 | 
						|
      xvt_print_close_page(_rcd);
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::export_text(const TFilename& fname, bool signature)
 | 
						|
{
 | 
						|
  if (fname.ends_with(".pdf", true))
 | 
						|
    return export_pdf(fname, signature);
 | 
						|
 | 
						|
  TToken_string str(1024, '=');
 | 
						|
 | 
						|
  ifstream ifs(_file);
 | 
						|
  ofstream ofs(fname);
 | 
						|
 | 
						|
  TString_array page;
 | 
						|
  int row, col, wid, hei;
 | 
						|
 | 
						|
  const TPoint res = page_res();
 | 
						|
 | 
						|
  while (!ifs.eof())
 | 
						|
  {
 | 
						|
    ifs.getline(str.get_buffer(), str.size());
 | 
						|
 | 
						|
    if (str.starts_with("<frame "))
 | 
						|
    {
 | 
						|
      // <frame x=%ld y=%ld dx=%ld dy=%ld />
 | 
						|
      const long x = str.get_long(1);
 | 
						|
      const long y = str.get_long(); 
 | 
						|
      const long dx= str.get_long(); 
 | 
						|
      const long dy= str.get_long(); 
 | 
						|
      row = y * lpi() / res.y;
 | 
						|
      col = x * cpi() / res.x;
 | 
						|
      wid = dx * cpi() / res.x;
 | 
						|
      hei = dy * lpi() / res.y;
 | 
						|
    } else
 | 
						|
    if (str == "<line/>")
 | 
						|
    {
 | 
						|
      if (hei == 0 && wid > 0)
 | 
						|
      {
 | 
						|
        if (page.objptr(row) == NULL)
 | 
						|
          page.add("", row);
 | 
						|
        TString& line = page.row(row);
 | 
						|
        for (int i = 0; i < wid; i++)
 | 
						|
        {
 | 
						|
          const int j = i+col;
 | 
						|
          if (j >= line.len())
 | 
						|
            line.overwrite("-", j);
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (line[j] == '|')
 | 
						|
              line[j] = '+';
 | 
						|
            else
 | 
						|
            {
 | 
						|
              if (line[j] == ' ')
 | 
						|
                line[j] = '-';
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else
 | 
						|
      if (hei > 0 && wid == 0)
 | 
						|
      {
 | 
						|
        for (int i = row; i < row+hei; i++)
 | 
						|
        {
 | 
						|
          if (page.objptr(i) == NULL)
 | 
						|
            page.add("", i);
 | 
						|
          TString& line = page.row(i);
 | 
						|
          if (line.len() <= col)
 | 
						|
            line.overwrite("|", col);
 | 
						|
          else
 | 
						|
          {
 | 
						|
            if (line[col] == '-')
 | 
						|
              line[col] = '+';
 | 
						|
            else
 | 
						|
            {
 | 
						|
              if (line[col] == ' ')
 | 
						|
                line[col] = '|';
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (str.starts_with("<page "))
 | 
						|
    {
 | 
						|
      page.destroy();
 | 
						|
    } else
 | 
						|
    if (str.starts_with("</page "))
 | 
						|
    {
 | 
						|
      const int last_row = page.last();
 | 
						|
      for (int i = 0; i <= last_row; i++)
 | 
						|
      {
 | 
						|
        const TString* line = (const TString*)page.objptr(i);
 | 
						|
        if (line != NULL)
 | 
						|
          ofs << *line;
 | 
						|
        ofs << endl;
 | 
						|
      }
 | 
						|
    } else
 | 
						|
    if (str == "<pages/>")
 | 
						|
    {
 | 
						|
      TString8 str; str.format("%u", pages());
 | 
						|
      TString& line = page.row(row);
 | 
						|
      switch (_horizontal_alignment)
 | 
						|
      {
 | 
						|
      case 'C': line.overwrite(str, col+(wid-str.len())/2); break;
 | 
						|
      case 'R': line.overwrite(str, col+wid-str.len()); break;
 | 
						|
      default : line.overwrite(str, col); break;
 | 
						|
      }      
 | 
						|
    } else
 | 
						|
    if (str == "<text>")
 | 
						|
    {
 | 
						|
      TString stringona;
 | 
						|
      while (!ifs.eof())
 | 
						|
      {
 | 
						|
        ifs.getline(str.get_buffer(), str.size());
 | 
						|
        if (str == "</text>")
 | 
						|
          break;
 | 
						|
        stringona << str << '\n';
 | 
						|
      }
 | 
						|
      stringona.rtrim();
 | 
						|
      TParagraph_string para(stringona, wid);
 | 
						|
      for (int i = 0; i < hei && i < para.items(); i++)
 | 
						|
      {
 | 
						|
        const int j = row+i;
 | 
						|
        if (page.objptr(j) == NULL)
 | 
						|
          page.add("", j);
 | 
						|
        str = para.get();
 | 
						|
        TString& line = page.row(j);
 | 
						|
        switch (_horizontal_alignment)
 | 
						|
        {
 | 
						|
        case 'C': line.overwrite(str, col+(wid-str.len())/2); break;
 | 
						|
        case 'R': line.overwrite(str, col+wid-str.len()); break;
 | 
						|
        default : line.overwrite(str, col); break;
 | 
						|
        }      
 | 
						|
      }
 | 
						|
    } else
 | 
						|
    if (str.starts_with("<text_align "))
 | 
						|
    {
 | 
						|
      // <text_align horizontal=%c vertical=%c />
 | 
						|
      _horizontal_alignment = str.get_char(1);
 | 
						|
      _vertical_alignment = str.get_char();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::init()
 | 
						|
{
 | 
						|
  if (is_pdf())
 | 
						|
  {
 | 
						|
    int size;
 | 
						|
    _rcd = xvt_print_create_by_name(&size, XVT_PDF_PRINTER_NAME);
 | 
						|
  }
 | 
						|
  else
 | 
						|
    _rcd = printer().get_printrcd();
 | 
						|
 | 
						|
  if (!xvt_print_is_valid(_rcd))
 | 
						|
    return error_box(TR("Stampante non valida"));
 | 
						|
 | 
						|
  xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _rcd, &_ph, &_pw, &_pvr, &_phr);
 | 
						|
 | 
						|
  if (_pw <= 0 || _ph <= 0)
 | 
						|
    return error_box(TR("Dimensioni pagina NULLE"));
 | 
						|
  if (_pvr <= 0 || _phr <= 0)
 | 
						|
    return error_box(TR("Risoluzione stampante NULLA"));
 | 
						|
 | 
						|
  _ph = _ph * BOOKDPI / _pvr;
 | 
						|
  _pw = _pw * BOOKDPI / _phr;
 | 
						|
  _pvr = _phr = BOOKDPI;
 | 
						|
 | 
						|
  if (_printwin != NULL)
 | 
						|
    delete _printwin;
 | 
						|
  _printwin = new TWindow_printer(_rcd, _pdf_file);
 | 
						|
  
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TBook::split_file(int colonne)
 | 
						|
{
 | 
						|
  TProgind pi(pages(), TR("Rigenerazione pagine"), true, true);
 | 
						|
 | 
						|
  TFilename temp; temp.temp();
 | 
						|
  ofstream out(temp);
 | 
						|
  TPointer_array index;
 | 
						|
  
 | 
						|
  close_output();  // Chiudo file di stampa eventualmente aperto
 | 
						|
  ifstream ifs(_file); // Apro file di stampa da splittare
 | 
						|
 | 
						|
  TToken_string str(1024, '=');
 | 
						|
  for (unsigned int page = 1; page <= pages(); page++) 
 | 
						|
  {
 | 
						|
    if (!pi.setstatus(page))
 | 
						|
      break;
 | 
						|
    const streampos pos = _index.get_long(page);
 | 
						|
    for (int c = 0; c < colonne; c++)
 | 
						|
    {
 | 
						|
      const TRectangle rct_page(c*_pw, 0, _pw, _ph);
 | 
						|
      
 | 
						|
      ifs.seekg(pos);
 | 
						|
      while (!ifs.eof())
 | 
						|
      {
 | 
						|
        ifs.getline(str.get_buffer(), str.size());
 | 
						|
        
 | 
						|
        if (str.starts_with("<page "))
 | 
						|
        {
 | 
						|
          const int p = (page-1)*colonne+1+c;
 | 
						|
          index.add_long(out.tellp(), p);
 | 
						|
          str.format("<page number=%d>", p);
 | 
						|
        } else
 | 
						|
        if (str.starts_with("<frame "))
 | 
						|
        {
 | 
						|
          // <frame x=%ld y=%ld dx=%ld dy=%ld />
 | 
						|
          const long x = str.get_long(1);
 | 
						|
          const long y = str.get_long(); 
 | 
						|
          const long dx= str.get_long(); 
 | 
						|
          const long dy= str.get_long(); 
 | 
						|
          str.format("<frame x=%ld y=%ld dx=%ld dy=%ld />", x-rct_page.x, y, dx, dy);
 | 
						|
        } else
 | 
						|
        if (str.starts_with("</page "))
 | 
						|
        {
 | 
						|
          str.format("</page number=%d>", index.last());
 | 
						|
        }
 | 
						|
 | 
						|
        out << str << endl;
 | 
						|
        if (str.starts_with("</page "))
 | 
						|
          break;
 | 
						|
      } 
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  out.close();
 | 
						|
  
 | 
						|
  // Sostituisce il file di stampa con quello splittato ed aggiorna l'indice delle pagine
 | 
						|
  fcopy(temp, _file);
 | 
						|
  xvt_fsys_remove_file(temp);
 | 
						|
  _index = index;
 | 
						|
  _pages = _index.last();
 | 
						|
}
 | 
						|
 | 
						|
void TBook::close_output()
 | 
						|
{
 | 
						|
  if (_out != NULL)
 | 
						|
  {
 | 
						|
    _out->close();
 | 
						|
    delete _out;
 | 
						|
  }
 | 
						|
  _out = NULL;
 | 
						|
}
 | 
						|
 | 
						|
void TBook::join_file(int pps)
 | 
						|
{
 | 
						|
  TProgind pi(pages(), TR("Rigenerazione pagine"), true, true);
 | 
						|
 | 
						|
  TFilename temp; temp.temp();
 | 
						|
  ofstream out(temp);
 | 
						|
  
 | 
						|
  close_output();      // Chiudo file di stampa eventualmente aperto
 | 
						|
  ifstream ifs(_file); // Apro file di stampa da splittare
 | 
						|
 | 
						|
  _index.destroy();    // Distruggo il vecchio indice delle pagine che poi ricostruisco
 | 
						|
  _pages = (_pages - 1) / pps + 1;  // Ricalcolo in nuovo numero di pagine totali
 | 
						|
 | 
						|
  int in_page = 1;
 | 
						|
  int out_page = 0;
 | 
						|
  int off_page = 0;
 | 
						|
 | 
						|
  TToken_string str(1024, '=');
 | 
						|
  while (!ifs.eof())
 | 
						|
  {
 | 
						|
    ifs.getline(str.get_buffer(), str.size());
 | 
						|
    
 | 
						|
    if (str.starts_with("<page "))
 | 
						|
    {
 | 
						|
      // <page number=%d />
 | 
						|
      in_page = str.get_int(1);
 | 
						|
      const int sub = ((in_page - 1) % pps);
 | 
						|
      off_page = sub * logical_page_height() / pps;
 | 
						|
      if (sub == 0)
 | 
						|
      {
 | 
						|
        out_page = (in_page - 1) / pps + 1;
 | 
						|
        _index.add_long(out.tellp(), out_page);
 | 
						|
        str.format("<page number=%d>", out_page);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        // E' utile resettare l'allineamento dei testi :-)
 | 
						|
        str = "<text_align horizontal=L vertical=T />";
 | 
						|
      }
 | 
						|
    } else
 | 
						|
    if (str.starts_with("<frame ") && off_page > 0)
 | 
						|
    {
 | 
						|
      // <frame x=ld y=%ld dx=%ld dy=%ld />
 | 
						|
      const long x = str.get_long(1);
 | 
						|
      const long y = str.get_long(); 
 | 
						|
      const long dx= str.get_long(); 
 | 
						|
      const long dy= str.get_long(); 
 | 
						|
      str.format("<frame x=%ld y=%ld dx=%ld dy=%ld />", x, y+off_page, dx, dy);
 | 
						|
    } else
 | 
						|
    if (str.starts_with("</page "))
 | 
						|
    {
 | 
						|
      if (out_page % pps == 0)
 | 
						|
      {
 | 
						|
        str.format("</page number=%d>", out_page);
 | 
						|
        out_page = 0;
 | 
						|
      }
 | 
						|
      else 
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
    out << str << endl;
 | 
						|
  } 
 | 
						|
 | 
						|
  if (out_page != 0) // Non ho ancora scritto l'ultimo fine pagina
 | 
						|
  {
 | 
						|
    str.format("</page number=%d>", out_page);
 | 
						|
    out << str << endl;
 | 
						|
  }
 | 
						|
 | 
						|
  out.close();
 | 
						|
  
 | 
						|
  // Sostituisce il file di stampa con quello joinato
 | 
						|
  fcopy(temp, _file);
 | 
						|
  xvt_fsys_remove_file(temp);
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::can_split(int pages) const
 | 
						|
{
 | 
						|
  return yesno_box(FR("Si desidera suddividere le pagine su %d fogli"), pages);
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::can_merge(int pages) const
 | 
						|
{
 | 
						|
  return yesno_box(FR("Si desidera raggruppare %d pagine per foglio"), pages);
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::split_file_if_needed()
 | 
						|
{
 | 
						|
  if (_max_frame.x > 100 && _max_frame.y > 100) // Evita calcolo splitting se possibile
 | 
						|
  {
 | 
						|
 | 
						|
    const TPoint sheet(_pw, _ph);  
 | 
						|
  
 | 
						|
    const int spp = _max_frame.x > sheet.x ? (_max_frame.x+sheet.x-1) / sheet.x : 1;
 | 
						|
    if (spp > 1 && can_split(spp))  // Sheets per page
 | 
						|
    {
 | 
						|
      split_file(spp);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      const int pps = (_max_frame.y > 100 && pages() > 1) ? sheet.y / _max_frame.y : 1;
 | 
						|
      if (pps > 1 && can_merge(pps))
 | 
						|
        join_file(pps);
 | 
						|
    }
 | 
						|
    _max_frame.x = _max_frame.y = 0; // Impedisce ulteriore splitting
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::main_loop()
 | 
						|
{
 | 
						|
  _print_aborted = true;
 | 
						|
  if (!init())
 | 
						|
    return false;
 | 
						|
 | 
						|
  if (_pageto < _pagefrom)
 | 
						|
    _pageto = pages();
 | 
						|
 | 
						|
  _print_aborted = false;
 | 
						|
  for (word copy = 0; copy < _copies && !_print_aborted; copy++)
 | 
						|
  {
 | 
						|
    for (size_t page = _pagefrom; page <= _pageto && !_print_aborted; page++)
 | 
						|
    {
 | 
						|
      if (!print_page( *_printwin, page))
 | 
						|
        _print_aborted = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (is_pdf())
 | 
						|
  {
 | 
						|
    xvt_print_destroy(_rcd);
 | 
						|
    _rcd = NULL;
 | 
						|
		_pdf_file.cut(0);
 | 
						|
  }
 | 
						|
 | 
						|
  return !_print_aborted;
 | 
						|
}
 | 
						|
 | 
						|
static BOOLEAN main_loop_callback(long jolly)
 | 
						|
{
 | 
						|
  TBook* pp = (TBook*)jolly;
 | 
						|
  return pp->main_loop();
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::print(size_t pagefrom, size_t pageto, word copies)
 | 
						|
{
 | 
						|
  if (pages() <= 0)
 | 
						|
    return false;
 | 
						|
 | 
						|
  if (pagefrom == 0)
 | 
						|
  {
 | 
						|
    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, 1);
 | 
						|
    msk.set(F_TOPAGE, pages());
 | 
						|
    msk.set(F_COPIES, 1);
 | 
						|
    if (msk.run() == K_ENTER)
 | 
						|
    {
 | 
						|
      _copies = msk.get_int(F_COPIES);
 | 
						|
      _pagefrom = msk.get_int(F_FROMPAGE);
 | 
						|
      _pageto = msk.get_int(F_TOPAGE);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    _pagefrom = pagefrom;
 | 
						|
    _pageto = pageto;
 | 
						|
    _copies = copies;
 | 
						|
  }
 | 
						|
 | 
						|
  _pdf_file.cut(0);
 | 
						|
  return xvt_print_start_thread(main_loop_callback, (long)this) != 0;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::export_pdf(const TFilename& filename, bool certified)
 | 
						|
{
 | 
						|
  bool ok = (pages() > 0) && dongle().active(RSAUT);
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    _pdf_file = filename;
 | 
						|
    _pagefrom = 1;
 | 
						|
    _pageto = 0;
 | 
						|
    _copies = 1;
 | 
						|
    ok = xvt_print_start_thread(main_loop_callback, (long)this) != 0;
 | 
						|
    if (ok && certified)
 | 
						|
    {
 | 
						|
      if (!xvt_pdf_sign(filename))
 | 
						|
        error_box(TR("Impossibile apporre la firma digitale al documento"));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::esporta()
 | 
						|
{
 | 
						|
  if (pages() <= 0)
 | 
						|
    return false;
 | 
						|
 | 
						|
  split_file_if_needed();
 | 
						|
 | 
						|
	TFilename fname;
 | 
						|
	const KEY key = spotlite_ask_name(fname);
 | 
						|
  bool ok = isalpha(key) != 0;
 | 
						|
  const bool signature = key >= 'a';
 | 
						|
  switch (key)
 | 
						|
  {
 | 
						|
  case 'A': 
 | 
						|
  case 'a': 
 | 
						|
    ok = archive(NULL, signature); 
 | 
						|
    break;
 | 
						|
  case 'E': 
 | 
						|
  case 'e': 
 | 
						|
    ok = export_text(fname, signature); 
 | 
						|
    if (ok)
 | 
						|
      xvt_sys_goto_url(fname, "open");
 | 
						|
    break;
 | 
						|
  case 'M':
 | 
						|
  case 'm':
 | 
						|
    ok = send_mail(fname, signature);
 | 
						|
    break;
 | 
						|
  case 'P': 
 | 
						|
  case 'p': 
 | 
						|
    ok = export_pdf(fname, signature); 
 | 
						|
    if (ok)
 | 
						|
      xvt_sys_goto_url(fname, "open");
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::archive(const char* repname, bool signature)
 | 
						|
{
 | 
						|
  TFilename pdf; 
 | 
						|
  bool ok = spotlite_generate_name(repname, pdf);
 | 
						|
  if (ok)
 | 
						|
  {
 | 
						|
    ok = export_pdf(pdf, signature);
 | 
						|
    if (ok)
 | 
						|
      spotlite_notify(pdf);
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::send_mail(const TFilename& file, bool signature)
 | 
						|
{
 | 
						|
  bool ok = export_pdf(file, signature);
 | 
						|
  if (ok)
 | 
						|
    ok = spotlite_send_mail(file);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::preview()
 | 
						|
{
 | 
						|
  split_file_if_needed();
 | 
						|
 | 
						|
  TPreview_mask msk(this);
 | 
						|
 | 
						|
  //gestino anteprima di stampa;se si ha l'anteprima,una volta lanciata la maschera di stampa, si torna..
 | 
						|
  //..all'anteprima e non alla maschera del programma (decisivo per stampe con elaborazione lunga)
 | 
						|
  bool go_on = true;
 | 
						|
  while (go_on)
 | 
						|
  {
 | 
						|
    const KEY k = msk.run();
 | 
						|
    switch (k)
 | 
						|
    {
 | 
						|
    case K_QUIT: go_on = false; break;
 | 
						|
    case K_SAVE: esporta(); break;
 | 
						|
    default    : print(); break;      
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool TBook::print_or_preview()
 | 
						|
{
 | 
						|
  bool ok = true;
 | 
						|
  switch (printer().printtype())
 | 
						|
  {
 | 
						|
  case screenvis: 
 | 
						|
    ok = preview(); 
 | 
						|
    break;
 | 
						|
  case exportprinter:
 | 
						|
    {
 | 
						|
      const TFilename f = printer().get_export_file();
 | 
						|
      ok = export_text(f, false);
 | 
						|
      if (ok)
 | 
						|
        xvt_sys_goto_url(f, "open");
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    ok = print();
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
TBook::TBook(const char* name) 
 | 
						|
     : _out(NULL), _is_temporary(false),
 | 
						|
       _pw(0), _ph(0), _pvr(0), _phr(0), _max_frame(0,0),
 | 
						|
       _pages(0), _page(0), _rcd(NULL), _printwin(NULL), _page_is_open(false)
 | 
						|
 | 
						|
 | 
						|
{
 | 
						|
  _file = name;
 | 
						|
  if (_file.blank())
 | 
						|
  {
 | 
						|
    _file.temp("rep");
 | 
						|
    _is_temporary = true;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TBook::~TBook()
 | 
						|
{
 | 
						|
  close_output();
 | 
						|
  if (_is_temporary)
 | 
						|
    xvt_fsys_remove_file(_file);
 | 
						|
 | 
						|
  if (_printwin != NULL)
 | 
						|
    delete _printwin;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPrintind
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TPrintind : public TProgind
 | 
						|
{
 | 
						|
  TArray _modules;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual void update_bar();
 | 
						|
 | 
						|
public:
 | 
						|
  TPrintind(long n, const char* msg);
 | 
						|
};
 | 
						|
 | 
						|
void TPrintind::update_bar()
 | 
						|
{
 | 
						|
  TProgind::update_bar();
 | 
						|
 | 
						|
  const int m = _modules.items();
 | 
						|
  if (m > 0) // come dire ADVANCED_GRAPHICS
 | 
						|
  {
 | 
						|
    const int n = _status * 100 / _max;
 | 
						|
    const TImage& img = (const TImage&)_modules[n%m];
 | 
						|
    RCT r; get_bar_rct(r);
 | 
						|
    img.draw(win(), r.right - img.width(), r.bottom + 2);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TPrintind::TPrintind(long n, const char* msg) : TProgind(n, msg, true, true)
 | 
						|
 | 
						|
{
 | 
						|
  if (ADVANCED_GRAPHICS)
 | 
						|
  {
 | 
						|
    for (int i = 0; i < 4; i++)
 | 
						|
    {
 | 
						|
      TImage* img = new TImage(BMP_MODULE1 + i); 
 | 
						|
      img->convert_transparent_color(MASK_BACK_COLOR);
 | 
						|
      _modules.add(img);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TReport_book
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void TReport_book::define_frame(const TRectangle& r)
 | 
						|
{
 | 
						|
  TPoint ptlog = r; ptlog += _delta;
 | 
						|
  TPoint szlog = r.size();
 | 
						|
  const TRectangle rect(log2dev(ptlog), log2dev(szlog));
 | 
						|
  TBook::define_frame(rect);
 | 
						|
}
 | 
						|
 | 
						|
long TReport_book::print_section(char type, int level)
 | 
						|
{
 | 
						|
  long h = -3;  // Hidden
 | 
						|
  TReport_section* rs = _report->find_section(type, level);
 | 
						|
  if (rs != NULL)
 | 
						|
    h = print_section(*rs);
 | 
						|
  return h;
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::open_page()
 | 
						|
{
 | 
						|
  if (!TBook::open_page())
 | 
						|
    return false;
 | 
						|
 | 
						|
  _report->set_page(++_rep_page, page());
 | 
						|
 | 
						|
  _page_break_allowed = false;
 | 
						|
  _delta.reset();
 | 
						|
 | 
						|
  TReport_section* page_background = _report->find_section('B', 0);
 | 
						|
  if (page_background != NULL)
 | 
						|
  {
 | 
						|
    _delta = page_background->pos();
 | 
						|
    print_section(*page_background);
 | 
						|
    _delta.reset();
 | 
						|
  }
 | 
						|
 | 
						|
  if (_rep_page == 1)
 | 
						|
  {
 | 
						|
    const long height = print_section('H', 1);
 | 
						|
    if (height > 0)
 | 
						|
      _delta.y += height;
 | 
						|
  }
 | 
						|
 | 
						|
  TReport_section* page_head = _report->find_section('H', 0);
 | 
						|
  if (page_head != NULL && (_rep_page > 1 || !page_head->hidden_if_needed()))
 | 
						|
  {
 | 
						|
    _delta += page_head->pos();
 | 
						|
    const long height = print_section(*page_head);
 | 
						|
    if (height > 0)
 | 
						|
    {
 | 
						|
      _delta.y += height;
 | 
						|
      _delta.x = 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::close_page()
 | 
						|
{
 | 
						|
  if (_page_is_open)
 | 
						|
  {
 | 
						|
    TReport_section* page_foot = _report->find_section('F', 0);
 | 
						|
    if (page_foot != NULL && (!_is_last_page || !page_foot->hidden_if_needed()))
 | 
						|
    {
 | 
						|
      _delta.x = page_foot->pos().x;
 | 
						|
      _delta.y = _logical_foot_pos;
 | 
						|
      print_section(*page_foot);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TBook::close_page();
 | 
						|
}
 | 
						|
 | 
						|
void TReport_book::reprint_group_headers(const TReport_section& rs)
 | 
						|
{
 | 
						|
  int max_group = _report->find_max_level('H');
 | 
						|
  if (rs.type() == 'H' && rs.level() <= max_group)
 | 
						|
    max_group = rs.level()-1;
 | 
						|
 | 
						|
  for (int level = 2; level <= max_group; level++)
 | 
						|
  {
 | 
						|
    TReport_section& rs = _report->section('H', level);
 | 
						|
    if (rs.repeat_on_page())
 | 
						|
    {
 | 
						|
      const long height = rs.compute_size().y; // Compute size after the initilization script!
 | 
						|
      if (height > 0)
 | 
						|
      {
 | 
						|
        rs.print(*this);
 | 
						|
        _delta.y += height;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (rs.level() > 10) // E' una sottosezione ?
 | 
						|
  {
 | 
						|
    TPointer_array headers; // Elenco degli header di sottosezione che devo stampare
 | 
						|
    for (int level = rs.level(); level > 10; level /= 10)
 | 
						|
    {
 | 
						|
      TReport_section& rs = _report->section('H', level);
 | 
						|
      if (rs.repeat_on_page())
 | 
						|
      {
 | 
						|
        const long height = rs.compute_size().y; // Compute size after the initilization script!
 | 
						|
        if (height > 0)
 | 
						|
          headers.add(rs);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    for (int i = headers.last(); i >= 0; i--)  // Stampo in ordine livello
 | 
						|
    {
 | 
						|
      TReport_section& rs = (TReport_section&)headers[i];
 | 
						|
      const long height = rs.compute_size().y;
 | 
						|
      rs.print(*this);
 | 
						|
      _delta.y += height;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Stampa una sezione e ne ritorna l'altezza.  
 | 
						|
// In caso di problemi particolari torna un'altezza negativa:
 | 
						|
// -1 Abort
 | 
						|
// -2 Condizione di stampa non verificata
 | 
						|
// -3 Nascosta
 | 
						|
long TReport_book::print_section(TReport_section& rs)
 | 
						|
{
 | 
						|
  if (_print_aborted)
 | 
						|
    return -1;
 | 
						|
 | 
						|
  rs.load_fields();
 | 
						|
  rs.init_dynamic_heights(*this);
 | 
						|
 | 
						|
  // Non sono sicuro se vada prima di load_fields o dopo execute_prescript
 | 
						|
  if (rs.condition().full())
 | 
						|
  {
 | 
						|
    TVariant var;
 | 
						|
    _report->evaluate(rs.condition(), var, _alfafld);
 | 
						|
    if (!var.as_bool())
 | 
						|
      return -2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!rs.execute_prescript(*this))
 | 
						|
  {
 | 
						|
    _print_aborted = true;
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  if (rs.hidden())
 | 
						|
  {
 | 
						|
    if (!rs.execute_postscript()) // Faccio ugualmente i post-script
 | 
						|
      _print_aborted = true;
 | 
						|
    return -3;
 | 
						|
  }
 | 
						|
 | 
						|
  const long height = rs.compute_size().y; // Compute size after the initilization script!
 | 
						|
 | 
						|
  if (height > 0) // Has some visible fields
 | 
						|
  {
 | 
						|
    long reprint_from = 0;  // Posizione di stampa per sezione interrotte a meta'
 | 
						|
 | 
						|
    bool page_break = _page_break_allowed && rs.page_break(); // Salto pagina "forzato"
 | 
						|
    if (!page_break && rs.level() > 0)  // Controlla se il salto pagina e' "necessario"
 | 
						|
    {
 | 
						|
      long h = height;
 | 
						|
      if (rs.keep_with_next()) // Devo mantenermi con la prossima sezione
 | 
						|
      {
 | 
						|
        char next_type = 'B';  // Spesso la prossima sezione e' body 1
 | 
						|
        int next_level = 1;
 | 
						|
        if (rs.type() == 'H')  // Tento di essere piu' preciso con gli headers
 | 
						|
        {
 | 
						|
          const int maxlev = rs.report().find_max_level('H'); 
 | 
						|
          if (rs.level() < maxlev)
 | 
						|
          {
 | 
						|
            next_type = 'H';
 | 
						|
            next_level = rs.level()+1;
 | 
						|
            h += 100;  // Bonus per il body successivo all'header successivo
 | 
						|
          }
 | 
						|
        }
 | 
						|
        const TReport_section& next_section = rs.report().section(next_type, next_level);
 | 
						|
        if (next_section.page_break())
 | 
						|
          h += _ph;
 | 
						|
        else   
 | 
						|
          h += next_section.compute_size().y;
 | 
						|
      }
 | 
						|
      
 | 
						|
      const long space_left = _logical_foot_pos - _delta.y; // Calcola spazio rimasto
 | 
						|
      page_break = h > space_left; // Controlla se e' sufficiente
 | 
						|
      
 | 
						|
      // Controllo se la sezione puo' essere stampata su due pagine
 | 
						|
      if (page_break && space_left >= 100 && rs.can_be_broken())
 | 
						|
      {
 | 
						|
        reprint_from = space_left / 100 * 100;
 | 
						|
        rs.print_clipped(*this, 0, reprint_from);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (page_break)
 | 
						|
    {
 | 
						|
      close_page();
 | 
						|
      open_page();
 | 
						|
      reprint_group_headers(rs);
 | 
						|
    }
 | 
						|
    if (_page_is_open)
 | 
						|
    {
 | 
						|
      if (reprint_from > 0)
 | 
						|
      {
 | 
						|
        _delta.y -= reprint_from;
 | 
						|
        rs.print_clipped(*this, reprint_from, height);
 | 
						|
      }
 | 
						|
      else
 | 
						|
        rs.print(*this);
 | 
						|
    }
 | 
						|
 | 
						|
    if (rs.level() > 0 && (rs.type() != 'H' || rs.level() > 1)) // Ho stampato qualcosa che non sia lo sfondo!
 | 
						|
			_page_break_allowed = true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!rs.execute_postscript())
 | 
						|
  {
 | 
						|
    _print_aborted = true;
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  return height;
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::init(TReport& rep)
 | 
						|
{
 | 
						|
  TPrinter& pr = printer();
 | 
						|
 | 
						|
  bool save_profile = rep.save_last_printer();
 | 
						|
  if (save_profile && !pr.manual_setup())
 | 
						|
  {
 | 
						|
    const TString profile = rep.filename().name();
 | 
						|
    TConfig prini(CONFIG_STAMPE, profile);
 | 
						|
    const TString& rep_printer = prini.get("Name");
 | 
						|
    const TString& cur_printer = pr.printername();
 | 
						|
    if (rep_printer.full() && rep_printer != cur_printer) 
 | 
						|
    {
 | 
						|
      pr.read_configuration(profile); // Uso la stampante preferita dal report
 | 
						|
      save_profile = false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Controlla orientamento della carta prima di inizializzare
 | 
						|
  const int report_orientation = rep.orientation();
 | 
						|
  if (report_orientation > 0)
 | 
						|
  {
 | 
						|
    pr.set_landscape_orientation(report_orientation == 2);
 | 
						|
    // I parametri verranno riletti dalla TBook::init()
 | 
						|
  }
 | 
						|
 | 
						|
  if (save_profile) 
 | 
						|
  {
 | 
						|
    const TString profile = rep.filename().name();
 | 
						|
    pr.save_configuration(profile);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!TBook::init())
 | 
						|
    return false;
 | 
						|
 | 
						|
  _report = &rep;
 | 
						|
  if (rep.use_printer_font())
 | 
						|
    rep.load_printer_font();
 | 
						|
 | 
						|
  const TPoint siz = page_size();
 | 
						|
  const TPoint res = page_res();
 | 
						|
 | 
						|
  const double pollici_pagina_y = (double)siz.y / (double)res.y;
 | 
						|
  const double righe_pagina = pollici_pagina_y * lpi();
 | 
						|
  _logical_page_height = long(righe_pagina*100.0);
 | 
						|
 | 
						|
  const double pollici_pagina_x = (double)siz.x / (double)res.x;
 | 
						|
  const double colonne_pagina = pollici_pagina_x * cpi();
 | 
						|
  _logical_page_width = long(colonne_pagina*100.0);
 | 
						|
  
 | 
						|
  const TReport_section& footer = _report->section('F',0);
 | 
						|
  _logical_foot_pos = footer.pos().y;
 | 
						|
  if (_logical_foot_pos <= 0)
 | 
						|
  {
 | 
						|
    const long logical_footer_height = footer.compute_size().y;
 | 
						|
    _logical_foot_pos = _logical_page_height - logical_footer_height;  
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void TReport_book::print_subsections(int father)
 | 
						|
{
 | 
						|
  for (int i = 1; i <= 9 && !_print_aborted; i++)
 | 
						|
  {
 | 
						|
    const int level = father*10+i;
 | 
						|
    TReport_section* rs = _report->find_section('B', level);
 | 
						|
    if (rs == NULL)
 | 
						|
      break;
 | 
						|
 | 
						|
    TRecordset* rex = rs->recordset();
 | 
						|
    if (rex != NULL)
 | 
						|
    {
 | 
						|
      rex->requery();
 | 
						|
      if (rex->items() > 0)
 | 
						|
      {
 | 
						|
        long height = print_section('H', level);
 | 
						|
        if (height > 0)
 | 
						|
          _delta.y += height;
 | 
						|
        for (bool ok = rex->move_to(0); ok && !_print_aborted; ok = rex->move_next())
 | 
						|
        {
 | 
						|
          height = print_section('B', level);
 | 
						|
          if (height >= 0)
 | 
						|
          {
 | 
						|
            _delta.y += height;
 | 
						|
            print_subsections(level);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        height = print_section('F', level);
 | 
						|
        if (height > 0)
 | 
						|
          _delta.y += height;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TReport_book::add_doc(const TString& name)
 | 
						|
{
 | 
						|
  if (name.ends_with(".rep", true)) // Tratto a parte i report!
 | 
						|
  {
 | 
						|
    TReport* eminem = new TReport;
 | 
						|
    if (eminem->load(name))
 | 
						|
    {
 | 
						|
      TReport* rep = _report; // Salvo variabile globale
 | 
						|
 | 
						|
      if (rep->use_mask())
 | 
						|
      {
 | 
						|
        TFilename msk = rep->filename().name(); 
 | 
						|
        msk.ext("msk");
 | 
						|
        if (msk.custom_path())
 | 
						|
        {
 | 
						|
          TMask m(msk);
 | 
						|
          rep->report2mask(m);
 | 
						|
          eminem->mask2report(m);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      add(*eminem, true);
 | 
						|
      _report = rep;          // Ripristino variabile globale
 | 
						|
    }
 | 
						|
    delete eminem;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    TBook::add_doc(name);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TReport_book::add(TReport& rep, bool progind)
 | 
						|
{
 | 
						|
  if (!init(rep))
 | 
						|
    return false;
 | 
						|
 | 
						|
  if (!_report->execute_prescript())
 | 
						|
    return false;
 | 
						|
 | 
						|
  TRecordset* rex = _report->recordset();
 | 
						|
  if (rex == NULL)
 | 
						|
    return true;
 | 
						|
 | 
						|
  rex->requery();
 | 
						|
  const TRecnotype rex_items = rex->items();
 | 
						|
  if (rex_items <= 0)
 | 
						|
    return true;
 | 
						|
 | 
						|
  TString msg = TR("Elaborazione report");
 | 
						|
  msg << ' ' << _report->filename();
 | 
						|
  
 | 
						|
  TProgind* pi = NULL;
 | 
						|
  if (progind && rex_items > 1)
 | 
						|
    pi = new TPrintind(rex_items, msg);
 | 
						|
 | 
						|
  TString_array oldgroup, newgroup;
 | 
						|
  const int max_group = _report->find_max_level('H');
 | 
						|
  if (max_group >= 2)
 | 
						|
  {
 | 
						|
    for (int g = 2; g <= max_group; g++)
 | 
						|
      oldgroup.add(EMPTY_STRING, g);
 | 
						|
  }
 | 
						|
  const int max_body = _report->find_max_level('B');
 | 
						|
  int last_body_height = 0;
 | 
						|
  
 | 
						|
  _rep_page = rep.last_printed_page(); // Azzera numero di pagina relativo
 | 
						|
  _is_last_page = false;
 | 
						|
	
 | 
						|
	bool ok = rex->move_first();
 | 
						|
	
 | 
						|
	open_page();
 | 
						|
  for (; ok && !_print_aborted; ok = rex->move_next())
 | 
						|
  {
 | 
						|
    if (max_group >= 2) // Gestione raggruppamenti
 | 
						|
    {
 | 
						|
      int first_changed = 0;
 | 
						|
      TVariant var;
 | 
						|
      for (int g = 2; g <= max_group; g++)
 | 
						|
      {
 | 
						|
        const TString& expr = _report->section('H', g).grouped_by();
 | 
						|
        _report->evaluate(expr, var, _alfafld);
 | 
						|
        const TString& grp = var.as_string();
 | 
						|
        newgroup.add(grp, g);
 | 
						|
        if (newgroup.row(g) != oldgroup.row(g) || rex->current_row() == 0)
 | 
						|
        {
 | 
						|
          if (first_changed == 0)
 | 
						|
            first_changed = g;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (first_changed)
 | 
						|
      {
 | 
						|
        oldgroup = newgroup;
 | 
						|
 | 
						|
        if (_delta.x > 0) // Devo tornare a capo!
 | 
						|
          _delta.y += last_body_height;
 | 
						|
        _delta.x = 0;
 | 
						|
        
 | 
						|
        if (rex->current_row() > 0)
 | 
						|
        {
 | 
						|
          for (int g = max_group; g >= first_changed ; g--)
 | 
						|
          {
 | 
						|
            const long height = print_section('F', g);
 | 
						|
            if (height > 0)
 | 
						|
              _delta.y += height;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        for (int g = first_changed; g <= max_group; g++)
 | 
						|
        {
 | 
						|
          const long height = print_section('H', g);
 | 
						|
          if (height > 0)
 | 
						|
            _delta.y += height;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // Stampa di tutti i body
 | 
						|
    for (int b = 1; b <= max_body; b++)
 | 
						|
    {
 | 
						|
      const int dy = print_section('B', b);
 | 
						|
      if (dy > 0) // Ho stampato fisicamente qualcosa
 | 
						|
      {
 | 
						|
        // Cerco di vedere se e' possibile la stampa etichette
 | 
						|
        int column_delta = 0;
 | 
						|
        const int dx = _report->section('B', b).size().x;
 | 
						|
        // Se dx > 0 ho una sezione a dimensione fissa
 | 
						|
        if (dx > 0 && _delta.x+2*dx <= _logical_page_width)
 | 
						|
        {
 | 
						|
          column_delta = dx;
 | 
						|
          last_body_height = dy;
 | 
						|
        }
 | 
						|
      
 | 
						|
        if (column_delta > 0)
 | 
						|
          _delta.x += column_delta;
 | 
						|
        else
 | 
						|
        {
 | 
						|
          _delta.x = 0;
 | 
						|
          _delta.y += dy;
 | 
						|
          last_body_height = 0; // Non servirebbe strettamente
 | 
						|
        }  
 | 
						|
      }
 | 
						|
      if (dy >= 0)
 | 
						|
      {
 | 
						|
        // Stampa eventuali sottosezioni
 | 
						|
        print_subsections(b);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (pi != NULL)
 | 
						|
    {
 | 
						|
      if (!pi->addstatus(1))
 | 
						|
        _print_aborted = true;
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
  if (!_print_aborted)
 | 
						|
  {
 | 
						|
    // Devo stampare tutte le code degli eventuali raggrupamenti
 | 
						|
    for (int g = max_group; g >= 2 ; g--)
 | 
						|
    {
 | 
						|
      const long height = print_section('F', g);
 | 
						|
      if (height > 0)
 | 
						|
        _delta.y += height;
 | 
						|
    }
 | 
						|
 | 
						|
    TReport_section* fl = _report->find_section('F',1);
 | 
						|
    if (fl != NULL)          // Gestione footer last (se esite)
 | 
						|
    {
 | 
						|
      const int fy = fl->pos().y;
 | 
						|
      if (fy > 0)            // Ha una coordinata y imposta
 | 
						|
      {
 | 
						|
        if (fy < _delta.y)   // Sono gia' andato oltre quindi salto pagina
 | 
						|
        {
 | 
						|
          close_page();
 | 
						|
          open_page();
 | 
						|
        }
 | 
						|
        _delta.x = 0;
 | 
						|
        _delta.y = fy;
 | 
						|
 | 
						|
        // Azzero temporaneamente le dimensioni del footer per evitare salti pagina
 | 
						|
        const int lfp = _logical_foot_pos;
 | 
						|
        _logical_foot_pos = _logical_page_height; 
 | 
						|
        print_section(*fl);
 | 
						|
        _logical_foot_pos = lfp;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        print_section(*fl);  // Stampa normale
 | 
						|
    }
 | 
						|
 | 
						|
    _is_last_page = true;
 | 
						|
    close_page();
 | 
						|
 | 
						|
    _report->execute_postscript();
 | 
						|
 | 
						|
    if (!_print_aborted)
 | 
						|
    {
 | 
						|
      const TString_array& all = _report->allegates();
 | 
						|
      for (int a = 0; a < all.items(); a++)
 | 
						|
      {
 | 
						|
        TFilename name = all.row(a);
 | 
						|
        if (name.find('#') >= 0) // Se puo' essere un'espressione
 | 
						|
        {
 | 
						|
          TVariant var;
 | 
						|
          if (_report->evaluate(name, var, _alfafld))
 | 
						|
            name = var.as_string();
 | 
						|
        }
 | 
						|
        add_doc(name);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (pi != NULL)
 | 
						|
    delete pi;
 | 
						|
 | 
						|
  return !_print_aborted;
 | 
						|
}
 | 
						|
 | 
						|
int TReport_book::lpi() const
 | 
						|
{
 | 
						|
  if (_report != NULL)
 | 
						|
    return _report->print_lpi();
 | 
						|
  return TBook::lpi();
 | 
						|
}
 | 
						|
 | 
						|
int TReport_book::cpi() const
 | 
						|
{
 | 
						|
  if (_report != NULL)
 | 
						|
    return _report->print_cpi();
 | 
						|
  return TBook::cpi();
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::can_split(int pages) const
 | 
						|
{
 | 
						|
  if (_report != NULL)
 | 
						|
    return _report->page_split_allowed();
 | 
						|
  return TBook::can_split(pages);
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::can_merge(int pages) const
 | 
						|
{
 | 
						|
  if (_report != NULL)
 | 
						|
    return _report->page_merge_allowed();
 | 
						|
  return TBook::can_merge(pages);
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::print(size_t pagefrom, size_t pageto, word copies)
 | 
						|
{
 | 
						|
  if (pages() <= 0)
 | 
						|
    return false;
 | 
						|
  split_file_if_needed();
 | 
						|
 | 
						|
  if (pagefrom <= 0)
 | 
						|
  {
 | 
						|
    TPrinter& p = printer();
 | 
						|
    TMask msk("bagn003");
 | 
						|
    msk.set(F_PRINTER, p.printername());
 | 
						|
    if (_report != NULL)
 | 
						|
    {
 | 
						|
      msk.set(F_FORM, _report->filename());
 | 
						|
      msk.set(F_FONT, _report->print_font().name());
 | 
						|
      msk.set(F_SIZE, _report->print_font().size());
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      msk.set(F_FONT, p.fontname());
 | 
						|
      msk.set(F_SIZE, p.get_char_size());
 | 
						|
    }
 | 
						|
    msk.set(F_LINES, lpi());
 | 
						|
    msk.set(F_ORIENT, p.is_portrait() ? 1 : 2);
 | 
						|
    msk.set(F_ISGRAPHICS, p.isgraphics());
 | 
						|
    msk.set(F_FROMPAGE, 1);
 | 
						|
    msk.set(F_TOPAGE, pages());
 | 
						|
    msk.set(F_COPIES, 1);
 | 
						|
    if (msk.run() == K_ENTER)
 | 
						|
    {
 | 
						|
      copies = msk.get_int(F_COPIES);
 | 
						|
      pagefrom = msk.get_int(F_FROMPAGE);
 | 
						|
      pageto = msk.get_int(F_TOPAGE);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return TBook::print(pagefrom, pageto, copies);
 | 
						|
}
 | 
						|
 | 
						|
bool TReport_book::archive(const char* repname)
 | 
						|
{
 | 
						|
  TFilename n = repname;
 | 
						|
  if (n.blank() && _report != NULL)
 | 
						|
  {
 | 
						|
    n = _report->filename().name();
 | 
						|
    n.ext("");
 | 
						|
  }
 | 
						|
  return TBook::archive(n);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TReport_book::on_link(const TReport_link& lnk)
 | 
						|
{
 | 
						|
  bool ok = false;
 | 
						|
  if (_report != NULL)
 | 
						|
    ok = _report->on_link(lnk);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
TReport_book::TReport_book(const char* name) 
 | 
						|
            : TBook(name), _report(NULL)
 | 
						|
{ }
 |