Files correlati : Ricompilazione Demo : [ ] Commento :eliminato pernicioso inconveniente che impediva ai poveri report di sfruttare l'intero rettangolo di stampa di un campo di testo. Aggiunto il metodo log2pix che permette di considerare l'effettiva grandezza del campo in stampa. git-svn-id: svn://10.65.10.50/trunk@14313 c028cbd2-c16b-5b4b-a496-9718f37d4682
2406 lines
59 KiB
C++
Executable File
2406 lines
59 KiB
C++
Executable File
#include <automask.h>
|
|
#include <colors.h>
|
|
#include <config.h>
|
|
#include <defmask.h>
|
|
#include <diction.h>
|
|
#include <printer.h>
|
|
#include <progind.h>
|
|
#include <reprint.h>
|
|
#include <statbar.h>
|
|
#include <urldefid.h>
|
|
|
|
#include <bagn003.h>
|
|
#include <bagn009.h>
|
|
|
|
static bool _print_aborted = false;
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Utility
|
|
///////////////////////////////////////////////////////////
|
|
|
|
static void advanced_draw_justified_text_line(TWindow& win, 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++;
|
|
|
|
WINDOW w = win.win();
|
|
|
|
// 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(TWindow& win, const char* text, const RCT& r, char halign, char valign)
|
|
{
|
|
WINDOW w = win.win();
|
|
|
|
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;
|
|
}
|
|
|
|
RCT orig; xvt_dwin_get_clip(w, &orig);
|
|
const bool restore_clip = !xvt_rect_is_empty(&orig);
|
|
if (restore_clip)
|
|
{
|
|
RCT clipper;
|
|
xvt_rect_intersect(&clipper, &orig, (RCT*)&r);
|
|
xvt_dwin_set_clip(w, (RCT*)&clipper);
|
|
|
|
}
|
|
else
|
|
xvt_dwin_set_clip(w, (RCT*)&r);
|
|
|
|
if (halign == 'J')
|
|
advanced_draw_justified_text_line(win, text, x, y, dx);
|
|
else
|
|
xvt_dwin_draw_text(w, x, y, text, -1);
|
|
|
|
if (restore_clip)
|
|
xvt_dwin_set_clip(w, &orig);
|
|
else
|
|
xvt_dwin_set_clip(w, NULL);
|
|
}
|
|
|
|
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(TWindow& 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.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.blank())
|
|
{
|
|
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';
|
|
advanced_draw_text_line(win, line, rctline, ha, 'T');
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (halign == 'J') halign = 'L';
|
|
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;
|
|
|
|
virtual void handler(WINDOW win, EVENT* ep);
|
|
virtual void update();
|
|
virtual bool on_key(KEY k);
|
|
|
|
void update_scroll_range();
|
|
void do_scroll(int kx, int ky);
|
|
|
|
public:
|
|
virtual PNT log2dev(long lx, long ly) 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();
|
|
};
|
|
|
|
PNT TPrint_preview_window::log2dev(long lx, long ly) const
|
|
{
|
|
PNT pnt = { short(lx), short(ly) };
|
|
|
|
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()
|
|
{
|
|
PNT pnt = { 0, 0 };
|
|
|
|
const TPoint res = _book->page_res();
|
|
if (res.x > 0 && res.y > 0) // Should always be true :-)
|
|
{
|
|
const TPoint size = _book->page_size();
|
|
pnt.h = short(size.x * _zoom / res.x);
|
|
pnt.v = short(size.y * _zoom / res.y);
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
pnt.h -= rct.right; if (pnt.h < 0) pnt.h = 0;
|
|
pnt.v -= rct.bottom; if (pnt.v < 0) pnt.v = 0;
|
|
}
|
|
|
|
update_thumb(0, 0);
|
|
set_scroll_max(pnt.h, pnt.v);
|
|
}
|
|
|
|
void TPrint_preview_window::update()
|
|
{
|
|
clear(MASK_BACK_COLOR);
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
|
|
const TPoint size = _book->page_size();
|
|
const PNT pag = log2dev(size.x, size.y);
|
|
if (pag.h < rct.right) rct.right = pag.h;
|
|
if (pag.v < rct.bottom) rct.bottom = pag.v;
|
|
hide_pen();
|
|
set_brush(COLOR_WHITE);
|
|
xvt_dwin_draw_rect(win(), &rct); // Disegna foglio bianco
|
|
|
|
if (_grid)
|
|
{
|
|
const TPoint res = _book->page_res();
|
|
const int lpi = _book->lpi();
|
|
for (int i = 1; lpi > 0; i++)
|
|
{
|
|
set_pen(i%lpi ? MAKE_COLOR(232,232,255) : MAKE_COLOR(255,192,255));
|
|
const short y = 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 ? MAKE_COLOR(232,232,255) : MAKE_COLOR(255,192,255));
|
|
const short x = j * res.x / cpi;
|
|
if (x > size.x)
|
|
break;
|
|
line(x, 0, x, (short)size.y);
|
|
}
|
|
}
|
|
|
|
_book->print_page(*this, _page);
|
|
|
|
TString80 str; str.format(FR("Pagina %u di %u"), _page, _book->pages());
|
|
statbar_set_title(TASK_WIN, str);
|
|
}
|
|
|
|
#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 < 300;
|
|
menu[6].tag = POPUP_ZOOMOUT; menu[6].text = (char*)TR("Zoom -"); menu[6].enabled = _zoom > 50;
|
|
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, TR("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 > 50) { _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;
|
|
update_scroll_range();
|
|
|
|
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:
|
|
void export_text();
|
|
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' :
|
|
dispatch_e_char(_pvf->win().win(), k);
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return TAutomask::on_key(k);
|
|
}
|
|
|
|
void TPreview_mask::handler(WINDOW win, EVENT* ep)
|
|
{
|
|
// Riflessione eventi di scroll
|
|
if (ep->type == E_HSCROLL || ep->type == E_VSCROLL)
|
|
::dispatch_event(_pvf->win().win(), *ep, false);
|
|
|
|
TAutomask::handler(win, ep);
|
|
}
|
|
|
|
void TPreview_mask::export_text()
|
|
{
|
|
TFilename n; n.temp(NULL, "txt");
|
|
if (_book->export_text(n))
|
|
xvt_sys_goto_url(n, "open");
|
|
}
|
|
|
|
bool TPreview_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
|
{
|
|
if (e == fe_button)
|
|
{
|
|
switch (o.dlg())
|
|
{
|
|
case DLG_FIRSTREC: dispatch_e_menu(_pvf->win().win(), POPUP_FIRST); break;
|
|
case DLG_PREVREC : dispatch_e_menu(_pvf->win().win(), POPUP_PREV); break;
|
|
case DLG_FINDREC : dispatch_e_menu(_pvf->win().win(), POPUP_SEARCH);break;
|
|
case DLG_NEXTREC : dispatch_e_menu(_pvf->win().win(), POPUP_NEXT); break;
|
|
case DLG_LASTREC : dispatch_e_menu(_pvf->win().win(), POPUP_LAST); break;
|
|
case DLG_EDIT : export_text(); break;
|
|
default: break;
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
read_mask("bagn008", 0, -1);
|
|
set_handlers();
|
|
|
|
int pos = id2pos(DLG_FINDREC);
|
|
if (pos >= 0 && id2pos(DLG_FIRSTREC) >= 0) //se e' un bottone pentapartito...
|
|
{
|
|
TButton_field& f_find = (TButton_field &)fld(pos);
|
|
RCT rct_base; f_find.get_rect(rct_base);
|
|
const int bwidth = (rct_base.right - rct_base.left);
|
|
const int bheight = (rct_base.bottom - rct_base.top);
|
|
if (bwidth > 3*bheight/2) // Controllo se ho gia' ridimensionato i bottoni in precedenza
|
|
{
|
|
int bx = bwidth / 3;
|
|
int by = bheight / 2;
|
|
|
|
RCT r = rct_base; r.left += bx-2; r.right -= bx-2;
|
|
f_find.set_rect(r); // Ridimensiona il bottone centrale di ricerca
|
|
|
|
bx += 5; by += 3; // Aggiusta dimensioni bottoni sussidiari
|
|
|
|
pos = id2pos(DLG_FIRSTREC);
|
|
if (pos >= 0)
|
|
{
|
|
r = rct_base; r.top = r.bottom - by; r.right = r.left + bx;
|
|
fld(pos).set_rect(r);
|
|
}
|
|
pos = id2pos(DLG_PREVREC);
|
|
if (pos >= 0)
|
|
{
|
|
r = rct_base; r.bottom = r.top + by; r.right = r.left + bx;
|
|
fld(pos).set_rect(r);
|
|
}
|
|
pos = id2pos(DLG_NEXTREC);
|
|
if (pos >= 0)
|
|
{
|
|
r = rct_base; r.bottom = r.top + by; r.left = r.right - bx;
|
|
fld(pos).set_rect(r);
|
|
}
|
|
pos = id2pos(DLG_LASTREC);
|
|
if (pos >= 0)
|
|
{
|
|
r = rct_base; r.top = r.bottom - by; r.left = r.right - bx;
|
|
fld(pos).set_rect(r);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TWindow_printer
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TWindow_printer : public TWindow
|
|
{
|
|
long _pvr, _phr;
|
|
|
|
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 = (x * _phr) / BOOKDPI;
|
|
ptdev.v = (y * _pvr) / BOOKDPI;
|
|
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)
|
|
{
|
|
long ph, pw;
|
|
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)
|
|
_out = new ofstream(_file);
|
|
|
|
_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;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
const TFixed_string str(txt);
|
|
if (!str.blank())
|
|
{
|
|
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)
|
|
{
|
|
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, name, page, 'C', 'T');
|
|
|
|
const TPoint pr = page_res();
|
|
rect.deflate(pr.x/2, pr.y/2);
|
|
win.log2dev(rect, page);
|
|
|
|
TString4 ext = name.right(3); ext.lower();
|
|
if (ext == "bmp" || ext == "gif" || ext == "jpg" || ext == "peg")
|
|
{
|
|
const TImage* img = _images.image(name);
|
|
if (img != NULL)
|
|
{
|
|
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();
|
|
}
|
|
|
|
const int buffer_size = 1024;
|
|
TString str(buffer_size);
|
|
char* buffer = str.get_buffer();
|
|
|
|
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(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(win, stringona, rct, _horizontal_alignment, _vertical_alignment);
|
|
win.set_color(dct.fore_color, dct.back_color);
|
|
xvt_dwin_set_font(w, oldfont);
|
|
xvt_font_destroy(newfont);
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
if (str.starts_with("<brush "))
|
|
{
|
|
COLOR col = COLOR_BLACK;
|
|
PAT_STYLE pat = PAT_SOLID;
|
|
sscanf(str, "<brush color=%u pattern=%u />", &col, &pat);
|
|
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 "))
|
|
{
|
|
long x, y, dx, dy;
|
|
sscanf(str, "<frame x=%ld y=%ld dx=%ld dy=%ld />", &x, &y, &dx, &dy);
|
|
_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(win, str, rct, _horizontal_alignment, _vertical_alignment);
|
|
continue;
|
|
}
|
|
if (str.starts_with("<pen "))
|
|
{
|
|
COLOR col = COLOR_BLACK;
|
|
int width = 0;
|
|
PEN_STYLE style = P_SOLID;
|
|
sscanf(str, "<pen color=%u width=%d style=%u />", &col, &width, &style);
|
|
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 == "<text>")
|
|
{
|
|
paragrafo.destroy();
|
|
while (!ifs.eof())
|
|
{
|
|
ifs.getline(buffer, str.size());
|
|
if (str == "</text>")
|
|
break;
|
|
paragrafo.add(str);
|
|
}
|
|
advanced_draw_paragraph(win, paragrafo, rct,
|
|
_horizontal_alignment, _vertical_alignment,
|
|
default_10row_height);
|
|
|
|
continue;
|
|
}
|
|
if (str.starts_with("<text_align "))
|
|
{
|
|
sscanf(str, "<text_align horizontal=%c vertical=%c />",
|
|
&_horizontal_alignment, &_vertical_alignment);
|
|
continue;
|
|
}
|
|
if (str.starts_with("<text_color"))
|
|
{
|
|
COLOR fore, back;
|
|
int opaque;
|
|
sscanf(str, "<text_color fore=%u back=%u opaque=%d />", &fore, &back, &opaque);
|
|
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) const
|
|
{
|
|
TString str(1024);
|
|
char* buffer = str.get_buffer();
|
|
|
|
ifstream ifs(_file);
|
|
ofstream ofs(fname);
|
|
|
|
TString_array page;
|
|
int row, col, wid, hei;
|
|
|
|
const TPoint res = page_res();
|
|
|
|
while (!ifs.eof())
|
|
{
|
|
ifs.getline(buffer, str.size());
|
|
|
|
if (str.starts_with("<frame "))
|
|
{
|
|
long x, y, dx, dy;
|
|
sscanf(str, "<frame x=%ld y=%ld dx=%ld dy=%ld />", &x, &y, &dx, &dy);
|
|
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(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 "))
|
|
{
|
|
sscanf(str, "<text_align horizontal=%c vertical=%c />",
|
|
&_horizontal_alignment, &_vertical_alignment);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TBook::init()
|
|
{
|
|
if (!is_pdf())
|
|
{
|
|
_rcd = printer().get_printrcd();
|
|
}
|
|
else
|
|
{
|
|
int intSize;
|
|
_rcd = xvt_print_create_by_name(&intSize, XVT_PDF_PRINTER_NAME);
|
|
}
|
|
|
|
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"));
|
|
|
|
_ph = _ph * BOOKDPI / _pvr;
|
|
_pw = _pw * BOOKDPI / _phr;
|
|
_pvr = _phr = BOOKDPI;
|
|
|
|
bool ok = true;
|
|
|
|
if (_pvr < 96 || _phr < 96) // Risoluzione minima di Acrobat Writer
|
|
{
|
|
ok = yesno_box(FR("Stampante obsoleta o non adeguatamente configurata:\n"
|
|
"Risoluzione %ldx%ld. Continuare ugualmente?"), _phr, _pvr);
|
|
}
|
|
|
|
if (ok)
|
|
{
|
|
if (_printwin != NULL)
|
|
delete _printwin;
|
|
_printwin = new TWindow_printer(_rcd, _pdf_file);
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
bool TBook::main_loop()
|
|
{
|
|
_print_aborted = true;
|
|
if (!init())
|
|
return false;
|
|
|
|
if (_pageto < _pagefrom)
|
|
_pageto = pages();
|
|
|
|
_print_aborted = false;
|
|
for (size_t c = 0; c < _copies && !_print_aborted; c++)
|
|
{
|
|
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;
|
|
}
|
|
|
|
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, size_t 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_ISGRAPHICS, p.isgraphics() ? "X" : "");
|
|
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);
|
|
xvt_print_start_thread(main_loop_callback, (long)this);
|
|
return true;
|
|
}
|
|
|
|
bool TBook::print_to_pdf(size_t pagefrom, size_t pageto, size_t copies)
|
|
{
|
|
if (pages() <= 0)
|
|
return false;
|
|
|
|
if (pagefrom == 0)
|
|
{
|
|
TPrinter& p = printer();
|
|
TMask msk("bagn009");
|
|
msk.set(F_FNAMEPDF, "");
|
|
msk.set(F_FONT, p.fontname());
|
|
msk.set(F_SIZE, p.get_char_size());
|
|
|
|
msk.set(F_FROMPAGE, 1);
|
|
msk.set(F_TOPAGE, pages());
|
|
if (msk.run() == K_ENTER)
|
|
{
|
|
_copies = 1;
|
|
_pagefrom = msk.get_int(F_FROMPAGE);
|
|
_pageto = msk.get_int(F_TOPAGE);
|
|
_pdf_file = msk.get(F_DNAMEPDF);
|
|
_pdf_file.add(msk.get(F_FNAMEPDF));
|
|
_pdf_file.ext(".pdf");
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
_pagefrom = pagefrom;
|
|
_pageto = pageto;
|
|
_copies = copies;
|
|
_pdf_file = "campo.pdf";
|
|
}
|
|
|
|
xvt_print_start_thread(main_loop_callback, (long)this);
|
|
return true;
|
|
}
|
|
|
|
bool TBook::preview()
|
|
{
|
|
TPreview_mask msk(this);
|
|
const KEY k = msk.run();
|
|
switch (k)
|
|
{
|
|
case K_QUIT:
|
|
break;
|
|
case 'P':
|
|
print_to_pdf();
|
|
break;
|
|
default:
|
|
print();
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TBook::print_or_preview()
|
|
{
|
|
bool ok = true;
|
|
switch (printer().printtype())
|
|
{
|
|
case screenvis:
|
|
ok = preview();
|
|
break;
|
|
case exportprinter:
|
|
ok = export_text(printer().get_export_file());
|
|
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),
|
|
_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()
|
|
{
|
|
if (_out != NULL)
|
|
{
|
|
_out->close();
|
|
delete _out;
|
|
if (_is_temporary)
|
|
xvt_fsys_removefile(_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)
|
|
{
|
|
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().blank())
|
|
{
|
|
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)
|
|
{
|
|
// Controlla orientamento della carta prima di inizializzare
|
|
const int report_orientation = rep.orientation();
|
|
if (report_orientation > 0)
|
|
{
|
|
PRINT_RCD* rcd = printer().get_printrcd();
|
|
if (xvt_print_is_valid(rcd))
|
|
{
|
|
long ph, pw, phr, pvr;
|
|
xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, rcd, &ph, &pw, &phr, &pvr);
|
|
const int priter_orientation = ph > pw ? 1 : 2;
|
|
if (report_orientation != priter_orientation)
|
|
{
|
|
// Scambia orientamento della carta
|
|
xvt_app_escape(XVT_ESC_SET_PRINTER_INFO, rcd, &pw, &ph, NULL, NULL);
|
|
// I parametri verranno riletti dalla TBook::init()
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
if (rex->items() <= 0)
|
|
return true;
|
|
|
|
TString msg = TR("Elaborazione report");
|
|
msg << ' ' << _report->filename();
|
|
|
|
TProgind* pi = NULL;
|
|
if (progind)
|
|
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_to(0);
|
|
|
|
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)
|
|
{
|
|
pi->addstatus(1);
|
|
if (pi->iscancelled())
|
|
_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::print(size_t pagefrom, size_t pageto, size_t copies)
|
|
{
|
|
if (pages() <= 0)
|
|
return false;
|
|
|
|
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());
|
|
}
|
|
msk.set(F_ISGRAPHICS, p.isgraphics() ? "X" : "");
|
|
msk.set(F_FROMPAGE, 1);
|
|
msk.set(F_TOPAGE, page());
|
|
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::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)
|
|
{ }
|