campo-sirio/include/window.cpp
guy 55a36762ef archives.cpp Tolto include windows.h
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
1997-01-17 11:07:43 +00:00

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);
}