#include #include #include #define __WINDOW_CPP #include #include #if XVT_OS == XVT_OS_WIN #include #endif /////////////////////////////////////////////////////////// // TWindow_manager /////////////////////////////////////////////////////////// // @C // Classe TWindow_manager // // @END class TWindow_manager { // @DPRIV enum { MAX_WIN = 4 }; // Max number of modal windows TWindow* _window[MAX_WIN]; // Stack of active windows char _current; // Stack pointer void menu_enable(bool) const; // Abilita o disabilita il menu della task window public: // @FPUB TWindow_manager(); // Costruttore ~TWindow_manager() { destroy(); } void reg(TWindow* m); // Registra la finestra corrente void unreg(const TWindow* m); // De-registra la finestra corrente TWindow* cur_win() const { return (_current < 0) ? NULL : _window[_current]; } // Ritorna il puntatore alla finestra corrente void destroy(); bool can_close() const; } WinManager; TWindow_manager::TWindow_manager() : _current(-1) {} 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: case MENU_FILE: case MENU_EDIT: case MENU_ALT_EDIT: if (m->child) xvt_menu_enable(m->child, on); break; case 65535: // Separator case M_FILE_NEW: case M_FILE_REVERT: case M_FILE_QUIT: case M_FILE_ABOUT: case M_FILE_PRINT: case M_FILE_PG_SETUP: case (M_FILE+11): case M_EDIT_SEARCH: break; // Leave them as they are default: win_menu_enable(TASK_WIN, m->tag, on); break; } m++; } } void TWindow_manager::menu_enable(bool on) const { MENU_ITEM *mi = win_menu_fetch(TASK_WIN); xvt_menu_enable(mi, on); win_update_menu_bar(TASK_WIN); menu_free(mi); } void TWindow_manager::reg(TWindow* m) { _current++; CHECK(_current < MAX_WIN, "Too many windows"); switch (_current) { case 0 : menu_enable(FALSE); break; case 1 : win_menu_enable(TASK_WIN, M_FILE_QUIT, FALSE); default: _window[_current-1]->disable(); 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 { cur_win()->enable(); win_menu_enable(TASK_WIN, M_FILE_QUIT, _current == 0); } } void close_all_dialogs() { WinManager.destroy(); } bool can_close() { return WinManager.can_close(); } WINDOW cur_win() { const TWindow* w = WinManager.cur_win(); return w ? w->win() : NULL_WIN; } /////////////////////////////////////////////////////////// // TWindow /////////////////////////////////////////////////////////// DRAW_CTOOLS TWindow::_ct; bool TWindow::_ctools_saved; TWindow::TWindow() : _win(NULL_WIN), _open(FALSE), _modal(FALSE), _running(FALSE), _lastkey(0) {} long TWindow::window_handler(WINDOW win, EVENT* ep) { TWindow* w = (TWindow*)get_app_data(win); CHECK(w != NULL, "Invalid window"); w->handler(win, ep); return 0L; } WINDOW TWindow::create(short x, short y, short dx, short dy, const char* title, long flags, WIN_TYPE wt, WINDOW parent) { flags |= WSF_NO_MENUBAR; if (parent == NULL_WIN) parent = TASK_WIN; if (parent == TASK_WIN) flags |= WSF_INVISIBLE; _win = xvt_create_window( wt, x, y, dx, dy, title, parent, flags, window_handler, PTR_LONG(this) ); CHECK(_win, "Can't create a window"); return _win; } TWindow::~TWindow() { if (_win != NULL_WIN) { close_window(_win); _win = NULL_WIN; } } void TWindow::open() { CHECK(win() != NULL_WIN, "Can't open a NULL window"); show_window(win(), _open = TRUE); set_front_window(win()); } 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"); show_window(_win, _open = FALSE); } void TWindow::close_modal() { WinManager.unreg(this); close(); _open = 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; } KEY TWindow::run() { const bool was_open = is_open(); start_run(); _running = TRUE; if (!was_open) open_modal(); else open(); while (_running) do_events(); if (!was_open) close_modal(); return last_key(); } void TWindow::handler(WINDOW win, EVENT* ep) { switch(ep->type) { case E_CLOSE: stop_run(K_ESC); break; case E_UPDATE: { clear_window(win, NORMAL_BACK_COLOR); update(); } break; case E_CHAR: on_key(e_char_to_key(ep)); break; case E_DESTROY: _win = NULL_WIN; break; default: break; } } TPoint TWindow::size() const { RCT r; get_client_rect(_win ? _win : TASK_WIN, &r); return TPoint(r.right / CHARX, r.bottom / CHARY); } WINDOW TWindow::parent() const { return get_parent(win()); } void TWindow::set_focus() { if (_win) set_front_window(_win); } void TWindow::iconize() const { #if XVTWS != WMWS HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_MINIMIZE); #endif } void TWindow::maximize() const { #if XVTWS != WMWS HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW); ShowWindow(hwnd, SW_SHOWMAXIMIZED); #else RCT r; set_rect(&r, 1,1,79,23); move_window(win(),&r); #endif } void TWindow::enable(bool on) const { enable_window(win(), on); } void TWindow::set_caption(const char* title) { set_title(win(), (char*)title); } const char* TWindow::get_caption() const { char* title = &__tmp_string[512]; get_title(win(), title, 80); return title; } void TWindow::force_update() { if (win() != NULL_WIN) invalidate_rect(win(), NULL); } bool TWindow::save_ctools() { if (_ctools_saved == FALSE) { win_get_draw_ctools(win(), &_ct); return _ctools_saved = TRUE; } return FALSE; } bool TWindow::restore_ctools() { if (_ctools_saved) { win_set_draw_ctools(win(), &_ct); _ctools_saved = FALSE; return TRUE; } return FALSE; } void TWindow::set_color(COLOR fore, COLOR back) { win_set_fore_color(win(), fore); win_set_back_color(win(), back); } void TWindow::set_pen(COLOR color, int width, PAT_STYLE pat, PEN_STYLE style) { CPEN pen; pen.width = width; pen.pat = pat; pen.style = style; pen.color = color; win_set_cpen(win(), &pen); } void TWindow::hide_pen() { win_set_std_cpen(win(), TL_PEN_HOLLOW); } void TWindow::set_brush(COLOR color, PAT_STYLE pat) { CBRUSH brush = { pat, color }; win_set_cbrush(win(), &brush); } void TWindow::hide_brush() { CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE }; win_set_cbrush(win(), &brush); } HIDDEN void swap(short& a, short& b) { short tmp = a; a = b; b = tmp; } void TWindow::frame(short left, short top, short right, short bottom, int flag) { if (left > right) swap(left, right); if (top > bottom) swap(top, bottom); const bool saved = flag && save_ctools(); if (flag & 1) hide_pen(); if (flag & 2) hide_brush(); if (flag & 4) { set_mode(M_XOR); set_brush(COLOR_BLACK); // Needed for Windows } 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 XVTWS != WMWS if (flag & 2) { r.left += CHARX>>1; r.top += CHARY>>1; r.right-= CHARX>>1; r.bottom -= CHARY>>1; } #endif win_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); } void TWindow::set_opaque_text(bool o) { DRAW_CTOOLS ct; win_get_draw_ctools(win(), &ct); ct.opaque_text = o; win_set_draw_ctools(win(), &ct); } void TWindow::set_font(int family, int style, int dim) { xvt_set_font(win(), family, style, dim); } PNT TWindow::log2dev(long x, long y) const { PNT pnt; pnt.h = (int)x*CHARX; pnt.v = (int)y*CHARY; return pnt; } TPoint TWindow::dev2log(const PNT& p) const { TPoint pnt(p.h / CHARX, p.v / CHARY); return pnt; } void TWindow::stringat(short x, short y, const char* str) { PNT pnt = log2dev(x,y); #if XVTWS != WMVS pnt.v += CHARY-3; #endif win_draw_text(win(), pnt.h, pnt.v, (char *)str, -1); } void TWindow::printat(short x, short y, const char* fmt, ...) { va_list argptr; va_start(argptr, fmt); vsprintf(__tmp_string, fmt, argptr); va_end(argptr); stringat(x, y, __tmp_string); } void TWindow::line(short x0, short y0, short x1, short y1) { PNT f = log2dev(x0,y0); PNT t = log2dev(x1,y1); 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; win_move_to(_win, f); win_draw_line(_win, t); } void TWindow::icon(short x0, short y0, int iconid) { #if XVTWS == WMWS bar(x0, y0, x0+1, y0+1); #else PNT f = log2dev(x0,y0); if (iconid < 0) iconid = ICON_RSRC; win_draw_icon(win(), f.h, f.v, iconid); #endif } void TWindow::clear(COLOR color) { clear_window(win(), color); } void TWindow::set_mode(DRAW_MODE mode) { win_set_draw_mode(win(), mode); } /////////////////////////////////////////////////////////// // 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) { _has_hscroll = (flags & WSF_HSCROLL) != 0; _has_vscroll = (flags & WSF_VSCROLL) != 0 ; return TWindow::create(x, y, dx, dy, title, flags, wt, parent); } PNT TScroll_window::log2dev(long x, long y) const { if (_autoscroll) { 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; set_scroll_range(win(), HSCROLL, 0, int(maxx)); } if (_has_vscroll && maxy >= 0) { _shift = 0; while ((maxy >> _shift) > 0x7FFF) _shift++; _max.y = maxy; set_scroll_range(win(), VSCROLL, 0, int(maxy >> _shift)); } } void TScroll_window::update_thumb(long x, long y) { if (x >= 0 && x <= _max.x) _origin.x = x; if (y >= 0 && y <= _max.y) _origin.y = y; if (_has_hscroll) set_scroll_pos(win(), HSCROLL, int(_origin.x)); if (_has_vscroll) set_scroll_pos(win(), VSCROLL, int(_origin.y >> _shift)); } void TScroll_window::handler(WINDOW win, EVENT* ep) { bool up = FALSE; switch (ep->type) { case E_HSCROLL: case E_VSCROLL: { long& pos = (ep->type == E_HSCROLL) ? _origin.x : _origin.y; long& max = (ep->type == E_HSCROLL) ? _max.x : _max.y; short pag = (ep->type == E_HSCROLL) ? columns()/2+1 : rows()/2+1; switch(ep->v.scroll.what) { case SC_PAGE_UP: pos -= pag; up = TRUE; break; case SC_LINE_UP: pos--; up = TRUE; break; case SC_PAGE_DOWN: pos += pag; up = TRUE; break; case SC_LINE_DOWN: pos++; up = TRUE; break; case SC_THUMB: pos = ep->v.scroll.pos; up = TRUE; break; default: break; } if (pos < 0) pos = 0; if (pos > max) pos = max; } break; default: break; } if (up) { 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); }