#include #include #include #include #include #include #include #include #include #include #include #include #include const char* const PRINT_FONT = XVT_FFN_FIXED; int PRINT_HEIGHT = 10; #define BUTTONROW_SIZE (_showbuts ? 4 : 0) #define X_OFFSET (_rulers ? 6 : 1) #define Y_OFFSET (_rulers ? 1 : 0) #define TEXTROWS (rows() - Y_OFFSET - BUTTONROW_SIZE) #define TEXTCOLUMNS (columns() - X_OFFSET) #define BACKGROUND MASK_BACK_COLOR #define FOREGROUND NORMAL_COLOR #define K_CTRL_DOWN (K_CTRL + K_DOWN) #define K_CTRL_UP (K_CTRL + K_UP) #define K_SHIFT_UP (K_SHIFT + K_UP) #define K_SHIFT_DOWN (K_SHIFT + K_DOWN) #define K_SHIFT_LEFT (K_SHIFT + K_LEFT) #define K_SHIFT_RIGHT (K_SHIFT + K_RIGHT) #define K_ALT_RIGHT (K_CTRL + 'K') #define K_ALT_LEFT (K_CTRL + 'L') #define CTRL_C (K_CTRL + 'C') #define CTRL_G (K_CTRL + 'G') #define CTRL_E (K_CTRL + 'E') #define CTRL_S (K_CTRL + 'S') #define CTRL_R (K_CTRL + 'R') #define CTRL_P (K_CTRL + 'P') class _BkMenuItem : public TObject { public: TString _txt; TArray* _arr; int _id; // per comodita' _BkMenuItem(const char* t = "") { _txt = t; _arr = NULL; } virtual ~_BkMenuItem() { if (_arr != NULL) delete _arr; } }; class _BkMenuDesc : public TObject { public: TString_array _menu; int _father_id; _BkMenuDesc() {} virtual ~_BkMenuDesc() {} }; int TViswin::tabx(int x) const { return char2pixel(x); } int TViswin::taby(int y) const { return y * CHARY; } // @doc INTERNAL // @mfunc Abilita/Disabilita una voce di menu' void TViswin::check_menu_item( MENU_TAG item, // @parm Voce del menu' da abilitare bool on) // @parm Operazione da svolgere sulla voce di menu': // @flag TRUE | Viene abilitata la voce // @flag TRUE | Viene disabilitata la voce { ignore_xvt_errors(TRUE); xvt_menu_set_item_checked(win(), item, on); xvt_menu_update(win()); ignore_xvt_errors(FALSE); } void TViswin::enable_menu_item(MENU_TAG item, bool on) { ignore_xvt_errors(TRUE); xvt_menu_set_item_enabled(win(), item, on); xvt_menu_update(win()); ignore_xvt_errors(FALSE); } HIDDEN _BkMenuItem* find_menu_node(TArray& tree, int id) { _BkMenuItem* fnd = NULL; for (int m = 0; m < tree.items(); m++) { _BkMenuItem& bkit = (_BkMenuItem&) tree[m]; if (bkit._id == id) return &bkit; else if (bkit._arr != NULL) { if ((fnd = find_menu_node(*(bkit._arr), id)) != NULL) break; } } return fnd; } HIDDEN void build_menu_tree(TArray& flat, TArray& tree, int level) { // find ID in flat array _BkMenuDesc* bds = NULL; int i; for (i = 0; i < flat.items(); i++) { _BkMenuDesc& bdss = (_BkMenuDesc&)flat[i]; if (bdss._father_id == 1000 + level) { bds = &bdss; break; } } if (bds == NULL) { bds = new _BkMenuDesc; bds->_father_id = 1000 + level; flat.add(bds); } for (i = 0; i < tree.items(); i++) { _BkMenuItem& bki = (_BkMenuItem&)tree[i]; bds->_menu.add(bki._txt); if (bki._arr != NULL) build_menu_tree(flat, *(bki._arr), bki._id); } } void TViswin::build_index_menu() { if (_menu_present) return; // builds bk_menu tree and index menu TArray bk_tree; TToken_string tt(128); int i; // build tree for (i = 0; i < _bookmarks->items(); i++) { BkDef& bkd = (BkDef&)(*_bookmarks)[i]; tt.format("%d", bkd._id + 1000); tt.add(bkd._txt); _BkMenuItem* bkit = new _BkMenuItem((const char*)tt); bkit->_id = bkd._id; int father_id = bkd._father_id == -1 ? 0 : bkd._father_id; if (father_id == 0) // toplevel bk_tree.add(bkit); else { _BkMenuItem* father = find_menu_node(bk_tree, father_id); if (father != NULL) { if (father->_arr == NULL) father->_arr = new TArray(4); father->_arr->add(bkit); } } } // build menu if (bk_tree.items() > 0) { TString_array top(1); top.add("1000|Indice"); add_menu(top); } TArray flat(4); build_menu_tree(flat, bk_tree, 0); for (i = 0; i < flat.items(); i++) { _BkMenuDesc& bds = (_BkMenuDesc&)flat[i]; if (bds._menu.items() > 0) add_menu(bds._menu, bds._father_id); } _menu_present = TRUE; } void TViswin::exec_link() { if (_linkID != -1) { if (!_toplevel) { // link da browsefile_field MASK_LINKHANDLER pl = _brwfld->_lh; if (pl != NULL) pl(_brwfld->mask(), _linkID, _multiple ? (const char*)_multiple_link : (const char*)_linktxt, TRUE); } else { bool reload = false; LINKHANDLER pl = printer().getlinkhandler(); if (pl) reload = pl(_linkID, _multiple ? (const char*)_multiple_link : (const char*)_linktxt); if (main_app().class_id() == CLASS_PRINT_APPLICATION) { if (!reload) { // Backward compatibility mode // dai opzione per rifare la stampa se e' arrivato un messaggio dall'applicazione chiamata TMailbox m; reload = m.next_s(MSG_LN) != NULL; } if (reload && yesno_box(TR("Si desidera riaggiornare la stampa?"))) { TPrint_application& papp = (TPrint_application&)main_app(); papp.repeat_print(); papp.current_cursor()->update(); xvtil_statbar_refresh (); stop_run(K_ENTER); } } } // _toplevel if (_toplevel) { set_focus(); _inside_linkexec = TRUE; check_link(); force_update(); do_events(); check_link (&_point); _inside_linkexec = FALSE; } } // linkID != -1 else beep(); } void TViswin::display_link (long y, long x1, long x2, const char *d) { if (!_link_displayed) { paint_link (y, x1, x2); _link_displayed = TRUE; if (_in_update) return; TString80 dd; dd.strncpy(d, 50); xvtil_statbar_set(dd); if (_showbuts) enable_button(DLG_LINK); if (_toplevel) enable_menu_item(M_VISWIN_LINK, true); if (!_toplevel && !_inside_linkexec) { // chiama l'handler per maschere con FALSE come terzo parametro MASK_LINKHANDLER pl = _brwfld->_lh; if (pl != NULL) pl(_brwfld->mask(), _linkID, _multiple ? (const char*)_multiple_link : (const char*)_linktxt, FALSE); } } } // @doc INTERNAL // @mfunc Cancella il link void TViswin::erase_link ( long y, // @parm Altezza del link da disegnare long x1, // @parm Prima coordinata x del link da cancellare long x2) // @parm Seconda coordinata x del link da cancellare { if (_link_displayed) { paint_link (y, x1, x2); _link_displayed = FALSE; if (!_in_update) { xvtil_statbar_set(""); xvtil_statbar_refresh(); if (_showbuts) disable_button(DLG_LINK); if (_toplevel) enable_menu_item(M_VISWIN_LINK, FALSE); } } } // @doc INTERNAL // @mfunc Disegna il link void TViswin::paint_link ( long y, // @parm Altezza del link da disegnare long x1, // @parm Prima coordinata x del link da disegnare long x2) // @parm Seconda coordinata x del link da disegnare { if (adjust_box (x1, x2, y)) invert_bar ((int)(x1 + (long)X_OFFSET), (int)(y + (long)Y_OFFSET), (int)(x2 + (long)X_OFFSET), (int)(y + (long)Y_OFFSET+1l)); } // @doc INTERNAL // @mfunc Modifica le dimensione di un box // @rdesc Ritorna se sono state modificate le dimensioni del box: // @flag TRUE | Sono state riassegnate le coordinate a

e

// @flag FALSE | Non sono state riassegnate le misure del box poiche'

