55a36762ef
checks.cpp Tolto include windows.h colors.cpp Tolto include windows.h controls.cpp Aggiunto cambiamento del font runtime dei TText_control execp.cpp Tolto include windows.h form.cpp Tolto include windows.h mask.cpp Corretta formattazione di due righe maskfld.cpp Aggiunto messaggio CHECK msksheet.cpp Tolto include windows.h relapp.cpp Tolto include windows.h strings.pp Corretto CHECK della TFixed_string::format() viswin.cpp Tolto include windows.h window.cpp Tolto include windows.h xvtility.cpp Corretto calcolo altezza righe delle maschere git-svn-id: svn://10.65.10.50/trunk@4085 c028cbd2-c16b-5b4b-a496-9718f37d4682
1311 lines
30 KiB
C++
Executable File
1311 lines
30 KiB
C++
Executable File
#define XVT_INCL_NATIVE
|
|
#define STRICT
|
|
|
|
#define XI_INTERNAL
|
|
#include <xi.h>
|
|
|
|
#include <applicat.h>
|
|
#include <checks.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
#define __WINDOW_CPP
|
|
#include <window.h>
|
|
#include <colors.h>
|
|
|
|
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') != -1);
|
|
m.checkable = flag.find('C') != -1 || flag.find('c') != -1;
|
|
m.checked = flag.find('c') != -1;
|
|
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
|
|
char _current;
|
|
// @cmember:(INTERNAL) Permette di abilitare/disabilitare il menu' della task window (stesso
|
|
// funzionamento della <mf TMask::enable>)
|
|
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 Libera lo spazio per aprire il file (vedi <p _lowhandle>)
|
|
void free_handle();
|
|
// @cmember Occupa lo spazio per aprire il file (vedi <p _lowhandle>)
|
|
void lock_handle();
|
|
|
|
// @cmember Registra la finestra <p m> 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)
|
|
{
|
|
lock_handle();
|
|
}
|
|
|
|
TWindow_manager::~TWindow_manager()
|
|
{
|
|
destroy();
|
|
free_handle();
|
|
}
|
|
|
|
void TWindow_manager::destroy()
|
|
{
|
|
while (_current >= 0)
|
|
{
|
|
TWindow* w = cur_win();
|
|
w->stop_run(K_FORCE_CLOSE);
|
|
w->close_modal();
|
|
}
|
|
}
|
|
|
|
void TWindow_manager::lock_handle()
|
|
{
|
|
CHECK(_lowhandle == NULL, "Can't relock low handle");
|
|
_lowhandle = fopen("con", "r");
|
|
CHECK(_lowhandle != NULL, "Can't lock low handle");
|
|
}
|
|
|
|
void TWindow_manager::free_handle()
|
|
{
|
|
CHECK(_lowhandle, "Can't unlock low handle");
|
|
fclose(_lowhandle);
|
|
_lowhandle = NULL;
|
|
}
|
|
|
|
|
|
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 MENU_FILE: // Leave it as is
|
|
case M_FONT:
|
|
case -1: // Separator
|
|
break;
|
|
default:
|
|
xvt_menu_set_item_enabled(TASK_WIN, m->tag, on);
|
|
break;
|
|
}
|
|
m++;
|
|
}
|
|
}
|
|
|
|
|
|
void TWindow_manager::menu_enable(bool on) const
|
|
{
|
|
MENU_ITEM *mi = xvt_menu_get_tree(TASK_WIN);
|
|
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);
|
|
xvt_menu_set_item_enabled(TASK_WIN, M_FILE_REVERT, 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);
|
|
xvt_menu_set_item_enabled(TASK_WIN, M_FILE_REVERT, 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
|
|
{
|
|
cur_win()->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_set_item_enabled(TASK_WIN, M_FILE_REVERT, cf);
|
|
|
|
xvt_menu_update(TASK_WIN);
|
|
cur_win()->set_focus();
|
|
}
|
|
}
|
|
|
|
|
|
// @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) != NULL;
|
|
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)
|
|
{
|
|
win = w->win();
|
|
if (!is_valid_window(w->win()))
|
|
{
|
|
w->stop_run(K_FORCE_CLOSE);
|
|
win = NULL_WIN;
|
|
}
|
|
}
|
|
return win;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TImage
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
// Certified 99%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Setta l'immagine e le sue dimensioni
|
|
//
|
|
// @rdesc Ritorna l'immagine stessa
|
|
XVT_IMAGE TImage::set(
|
|
XVT_IMAGE i) // @parm Immagine da settare
|
|
|
|
// @comm L'immagine precedente viene cancellata quando viene settata una nuova
|
|
{
|
|
if (_image)
|
|
xvt_image_destroy(_image);
|
|
_image = i;
|
|
if (i)
|
|
{
|
|
_src.left = _src.top = 0;
|
|
xvt_image_get_dimensions(i, &_src.right, &_src.bottom);
|
|
_dst = _src;
|
|
}
|
|
return _image;
|
|
}
|
|
|
|
// Certified 100%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Legge l'immagine dal file
|
|
XVT_IMAGE TImage::load(
|
|
const char* n) // @parm Nome del file contenente l'immagine
|
|
{
|
|
WinManager.free_handle();
|
|
XVT_IMAGE i = xvt_image_read_bmp((char*)n);
|
|
WinManager.lock_handle();
|
|
|
|
if (i != NULL) set(i);
|
|
return i;
|
|
}
|
|
|
|
// Certified 100%
|
|
XVT_IMAGE TImage::load(short id)
|
|
{
|
|
return set(xvt_res_get_image(id));
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
TImage::TImage(const char* n) : _image(NULL)
|
|
{
|
|
if (n && *n) load(n);
|
|
}
|
|
|
|
// Certified 100%
|
|
TImage::TImage(short id) : _image(NULL)
|
|
{
|
|
if (id > 0) load(id);
|
|
}
|
|
|
|
// Certified 90%
|
|
TImage::TImage(const TImage& im, short w, short h) : _image(NULL)
|
|
{
|
|
const XVT_IMAGE_FORMAT fmt = xvt_image_get_format(im._image);
|
|
set(xvt_image_create(fmt, w, h, NULL));
|
|
|
|
if (ok())
|
|
{
|
|
if (fmt == XVT_IMAGE_CL8)
|
|
{
|
|
const short colors = xvt_image_get_ncolors(im._image);
|
|
xvt_image_set_ncolors(_image, colors);
|
|
for (short c = 0; c < colors; c++)
|
|
xvt_image_set_clut(_image, c, xvt_image_get_clut((XVT_IMAGE)im._image, c));
|
|
}
|
|
xvt_image_transfer(_image, (XVT_IMAGE)im._image, &_src, (RCT*)&im._src);
|
|
}
|
|
}
|
|
|
|
// Certified 100%
|
|
TImage::~TImage()
|
|
{
|
|
if (_image != NULL)
|
|
xvt_image_destroy(_image);
|
|
}
|
|
|
|
// Certified 100%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Permette di settare la posizione della figura
|
|
void TImage::set_pos(
|
|
int x, // @parm Coordinata x dell'immagine da settare
|
|
int y) // @parm Coordinata y dell'immagine da settare
|
|
|
|
// @comm Permette di aggiornare il mebro <p _dst> sommandogli i valori
|
|
// passati con <p x> e <p y>
|
|
{
|
|
_dst = _src;
|
|
xvt_rect_offset(&_dst, x, y);
|
|
}
|
|
|
|
// Certified 100%
|
|
void TImage::draw(WINDOW w) const
|
|
{
|
|
xvt_dwin_draw_image(w, _image, (RCT*)&_dst, (RCT*)&_src);
|
|
}
|
|
|
|
// Certified 100%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Permette di gestire il disegno dell'immagine sullo schermo
|
|
void TImage::draw(
|
|
WINDOW w, // @parm Immagine da disegnare
|
|
int x, // @parm Coordinata x in cui disegnare l'immagine
|
|
int y) const // @parm Coordinata y in cui disegnare l'immagine
|
|
// @parm RCT& | _src | Rettangolo contenente l'immagine da disegnare
|
|
// @parm RCT& | _dst | Rettangolo in cui disegnare l'immagine
|
|
|
|
// @syntax void draw(WINDOW w);
|
|
// @syntax void draw(WINDOW w, int x, int y);
|
|
// @syntax void draw(WINDOW w, const RCT& dst);
|
|
// @syntax void draw(WINDOW w, const RCT& dst, const RCT& src);
|
|
|
|
// @comm Nel caso utilizzo l'ultima sintassi e' possibile disegnare solo una parte
|
|
// dell'immagine, precisamente delle dimensioni <p _dst> se tale parametro e'
|
|
// minore di <p _pst>
|
|
{
|
|
RCT dst = _src;
|
|
xvt_rect_offset(&dst, x, y);
|
|
xvt_dwin_draw_image(w, _image, &dst, (RCT*)&_src);
|
|
}
|
|
|
|
// Certified 100%
|
|
void TImage::draw(WINDOW w, const RCT& dst) const
|
|
{
|
|
xvt_dwin_draw_image(w, _image, (RCT*)&dst, (RCT*)&_src);
|
|
}
|
|
|
|
// Certified 100%
|
|
void TImage::draw(WINDOW w, const RCT& dst, const RCT& src) const
|
|
{
|
|
xvt_dwin_draw_image(w, _image, (RCT*)&dst, (RCT*)&src);
|
|
}
|
|
|
|
// Certified 99%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Fa corrispondere la palette della finestra a quella dell'immagine
|
|
void TImage::set_palette(
|
|
WINDOW w) const // @parm Finestra a cui settare la palette
|
|
{
|
|
XVT_PALETTE wp = xvt_vobj_get_palet(w);
|
|
if (wp != NULL)
|
|
{
|
|
XVT_PALETTE p = xvt_palet_create(XVT_PALETTE_USER, NULL);
|
|
const int ncolors = xvt_palet_get_ncolors(wp);
|
|
COLOR* color = new COLOR[ncolors];
|
|
xvt_palet_get_colors(wp, color, ncolors);
|
|
xvt_palet_add_colors(p, color, ncolors);
|
|
delete color;
|
|
xvt_palet_add_colors_from_image(p, _image);
|
|
xvt_vobj_set_palet(w, p);
|
|
xvt_palet_destroy(wp);
|
|
}
|
|
}
|
|
|
|
// Certified 100%
|
|
void TImage::set_clut(byte n, COLOR c)
|
|
{
|
|
if (xvt_image_get_format(_image) == XVT_IMAGE_CL8)
|
|
xvt_image_set_clut(_image, n, c);
|
|
}
|
|
|
|
// Certified 99%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Setta i colori dell'immagine in modo da renderla trasparente
|
|
void TImage::convert_to_default_colors()
|
|
|
|
// @comm Legge nell'immagine i colori CYAN e DARK_CYAN e li setta a seconda del colore
|
|
// della finestra per fare in modo di rendere trasparenti tali colori.
|
|
{
|
|
if (MASK_BACK_COLOR != COLOR_DKCYAN && xvt_image_get_format(_image) == XVT_IMAGE_CL8)
|
|
{
|
|
short dx, dy; xvt_image_get_dimensions(_image, &dx, &dy);
|
|
for (short y = 0; y < dy; y++) for (short x = 0; x < dx; x++)
|
|
{
|
|
const COLOR c = xvt_image_get_pixel(_image, x, y);
|
|
switch (c)
|
|
{
|
|
case COLOR_DKCYAN & 0x00FFFFFF:
|
|
xvt_image_set_pixel(_image, x, y, MASK_BACK_COLOR); break;
|
|
case COLOR_CYAN & 0x00FFFFFF:
|
|
xvt_image_set_pixel(_image, x, y, MASK_LIGHT_COLOR); break;
|
|
case COLOR_GRAY & 0x00FFFFFF:
|
|
xvt_image_set_pixel(_image, x, y, MASK_DARK_COLOR); break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// @mfunc Setta i colori dell'immagine in modo da renderla trasparente
|
|
void TImage::convert_transparent_color(COLOR transparent)
|
|
|
|
// @comm Legge nell'immagine i pixel uguali a quello in alto a sinistra e li setta
|
|
// uguali allo sfondo delle maschere
|
|
{
|
|
const COLOR trans = xvt_image_get_pixel(_image, 0, 0) & 0x00FFFFFF;
|
|
if (trans != (transparent & 0x00FFFFFF) &&
|
|
xvt_image_get_format(_image) == XVT_IMAGE_CL8)
|
|
{
|
|
for (int index = 0; index < 256; index++)
|
|
if (trans == (xvt_image_get_clut(_image, index) & 0x00FFFFFF))
|
|
{
|
|
xvt_image_set_clut(_image, index, transparent);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TWindow
|
|
///////////////////////////////////////////////////////////
|
|
|
|
DRAW_CTOOLS TWindow::_ct;
|
|
bool TWindow::_ctools_saved;
|
|
|
|
|
|
TWindow::TWindow()
|
|
: _win(NULL_WIN), _open(FALSE), _modal(FALSE), _active(TRUE),
|
|
_running(FALSE), _pixmap(FALSE), _lastkey(0)
|
|
{}
|
|
|
|
word TWindow::class_id() const
|
|
{ return CLASS_WINDOW; }
|
|
|
|
long XVT_CALLCONV1 TWindow::window_handler(WINDOW win, EVENT* ep)
|
|
{
|
|
TWindow* w = (TWindow*)xvt_vobj_get_data(win);
|
|
CHECK(w != NULL, "Invalid window");
|
|
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 = xvt_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)
|
|
{
|
|
if (is_valid_window(_win));
|
|
xvt_vobj_destroy(_win);
|
|
_win = NULL_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()
|
|
{
|
|
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;
|
|
}
|
|
|
|
// @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();
|
|
|
|
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_CLOSE:
|
|
stop_run(K_ESC);
|
|
break;
|
|
case E_CONTROL:
|
|
if (ep->v.ctl.ci.type == WC_PUSHBUTTON)
|
|
on_button(ep->v.ctl.id);
|
|
break;
|
|
case E_UPDATE:
|
|
update();
|
|
break;
|
|
case E_CHAR:
|
|
on_key(e_char_to_key(ep));
|
|
break;
|
|
case E_DESTROY:
|
|
_win = NULL_WIN;
|
|
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);
|
|
}
|
|
|
|
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::iconize() const
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
|
|
ShowWindow(hwnd, SW_MINIMIZE);
|
|
#endif
|
|
}
|
|
|
|
void TWindow::maximize() const
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
|
|
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
|
|
#else
|
|
RCT r; xvt_rect_set(&r, 1,1,79,23);
|
|
xvt_vobj_move(win(),&r);
|
|
#endif
|
|
}
|
|
|
|
|
|
void TWindow::set_background_color(COLOR col)
|
|
{
|
|
XI_OBJ* itf = xi_get_itf(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(), (char*)title);
|
|
}
|
|
|
|
|
|
const char* TWindow::get_caption() const
|
|
{
|
|
char* title = &__tmp_string[512];
|
|
xvt_vobj_get_title(win(), title, 80);
|
|
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 <p left> <gt> <p right> oppure <p top> <gt> <p bottom> 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 && 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 XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
if (flag & 2)
|
|
{
|
|
r.left += CHARX>>1; r.top += CHARY>>1;
|
|
r.right-= CHARX>>1; r.bottom -= CHARY>>1;
|
|
}
|
|
#endif
|
|
|
|
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 <p o> 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)
|
|
{
|
|
xvt_set_font(win(), family, style, dim);
|
|
}
|
|
|
|
PNT TWindow::log2dev(long x, long y) const
|
|
{
|
|
PNT pnt;
|
|
|
|
pnt.h = (int)x;
|
|
pnt.v = (int)y;
|
|
|
|
if (!_pixmap)
|
|
{
|
|
pnt.h *= CHARX;
|
|
pnt.v *= CHARY;
|
|
}
|
|
|
|
return pnt;
|
|
}
|
|
|
|
TPoint TWindow::dev2log(const PNT& p) const
|
|
{
|
|
TPoint pnt(_pixmap ? p.h : p.h/CHARX, _pixmap ? p.v : p.v/CHARY);
|
|
return pnt;
|
|
}
|
|
|
|
|
|
void TWindow::stringat(short x, short y, const char* str)
|
|
{
|
|
PNT pnt = log2dev(x,y);
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
pnt.v += BASEY;
|
|
#endif
|
|
|
|
xvt_dwin_draw_text(win(), pnt.h, pnt.v, (char *)str, -1);
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Scrive il testo formattato nella finestra all 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 <p 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 XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
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;
|
|
#endif
|
|
|
|
xvt_dwin_draw_set_pos(win(), f);
|
|
xvt_dwin_draw_line(win(), t);
|
|
}
|
|
|
|
void TWindow::icon(short x0, short y0, int iconid)
|
|
{
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
bar(x0, y0, x0+1, y0+1);
|
|
#else
|
|
PNT f = log2dev(x0,y0);
|
|
if (iconid < 0) iconid = ICON_RSRC;
|
|
xvt_dwin_draw_icon(win(), f.h, f.v, iconid);
|
|
#endif
|
|
}
|
|
|
|
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 <p id> 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
|
|
for (int 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
|
|
for (int 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)
|
|
{
|
|
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)
|
|
{
|
|
bool up = FALSE;
|
|
|
|
switch (ep->type)
|
|
{
|
|
case E_HSCROLL:
|
|
case E_VSCROLL:
|
|
{
|
|
long& pos = (ep->type == E_HSCROLL) ? _origin.x : _origin.y;
|
|
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;
|
|
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);
|
|
}
|
|
|