#define XVT_INCL_NATIVE #define XI_INTERNAL #include #include #include #include #define __WINDOW_CPP #include #include /////////////////////////////////////////////////////////// // TRectangle /////////////////////////////////////////////////////////// void TRectangle::copy(const TRectangle& r) { x = r.x; y = r.y; _size = r._size; } void TRectangle::normalize() { if (_size.x < 0) { x += _size.x; _size.x = -_size.x; } if (_size.y < 0) { y += _size.y; _size.y = -_size.y; } } void TRectangle::set(long cx, long cy, long dx, long dy) { x = cx; y = cy; _size.set(dx, dy); normalize(); } void TRectangle::set(const TPoint& pt, const TPoint& sz) { set(pt.x, pt.y, sz.x, sz.y); } void TRectangle::set_bounds(long left, long top, long right, long bottom) { set(left, top, right-left, bottom-top); } bool TRectangle::contains(const TPoint& p) const { if (p.x < left()) return false; if (p.y < top()) return false; if (p.x > right()) return false; if (p.y > bottom()) return false; return true; } bool TRectangle::contains(const TRectangle& r) const { return r.left() >= left() && r.right() <= right() && r.top() >= top() && r.bottom() < bottom(); } bool TRectangle::intersects(const TRectangle& r) const { if (left() > r.right()) return false; if (right() < r.left()) return false; if (top() > r.bottom()) return false; if (bottom() < r.top()) return false; return true; } void TRectangle::merge(const TRectangle& rct) { long l = x, t = y, r = right(), b = bottom(); if (rct.x < l) l = rct.x; if (rct.y < t) t = rct.y; if (rct.right() > r) r = rct.right(); if (rct.bottom() > b) b = rct.bottom(); set_bounds(l, t, r, b); } void TRectangle::inflate(int dx, int dy) { x -= dx; y -= dy; _size.x += 2*dx; _size.y += 2*dy; normalize(); } void TRectangle::deflate(int dx, int dy) { inflate(-dx, -dy); } /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// HIDDEN MENU_ITEM* find_menu_item(MENU_ITEM* menu, MENU_TAG id, bool ismbar) { MENU_ITEM* fnd = NULL; MENU_ITEM* mn = ismbar ? &menu[0] : &menu->child[0]; for (int m = 0; mn != NULL && mn->tag != 0; m++, mn=ismbar?&menu[m]:&menu->child[m]) { fnd = mn->tag == id ? mn : find_menu_item(mn, id, FALSE); if (fnd != NULL) break; } return fnd; } HIDDEN bool remove_menu_item(MENU_ITEM* menu, MENU_TAG id, bool ismbar) { MENU_ITEM* mn = ismbar ? &menu[0] : &menu->child[0]; for (int m = 0; mn != NULL && mn->tag != 0; m++, mn=ismbar?&menu[m]:&menu->child[m]) { if (mn->tag == id) { do { xvt_mem_rep((DATA_PTR)mn, (DATA_PTR)(mn+1), sizeof(MENU_ITEM), 1); mn++; } while (mn->tag != 0); return TRUE; } else if (remove_menu_item(mn, id, FALSE)) return TRUE; } return FALSE; } HIDDEN void set_menu_item(MENU_ITEM& m, TToken_string& tt) { MENU_TAG tag = tt.get_int(0); TString flag = tt.items() <= 2 ? "": tt.get(2); char* text = NULL; if (strlen(tt.get(1)) > 0) { text = (char*)xvt_mem_alloc(strlen(tt.get(1)) + 1); strcpy(text, tt.get(1)); } m.tag = tag; m.text = text; m.enabled = flag.find('D') < 0; m.checkable = flag.find('C') >= 0 || flag.find('c') >= 0; m.checked = flag.find('c') >= 0; m.separator = text == NULL; } /////////////////////////////////////////////////////////// // TWindow_manager /////////////////////////////////////////////////////////// // @doc INTERNAL // @class TWindow_manager | Classe per la gestione di un array di finestre modali class TWindow_manager { // @author:(INTERNAL) Guido // @access:(INTERNAL) Private Member // @ccost:(INTERNAL) MAX_WIN | 8 | Numero massimo di finestre modali enum { MAX_WIN = 8 }; // @cmember:(INTERNAL) Stack contenente la finestra attiva TWindow* _window[MAX_WIN]; // @cmember:(INTERNAL) Stack pointer short _current; // @cmember:(INTERNAL) Permette di abilitare/disabilitare il menu' della task window (stesso // funzionamento della ) void menu_enable(bool) const; // @cmember:(INTERNAL) Tiene sempre disponibile un file con un numero di handle inferiore a 20 // (per sopperire ad una mancanza di XVT) FILE* _lowhandle; // @access Public Member public: // @cmember Costruttore TWindow_manager(); // @cmember Distruttore ~TWindow_manager(); // @cmember Registra la finestra

