b108a12dba
git-svn-id: svn://10.65.10.50/trunk@64 c028cbd2-c16b-5b4b-a496-9718f37d4682
735 lines
13 KiB
C++
Executable File
735 lines
13 KiB
C++
Executable File
#include <checks.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
#define __WINDOW_CPP
|
|
#include <window.h>
|
|
#include <colors.h>
|
|
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
#include <windows.h>
|
|
#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 { return _current < 1; }
|
|
} 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();
|
|
}
|
|
}
|
|
|
|
// 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())
|
|
{
|
|
error_box("You can unregister the current window only");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
_current--;
|
|
|
|
if (_current < 0)
|
|
menu_enable(TRUE);
|
|
else
|
|
{
|
|
if (_current == 0)
|
|
win_menu_enable(TASK_WIN, M_FILE_QUIT, TRUE);
|
|
cur_win()->enable();
|
|
}
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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);
|
|
}
|
|
|
|
void TWindow::clear(COLOR color)
|
|
|
|
{ clear_window(win(), color); }
|
|
|
|
void TWindow::set_mode(DRAW_MODE mode)
|
|
|
|
{ win_set_draw_mode(win(), mode); }
|