#include #include #include #include #include HIDDEN int LEN_SPACES(WINDOW win, int x) { HIDDEN int w = 0L; const int columns = 132; if (x < 0) { x = columns; w = 0L; } if (w == 0L) { TString256 spc; spc.fill('m', columns); w = xvt_dwin_get_text_width(win, spc.get_buffer(), columns); } const int tab = w * x / columns; return tab; } void TPrintwin::paint_background(long j) { const bool isbackground = _bg->items() > 0 && printer().isgraphics(); const bool fink_mode = printer().get_fink_mode(); int rw = (int)(j % _formlen); int cnt = 0; char ch; char curcol = 'n'; char curpen = 'n'; char curpat = 'n'; char curwid = '1'; unsigned int x1, y1, x2, y2, id; PNT b, e; if (!fink_mode) { const char* line = printer().background_chars(rw); set_color (COLOR_BLACK, COLOR_WHITE); xvt_dwin_draw_text(win(), _hofs , (rw*_chary + _chary - _descent + _vofs), (char*)line, -1); // return; } if (!isbackground) return; TString& rwd = (TString&)(*_bg)[rw]; while ((ch = rwd[cnt++])) { if (!fink_mode && (ch == 'v' || ch == 'o' || ch == 'u' || ch == 'h' || ch == 'r')) continue; switch(ch) { case 'v': // verticale intera x1 = (byte)rwd[cnt++]-1; b.h = e.h = LEN_SPACES(win(), x1)+LEN_SPACES(win(), 1)/2+_hofs; b.v = rw * _chary + _vofs; e.v = (rw+1) * _chary + _vofs; xvt_dwin_draw_set_pos(win(),b); xvt_dwin_draw_line(win(),e); break; case 'o': // verticale pezzo sopra x1 = (byte)rwd[cnt++]-1; b.h = e.h = LEN_SPACES(win(), x1)+LEN_SPACES(win(), 1)/2 + _hofs; b.v = rw * _chary + _vofs; e.v = rw * _chary + _chary/2 + _vofs; xvt_dwin_draw_set_pos(win(),b); xvt_dwin_draw_line(win(),e); break; case 'u': // verticale pezzo sotto x1 = (byte)rwd[cnt++]-1; b.h = e.h = LEN_SPACES(win(), x1)+LEN_SPACES(win(), 1)/2 + _hofs; b.v = rw*_chary + _chary/2 + _vofs; e.v = (rw+1) * _chary + _vofs; xvt_dwin_draw_set_pos(win(),b); xvt_dwin_draw_line(win(),e); break; case 'h': // orizzontale intera x1 = (byte)rwd[cnt++]-1; x2 = (byte)rwd[cnt++]-1; b.v = e.v = rw*_chary + _chary/2 + _vofs; b.h = LEN_SPACES(win(), x1)+_hofs; e.h = LEN_SPACES(win(), x2)+_hofs; xvt_dwin_draw_set_pos(win(),b); xvt_dwin_draw_line(win(),e); break; case 'r': // orizzontale scorciata agli estremi x1 = (byte)rwd[cnt++]-1; x2 = (byte)rwd[cnt++]-1; b.v = e.v = rw*_chary + _chary/2 + _vofs; b.h = LEN_SPACES(win(), x1)+LEN_SPACES(win(), 1)/2 + _hofs; e.h = LEN_SPACES(win(), x2)+LEN_SPACES(win(), 1)/2+_hofs; xvt_dwin_draw_set_pos(win(),b); xvt_dwin_draw_line(win(),e); break; case 'i': id = (byte)(rwd[cnt++])-1; // Numero immagine y1 = (byte)(rwd[cnt++])-1; // Riga sorgente x1 = (byte)(rwd[cnt++])-1; // Colonna sorgente x2 = (byte)(rwd[cnt++]); // Larghezza destinazione (in caratteri) y2 = (byte)(rwd[cnt++]); // Altezza destinazione (in caratteri) if (id >= 0) { #ifndef XVAGA // Ai tempi non veniva in mente un modo peggiore const short width = LEN_SPACES(win(), x2); // Larghezza in pixel TImage* i = (TImage*)_images.objptr(id); if (i == NULL) { const TString_array& a = printer().image_names(); const TImage src(a.row(id)); if (src.ok()) { // memorizzo l'immagine in risoluzione di stampa! Visto che ho RAM da buttare. i = new TImage(src, width, _chary*y2); _images.add(i, id); } } if (i && i->ok()) { RCT src; xvt_rect_set(&src, 0, int(_chary*y1), width, min(int(_chary*(y1+1)), i->height())); if (src.top < i->height()) { PNT p; p.h = LEN_SPACES(win(), x1) + _hofs; p.v = _chary*rw + _vofs; RCT dst = src; xvt_rect_set_pos(&dst, p); i->draw(win(), dst, src); } } #else if (y1 == 0) // Disegno solo una volta per tutte alla prima fetta! { TImage* i = (TImage*)_images.objptr(id); if (i == NULL) { // memorizzo l'immagine cosė com'č alla risoluzione originale! const TString_array& a = printer().image_names(); i = new TImage(a.row(id)); _images.add(i, id); } if (i != NULL && i->ok()) { RCT dst; dst.left = LEN_SPACES(win(), x1) + _hofs; dst.top = _chary*rw + _vofs; dst.right = dst.left + LEN_SPACES(win(), x2); dst.bottom = dst.top + _chary*y2; i->draw(win(), dst); } } #endif } break; case 'W': curwid = rwd[cnt++]; set_pen(trans_color(curcol), curwid- '0', trans_brush(curpat), trans_pen(curpen)); break; case 'P': curpen = rwd[cnt++]; set_pen(trans_color(curcol), curwid- '0', trans_brush(curpat), trans_pen(curpen)); break; case 'B': curpat = rwd[cnt++]; set_pen(trans_color(curcol), curwid- '0', trans_brush(curpat), trans_pen(curpen)); break; case 'C': curcol = rwd[cnt++]; set_pen(trans_color(curcol), curwid- '0', trans_brush(curpat), trans_pen(curpen)); break; default: break; } } // restore default pen set_pen(COLOR_BLACK); } void TPrintwin::paint_image(int row, const char* cp) { TToken_string tok(cp+2, ','); TImage img(tok.get(0)); const int x = _hofs + LEN_SPACES(win(), tok.get_int()-1); const int y = _vofs + row * _chary; int dx = LEN_SPACES(win(), tok.get_int(3)-tok.get_int(1)+1); int dy = _chary * (tok.get_int(4)-tok.get_int(2)+1); if (img.ok()) { const double ratiox = double(img.width()) / dx; const double ratioy = double(img.height()) / dy; const double ratio = ratiox > ratioy ? ratiox : ratioy; dx = int(img.width() / ratio); dy = int(img.height() / ratio); RCT dst; xvt_rect_set(&dst, x, y, x+dx, y+dy); img.draw(win(), dst); } else { RCT dst; xvt_rect_set(&dst, x, y, x+dx, y+dy); set_pen(COLOR_RED); xvt_dwin_draw_rect(win(), &dst); } } void TPrintwin::paint_row(long j) { const int row = (int)(j % _formlen); const int y = row*_chary + _chary - _descent + ((_chary == 1) ? 0 : _vofs); paint_background(j); _txt.read_line(j); int pos = 0; int curr_style = -1; for (const char* cp = _txt.piece(); cp; cp = _txt.piece()) { const int st = _txt.get_style(); const COLOR bg = trans_color(_txt.get_background()); const COLOR fg = trans_color(_txt.get_foreground()); if (bg != fg) // Testo vero e visibile { if (st != curr_style) { set_font(printer().fontname(), st, _char_size); curr_style = st; } const char* beg = cp; while (*beg) { for (; *beg == ' '; beg++) // Salta spazi iniziali pos++; if (*beg) { int len = 0; const char * end; for (end = beg; *end && (*end != ' ' || *(end+1) != ' '); end++) len++; // Misura stringa da stampare xvt_dwin_draw_text(win(), _hofs + LEN_SPACES(win(), pos), y, beg, len); pos += len; beg = end; } } } else // Testo trasparente (elementi grafici aggiuntivi) { if (*cp == 'i') paint_image(row, cp); } } } // @doc INTERNAL // @mfunc Permette di stampare un rettangolo a video // // @rdesc Ritorna se e' riuscito a stampare in una unica pagina bool TPrintwin::print_band( int page, // @parm Numero della pagina da stampare const RCT& r) // @parm Parte di finestra da stampare // @comm Di solito viene disegnata l'intera pagina, ma la cosa dipende dal driver di stampa { const long first_row = (long)page * _formlen; const int rows = (r.bottom - r.top) / _chary; const int top = r.top / _chary; const long lines = _txt.lines(); int k; for (k = top; k < top+rows; k++) { const long row = first_row + k; if (row < lines && k < _formlen) paint_row(row); else break; } return (first_row + k < lines); } // @doc INTERNAL // @mfunc Inizia la stampa // // @rdesc Ritorna se viene interrotta la stampa: // // @flag TRUE | La stampa e' andata a buon fine // @flag FALSE | La stampa e' stata interrotta bool TPrintwin::do_print(word page_from, word page_to, word copies) // @comm Quando possibile parte un processo concorrente (dipende dal sistema operativo) { CHECKD(page_from > 0, "Invalid page start ", page_from); CHECKD(copies > 0, "Invalid number of copies ", copies); _blank_lines_to_print = 0; for (word c = 0; c < copies && !_aborted; c++) { bool finished = FALSE; for (word page = page_from-1; !finished && !_aborted; page++) { if (page_to >= page_from && page >= page_to) break; _aborted = xvt_print_open_page(_printrcd) == 0; if (!_aborted) { for (const RCT* rct = xvt_print_get_next_band(); rct != NULL; rct = xvt_print_get_next_band()) { set_font(XVT_FFN_SYSTEM, XVT_FS_NONE, _char_size); // ??? set_font(printer().fontname(), XVT_FS_NONE, _char_size); LEN_SPACES(win(), -1); // Resetta bene le dimensioni font if (!print_band(page, *rct)) { finished = TRUE; while (xvt_print_get_next_band()); // Esce dalla lista delle bande break; } } _aborted = xvt_print_close_page(_printrcd) == 0; } } } return !_aborted; } TPrintwin::TPrintwin(TTextfile& txt, const char* title) : _aborted(FALSE), _txt(txt), _inited(FALSE) { TPrinter& p = printer(); _printrcd = p.get_printrcd(); if (!xvt_print_is_valid(_printrcd)) { _aborted = TRUE; return; } if (title == NULL) title = main_app().title(); WINDOW prwin = xvt_print_create_win(_printrcd, title); if (prwin == NULL_WIN) { _aborted = TRUE; return; } set_win(prwin); const bool ispdf = (xvt_print_is_pdf(_printrcd) != 0); if (ispdf) { if (_aborted = (xvt_print_open_page(_printrcd) == 0)) return; } _char_size = p.get_char_size(); set_font(p.fontname(), XVT_FS_NONE, _char_size); LEN_SPACES(win(), -1); // force update _pagelen = p.formlen(); if (!ispdf) p.init_formlen(prwin); // Calcola offset e altre misure pagina int abs_column=p.get_column_offset(); int segno = abs_column>=0 ? 1 : -1; abs_column*=segno; xvt_dwin_get_font_metrics(prwin, &_lead, &_ascent, &_descent); _bg = &p.getbgdesc(); _chary = p.get_dots_per_line(); _hofs = p.get_horz_offset() + segno*LEN_SPACES(prwin,abs_column); _vofs = p.get_vert_offset() + p.get_line_offset()*_chary; _formlen = p.formlen(); p.formlen(_pagelen); _formwidth = p.formwidth(); _inited = TRUE; } TPrintwin::~TPrintwin() { if (_inited && win() != NULL_WIN) xvt_vobj_destroy(win()); set_win(NULL_WIN); }