corrente void reg(TWindow* m); // @cmember De-registra la finestra corrente void unreg(const TWindow* m); // @cmember Ritorna il puntatore alla finestra corrente TWindow* cur_win() const { return (_current < 0) ? NULL : _window[_current]; } // @cmember Chiude tutte le finestre modali aperte void destroy(); // @cmember Ritorna TRUE se la finestra corrente puo' essere chiusa bool can_close() const; } WinManager; TWindow_manager::TWindow_manager() : _current(-1), _lowhandle(NULL) { } TWindow_manager::~TWindow_manager() { destroy(); } void TWindow_manager::destroy() { while (_current >= 0) { TWindow* w = cur_win(); w->stop_run(K_FORCE_CLOSE); w->close_modal(); } } bool TWindow_manager::can_close() const { bool ok = true; if (_current >= 0) ok = cur_win()->can_be_closed(); return ok; } // Dis/abilitazione del menu principale HIDDEN void xvt_menu_enable(MENU_ITEM* m, bool on) { while (m->tag) { switch(m->tag) { case M_FILE: // Leave it as is case M_EDIT: case M_FONT: case M_STYLE: case M_HELP: case -1: // Separator break; default: xvt_menu_set_item_enabled(TASK_WIN, m->tag, on); } m++; } } void TWindow_manager::menu_enable(bool on) const { MENU_ITEM *mi = xvt_menu_get_tree(TASK_WIN); if (mi) { xvt_menu_enable(mi, on); xvt_menu_update(TASK_WIN); xvt_res_free_menu_tree(mi); } } void TWindow_manager::reg(TWindow* m) { _current++; CHECK(_current < MAX_WIN, "Too many windows"); switch (_current) { case 0 : menu_enable(FALSE); { const bool on = main_app().firm_change_enabled(); xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, on); } break; case 1 : xvt_menu_set_item_enabled(TASK_WIN, M_FILE_QUIT, FALSE); xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, FALSE); default: _window[_current-1]->deactivate(); break; } _window[_current] = m; } void TWindow_manager::unreg(const TWindow* m) { #ifdef DBG if (m != cur_win()) { yesnofatal_box("E' successo un casino nel Window Manager"); return; } #endif _current--; if (_current < 0) { menu_enable(TRUE); } else { TWindow& w = *cur_win(); w.activate(); xvt_menu_set_item_enabled(TASK_WIN, M_FILE_QUIT, _current == 0); const bool cf = _current == 0 && main_app().firm_change_enabled(); xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, cf); xvt_menu_update(TASK_WIN); w.set_focus(); w.force_update(); } } // @func Chiude tutte le finestre aperte void close_all_dialogs() { WinManager.destroy(); } // @doc EXTERNAL // @func Indica se l'applicazione puo' essere terminata // // @rdesc Ritorna il risultato della ricerca: // // @flag TRUE | Se l'aplicazione puo' essere chiusa // @flag FALSE | Se l'applicazione non puo' essere chiusa bool can_close() { return WinManager.can_close(); } bool is_valid_window(WINDOW w) { bool ok = FALSE; if (w != NULL_WIN) ok = (xvt_vobj_get_attr(w, ATTR_NATIVE_WINDOW) != 0L); return ok; } // @func Ritorna l'handle della finestra corrente // // @rdesc Restituisce l'handle della finestra corrente. WINDOW cur_win() // @comm Se non esiste una finestra corrente allora ritorna NULL_WIN { WINDOW win = NULL_WIN; TWindow* w = WinManager.cur_win(); if (w != NULL) { win = w->win(); /*if (!is_valid_window(win)) { w->stop_run(K_FORCE_CLOSE); win = NULL_WIN; }*/ } return win; } /////////////////////////////////////////////////////////// // TWindow /////////////////////////////////////////////////////////// DRAW_CTOOLS TWindow::_ct; bool TWindow::_ctools_saved; TWindow::TWindow() : _win(NULL_WIN), _lastkey(0), _base_char_width(0L), _open(FALSE), _modal(FALSE), _active(TRUE), _running(FALSE), _pixmap(FALSE) {} word TWindow::class_id() const { return CLASS_WINDOW; } long TWindow::window_handler(WINDOW win, EVENT* ep) { TWindow* w = (TWindow*)xvt_vobj_get_data(win); if (w != NULL) w->handler(win, ep); return 0L; } // @doc EXTERNAL // @mfunc Crea la finestra // // @rdesc Ritorna l'handle della finestra creata WINDOW TWindow::create( short x, // @parm Coordinata x della finestra short y, // @parm Coordinata y della finestra short dx, // @parm Larghezza della finestra short dy, // @parm Altezza della finestra const char* title, // @parm Titolo da assegnare alla finestra (default "") long flags, // @parm Flag della finestra (default WSF_NONE) WIN_TYPE wt, // @parm Tipo di finestra da creare (default W_DOC) WINDOW parent, // @parm Handler della finestra padre (default NULL_WIN) int menu) // @parm Menu' da assegnare alla finestra (default 0) { if (menu == 0) flags |= WSF_NO_MENUBAR; if (parent == NULL_WIN) parent = TASK_WIN; if (parent == TASK_WIN) flags |= WSF_INVISIBLE; _win = xvtil_create_window( wt, x, y, dx, dy, title, menu, parent, flags, window_handler, PTR_LONG(this) ); CHECK(_win, "Can't create a window"); return _win; } TWindow::~TWindow() { if (_win != NULL_WIN) { const WINDOW del_win = _win; // Memorizzo l'handle da cancellare _win = NULL_WIN; // Azzero preventivamente l'handle medesimo if (is_valid_window(del_win)) xvt_vobj_destroy(del_win); } } void TWindow::open() { WINDOW w = win(); CHECK(is_valid_window(w), "Can't open a NULL window"); xvt_vobj_set_visible(w, _open = TRUE); xvt_scr_set_focus_vobj(w); xvt_vobj_raise(w); } void TWindow::open_modal() { set_modal(TRUE); _open = TRUE; open(); WinManager.reg(this); } void TWindow::close() { CHECK(_win != NULL_WIN, "Can't close a NULL window"); if (is_valid_window(_win)) xvt_vobj_set_visible(_win, _open = FALSE); } void TWindow::close_modal() { if (is_modal()) { WinManager.unreg(this); close(); _open = FALSE; set_modal(FALSE); } } bool TWindow::stop_run(KEY key) { _running = FALSE; _lastkey = key; return TRUE; } bool TWindow::can_be_closed() const { const bool ok = !is_modal(); if (!ok) error_box("Chiudere la finestra attiva prima di uscire dal programma"); return ok; } // @doc EXTERNAL // @mfunc Esegue la finestra // // @rdesc Ritorna l'ultimo tasto premuto nella finestra KEY TWindow::run() // @comm Se la finestra non era aperta la apre in modo modale { const bool was_open = is_open(); start_run(); _running = TRUE; if (!was_open) open_modal(); else open(); while (_running) { do_events(); xvt_sys_sleep(50); } if (!was_open) close_modal(); do_events(); return last_key(); } void TWindow::on_button(short dlg) { switch(dlg) { case DLG_OK: stop_run(K_ENTER); break; case DLG_CANCEL: stop_run(K_ESC); break; case DLG_QUIT: stop_run(K_QUIT); break; default: break; } } // @doc EXTERNAL // @mfunc Gestisce l'handler della finestra void TWindow::handler( WINDOW win, // @parm Finestra da gestire EVENT* ep) // @parm Evento da gestire nella finestra { switch(ep->type) { case E_CHAR: on_key(e_char_to_key(ep)); break; case E_CLOSE: stop_run(K_ESC); break; case E_CREATE: if (_win == NULL_WIN) _win = win; // Gestisco meglio gli eventi che avvengono durante la creazione break; case E_CONTROL: if (ep->v.ctl.ci.type == WC_PUSHBUTTON) on_button(ep->v.ctl.id); break; case E_DESTROY: _win = NULL_WIN; break; case E_UPDATE: update(); break; default: break; } } void TWindow::on_idle() { // Non c'e' niente da fare qui, ma non si puo' mai sapere } TPoint TWindow::size() const { RCT r; xvt_vobj_get_client_rect(win() ? win() : TASK_WIN, &r); // return TPoint(r.right / CHARX, r.bottom / CHARY); TPoint pnt; pnt.x = int(80L * r.right / char2pixel(80)); pnt.y = r.bottom / CHARY; return pnt; } WINDOW TWindow::parent() const { return xvt_vobj_get_parent(win()); } void TWindow::set_focus() { WINDOW w = win(); if (w) { xvt_scr_set_focus_vobj(w); xvt_vobj_raise(w); } } void TWindow::maximize() const { xvt_vobj_maximize(win()); } void TWindow::minimize() const { xvt_vobj_minimize(win()); } void TWindow::set_background_color(COLOR col) { XI_OBJ* itf = xi_get_itf((XinWindow)win()); itf->v.itf->back_color = col; force_update(); } // @doc EXTERNAL // @mfunc Attiva/disattiva la finestra void TWindow::activate( bool on) // @parm Indica l'operazione da svolgere sulla finestra: // // @flag TRUE | Abilita la finestra (default) // @flag FALSE | Disabilita la finestra { xvt_vobj_set_enabled(win(), _active = on); } void TWindow::set_caption(const char* title) { xvt_vobj_set_title(win(), title); } const char* TWindow::get_caption(TString& str) const { char* title = str.get_buffer(128); xvt_vobj_get_title(win(), title, str.size()); return title; } void TWindow::force_update() { if (win() != NULL_WIN) xvt_dwin_invalidate_rect(win(), NULL); } bool TWindow::save_ctools() { if (_ctools_saved == FALSE) { xvt_dwin_get_draw_ctools(win(), &_ct); return _ctools_saved = TRUE; } return FALSE; } bool TWindow::restore_ctools() { if (_ctools_saved) { xvt_dwin_set_draw_ctools(win(), &_ct); _ctools_saved = FALSE; return TRUE; } return FALSE; } void TWindow::set_color(COLOR fore, COLOR back) { WINDOW w = win(); xvt_dwin_set_fore_color(w, fore); xvt_dwin_set_back_color(w, back); } // @doc EXTERNAL // @mfunc Sceglie la penna da utilizzare nella finestra void TWindow::set_pen( COLOR color, // @parm Colore della penna int width, // @parm Larghezza del tratto (default 1) PAT_STYLE pat, // @parm Stile del pattern (default PAT_SOLID) PEN_STYLE style) // @parm Stile della penna (default P_SOLID) { CPEN pen; pen.width = width; pen.pat = pat; pen.style = style; pen.color = color; xvt_dwin_set_cpen(win(), &pen); } void TWindow::hide_pen() { xvt_dwin_set_std_cpen(win(), TL_PEN_HOLLOW); } void TWindow::set_brush(COLOR color, PAT_STYLE pat) { CBRUSH brush = { pat, color }; xvt_dwin_set_cbrush(win(), &brush); } void TWindow::hide_brush() { CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE }; xvt_dwin_set_cbrush(win(), &brush); } HIDDEN void swap(short& a, short& b) { short tmp = a; a = b; b = tmp; } // @doc EXTERNAL // @mfunc Disegna un rettangolo con la possibilita' di settare la penna e il draw_mode void TWindow::frame( short left, // @parm Lato sinistro del rettangolo short top, // @parm Lato superiore del rettangolo short right, // @parm Lato destro del rettangolo short bottom, // @parm Lato inferiore del rettangolo int flag) // @parm Flag da assegnare per il disegno del rettangolo // @comm Se

