campo-sirio/include/mask.cpp
guy 81534d006f Patch level : 10.0
Files correlati     : tutti
Ricompilazione Demo : [ ]
Commento            :
0001213: mappa di login, fuoco
Lla mappa di login si apre ma per poter digitare la password bisogna cliccare sul campo col mouse. Stesso problema richiamando le ricerche, per esempio quella clienti.


git-svn-id: svn://10.65.10.50/trunk@18591 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 15:16:49 +00:00

2650 lines
68 KiB
C++
Executable File

#include <xinclude.h>
#include <controls.h>
#include <browfile.h>
#include <colors.h>
#include <diction.h>
#include <msksheet.h>
#include <prefix.h>
#include <recarray.h>
#include <relation.h>
#include <statbar.h>
#include <toolfld.h>
#include <treectrl.h>
#include <urldefid.h>
#include <utility.h>
#include <user.h>
HIDDEN const char* const MASK_EXT = "msk";
///////////////////////////////////////////////////////////
// TMask methods
///////////////////////////////////////////////////////////
void TMask::init_mask()
{
_msg_field = 0;
_msg_key = 0;
_pages = 0; // Azzera numero pagine e sheets
if (_mask_num == 0) _sheet = NULL; // Non appartiene a nessuno sheet
_enabled.set(MAX_PAGES);
_enabled.set(); // Abilita tutte le pagine
_should_check = true;
_focus = _first_focus = 0; // Il primo ha il focus
_page = -1; // Nessuna pagina corrente
_handler = NULL; // Nessun handler utente
_mode = NO_MODE; // Inizializza modo
_error_severity = 0;
_msg_field = 0;
_msg_key = 0;
_test_fld = -1;
_last_test = -1;
_toolwin = _toolbar = _notebook = _single = NULL_WIN;
memset(_pagewin, 0, sizeof(_pagewin)); // Azzero lista pagine
}
WINDOW TMask::page_win(int p) const
{
if (p >= MAX_PAGES)
return p == MAX_PAGES ? toolwin() : toolbar();
if (p >= 0 && p < _pages)
return _pagewin[p];
return p <= 0 ? win() : NULL_WIN;
}
WINDOW TMask::curr_win() const
{
return page_win(_page > 0 && _page < _pages ? _page : 0);
}
TMask::TMask() : _mask_num(0)
{ init_mask(); }
TMask::TMask(const char* title, int pages, int cols, int rows,
int xpos, int ypos, WINDOW parent) : _mask_num(0)
{
init_mask();
if (pages > 1)
{
WINDOW w = create_interface(parent, xpos, ypos, cols, rows, title, this);
set_win(w); // Crea la pagina principale che ospitera' il notebook
create_book(false); // Crea il notebook che ospitera' le pagine
for (int p = 1; p <= pages; p++)
{
WINDOW w = create_interface(notebook(), 0, 0, 0, 0, title, this);
insert_page(w, -1); // Aggiunge nuova pagina in fondo
}
}
else
{
WINDOW w = create_interface(parent, xpos, ypos, cols, rows, title, this);
insert_page(w, 0);
}
}
void TMask::set_locking(TBit_array& read_only, TToken_string& list, bool on)
{
if (list.find('*') >= 0)
{
if (on)
{
read_only.set(fields());
read_only.set();
}
else
read_only.reset();
}
else
{
FOR_EACH_TOKEN(list, fld)
{
const TFixed_string id(fld);
if (id[0] == '-' || id.ends_with("@")) // Gestione gruppi
{
const int grp = abs(atoi(fld));
FOR_EACH_MASK_FIELD((*this), pos, f)
{
if (f->in_group(grp))
read_only.set(pos, on);
}
}
else
{
const int pos = field2pos(fld);
if (pos >= 0)
read_only.set(pos, on);
}
}
}
}
// @mfunc Legge la maschera da file
void TMask::read_mask(
const char* name, // @parm Nome della maschera da leggere (senza estensione)
int num, // @parm Numero della maschera da leggere all'interno del file
int max) // @parm Numero massimo di pagine che deve avere la maschera
{
TWait_cursor hourglass;
if (max <= 0) max = MAX_PAGES;
_source_file = name;
_source_file.ext(MASK_EXT);
_source_file.lower();
_source_file.custom_path();
TScanner scanner(_source_file);
if (num != 0)
_mask_num = num;
// Salta la maschera principale e quelle degli sheet precedenti a pie' pari
for (int i = 0; i < num; i++)
{
while (scanner.ok())
if (scanner.line() == "ENDMASK") break;
}
init_mask();
while (scanner.ok() && scanner.popkey() != "EN")
{
if (scanner.key() == "PA")
{
read_page(scanner, false);
if (_pages >= max)
break;
}
else
{
if (scanner.key() == "TO")
read_page(scanner, true);
}
}
if (_pages <= 0)
fatal_box("Impossibile leggere la maschera %s : %d", (const char*)_source_file, num);
if (num == 0)
{
TFilename prof; make_profile_name(prof);
if (prof.exist())
{
// Costruisce la lista dei gruppi di appartenenza dell'utente
const TString_array& uag = user_and_groups();
TConfig ini(prof);
FOR_EACH_ARRAY_ROW_BACK(uag, c, utonto)
{
*utonto << "_Locks";
if (ini.set_paragraph(*utonto))
{
TBit_array read_only;
TAuto_token_string lfields(ini.get("Lock"));
TAuto_token_string ufields(ini.get("Unlock"));
if (ufields.find("*")>=0)
{
set_locking(read_only, lfields, true);
}
else
{
set_locking(read_only, lfields, true);
set_locking(read_only, ufields, false);
}
FOR_EACH_MASK_FIELD((*this), j, f)
{
if (f->is_loadable())
{
const bool ro = read_only[j];
if (f->read_only() != ro)
f->set_read_only(ro);
}
}
}
}
TAssoc_array & defs = ini.list_variables("defaults");
FOR_EACH_ASSOC_STRING(defs, obj, key, str)
{
short id = atoi(key);
const int pos = id2pos(id);
if (pos >= 0 && fld(pos).is_operable())
fld(pos).set_default(str);
}
}
}
}
void TMask::add_field(TMask_field* f)
{
const long pos = _field.add(f)+1;
const short id = f->dlg();
if (id > 0 && id < 512)
{
if (f->is_sheet())
{
for (short cid = 101; cid <= 110; cid++)
{
if (_position.objptr(cid) && f->parent() == field(cid).parent())
{
NFCHECK("Lo sheet %d mal sopporta la convivenza col campo %d", id, cid);
break;
}
}
}
if (_position.objptr(id))
{
if (id > DLG_QUIT)
NFCHECK("Il campo %d e' duplicato!", id);
}
else
_position.TArray::add((TObject*)pos, id);
}
}
void TMask::set_tab_buttons(TToken_string& tabs)
{
int tab = 0;
WINDOW nb = notebook();
if (nb == NULL_WIN)
nb = create_book(false);
FOR_EACH_TOKEN(tabs, title)
{
if (tab >= _pages) // Se devo creare piu' orecchie che pagine...
insert_page(page_win(_pages-1), -1); // ... ripeto l'ultima pagina
xvt_notebk_set_tab_title(nb, tab, title);
tab++;
}
}
void TMask::set_default_tab_buttons()
{
TToken_string tabs;
TString16 pag;
for (int i = 1; i <= _pages; i++)
{
pag.format(FR("Pag.%d"), i);
tabs.add(pag);
}
set_tab_buttons(tabs);
}
TMask::TMask(const char* maskname, int num, int max)
: _mask_num(num), _sheet(NULL)
{
if (maskname && *maskname)
read_mask(maskname, num, max);
}
TMask::~TMask()
{
_field.destroy();
}
word TMask::class_id() const
{ return CLASS_MASK; }
bool TMask::is_kind_of(word c) const
{
if (c == CLASS_MASK)
return true;
return TWindow::is_kind_of(c);
}
void TMask::open()
{
if (!_open || _page != 0)
_open = true;
if (toolbar() != NULL_WIN)
xvt_toolbar_realize(toolbar()); // Non si capisce perche' ce ne sia bisogno, ma tant'e'
_focus = first_focus(0);
set_focus_field(fld(_focus).dlg());
}
int TMask::find_first_active(WINDOW p) const
{
const int max = fields();
for (int f = 0; f < max; f++)
{
TMask_field& c = fld(f);
if (c.active() && c.parent() == p)
return f;
}
return -1;
}
int TMask::first_focus(short id, bool dirty)
{
static int tempfirstfocus = -1;
static bool tempdirty = false;
int f = _first_focus;
if (id == 0)
{
if (tempfirstfocus >= 0)
{
f = tempfirstfocus;
if (tempdirty && fld(f).dirty() == false)
fld(f).set_dirty();
tempfirstfocus = -1;
}
else
{
if (f < 0 || !fld(f).active())
{
f = find_first_active(curr_win());
if (f < 0 && toolwin() != NULL_WIN)
f = find_first_active(toolwin());
if (f < 0 && toolbar() != NULL_WIN)
f = find_first_active(toolbar());
}
}
}
else
{
if (id > 0)
{
f = _first_focus = id2pos(id);
tempfirstfocus = -1;
}
else
{
f = tempfirstfocus = id2pos(-id);
tempdirty = dirty;
}
}
CHECKD(f >= 0 && f < fields(), "Invalid focus field ", f);
return f;
}
TOperable_field& TMask::focus_field() const
{
if (is_open())
{
const short focus = low_get_focus_id(curr_win());
if (focus > 0 )
((TMask *)this)->notify_focus_field(focus);
}
TMask_field & f = fld(_focus);
CHECK(f.is_kind_of(CLASS_OPERABLE_FIELD), "A non operable_field has the focus");
return (TOperable_field&)f;
}
void TMask::set_focus_field(short id)
{
notify_focus_field(id);
if (is_open())
{
const TMask_field& f = field(id);
int p = _page > 0 ? _page : 0;
if (f.parent() != curr_win()) // Controllo se devo cambiar pagina
{
p = find_parent_page(f);
if (p < 0 || p >= _pages || !page_enabled(p))
p = 0;
}
show_page(p);
}
}
void TMask::notify_focus_field(short id)
{
const int pos = id2pos(id);
CHECKD(pos >= 0, "Can't set focus to field ", id);
_focus = pos;
}
bool TMask::can_be_closed() const
{
if (is_running())
{
bool ok = true;
if ((edit_mode() || insert_mode()) && dirty() && id2pos(DLG_QUIT) < 0)
ok = yesno_box(TR("Annullare i dati inseriti?"));
if (ok)
((TMask*)this)->stop_run(K_FORCE_CLOSE);
return false;
}
return true; // Should never happen!
}
void TMask::close()
{
_open = false;
_page = -1;
xvt_vobj_set_visible(win(), false);
}
short TMask::dirty() const
{
const int max = fields();
for (int i = 0; i < max; i++)
{
const TMask_field& f = fld(i);
if (f.dirty() && f.active())
return f.dlg();
}
return 0;
}
void TMask::load_checks() const
{
const int max = fields();
int i;
for (i = 0; i < max; i++)
{
const TMask_field& f = fld(i);
if (f.is_edit())
((TEdit_field&)f).test_drivers();
}
for (i = 0; i < max; i++)
{
TMask_field& f = fld(i);
if (f.has_check())
f.check(STARTING_CHECK);
}
}
// @doc EXTERNAL
// @mfunc Abilita/disabilita una pagina e tutte le successive
void TMask::enable_page(
byte page, // @parm Pagina da abilitare/disabilitare
bool on) // @parm Operazione da svolgere:
//
// @flag true | Abilita la pagina <p page> (default)
// @flag false | Disabilita la pagina <p page>
{
if (page > 0 && page < _pages) // Non posso spegnere la prima pagina
{
if (_enabled[page] != on)
{
CHECK(_notebook, "Can't find an useful notebook");
const short tabs = xvt_notebk_get_num_tabs(_notebook);
if (on)
{
// Riaggiungo i tab buttons (normalmente tabs == page)
for (short i = tabs; i < _pages; i++)
{
_enabled.set(i, true);
xvt_notebk_add_page(_notebook, _pagewin[i], NULL, NULL, i);
}
}
else
{
// Elimino i tab buttons (normalmente tabs == _pages)
for (short i = tabs-1; i >= page; i--)
{
_enabled.set(i, false);
xvt_notebk_rem_tab(_notebook, i);
}
_page = -1;
}
}
}
}
// Controlla lo stato di abilitazione di una pagina
// Certified 99%
bool TMask::page_enabled(byte p) const
{
// First page and toolbars are always enabled
const bool on = p == 0 || p >= MAX_PAGES || _enabled[p];
return on;
}
void TMask::start_run()
{
const long start = clock();
const int max = fields();
if (_should_check)
{
TWait_cursor hourglass;
load_checks();
for (int i = 0; i < max; i++)
{
TMask_field& f = fld(i);
if (f.dirty() <= 1) // Attenzione puo' valere anche 3 per i very dirty!
{
f.set_dirty(false);
const bool op = f.is_operable() && (f.active() || f.ghost()) &&
!f.is_kind_of(CLASS_BUTTON_FIELD) &&
!f.is_kind_of(CLASS_BUTTON_TOOL);
if (op)
f.on_hit(); // Lancia messaggio di inizializzazione
}
}
}
_should_check = true;
// Make sure that "nearly" all fields are clean!
for (int i = 0; i < max; i++)
{
TMask_field& f = fld(i);
if (f.dirty() == 1) // Attenzione puo' valere anche 3 per i very dirty!
f.set_dirty(false);
}
_last_test = -1;
}
bool TMask::check_fields()
{
WINDOW curpage = NULL_WIN; // Page under test
const bool sheet = is_sheetmask() && !is_open();
const int max = fields();
for (int i = 0; i < max; i++)
{
TMask_field& f = fld(i);
const bool on = f.active() || (f.shown() && f.is_sheet());
if (on) // Don't test inactive fields
{
if (f.parent() != curpage)
{
const int pa = find_parent_page(f);
if (!page_enabled(pa))
break; // Page disabled: end of test
curpage = f.parent(); // Update current page
}
if (sheet) f.set_dirty(); // Force check in sheet masks
if (f.on_key(K_ENTER) == false)
{
if (is_open())
set_focus_field(f.dlg());
return false;
}
}
}
return true;
}
void TMask::check_field( short fld_id )
{
if (fld_id <= 0)
{
const int gr = -fld_id;
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (gr == 0 || f.in_group(gr))
{
f.on_hit();
f.check();
}
}
}
else
{
field(fld_id).on_hit();
field(fld_id).check();
}
}
// @doc EXTERNAL
// @mfunc Converte un identificatore di campo nella sua posizione
//
// @rdesc Ritorna la posizione del campo nella maschera (-1 se non lo trova)
int TMask::id2pos(
short id) const // @parm Identificatore del campo del quale trovare la posizione
// @comm Cerca nella maschera il campo con identificatore <p id> e ne ritorna il numero ordinale
// (es. il campo 120 e' il quarto della maschera)
{
int pos = -1;
if (id > 0)
{
if (id < 512)
pos = int(long(_position.objptr(id))-1);
else
{
for (pos = fields()-1; pos >= 0; pos--)
if (fld(pos).dlg() == id)
break;
}
}
return pos;
}
TMask_field& TMask::field(short id) const
{
int pos = id2pos(id);
if (pos < 0)
{
yesnofatal_box("Non esiste il campo %d sulla maschera %s", id, (const char*)_source_file);
pos = 0;
}
return fld(pos);
}
int TMask::field2pos(const char* fieldname) const
{
const int id = atoi(fieldname);
int i;
for (i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (id == 0)
{
const TFieldref* fr = f.field();
if (fr != NULL && fr->name() == fieldname)
break;
}
else
{
if (f.dlg() == id)
break;
}
}
return i;
}
TMask_field* TMask::find_by_id(short id) const
{
const int i = id2pos(id);
return i >= 0 ? &fld(i) : NULL;
}
TMask_field* TMask::find_by_fieldname(const char* fieldname) const
{
const int i = field2pos(fieldname);
return i >= 0 ? &fld(i) : NULL;
}
TEdit_field& TMask::efield(short id) const
{
TMask_field& f = field(id);
CHECKD(f.is_edit(), "Impossibile trattare come editabile il campo ", id);
return (TEdit_field&)f;
}
TList_field& TMask::lfield(short id) const
{
TMask_field& f = field(id);
CHECKD(f.is_list(), "Impossibile trattare come listbox il campo ", id);
return (TList_field&)f;
}
TSheet_field& TMask::sfield(short id) const
{
TMask_field& f = field(id);
CHECKD(f.is_sheet(), "Impossibile trattare come spreadsheet il campo ", id);
return (TSheet_field&)f;
}
TTree_field& TMask::tfield(short id) const
{
TMask_field& f = field(id);
CHECKD(f.is_kind_of(CLASS_TREE_FIELD), "Impossibile trattare come albero il campo ", id);
return (TTree_field&)f;
}
// @doc EXTERNAL
int TMask::find_parent_page(const TMask_field& f) const
{
return win2page(f.parent());
}
// @mfunc Forza la chiusura della maschera
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag true | E' riuscita a chiudere la maschera
// @flag false | Non e' riuscita a chiudere la maschera
bool TMask::stop_run(
KEY key) // @parm Tasto che deve provocare la chiusura
// @comm Permette di chiudere la maschera come se l'utente avesse premuto il tasto <p key>.
// Nel caso la maschera non si chiuda (es. un check fallito), ritorna false.
{
if (key != K_AUTO_ENTER && key != K_FORCE_CLOSE)
{
const int last = fields();
int i;
// Cerca se esiste un bottone avente come exit_key() il tasto key
for (i = 0; i < last; i++)
{
const TMask_field& f = fld(i);
if (f.is_operable() && !f.is_editable() && f.active())
{
if (f.is_kind_of(CLASS_BUTTON_FIELD))
{
const TButton_field& b = (const TButton_field&)f;
if (b.exit_key() == key)
break;
} else
if (f.is_kind_of(CLASS_BUTTON_TOOL))
{
const TButton_tool& b = (const TButton_tool&)f;
if (b.exit_key() == key)
break;
}
}
}
if (i >= last)
return false;
}
if (key == K_CTRL_ENTER || key == K_AUTO_ENTER)
key = K_ENTER;
else
{
if (key == K_FORCE_CLOSE)
key = (id2pos(DLG_QUIT)<0 && id2pos(DLG_CANCEL)>=0) ? K_ESC : K_QUIT;
}
if (key != K_ESC && key != K_QUIT && key != K_DEL && key != K_F9)
{
bool ok = check_current_field();
if (ok)
ok = check_fields();
if (ok)
{
if (id2pos(DLG_PROFILE) >= 0 && field(DLG_PROFILE).hidden())
save_profile();
}
else
return false;
}
return TWindow::stop_run(key);
}
void TMask::on_button(short)
{
/* Non devo fare niente !!! non essendo una TWindow */
}
void TMask::handler(WINDOW w, EVENT* ep)
{
static TSheet_field* _last_sheet = NULL;
if (ep->type == E_MOUSE_DOWN && ep->v.mouse.button == 1)
{
_last_sheet = NULL;
w = curr_win();
for (int f = fields()-1; f >= 0; f--)
{
TMask_field& cur_fld = fld(f);
if (cur_fld.shown() && cur_fld.parent() == w)
{
RCT rct; cur_fld.get_rect(rct);
if (xvt_rect_has_point(&rct, ep->v.mouse.where))
{
if (cur_fld.is_kind_of(CLASS_SHEET_FIELD))
_last_sheet = (TSheet_field*)&cur_fld;
else
cur_fld.on_key(K_F11);
break;
}
}
}
if (_last_sheet)
{
MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
if (menu != NULL)
{
const PNT& p = ep->v.mouse.where;
xvt_menu_popup(menu->child, w, p, XVT_POPUP_CENTER, 0); // verificare
xvt_res_free_menu_tree(menu);
}
}
return;
}
if (ep->type == E_COMMAND)
{
const int tag = ep->v.cmd.tag;
if (_last_sheet != NULL)
{
switch (tag - BROWSE_BAR)
{
case 1: _last_sheet->save_columns_order(); break;
case 2: _last_sheet->reset_columns_order(); break;
case 3: _last_sheet->on_key(K_F11); break;
case 4: _last_sheet->esporta(); break;
default: break;
}
return;
}
if (tag == M_HELP_ONCONTEXT)
{
on_key(K_F1);
return;
}
}
if (ep->type == E_VSCROLL)
{
for (int i = 0; i < fields(); i++)
{
const TMask_field& ff = fld(i);
if (ff._ctl != NULL)
{
XI_OBJ* obj = ff._ctl->xi_object();
if (obj->type == 11)
{
const int dir = ep->v.scroll.what == SC_LINE_UP ? -3 : +3;
xi_scroll(obj, dir);
break;
}
}
}
}
if (ep->type == E_CONTROL)
{
if (is_running()) // Scarto a priori gli eventi di inizializzazione
{
switch (ep->v.ctl.ci.type)
{
case WC_NOTEBK:
if (ep->v.ctl.ci.win == _notebook)
{
const int new_page = ep->v.ctl.ci.v.notebk.tab_no;
if (new_page != _page && new_page < _pages) // Cambio pagina effettivo
{
if (fld(_focus).on_key(K_TAB))
show_page(new_page);
}
}
break;
case WC_ICON: // In realta' trattasi di bottone di toolbar
if (ep->v.ctl.ci.win == toolbar()) // Test di sicurezza semi-inutile
{
TMask_field& tool = field(ep->v.ctl.id);
if (tool.active())
tool.on_key(K_SPACE); // Gestisco l'evento di pressione del bottone
}
break;
case WC_HSCROLL:
case WC_VSCROLL:
if (id2pos(ep->v.ctl.id) < 0) // potrebbero non avere un controllo associato
break;
// fall down
case WC_HSLIDER:
case WC_VSLIDER:
case WC_PROPGRID:
{
TMask_field& f = field(ep->v.ctl.id);
f.set_focusdirty();
f.on_key(K_SPACE);
}
break;
default:
break;
}
}
return;
}
if (ep->type == E_UPDATE && w == page_win(0))
{
if (source_file().find("custom") > 0)
{
RCT rct; xvt_vobj_get_client_rect(w, &rct);
rct.left += 2; rct.right -= 2; rct.bottom -= 2;
DRAW_CTOOLS dct;
xvt_dwin_get_draw_ctools(w, &dct);
dct.fore_color = FOCUS_COLOR;
dct.back_color = FOCUS_BACK_COLOR;
dct.opaque_text = TRUE;
xvt_dwin_set_draw_ctools(w, &dct);
//xvt_dwin_set_font(w, DEF_FONT);
xvt_dwin_set_clip(w, NULL);
const char* text = "Custom";
const int tw = xvt_dwin_get_text_width(w, text, -1);
xvt_dwin_draw_text(w, rct.left, rct.bottom, text, -1);
xvt_dwin_draw_text(w, (rct.right-rct.left-tw)/2, rct.bottom, text, -1);
xvt_dwin_draw_text(w, rct.right-tw, rct.bottom, text, -1);
}
}
TWindow::handler(w, ep);
}
// @doc EXTERNAL
// @mfunc Assegna una azione al tasto non standard
//
// @rdesc Ritrna se e' stto effetuato una azione:
//
// @flag true | Era prevista una azione collegata al tasto ed e' stata eseguita
// @flag false | Non era prevista nessuna azione collegata al tasto
bool TMask::on_key(
KEY key) // @parm Tasto premuto sulla maschera
// @comm Controlla se il tasto e' tra quelli standard previsti dalla maschera corrente, in caso
// contrario ne assegna una azione
{
if (_handler)
{
const bool cont = _handler(*this, key);
if (!cont)
return false;
}
switch(key)
{
case K_AUTO_ENTER:
case K_CTRL_ENTER:
case K_QUIT:
case K_ESC:
stop_run(key);
break;
case K_PREV:
if (fld(_focus).on_key(K_TAB))
next_page(-1);
break;
case K_NEXT:
if (fld(_focus).on_key(K_TAB))
next_page(+1);
break;
case K_F1:
{
const char* key = source_file().name_only();
EVENT e; memset(&e, 0, sizeof(e));
e.type = E_HELP;
e.v.help.tag = M_HELP_ONCONTEXT;
e.v.help.obj = win();
e.v.help.tid = (long)key;
TFilename n = "campo";
TString4 module; module.strncpy(key, 2); module.lower();
if (module != "ba")
n.insert(module);
FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(n, &fs);
XVT_HELP_INFO hi = xvt_help_open_helpfile(&fs, 0);
xvt_help_process_event(hi, win(), &e);
}
break;
case K_F12:
send_key(K_F12, focus_field().dlg());
break;
case K_CTRL+'+':
if (is_running())
{
// Cerco nella pagina corrente il primo spreadsheet a partire dal campo col focus
if (_focus < 0) _focus = 0;
const WINDOW myparent = fld(_focus).parent();
for (int fire = _focus; fire < fields(); fire++)
{
TMask_field& f = fld(fire);
if (f.parent() != myparent)
break;
if (f.is_sheet())
{
send_key(key, f.dlg());
break;
}
}
}
break;
default:
if (key > K_CTRL)
{
key -= K_CTRL;
if (key >= K_F1 && key <= K_F12)
{
const int page = key - K_F1;
if (page < _pages && fld(_focus).on_key(K_TAB))
show_page(page);
}
else
{
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (f.is_operable() && !f.is_editable() && f.active())
{
KEY vk = 0;
if (f.is_kind_of(CLASS_BUTTON_FIELD))
{
TButton_field& b = (TButton_field&)f;
vk = b.virtual_key();
} else
if (f.is_kind_of(CLASS_BUTTON_TOOL))
{
TButton_tool& t = (TButton_tool&)f;
vk = t.virtual_key();
}
if (vk > 0 && vk == key)
{
f.on_key(K_SPACE);
break;
}
}
}
}
}
}
return true;
}
bool TMask::on_dirty(TMask_field&)
{
return true;
}
int TMask::win2page(WINDOW w) const
{
if (w == toolwin())
return MAX_PAGES;
if (w == toolbar())
return MAX_PAGES+1;
int p;
for (p = _pages-1; p >= 0; p--)
if (w == page_win(p))
break;
return p;
}
TMask_field* TMask::parse_field(TScanner& scanner)
{
const TString& k = scanner.key();
if (k == "BO") return new TBoolean_field(this);
if (k == "BR") return new TBrowsefile_field(this);
if (k == "BU") return new TButton_field(this);
if (k == "CL") return new TGolem_client_field(this);
if (k == "CU") return new TCurrency_field(this);
if (k == "DA") return new TDate_field(this);
if (k == "GO") return new TGolem_field(this);
if (k == "GR") return new TGroup_field(this);
if (k == "LI") return new TList_field(this);
if (k == "ME") return new TMemo_field(this);
if (k == "NU") return new TReal_field(this);
if (k == "PR") return new TProp_field(this);
if (k == "RA") return new TRadio_field(this);
if (k == "SL") return new TSlider_field(this);
if (k == "SP") return new TSheet_field(this);
if (k == "ST") return new TEdit_field(this);
if (k == "TE") return new TText_field(this);
if (k == "TR") return new TTree_field(this);
if (k == "ZO") return new TZoom_field(this);
return NULL;
}
TMask_field* TMask::parse_tool(TScanner& scanner)
{
const TString& k = scanner.key();
if (k == "BU") return new TButton_tool(this);
return NULL;
}
int TMask::sheets() const
{
int count = 0;
for (int f = fields()-1; f >= 0; f--)
{
if (fld(f).is_sheet())
count++;
}
return count;
}
// @doc EXTERNAL
// @mfunc Legge la pagina dal file
//
// @rdesc Ritorna l'handle della finestra creata
void TMask::read_page(
TScanner& scanner, // @parm File dal quale leggere la pagina
bool is_toolbar) // @parm Indica se e' la toolbar
// @comm Il parametro <p toolbar> e' utilizzato per indicare se la pagina deve essere visualizzata
// a tutto schermo (true) oppure no
{
const TString title = dictionary_translate(scanner.string());
RCT r;
if (!is_toolbar && notebook() != NULL_WIN) // Pagina oltre la prima
{
scanner.line(); // Scarto rettangolo inutile
xvt_rect_set(&r, 0, 0, 0, 0);
}
else
{
scanner.rectangle(r.left, r.top, r.right, r.bottom);
if (is_toolbar)
{
if (r.top > 15) // Rendi negative le coordinate delle toolbar per ...
r.top -= 23; // ... ottimizzare l'uso dello schermo ad alta risoluzione
}
}
if (_notebook == NULL_WIN && _single == NULL) // Controlla se la maschera ha piu' di una pagina ...
{ // ... nel caso serva un notebook per le prossime
const streampos pos = scanner.tellg(); // Memorizza posizione dello scanner
while (true)
{
const TString& l = scanner.line();
if (l.empty() || l == "ENDMASK") // Fine maschera
break;
if (l.starts_with("PA") || l.starts_with("TO")) // Ho trovato un'altra pagina!
{
if (is_toolbar)
create_book(false); // Crea notebook
else
{
WINDOW w = create_interface(NULL_WIN, r.left, r.top, r.right, r.bottom, title, this);
insert_page(w, 0); // Crea pagina principale
const bool single = l.starts_with("TO"); // Crea sotto-pagina singola o multipla?
create_book(single);
}
break;
}
}
scanner.seekg(pos); // Ripristina posizione dello scanner
}
WINDOW w = NULL_WIN;
if (is_toolbar)
{
if (r.top == 0)
w = create_bar(1);
else
{
CHECKD(r.top < 0, "Bad bottom bar height ", r.top);
w = create_bar(r.top);
}
}
else
{
if (notebook() != NULL_WIN)
w = create_page(title, -1);
else
{
if (_single != NULL_WIN)
w = _single;
else
{
CHECK(win() == NULL_WIN, "bad page sequence");
w = create_interface(NULL_WIN, r.left, r.top, r.right, r.bottom, title, this);
insert_page(w, 0);
}
}
}
while (scanner.popkey() != "EN")
{
TMask_field* f = NULL;
if (is_toolbar && r.top == 0)
f = parse_tool(scanner);
else
f = parse_field(scanner);
if (f == NULL)
{
#ifdef DBG
const int pf = fields();
TString e;
e << "Campo non riconosciuto alla posizione " << pf;
if (pf > 0)
e << "\nL'ultimo riconosciuto e' " << fld(pf-1).dlg() << ": " << fld(pf-1).prompt();
error_box(e);
#endif
while (scanner.popkey() != "EN");
}
else
{
f->construct(scanner, w);
add_field(f);
}
}
if (is_toolbar && r.top ==0 && _toolbar != NULL_WIN)
xvt_toolbar_realize(_toolbar);
}
bool TMask::check_current_field() const
{
bool ok = true;
if (_focus >= 0)
{
TMask_field& ff = fld(_focus);
if (ff.focusdirty())
ok = ff.on_key(K_TAB);
}
return ok;
}
WINDOW TMask::create_book(bool single)
{
WINDOW parent = win();
if (parent == NULL_WIN)
{
parent = create_interface(NULL_WIN, 0, 0, 0, 0, "", this);
set_win(parent);
}
if (single)
{
CHECK(_single == NULL_WIN, "One single page pane, please!");
_single = create_interface(parent, 0, 0, 0, 0, "", this);
xvt_pane_add(parent, _single, "_MainSingle_", 0, 0);
_pagewin[0] = _single;
_pages = 1;
}
else
{
CHECK(_notebook == NULL_WIN, "One single notebook, please!");
XVT_COLOR_COMPONENT xcc[4]; memset(xcc, 0, sizeof(xcc));
xcc[0].type = XVT_COLOR_BACKGROUND; xcc[0].color = MASK_BACK_COLOR;
xcc[1].type = XVT_COLOR_FOREGROUND; xcc[1].color = NORMAL_COLOR;
WIN_DEF wd; memset(&wd, 0, sizeof(wd));
wd.wtype = WC_NOTEBK;
wd.ctlcolors = xcc;
wd.v.ctl.flags = CTL_FLAG_TAB_DEFAULT | CTL_FLAG_TAB_TOP;
xvt_vobj_get_client_rect(parent, &wd.rct);
_notebook = xvt_ctl_create_def(&wd, parent, long(this));
xvt_pane_add(parent, _notebook, "_MainNoteBook_", 0, 0);
if (_single != NULL) // Bello ... se solo andasse!
{
xvt_pane_detach(_single);
insert_page(_single, 0);
_single = NULL_WIN;
}
}
return single ? _single : _notebook;
}
void TMask::insert_bar(WINDOW page)
{
WINDOW parent = win();
CHECK(page != NULL_WIN, "Invalid toolbar");
CHECK(parent != NULL_WIN, "Invalid main window for toolbar");
if (_notebook == NULL_WIN && _single == NULL_WIN)
create_book(true); // In assenza di notebook crea un pane a pagina singola
RCT rct_win; xvt_vobj_get_outer_rect(parent, &rct_win);
RCT rct_bar; xvt_vobj_get_outer_rect(page, &rct_bar);
if (rct_bar.top > (rct_win.bottom-rct_win.top)/2) // BottomBar
{
CHECK(_toolwin == NULL_WIN, "One single bottom bar, please!");
_toolwin = page;
xvt_pane_add(parent, _toolwin, "_BottomBar_", 4, 0);
// Ammazza la caption e ne blocca le dimensioni
xvt_pane_change_flags(page, 0, 1 <<10); // No caption
xvt_pane_change_flags(page, 0, 1 << 8); // No resize
}
else // TopBar
{
CHECK(_toolbar == NULL_WIN, "One single top bar, please!");
if (rows() < 18) // Ridimensiono maschera piccola (non massimizzata)
{
const short bar_height = max(rct_bar.bottom - rct_bar.top, TOOL_SIZE + TOOL_TEXT * 12);
RCT rct_new; xvt_vobj_get_client_rect(parent, &rct_new);
rct_new.bottom += bar_height;
xvt_rect_offset(&rct_new, rct_win.left, rct_win.top-bar_height/2);
xvt_vobj_move(parent, &rct_new);
}
_toolbar = page;
xvt_pane_add(parent, _toolbar, "_TopBar_", 62, 0);
}
}
WINDOW TMask::create_bar(int height)
{
WINDOW w = NULL_WIN;
if (height < 0)
w = create_interface(win(), 0, height, 0, 0, "", this); // Bottom bar
else
{
const long flags = TOOL_TEXT ? CTL_FLAG_PASSWORD : 0;
w = xvt_toolbar_create(-1, 0, 0, -1, TOOL_SIZE, flags, win()); // Top bar
XVT_COLOR_COMPONENT cc[4]; memset(cc, 0, sizeof(cc));
cc[0].type = XVT_COLOR_BLEND; cc[0].color = MASK_BACK_COLOR;
cc[1].type = XVT_COLOR_FOREGROUND; cc[1].color = NORMAL_COLOR;
xvt_ctl_set_colors(w, cc, XVT_COLOR_ACTION_SET);
}
insert_bar(w); // Inserisce toolbar e crea notebook, se necessario
return w;
}
void TMask::insert_page(WINDOW page, int dove)
{
CHECKD(dove >= -1 && dove <= _pages, "Invalid page position:", dove);
// Per le pagine dopo la prima devo creare il notebook
if (_pages == 1 && _notebook == NULL_WIN)
create_book(false);
memset(_pagewin, 0, sizeof(_pagewin)); // Azzero lista pagine
if (_notebook != NULL_WIN) // property sheet
{
xvt_notebk_add_page(_notebook, page, NULL, NULL, dove);
_pages = xvt_notebk_get_num_tabs(_notebook);
// Ricostruisco lista pagine
for (short p = 0; p < _pages; p++)
_pagewin[p] = xvt_notebk_get_page(_notebook, p);
}
else // single page
{
CHECK(win() == NULL_WIN, "One single main page, please!");
set_win(page);
_pagewin[0] = page; // Assegno la prima ed unica pagina
_pages = 1;
}
}
WINDOW TMask::create_page(const char* title, int dove)
{
CHECKD(dove < 0 || dove < MAX_PAGES, "invalid page position ", dove);
WINDOW w = create_interface(notebook(), 0, 0, 0, 0, title, this);
insert_page(w, dove);
return w;
}
void TMask::set_focus()
{
TWindow::set_focus();
WINDOW w = curr_win();
if (w != win()) // Succede se ci sono notebook o toolbar
{
xvt_scr_set_focus_vobj(w);
xvt_vobj_raise(w);
}
}
// @doc EXTERNAL
// @mfunc Mostra la prossima/precedente pagina
void TMask::next_page(
int p) // @parm Pagina alla quale saltare
// @comm Il valore <p p> puo' assumere i seguenti valori:
//
// @flag -1 | Mostra la pagina precedente
// @flag 0 | Mostra la pagina corrente
// @flag +1 | Mostra la pagina successiva
// @flag 1000+n | Mostra la pagina n-esima
{
const int prev = _page; // Previous page
if (p != 0)
{
const int k = (p < 1000) ? _page+p : p-1000;
if (k < 0 || k >= _pages || !page_enabled(k))
{
beep();
return;
}
_page = k;
}
else
{
if (_page < 0 || _page >= _pages)
_page = 0;
}
if (_page != prev)
{
xvt_vobj_set_visible(win(), true);
if (notebook() != NULL)
xvt_notebk_set_front_page(notebook(), _page);
}
if (_focus < 0 || fld(_focus).parent() != curr_win() || !fld(_focus).active())
{
_focus = find_first_active(curr_win());
if (_focus < 0 && toolwin() != NULL_WIN)
_focus = find_first_active(toolwin());
if (_focus < 0 && toolbar() != NULL_WIN)
_focus = find_first_active(toolbar());
}
set_focus();
if (_focus >= 0)
{
TMask_field& ff = fld(_focus);
if (ff.active())
ff.highlight();
}
}
void TMask::show_page(int p)
{
CHECKD(p >= 0 && p < _pages, "Pagina errata ", p);
next_page(1000 + p);
}
void TMask::reset(short fld_id)
{
if (fld_id <= 0)
{
const int gr = -fld_id;
for (int f = fields()-1; f >= 0; f--)
{
TMask_field& c = fld(f);
if (gr == 0 || c.in_group(gr))
{
c._flags.dirty = c._flags.focusdirty = false;
c.reset();
}
}
}
else field(fld_id).reset();
}
const TString& TMask::get(short fld_id) const
{
const TString& s = field(fld_id).get();
return s;
}
const TString& TMask::get(const char * fld_id) const
{
const TString * s = &EMPTY_STRING;
for (int i = 0 ; i < fields(); i++)
{
TMask_field& f = fld(i);
const TFieldref * campo = f.field();
if (campo != NULL && campo->name() == fld_id)
{
s= &f.get();
if (f.active())
break;
}
}
return *s;
}
long TMask::get_long(short fld_id) const
{
// const TString& s = field(fld_id).get();
const TString& s = get(fld_id);
return atol(s);
}
bool TMask::get_bool(short fld_id) const
{
// const TString& s = field(fld_id).get();
const TString& s = get(fld_id);
return s.not_empty();
}
real TMask::get_real(short fld_id) const
{
// const TString& s = field(fld_id).get();
const TString& s = get(fld_id);
return real(s);
}
TDate TMask::get_date(short fld_id) const
{
// const TString& s = field(fld_id).get();
const TString& s = get(fld_id);
return TDate(s);
}
TCurrency& TMask::get_currency(short fld_id, TCurrency& c) const
{
const TMask_field& cf = field(fld_id);
if (cf.class_id() == CLASS_CURRENCY_FIELD)
{
((TCurrency_field&)cf).get_currency(c);
}
else
{
real n(cf.get());
c.force_value("");
c.set_num(n);
}
return c;
}
// @doc EXTERNAL
// @mfunc Setta il campo con un valore
void TMask::set(
short fld_id, // @parm Identificatore del campo da settare
const char* s, // @parm Stringa da assegnare al campo
byte hit) // @parm Indica se occorre rifare i controlli una volta settato il campo
// con il nuovo valore (default false)
// @parm long | n | Numero da asegnare al campo
// @syntax set(short fld_id, const char *s, bool hit);
// @syntax set(short fld_id, long n, bool hit);
{
TMask_field& f = field(fld_id);
f.set(s);
if ((f.active() || f.ghost()))
{
f.set_dirty();
if (hit & 0x2)
f.check();
if (hit & 0x1)
f.on_hit();
}
}
void TMask::set(
const char * fld_id, // @parm FIELD del campo da settare
const char* str, // @parm Stringa da assegnare al campo
byte hit) // @parm Indica se occorre rifare i controlli una volta settato il campo
// con il nuovo valore (default false)
// @parm long | n | Numero da asegnare al campo
// @syntax set(short fld_id, const char *s, bool hit);
// @syntax set(short fld_id, long n, bool hit);
{
for (int i = 0 ; i < fields(); i++)
{
TMask_field& f = fld(i);
const TFieldref * campo = f.field();
if (campo != NULL && campo->name() == fld_id)
set(f.dlg(), str, hit);
}
}
void TMask::set(short fld_id, long n, byte hit)
{
TString16 s;
s << n;
set(fld_id, s, hit);
}
void TMask::set(short fld_id, const real& n, byte hit)
{
CHECK(id2pos(fld_id) < 0 || field(fld_id).is_edit(), "Can't set a real value in a non edit field");
set(fld_id, n.string(), hit);
}
void TMask::set(short fld_id, const TDate& d, byte hit)
{
CHECK(id2pos(fld_id) < 0 || field(fld_id).is_kind_of(CLASS_DATE_FIELD), "Can't set a date in a non-date field");
set(fld_id, d.string(), hit);
}
void TMask::set(short fld_id, const TCurrency& n, byte hit)
{
CHECK(field(fld_id).is_kind_of(CLASS_CURRENCY_FIELD), "Can't set a currency in a non-currency field");
// CHECK(id2pos(fld_id) < 0 || field(fld_id).is_edit(), "Can't set a currency in a non edit field");
set(fld_id, n.get_num().string(), hit);
}
// @doc EXTERNAL
// @mfunc Permette di attivare/disattivare tutta la maschera
void TMask::activate(
bool on) // @parm Indica l'operazione da svolgere sul campo:
//
// @flag true | Attiva la pagina(default)
// @flag false | Disattiva la pagina
{
TWindow::activate(on);
// Maschera vecchia e decrepita senza toolbar: nascondo i bottoni
if (toolwin() != NULL_WIN && toolbar() == NULL_WIN)
xvt_vobj_set_visible(toolwin(), on);
}
// @doc EXTERNAL
// @mfunc Abilita/disabilita un campo
void TMask::enable(
short fld_id, // @parm Identificatore del campo da abilitare (0 tutti i campi, <0 id gruppo)
bool on) // @parm Indica l'operazione da svolgere sul campo:
//
// @flag true | Abilita il campo (default)
// @flag false | Disabilita il campo
{
if (fld_id <= 0)
{
const int gr = -fld_id;
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (gr == 0 || f.in_group(gr))
f.enable(on);
}
}
else
field(fld_id).enable(on);
}
void TMask::enable_default(short fld_id)
{
if (fld_id <= 0)
{
const int gr = -fld_id;
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (gr == 0 || f.in_group(gr))
f.enable_default();
}
}
else
field(fld_id).enable_default();
}
word TMask::num_keys() const
{
word max = 0;
for (int i = fields()-1; i >= 0; i--)
{
const TMask_field& f = fld(i);
if (f.is_editable())
{
word k = ((const TEditable_field&)f).last_key();
if (k > max) max = k;
}
}
return max;
}
// @doc EXTERNAL
// @mfunc Abilita/disabilita i campi di una chiave sulla maschera
void TMask::enable_key(
word key, // @parm Chiave di cui abilitare il campo
bool on) // @parm Indica l'operazione da svolgere sul tasto:
//
// @flag true | Abilita il campo (default)
// @flag false | Disabilita il campo
{
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (f.in_key(key))
{
if (on)
{
f.enable_default();
if (!f.shown())
f.show_default();
}
else
f.disable();
}
}
}
// @doc EXTERNAL
// @mfunc Ritorna il l'identificatore di un campo della chiave <p key>
//
// @rdesc Ritorna l'identificatore del campo cercato
TEditable_field* TMask::get_key_field(
word key, // @parm Chiave di cui controllare l'esistenza
bool first) const // @parm Indica se la ricerca dev partire dell'inizio. Assume i valori:
//
// @flag true | Comincia la ricerca dal primo campo della maschera
// @flag false | Comincia la ricerca dal campo attuale nella maschera
{
static int last = 0;
if (first) last = 0;
const int max = fields();
for (int i = last; i < max; i++)
{
TMask_field& f = fld(i);
if (f.in_key(key))
{
last = i+1;
return (TEditable_field*)&f;
}
}
return NULL;
}
bool TMask::key_valid(word key) const
{
const int maxflds = fields();
bool full = false;
for (int f = 0; f < maxflds; f++)
{
TMask_field& c = fld(f);
if (c.is_editable() && c.shown() && c.in_key(key))
{
if (c.empty())
{
if (c.required())
return false;
}
else
full = true;
}
}
return full;
}
// @doc EXTERNAL
// @mfunc Permette di mostrare/nascondere un campo
void TMask::show(
short fld_id, // @parm Campo da mostrare/nascondere (default -1)
bool on) // @parm Indica l'operazione da svolgere sul campo:
//
// @flag true | Mostra il campo(default)
// @flag false | Nasconde il campo
// @comm Se <p fld_id> e' -1 allora permette di operare su tutti i campi della maschera
{
if (fld_id <= 0)
{
const int gr = -fld_id;
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (gr == 0 || f.in_group(gr))
f.show(on);
}
}
else field(fld_id).show(on);
}
// @doc EXTERNAL
// @mfunc Rimette lo stato di default del campo
void TMask::show_default(
short fld_id) // @parm Identificatore del campo da risettare (default -1)
// @comm Se <p parm> Assume il valore -1 vuole dire che vengono risettati tutti i campi della amschera
{
if (fld_id <= 0)
{
for (int i = fields()-1; i >= 0; i--)
fld(i).show_default();
} else field(fld_id).show_default();
}
void TMask::autoload(const TRelation& r)
{
FOR_EACH_MASK_FIELD((*this), i, f) if (f->is_loadable())
((TLoadable_field*)f)->autoload(r);
}
void TMask::autosave(TRelation& r) const
{
FOR_EACH_MASK_FIELD((*this), i, f) if (f->is_loadable())
{
bool save = f->shown();
if (!save && f->is_editable())
{
// tenta di effettuare il save dei campi Edit hidden:
// salva il nuovo valore solo se il precedente era blank
if (f->field() != NULL)
{
const char* str = f->field()->read(r);
save = *str == '\0';
}
}
if (save)
((TLoadable_field*)f)->autosave(r);
}
}
void TMask::on_firm_change()
{
TString16 firm;
firm << prefix().get_codditta();
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (f._flags.firm)
{
f.set(firm);
f.check(STARTING_CHECK);
f.on_hit();
}
}
}
void TMask::on_idle()
{
if (_focus >= 0 && _focus < fields())
{
if (fld(_focus).is_operable())
{
TOperable_field& s = (TOperable_field&)fld(_focus);
s.on_idle();
if (_msg_field > 0)
{
TMask_field& f = field(_msg_field);
_msg_field = 0;
if (_msg_key > 0)
f.on_key(_msg_key);
}
}
if (_error_severity > 0)
{
set_focus();
switch(_error_severity)
{
case 2:
warning_box("%s", (const char*)_error_message); break;
case 3:
error_box("%s", (const char*)_error_message); break;
default:
message_box("%s", (const char*)_error_message); break;
}
_error_severity = 0;
}
if (_test_fld >= 0)
{
const TOperable_field & f = focus_field();
if (_last_test != f.dlg())
{
TEditable_field & e = (TEditable_field &) field(_test_fld);
if (!f.in_key(0) || !e.has_a_common_key(f))
{
e.test_key_complete(false);
_test_fld = -1;
}
_last_test = f.dlg();
}
}
}
}
// @doc EXTERNAL
// @mfunc Permette di mandare un tasto ad un campo
void TMask::send_key(
KEY key, // @parm Codice del tasto da spedire
short to, // @parm Identificatore del campo che deve ricevere
TMask_field* from) // @parm Campo che spedisce il tasto
{
if (to == 0)
{
WINDOW w = from ? from->parent() : win();
dispatch_e_char(w, key);
return;
}
if (to > 0)
{
if (to == DLG_PAGE)
{
CHECK(from, "You should specify a sender!");
const int p = find_parent_page(*from)+1;
CHECKD(p > 0 && p < _pages, "You should specify a good page, not ", p);
key -= K_CTRL+K_SHIFT;
enable_page(p, key == 's' || key == 'e');
}
else
{
const int pos = id2pos(to);
if (pos >= 0)
{
if (_msg_field > 0)
on_idle();
_msg_field = to;
_msg_key = key;
}
#ifdef DBG
else
NFCHECK("Can't send key %u to field %d", key, to);
#endif
}
}
else
{
const int gr = -to;
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& campo = fld(i);
if (campo.in_group(gr))
campo.on_key(key);
}
}
}
// @doc EXTERNAL
// @mfunc Permette di mandare un handler ad controllo o ad una maschera
void TMask::set_handler(
short fld_id, // @parm Identificatere del campo che deve ricevere l'handler
CONTROL_HANDLER handler) // @parm Handler da spedire al campo
// @parm MASK_HANDLER | handler | Handler da spedire alla maschera
// @syntax set_handler(short fld_id, CONTROL_HANDLER handler);
// @syntax set_handler(MASK_HANDLER handler);
//
// @comm Nel primo caso viene mandato un <t CONTROL_HANDLER> al campo indicato
// da <p fld_id>, mentre nel secondo viene mandato un <t MASK_HANDLER>
// alla maschera corrente
{
TMask_field& f = field(fld_id);
CHECKD(f.is_operable(), "Can't set an handler to non-operable field ", fld_id);
((TOperable_field&)f).set_handler(handler);
}
void TMask::set_handler(MASK_HANDLER handler)
{
_handler = handler;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo testo alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TMask_field& TMask::add_static (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
const char* flags) // @parm Flag di controllo del campo (deafult "")
// @xref <mf TMask::add_string> <mf TMask::add_number> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TText_field* f = new TText_field(this);
f->construct(id, prompt, x, y, 0, page_win(page), flags);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo stringa alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TEdit_field& TMask::add_string (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dim, // @parm Lunghezza del campo sulla maschera
const char* flags, // @parm Flag di controllo del campo (defailt "")
int width) // @parm Lunghezza totale del campo stringa (default 0)
// @xref <mf TMask::add_static> <mf TMask::add_number> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TEdit_field* f = new TEdit_field(this);
f->construct(id, prompt, x, y, dim, page_win(page), flags, width);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo bottone alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TButton_field& TMask::add_button (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo (in caratteri, default 9)
int dy, // @parm Altezza del campo (in caratteri, default 1)
const char* flags, // @parm Flag di controllo del campo (default "")
short bmpup, // @parm Icona normale
short bmpdn) // @parm Icona premuta
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_date> <mf TMask::add_radio> <mf TMask::add_memo>
{
TButton_field* f = new TButton_field(this);
f->construct(id, prompt, x, y, dy, page_win(page), flags, dx, bmpup, bmpdn);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo boolean alla maschera
//
// @rdesc Ritorna il descrittore del campo aggiunto
TBoolean_field& TMask::add_boolean (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
const char* flags) // @parm Flag di controllo del campo (default "")
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_date> <mf TMask::add_radio> <mf TMask::add_memo>
{
TBoolean_field* f = new TBoolean_field(this);
f->construct(id, prompt, x, y, strlen(prompt), page_win(page), flags);
add_field(f);
return *f;
}
TCheckbutton_field& TMask::add_checkbutton (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo (in caratteri, default 9)
int dy, // @parm Altezza del campo (in caratteri, default 1)
const char* flags, // @parm Flag di controllo del campo (default "")
short bmpup, // @parm Icona normale
short bmpdn) // @parm Icona premuta
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_date> <mf TMask::add_radio> <mf TMask::add_memo>
{
TCheckbutton_field* f = new TCheckbutton_field(this);
f->construct(id, prompt, x, y, dy, page_win(page), flags, dx);
if (bmpup > 0)
((TCheckbutton_control*)f->_ctl)->set_icon(bmpup, bmpdn);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo numerico alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TReal_field& TMask::add_number (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dim, // @parm Lunghezza del campo sulla maschera
const char* flags, // @parm Flag di controllo del campo (default "")
int ndec) // @parm Numero di decimali (default 0)
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TReal_field* f = new TReal_field(this);
f->construct(id, prompt, x, y, dim, page_win(page), flags, ndec);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo importo alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TCurrency_field& TMask::add_currency (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dim, // @parm Lunghezza del campo sulla maschera
const char* flags, // @parm Flag di controllo del campo (default "")
short driver) // @parm Campo con codice valuta
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TCurrency_field* f = new TCurrency_field(this);
f->construct(id, prompt, x, y, dim, page_win(page), flags, 0);
if (driver != 0)
f->add_driver(driver);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo data alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TDate_field& TMask::add_date (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
const char* flags) // @parm Flag di controllo del campo (default "")
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TDate_field* f = new TDate_field(this);
f->construct(id, prompt, x, y, 10, page_win(page), flags);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo lista alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TList_field& TMask::add_list (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dim, // @parm Lunghezza del campo sulla maschera
const char* flags, // @parm Flag di controllo del campo (default "")
const char* codes, // @parm tokenstring con i codici (NULL def.)
const char* items) // @parm tokenstring con gli items (NULL def.)
// @xref <mf TMask::add_static> <mf TMask::add_number> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TList_field* f = new TList_field(this);
f->construct(id, prompt, x, y, dim, page_win(page), flags);
f->replace_items(codes,items);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo radio button alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TRadio_field& TMask::add_radio(
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo (in caratteri)
const char* codes, // @parm Array di codici delle voci
const char* items, // @parm Array di prompt delle voci
const char* flags) // @parm Flag di controllo del campo (default "")
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_date> <mf TMask::add_button> <mf TMask::add_memo>
{
TRadio_field* f = new TRadio_field(this);
f->replace_items(codes, items);
f->construct(id, prompt, x, y, dx, page_win(page), flags, dx);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo zoom alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TZoom_field& TMask::add_zoom (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dim, // @parm Lunghezza del campo sulla maschera
const char* flags, // @parm Flag di controllo del campo (defailt "")
int width) // @parm Lunghezza totale del campo stringa (default 0)
// @xref <mf TMask::add_static> <mf TMask::add_number> <mf TMask::add_date>
// <mf TMask::add_button> <mf TMask::add_radio> <mf TMask::add_memo>
{
TZoom_field* f = new TZoom_field(this);
f->construct(id, prompt, x, y, dim, page_win(page), flags, width);
add_field(f);
return *f;
}
// @doc EXTERNAL
// @mfunc Aggiunge runtime un campo memo alla maschera
//
// @rdesc Ritorna l'handle del campo creato
TMemo_field& TMask::add_memo(
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo (in caratteri, deafilt 78)
int dy, // @parm Altezza del campo (in caratteri, default 4)
const char* flags) // @parm Flag di controllo del campo (default "")
// @xref <mf TMask::add_static> <mf TMask::add_string> <mf TMask::add_number>
// <mf TMask::add_date> <mf TMask::add_button> <mf TMask::add_radio>
{
TMemo_field* f = new TMemo_field(this);
f->construct(id, prompt, x, y, dy, page_win(page), flags, dx);
add_field(f);
return *f;
}
TTree_field& TMask::add_tree (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo sulla maschera
int dy, // @parm Altezza del campo sulla maschera
const char* flags)// @parm Flag di controllo del campo (default "")
{
TTree_field* f = new TTree_field(this);
f->construct(id, "", x, y, dy, page_win(page), flags, dx);
add_field(f);
return *f;
}
TGroup_field& TMask::add_groupbox (
short id, // @parm Numero identificatore del campo da aggiungere
int page, // @parm Pagina nel quale aggiungere il campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Coordinata x (in caratteri)
int y, // @parm Coordinata y (in caratteri)
int dx, // @parm Larghezza del campo sulla maschera
int dy, // @parm Altezza del campo sulla maschera
const char* flags)// @parm Flag di controllo del campo (default "")
{
TGroup_field* f = new TGroup_field(this);
f->construct(id, prompt, x, y, dy, page_win(page), flags, dx);
add_field(f);
return *f;
}
TButton_tool& TMask::add_button_tool(short id, const char* prompt, short bmpup)
{
if (toolbar() == NULL_WIN) // Se non c'e' ancora la toolbar, me l'invento adesso
create_bar(1);
CHECKD(id <= 0 || bmpup > 0, "Toolbar button needs a wonderful icon ", id);
TButton_tool* t = new TButton_tool(this);
t->construct(id, prompt, 0, 0, 0, toolbar(), "", 0, bmpup, 0);
add_field(t);
return *t;
}
// @doc EXTERNAL
// @mfunc Salva i valori dei campi della maschera sul file di salvataggio
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag true | Se l'operazione e' avvenuta corretamente
// @flag false | Se non si riesce a creare il file di salvataggio
bool TMask::save(
bool append) const // @parm Indica se creare il file o appendere (true) le informazioni
// ad uno gia' esistente (false, default).
{
FILE* f = fopen(_workfile, append ? "a" : "w");
if (f == NULL)
return yesnofatal_box("Non posso aprire %s ", (const char*) _workfile);
const int max = fields();
for (int i = 0; i < max; i++)
{
TMask_field& c = fld(i);
if (c.is_editable())
fprintf(f, "%d|%s\n", c.dlg(), (const char*)c.get());
}
fprintf(f, "[EOM]\n");
fclose(f);
return true;
}
// @doc EXTERNAL
// @mfunc Legge i valori dei campi della maschera da file di salvataggioo
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag true | Se l'operazione e' avvenuta corretamente
// @flag false | Se non si riesce a leggere il file di salvataggio
bool TMask::load(
bool reset) // @parm Indica la posizione di lettura del file:
//
// @flag true | Comincia la lettura dell'inizio
// @flag false | Comincia la lettura dalla posizione corrente dell'offset
{
FILE* f = fopen(_workfile, "r");
if (f == NULL) return false;
if (reset) _lastpos = 0;
fseek(f, _lastpos, SEEK_SET);
TToken_string t(256);
char* buffer = t.get_buffer();
while (fgets(buffer, t.size(), f) != NULL && t != "[EOM]")
{
if (t.not_empty())
{
t.rtrim();
const int pos = id2pos(t.get_int(0));
if (pos >= 0) fld(pos).set(t.get());
}
}
_lastpos = ftell(f);
fclose(f);
return true;
}
// @doc EXTERNAL
// @mfunc Copia i valori dei campi dalla maschera <p m>
//
void TMask::copy_values(
const TMask& m) // @parm Maschera sorgente
{
reset();
const int nfields = fields();
for (int i = 0; i < nfields; i++)
{
TMask_field& dest_field = fld( i );
if (dest_field.is_editable() )
{
const int pos = m.id2pos(dest_field.dlg());
if (pos >= 0)
{
const TMask_field& source_field = m.fld(pos);
dest_field.set( source_field.get( ) );
}
}
}
}
bool TMask::make_profile_name(TFilename& f) const
{
f = source_file().name();
f.ext("ini");
if (!f.custom_path()) // Prova a cercare la configurazione in custom ...
{ // ... altrimenti riprova in config
f =::firm2dir(-1); // Directory dati
f.add("config"); // Directory config
f.add(source_file().name()); // Nome Maschera
f.ext("ini"); // Estensione
}
return f.exist();
}
int TMask::save_profile(int num, const char* desc) const
{
TFilename prof;
make_profile_name(prof);
TConfig ini(prof, "Main");
if (num == 0)
num = ini.get_int(user());
if (num <= 0)
{
TString_array p;
TBit_array b(256);
b.set(255); b.set(); b.reset(0);
ini.list_paragraphs(p);
FOR_EACH_ARRAY_ROW_BACK(p, r, row)
{
num = atoi(*row);
if (num > 0)
b.reset(num);
}
num = int(b.first_one());
}
TString16 para; para << num;
ini.set(user(), para);
TString description = desc;
if (ini.set_paragraph(para))
{
if (description.blank())
description = ini.get("Description");
ini.remove_all();
}
else
{
if (description.blank())
description << "Profilo standard per " << user();
}
ini.set("Description", description);
TString16 name;
for (int i = 0; i < fields(); i++)
{
TMask_field& f = fld(i);
if (f.is_loadable() && f.get_default().empty())
{
name.format("F_%d", f.dlg());
if (f.is_sheet())
{
TSheet_field& s = (TSheet_field&)f;
FOR_EACH_SHEET_ROW(s, r, row)
ini.set(name, *row, NULL, true, r);
}
else
{
if (!f.is_firm())
ini.set(name, f.get());
}
}
}
return num;
}
int TMask::load_profile(int num, bool reset)
{
TFilename prof;
if (make_profile_name(prof))
{
TConfig ini(prof, "Main");
if (num <= 0)
num = ini.get_int(user());
else
ini.set(user(), num);
TString16 name; name << num;
TAssoc_array& var = ini.list_variables(name);
if (var.items() > 0)
{
for (int pos = fields()-1; pos >= 0; pos--)
{
TMask_field& f = fld(pos);
if (f.is_loadable() && f.get_default().empty())
{
name.format("F_%d", f.dlg());
if (reset || var.objptr(name) != NULL)
{
if (f.is_sheet())
{
TSheet_field& sf = (TSheet_field&)f;
sf.destroy();
for (int r = 0; ini.exist(name,r); r++)
sf.row(r) = ini.get(name, NULL, r);
sf.force_update();
}
else
{
if (!f.is_firm())
f.set(ini.get(name));
}
}
}
}
}
}
return num;
}
bool TMask::kill_profile(int num)
{
TFilename prof;
make_profile_name(prof);
TConfig ini(prof, "Main");
if (num <= 0)
num = ini.get_int(user());
TString8 name; name << num;
const bool ok = ini.set_paragraph(name);
if (ok)
ini.remove_all();
return ok;
}
void TMask::load_defaults()
{
for (int pos = 0; pos < fields(); pos++)
{
TMask_field& f = fld(pos);
if (f.is_loadable())
{
const TString & def = f.get_default();
if (def.full())
f.set(def);
}
}
}
const char* TMask::get_caption(TString& str) const
{
char* title = str.get_buffer(128);
xvt_vobj_get_title(win(), title, str.size());
return title;
}
void TMask::set_caption(const char* c)
{
TToken_string captions(c);
if (_notebook != NULL_WIN)
{
for (int p = 0; p < _pages; p++)
{
const char* title = captions.get();
if (title == NULL)
title = captions.get(0);
xvt_notebk_set_tab_title(_notebook, p, title);
}
}
else
xvt_vobj_set_title(win(), captions.get(0));
}
void TMask::post_error_message(const char* msg, int sev)
{
CHECK(sev > 0 && msg, "Bad error message posted");
if (_error_severity > 0) // C'e' gia' un messaggio d'errore in coda
on_idle();
_error_message = msg;
_error_severity = sev;
}
// @doc INTERNAL
// @mfunc costruttore di copia
TTimed_box::TTimed_box(const char * header,const char * message,int seconds,short button_id,int x,int y)
: TMask(header,1,x,y)
{
// costruisce una maschera run time
add_memo(FIRST_FIELD, 0, "", 1, 0,-1,-3);
set(FIRST_FIELD, message);
// setta il timer per l'evento
_timer_delay=seconds * 1000 + 1;
_timer_id=XVT_TIMER_ERROR;
_button_id=button_id;
}
void TTimed_box::start_run()
{
if (_timer_id!=XVT_TIMER_ERROR)
xvt_timer_destroy(_timer_id);
_timer_id=xvt_timer_create(win(),_timer_delay);
TMask::start_run();
}
void TTimed_box::handler(WINDOW win, EVENT* ep)
{
if (ep->type == E_TIMER && ep->v.timer.id==_timer_id)
send_key(K_SPACE, _button_id);
TMask::handler(win, ep);
}
TTimed_box::~TTimed_box()
{
if (_timer_id != XVT_TIMER_ERROR)
xvt_timer_destroy(_timer_id);
}
TTimed_breakbox::TTimed_breakbox(const char * message,int seconds,int x,int y)
: TTimed_box(TR("Richiesta di interruzione"),message,seconds,DLG_OK,x,y)
{
add_button(DLG_CANCEL, 0, TR("Interrompi"), -22, -1, 12, 2,"",0);
add_button(DLG_OK, 0, TR("Riprova"), -12, -1, 12, 2,"",0);
}
TTimed_breakbox::~TTimed_breakbox()
{}
// @doc INTERNAL
// @mfunc costruttore di copia
TYesnoallnone_box::TYesnoallnone_box(const char * message, int default_key)
: TMask(TR("Richiesta"),1,40,8)
{
// costruisce una maschera run time
add_memo(FIRST_FIELD, 0, "", 1, 0,-1,-3);
set(FIRST_FIELD, message);
disable(FIRST_FIELD);
add_button(DLG_OK, 0, TR("Tutti"), -14, -1, 8, 2,"",0);
add_button(FIRST_FIELD+1, 0, TR("Si"), -24, -1, 8, 2,"",0).set_exit_key(K_YES);
add_button(FIRST_FIELD+2, 0, TR("No"), -34, -1, 8, 2,"",0).set_exit_key(K_NO);
add_button(DLG_CANCEL, 0, TR("Nessuno"), -44, -1, 8, 2,"",0);
switch (default_key)
{
case K_ENTER:
first_focus(DLG_OK); break;
case K_ESC:
first_focus(DLG_CANCEL); break;
case K_NO:
first_focus(FIRST_FIELD+2); break;
default:
first_focus(FIRST_FIELD+1);
}
}
TYesnoallnone_box::~TYesnoallnone_box()
{}