#include #include #include #include #include #include #include #include #include #include #include #include #include #include HIDDEN TPrinter* _printer = NULL; /////////////////////////////////////////////////////////// // Maschera impostazione stampante (fatta come si deve dopo 10 anni!) /////////////////////////////////////////////////////////// class TPrinter_setup_mask : public TAutomask { private: bool _skip_events; TString _pdev, _font; PRINT_RCD* _pcd; int _pcd_size; bool _pcd_owned; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); int fill_font_list(); void fill_size_list(); public: void set_print_rcd(PRINT_RCD* pcd, int size, bool take_ownership); PRINT_RCD* get_print_rcd(int& size); TPrinter_setup_mask(); virtual ~TPrinter_setup_mask(); }; void TPrinter_setup_mask::set_print_rcd(PRINT_RCD* pcd, int size, bool take_ownership) { if (_pcd != NULL && _pcd_owned) xvt_print_destroy(_pcd); if (pcd == NULL) { _pcd_owned = true; _pcd = xvt_print_create(&_pcd_size); } else { _pcd_owned = take_ownership; _pcd = pcd; _pcd_size = size; } xvt_print_get_name(_pcd, _pdev.get_buffer(), _pdev.size()); } PRINT_RCD* TPrinter_setup_mask::get_print_rcd(int& size) { CHECK(_pcd != NULL && _pcd_size > 0, "Invalid PRINT_RCD"); PRINT_RCD* pcd = _pcd; size = _pcd_size; _pcd_owned = false; _pcd = NULL; _pcd_size = 0; return pcd; } int TPrinter_setup_mask::fill_font_list() { const int MAX_FAMILIES = 256; char* family[MAX_FAMILIES]; const int num_families = (int)xvt_fmap_get_families(_pcd, family, MAX_FAMILIES); TToken_string fn(num_families * 16); for (int i = 0; i < num_families; i++) { fn.add(family[i]); xvt_mem_free(family[i]); } TString oldfont = _font; // Memorizzo il font corrente in quanto poi cambia TList_field& lst = lfield(MSK_FONT); lst.replace_items(fn, fn); // Controlla se il font c'e' ancora if (fn.get_pos(oldfont) < 0) oldfont = fn.get(0); set(MSK_FONT, oldfont, 0x1); return num_families; } void TPrinter_setup_mask::fill_size_list() { const int MAXSIZES = 128; long sizes[MAXSIZES]; BOOLEAN scalable = FALSE; const int num_sizes = (int)xvt_fmap_get_family_sizes(_pcd, _font.get_buffer(), sizes, &scalable, MAXSIZES); TToken_string pn1; if (scalable) { for (int i = 4; i <= 32; i++) pn1.add(i); } else { if (num_sizes > 0) { for (int i = 0; i < num_sizes; i++) pn1.add(sizes[i]); } else pn1.add(printer().get_char_size()); // semper better than nothing } TList_field& lst = lfield(MSK_SIZE); const TString4 old_size = lst.get(); lst.replace_items(pn1, pn1); lst.set(old_size); lst.enable(pn1.items() > 1); } bool TPrinter_setup_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { if (_skip_events) return true; bool ok = true; switch (o.dlg()) { case MSK_DEFAULT: if (fe_modify) { if (o.get().full()) { set_print_rcd(NULL, 0, true); set(MSK_PRINTERS, _pdev, 0x1); } } break; case MSK_PRINTERS: if (fe_modify) { const TString& pdev = o.get(); // Nome stampante corrente if (pdev != _pdev) { TWait_cursor hourglass; int tmp_size = 0; PRINT_RCD* tmp_pcd = xvt_print_create_by_name(&tmp_size, pdev); if (tmp_pcd != NULL) { set_print_rcd(tmp_pcd, tmp_size, true); if (fill_font_list() <= 0) return error_box(TR("Impossibile inizializzare la stampante %s"), (const char*)pdev); } } } break; case MSK_FONT: if (e == fe_modify) { const TString& family = o.get(); if (_font != family) { TWait_cursor hourglass; _font = family; fill_size_list(); } } break; case MSK_SIZE: if (e == fe_modify || e == fe_close) { const int fs = atoi(o.get()); const int ls = 72 / get_int(MSK_LINES); if (fs < ls/2 || fs > 4*ls/3) ok = yesno_box(TR("La dimensione del carattere non e' adeguata all'interlinea\nSi desidera continuare ugualmente?")); } break; case DLG_SETPRINT: if (e == fe_button) { if (xvt_dm_post_page_setup(_pcd)) { // see if user has changed printer // determine name of currently selected printer TString256 name; xvt_print_get_name(_pcd, name.get_buffer(), name.size()); set(MSK_PRINTERS, name, 0x1); on_field_event(lfield(MSK_ORIENTATION), fe_init, 0); } } break; case MSK_ORIENTATION: if (e == fe_init) { long ph, pw; xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _pcd, &ph, &pw, NULL, NULL); o.set(ph > pw ? "1" : "2"); } else if (e == fe_modify || e == fe_close) { long ph, pw; xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _pcd, &ph, &pw, NULL, NULL); const int priter_orientation = ph > pw ? 1 : 2; const int user_orientation = atoi(o.get()); if (user_orientation != priter_orientation) // Scambia orientamento della carta xvt_app_escape(XVT_ESC_SET_PRINTER_INFO, _pcd, &pw, &ph, NULL, NULL); } break; default: break; } return ok; } TPrinter_setup_mask::TPrinter_setup_mask() : TAutomask("bagn001a"), _pcd(NULL), _pcd_size(0), _pcd_owned(false), _pdev(128) { TPrinter& pr = printer(); set(MSK_FILENAME, pr.get_printerfile()); const bool can_save = pr._config == "Printer"; enable(DLG_OK, can_save); if (pr.forced_default_printer()) set_print_rcd(NULL, 0, true); else set_print_rcd(pr._print_rcd, pr._print_rcd_size, false); // Crea la lista delle stampanti TToken_string pn2; SLIST plist = xvt_print_list_devices(); for (SLIST_ELT pitem = xvt_slist_get_first(plist); pitem != NULL; pitem = xvt_slist_get_next(plist, pitem)) { const char* pname = xvt_slist_get(plist, pitem, NULL); pn2.add(pname); } xvt_slist_destroy(plist); _skip_events = true; if (pr._printertype == fileprinter) set(MSK_TYPE, "1"); else if (pr._printertype == screenvis) set(MSK_TYPE, "2"); else if (pr._printertype == acrobatprinter) set(MSK_TYPE, "4"); else set(MSK_TYPE, "0"); TList_field& plst = lfield(MSK_PRINTERS); plst.replace_items(pn2, pn2); // Genera printer list set(MSK_PRINTERS, _pdev); _font = pr._fontname; fill_font_list(); fill_size_list(); set(MSK_FONT, _font); // Fare solo quando la lista e' piena set(MSK_SIZE, pr._ch_size); // Fare solo quando la lista e' piena set(MSK_LINES, pr._lines_per_inch); set(MSK_ISGRAPHICS, pr.isgraphics() ? "X" : ""); set(MSK_DEFAULT, pr.forced_default_printer() ? "X" : ""); TButton_tool& sp = (TButton_tool&)field(DLG_SETPRINT); sp.set_exit_key(0); // Evita chiamate ricorsive all'impostazione stampante _skip_events = false; } TPrinter_setup_mask::~TPrinter_setup_mask() { if (_pcd_owned && _pcd != NULL) { xvt_print_destroy(_pcd); _pcd_owned = false; _pcd = NULL; _pcd_size = 0; } } /////////////////////////////////////////////////////////// // TPrinter /////////////////////////////////////////////////////////// TPrinter& printer() { if (_printer == NULL) _printer = new TPrinter; return *_printer; } void printer_destroy() { if (_printer != NULL) { delete _printer; _printer = NULL; } } // ---------------------------------------------------------------------- // TPrint_intersector // ---------------------------------------------------------------------- // TPrint_intersector: calcola intersezioni tra elementi grafici e // restituisce, riga per riga, i necessari caratteri di fincatura per // finculare in modo carattere // usata da viswin e printwin class TPrint_intersector : public TString_array { const char* _fink; char check_intersection(int x, int y, char ch); void h_line(int x1, int y1, int len); void v_line(int x1, int y1, int len); // caratteri fincazione: l'ho fatto perche' e' inline char f_topleft() const { return _fink[0]; } char f_topmiddle() const { return _fink[1]; } char f_topright() const { return _fink[2]; } char f_botleft() const { return _fink[3]; } char f_botmiddle() const { return _fink[4]; } char f_botright() const { return _fink[5]; } char f_centerleft() const { return _fink[6]; } char f_centermiddle() const { return _fink[7]; } char f_centerright() const { return _fink[8]; } char f_horizontal() const { return _fink[9]; } char f_vertical() const { return _fink[10]; } public: // aggiunge un elemento grafico void add(TGraphic_shape s, int x1, int y1, int x2, int y2); // aggiunge alla stringa passata i necessari caratteri, leggendo // dalla pagina interna const char* get_chars(int line) const; // sbianca tutto void clear(); TPrint_intersector(const char* fink, int pagesize) : TString_array(pagesize) , _fink(fink) {} virtual ~TPrint_intersector() {} }; char TPrint_intersector::check_intersection(int x, int y, char ch) { char a = ' ', b = ' ', c = ' ', d = ' '; if (y > 0 && objptr(y-1) != NULL) b = row(y-1)[x]; if (objptr(y+1) != NULL) d = row(y+1)[x]; if (x > 0) a = row(y)[x-1]; if (x < row(y).len()-1) c = row(y)[x+1]; if (a == ' ' && b == ' ' && c != ' ' && d != ' ') ch = f_topleft(); else if (a == ' ' && b != ' ' && c != ' ' && d == ' ') ch = f_botleft(); else if (a != ' ' && b != ' ' && c == ' ' && d == ' ') ch = f_botright(); else if (a != ' ' && b == ' ' && c == ' ' && d != ' ') ch = f_topright(); else if (a != ' ' && b != ' ' && c == ' ' && d != ' ') ch = f_centerright(); else if (a == ' ' && b != ' ' && c != ' ' && d != ' ') ch = f_centerleft(); else if (a != ' ' && b != ' ' && c != ' ' && d == ' ') ch = f_botmiddle(); else if (a != ' ' && b == ' ' && c != ' ' && d != ' ') ch = f_topmiddle(); else if ((a != ' ' && b != ' ' && c != ' ' && d != ' ') || ((a != ' ' && b == ' ' && c != ' ' && d == ' ') && ch == f_vertical()) || ((a == ' ' && b != ' ' && c == ' ' && d != ' ') && ch == f_horizontal())) ch = f_centermiddle(); return ch; } void TPrint_intersector::h_line(int x1, int y1, int len) { if (objptr(y1) == NULL) { TString* ss = new TString(256, ' '); TArray::add(ss, y1); } TString& s = row(y1); int i; for (i = x1; i < x1+len; i++) s[i] = f_horizontal(); for (i = x1; i < x1+len; i++) s[i] = check_intersection(i, y1, f_horizontal()); } void TPrint_intersector::v_line(int x1, int y1, int len) { int i; for (i = y1; i < y1+len; i++) { if (objptr(i) == NULL) { TString* ss = new TString(256, ' '); TArray::add(ss, i); } row(i)[x1] = f_vertical(); } for (i = y1; i < y1+len; i++) row(i)[x1] = check_intersection(x1, i, f_vertical()); } void TPrint_intersector::add(TGraphic_shape s, int x1, int y1, int x2, int y2) { // rows start at 0 y1 --; y2 --; // columns pure, ma e' possibile che siano gia' 0 se la generazione // e' stata automatica (colonna 1. campo - 1) if (x1 > 0) x1 --; if (x2 > 0) x2 --; switch (s) { case line: if (x1 == x2) // vertical v_line(x1, y1, y2-y1+1); else if (y1 == y2) // horizontal h_line(x1,y1, x2-x1+1); else error_box("Linee oblique non supportate in modalita' testo"); break; case box: h_line(x1, y1, x2-x1+1); h_line(x1, y2, x2-x1+1); v_line(x1, y1, y2-y1+1); v_line(x2, y1, y2-y1+1); break; default: break; } } const char* TPrint_intersector::get_chars(int line) const { if (objptr(line) == NULL) return ""; else return row(line); } void TPrint_intersector::clear() { for (int i = 0; i < items(); i++) { TString* s = (TString*)objptr(i); if (s != NULL) s->spaces(); } } /////////////////////////////////////////////////////////// // TPrint_txt_info /////////////////////////////////////////////////////////// struct TPrint_txt_info { TTextfile* _txt; TFilename _pdf_file; word _copies; word _pagefrom; word _pageto; word _lastpage; bool edit(); bool editpdf(); TPrint_txt_info(TTextfile& txt); }; bool TPrint_txt_info::edit() { TPrinter& p = printer(); TMask msk("bagn003"); msk.set(F_PRINTER, p.printername()); msk.set(F_FORM, p.get_form_name()); msk.set(F_FONT, p.fontname()); msk.set(F_SIZE, p.get_char_size()); msk.set(F_LINES, p.get_lines_per_inch()); msk.set(F_ORIENT, p.is_portrait() ? 1 : 2); msk.set(F_ISGRAPHICS, p.isgraphics()); msk.set(F_FROMPAGE, _pagefrom); msk.set(F_TOPAGE, _lastpage); msk.set(F_COPIES, _copies); const bool ok = msk.run() == K_ENTER; if (ok) { _copies = msk.get_int(F_COPIES); _pagefrom = msk.get_int(F_FROMPAGE); _pageto = msk.get_int(F_TOPAGE); if (_pageto < _pagefrom || _pageto >= _lastpage) _pageto = 0; } return ok; } bool TPrint_txt_info::editpdf() { TPrinter& p = printer(); TMask msk("bagn009"); TFilename f; f.tempdir(); msk.set(F_PRINTER, f); f = p.get_form_name().name(); f.ext(""); msk.set(F_FORM, f); const bool ok = msk.run() == K_ENTER; if (ok) { _copies = 1; _pagefrom = 1; _pageto = 0; _pdf_file = msk.get(F_PRINTER); _pdf_file.add(msk.get(F_FORM)); _pdf_file.ext(".pdf"); } return ok; } TPrint_txt_info::TPrint_txt_info(TTextfile& txt) : _txt(&txt), _copies(1), _pagefrom(1), _pageto(0) { const word ps = printer().formlen(); const long li = txt.lines(); _lastpage = word((li+ps-1) / ps); } // @cmember Ritorna vero se la stampante e' generica/solo testo bool TPrinter::is_generic() const { bool yes = _dots_per_line == 1; if (!yes) yes = _prname.find("Generic") >= 0; return yes; } // @cmember Ritorna vero se sono attivati gli elementi grafici bool TPrinter::isgraphics() const { return _isgraphics; } // @cmember Attivati gli elementi grafici se possibile bool TPrinter::set_graphics(bool g) { _isgraphics = g && !is_generic(); return _isgraphics; } BOOLEAN TPrinter::start_print(long data) { const TPrint_txt_info *pd = (TPrint_txt_info *) data; TTextfile& txt = *(pd->_txt); TPrinter& stampante = printer(); const int vofs = stampante.get_line_offset(); const int hofs = stampante.get_column_offset(); if (stampante.is_generic() && (vofs != 0 || hofs != 0)) { TTextfile new_txt; TString s(256); const long last_row = txt.lines(); long out_row = 0; for (long row = (vofs < 0 ? -vofs : 0); row < last_row; row++) { const int pagelen = stampante.formlen(); const int page_row = (int) (out_row % pagelen); if (vofs > 0 && page_row == 0) { const int page = (int) (out_row / pagelen); for (int i = vofs; i > 0; i--) { out_row++; if (page > 0) row++; new_txt.append(""); } } if (vofs < 0 && page_row == pagelen + vofs) { for (int i = -vofs; i > 0; i--) { out_row++; row++; new_txt.append(""); } } s = txt.line(row); if (hofs < 0) s.ltrim(-hofs); else if(hofs > 0) s.lpad(s.len() + hofs); new_txt.append(s); out_row++; } TPrintwin pw(new_txt); pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies); return pw.aborted(); } else { TPrintwin pw(txt); if (pw.win() != NULL_WIN) pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies); return pw.aborted(); } } BOOLEAN TPrinter::start_print_pdf(long data) { const TPrint_txt_info *pd = (TPrint_txt_info *) data; TTextfile& txt = *(pd->_txt); TPrintwin pw(txt, pd->_pdf_file); if (pw.win() != NULL_WIN) pw.do_print(pd->_pagefrom, pd->_pageto, pd->_copies); return pw.aborted(); } // utils del caz HIDDEN int read_int (const char *s, int &n, int &cnt) { char nbuf[16]; while (!isdigit (s[cnt])) cnt++; int j; for (j = 0; isdigit (s[cnt]); j++) nbuf[j] = s[cnt++]; nbuf[j] = '\0'; return n = atoi (nbuf); } void TPrinter::parse_background(const char* bg_desc, TString_array& background) { TString_array pix; char op, ch; int x1, x2, y1, y2; int id, cnt = 0; TToken_string tt; TFilename bmp; if (!_fink_mode && _finker == NULL) _finker = new TPrint_intersector(_fink, _formlen); else if (_finker) _finker->clear(); while ((ch = bg_desc[cnt++]) != '\0') { op = ch; tt = ""; char bf[2]; bf[1] = '\0'; switch (op) { case ' ': case '\t': case '\n': continue; // ignore whitespace break; case 'i': cnt++; for (x1 = 0; bg_desc[cnt] != ','; x1++) bmp[x1] = bg_desc[cnt++]; bmp[x1] = '\0'; id = _image_names.find(bmp); if (id < 0) id = _image_names.add(bmp); read_int(bg_desc, x1, cnt); if (x1 <= 0) x1 = 1; read_int(bg_desc, y1, cnt); if (y1 <= 0) y1 = 1; read_int(bg_desc, x2, cnt); if (x2 <= 0) x2 = formwidth(); read_int(bg_desc, y2, cnt); if (y2 <= 0) y2 = formlen(); cnt++; if (_isgraphics) { tt << op; tt.add(id); tt.add(x1); tt.add(y1); tt.add(x2); tt.add(y2); } break; case 'l': // line case 'b': // box case 'r': // round box cnt++; read_int (bg_desc, x1, cnt); read_int (bg_desc, y1, cnt); read_int (bg_desc, x2, cnt); read_int (bg_desc, y2, cnt); cnt++; // skip separator if (_isgraphics && _fink_mode) { tt << op; tt.add (x1 - 1); tt.add (y1 - 1); tt.add (x2 - 1); tt.add (y2 - 1); } else { TGraphic_shape s = op == 'b' ? box : line; _finker->add(s, x1, y1, x2, y2); } break; case 't': // text cnt++; read_int (bg_desc, x1, cnt); read_int (bg_desc, y1, cnt); cnt++; tt << op; tt.add (x1-1); tt.add (y1-1); tt << '|'; while ((ch = bg_desc[cnt++]) != '}') tt << ch; break; case 'P': // set pen style case 'B': // set brush case 'W': // set line width case 'C': // set pen color tt << op; bf[0] = bg_desc[cnt++]; tt.add (bf); break; default: yesnofatal_box ("Unknown background opcode: %c", op); break; } pix.add (tt); } // now build row descriptions // colors are listed in printapp: char curcol = 'n'; char curpen = 'n'; char curpat = 'n'; char curwid = '1'; for (int l = 0; l < _formlen; l++) { if (background.objptr(l) == NULL) // Se la riga non esiste creala { TToken_string* r = new TToken_string(15); if (curcol != 'n') *r << 'C' << curcol; // Setta valori se diversi da default if (curpat != 'n') *r << 'B' << curpat; if (curwid != '1') *r << 'W' << curwid; if (curpen != 'n') *r << 'P' << curcol; background.add(r, l); } TString& rwd = background.row(l); for (int j = 0; j < pix.items(); j++) { TToken_string& tt = pix.row(j); // la stringa contiene l'opcode piu' i parametri in binario, // incrementati di 1 per evitare lo 0 switch (tt.get_char(0)) { case 'b': x1 = tt.get_int (1) + 1; y1 = tt.get_int (2) + 1; x2 = tt.get_int (3) + 1; y2 = tt.get_int (4) + 1; if (y1 == l + 1) // at ze biginnin { rwd << 'u' << char (x1); rwd << 'r' << char (x1) << char (x2); rwd << 'u' << char (x2); } else if (y2 == l + 1) // at ze end { rwd << 'o' << char (x1); rwd << 'r' << char (x1) << char (x2); rwd << 'o' << char (x2); } else if (y1 < l + 1 && y2 > l + 1) // in ze middol { rwd << 'v' << char (x1); rwd << 'v' << char (x2); } break; case 'l': x1 = tt.get_int (1) + 1; y1 = tt.get_int (2) + 1; x2 = tt.get_int (3) + 1; y2 = tt.get_int (4) + 1; if (y1 == y2 && y1 == l + 1) // orizzontale { rwd << 'h' << char (x1) << char (x2); } else if (y1 <= l + 1 && y2 >= l + 1) // verticale { rwd << 'v' << char (x1); } break; case 'r': x1 = tt.get_int (1) + 1; y1 = tt.get_int (2) + 1; x2 = tt.get_int (3) + 1; y2 = tt.get_int (4) + 1; if (y1 == y2) // orizzontale { if (y1 == l+1) rwd << 'r' << char (x1) << char (x2); } else { const int l1 = l+1; if (l1 >= y1 && l1 <= y2) // verticale { char code = 'v'; if (y1 == l1) code = 'u'; else if (y2 == l1) code = 'o'; rwd << code << char(x1); } } break; case 't': x1 = tt.get_int (1) + 1; y1 = tt.get_int (2) + 1; // al gh'e' if (y1 == l + 1) {} break; case 'i': id = tt.get_int(); x1 = tt.get_int(); y1 = tt.get_int(); x2 = tt.get_int(); y2 = tt.get_int(); if (l+1 >= y1 && l+1 <= y2) rwd << 'i' << char(id+1) << char(l-y1+2) << char(x1) << char(x2-x1+1) << char(y2-y1+1); break; case 'W': curwid = *(tt.get (1)); rwd << 'W' << curwid; break; case 'P': curpen = *(tt.get (1)); rwd << 'P' << curpen; break; case 'B': curpat = *(tt.get (1)); rwd << 'B' << curpat; break; case 'C': curcol = *(tt.get (1)); rwd << 'C' << curcol; break; default: break; } } } } void TPrinter::setbackground(const char* b, int index) { CHECK(index >= 0 && index <= 3, "Bad background index"); _backgrounds.destroy(index); if (b && *b) { TString_array* bg = new TString_array(formlen()); _backgrounds.add(bg, index); parse_background(b, *bg); } } TString_array& TPrinter::getbgdesc(word page) const { int index = 0; if (page == 0 && _backgrounds.objptr(3)) index = 3; if (page == 1 && _backgrounds.objptr(2)) index = 2; if (index == 0 && (page & 0x1) == 0 && _backgrounds.objptr(1)) index = 1; TString_array* bg = (TString_array*)_backgrounds.objptr(index); if (bg == NULL) { bg = new TString_array(formlen()); ((TPrinter*)this)->_backgrounds.add(bg, index); // keep const } return *bg; } //bool printers_on_key(TMask_field & f, KEY key); ////////// TPRINTROW ////////// TPrintrow::TPrintrow() { reset(); } TPrintrow::TPrintrow(const TPrintrow& pr) { reset(); _row = pr.row (); memcpy (_attr, pr._attr, MAX_PR_WIDTH); memcpy (_cols, pr._cols, MAX_PR_WIDTH); _tab = pr._tab; if (pr._images) _images = new TToken_string(*pr._images); _currentstyle = pr._currentstyle; _currentcolor = pr._currentcolor; _lastpos = pr._lastpos; } TPrintrow::~TPrintrow() { if (_images) delete _images; } TObject *TPrintrow::dup () const { return new TPrintrow(*this); } const char *TPrintrow::class_name () const { return "Printrow"; } word TPrintrow::class_id() const { return CLASS_PRINTROW; } TPrintrow& TPrintrow::reset() { _row.spaces (sizeof(_attr)); // Azzera testo memset(_attr, normalstyle, sizeof (_attr)); // Azzera stile _tab.reset(); // Azzera tabulazioni _images = NULL; _currentcolor = 'w'; _currentcolor <<= 8; _currentcolor += 'n'; for (int i = 0; i < MAX_PR_WIDTH; i++) _cols[i] = _currentcolor; // Azzera colori _lastpos = 0; _currentstyle = normalstyle; return *this; } const char* TPrintrow::row_codified() const { char last_attr = -1; int last_color = -1; int k = 0, i = 0, len = 0; const int kmax = 1024; char* tmp = get_tmp_string(kmax).get_buffer(); // Calcolo lunghezza stringa for (i = _row.size()-1; i >= 0; i--) { if (_row[i] != ' ') { len = i+1; break; } } for (i = 0; i < len; i++) { if (_tab[i]) { tmp[k++] = '@'; tmp[k++] = 't'; } if (_attr[i] != last_attr) { tmp[k++] = '@'; switch (_attr[i]) { case normalstyle: tmp[k++] = 'r'; break; case boldstyle: tmp[k++] = 'b'; break; case italicstyle: tmp[k++] = 'i'; break; case underlinedstyle: tmp[k++] = 'u'; break; } last_attr = _attr[i]; } if (_cols[i] != last_color) { tmp[k++] = '$'; tmp[k++] = '['; tmp[k++] = (char) (_cols[i] & 0x00ff); tmp[k++] = ','; tmp[k++] = (char) (_cols[i] >> 8); tmp[k++] = ']'; last_color = _cols[i]; } if (_row[i] == '@' && strchr("<#>", _row[i+1]) == NULL) tmp[k++] = '@'; // Escape for @ tmp[k++] = _row[i]; } CHECKD(k < kmax, "Internal buffer overflow ", k); tmp[k] = '\0'; if (_images) { strcat(tmp, "$[w,w]"); // Bianco su bianco! FOR_EACH_TOKEN((*_images), tok) strcat(tmp, tok); } return tmp; } TPrintrow& TPrintrow::put(const char *str, int position, int len) { if (len <= 0) len = strlen (str); if (position < 0) position = _lastpos; else _tab.set(position); char bg = 'w', fg = 'n'; for (int i = 0; i < len; i++) { char c = str[i]; if (c == '$' && str[i + 1] == '[') { ++i; fg = str[++i]; c = str[++i]; if (c == ']') bg = _currentcolor >> 8; else if (c == ',') { bg = str[++i]; i++; } else { CHECK (0, "Error in color specification"); } _currentcolor = (bg << 8) + fg; } else if (c == '@') { c = str[++i]; switch (toupper (c)) { case '@': // Escape for @ _row[position] = '@'; _attr[position] = _currentstyle; _cols[position++] = _currentcolor; break; case '#': case '<': case '>': // printer MUST handle them { const int n = (c == '#') ? 5 : ((c == '>') ? 10 : 8); _row[position] = '@'; _attr[position] = _currentstyle; _cols[position++] = _currentcolor; for (int j = 1; j < n; j++) { _row[position] = c; _attr[position] = _currentstyle; _cols[position++] = _currentcolor; } } break; case 'T': _tab.set(position); break; case 'B': _currentstyle = boldstyle; break; case 'I': _currentstyle = italicstyle; break; case 'U': _currentstyle = underlinedstyle; break; case 'R': _currentstyle = normalstyle; break; case 'F': { const int f = i; for ( ; str[i] && str[i] != ']'; i++); TString name = &str[f+2]; name.cut(i-f-2); name.insert("i{"); name << '}'; if (_images == NULL) _images = new TToken_string; _images->add(name); } break; default: // should be number followed by skip or jump if (isdigit (c)) { // read number char digbuf[8]; int cnt = 0; digbuf[cnt++] = c; while (isdigit (c = str[++i])) digbuf[cnt++] = c; digbuf[cnt] = '\0'; int pp = atoi (digbuf); if (toupper (c) == 'G') { if (pp >= MAX_PR_WIDTH) fatal_box ("printrow reaches position %d", pp); if (pp > position) for (int k = position; k < pp; k++) { _attr[k] = _currentstyle; _cols[k] = _currentcolor; } position = pp; _tab.set(position); } else if (toupper (c) == 'J') { if (pp + position >= MAX_PR_WIDTH) fatal_box ("printrow reaches position %d", pp + position); for (int k = 0; k < pp; k++) { _attr[k + position] = _currentstyle; _cols[k + position] = _currentcolor; } position += pp; _tab.set(position); } } else { _row[position] = c; _attr[position] = _currentstyle; _cols[position++] = _currentcolor; } } // switch } else { _row[position] = c; _attr[position] = _currentstyle; _cols[position++] = _currentcolor; } } // for _lastpos = position; return *this; } ////////// TPRINTER ////////// void TPrinter::set_printrcd() { if (_print_rcd != NULL) { xvt_print_destroy(_print_rcd); _print_rcd = NULL; _print_rcd_size = 0; } bool ok = false; if (_prname.full() && !forced_default_printer()) { _print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname); ok = xvt_print_is_valid(_print_rcd) != 0; } if (!ok) { _print_rcd = xvt_print_create(&_print_rcd_size); xvt_print_get_name(_print_rcd, _prname.get_buffer(), _prname.size()); ok = xvt_print_is_valid(_print_rcd) != 0; } if (!ok) error_box(FR("Errore di inizializzazione della stampante %s"), (const char*)_prname); } PRINT_RCD* TPrinter::get_printrcd(int *size) { if (_print_rcd == NULL) set_printrcd(); if (size != NULL) *size = _print_rcd_size; return _print_rcd; } // @doc EXTERNAL // @mfunc Setta le caratteristiche della stampante leggendole da

