c93f5b89bd
Files correlati : Ricompilazione Demo : [ ] Commento : Corretto l'aggiornamento della stampa nel caso di spezzamento su più pagine. Corretta la visualizzazione nel caso la stampa esca dalla pagina. git-svn-id: svn://10.65.10.50/branches/R_10_00@23220 c028cbd2-c16b-5b4b-a496-9718f37d4682
3080 lines
78 KiB
C++
Executable File
3080 lines
78 KiB
C++
Executable File
#include <applicat.h>
|
|
#include <automask.h>
|
|
#include <colors.h>
|
|
#include <config.h>
|
|
#include <defmask.h>
|
|
#include <dongle.h>
|
|
#include <execp.h>
|
|
#include <modaut.h>
|
|
#include <printer.h>
|
|
#include <progind.h>
|
|
#include <reprint.h>
|
|
#include <spotlite.h>
|
|
#include <statbar.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-1; 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-descent)/2; break;
|
|
case 'T': y = r.top + ascent; break;
|
|
default : y -= descent+leading; 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, &r) != 0;
|
|
if (can_draw)
|
|
xvt_dwin_set_clip(w, &clipper);
|
|
else
|
|
restore_clip = false;
|
|
}
|
|
else
|
|
xvt_dwin_set_clip(w, &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 needed_rows = para.items();
|
|
if (needed_rows > 1) // Devo scrivere piu' righe?
|
|
{
|
|
int leading, ascent, descent;
|
|
xvt_dwin_get_font_metrics(win, &leading, &ascent, &descent);
|
|
|
|
const int rct_height = rct.bottom - rct.top;
|
|
const int row_height = leading + ascent + descent;
|
|
int ky10 = row_height * 10;
|
|
// Aggiusta l'altezza di una riga standard, se necessario
|
|
if (ky10 < default_10row_height && ky10 > 75*default_10row_height/100)
|
|
{
|
|
const int avail_rows = (rct_height+row_height/4)/row_height;
|
|
if (avail_rows > needed_rows)
|
|
ky10 = default_10row_height; else
|
|
if (avail_rows >= 4 && avail_rows >= needed_rows-1)
|
|
ky10 = rct_height*10/needed_rows;
|
|
}
|
|
|
|
int ybase = rct.top;
|
|
switch (valign)
|
|
{
|
|
case 'C': ybase += (rct_height - (needed_rows * ky10) / 10) / 2; break;
|
|
case 'B': ybase += rct_height - (needed_rows * ky10) / 10; break;
|
|
default : break;
|
|
}
|
|
|
|
const int lastop = rct.bottom - ky10/20; // Ultima y valida = base del rettangolo MENO mezza riga
|
|
for (int row = 0; row < needed_rows; row++)
|
|
{
|
|
const int top = ybase + (ky10 * row) / 10;
|
|
if (top < lastop)
|
|
{
|
|
const TString& line = para.row(row);
|
|
if (line.full())
|
|
{
|
|
RCT rctline = rct;
|
|
rctline.top = top;
|
|
rctline.bottom = ybase + (ky10 * (row+1)) / 10; // top + ky10 / 10;
|
|
char ha = halign;
|
|
if (ha == 'J' && (row == needed_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 long 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();
|
|
short book2pix(int size) const;
|
|
|
|
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();
|
|
};
|
|
|
|
short TPrint_preview_window::book2pix(int sz) const
|
|
{
|
|
return short(sz * _zoom / BOOKDPI);
|
|
}
|
|
|
|
PNT TPrint_preview_window::log2dev(long lx, long ly) const
|
|
{
|
|
PNT pnt = { book2pix(ly), book2pix(lx) };
|
|
|
|
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 TSize 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 TSize 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 TSize 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 TSize 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*)TR("Prima"); menu[0].enabled = _page > 1;
|
|
menu[1].tag = POPUP_PREV; menu[1].text = (char*)TR("Indietro"); menu[1].enabled = _page > 1;
|
|
menu[2].tag = POPUP_NEXT; menu[2].text = (char*)TR("Avanti"); menu[2].enabled = _page < _book->pages();
|
|
menu[3].tag = POPUP_LAST; menu[3].text = (char*)TR("Ultima"); menu[3].enabled = _page < _book->pages();
|
|
menu[4].tag = -1; menu[4].separator = true;
|
|
menu[5].tag = POPUP_ZOOMIN; menu[5].text = (char*)TR("Zoom +"); menu[5].enabled = _zoom < SCREENDPI*4;
|
|
menu[6].tag = POPUP_ZOOMOUT; menu[6].text = (char*)TR("Zoom -"); menu[6].enabled = _zoom > SCREENDPI/4;
|
|
menu[7].tag = -1; menu[7].separator = true;
|
|
menu[8].tag = POPUP_GRID; menu[8].text = (char*)TR("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;
|
|
}
|
|
|
|
long 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 < SCREENDPI*4) { _zoom += SCREENDPI/8; update_scroll_range(); } break;
|
|
case POPUP_ZOOMOUT: if (_zoom > SCREENDPI/4) { _zoom -= SCREENDPI/8; 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:
|
|
return TField_window::handler(win, ep);
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
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(SCREENDPI), _grid(false)
|
|
{
|
|
_pixmap = true;
|
|
_grid = ini_get_bool(CONFIG_GUI, "Preview", "Grid");
|
|
}
|
|
|
|
TPrint_preview_window::~TPrint_preview_window()
|
|
{
|
|
ini_set_string(CONFIG_GUI, "Preview", "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 long 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);
|
|
}
|
|
|
|
long 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:
|
|
return TAutomask::handler(win, ep);
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
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();
|
|
};
|
|
|
|
// Converte da coordinate espresse in 1/720 di pollice a coordinate fisiche su carta
|
|
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 TReport_pnt& ptlog) const
|
|
{
|
|
TPoint ptdev;
|
|
ptdev.x = (ptlog.x * BOOKDPI) / (100 * cpi());
|
|
ptdev.y = (ptlog.y * BOOKDPI) / (100 * lpi());
|
|
return ptdev;
|
|
}
|
|
|
|
TRectangle TBook::log2dev(const TReport_rct& rctlog) const
|
|
{
|
|
const TReport_pnt& lp0 = rctlog;
|
|
TReport_pnt lp1 = lp0; lp1 += rctlog.size();
|
|
const TPoint p0 = log2dev(lp0);
|
|
const TPoint p1 = log2dev(lp1);
|
|
return TRectangle(p0, p1-p0);
|
|
}
|
|
|
|
PNT TBook::log2pix(const TReport_pnt& ptlog) const
|
|
{
|
|
const TPoint ptdev = log2dev(ptlog);
|
|
return _printwin->log2dev(ptdev.x, ptdev.y);
|
|
}
|
|
|
|
// Converte da coordinate di stampa (1/720 di pollice) in pixel
|
|
short TBook::book2pix(int t) const
|
|
{
|
|
const PNT pnt = _printwin->log2dev(t, 0);
|
|
return pnt.h;
|
|
}
|
|
|
|
int TBook::compute_text_frame(const TString& tmp, const TReport_font& font, TReport_rct& rect, TString_array& para) const
|
|
{
|
|
// Calcola la larghezza massima e l'altezza di 10 righe
|
|
// const TReport_rct 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;
|
|
const PNT p0 = log2pix(TReport_pnt(0,0));
|
|
const PNT p1 = log2pix(TReport_pnt(rect.width(),1000));
|
|
const int max_row_width = p1.h-p0.h;
|
|
const int def_10row_height = p1.v-p0.v;
|
|
if (max_row_width < 100)
|
|
return 0; // Con un rettangolo quasi vuoto, si combina poco di buono!
|
|
|
|
WINDOW w = _printwin->win();
|
|
CHECK(w == PRINTER_WIN, "Finestra di stampa non valida");
|
|
xvt_dwin_set_font(w, font.get_xvt_font(*_printwin));
|
|
|
|
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(); 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 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;
|
|
|
|
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;
|
|
}
|
|
|
|
TSize TBook::page_size() const
|
|
{
|
|
if (_page_size.x <= 0 || _page_size.y <= 0) // Valori nulli: mi invento un A4
|
|
{
|
|
TSize pag = page_res();
|
|
pag.x *= 8; pag.y *= 11;
|
|
return pag;
|
|
}
|
|
return _page_size;
|
|
}
|
|
|
|
TSize TBook::page_res() const
|
|
{ return TSize(BOOKDPI, BOOKDPI); }
|
|
|
|
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((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::define_frame(const TReport_rct& rr)
|
|
{
|
|
const TRectangle rb = log2dev(rr); // Converto rr da coordinate logiche a rb a 720 DPI
|
|
define_frame(rb); // Salvo le coordinate a 720 DPI
|
|
}
|
|
|
|
void TBook::set_clip(long top, long bottom)
|
|
{
|
|
if (bottom >= top)
|
|
{
|
|
const TReport_rct rect(0, top, logical_page_width(), bottom-top);
|
|
define_frame(rect);
|
|
*_out << "<clip>" << endl;
|
|
}
|
|
else
|
|
*_out << "</clip>" << endl;
|
|
}
|
|
|
|
void TBook::draw_text(const TReport_rct& r, const char* txt, const char* section)
|
|
{
|
|
if (txt && *txt)
|
|
{
|
|
const TFixed_string str(txt);
|
|
if (str.full())
|
|
{
|
|
define_frame(r);
|
|
*_out << "<text owner=" << section << ">" << endl
|
|
<< str << endl << "</text>" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TBook::draw_text(const TReport_rct& r, const TString_array& txt, const char* section)
|
|
{
|
|
if (!txt.empty())
|
|
{
|
|
define_frame(r);
|
|
*_out << "<text owner=" << section << ">" << 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 TReport_rct& 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, int shade_angle)
|
|
{
|
|
if (_tools.brush.color != color || _tools.brush.pat != pattern || shade_angle != _shade_angle)
|
|
{
|
|
_tools.brush.color = color;
|
|
_tools.brush.pat = pattern;
|
|
_shade_angle = shade_angle;
|
|
*_out << "<brush color=" << color << " pattern=" << pattern;
|
|
if (pattern == PAT_SPECIAL)
|
|
*_out << " shade_angle=" << shade_angle;
|
|
*_out << " />" << 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 TReport_rct& r)
|
|
{
|
|
define_frame(r);
|
|
*_out << "<rectangle/>" << endl;
|
|
}
|
|
|
|
void TBook::draw_round_rectangle(const TReport_rct& r, int radius)
|
|
{
|
|
define_frame(r);
|
|
*_out << "<rounded_rectangle radius=" << radius << " />" << endl;
|
|
}
|
|
|
|
void TBook::draw_ellipse(const TReport_rct& r)
|
|
{
|
|
define_frame(r);
|
|
*_out << "<ellipse/>" << endl;
|
|
}
|
|
|
|
void TBook::draw_line(const TReport_rct& r)
|
|
{
|
|
define_frame(r);
|
|
*_out << "<line/>" << endl;
|
|
}
|
|
|
|
void TBook::draw_link(const TReport_rct& rect, const char* text, const char* link)
|
|
{
|
|
define_frame(rect);
|
|
*_out << "<a href=\"" << link << "\" >" << text << "</a>" << endl;
|
|
}
|
|
|
|
void TBook::draw_image(const TReport_rct& 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() == PRINTER_WIN;
|
|
|
|
if (print)
|
|
{
|
|
TWindow_printer& wp = (TWindow_printer&)win;
|
|
wp.print_doc(name);
|
|
}
|
|
else
|
|
{
|
|
const TSize 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 TSize 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;
|
|
int shade_angle = 0;
|
|
RCT visible;
|
|
if (preview)
|
|
{
|
|
xvt_vobj_get_client_rect(w, &visible);
|
|
TPrint_preview_window& pw = (TPrint_preview_window&)win;
|
|
pw.alinks().destroy();
|
|
}
|
|
else
|
|
xvt_rect_set_null(&visible);
|
|
|
|
TToken_string str(1024, '=');
|
|
|
|
TString_array paragrafo; // Testo completo di un campo
|
|
|
|
// Calcolo altezza riga standard
|
|
const TRectangle rect_riga(0,0,BOOKDPI*10/cpi(),BOOKDPI*10/lpi());
|
|
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 logical frame (1/720 coords)
|
|
RCT rct = { 0,0,0,0 }; // Physical frame (pixel coords)
|
|
|
|
_horizontal_alignment = 'L'; // Reset text alignment
|
|
_vertical_alignment = 'T';
|
|
|
|
bool page_is_open = false; // Stato attuale della pagina della stampante
|
|
|
|
if (preview)
|
|
{
|
|
RCT rct; xvt_vobj_get_client_rect(w, &rct);
|
|
|
|
const TSize size = page_size();
|
|
TPrint_preview_window& pw = (TPrint_preview_window&)win;
|
|
const PNT pag = pw.log2dev(size.x, size.y);
|
|
|
|
if (pag.h < rct.right)
|
|
{
|
|
rct.right = pag.h;
|
|
xvt_dwin_set_clip(w, &rct);
|
|
}
|
|
}
|
|
|
|
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 shade_angle=%d />
|
|
const COLOR col = str.get_long(1);
|
|
const PAT_STYLE pat = (PAT_STYLE)str.get_long();
|
|
if (pat <= PAT_HOLLOW)
|
|
win.hide_brush();
|
|
else
|
|
win.set_brush(col, pat);
|
|
shade_angle = (pat == PAT_SPECIAL) ? str.get_int() : 0;
|
|
continue;
|
|
}
|
|
if (str.starts_with("<clip"))
|
|
{
|
|
xvt_dwin_set_clip(w, &rct);
|
|
continue;
|
|
} else
|
|
if (str.starts_with("</clip"))
|
|
{
|
|
xvt_dwin_set_clip(w, NULL);
|
|
continue;
|
|
} 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); // Rettangolo in 1/720 di pollice
|
|
win.log2dev(_rect, rct); // Rettangolo in pixel su carta
|
|
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
|
|
{
|
|
if (name.ends_with(".png", true)) // Provo gestire trasparenza
|
|
{
|
|
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
|
|
{
|
|
double t = 0;
|
|
if (preview)
|
|
{
|
|
const TPrint_preview_window& pw = (const TPrint_preview_window&)win;
|
|
t = pw.book2pix(width ? 100*width : 50)/10.0;
|
|
if (t < 1.0) // Sfuma le linee sottili in anteprima
|
|
col = blend_colors(col, COLOR_WHITE, t);
|
|
}
|
|
else
|
|
{
|
|
t = book2pix(width ? 10*width : 5); // width e' in 1/72 di pollice
|
|
}
|
|
const int thickness = int(t+0.5); // Arrotonda all'unita' piu' vicina
|
|
win.set_pen(col, thickness);
|
|
}
|
|
continue;
|
|
}
|
|
if (str == "<rectangle/>")
|
|
{
|
|
DRAW_CTOOLS ct; xvt_dwin_get_draw_ctools(w, &ct);
|
|
if (ct.brush.pat == PAT_SPECIAL)
|
|
{
|
|
if (shade_angle >= 0)
|
|
xvt_dwin_draw_gradient_linear(w, &rct, ct.back_color, ct.brush.color, shade_angle);
|
|
else
|
|
xvt_dwin_draw_gradient_circular(w, &rct, ct.back_color, ct.brush.color, NULL);
|
|
if (ct.pen.style > PAT_HOLLOW)
|
|
{
|
|
win.hide_brush(); // Hide brush
|
|
xvt_dwin_draw_rect(w, &rct); // Draw frame only
|
|
xvt_dwin_set_cbrush(w, &ct.brush); // Restore brush
|
|
}
|
|
}
|
|
else
|
|
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 ")) // <text owner=B1>
|
|
{
|
|
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);
|
|
}
|
|
|
|
if (preview)
|
|
xvt_dwin_set_clip(w, NULL);
|
|
return true;
|
|
}
|
|
|
|
bool TBook::export_text(TFilename& fname, bool signature)
|
|
{
|
|
TString ext = fname.ext(); ext.lower();
|
|
if (ext == "pdf")
|
|
return export_pdf(fname, signature);
|
|
if (ext.starts_with("xls") || ext.starts_with("htm"))
|
|
return export_excel(fname, signature);
|
|
|
|
TToken_string str(1024, '=');
|
|
|
|
ifstream ifs(_file);
|
|
ofstream ofs(fname);
|
|
|
|
TString_array page;
|
|
int row, col, wid, hei;
|
|
|
|
const TSize 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.starts_with("<text ")) // <text owner=B1>
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
ofs.close();
|
|
if (signature && main_app().has_module(FDAUT))
|
|
{
|
|
char outfile[_MAX_PATH] = "";
|
|
if (xvt_sign_file(fname, outfile))
|
|
fname = outfile;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void reformat_excel(TString& str)
|
|
{
|
|
str.trim();
|
|
|
|
if (str.not_empty())
|
|
{
|
|
bool is_number = true;
|
|
bool is_mig = false;
|
|
bool is_dec = false;
|
|
for (int i = 0; str[i]; i++)
|
|
{
|
|
if (strchr("0123456789.,", str[i]) != NULL)
|
|
{
|
|
if (str[i] == '.') is_mig = true;
|
|
if (str[i] == ',') is_dec = true;
|
|
}
|
|
else
|
|
{
|
|
is_number = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (is_number && (is_dec || is_mig))
|
|
{
|
|
if (is_mig)
|
|
str.strip(".");
|
|
if (is_dec)
|
|
str.replace(',', '.');
|
|
const real n = str;
|
|
str = n.stringe();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TBook::export_excel(TFilename& fname, bool signature)
|
|
{
|
|
TTabulator tab;
|
|
|
|
int row = 0, col = 0, wid = 0;
|
|
TToken_string str(1024, '=');
|
|
|
|
const TSize res = page_res();
|
|
|
|
if (tab.empty()) // dummy test
|
|
{
|
|
ifstream ifs(_file);
|
|
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 w = str.get_long();
|
|
row = y * lpi() / res.y;
|
|
col = x * cpi() / res.x;
|
|
wid = w * cpi() / res.x;
|
|
} else
|
|
if (str.starts_with("<text owner="))
|
|
{
|
|
// <text owner=B1>
|
|
const char* section = str.get(1);
|
|
if ((section[0] == 'B'||section[0]=='F') && section[1]>'0')
|
|
tab.add_field(col, wid);
|
|
// Raggiunge fine del testo
|
|
while (str != "</text>" && !ifs.eof())
|
|
ifs.getline(str.get_buffer(), str.size());
|
|
} else
|
|
if (str.starts_with("</page"))
|
|
break;
|
|
}
|
|
tab.sort();
|
|
}
|
|
if (!tab.empty())
|
|
{
|
|
TString_array page;
|
|
|
|
ifstream ifs(_file);
|
|
ofstream ofs(fname);
|
|
|
|
short pageno = 0;
|
|
while (!ifs.eof())
|
|
{
|
|
ifs.getline(str.get_buffer(), str.size());
|
|
if (str.starts_with("<frame "))
|
|
{
|
|
const long x = str.get_long(1);
|
|
const long y = str.get_long();
|
|
const long w = str.get_long();
|
|
row = y * lpi() / res.y;
|
|
col = x * cpi() / res.x;
|
|
wid = w * cpi() / res.x;
|
|
} else
|
|
if (str.starts_with("<text "))
|
|
{
|
|
const char* section = str.get(1);
|
|
bool do_export = section[1] > '0';
|
|
if (!do_export)
|
|
{
|
|
switch (section[0])
|
|
{
|
|
case 'H': do_export = (pageno == 1); break; // Stampa gli header solo sulla prima pagina
|
|
default : break;
|
|
}
|
|
}
|
|
|
|
while (!ifs.eof())
|
|
{
|
|
ifs.getline(str.get_buffer(), str.size());
|
|
if (str == "</text>")
|
|
break;
|
|
if (do_export && str.full())
|
|
{
|
|
int idx, pos;
|
|
if (tab.find_column(col, wid, idx, pos))
|
|
{
|
|
TToken_string* line = (TToken_string*)page.objptr(row);
|
|
if (line == NULL)
|
|
{
|
|
line = new TToken_string(256,'\t');
|
|
page.add(line, row);
|
|
}
|
|
reformat_excel(str);
|
|
line->add(str, pos);
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
if (str.starts_with("<page"))
|
|
{
|
|
pageno = str.get_int(1);
|
|
} else
|
|
if (str.starts_with("</page"))
|
|
{
|
|
FOR_EACH_ARRAY_ROW(page, i, line) if (line->full())
|
|
{
|
|
ofs << *line << endl; // Stampo e...
|
|
line->cut(0); // ... svuoto
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (signature && main_app().has_module(FDAUT))
|
|
{
|
|
char outfile[_MAX_PATH] = "";
|
|
if (xvt_sign_file(fname, outfile))
|
|
fname = outfile;
|
|
}
|
|
|
|
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"));
|
|
|
|
long ph, pw, pvr, phr;
|
|
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"));
|
|
|
|
if (_page_size.x > 0 && (_page_size.x > _page_size.y) != (pw > ph)) // Orientamento incongruente
|
|
{
|
|
xvt_app_escape (XVT_ESC_SET_PRINTER_INFO, _rcd, &pw, &ph, NULL, NULL); // Scambio dimensioni
|
|
xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _rcd, &ph, &pw, &pvr, &phr); // Rileggo dimensioni e risoluzione
|
|
}
|
|
|
|
_page_size.y = ph * BOOKDPI / pvr;
|
|
_page_size.x = pw * BOOKDPI / phr;
|
|
|
|
if (_printwin != NULL)
|
|
delete _printwin;
|
|
_printwin = new TWindow_printer(_rcd, _pdf_file);
|
|
|
|
return _printwin->win() != NULL_WIN;
|
|
}
|
|
|
|
void TBook::split_file(int colonne)
|
|
{
|
|
TProgind pi(pages(), TR("Rigenerazione pagine"), true, true);
|
|
|
|
TFilename temp; temp.temp("bck");
|
|
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*_page_size.x, 0, _page_size.x, _page_size.y);
|
|
|
|
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((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);
|
|
|
|
ifstream itmp(temp); // Apro file di stampa da splittare
|
|
|
|
delete _out;
|
|
_out = new ofstream(_file);
|
|
while (!itmp.eof())
|
|
{
|
|
itmp.getline(str.get_buffer(), str.size());
|
|
(*_out) << str << endl;
|
|
}
|
|
itmp.close();
|
|
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("bck");
|
|
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;
|
|
off_page = sub * page_size().y / pps;
|
|
if (sub == 0)
|
|
{
|
|
out_page = (in_page - 1) / pps + 1;
|
|
_index.add_long((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 (in_page % pps == 0)
|
|
{
|
|
str.format("</page number=%d>", out_page);
|
|
in_page = 0;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
out << str << endl;
|
|
}
|
|
|
|
if (in_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 TSize sheet = page_size();
|
|
|
|
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 = !init();
|
|
|
|
if (!_print_aborted)
|
|
{
|
|
if (_pageto < _pagefrom)
|
|
_pageto = pages();
|
|
|
|
for (word copy = 0; copy < _copies && !_print_aborted; copy++)
|
|
{
|
|
for (size_t page = _pagefrom; page <= _pageto && !_print_aborted; page++)
|
|
_print_aborted = !print_page(*_printwin, page);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
TPrinter& p = printer();
|
|
|
|
if (pagefrom == 0)
|
|
{
|
|
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 = max(msk.get_int(F_COPIES), 1);
|
|
_pagefrom = msk.get_int(F_FROMPAGE);
|
|
_pageto = msk.get_int(F_TOPAGE);
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
_pagefrom = pagefrom;
|
|
_pageto = pageto;
|
|
_copies = max(copies, 1);
|
|
}
|
|
|
|
bool ok = false;
|
|
|
|
if (p.printtype() == acrobatprinter)
|
|
{
|
|
TFilename f; f.temp(NULL, "pdf");
|
|
_pdf_file = f;
|
|
ok = xvt_print_start_thread(main_loop_callback, (long)this) != 0;
|
|
if (ok && fsize(f) > 0)
|
|
printer().acrobatically_print_pdf(f);
|
|
f.fremove();
|
|
}
|
|
else
|
|
{
|
|
_pdf_file.cut(0);
|
|
ok = xvt_print_start_thread(main_loop_callback, (long)this) != 0;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TBook::export_pdf(TFilename& filename, bool signature)
|
|
{
|
|
bool ok = (pages() > 0) && main_app().has_module(RSAUT); // Controllo paranoico dei permessi
|
|
if (ok)
|
|
{
|
|
// Evita problemi di aggiornamento del pdf: deve sempre rigenerarlo!
|
|
if (filename.exist() && !filename.fremove())
|
|
return cantwrite_box(filename);
|
|
|
|
_pdf_file = filename;
|
|
_pagefrom = 1;
|
|
_pageto = 0;
|
|
_copies = 1;
|
|
ok = xvt_print_start_thread(main_loop_callback, (long)this) != 0;
|
|
if (ok)
|
|
ok = fsize(filename) > 0;
|
|
if (ok && signature && main_app().has_module(FDAUT)) // Controllo paranoico dei permessi
|
|
{
|
|
char outfile[_MAX_PATH] = "";
|
|
if (xvt_sign_file(filename, outfile) && filename != outfile)
|
|
{
|
|
filename.fremove(); // Sbatto via il documento originale non firmato
|
|
filename = outfile;
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
case 'X':
|
|
case 'x':
|
|
ok = export_excel(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(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);
|
|
|
|
// gestione 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 fileprinter:
|
|
case exportprinter:
|
|
{
|
|
TFilename f = printer().get_export_file();
|
|
ok = export_text(f, false);
|
|
if (ok)
|
|
xvt_sys_goto_url(f, "open");
|
|
}
|
|
break;
|
|
case acrobatprinter:
|
|
{
|
|
TFilename f; f.tempdir(); f.add("tmp.pdf");
|
|
if (export_pdf(f, false))
|
|
{
|
|
printer().acrobatically_print_pdf(f);
|
|
f.fremove();
|
|
}
|
|
}
|
|
break;
|
|
default: ok = print(); break;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
TBook::TBook(const char* name)
|
|
: _out(NULL), _is_temporary(false), _max_frame(0,0),
|
|
_pages(0), _page(0), _rcd(NULL), _printwin(NULL), _page_is_open(false)
|
|
{
|
|
_file = name;
|
|
if (_file.blank())
|
|
{
|
|
_file.temp("rep", "rap");
|
|
_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();
|
|
virtual void get_txt_rct(RCT& r) const;
|
|
|
|
public:
|
|
TPrintind(long n, const char* msg);
|
|
};
|
|
|
|
void TPrintind::get_txt_rct(RCT& r) const
|
|
{
|
|
TProgind::get_txt_rct(r);
|
|
r.right -= 48; // Lascia posto all'animazione
|
|
}
|
|
|
|
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.top - img.height() - 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 TReport_rct& rr)
|
|
{
|
|
TReport_rct ro(rr); ro += _delta; // Applico offset al rettangolo logico
|
|
TBook::define_frame(ro); // Salvo le coordinate a 720 DPI
|
|
}
|
|
|
|
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)
|
|
{
|
|
const TReport_pnt& pos = page_background->pos();
|
|
_delta.x = pos.x; _delta.y = pos.y;
|
|
print_section(*page_background);
|
|
_delta.reset();
|
|
}
|
|
|
|
if (_rep_page == 1)
|
|
{
|
|
const long height = print_section('H', 1);
|
|
if (height > 0)
|
|
{
|
|
_delta.y += height;
|
|
if (_delta.y >= _logical_foot_pos) // Copertina enorme?
|
|
{
|
|
close_page();
|
|
return open_page();
|
|
}
|
|
}
|
|
}
|
|
|
|
TReport_section* page_head = _report->find_section('H', 0);
|
|
if (page_head != NULL && (_rep_page > 1 || !page_head->hidden_if_needed()))
|
|
{
|
|
const TReport_pnt& pos = page_head->pos();
|
|
_delta.x += pos.x; _delta.y += pos.y;
|
|
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 = false;
|
|
if (_page_break_allowed) // Calcolo un eventuale salto pagina
|
|
{
|
|
page_break = rs.page_break(); // Sezione con 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 += _page_size.y;
|
|
else
|
|
h += next_section.compute_size().y;
|
|
}
|
|
|
|
const long space_left = (_logical_foot_pos - _delta.y)/100*100; // 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;
|
|
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 fosse 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() && (pr.printtype() < exportprinter);
|
|
if (save_profile && !pr.manual_setup())
|
|
{
|
|
const TString profile = rep.filename().name();
|
|
const TString& rep_printer = ini_get_string(CONFIG_STAMPE, profile, "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 TSize siz = page_size();
|
|
const TSize 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)
|
|
{
|
|
const TString_array& variables = rex->variables();
|
|
FOR_EACH_ARRAY_ROW(variables, v, name) if (!name->starts_with("#PARENT"))
|
|
{
|
|
const TReport_field* fld = _report->field(*name);
|
|
if (fld != NULL)
|
|
{
|
|
const TVariant& val = fld->get();
|
|
rex->set_var(*name, val);
|
|
}
|
|
}
|
|
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))
|
|
{
|
|
TFilename msk = _report->filename().name();
|
|
msk.ext("msk");
|
|
if (_report->use_mask() && msk.custom_path())
|
|
{
|
|
TMask m(msk);
|
|
_report->report2mask(m);
|
|
eminem->mask2report(m);
|
|
}
|
|
else
|
|
{
|
|
TRecordset* mainset = _report->recordset();
|
|
TRecordset* recset = eminem->recordset();
|
|
if (mainset && recset)
|
|
{
|
|
const TString_array& vars = mainset->variables();
|
|
FOR_EACH_ARRAY_ROW(vars, i, name)
|
|
recset->set_var(*name, mainset->get_var(*name));
|
|
if (main_app().name().starts_with("ve1"))
|
|
{
|
|
recset->set_var("#PROVV", mainset->get("PROVV"));
|
|
recset->set_var("#ANNO", mainset->get("ANNO"));
|
|
recset->set_var("#CODNUM", mainset->get("CODNUM"));
|
|
recset->set_var("#NDOC", mainset->get("NDOC"));
|
|
}
|
|
}
|
|
}
|
|
|
|
TReport* rep = _report; // Salvo variabile globale
|
|
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; msg << TR("Report ") << _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 || 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, bool signature)
|
|
{
|
|
TFilename n = repname;
|
|
if (n.blank() && _report != NULL)
|
|
{
|
|
n = _report->filename().name();
|
|
n.ext("");
|
|
}
|
|
return TBook::archive(n, signature);
|
|
}
|
|
|
|
|
|
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)
|
|
{ }
|