oppure

i valori // vengono scambiati per permettere il disegno corretto del rettangolo { if (left > right) swap(left, right); if (top > bottom) swap(top, bottom); const bool saved = flag != 0 && save_ctools(); if (flag & 1) hide_pen(); if (flag & 2) hide_brush(); if (flag & 4) { set_mode(M_XOR); #ifdef XVAGA set_brush(COLOR_WHITE); #else set_brush(COLOR_BLACK); // Needed for Windows #endif } const PNT f = log2dev(left,top); const PNT t = log2dev(right,bottom); RCT r; r.top = f.v; r.left = f.h; r.bottom = t.v; r.right = t.h; if (!_pixmap && (flag & 2)) { r.left += CHARX>>1; r.top += CHARY>>1; r.right-= CHARX>>1; r.bottom -= CHARY>>1; } xvt_dwin_draw_rect(win(), &r); if (saved) restore_ctools(); } void TWindow::rect(short left, short top, short right, short bottom) { frame(left, top, right, bottom, 2); } void TWindow::bar(short left, short top, short right, short bottom) { frame(left, top, right, bottom, 1); } void TWindow::invert_bar(short left, short top, short right, short bottom) { frame(left, top, right, bottom, 5); } // @doc EXTERNAL // @mfunc Setta opaque_text void TWindow::set_opaque_text( bool o) // @parm Indica la modalita' di scrittura dell'opaque_text { // @comm Quando