void TPrinter::init_formlen( WINDOW prwin) // @parm Finestra effettiva di stampa (default NULL_WIN) // @comm Nel caso

sia NULL_WIN vengono solamente aggiornati i valori { long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, get_printrcd(), &ph, &pw, &pvr, &phr); if (pvr > 0) { _formlen = int(ph * _lines_per_inch / pvr); // Total number of lines per page _dots_per_line = int(pvr / _lines_per_inch); // Number of point per line _vert_offset = (int)(ph - ((long)_formlen * _dots_per_line)) >> 1; _formwidth = int ((pw * 120) / (_ch_size * phr)); // nice guess if (prwin != NULL_WIN) { // Compute maximum number of chars per line int mincol = 0,maxcol=MAX_PR_WIDTH; TString256 spc; spc.fill('m', maxcol); _formwidth = maxcol; int w = 0; while (mincol < maxcol ) { w = xvt_dwin_get_text_width(prwin, (char*)(const char*)spc, _formwidth); if (w < pw) mincol = _formwidth+1; else maxcol=_formwidth-1; _formwidth=(mincol+maxcol)/2; } _horz_offset = (_formwidth > 80) ? (int)(pw - w)/2 : 0; if (_horz_offset < 0) _horz_offset = 0; } else { // _formwidth = int (pw * (_ch_size * 10 / 12) / phr); / ca$$ata _horz_offset = 0; } } } TPrinter::TPrinter() : _vf(NULL), _ch_size (12), _date (TODAY), _multiple_link (false), _isgraphics (true), _frozen (false), _print_rcd(NULL), _lines_per_inch (6), _l_offset(0), _c_offset(0), _export_header(false), _export_header_len(0), _appendfile(false), _manual_setup(false) { _footerhandler = _headerhandler = NULL; _linkhandler = NULL; _formlen = 66; _formwidth = 0; _frompage = 0; _topage = 0xffff; _hwformfeed = false; _currentpage = 1; _currentrow = 1; _headersize = 0; _footersize = 0; _isopen = false; // read configuration file read_configuration (); init_formlen (); set_fincatura("+++++++++-|"); set_fink_mode(true); _finker = _isgraphics && _fink_mode ? NULL : new TPrint_intersector(_fink, _formlen); } // @doc EXTERNAL // @mfunc Legge la configurazione della stampante void TPrinter::read_configuration( const char* parag) // parm Nome del file di configurazione della stampante (default NULL) // @comm Se

e' NULL viene letta la configurazione della stamapnte di default. { TWait_cursor hourglass; _config = parag; // Inizializza nome configurazione if (_config.blank()) // Se non specificata ... _config = "Printer"; // ... usa configurazione standard TConfig* iniptr = NULL; if (_config != "Printer") // Cerca configurazione speciale { iniptr = new TConfig(CONFIG_STAMPE, _config); const int what = iniptr->get_int("Type", NULL, -1, -1); if (what < 0) // Se configurazione annullata ... { delete iniptr; iniptr = NULL; } } if (iniptr == NULL) iniptr = new TConfig(CONFIG_GUI, "Printer"); const int what = iniptr->get_int("Type", NULL, -1, 4); // Tipo stampante _prname = iniptr->get("Name"); // Nome stampante corrente _printerfile = iniptr->get("File", NULL, -1, ""); // File di stampa set_fontname(iniptr->get("Font", NULL, -1, XVT_FFN_FIXED)); // Nome del font _ch_size = iniptr->get_int("Size", NULL, -1, 10); // Dimensione del font _lines_per_inch = iniptr->get_int("Lines", NULL, -1, 6); // Linee per pollice set_graphics(iniptr->get_bool("Graphic", NULL, -1, true)); // Grafica attiva _force_default = iniptr->get_bool("Default", NULL, -1, false); // Forza stampante di default bool read_rcd = false; if (_prname.full() && !forced_default_printer()) { const TString& host = iniptr->get("Host"); if (host.full()) { char hostname[256]; xvt_sys_get_host_name(hostname, sizeof(hostname)); read_rcd = (host == hostname); // Safe to read if (!read_rcd) { _prname.cut(0); // Forza la lettura parametri della stampante di default set_printrcd(); } } } if (read_rcd) { if (_print_rcd != NULL) xvt_print_destroy(_print_rcd); _print_rcd = xvt_print_create_by_name(&_print_rcd_size, _prname); if (xvt_print_is_valid(_print_rcd) && iniptr->exist("rcd", 0)) { TToken_string s(256); int i = 0; for (int index = 0; ; index++) { s = iniptr->get("rcd", NULL, index); if (s.not_empty()) { byte* rcd = (byte*)_print_rcd; for (const char* n = s.get(0); n != NULL && i < _print_rcd_size; n = s.get()) rcd[i++] = (byte)atoi(n); } else break; } } if (xvt_print_is_valid(_print_rcd)) { char name[256]; // Recupera nome "lungo" della stampante xvt_print_get_name(_print_rcd, name, sizeof(name)); _prname = name; init_formlen(); } else { error_box(TR("Attenzione: la stampante corrente non e' valida. " "Si prega di selezionare e registrare una nuova stampante.")); set_printrcd(); } } else { set_printrcd(); } delete iniptr; iniptr = NULL; if (_printerfile.empty()) { _printerfile.tempdir(); _printerfile << SLASH; } if (_config == "Printer" || _printertype == winprinter) { switch (what) { case 1: _printertype = fileprinter; break; case 2: _printertype = screenvis; break; case 3: _printertype = exportprinter; break; case 4: _printertype = acrobatprinter; break; default: _printertype = winprinter; break; } } } void TPrinter::save_configuration(const char* para) { TWait_cursor hourglass; if (para && *para) _config = para; CHECK(_config.not_empty(), "Invalid printer config"); TConfig prini(_config == "Printer" ? CONFIG_GUI : CONFIG_STAMPE, _config); prini.set("Type", _printertype); // Tipo stampante prini.set("Name", _prname); // Nome stampante corrente prini.set("File", _printerfile); // File di stampa prini.set("Font", _fontname); // Nome del font prini.set("Size", _ch_size); // Dimensione del font prini.set("Lines", _lines_per_inch); // Linee per pollice prini.set("Graphic", _isgraphics ? "X" : ""); // Grafica attiva prini.set("Default", _force_default ? "X" : ""); // Forza stampante default char hostname[256]; xvt_sys_get_host_name(hostname, sizeof(hostname)); prini.set("Host", hostname); prini.set("User", user()); int n = 0, index = 0; TToken_string val(256); int rcdsize; byte* rcd = (byte*)get_printrcd(&rcdsize); for (int i = 0; i < rcdsize; i++) { val.add((int)rcd[i]); n++; if (n == 24) { prini.set("rcd", val, NULL, true, index++); val.cut(n = 0); } } if (n > 0) prini.set("rcd", val, NULL, true, index); for (index++; prini.remove("rcd", index); index++); } TPrinter::~TPrinter () { if (_print_rcd != NULL) { xvt_print_destroy(_print_rcd); _print_rcd = NULL; } } const char* TPrinter::class_name() const { return "Printer"; } word TPrinter::class_id() const { return CLASS_PRINTER; } TPrintrow *TPrinter::getheaderline(int linetoget) { return ((TPrintrow *)_header.objptr (linetoget)); } TPrintrow *TPrinter::getfooterline(int linetoget) { return ((TPrintrow *)_footer.objptr(linetoget)); } // @doc EXTERNAL // @mfunc Setta il contenuto di una line dell'header void TPrinter::setheaderline ( int linetoset, // @parm Numero della linea da settare TPrintrow * line) // @parm Contenuto della linea dell'header // @parm const TPrintrow& | line | Indirizzo con il contenuto della // linea dell'header // @syntax void setheaderline (int linetoset, TPrintrow* line); // @syntax void setheaderline (int linetoset, const TPrintrow& line); { _header.add (line, linetoset); if (linetoset >= _headersize) _headersize = linetoset + 1; } void TPrinter::setheaderline (int linetoset, const TPrintrow & line) { TPrintrow *p = new TPrintrow (line); setheaderline (linetoset, p); } // @doc EXTERNAL // @mfunc Setta il contenuto di una line dell'header void TPrinter::setfooterline ( int linetoset, // @parm Numero della linea da settare TPrintrow * line) // @parm Contenuto della linea del footer // @parm const TPrintrow& | line | Indirizzo con il contenuto della // linea del footer // @syntax void setfooterline (int linetoset, TPrintrow* line); // @syntax void setfooterline (int linetoset, const TPrintrow& line); { _footer.add (line, linetoset); } void TPrinter::setfooterline (int linetoset, const TPrintrow& line) { TPrintrow *p = new TPrintrow (line); setfooterline (linetoset, p); } void TPrinter::resetheader () { _header.destroy (); _headersize = 0; } void TPrinter::resetfooter () { _footer.destroy (); // _footersize = 0; } // @doc EXTERNAL // @mfunc Metodo base per la stampa // // @rdesc Ritorna il risulato della stampa: // // @flag true | Se la stampa ha avuto successo // @flag false | Se la stampante non e' attiva bool TPrinter::printrow( TPrintrow* rowtoprint) // @parm Riga da stampare // @comm Se la pagina logica corrente e' precedente alla prima pagina logica o successiva // all'ultima pagina logica viene ritornato true. { if (!isopen ()) return false; if (_currentpage < _frompage || _currentpage > _topage) return true; TString rw; if (rowtoprint != NULL) { //rw = (_printertype == fileprinter) ? rowtoprint->row() : rowtoprint->row_codified(); rw = rowtoprint->row_codified(); // Permetto di salvare anche su fileprinter = pippo.xls rw.rtrim(); } if (_printertype != exportprinter) { for (int idx = 0; rw[idx]; idx++) { if (rw[idx] == '@') // gestione data e n. di pagina { switch (rw[idx + 1]) { case '#': rw.overwrite (format("%-5u", _currentpage), idx++); break; case '>': rw.overwrite (_date.string(full), idx++); break; case '<': rw.overwrite (_date.string(brief), idx++); break; default: break; } } } } if (_printertype == screenvis) { if (!_vf->frozen()) _vf->add_line(rw); else _frozen = true; } else { // add line to txt if (!_frozen) _txt.append(rw); } return true; } word TPrinter::rows_left() const { word left = _formlen - _currentrow - _footersize + 1; if (_currentrow < 2) left -= _headersize; return left; } // @doc EXTERNAL // @mfunc Permette di stampare una riga // // @rdesc Ritorna il risultato della stampa: // // @flag true | Se la stampa ha avuto successo // @flag false | Se non e' riuscito ad effettuare la stampa bool TPrinter::print( TPrintrow& rowtoprint) // @parm Riga da stampare // @comm Nel caso la riga non ci stia nella pagina logica corrente vengono stampanti il footer // della pagina corrente e l'header della successiva prima prima della stampa della riga // vera e propria. { bool ok = true; if (!(_printertype == exportprinter && !_export_header)) { if (_currentrow > _formlen - _footersize) ok = printfooter (); if (ok && _currentrow == 1) ok = printheader(); } if (ok) { ok = printrow(&rowtoprint); _currentrow++; } return ok; } bool TPrinter::printheader() { if (_headerhandler) _headerhandler(*this); bool ok = true; int i; for (i = 0; i < _headersize && ok; i++) ok = printrow(getheaderline(i)); // _currentrow = _headersize + 1; _currentrow = i+1; return ok; } bool TPrinter::printfooter() { if (_footerhandler) _footerhandler (*this); bool ok = true; for (int i = 0; i < _footersize && ok; i++) ok = printrow(getfooterline(i)); _currentrow = 1; _currentpage++; return ok; } // @doc EXTERNAL // @mfunc Permette di settare il tipo di fincatura void TPrinter::set_fink_mode( bool f) // @parm Indica il tipo di fincatura: // // @flag true | Fincatura di tipo grafico // @flag false | Fincatura di tipo testo // @comm Viene prima controllato che la stampante supporti la modalita' grafica, // in tal caso, se viene impostato il flag a true e la stampante e' generica // oppure non ha il flag di stampa elementi grafici attivato, la fincatura sara' // in modo testo. { _fink_mode = f && isgraphics(); } // @doc EXTERNAL // @mfunc Permette di saltare alcune righe dalla posizione corrente // // @rdesc Ritorna il risulato dell'operazione: // // @flag true | Se e' riuscito a saltare le righe // @flag false | Se non e' riuscito a saltare le righe bool TPrinter::skip( int linestoskip) // @parm Vengono accettati solo valori positivi // @xref { CHECK (linestoskip >= 0, "Linestoskip can't be negative"); int jumpline = _currentrow + linestoskip; return jump(jumpline); } // @doc EXTERNAL // @mfunc Permette di saltare alla riga indicata // // @rdesc Ritorna il risultato dell'operazione // // @flag true | Se e' riuscito a saltare alla riga // @flag false | Se non e' riuscito a saltare alla riga o se viene inserito un formfeed bool TPrinter::jump( int jumpline) // @parm Numero della riga a cui saltare nella stampa. Vengono accettai // solo valori positivi // @comm Nel caso si cerchi di saltare ad una riga superiore alla lunghezza della pagina attiva // viene inserito un formfeed. // @xref { int i = 0; bool ok = true; CHECK (jumpline >= 0, "Jumpline can't be negative"); if (jumpline > _formlen - _footersize) ok = formfeed(); else for (i = _currentrow; i < jumpline; i++) if (!printrow()) ok = false; if (jumpline > _formlen - _footersize) ok = false; return ok; } bool TPrinter::formfeed() { const int lastrow = _formlen - _footersize; for (; _currentrow + _export_header_len <= lastrow; _currentrow++) printrow(); return printfooter(); } void TPrinter::reset() { resetheader(); resetfooter(); _currentpage = 1; _currentrow = 1; } bool TPrinter::open() { if (_printertype == screenvis) { CHECK(_vf == NULL, "Print preview already open"); _vf = new TViswin (NULL, "Anteprima di stampa", true, true, _linksdescr.items () > 0); _vf->open_modal (); } else { // prepare text object for new text _txt.destroy(); _txt.interactive(false); } _currentrow = 1; _currentpage = 1; return _isopen = true; } bool TPrinter::set() { main_app().disable_menu_item(M_FILE_PG_SETUP); const TString oldprn = _prname; int old_rcd_size; PRINT_RCD* rcd = get_printrcd(&old_rcd_size); TString oldrcd(old_rcd_size); memcpy(oldrcd.get_buffer(), rcd, old_rcd_size); TPrinter_setup_mask mask; const KEY k = mask.run(); if (k != K_ESC) { _manual_setup = true; _print_rcd = mask.get_print_rcd(_print_rcd_size); xvt_print_get_name(_print_rcd, _prname.get_buffer(128), 128); switch (mask.get_int(MSK_TYPE)) { case 1: // file _printertype = fileprinter; _printerfile = mask.get (MSK_FILENAME); break; case 2: // video _printertype = screenvis; break; case 4: // acrobat _printertype = acrobatprinter; break; default: // stampante _printertype = winprinter; break; } set_fontname(mask.get(MSK_FONT)); const int cs = mask.get_int(MSK_SIZE); if (cs > 4) _ch_size = cs; _lines_per_inch = mask.get_int (MSK_LINES); _isgraphics = mask.get_bool (MSK_ISGRAPHICS); _force_default = mask.get_bool(MSK_DEFAULT); init_formlen (); if (k == K_INS) save_configuration(); } main_app().enable_menu_item (M_FILE_PG_SETUP); return true; } // @doc EXTERNAL // @mfunc Inserisce un file di export fatto da un'altra printer void TPrinter::merge_export_file( const char* file, bool header) // @parm Indica se gli header sono presenti nel file: // // @flag true | Gli header sono nel file e quindi non vengono stampanti (default) // @flag false | Gli header non sono nel file e quindi vengono stampanti // @comm Vengono inseriti nel file di export i formati e tutto il resto. Vengono ignorati gli // header supponendo che siano gia' presenti nel file { TTextfile txt(file); for (long i = 0; i < txt.lines(); i++) { TPrintrow* p = new TPrintrow(); p->put(txt.line_formatted(i)); if (header) printrow(p); else print(*p); } } // @doc EXTERNAL // @mfunc Crea un segnalibro // // @rdesc Ritorna l'identificatore del segnalibro creato int TPrinter::set_bookmark( const char* txt, // @parm Nome del segnalibro da creare int father) // @parm Identificatore del segnalibro padre a cui collegare quello // da creare { if (_printertype == screenvis) { BkDef* bkd = new BkDef; bkd->_row = (_currentrow + ((_currentpage - 1)*_formlen)) - 1; bkd->_father_id = father; bkd->_id = _bookmarks.items() + 1; bkd->_txt = txt; _bookmarks.add(bkd); return _bookmarks.items(); } return 0; } bool TPrinter::print_txt(TTextfile& txt) { bool ok = txt.lines() > 0; if (ok) { TPrint_txt_info what(txt); ok = what.edit(); if (ok) { xvt_print_open(); xvt_print_start_thread(start_print, long(&what)); xvt_print_close(); } } return ok; } bool TPrinter::print_pdf(TTextfile& txt, const TFilename& pdf) { bool ok = txt.lines() > 0; if (ok) { TPrint_txt_info what(txt); if (pdf.blank()) what.editpdf(); else what._pdf_file = pdf; ok = what._pdf_file.full(); if (ok) { TFilename old_printer; xvt_print_open(); xvt_print_get_name(_print_rcd, old_printer.get_buffer(), old_printer.size()); xvt_print_set_name(_print_rcd, XVT_PDF_PRINTER_NAME); xvt_print_start_thread(start_print_pdf, long(&what)); xvt_print_set_name(_print_rcd, old_printer); xvt_print_close(); } } return ok; } bool TPrinter::acrobatically_print_pdf(const TFilename& pdf) const { TString cmd(512); bool ok = xvt_sys_find_editor(pdf, cmd.get_buffer()) != FALSE; if (ok) { // /s=suppress banner; /t=file name + printer name cmd << " /s /t \"" << pdf << "\" \"" << printername() << "\""; xvt_sys_execute(cmd, TRUE, FALSE); } else error_box(TR("Adobe Acrobat non installato")); return ok; } bool TPrinter::auto_export(const TFilename& n) { TString ext = n.ext(); if (ext.blank()) return false; ext.lower(); if (ext == "pdf") { print_pdf(_txt, n); return true; } if (ext.starts_with("xls")) return _txt.write_xls(n); if (ext == "txt") { ofstream txt(n); for (long i = 0; i < _txt.lines(); i++) txt << _txt.line(i) << '\n'; txt.close(); return true; } return false; } void TPrinter::close() { // la stampante era aperta e ho stampato qualcosa c'è footer da stampare if (isopen() && _currentrow > 1 && _footersize > 0) formfeed(); switch (_printertype) { case winprinter: if (_txt.lines() > 0L) print_txt(_txt); break; case fileprinter: if (_printerfile.full() && _txt.lines() > 0L) { bool done = false; if (!_appendfile) done = auto_export(_printerfile); if (!done) { FILE* fp = fopen(_printerfile, _appendfile ? "a" : "w"); if (fp != NULL) { for (long i = 0; i < _txt.lines(); i++) fprintf(fp,"%s\n", _txt.line(i)); fclose(fp); done = true; } } if (done) message_box(FR("Stampa su file terminata. Nome archivio: %s"),(const char *)_printerfile); else cantwrite_box(_printerfile); } break; case exportprinter: if (_exportfile.full() && _txt.lines() > 0L) { ofstream txt(_exportfile); for (long i = 0; i < _txt.lines(); i++) txt << _txt.line_formatted(i) << '\n'; txt.close(); } break; case acrobatprinter: { TWait_cursor hourglass; TFilename fn; fn.tempdir(); fn.add("tmp.pdf"); if (print_pdf(_txt, fn)) acrobatically_print_pdf(fn); fn.fremove(); } break; case screenvis: default: { _vf->close_print(); const KEY key = _vf->run(); if (_vf->is_open()) _vf->close_modal(); _bookmarks.destroy(); if (key == K_CTRL+'S') { _isopen = false; _currentrow = _currentpage = 1; print_txt(_vf->text()); } delete _vf; _vf = NULL; } break; } if (_finker) { delete _finker; _finker = NULL; } // Dealloca sfondi ormai inutili _backgrounds.destroy(); freeze (false); _isopen = false; } // // TFile_printer // #include const long disk_sizes[] = { 360000L, 1200000L, 720000L, 1400000L, 2880000L }; TFile_printer::TFile_printer (const char *ffile, const char *label, int len_rec, int num_rec_inizio, int num_rec_fine, int tipo_disco) { set_printtype (fileprinter); _num_rec_testa_coda = num_rec_inizio + num_rec_fine; _file = ffile; _label = label; _len_rec = len_rec; _volume = 1; _size = disk_sizes[tipo_disco]; _num_rec_volume = int ((_size / len_rec) - _num_rec_testa_coda); _nome_file_fissato = true; _label_fissata = true; } void TFile_printer::open() { } void TFile_printer::close () { } bool TFile_printer::genera_dischetti () { int r; for (int i = 0; i < _tmp_files.items (); i++) { // Avvisa l'utente di inserire un dischetto r = yesno_box ("Inserire il dischetto n. %2d di %2d nel drive %2s", i + 1, _volume, _drive); if (!r) return error_box ("Procedura interrotta!"); // copia il file sul dischetto fcopy ((const char *) &_tmp_files[i], (const char *) _drive); } return true; } TFile_printer::~TFile_printer () { } bool TFile_printer::set () { TMask m ("bagn004"); int f; // // // -------------------------------------------------------------------- // Qui bisogna inserire la lista dei drive disponibili nella maschera // Per ora tale lista e' fissa e contiene solo A: e B: // -------------------------------------------------------------------- // // m.set (F_FILE_DESTINAZIONE, _file); m.set (F_LABEL, _label); if (_nome_file_fissato) m.disable (F_FILE_DESTINAZIONE); if (_label_fissata) m.disable (F_LABEL); const bool ok = m.run () == K_ENTER; if (ok) { f = atoi(m.get(F_FORMATO_DISCO)); _drive = m.get(F_DRIVE); _file = m.get(F_FILE_DESTINAZIONE); _label = m.get(F_LABEL); _size = disk_sizes[f]; _num_rec_volume = int ((_size / _len_rec) - _num_rec_testa_coda); } return ok; } const char* TPrinter::background_chars(int l) const { return _finker == NULL ? "" : _finker->get_chars(l); } /////////////////////////////////////////////////////////// // Calcolo dimensione font /////////////////////////////////////////////////////////// struct font_data { TString _name; int _size; int _columns; }; HIDDEN BOOLEAN calc_font_callback(long data) { font_data& fd = *(font_data*)data; // Create print window TPrinter& pr = printer(); WINDOW win = xvt_print_create_win(pr.get_printrcd(), "Calcolo font"); if (win != NULL_WIN) { long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, pr.get_printrcd(), &ph, &pw, &pvr, &phr); xvtil_set_font(win, pr.fontname(), XVT_FS_NONE, pr.get_char_size()); TString test(fd._columns); test.fill('M', fd._columns); int size; for (size = fd._size; size > 0; size--) { // Set print font xvtil_set_font(win, fd._name, XVT_FS_NONE, size); const int w = xvt_dwin_get_text_width(win, test, fd._columns); if (w <= pw) break; } if (size > 0) fd._size = size; xvt_vobj_destroy(win); } return win != NULL_WIN; } int TPrinter::calc_font_size(int columns) const { font_data fd; fd._name = fontname(); fd._size = get_char_size(); fd._columns = columns; xvt_print_open(); xvt_print_start_thread(calc_font_callback, (long)&fd); xvt_print_close(); return fd._size; } HIDDEN BOOLEAN calc_cols_callback(long data) { int &numcols=*(int *)data; // Create print window TPrinter& pr = printer(); WINDOW win = xvt_print_create_win(pr.get_printrcd(), "Calcolo numero colonne"); if (win != NULL_WIN) { long pw, ph, phr, pvr; // Printer width, height, horizontal and vertical resolution xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, pr.get_printrcd(), &ph, &pw, &pvr, &phr); xvtil_set_font(win, printer().fontname(), XVT_FS_NONE, pr.get_char_size()); // Compute maximum number of chars per line int mincol = 1, maxcol = MAX_PR_WIDTH; const TString spc(maxcol,'M'); numcols = (pw * 120) / (pr.get_char_size() * phr); // Primo guess while (mincol < maxcol ) { const int w = xvt_dwin_get_text_width(win, spc, numcols); if (w < pw) mincol = numcols+1; else maxcol=numcols-1; numcols=(mincol+maxcol)/2; } xvt_vobj_destroy(win); } return win != NULL_WIN; } // Funzione chiamata solo da sv1200, ma non si capisce perche' non usi la formwidth() int TPrinter::calc_num_cols() const { int numcols = 80; // Default sensato xvt_print_open(); xvt_print_start_thread(calc_cols_callback, (long)&numcols); xvt_print_close(); return numcols; } void TPrinter::set_portrait_orientation(bool portrait) { long pw, ph; // Printer width, height PRINT_RCD* rcd = get_printrcd(); xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, rcd, &ph, &pw, NULL, NULL); const bool is_portrait = ph >= pw; if (portrait != is_portrait) xvt_app_escape(XVT_ESC_SET_PRINTER_INFO, rcd, &pw, &ph, NULL, NULL); } bool TPrinter::is_landscape() const { long ph = 0, pw = 0; xvt_app_escape (XVT_ESC_GET_PRINTER_INFO, _print_rcd, &ph, &pw, NULL, NULL); return pw > ph; } /////////////////////////////////////////////////////////// // TTabulator /////////////////////////////////////////////////////////// class TTab_info : public TObject { int _start, _end; public: int intersection(int s, int e) const; int intersection(const TTab_info& i) const { return intersection(i._start, i._end); } void set_start(int s) { _start = s; } void set_end(int e) { _end = e; } void set(int s, int e) { _start = s; _end = e; } int start() const { return _start; } int end() const { return _end; } int width() const { return _end - _start + 1; } bool operator==(const TTab_info& ti) const { return _start == ti.start() && _end == ti.end(); } TTab_info(int s, int e) { set(s, e); } }; int TTab_info::intersection(int s, int e) const { int i = 0; if (e >= _start && s <= _end) i = min(_end, e) - max(_start, s); return i; } void TTabulator::add(int s, int e) { if (e >= s) _tab.add(new TTab_info(s, e)); } void TTabulator::split(int s0, int e0, int s1, int e1) { if (s0 >= (s1+e1)/2 && e0 <= e1+1) { add(s1, s0-1); add(s0, max(e1, e0)); return; } if (s1 >= (s0+e0)/2 && e1 <= e0+1) { add(s0, s1-1); add(s1, max(e0,e1)); return; } add(min(s0,s1), max(e0,e1)); /* int a[4] = { s0, e0, s1, e1 }; int i, j; for (i = 0; i < 3; i++) { for (j = i+1; j < 4; j++) { if (a[i] > a[j]) { const int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } int t = 3; for (i = 0; i < t; i++) { j = i+1; if (abs(a[i]-a[j]) <= 1) { if (i < 2) a[i] = a[j] = min(a[i],a[j]); else a[i] = a[j] = max(a[i],a[j]); t--; for (j = i+1; j <= t; j++) a[j] = a[j+1]; } } if (t > 0) { a[t-1]++; for (i = 0; i < t; i++) add(a[i], a[i+1]-1); } */ } int TTabulator::find_column(int column, int width) const { int start = column; int end = column + width - 1; int index = -1, inter = 0; FOR_EACH_ARRAY_ITEM(_tab, t, obj) { TTab_info& ti = *(TTab_info*)obj; const int i = ti.intersection(start, end); if (i > inter) { inter = i; index = t; } } return index; } static int tab_compare(const TObject** o0, const TObject** o1) { const TTab_info& t0 = *(TTab_info*)*o0; const TTab_info& t1 = *(TTab_info*)*o1; return t0.start() - t1.start(); } void TTabulator::add_field(int column, int width) { int start = column; int end = column + width - 1; int index = find_column(column, width); if (index >= 0) { const TTab_info& ti = (const TTab_info&)_tab[index]; if (ti.intersection(start, end) < width) { split(start, end, ti.start(), ti.end()); _tab.destroy(index, true); } } else add(start, end); } bool TTabulator::empty() const { return _tab.items() <= 1; } void TTabulator::sort() { if (empty()) { _tab.destroy(); for (int i = 0; i < 256; i += 8) add(i, i+7); } else { _tab.sort(tab_compare); for (int i = _tab.last(); i > 0; i--) { TTab_info& t0 = (TTab_info&)_tab[i-1]; TTab_info& t1 = (TTab_info&)_tab[i]; if (t1 == t0 || t1.width() <= 0) _tab.destroy(i); else { if (t1.start() - t0.end() >= 8) { _tab.insert(new TTab_info(t0.end()+1, t1.start()-1), i); } else { const int center = (t0.end() + t1.start())/2; t0.set_end(center); t1.set_start(center+1); } } } } }