#include #include #include #include #include #include "ba8201.h" #include "ba8303.h" /////////////////////////////////////////////////////////// // TPrint_preview_window /////////////////////////////////////////////////////////// class TPrint_preview_window : public TField_window { TPage_printer* _printer; word _page, _last; int _zoom; protected: void page_select(); void popup_menu(EVENT* ep); virtual void handler(WINDOW win, EVENT* ep); virtual void update(); virtual bool on_key(KEY k); public: virtual PNT log2dev(long lx, long ly) const; void set_printer(TPage_printer* printer) { _printer = printer; } TPrint_preview_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner, TPage_printer* printer); }; PNT TPrint_preview_window::log2dev(long lx, long ly) const { PNT pnt; pnt.h = short(lx * _zoom / 1000); pnt.v = short(ly * _zoom / 1000); const TPoint orig = origin(); pnt.h -= short(orig.x); pnt.v -= short(orig.y); return pnt; } void TPrint_preview_window::update() { _printer->print_page(_page); } #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 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 = true; 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 = _last == 0 || _page < _last; menu[3].tag = POPUP_LAST; menu[3].text = (char*)TR("Ultima"); menu[3].enabled = true; 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 > 75; 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("Ricerca", 1, 28, 4); m.add_number(101, 0, "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 (_last > 0 && _page > _last) _page = _last; } } void TPrint_preview_window::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_MOUSE_DOWN: if (ep->v.mouse.button != 0) popup_menu(ep); break; case E_COMMAND: { bool processed = true; switch(ep->v.cmd.tag) { case POPUP_FIRST : _page = 1; break; case POPUP_PREV : if (_page > 1) _page--; break; case POPUP_SEARCH : page_select(); break; case POPUP_NEXT : if (_last == 0 || _page < _last) _page++; break; case POPUP_LAST : if (_last == 0) { _printer->print_page(9999); _last = _printer->last_printed_page(); } _page = _last; break; case POPUP_ZOOMIN : if (_zoom < 300) { _zoom += 25; } break; case POPUP_ZOOMOUT: if (_zoom > 75) { _zoom -= 25; } break; default:processed = false; break; } if (processed) force_update(); } break; default: break; } TField_window::handler(win, ep); } 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_LEFT : dispatch_e_menu(win(), POPUP_PREV); break; case K_RIGHT : dispatch_e_menu(win(), POPUP_NEXT); break; case K_END: case K_LEND : dispatch_e_menu(win(), POPUP_LAST); break; default : 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, TPage_printer* printer) : TField_window(x, y, dx, dy, parent, owner), _printer(printer), _page(1), _last(0), _zoom(100) { const TPoint ps = printer->page_size(); set_scroll_max(ps.x/4, ps.y/4); } /////////////////////////////////////////////////////////// // TPrint_preview_field /////////////////////////////////////////////////////////// class TPrint_preview_field : public TWindowed_field { TPage_printer* _printer; protected: virtual TField_window* create_window(int x, int y, int dx, int dy, WINDOW parent); public: TPrint_preview_field(TMask* m, TPage_printer* printer) : TWindowed_field(m), _printer(printer) { } }; 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, _printer); } /////////////////////////////////////////////////////////// // TPreview_mask /////////////////////////////////////////////////////////// class TPreview_mask : public TAutomask { TPage_printer* _printer; 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); public: TPreview_mask(TPage_printer* printer); }; 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 : dispatch_e_char(_printer->win(), k); return true; default: break; } return TAutomask::on_key(k); } 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(_printer->win(), POPUP_FIRST); break; case DLG_PREVREC : dispatch_e_menu(_printer->win(), POPUP_PREV); break; case DLG_FINDREC : dispatch_e_menu(_printer->win(), POPUP_SEARCH);break; case DLG_NEXTREC : dispatch_e_menu(_printer->win(), POPUP_NEXT); break; case DLG_LASTREC : dispatch_e_menu(_printer->win(), POPUP_LAST); break; default: break; } } return true; } TMask_field* TPreview_mask::parse_field(TScanner& scanner) { if (scanner.token().starts_with("PR")) return new TPrint_preview_field(this, _printer); return TAutomask::parse_field(scanner); } TPreview_mask::TPreview_mask(TPage_printer* printer) : _printer(printer) { read_mask("ba8303", 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); } } } } /////////////////////////////////////////////////////////// // TPage_printer /////////////////////////////////////////////////////////// const char* TPage_printer::form_name() const { return printer().get_form_name(); } const char* TPage_printer::font_name() const { return printer().fontname(); } int TPage_printer::font_size() const { return printer().get_char_size(); } bool TPage_printer::ask_pages() { if (_pageto <= 0) _pageto = pages(); TPrinter& p = printer(); TMask msk("bagn003"); msk.set(F_PRINTER, p.printername()); msk.set(F_FORM, form_name()); msk.set(F_FONT, font_name()); msk.set(F_SIZE, font_size()); msk.set(F_ISGRAPHICS, p.isgraphics() ? "X" : ""); msk.set(F_FROMPAGE, _pagefrom); msk.set(F_TOPAGE, _pageto); msk.set(F_COPIES, _copies); const bool ok = msk.run() == K_ENTER; if (ok) { _copies = msk.get_int(F_COPIES); _pagefrom = msk.get_int(F_FROMPAGE); _pageto = msk.get_int(F_TOPAGE); if (_pageto < _pagefrom) _pageto = 0; } return ok; } bool TPage_printer::main_loop() { TPrinter& p = printer(); _rcd = p.get_printrcd(); if (!xvt_print_is_valid(_rcd)) return TRUE; // aborted WINDOW prwin = xvt_print_create_win(_rcd, (char*)(const char*)form_name()); if (prwin == NULL_WIN) return TRUE; // aborted set_win(prwin); xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _rcd, &_ph, &_pw, &_pvr, &_phr); bool ok = true; for (word c = 0; c < _copies && ok; c++) { _page = 0; ok = print_loop(); } xvt_vobj_destroy(prwin); set_win(NULL_WIN); return ok; } bool TPage_printer::page_in_range() const { if (_page < _pagefrom) return false; return _pageto < _pagefrom || _page <= _pageto; } PNT TPage_printer::log2dev(long lx, long ly) const { if (preview_mode()) return _preview_window->log2dev(lx, ly); const PNT p = { short(ly), short(lx) }; return p; } TPoint TPage_printer::dev2log(const PNT& pnt) const { CHECK(0, "dev2log: Pure virtual funtion call"); const TPoint p; return p; } bool TPage_printer::open_page() { _page++; if (page_in_range()) { if (print_mode()) _page_is_open = xvt_print_open_page(_rcd) != 0; else _page_is_open = true; } else _page_is_open = false; return _page_is_open; } bool TPage_printer::close_page() { const bool was_open = _page_is_open; if (was_open) { if (print_mode()) xvt_print_close_page(_rcd); _page_is_open = false; } return was_open; } static BOOLEAN main_loop_callback(long jolly) { TPage_printer* pp = (TPage_printer*)jolly; return pp->main_loop(); } bool TPage_printer::print() { bool ok = ask_pages(); if (ok) ok = xvt_print_start_thread(main_loop_callback, long(this)) == FALSE; return ok; } void TPage_printer::print_page(word page) { _pagefrom = _pageto = page; _page = 0; print_loop(); } bool TPage_printer::preview() { TPrinter& p = printer(); _rcd = p.get_printrcd(); if (!xvt_print_is_valid(_rcd)) return error_box("Stampante non valida"); xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _rcd, &_ph, &_pw, &_pvr, &_phr); if (_ph <= 0) return error_box("Risoluzione stampante NULLA"); _preview_mask = new TPreview_mask(this); TPrint_preview_field& pf = (TPrint_preview_field&)_preview_mask->field(DLG_USER); _preview_window = &pf.win(); set_win(_preview_window->win()); _pagefrom = _pageto = _page = 1; const KEY key = _preview_mask->run(); set_win(NULL_WIN); delete _preview_mask; _preview_mask = NULL; if (key == K_INS) print(); return true; } TPoint TPage_printer::page_size() const { return TPoint(_pw, _ph); } TPoint TPage_printer::page_res() const { TPoint pt(_phr, _pvr); return pt; } TPage_printer::TPage_printer() : _pagefrom(1), _pageto(0), _copies(1), _preview_mask(NULL) { _pixmap = true; // Fondamentale!!! } TPage_printer::~TPage_printer() { } /////////////////////////////////////////////////////////// // TReport_printer /////////////////////////////////////////////////////////// const char* TReport_printer::form_name() const { return _report.filename(); } const char* TReport_printer::font_name() const { return _report.font().name(); } int TReport_printer::font_size() const { return _report.font().size(); } PNT TReport_printer::log2dev(long lx, long ly) const { const TPoint res = page_res(); const double cx = (double)res.x / (double)_report.cpi(); const double cy = (double)res.y / (double)_report.lpi(); const long x = long((lx + _delta.x) * cx / 100.0); const long y = long((ly + _delta.y) * cy / 100.0); return TPage_printer::log2dev(x, y); // Useful for preview mode } long TReport_printer::print_section(char type, int level) { long h = 0; TReport_section* rs = _report.find_section(type, level); if (rs != NULL) h = print_section(*rs); return h; } bool TReport_printer::open_page() { const bool ok = TPage_printer::open_page(); _report.set_curr_page(_page); _delta.x = _delta.y = 0; _page_break_allowed = false; if (ok && preview_mode()) // Clear page needed { clear(COLOR_WHITE); const int max = 192; const int k = 100; for (int i = 1; i < max; i++) { set_pen((i%10) ? MAKE_COLOR(232,232,232) : COLOR_LTGRAY); line(0, i*k, max*k, i*k); line(i*k, 0, i*k, max*k); } } print_section('B', 0); if (_page == 1) _delta.y += print_section('H', 1); TReport_section* page_head = _report.find_section('H', 0); if (page_head != NULL && (_page > 1 || !page_head->hidden_if_needed())) _delta.y += print_section(*page_head); return ok; } bool TReport_printer::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 = 0; _delta.y = _logical_foot_pos; print_section(*page_foot); } } return TPage_printer::close_page(); } long TReport_printer::print_section(TReport_section& rs) { rs.load_fields(); rs.execute_prescript(); const long height = rs.compute_size().y; // Compute size after the initilization script! if (height > 0) // Has some visible fields { bool page_break = _page_break_allowed && rs.page_break(); if (!page_break) page_break = (_delta.y + height > _logical_foot_pos); if (page_break && rs.level() > 0) // Avoid recursion { close_page(); open_page(); } if (_page_is_open) rs.draw(*this, rdm_print); if (rs.level() > 0) // Ho stampa qualcosa che non sia lo sfondo! _page_break_allowed = true; } rs.execute_postscript(); return height; } bool TReport_printer::print_loop() { if (_report.recordset() == NULL) return false; TRecordset& rex = *_report.recordset(); if (rex.items() <= 0) return false; const TPoint siz = page_size(); const TPoint res = page_res(); const double pollici_pagina = (double)siz.y / (double)res.y; const double righe_pagina = pollici_pagina * _report.lpi(); _logical_page_height = long(righe_pagina*100.0); const long logical_footer_height = _report.section('F',0).compute_size().y; _logical_foot_pos = _logical_page_height - logical_footer_height; _report.unmap_font(); // Gestire bene le riscalature 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'); _is_last_page = false; open_page(); bool aborted = false; for (bool ok = rex.move_to(0); ok; ok = rex.move_next()) { if (_pageto >= _pagefrom && _page > _pageto) // out of range { aborted = true; break; } if (max_group >= 2) // Gestione raggruppamenti { int 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); newgroup.add(var.as_string(), g); if (newgroup.row(g) != oldgroup.row(g) || rex.current_row() == 0) changed = g; } if (changed) { oldgroup = newgroup; if (rex.current_row() > 0) { for (int g = 2; g <= changed; g++) _delta.y += print_section('F', g); } for (int g = changed; g >= 2 ; g--) _delta.y += print_section('H', g); } } for (int b = 1; b <= max_body; b++) _delta.y += print_section('B', b); } if (!aborted) { if (max_group >= 2) // Devo stampare tutte le code dei raggrupamenti { for (int g = 2; g <= max_group; g++) _delta.y += print_section('F', g); } if (rex.eof()) print_section('F', 1); _is_last_page = true; close_page(); } _lastprinted = _page; return true; }