e' FALSE il testo viene scritto in modo trasparente DRAW_CTOOLS ct; xvt_dwin_get_draw_ctools(win(), &ct); ct.opaque_text = o; xvt_dwin_set_draw_ctools(win(), &ct); } // @doc EXTERNAL // @mfunc Sceglie il font da utilizzare nella finestra void TWindow::set_font( const char* family, // @parm Famiglia di appartenenza del font (default XVT_FFN_FIXED) int style, // @parm Stile del font (default 0) int dim) // @parm Dimensione del font (default 0) { xvtil_set_font(win(), family, style, dim); _base_char_width = 0L; } int TWindow::char2pixel(int len) const { const int quantem = 80; if (_base_char_width == 0L) { const TString emme(quantem, 'M'); long& bcw = (long&)_base_char_width; bcw = xvt_dwin_get_text_width(win(), emme, quantem); } const int pix = int(len * _base_char_width / quantem); return pix; } PNT TWindow::log2dev(long x, long y) const { PNT pnt = { short(y), short(x) }; if (!_pixmap) { pnt.h = char2pixel(pnt.h); pnt.v *= CHARY; } return pnt; } TPoint TWindow::dev2log(const PNT& p) const { TPoint pnt(p.h, p.v); if (!_pixmap) { pnt.x = int(128L * p.h / char2pixel(128)); pnt.y /= CHARY; } return pnt; } void TWindow::log2dev(const TRectangle& lrct, RCT& drct) const { const PNT dp0 = log2dev(lrct.x, lrct.y); const PNT dp1 = log2dev(lrct.right(), lrct.bottom()); drct.left = dp0.h; drct.top = dp0.v; drct.right = dp1.h; drct.bottom = dp1.v; } void TWindow::dev2log(const RCT& rctd, TRectangle& rctl) const { const PNT dp0 = { rctd.top, rctd.left }; const PNT dp1 = { rctd.bottom, rctd.right }; const TPoint lp0 = dev2log(dp0); const TPoint lp1 = dev2log(dp1); rctl.set_bounds(lp0.x, lp0.y, lp1.x, lp1.y); } void TWindow::stringat(short x, short y, const char* str) { PNT pnt = log2dev(x,y); pnt.v += BASEY; xvt_dwin_draw_text(win(), pnt.h, pnt.v, str, -1); } // @doc EXTERNAL // @mfunc Scrive il testo formattato nella finestra alla posizione indicata void TWindow::printat( short x, // @parm Coordinata x della finestra in cui scrivere il testo short y, // @parm Coordinata y della finestra in cui scrivere il testo const char* fmt, // @parm Formato che deve essere dato al testo ...) // @parmvar Uno o piu' parametri corrispondenti ai codici in