e' nel testo bool TViswin::adjust_box ( long &x1, // @parm Prima coordinata da riassegnare long &x2, // @parm Seconda coordinata da riassegnare long y) // @parm Valore della riga che deve essere nel testo // @comm Sistema

e

in modo che il minore sia il primo, e controlla che

sia // nel testo (box e' su una sola riga, usata solo per i link) { if (y < origin ().y || y > origin ().y + _textrows) return FALSE; if (origin ().x > x1) x1 = origin ().x; if (origin ().x + _textcolumns < x2) x2 = origin ().x + _textcolumns; return TRUE; } // @doc INTERNAL // @mfunc Controlla se la posizione cursore

cade su un link ipertestuale e si // comporta di conseguenza // @rdesc Ritorna se la posizione cade sul link // @flag TRUE | Se ha constatato la corrispondenza // @flag FALSE | Se non ha constatato la corrispondenza bool TViswin::check_link ( TPoint* p) // @parm Posizione del cursore (default NULL) // @comm Se

e' NULL indica la posizione corrente del cursore { static int old_id = -1, plinkID = -1; static long y, x1, x2; static long py, px1, px2; if (p == NULL) // erase and go { if (old_id != -1) { erase_link (y, x1, x2); old_id = _linkID = plinkID = -1; py = px1 = px2 = x1 = y = x2 = 0l; } return FALSE; } // poi se e' il caso lo si risistema if (p == &_point) plinkID = -1; TArray & h = _txt.hotspots(); for (int i = 0; i < h.items (); i++) { TToken_string & t = (TToken_string &) h[i]; t.restart (); long ty = t.get_long (); long tx1 = t.get_long (); long tx2 = t.get_long (); if (p->y == ty && p->x < tx2 && p->x >= tx1) { // ci siamo int id = (int) t.get_long (4); if (ty != y || tx1 != x1 || tx2 != x2) { if (old_id != -1) erase_link (y, x1, x2); TToken_string & ttt = (TToken_string &) (*_links)[id]; ttt.restart (); _descr = ttt.get (); _linktxt = t.get(3); if (_multiple) { // get all parts of the same color const char *cp; _txt.read_line (ty); _multiple_link = ""; const char fg = *ttt.get(1); const char bg = *ttt.get(2); while ((cp = _txt.piece ())) { if (_txt.get_foreground() == fg && _txt.get_background() == bg) { _multiple_link.add (cp); _descr << ' ' << cp; } } } else _descr << _linktxt; old_id = _linkID = id; y = ty; x1 = tx1; x2 = tx2; display_link (y, x1, x2, _descr); } if (p == &_point) { _pdescr = _descr; plinkID = id; px1 = x1; px2 = x2; py = y; } return TRUE; } } // non sono su un bottone: puo' esserci il point if (old_id != -1 && plinkID == -1) { old_id = _linkID = -1; erase_link (y, x1, x2); x1 = x2 = y = 0l; } // se point e' su un bottone, evidenzia quello else if (plinkID != -1 && (x1 != px1 || x2 != px2 || y != py)) { // erase old one erase_link (y, x1, x2); old_id = _linkID = plinkID; x1 = px1; x2 = px2; y = py; _descr = _pdescr; display_link (y, x1, x2, _descr); return TRUE; } return FALSE; } bool TViswin::in_text (const TPoint & p) const { if (p.x > (X_OFFSET - 1) && p.x < columns() && p.y > (Y_OFFSET - 1) && p.y < (rows() - BUTTONROW_SIZE)) return TRUE; return FALSE; } // @doc INTERNAL // @mfunc Indica se occorre ridisegnare la selezione // // @rdesc Ritorna se e' necessario ridipingere la selezione bool TViswin::need_paint_sel ( bool smart) // @parm Indica se ridisegnarla in ogni caso // // @flag TRUE | Indica il ridisegno solamente se e' necessario // @flag FALSE | Indica il ridisegno in ogni caso { TPoint p1, p2; adjust_selection (p1, p2); long end = origin ().y + _textrows; bool r = _isselection; if (smart) r = r && ( (origin ().y >= p1.y - 1 && origin ().y <= p2.y + 1) || (end >= p1.y - 1 && end <= p2.y + 1)); return r; } void TViswin::erase_selection () { if (_sel_displayed) paint_selection (); _sel_displayed = FALSE; if (_toplevel) { enable_menu_item(M_VISWIN_COPY, FALSE); enable_menu_item(M_VISWIN_CLEAR, FALSE); } } void TViswin::display_selection () { if (!_sel_displayed) paint_selection (); _sel_displayed = TRUE; if (_toplevel) { enable_menu_item(M_VISWIN_COPY, TRUE); enable_menu_item(M_VISWIN_CLEAR, TRUE); } } // @doc INTERNAL // @mfunc Riposizona inizio e fine della selezione void TViswin::adjust_selection ( TPoint & p1, // @parm Primo punto per il riposizionamento della selezione TPoint & p2) // @parm Secondo punto per il riposizionamento della selezione // @comm Viene asseganto a

e

le coordinate di inizio e fine selezione { if (_sel_start.y < _sel_end.y) { p1 = _sel_start; p2 = _sel_end; } else { p1 = _sel_end; p2 = _sel_start; } } void TViswin::shift_screen(scroll dir) { RCT r; if (_scrolling) return; _scrolling = TRUE; // origin() e' gia' stata modificata switch (dir) { case up: case down: xvt_rect_set(&r, 0, taby(Y_OFFSET)/*+1*/, tabx(int(_textcolumns) + X_OFFSET), taby(int(_textrows) + Y_OFFSET)); xvt_dwin_scroll_rect (win(), &r, 0, dir == down ? taby(1) : -taby(1)); paint_row (dir == up ? origin ().y + _textrows - 1 : origin ().y); break; case left: case right: xvt_rect_set(&r, tabx(X_OFFSET), 0, tabx(int(_textcolumns) + X_OFFSET)/* + 2*/, taby(int(_textrows) + 1)/* - 2*/); xvt_dwin_scroll_rect (win (), &r, dir == right ? tabx(1) : -tabx(1), 0); paint_column (dir == left ? origin ().x + _textcolumns - 1 : origin ().x, dir == left); break; default: break; } _scrolling = FALSE; } // @doc INTERNAL // @mfunc Aggiunge un bottone alla finestra // // @rdesc Ritorna un puntatore al bottone (TControl) aggiunto TPushbutton_control* TViswin::add_button ( short id, // @parm Identificatore del bottone da aggiungere const char *caption, // @parm Testo del bottone da aggiungere short bup, // @parm Identificatore della bitmap normale short bdn) // @parm Identificatore della bitmap pramuta // @comm Aggiunge i bottoni nella finestra { TPushbutton_control* b = new TPushbutton_control(win(), id, -11, -1, 12, 2, "", caption, bup, bdn); _button.add(b); return b; } bool TViswin::enable_button(short id, bool on) { int i; for (i = _button.last(); i >= 0; i--) { TPushbutton_control* b = (TPushbutton_control*)_button.objptr(i); if (b->id() == id) { b->enable(on); break; } } return i >= 0; } void TViswin::repos_buttons () { if (_toplevel) { RCT wr; xvt_vobj_get_client_rect(win(), &wr); const int bar_h = BUTTONROW_SIZE * CHARY; const int bar_y = wr.bottom - bar_h + 1; for (int i = 0; i < _modules.items(); i++) { TImage& image = (TImage&)_modules[i]; const int iy = bar_y + (bar_h - image.height()) / 2; image.set_pos(4, iy); } const int buttons = _button.items(); if (buttons > 0) { RCT br; ((TPushbutton_control&)_button[0]).get_rect(br); const int width = br.right - br.left; int space = ((wr.right - wr.left) - buttons * width) / (buttons + 1); if (space < 0) space = 0; int x = space; const int by = br.top; for (int b = 0; b < buttons; b++) { const PNT p = { by, x }; xvt_rect_set_pos(&br, p); ((TPushbutton_control&)_button[b]).set_rect(br); x += space + width; } } } } void TViswin::open () { set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); repos_buttons(); TScroll_window::open(); show_buttons(_showbuts); force_update (); } // prints the window contents void TViswin::paint_screen () { RCT clip; get_clip_rect(clip); clip.left = clip.top = 0; xvt_dwin_set_clip(win(), &clip); for (int j = 0; j < _textrows; j++) { const long rw = origin ().y + j; if (rw < _txt.lines ()) paint_row (rw); else { if (!_isopen) { autoscroll (FALSE); set_mode (M_COPY); set_pen (COLOR_BLACK); PNT b, e; b.h = tabx(X_OFFSET-1); b.v = taby((int)(j + (long)Y_OFFSET - origin().y))/* -2 *****/; e.h = tabx(columns()); e.v = b.v; xvt_dwin_draw_set_pos(win(), b); xvt_dwin_draw_line(win(), e); set_pen (COLOR_LTGRAY); e.v++; b.v++; xvt_dwin_draw_set_pos (win (), b); xvt_dwin_draw_line (win (), e); set_brush (COLOR_DKGRAY); bar (X_OFFSET-1, (int)(j+(long)Y_OFFSET-origin().y), (int)columns()+1, (int)(rows()-(long)BUTTONROW_SIZE)); autoscroll (TRUE); } break; } } } // @doc INTERNAL // @mfunc Permette di stampare il background void TViswin::paint_background( long j, // @parm Numero della riga di cui stampare il background int row) // @parm Numero della riga a video sulla quale viene stampato il background { TPrinter& pr = printer(); if (_toplevel) { const word page = word((j-1) / pr.formlen() + 1); _bg = &pr.getbgdesc(page); } const bool isbackground = _bg->items() > 0 && pr.isgraphics(); const bool fink_mode = pr.get_fink_mode(); const int rw = (int)(j % (long)_formlen); const int ox = (int)origin().x; const int mx = ox + columns(); if (!fink_mode) { const char* line = pr.background_chars(rw); set_color(COLOR_BLACK, COLOR_WHITE); if (line != NULL && (int)strlen(line) > ox) stringat (X_OFFSET, row, &line[ox]); // return; } if (!isbackground) return; const TString& rwd = _bg->row(rw); char curcol = 'n'; char curpen = 'n'; char curpat = 'n'; char curwid = '1'; int x1, x2, y1, y2, id; PNT b, e; int cnt = 0; char ch; bool isbeg = FALSE; bool isend = FALSE; while ((ch = rwd[cnt++]) != '\0') { if (!fink_mode && (ch == 'v' || ch == 'o' || ch == 'u' || ch == 'h' || ch == 'r')) continue; switch (ch) { case 'v': // verticale intera x1 = (byte)rwd[cnt++]; if (x1 >= ox && x1 <= mx) { x1 += (X_OFFSET-1) - ox; b.h = e.h = tabx(2*x1+1)/2; b.v = taby(row); e.v = taby(row+1); xvt_dwin_draw_set_pos(win(), b); xvt_dwin_draw_line(win(), e); } break; case 'o': // verticale pezzo sopra x1 = (byte)rwd[cnt++]; if (x1 >= ox && x1 <= mx) { x1 += (X_OFFSET -1) - ox; b.h = e.h = tabx(2*x1+1) / 2; b.v = taby(row); e.v = taby(2*row+1)/2; xvt_dwin_draw_set_pos (win(), b); xvt_dwin_draw_line (win(), e); } break; case 'u': // verticale pezzo sotto x1 = (byte)rwd[cnt++]; if (x1 >= ox && x1 <= mx) { x1 += (X_OFFSET -1) - ox; b.h = e.h = tabx(2*x1+1)/2; b.v = taby(2*row+1)/2; e.v = taby(row + 1); xvt_dwin_draw_set_pos(win(), b); xvt_dwin_draw_line(win(), e); } break; case 'h': // orizzontale intera // x1 = (byte) rwd[cnt++] + (X_OFFSET -1) - ox; // x2 = (byte) rwd[cnt++] + (X_OFFSET -1) - ox; x1 = (byte) rwd[cnt++]; x2 = (byte) rwd[cnt++]; if (x1 <= mx && x2 >= ox) { x1 += (X_OFFSET -1) - ox; if (x1 < X_OFFSET) x1 = X_OFFSET; x2 += (X_OFFSET -1) - ox; b.v = e.v = taby(2*row+1) / 2; b.h = tabx(x1); e.h = tabx(x2 + 1); xvt_dwin_draw_set_pos(win(), b); xvt_dwin_draw_line(win(), e); } break; case 'r': // orizzontale scorciata agli estremi x1 = (byte) rwd[cnt++]; x2 = (byte) rwd[cnt++]; isbeg = ox <= (x1-1); isend = mx >= (x2-1); if (x1 <= mx && x2 >= ox) { x1 += (X_OFFSET -1) - ox; if (x1 < X_OFFSET) x1 = X_OFFSET; x2 += (X_OFFSET -1) - ox; b.v = e.v = taby(2*row+1) / 2; if (isbeg) b.h = tabx(2*x1+1) / 2; else b.h = tabx(x1); if (isend) e.h = tabx(2*x2+1) / 2; else e.h = tabx(x2 +1); 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 destinazione x2 = (byte)(rwd[cnt++]); // Larghezza destinazione (in caratteri) y2 = (byte)(rwd[cnt++]); // Altezza destinazione (in caratteri) if (id >= 0) { TImage* i = (TImage*)_images.objptr(id); if (i == NULL) { const TString_array& a = pr.image_names(); const TImage src(a.row(id)); if (src.ok()) { i = new TImage(src, x2*CHARX, y2*CHARY); _images.add(i, id); } } if (i && i->ok()) { RCT src; xvt_rect_set(&src, 0, y1*CHARY, i->width(), min((y1+1)*CHARY, i->height())); RCT dst; xvt_rect_set(&dst, 0, 0, tabx(x2), taby(1)); xvt_rect_offset(&dst, tabx(x1-origin().x+X_OFFSET), taby(row)); i->draw(win(), dst, src); } } 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 TViswin::get_clip_rect(RCT& clip) const { xvt_vobj_get_client_rect(win(), &clip); if (_rulers) { clip.left += tabx(X_OFFSET); clip.top += taby(1); } if (_showbuts) clip.bottom = clip.top + taby(int(_textrows)); } void TViswin::paint_image(int row, const char* cp) { TToken_string tok(cp+2, ','); TImage img(tok.get(0)); RCT clip; get_clip_rect(clip); xvt_dwin_set_clip(win(), &clip); const int x = tabx(X_OFFSET+tok.get_int()-int(origin().x)-1); const int y = taby(row); int dx = tabx(tok.get_int(3)-tok.get_int(1)+1); int dy = taby(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); } xvt_dwin_set_clip(win(), NULL); } void TViswin::paint_row (long j) { if (need_paint_sel (FALSE)) { TPoint p1, p2; adjust_selection (p1, p2); } const long y = origin ().y; const int row = (int) (j + (long)Y_OFFSET - y); autoscroll(FALSE); set_font(PRINT_FONT, XVT_FS_NONE, PRINT_HEIGHT); set_mode(M_COPY); set_opaque_text(TRUE); if (_rulers) { set_color(FOREGROUND, BACKGROUND); set_brush(BACKGROUND); printat(0, row, "%05ld", j + 1); } if (_scrolling) { hide_pen (); set_brush (COLOR_WHITE); RCT r; r.top = row * CHARY; r.left = tabx(X_OFFSET -1), r.bottom = r.top + taby(1)/* + 1*/; r.right = tabx(255); xvt_dwin_draw_rect (win (), &r); } paint_background(j, row); set_opaque_text(FALSE); const char *cp; int pos = 0; _txt.read_line (j, origin().x); while ((cp = _txt.piece ()) != NULL) { 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) { if (*cp == 'i') paint_image(row, cp); } else { set_font(PRINT_FONT, st, PRINT_HEIGHT); set_color(fg, bg); stringat(X_OFFSET+pos, row, cp); } pos += strlen (cp); } if (_scrolling && (pos < _textcolumns)) { set_color (COLOR_BLACK, COLOR_WHITE); TString256 fill; fill.spaces(256); stringat(X_OFFSET+pos, row, fill); } if ((j % _formlen) == (_formlen - 1) && _toplevel) // last row { PNT b, e; b.h = tabx(X_OFFSET -1); b.v = taby(row + Y_OFFSET) - 1; e.h = tabx(164); e.v = taby(row + Y_OFFSET) - 1; set_pen (COLOR_LTGRAY, 2, PAT_SOLID, P_DASH); xvt_dwin_draw_set_pos (win(), b); xvt_dwin_draw_line (win(), e); } autoscroll (TRUE); } // @doc INTERNAL // @mfunc Disegna una colonna void TViswin::paint_column ( long j, // @parm Colonna da disegnare bool end) // @parm Indica se si tratta dell'ultima colonna: // // @flag TRUE | E' l'ultima colonna ed implica uno scroll orizzonatle avvenuto // @flag FALSE | Non e' l'ultima colonna { paint_header (); set_opaque_text (FALSE); set_mode (M_COPY); TPoint p1, p2; if (need_paint_sel (FALSE)) adjust_selection (p1, p2); set_color (COLOR_BLACK, COLOR_WHITE); autoscroll (FALSE); RCT clipper; xvt_rect_set(&clipper, tabx(X_OFFSET), 0, tabx(X_OFFSET+1), taby(int(_textrows + 1))); if (end) xvt_rect_offset(&clipper, tabx(int(_textcolumns-1)), 0); xvt_dwin_set_clip(win(), &clipper); const int col = end ? (int) (_textcolumns + X_OFFSET -1) : X_OFFSET; set_brush(COLOR_WHITE); bar(col, Y_OFFSET, col+1, int(_textrows + Y_OFFSET)); const long orig_y = origin().y; const long last = min(_txt.lines() - orig_y, _textrows); for (long l = 0L; l < last; l++) { const long riga_txt = orig_y + l; const int riga_scr = (int)l+Y_OFFSET; paint_background (riga_txt, riga_scr); if ((riga_txt% _formlen) == (_formlen - 1) && _toplevel) { PNT b, e; b.h = tabx(short(col)); b.v = taby(riga_scr+1) -1 ; e.h = tabx(short(col+1)); e.v = taby(riga_scr+1) -1; set_pen (COLOR_LTGRAY, 2, PAT_SOLID, P_DASH); xvt_dwin_draw_set_pos (win(), b); xvt_dwin_draw_line (win(), e); } const char *c = (const char *) _txt.line (riga_txt); const int st = _txt.get_style ((int) j); set_font (PRINT_FONT, st, PRINT_HEIGHT); COLOR bg = trans_color (_txt.get_background ((int) j)); COLOR fg = trans_color (_txt.get_foreground ((int) j)); set_color (fg, bg); char str[2] = { (unsigned int)j < strlen (c) ? c[(int)j] : ' ', '\0' }; stringat (col, riga_scr, str); } xvt_dwin_set_clip(win(), NULL); autoscroll (TRUE); } void TViswin::draw_crossbars () // prints reference crossbars { if (_cross.v > taby(1) && _cross.v < taby(rows () - BUTTONROW_SIZE) && _cross.h > tabx (X_OFFSET - 1) && _cross.h < tabx(columns()) ) { set_pen (COLOR_BLACK); set_mode (M_XOR); PNT b1, e1, b2, e2; autoscroll (FALSE); b1.h = _cross.h; b1.v = taby(Y_OFFSET); e1.h = _cross.h; e1.v = taby((rows() - BUTTONROW_SIZE + (_rulers ? 0 : 1))); b2.h = tabx(X_OFFSET -1); b2.v = _cross.v; e2.h = tabx(columns()); e2.v = _cross.v; xvt_dwin_draw_set_pos (win (), b1); xvt_dwin_draw_line (win (), e1); xvt_dwin_draw_set_pos (win (), b2); xvt_dwin_draw_line (win (), e2); autoscroll (TRUE); } } void TViswin::display_crossbar () { if (!_cross_displayed) draw_crossbars (); _cross_displayed = TRUE; } void TViswin::erase_crossbar () { if (_cross_displayed) draw_crossbars (); _cross_displayed = FALSE; } void TViswin::display_point() { if (!_point_displayed) paint_point (); _point_displayed = TRUE; } void TViswin::erase_point() { if (_point_displayed) paint_point (); _point_displayed = FALSE; } // @doc INTERNAL // @mfunc Disegna il cursore in xor nello stile del momento void TViswin::paint_point ( bool erase) // @parm Indica di cancellare il cursore precedente (default FALSE): // // @flag TRUE | Cancella il cursore precedente // @flag FALSE | Mantiene il cursore precedente { autoscroll (FALSE); const int x = int(_point.x - origin().x + X_OFFSET); const int y = int(_point.y - origin().y + Y_OFFSET); if (_isbar) { invert_bar (X_OFFSET, y, (int)columns(), y+1); invert_bar (x, Y_OFFSET, x+1, (int)(rows() - BUTTONROW_SIZE)); } else { invert_bar (x, y, x+1, y+1); if (_rulers) { invert_bar (0, y, X_OFFSET-1, y+1); invert_bar (x, 0, x+1, 1); } } autoscroll (TRUE); } // draw screen header void TViswin::paint_header () { if (!_rulers) return; set_mode (M_COPY); set_opaque_text (TRUE); set_color (FOREGROUND, BACKGROUND); set_font (PRINT_FONT, XVT_FS_NONE, PRINT_HEIGHT); TString16 htmpst; for (int i = 1; i < 26; i++) { htmpst.format ("%d", i); htmpst.right_just (10, '.'); xvt_dwin_draw_text(win(), tabx(i*10 - 4 - int(origin().x)), CHARY-2, htmpst, 10); } autoscroll (FALSE); set_color (COLOR_WHITE, BACKGROUND); printat (0, 0, "P.%3ld", (origin().y / _formlen) + 1L); autoscroll (TRUE); } void TViswin::paint_selection () { TPoint p1, p2; adjust_selection (p1, p2); // paint rows for (long l = p1.y; l <= p2.y; l++) { int top, left, right; top = (int) (l - origin().y + Y_OFFSET); if (top > 0 && top <= _textrows) { left = p1.y == l ? (int)(p1.x-origin().x + (long)X_OFFSET) : X_OFFSET; right = p2.y == l ? (int)(p2.x-origin().x + (long)X_OFFSET) : (int)(_textcolumns + (long)X_OFFSET); autoscroll (FALSE); invert_bar (left, top, right, top + 1); autoscroll (TRUE); } } } // @doc INTERNAL // @mfunc Disegna la pagina che scorre void TViswin::paint_waitbar() { HIDDEN int pic = 0; ((TImage&)_modules[pic]).draw(win()); pic = (pic+1) & 0x3; } void TViswin::txt_clear(COLOR color) { autoscroll(FALSE); set_brush(color); set_mode(M_COPY); bar ((X_OFFSET-1), Y_OFFSET -1, columns()+16, rows()-BUTTONROW_SIZE); } bool TViswin::can_be_closed() const { ((TViswin*)this)->on_button(DLG_QUIT); return FALSE; } void TViswin::update () { if (_scrolling || _in_update) return; _in_update = TRUE; erase_point(); autoscroll(FALSE); set_mode(M_COPY); if (!_toplevel) TField_window::update(); check_link(); if (_isselection) erase_selection (); txt_clear(COLOR_WHITE); set_brush (BACKGROUND); if (_rulers) { bar (0, 0, columns() + 1, 1); bar (0, 0, 5, rows() + 1); } if (_showbuts && _isopen) paint_waitbar(); else if (_showbuts) ((TImage&)_modules[4]).draw(win()); autoscroll (TRUE); paint_screen(); paint_header(); if (_isselection) display_selection(); display_point(); check_link(&_point); autoscroll (TRUE); _need_scroll = none; _in_update = FALSE; } void TViswin::abort_print () { if (yesno_box ("Interruzione della stampa su video?")) { _txt.freeze (); freeze (); printer().freeze(); set_focus (); close_print(); } } void TViswin::scroll_error(long x, long y) { beep(); update_thumb(x, y); } void TViswin::on_button(short dlg) { switch (dlg) { case DLG_QUIT: if (_isopen) abort_print(); else { xvtil_statbar_set(""); xvtil_statbar_refresh(); stop_run(K_ENTER); } break; case DLG_PRINT: dispatch_e_menu(win(), M_VISWIN_PRINT); break; case DLG_PDF: xvtil_statbar_set (""); xvtil_statbar_refresh (); stop_run(CTRL_P); break; case DLG_SAVEREC: check_link(); call_editor(); update(); check_link(&_point); break; case DLG_LINK: exec_link(); break; default: TWindow::on_button(dlg); break; } } long TViswin::handler (WINDOW win, EVENT * ep) { static bool ignore = FALSE; int kdiff_x, kdiff_y; PNT newcross; TPoint p; bool tlnk = FALSE; int kdiff; long new_origin; switch (ep->type) { case E_USER: if (ep->v.user.id == E_ADDLINE) { set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); } else if (ep->v.user.id == E_ADDLINE_ONSCREEN) { set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); erase_point (); if (need_paint_sel (FALSE)) erase_selection (); paint_row (_txt.lines () - 1l); if (need_paint_sel (FALSE)) display_selection (); display_point (); force_update (); } autoscroll (FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; autoscroll (TRUE); break; case E_COMMAND: if (ep->v.cmd.tag > 1000 && ep->v.cmd.tag < 2000) { // bookmark int index = ep->v.cmd.tag - 1001; BkDef& bds = (BkDef&)(*_bookmarks)[index]; goto_pos(bds._row, 0l); } else switch(ep->v.cmd.tag) { case M_VISWIN_STOP: // interrompi dispatch_e_char(win, K_ESC); break; case M_VISWIN_LINK: // collega dispatch_e_char(win, CTRL_G); break; case M_VISWIN_EDIT: // esporta dispatch_e_char(win, CTRL_E); break; case M_VISWIN_PRINT: // stampa xvtil_statbar_set (""); xvtil_statbar_refresh (); stop_run(CTRL_S); break; case M_SHOW_RULERS: // mostra righelli show_rulers(_rulers == 0); check_menu_item(M_SHOW_RULERS, _rulers != 0); break; case M_SHOW_BUTTONS: // mostra bottoni show_buttons(!_showbuts); check_menu_item(M_SHOW_BUTTONS, _showbuts); break; case M_VISWIN_QUIT: // chiudi xvtil_statbar_set (""); xvtil_statbar_refresh (); stop_run (K_ENTER); break; case M_VISWIN_COPY: // copia nella clipboard dispatch_e_char(win, CTRL_C); break; case M_VISWIN_CLEAR: // annulla selezione dispatch_e_char(win,K_ENTER); break; case M_VISWIN_SEARCH: // cerca find(); break; case M_VISWIN_NEXT: // cerca il prossimo find_next(); break; case M_VISWIN_REDRAW: // ridisegna refresh(); break; } break; case E_CONTROL: break; case E_TIMER: if (ep->v.timer.id == _timer) { xvt_timer_destroy (_timer); _timer = 0; } else if (ep->v.timer.id == _wtimer) { if (_showbuts) paint_waitbar (); if (!_isopen) { xvt_timer_destroy (_wtimer); _wtimer = 0; } } break; case E_MOUSE_DBL: break; case E_MOUSE_DOWN: autoscroll(FALSE); p = dev2log(ep->v.mouse.where); autoscroll(TRUE); xvt_win_trap_pointer (win); if (ep->v.mouse.button == 0) // left button: text selection { if (need_paint_sel (FALSE)) { erase_selection (); _isselection = FALSE; } if (!in_text (p) || (p.y + origin().y) >= _txt.lines ()) { ignore = TRUE; break; } erase_point (); // _sel_start = ep->v.mouse.where; _sel_start = p; _sel_start.x += (origin ().x - X_OFFSET); _sel_start.y += (origin ().y - Y_OFFSET); _sel_end = _sel_start; _selecting = TRUE; } else { // show crossbars _cross = ep->v.mouse.where; display_crossbar (); _iscross = TRUE; } break; case E_MOUSE_UP: xvt_win_release_pointer (); if (ep->v.mouse.button == 0) // left button: text selection/move // point { autoscroll(FALSE); p = dev2log(ep->v.mouse.where); autoscroll(TRUE); if (_isopen && _toplevel && (p.x >= 4 && p.x <= X_OFFSET) && (p.y >= (int)rows() - BUTTONROW_SIZE && p.y <= (int)rows() - Y_OFFSET)) { abort_print (); ignore = TRUE; } if (ignore) { ignore = FALSE; _selecting = FALSE; break; } // confirm selection & store p.x += (origin ().x - X_OFFSET); p.y += (origin ().y - Y_OFFSET); if (_sel_start == p) { if (_isselection) { _isselection = FALSE; erase_selection (); } if (_sel_start == _point && !_selecting) { dispatch_e_char (win, K_F5); } else { _point.x = p.x; _point.y = p.y; if (_point.y > _txt.lines ()) _point.y = _txt.lines () - 1l; if (_point.y < 0) _point.y = 0; if (_point.x < 0) _point.x = 0; if (_point.x > 255) _point.x = 255; check_link (&_point); display_point (); } } else { _sel_end.x = p.x; _sel_end.y = p.y; if (_sel_end.y >= _txt.lines ()) _sel_end.y = _txt.lines () - 1l; if (_sel_end.y < 0) _sel_end.y = 0; if (_sel_end.x < 0) _sel_end.x = 0; if (_sel_end.x > 255) _sel_end.x = 255; _point = _sel_end; _isselection = _selecting; check_link (&_point); display_point (); } _selecting = FALSE; } else { erase_crossbar (); _iscross = FALSE; } break; case E_MOUSE_MOVE: { if (_selecting || _iscross) { autoscroll(FALSE); p = dev2log(ep->v.mouse.where); autoscroll(TRUE); if (_selecting) _isselection = TRUE; // scroll if necessary if (p.y >= _textrows + 1l) { if (_isselection) erase_selection (); if (_iscross) erase_crossbar (); dispatch_e_scroll (win, K_DOWN); if (_isselection) display_selection (); if (_iscross) display_crossbar (); } else if (p.y <= 0l) { if (_isselection) erase_selection (); if (_iscross) erase_crossbar (); dispatch_e_scroll (win, K_UP); if (_isselection) display_selection (); if (_iscross) display_crossbar (); } else if (p.x <= (long)(X_OFFSET - 1)) { if (_isselection) erase_selection (); if (_iscross) erase_crossbar (); dispatch_e_scroll (win, K_LEFT); if (_isselection) display_selection (); if (_iscross) display_crossbar (); } else if (p.x >= _textcolumns + X_OFFSET) { if (_isselection) erase_selection (); if (_iscross) erase_crossbar (); dispatch_e_scroll (win, K_RIGHT); if (_isselection) display_selection (); if (_iscross) display_crossbar (); } if (_selecting) { if (in_text (p)) { p.x += (origin ().x - X_OFFSET); p.y += (origin ().y - Y_OFFSET); _point = p; if (_point.y >= _txt.lines ()) _point.y = _txt.lines () - 1l; } if (_point != _sel_end) { erase_selection (); _sel_end = _point; display_selection (); } } } if (_iscross) { newcross = ep->v.mouse.where; if (_cross.h != newcross.h || _cross.v != newcross.v) { erase_crossbar (); _cross = newcross; display_crossbar (); } } } break; case E_SIZE: if (is_open ()) { check_link (); erase_point (); if (_isselection) erase_selection (); autoscroll (FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; autoscroll (TRUE); repos_buttons (); display_point (); force_update (); do_events (); check_link (&_point); } break; case E_HSCROLL: case E_VSCROLL: { erase_point (); tlnk = TRUE; switch (ep->v.scroll.what) { case SC_PAGE_UP: if (ep->type == E_VSCROLL) { if (origin().y > 0) { kdiff = (int) (_point.y - origin ().y); new_origin = origin ().y > _textrows ? origin().y - _textrows + 1l : 0; _point.y = new_origin + kdiff; check_link (); update_thumb (origin ().x, new_origin); update (); // ORRIIIBILE! check_link (&_point); } else scroll_error(-1, 0); } else { if (origin ().x > 0) { kdiff = (int) (_point.x - origin ().x); new_origin = origin ().x > _textcolumns ? origin().x - _textcolumns + 1 : 0; _point.x = new_origin + kdiff; check_link (); update_thumb(new_origin, origin().y); update (); // AAAARGH! check_link (&_point); } else scroll_error(0, -1); } break; case SC_LINE_UP: if (ep->type == E_VSCROLL) { if (origin ().y > 0l) { _point.y--; if (need_paint_sel ()) erase_selection (); check_link (); update_thumb (origin().x, origin().y - 1l); //_need_scroll = down; update (); // AAAARGH! check_link (&_point); } else scroll_error(-1, 0); } else { if (origin ().x > 0l) { if (need_paint_sel (FALSE)) erase_selection (); check_link (); update_thumb (origin().x - 1l, origin().y); _point.x--; _need_scroll = right; } else scroll_error(0, -1); } break; case SC_PAGE_DOWN: if (ep->type == E_VSCROLL) { if ((origin().y + _textrows) < _txt.lines()) { kdiff = (int) (_point.y - origin ().y); new_origin = (_txt.lines () - origin ().y) > (_textrows * 2l) ? origin ().y + _textrows - 1 : _txt.lines () - _textrows; _point.y = new_origin + kdiff; check_link (); update_thumb (origin ().x, new_origin); update (); // AAAARGH! check_link (&_point); } else scroll_error(-1, _txt.lines()-_textrows/*-1*/); } else { if ((origin().x + _textcolumns) < 256) { kdiff = (int) (_point.x - origin ().x); new_origin = (256 - origin ().x) > _textcolumns ? origin ().x + _textcolumns - 1 : 256 - _textcolumns; _point.x = new_origin + kdiff; check_link (); update_thumb (new_origin, origin().y); update (); // AAAARGH! check_link (&_point); } else scroll_error(255-_textcolumns, -1); } break; case SC_LINE_DOWN: if (ep->type == E_VSCROLL) { if ((origin().y + _textrows) < _txt.lines ()) { if (need_paint_sel ()) erase_selection (); check_link (); update_thumb (origin ().x, origin ().y + 1l); _point.y++; // _need_scroll = up; update (); // AAAARGH! check_link (&_point); } else scroll_error(-1, _txt.lines()-_textrows/*-1*/); } else { if ((origin ().x + _textcolumns) < 256) { if (need_paint_sel (FALSE)) erase_selection (); check_link (); update_thumb (origin ().x + 1l, origin ().y); _need_scroll = left; _point.x++; } else scroll_error(255-_textcolumns, -1); } break; case SC_THUMB: check_link (); kdiff_x = (int) (_point.x - origin ().x); kdiff_y = (int) (_point.y - origin ().y); p.x = ep->type == E_VSCROLL ? origin ().x : ep->v.scroll.pos; p.y = ep->type == E_HSCROLL ? origin ().y : ep->v.scroll.pos; if ((p.y + _textrows) >= _txt.lines ()) p.y = _txt.lines () - _textrows -1; if ((p.x + _textcolumns) >= 255) p.x = 255 - _textcolumns; update_thumb (p.x, p.y); _point.x = ep->type == E_VSCROLL ? origin ().x : origin ().x + kdiff_x; _point.y = ep->type == E_HSCROLL ? origin ().y : origin ().y + kdiff_y; update (); check_link (&_point); break; default: break; } // for failed scrollings if (!_selecting && _need_scroll == none) { check_link (&_point); display_point (); } } break; default: break; } if (_need_scroll != none) { const scroll tmp = _need_scroll; _need_scroll = none; shift_screen (tmp); if (!_selecting) { check_link (&_point); display_point (); } if (_isselection) display_selection (); } return TWindow::handler (win, ep); } bool TViswin::on_key(KEY key) { if (_timer) return TRUE; _timer = xvt_timer_create (win (), 50l); EVENT_TYPE type = E_USER; if (key == K_UP || key == K_DOWN || key == K_LEFT || key == K_RIGHT) if (_selflag) key += K_SHIFT; if (_selecting && key != K_SHIFT_UP && key != K_SHIFT_DOWN && key != K_SHIFT_LEFT && key != K_SHIFT_RIGHT) _selecting = FALSE; switch (key) { case K_F7: find(); break; case K_F3: find_next(); break; case CTRL_E: if (_isedit) { check_link (); call_editor (); set_focus (); update (); check_link (&_point); } break; case CTRL_G: exec_link(); break; case CTRL_C: sel_to_clipboard(); break; case CTRL_S: if (_isprint) stop_run(CTRL_S); break; case CTRL_P: if (_isprint) stop_run(CTRL_P); break; case CTRL_R: check_link (); force_update (); do_events (); check_link (&_point); break; case K_ESC: if (_isopen && _toplevel) abort_print (); else { xvtil_statbar_set (""); xvtil_statbar_refresh (); stop_run (K_ESC); } break; case K_ENTER: if (_isselection) { erase_selection (); _isselection = FALSE; } if (_toplevel) exec_link(); break; case K_TAB: if (!_toplevel) { TMask& m = owner().mask(); const int pos = m.id2pos(owner().dlg()); for (int i = pos+1; i < m.fields(); i++) { const TMask_field& f = m.fld(i); if (f.active()) { m.set_focus_field(f.dlg()); break; } } } break; case K_BTAB: if (!_toplevel) { TMask& m = owner().mask(); const int pos = m.id2pos(owner().dlg()); for (int i = pos-1; i >= 0; i--) { const TMask_field& f = m.fld(i); if (f.active()) { m.set_focus_field(f.dlg()); break; } } } break; case K_SPACE: case K_CTRL_ENTER: if (_linkID != -1) exec_link(); break; case K_LHOME: update_thumb (0, 0); _point.set (0, 0); check_link (&_point); force_update(); break; case K_LEND: update_thumb (0, _txt.lines () - _textrows); _point.set (0, _txt.lines () - 1); check_link (&_point); force_update(); break; case K_RIGHT: case K_LEFT: case K_WRIGHT: case K_WLEFT: case K_ALT_RIGHT: case K_ALT_LEFT: case K_SHIFT_RIGHT: case K_SHIFT_LEFT: type = E_HSCROLL; break; case K_UP: case K_DOWN: case K_NEXT: case K_PREV: case K_CTRL_UP: case K_CTRL_DOWN: case K_SHIFT_UP: case K_SHIFT_DOWN: type = E_VSCROLL; break; case K_F5: check_link (); erase_point (); _isbar = !_isbar; force_update (); do_events (); check_link (&_point); break; case K_F6: _selflag = !_selflag; break; case '+': if (PRINT_HEIGHT <= 14) { PRINT_HEIGHT += 2; force_update(); } break; case '-': if (PRINT_HEIGHT >= 6) { PRINT_HEIGHT -= 2; force_update(); } default: break; } switch (type) { case E_HSCROLL: case E_VSCROLL: { erase_point (); check_link (); switch (key) { case K_PREV: dispatch_e_scroll (win(), K_PREV); break; case K_NEXT: dispatch_e_scroll (win(), K_NEXT); break; case K_WLEFT: dispatch_e_scroll (win(), K_BTAB); break; case K_WRIGHT: dispatch_e_scroll (win(), K_TAB); break; case K_CTRL_UP: dispatch_e_scroll (win(), K_UP); break; case K_CTRL_DOWN: dispatch_e_scroll (win(), K_DOWN); break; case K_ALT_LEFT: dispatch_e_scroll (win(), K_LEFT); break; case K_ALT_RIGHT: dispatch_e_scroll (win(), K_RIGHT); break; case K_UP: case K_SHIFT_UP: if (key == K_SHIFT_UP) { if (need_paint_sel (FALSE)) erase_selection (); if (!_selecting) { _sel_start = _point; _selecting = TRUE; } } if (_point.y > 0l) { if (_point.y == origin ().y) { if (need_paint_sel ()) erase_selection (); update_thumb (origin ().x, --_point.y); _need_scroll = down; } else _point.y--; if (key == K_SHIFT_UP) { _sel_end = _point; _isselection = TRUE; } } else beep (); break; case K_LEFT: case K_SHIFT_LEFT: if (_point.x > 0l) { if (key == K_SHIFT_LEFT) { if (need_paint_sel (FALSE)) erase_selection (); if (!_selecting) { _sel_start = _point; _selecting = TRUE; } } if (_point.x == origin ().x) { if (need_paint_sel (FALSE)) erase_selection(); update_thumb (--_point.x, origin ().y); _need_scroll = right; } else _point.x--; if (key == K_SHIFT_LEFT) { _sel_end = _point; _isselection = TRUE; } } else beep (); break; case K_DOWN: case K_SHIFT_DOWN: if (_point.y < (_txt.lines() - 1)) { if (key == K_SHIFT_DOWN) { if (need_paint_sel (FALSE)) erase_selection(); if (!_selecting) { _sel_start = _point; _selecting = TRUE; } } if (_point.y == origin().y + _textrows - 1) { if (need_paint_sel()) erase_selection(); // check_link(); update_thumb (origin().x, (++_point.y) - _textrows + 1); _need_scroll = up; } else _point.y++; if (key == K_SHIFT_DOWN) { _sel_end = _point; _isselection = TRUE; } } else beep (); break; case K_RIGHT: case K_SHIFT_RIGHT: if (_point.x < 256) { if (key == K_SHIFT_RIGHT) { if (need_paint_sel (FALSE)) erase_selection (); if (!_selecting) { _sel_start = _point; _selecting = TRUE; } } if (_point.x == (origin ().x + _textcolumns - 1)) { if (need_paint_sel (FALSE)) erase_selection (); // check_link(); update_thumb ((++_point.x) - _textcolumns + 1l, origin ().y); _need_scroll = left; } else _point.x++; if (key == K_SHIFT_RIGHT) { _sel_end = _point; _isselection = TRUE; } } else beep(); break; default: break; } if (_need_scroll != none) { scroll tmp = _need_scroll; _need_scroll = none; shift_screen (tmp); } if (_isselection) display_selection (); check_link (&_point); update(); } break; default: break; } return TWindow::on_key (key); } void TViswin::sel_to_clipboard() { if (!_isselection) return; TPoint p1, p2; adjust_selection (p1, p2); TString_array txt; _txt.write(txt, &p1, &p2); long size = 0l; int eol_len = strlen(EOL_SEQ); xvt_cb_open(TRUE); // open clipboard int i; for (i = 0; i < txt.items(); i++) size += txt.row(i).len() + eol_len; char* p = xvt_cb_alloc_data(size); // allocate clipboard if (p == NULL) { error_box(FR("Impossibile allocare una clipboard di %ld bytes"), size); return; } // put data for (i = 0; i < txt.items(); i++) { const TString& s = txt.row(i); const int slen = s.len(); int j; for (j = 0; j < slen; j++) *p++ = s[j]; for (j = 0; j < eol_len; j++) *p++ = EOL_SEQ[j]; } if (!xvt_cb_put_data(CB_TEXT, NULL, size, (PICTURE)NULL)) error_box("Errore di copiatura del testo nella clipboard"); xvt_cb_free_data(); // free memory xvt_cb_close(); // close clipboard } bool TViswin::call_editor() { TFilename pdf; const KEY key = spotlite_ask_name(pdf); bool ok = key >= 'A' && key <= 'Z'; switch (key) { case 'A': ok = printer().print_pdf(_txt, pdf); if (ok) spotlite_notify(pdf); break; case 'X': ok = _txt.write_xls(pdf); if (ok) ::edit_url(pdf); break; case 'E': if (_isselection) { TPoint p1, p2; adjust_selection (p1, p2); ok = _txt.write (pdf, &p1, &p2); } else ok = _txt.write (pdf, NULL, NULL); if (ok) ::edit_url(pdf); break; case 'M': ok = printer().print_pdf(_txt, pdf); if (ok) spotlite_send_mail(pdf); break; case 'P': ok = printer().print_pdf(_txt, pdf); if (ok) xvt_sys_goto_url(pdf, "open"); break; default: ok = false; break; } return ok; } void TViswin::add_line (const char *l) { if (_isopen && !_frozen) { if (_txt.frozen ()) // error writing files { close_print (); return; } _txt.append (l); const long tot = _txt.lines(); const bool visible = (tot - origin().y) <= _textrows; if (visible) { EVENT ev; ev.type = E_USER; ev.v.user.id = E_ADDLINE_ONSCREEN; xvt_win_dispatch_event (win(), &ev); } else set_scroll_max (MAXLEN - 1, tot-1); if ((tot & 0xF) == 0) do_events (); } } void TViswin::destroy_lines() { if (_isopen && !_frozen) { _txt.destroy(); force_update(); } } void TViswin::close_print () { _isopen = FALSE; if (_showbuts) { xvt_timer_destroy (_wtimer); _wtimer = 0; } if (_toplevel) { xvt_menu_set_item_title(win(), M_VISWIN_QUIT, TR("Fine\tESC")); enable_menu_item(M_VISWIN_STOP, FALSE); if (_isedit) enable_button(DLG_SAVEREC); if (_isprint) { enable_button(DLG_PRINT); enable_menu_item(M_VISWIN_PRINT, TRUE); } // build bookmark menu tree _bookmarks = &(printer().get_bookmarks()); if (_bookmarks->items() > 0) build_index_menu(); } const TImage* i = (TImage*)_images.objptr(0); set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); force_update (); } void TViswin::goto_end() { goto_pos(0l, _txt.lines () - _textrows); } void TViswin::goto_top() { goto_pos(0l,0l); } // @doc INTERNAL // @mfunc Sposta la visualizzazione di stampa alla posizione indicata void TViswin::goto_pos( long r, // @parm Riga a cui spostare la visualizzazione di stampa long c, // @parm Colonna a cui spostare la visualizzazione di stampa bool moveorigin) // @parm Indica se occorre spostare l'origine (default TRUE) // @xref e { if (r >= _txt.lines() || c >= 256) return; check_link(); erase_point(); if (_isselection) erase_selection(); _point.x = c; _point.y = r; if (!moveorigin) c = (c > (origin().x + _textcolumns)) ? c - origin().x : 0l; if (_txt.lines() > _textrows) update_thumb(c,r); check_link(&_point); if (_isselection) display_selection(); display_point(); refresh(); } void TViswin::refresh() { force_update(); } // @doc INTERNAL // @mfunc Funzione di ricerca non interattiva // // @rdesc Ritorna la riga in cui e' stata trovato il testo (-1 se non e' stato trovato) long TViswin::search( const char* txt, // @parm Testo da cercare int& pos, // @parm Intero in cui posizionare la posizione del carattere long from, // @parm Posizione all'interno della riga da cui iniziare la ricerca (default 0) bool down, // @parm Indica se la ricerca va effettuata all'indietro: // // @flag TRUE | Ricerca dalla posizione indicata all'inizio della riga (default) // @flag FALSE | Ricerca dalla posizione indicata alla fine della riga bool cs, // @parm Indica se ricerca il testo con criterio case sensitive (default FALSE) bool regx) // @parm indica se considerare espressioni regolari (def FALSE) { return _txt.search(txt,pos,from,down, cs, regx); } // @doc INTERNAL // @mfunc Funzione di sostituzione di un testo all'interno di una riga non interattiva // // @rdesc Ritorna la posizione in cui e' stato sostituito il testo. Ritorna -1 se non e' stata // fatto nessuna operazione di sostituzione. int TViswin::replace( long l, // @parm Numero della riga nella quale sostituire il testo const char* txt, // @parm Testo da inserire nella riga int pos, // @parm Posizione nella quale inserire il testo (default 0) int len) // @parm Lunghezza del testo da sostituire (default -1) { if (l == -1l) return -1; int ret = _txt.replace(l,txt,pos,len); if (ret != -1) { TPoint p; p.x = pos; p.y = l; } return ret; } void TViswin::find() { TMask m("bagn005"); m.set(F_STRING, _txt_to_find); m.set(F_DIRECT, _down_dir ? "D" : "U"); m.set(F_CASE, _case_sensitive ? "X" : ""); m.set(F_REGEXP, _regexp ? "X" : ""); if (m.run() == K_ENTER) { _txt_to_find = m.get(F_STRING); _down_dir = m.get(F_DIRECT) == "D"; _case_sensitive = m.get_bool(F_CASE); _regexp = m.get_bool(F_REGEXP); int x; long l = search(_txt_to_find, x, _point.y, _down_dir, _case_sensitive, _regexp); if (l == -1l) { _last_found.y = -1l; beep(); } else { goto_pos(l, (long)x, FALSE); _last_found.x = (long)x; _last_found.y = l; } } if (_toplevel) enable_menu_item(M_VISWIN_NEXT, TRUE); } void TViswin::find_next() { int x; if (_txt_to_find.empty() || _last_found.y == -1l) beep(); else { long l = search(_txt_to_find, x, _point.y+(_down_dir ? 1l : -1l), _down_dir, _case_sensitive, _regexp); if (l == -1) beep(); else goto_pos(l,x,FALSE); } } void TViswin::show_rulers (bool on) { _rulers = on; autoscroll(FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; autoscroll(TRUE); refresh(); } // @doc INTERNAL // @mfunc Mostra/nasconde i bottoni della finestra di anteprima void TViswin::show_buttons( bool on) // @parm Indica l'operazione da svolgere: // // @flag TRUE | Mostra i bottoni della finestra (default) // @flag FALSE | Nasconde i bottoni della finestra { _showbuts = on; autoscroll (FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; autoscroll(TRUE); for (int i = 0; i < _button.items(); i++) ((TPushbutton_control&)_button[i]).show(on); refresh(); } TViswin::TViswin(const char *fname, const char *title, bool editbutton, bool printbutton, bool linkbutton, int x, int y, int height, int width, byte rulers, // overridden by config parms WINDOW parent, TBrowsefile_field* brwfld): TField_window(x, y, width, height, parent, brwfld), _filename (fname), _islink (linkbutton), _isedit (editbutton), _isprint (printbutton), _iscross (FALSE), _selecting (FALSE), _isselection (FALSE), _isbar (FALSE), _scrolling (FALSE), _timer (0), _wtimer(0), _selflag (FALSE), _sel_displayed (FALSE), _link_displayed (FALSE), _cross_displayed (FALSE), _point_displayed (FALSE), _need_scroll (none), _txt (fname, BUFFERSIZE), _txt_to_find(64), _in_update(FALSE), _down_dir(TRUE), _case_sensitive(FALSE), _regexp(FALSE), _multiple (FALSE), _frozen (FALSE), _rulers(rulers), _showbuts(FALSE), _menu_present(FALSE), _brwfld(brwfld) { TWait_cursor hourglass; if (title == NULL) title = fname ? fname : "Anteprima di stampa"; _last_found.y = -1; _isopen = fname == NULL || *fname <= ' '; if (_isopen) _filename = _txt.name(); if (parent == NULL_WIN) parent = TASK_WIN; _toplevel = brwfld == NULL; // parent == TASK_WIN; if (_toplevel) { // load info from config on buttons and rulers TConfig cnf(CONFIG_USER, "Visualizzazione"); _showbuts = cnf.get_bool("Bottoni", NULL, -1,TRUE); // Se rulers vale 3 allora leggi dal config il vero valore if (_rulers != 0 && _rulers != 1) _rulers = cnf.get_bool("Righelli", NULL, -1, TRUE); PRINT_HEIGHT = cnf.get_int("FontSize", NULL, -1, PRINT_HEIGHT); } else PRINT_HEIGHT = 10; // height = rows(); qui const int larg = 76; const int alt = 20; RCT r; xvt_vobj_get_client_rect (parent, &r); int maxlarg = width == 0 ? (r.right / CHARX - 6) : width; int maxalt = height == 0 ? (r.bottom / CHARY - 6) : height; if (_toplevel && larg > maxlarg) maxlarg = larg; if (_toplevel && alt > maxalt) maxalt = alt; int i; for (i = 0; i < 4; i++) _modules.add(new TImage(BMP_MODULE1 + i), i); _modules.add(new TImage(BMP_MODULE), i); for (i = 0; i < _modules.items(); i++) ((TImage*)_modules.objptr(i))->convert_transparent_color(MASK_BACK_COLOR); if (_toplevel) { const long flags = WSF_HSCROLL | WSF_VSCROLL | WSF_SIZE; WIN_TYPE rt = W_DOC; WINDOW myself = create(x, y, maxlarg, maxalt, title, flags, rt, parent, _toplevel ? VISWIN_BAR : 0); attach_interface(myself, BACKGROUND); } else { // La finestra e' gia' creata automaticamente dal TWindowed_field } set_opaque_text (TRUE); set_font (PRINT_FONT, XVT_FS_NONE, PRINT_HEIGHT); if (_toplevel) { if (width == 0 && height == 0) maximize(); enable_menu_item(M_VISWIN_COPY, FALSE); enable_menu_item(M_VISWIN_CLEAR, FALSE); enable_menu_item(M_SHOW_RULERS, TRUE); enable_menu_item(M_SHOW_BUTTONS, TRUE); check_menu_item(M_SHOW_RULERS, _rulers != 0); check_menu_item(M_SHOW_BUTTONS, _showbuts); enable_menu_item(M_VISWIN_PRINT, FALSE); } if (_txt.lines() > 0l) set_scroll_max (MAXLEN - 1, _txt.lines () <= _textrows ? _txt.lines () : _txt.lines () - _textrows); if (_toplevel) { add_button (DLG_QUIT, "", BMP_QUIT, BMP_QUITDN); if (_isedit) { add_button(DLG_SAVEREC, BR("~Registra", 8), BMP_SAVEREC, BMP_SAVERECDN); disable_button(DLG_SAVEREC); } if (_islink) { add_button(DLG_LINK, "", BMP_LINK); disable_button(DLG_LINK); } if (_isprint) { add_button (DLG_PRINT, "", BMP_PRINT); disable_button(DLG_PRINT); enable_menu_item(M_VISWIN_PRINT, FALSE); } } if (_isopen && _showbuts) _wtimer = xvt_timer_create(win(), 750L); _point.set (0, 0); autoscroll (FALSE); _textrows = TEXTROWS; _textcolumns = TEXTCOLUMNS; autoscroll (TRUE); _links = _toplevel ? &(printer().links()) : &(_brwfld->_links); _multiple = _toplevel ? (printer ().ismultiplelink()) : (_brwfld->is_multiple_link()); _bg = _toplevel ? &(printer().getbgdesc()) : &_brwfld->get_bg_desc(); _formlen = _toplevel ? printer().formlen() : height; _linkID = -1; _inside_linkexec = FALSE; for (i = 0; i < _links->items (); i++) { TToken_string & t = (TToken_string &) (*_links)[i]; char f = *(t.get(1)); char b = *(t.get(2)); t.restart(); _txt.set_hotspots(f, b); } } TViswin ::~TViswin () { // avoid deleting child window (already deleted by mask) if (!_toplevel) set_win(NULL_WIN); } /////////////////////////////////////////////////////////// // Campo di visualizzazione sulle maschere /////////////////////////////////////////////////////////// // Certified 100% TBrowsefile_field::TBrowsefile_field(TMask* m) : TWindowed_field(m), _lh(NULL), _m_link(FALSE), _background(36) {} // Certified 100% word TBrowsefile_field::class_id() const { return CLASS_BROWSEFILE_FIELD; } // Certified 100% TBrowsefile_field::~TBrowsefile_field() { } // Certified 100% TField_window* TBrowsefile_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TViswin(_ctl_data._prompt, _ctl_data._prompt, FALSE, FALSE, FALSE, x, y, dy, dx, _flags.rightjust ? TRUE : FALSE, parent, this); } long TBrowsefile_field::set_text(const char* file, const char* line) // se line != NULL ritorna il numero dell'ultima riga del file che // comincia (trimmata) come passato; se non la trova ritorna -1 { long ret = -1; FILE* instr = NULL; fopen_s(&instr, file, "r"); // Secured FILE* instr = fopen(file, "r"); if (instr != NULL) { TWait_cursor hourglass; TString256 tmpp; long lines = 0l; while (!feof(instr)) { if (fgets(tmpp.get_buffer(), tmpp.size(), instr) == NULL) break; char& last = tmpp[tmpp.len()-1]; if (last == '\n') last = '\0'; add_line(tmpp); if (line != NULL) { if (tmpp.find(line) != -1) ret = lines; } lines++; } fclose(instr); } vis_win().close_print(); return ret; } int TBrowsefile_field::find_link(const char* descr) { for (int i = 0; i < _links.items(); i++) { TToken_string& tt = (TToken_string&)_links[i]; const TFixed_string d(tt.get(0)); if (d == descr) return i; } return -1; } int TBrowsefile_field::enable_link(const char *descr, char fg, char bg) { int lnk = find_link(descr); if (lnk < 0) { TToken_string *tt = new TToken_string(30); char b[2] = { '\0', '\0' }; tt->add(descr); b[0] = fg; tt->add(b); b[0] = bg; tt->add(b); lnk = _links.add(tt); vis_win()._txt.set_hotspots(fg, bg); } return lnk; } void TBrowsefile_field::disable_link(char fg, char bg) { for (int i = 0; i < _links.items (); i++) { TToken_string & t = (TToken_string&)_links[i]; const char f = *(t.get(1)); const char b = *(t.get()); if (f == fg && b == bg) { _links.remove(i, TRUE); break; } } } void TBrowsefile_field::set_background(const char* bg) { printer().parse_background(bg, _background); } void TBrowsefile_field::add_line(const char* l) { vis_win().add_line(l); } void TBrowsefile_field::close() { vis_win().close_print(); } void TBrowsefile_field::goto_pos(long r, long c) { vis_win().goto_pos(r,c,TRUE); } void TBrowsefile_field::goto_top() { vis_win().goto_top(); } void TBrowsefile_field::goto_end() { vis_win().goto_end(); } void TBrowsefile_field::refresh() { vis_win().refresh(); } const char* TBrowsefile_field::get_text(long line, int column, int len) { return vis_win()._txt.line(line,(long)column, len); } long TBrowsefile_field::lines() { return vis_win()._txt.lines(); }