{ if (fmt && *fmt) { if (strchr(fmt, '%') != NULL) { TString256 str; // TString str(256); char* tmp = str.get_buffer(); va_list argptr; va_start(argptr, fmt); vsprintf(tmp, fmt, argptr); va_end(argptr); stringat(x, y, tmp); } else stringat(x, y, fmt); } } void TWindow::line(short x0, short y0, short x1, short y1) { PNT f = log2dev(x0,y0); PNT t = log2dev(x1,y1); if (!_pixmap) { if (f.h == 0) f.h = -CHARX; else f.h += CHARX>>1; if (f.v == 0) f.v = -CHARY; else f.v += CHARY>>1; if (t.h == 0) t.h = -CHARX; else t.h += CHARX>>1; if (t.v == 0) t.v = -CHARY; else t.v += CHARY>>1; } xvt_dwin_draw_set_pos(win(), f); xvt_dwin_draw_line(win(), t); } void TWindow::icon(short x0, short y0, int iconid) { PNT f = log2dev(x0,y0); if (iconid < 0) iconid = ICON_RSRC; xvt_dwin_draw_icon(win(), f.h, f.v, iconid); } void TWindow::clear(COLOR color) { xvt_dwin_clear(win(), color); } void TWindow::set_mode(DRAW_MODE mode) { xvt_dwin_set_draw_mode(win(), mode); } // @doc EXTERNAL // @mfunc Aggiunge voci di menu' durante l'esecuzione di una finestra // // @rdesc Ritorna se e' riuscito ad aggiungere la voce al menu': // // @flag TRUE | Se ha ggiunto la voce // @flag FALSE | Se non ha ggiunto la voce bool TWindow::add_menu( TString_array& menu, // @parm Array da aggiungere al menu' MENU_TAG id, // @parm Identificatore del menu' a cui aggiungere le voci bool force) // @parm Mai usato // @comm Nel caso

sia uguale a 0 la voce veine aggiunte nella barra dei menu' { CHECK(menu.items() > 0, "TWindow::add_menu: no menus to add"); // get menu tree MENU_ITEM* menubar = xvt_menu_get_tree(win()); if (id == 0) // add to menubar { // count menus int nmen; for (nmen = 0; menubar[nmen].tag != 0; nmen++); menubar = (MENU_ITEM*)xvt_mem_realloc((DATA_PTR)menubar, sizeof(MENU_ITEM)*(nmen+menu.items()+1)); // zero new xvt_mem_rep((DATA_PTR)&menubar[nmen], "\0", 1, sizeof(MENU_ITEM)*(menu.items()+1)); // add new menus for (int i = 0; i < menu.items(); i++) set_menu_item(menubar[nmen+i], menu.row(i)); } else // add to menu { MENU_ITEM* father = find_menu_item(menubar, id, TRUE); CHECK(father != NULL, "TWindow::add_menu: you're adding to a NULL menu item"); // count children int nmen; for (nmen = 0; father->child != NULL && father->child[nmen].tag != 0; nmen++); father->child = (MENU_ITEM*)xvt_mem_realloc((DATA_PTR)father->child, sizeof(MENU_ITEM)*(nmen+menu.items()+1)); // zero new xvt_mem_rep((DATA_PTR)&(father->child[nmen]), "\0", 1, sizeof(MENU_ITEM)*(menu.items()+1)); // add new menus for (int i = 0; i < menu.items(); i++) set_menu_item(father->child[nmen+i], menu.row(i)); } xvt_menu_set_tree(win(), menubar); xvt_res_free_menu_tree(menubar); return TRUE; } bool TWindow::remove_menu(MENU_TAG id) { MENU_ITEM* menubar = xvt_menu_get_tree(win()); if (remove_menu_item(menubar, id, TRUE)) { xvt_menu_set_tree(win(),menubar); xvt_res_free_menu_tree(menubar); } return TRUE; } /////////////////////////////////////////////////////////// // TTemp_window /////////////////////////////////////////////////////////// TTemp_window::TTemp_window(WINDOW w) { set_win(w); } TTemp_window::~TTemp_window() { set_win(NULL_WIN); // I don't want to be closed! } /////////////////////////////////////////////////////////// // TScroll_window /////////////////////////////////////////////////////////// TScroll_window::TScroll_window() : _origin(0, 0), _max(0, 0), _shift(0), _autoscroll(TRUE), _has_hscroll(TRUE), _has_vscroll(TRUE) { } WINDOW TScroll_window::create(short x, short y, short dx, short dy, const char* title, long flags, WIN_TYPE wt, WINDOW parent, int menu) { _has_hscroll = (flags & WSF_HSCROLL) != 0; _has_vscroll = (flags & WSF_VSCROLL) != 0 ; return TWindow::create(x, y, dx, dy, title, flags, wt, parent, menu); } PNT TScroll_window::log2dev(long x, long y) const { if (_autoscroll) { if (_pixmap) { x -= _origin.x * CHARX; y -= (_origin.y >> _shift) * CHARY; } else { x -= _origin.x; y -= _origin.y >> _shift; } } return TWindow::log2dev(x,y); } void TScroll_window::set_scroll_max(long maxx, long maxy) { if (_has_hscroll && maxx >= 0) { _max.x = maxx; xvt_sbar_set_range(win(), HSCROLL, 0, int(maxx)); } if (_has_vscroll && maxy >= 0) { _shift = 0; while ((maxy >> _shift) > 0x7FFF) _shift++; _max.y = maxy; xvt_sbar_set_range(win(), VSCROLL, 0, int(maxy >> _shift)); } } // @doc EXTERNAL // @mfunc Aggiorna la scrollbar void TScroll_window::update_thumb( long x, // @parm Indica la posizione in x in cui spostare la finestra (default -1) long y) // @parm Indica la posizione in x in cui spostare la finestra (default -1) // @comm Nel caso si voglia aggiornare solamente una coordinata l'altra dovra' essere // settata a -1 { if (x >= 0 && x <= _max.x) _origin.x = x; if (y >= 0 && y <= _max.y) _origin.y = y; if (_has_hscroll) xvt_sbar_set_pos(win(), HSCROLL, int(_origin.x)); if (_has_vscroll) xvt_sbar_set_pos(win(), VSCROLL, int(_origin.y >> _shift)); } void TScroll_window::handler(WINDOW win, EVENT* ep) { if (ep->type == E_HSCROLL || ep->type == E_VSCROLL) { long& pos = (ep->type == E_HSCROLL) ? _origin.x : _origin.y; const long oldpos = pos; const long max = (ep->type == E_HSCROLL) ? _max.x : _max.y; const short pag = (ep->type == E_HSCROLL) ? columns()/2+1 : rows()/2+1; switch(ep->v.scroll.what) { case SC_PAGE_UP: pos -= pag; break; case SC_LINE_UP: pos--; break; case SC_PAGE_DOWN: pos += pag; break; case SC_LINE_DOWN: pos++; break; case SC_THUMB: pos = ep->v.scroll.pos; break; default: break; } if (pos < 0) pos = 0; if (pos > max) pos = max; if (pos != oldpos) { update_thumb(); force_update(); } } TWindow::handler(win, ep); } bool TScroll_window::on_key(KEY key) { switch(key) { case K_LHOME: update_thumb(0,0); force_update(); break; case K_LEND: update_thumb(0,range().y); force_update(); break; case K_TAB: update_thumb(origin().x+8); force_update(); break; case K_BTAB: { long x = origin().x-8; if (x < 0) x = 0; update_thumb(x); force_update(); } break; case K_UP: case K_DOWN: case K_PREV: case K_NEXT: case K_LEFT: case K_RIGHT: dispatch_e_scroll(win(), key); break; default: break; } return TWindow::on_key(key); }