campo-sirio/include/maskfld.cpp
guy c09ac8f7a7 mask.h Tolto membro int _sheets che teneva il conto degli
spreadsheets contenuti in una maschera che richiedeva di
             essere aggiornato da tutte le maschere derivate
mask.cpp     Modificato metodo sheets() che conta gli sheet presenti
             semplificando la vita alle maschere derivate
             Gestione menu di modifica
msksheet.cpp Adeguato uso del metodo TMask::sheets()
varmask.h    Modificata indentazione
varmask.cpp  Adeguato uso del metodo TMask::sheets()
             Tolta stringa statica var_mask_str
maskfld.*    Tolti metodi obsoleti on_clipboard


git-svn-id: svn://10.65.10.50/trunk@6042 c028cbd2-c16b-5b4b-a496-9718f37d4682
1998-01-28 08:45:59 +00:00

4221 lines
94 KiB
C++
Executable File

#define STRICT
#define XVT_INCL_NATIVE
#include <xvt.h>
#include <applicat.h>
#include <colors.h>
#include <controls.h>
#include <defmask.h>
#include <execp.h>
#include <mailbox.h>
#include <mask.h>
#include <prefix.h>
#include <relation.h>
#include <sheet.h>
#include <tabutil.h>
#include <urldefid.h>
#include <utility.h>
#include <validate.h>
#include <xvtility.h>
#include <text.h>
// @doc INTERNAL
// @func HIDDEN void | smart_trim | Elimina gli spazi iniziali e/o finali da un stringa
HIDDEN void smart_trim(
TString & s, // @parm Stringa
byte mode // @parm operazione da effettuare ( 0 = nessuna operazione
// 1 = trimma a sinistra
// 2 = trimma a destra
// 3 = trimma da entrambi i lati
)
{
switch (mode)
{
case 1: s.ltrim(); break;
case 2: s.rtrim(); break;
case 3: s.trim(); break;
default: break;
}
}
///////////////////////////////////////////////////////////
// Field Flags
///////////////////////////////////////////////////////////
// Certified 100%
TMask_field::TField_Flags::TField_Flags()
{
automagic = persistent = FALSE;
enabled = enable_default = TRUE;
shown = show_default = TRUE;
uppercase = rightjust = FALSE;
zerofilled = button = FALSE;
dirty = focusdirty = FALSE;
roman = exchange = FALSE;
firm = ghost = FALSE;
password = FALSE;
trim = 3;
pipeallowed = FALSE;
}
// Certified 100%
char TMask_field::TField_Flags::update(const char* f)
{
for (const char* s = f; *s; s++)
switch(*s)
{
case '#':
trim = 2; break;
case '@':
trim = 1; break;
case ' ':
case '_':
trim = 0; break;
case '*':
password = TRUE; break;
case 'A':
automagic = persistent = TRUE; break;
case 'B':
button = TRUE; break;
case 'D':
enable_default = enabled = FALSE; break;
case 'F':
firm = persistent = TRUE; break;
case 'G':
ghost = TRUE; break;
case 'H':
show_default = shown = FALSE; break;
case 'I':
break; // reserved for sheetfield insert
case 'M':
roman = TRUE; break;
case 'P':
persistent = TRUE; break;
case 'R':
rightjust = TRUE; break;
case 'U':
uppercase = TRUE; break;
case 'V':
exchange = TRUE; break;
case 'Z':
zerofilled = TRUE; break;
default :
break;
}
return *s;
}
///////////////////////////////////////////////////////////
// TMask_field
///////////////////////////////////////////////////////////
TMask_field::TControl_data TMask_field::_ctl_data;
void TMask_field::TControl_data::reset()
{
_dlg = -1;
_x = _y = -1;
_width = 0;
_height = 1;
_size = 0;
_decimals = 0;
_bmp_up = _bmp_dn = 0;
_prompt.cut(0);
_flags.cut(0);
_park.spaces(256);
_park.cut(0);
}
TMask_field::TMask_field(TMask* m)
: _mask(m), _ctl(NULL), _groups(NULL)
{
}
// Certified 100%
TMask_field::~TMask_field()
{
if (_ctl) delete _ctl;
if (_groups) delete _groups;
}
// Certified 100%
const char* TMask_field::class_name() const
{ return "Field"; }
// Certified 100%
word TMask_field::class_id() const
{ return CLASS_FIELD; }
// Certified 100%
bool TMask_field::is_kind_of(word cid) const
{ return cid == CLASS_FIELD || TObject::is_kind_of(cid); }
// Certified 100%
bool TMask_field::ok() const
{ return _ctl != NULL; }
// Certified 100%
void TMask_field::parse_head(TScanner&)
{}
short TMask_field::dlg() const
{
return _ctl ? _ctl->id() : _ctl_data._dlg;
}
void TMask_field::highlight() const
{
#ifdef DBG
yesnofatal_box("Can't set the focus to non-operable field %d", dlg());
#endif
}
void TMask_field::set_focus() const
{
#ifdef DBG
yesnofatal_box("Can't set the focus to non-operable field %d", dlg());
#endif
}
// @doc INTERNAL
// Certified 100%
// @mfunc Converte una stringa in un identificatore di campo.
short TMask_field::atodlg(
const char* s) const // @parm stringa da convertire in numero
// @comm In modo DBG controlla anche che sia un numero valido
{
short d = s ? atoi(s) : 0;
#ifdef DBG
if (d == 0 || d < -1 || d > 1000)
{
yesnofatal_box("Identificatore non valido nel campo %d: '%s'", _ctl_data._dlg, s);
d = DLG_NULL;
}
#endif
return d;
}
// @doc EXTERNAL
// @mfunc Costruisce il campo
void TMask_field::construct(
short id, // @parm Identificatore del campo
const char* prompt, // @parm Prompt del campo
int x, // @parm Posizione in x (in caratteri) del campo nella maschera
int y, // @parm Posizione in y (in caratteri) del campo nella maschera
int len, // @parm Lunghezza del buffer campo
WINDOW parent, // @parm Finestra padre alla quale assegnare il campo
const char* flags, // @parm Flags del campo (default "")
int width) // @parm Lunghezza a video del campo
// @parm TScanner& | scanner | File dal quale leggere leggere le informazioni
// @syntax void construct(TScanner& scanner, WINDOW parent);
// @syntax void construct(short id, const char* prompt, int x, int y, int len, WINDOW parent, const char* flags, int width);
//
// @comm E' possibile costruire il campo leggendo direttamente dal file, oppure passare alla funzione
// tutti i parametri necessari alla definizione del campo stesso
{
_ctl_data.reset();
_ctl_data._x = x;
_ctl_data._y = y;
_ctl_data._prompt = prompt;
_ctl_data._size = len;
switch(class_id())
{
case CLASS_REAL_FIELD:
((TReal_field*)this)->set_decimals(width);
_ctl_data._width = len;
break;
case CLASS_BUTTON_FIELD:
_ctl_data._height = len;
_ctl_data._width = width <= 0 ? 12 : width;
break;
case CLASS_MEMO_FIELD:
_ctl_data._height = len;
_ctl_data._width = width;
_ctl_data._size = len * width;
break;
default:
_ctl_data._width = width == 0 ? len : width;
break;
}
_ctl_data._dlg = id;
_ctl_data._flags = flags;
_flags.update(flags);
create(parent);
}
void TMask_field::construct(TScanner& scanner, WINDOW parent)
{
_ctl_data.reset();
_ctl_data._dlg = atodlg(scanner.pop());
parse_head(scanner);
scanner.popkey(); // BEGIN
#ifdef DBG
if (scanner.key() != "BE")
{
NFCHECK("Testata errata o BEGIN mancante nel campo %d", _ctl_data._dlg);
scanner.push();
}
if (_ctl_data._dlg > 0)
{
const TMask& m = mask();
for (int f = m.fields()-1; f >= 0; f--)
{
const TMask_field& mf = m.fld(f);
if (mf.dlg() == _ctl_data._dlg && mf.parent() == parent)
NFCHECK("Esistono due campi con identificatore %d", _ctl_data._dlg);
}
}
#endif
while(scanner.popkey() != "EN") // END of control
parse_item(scanner);
create(parent);
}
void TMask_field::set_group(byte group)
{
if (_groups == NULL)
_groups = new TBit_array;
_groups->set(long(group));
_groups->set(0L);
}
bool TMask_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "PR") // PROMPT
{
_ctl_data._x = scanner.integer();
_ctl_data._y = scanner.integer();
_ctl_data._prompt = scanner.string();
return TRUE;
}
if (scanner.key() == "FL") // FLAGS
{
const char* f = scanner.string();
if (_flags.update(f) == '\0')
_ctl_data._flags << f;
return TRUE;
}
if (scanner.key() == "GR")
{
if (_groups == NULL)
_groups = new TBit_array;
_groups->set(scanner.line());
return TRUE;
}
NFCHECK("'%s' Token non riconosciuto nel campo %d: %s",
(const char*)scanner.token(), (int)dlg(), (const char*)_ctl_data._prompt);
return FALSE;
}
// Certified 100%
WINDOW TMask_field::parent() const
{
CHECK(_ctl, "Can't get the parent of a NULL control");
return _ctl->parent();
}
RCT& TMask_field::get_rect(RCT& r) const
{
if (_ctl) _ctl->get_rect(r);
else memset(&r, 0, sizeof(r));
return r;
}
void TMask_field::set_rect(const RCT& r)
{
if (_ctl) _ctl->set_rect(r);
}
// Certified 100%
// @doc EXTERNAL
// @mfunc Abilita/disabilita il campo (lo rende scrivibile)
void TMask_field::enable(
bool on) // @parm Operazione da svolgere:
//
// @flag TRUE | Abilita il campo (default)
// @flag FALSE | Disabilita il campo
{
_flags.enabled = on;
}
// Certified 100%
void TMask_field::enable_default()
{
const bool ed = _flags.enable_default;
enable(ed);
}
// Certified 100%
// @doc EXTERNAL
// @mfunc Permette di rendere visibile/invisibile un campo
void TMask_field::show(
bool on) // @parm Operazione da svolgere:
//
// @flag TRUE | Rendere visibile il campo (default)
// @flag FALSE | Rendere invisibile il campo
{
if (_ctl)
{
_ctl->show(on);
_flags.shown = on;
}
}
// Certified 100%
void TMask_field::show_default()
{
const bool sd = _flags.show_default;
show(sd);
}
// Certified 100%
bool TMask_field::active() const
{
return is_operable() && enabled() && shown();
}
void TMask_field::set_dirty(bool d)
{
if (_flags.dirty == 3)
{
if (d == FALSE) // Non permette di annullare il dirty dei campi errati
return;
}
#ifdef DBG
if (d == 3)
_flags.dirty = d; // Riga per breakpoint
#endif
_flags.dirty = d;
set_focusdirty(d);
}
// Certified 100%
const char* TMask_field::prompt() const
{
return _ctl ? _ctl->caption() : "";
}
// Certified 100%
void TMask_field::reset()
{
if (!_flags.persistent)
set("");
}
// Certified 100%
void TMask_field::set_prompt(const char* p)
{
if (_ctl) _ctl->set_caption(p);
}
void TMask_field::set(const char*)
{
}
void TMask_field::set(long n)
{
char s[16]; sprintf(s, "%ld", n);
set(s);
}
const TString& TMask_field::get() const
{
return _ctl_data._park.cut(0);
}
// @doc EXTERNAL
// @mfunc Verifica se il campo deve essere sottoposto a check
//
// @rdesc Ritorna il risultato:
//
// @flag TRUE | Se il campo e' da sottoporre a check
// @flag FALSE | Se il campo non e' da sottoporre check
bool TMask_field::to_check(
KEY k, // @parm Tasto da passare al campo come simulazione di inizio controllo
bool checkrun) const // @parm Permette di ritornare TRUE se la maschera e' in start_run() mode
{
bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty());
if (!yes && checkrun)
yes = k == K_TAB && !mask().is_running();
return yes;
}
void TMask_field::send_key(KEY k, short to)
{
_mask->send_key(k, to, this);
}
void TMask_field::check_type(CheckType)
{ CHECK(0, "Can't set check type to non-edit field"); }
void TMask_field::set_handler(CONTROL_HANDLER)
{ CHECK(0, "Can't set the handler to a TMask_field"); }
bool TMask_field::on_hit()
{
CHECK(0, "Can't hit non-operable field");
return FALSE;
}
// Certified 100%
bool TMask_field::on_key(KEY key)
{
#ifdef DBG
if (key > (K_CTRL+K_SPACE))
return error_box("Tasto ignorato %d", key);
#endif
return TRUE;
}
#define build_msg() char* _msg = (char*)(const char*)_ctl_data._park;va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr)
// @doc EXTERNAL
// @mfunc Crea una error-box relativo al campo (chiama <f error_box>)
//
// @rdesc Ritorna sempre FALSE
bool TMask_field::error_box(
const char* fmt, // @parm Formato della stringa da scrivere
...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti
// viene creata una finestra di errore normale.
{
build_msg();
if (mask().is_sheetmask() && !mask().is_running())
{
xvt_statbar_set(_msg);
beep();
}
else
{
mask().post_error_message(_msg, 3);
}
return FALSE;
}
bool TMask_field::message_box(const char* fmt, ...) const
{
build_msg();
mask().post_error_message(_msg, 1);
return FALSE;
}
// @doc EXTERNAL
// @mfunc Crea una warning-box relativo al campo (chiama <f warning_box>)
//
// @rdesc Ritorna sempre FALSE
bool TMask_field::warning_box(
const char* fmt, // @parm Formato della stringa da scrivere
...) const // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
// @comm Se il campo e' uno sheet viene aggiornata la barra di stato, altrimenti
// viene creata una finestra di warning normale.
{
build_msg();
if (mask().is_sheetmask() && !mask().is_running())
{
xvt_statbar_set(_msg);
beep();
}
else
{
mask().post_error_message(_msg, 2);
}
return FALSE;
}
bool TMask_field::yesno_box(const char* fmt, ...) const
{
set_focus();
build_msg();
const bool yes = ::yesno_box("%s", _msg);
set_focus();
return yes;
}
KEY TMask_field::yesnocancel_box(const char* fmt, ...) const
{
set_focus();
build_msg();
const KEY k = ::yesnocancel_box("%s", _msg);
set_focus();
return k;
}
///////////////////////////////////////////////////////////
// TText_field
///////////////////////////////////////////////////////////
// Certified 100%
word TText_field::class_id() const
{ return CLASS_TEXT_FIELD; }
// Certified 100%
bool TText_field::is_kind_of(word cid) const
{ return cid == CLASS_TEXT_FIELD || TMask_field::is_kind_of(cid); }
// Certified 100%
void TText_field::create(WINDOW parent)
{
_ctl = new TText_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y,
0, 1,
_ctl_data._flags, _ctl_data._prompt);
}
///////////////////////////////////////////////////////////
// TGroup_field
///////////////////////////////////////////////////////////
TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask)
{
_flags.persistent = TRUE;
}
// _size means _heigth
void TGroup_field::parse_head(TScanner& scanner)
{
_ctl_data._width = scanner.integer();
_ctl_data._size = scanner.integer();
}
void TGroup_field::create(WINDOW parent)
{
_ctl = new TGroupbox_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y,
_ctl_data._width, _ctl_data._size,
_ctl_data._flags, _ctl_data._prompt);
}
///////////////////////////////////////////////////////////
// TOperable_field
///////////////////////////////////////////////////////////
TOperable_field::TOperable_field(TMask* m)
: TMask_field(m), _handler(NULL), _message(NULL)
{ }
TOperable_field::~TOperable_field()
{
if (_message) delete _message;
}
TToken_string* TOperable_field::message(int m, bool crea)
{
TToken_string* msg = _message ? _message->rowptr(m) : NULL;
if (msg == NULL && crea)
{
if (_message == NULL)
_message = new TString_array(2);
msg = new TToken_string(16);
_message->add(msg, m);
}
return msg;
}
bool TOperable_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "HE") // HELP
{
scanner.string(); // Ignored from this version
return TRUE;
}
if (scanner.key() == "ME")
{
const TString& m = scanner.line().strip_spaces();
message(0, TRUE)->add(m);
return TRUE;
}
return TMask_field::parse_item(scanner);
}
void TOperable_field::set_focus() const
{
mask().set_focus_field(dlg());
}
// Certified 100%
bool TOperable_field::is_kind_of(word cid) const
{ return cid == CLASS_OPERABLE_FIELD || TMask_field::is_kind_of(cid); }
void TOperable_field::enable(bool on)
{
TMask_field::enable(on);
if (_ctl) _ctl->enable(on);
}
bool TOperable_field::on_key(
KEY key) // @parm Tasto notificato
{
switch(key)
{
case K_F11:
{
TString msg(80);
msg << "Identificatore: " << dlg() << '\n'
<< "Maschera: " << mask().source_file() << '\n';
if (field() != NULL)
msg << "Campo: " << *field();
message_box(msg);
}
break;
case K_CTRL + K_TAB:
mask().notify_focus_field(dlg());
return handler(key);
default:
return handler(key);
}
return TMask_field::on_key(key);
}
// Certified 50%
HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg)
{
#ifdef DBG
if (f.class_id() != CLASS_LIST_FIELD)
{
yesnofatal_box("Can't add/delete items of non list-box field %d", f.dlg());
return;
}
#endif
TList_field& l = (TList_field&)f;
TToken_string item(16);
item = msg.get();
if (add) item.add(msg.get());
item.strip("\"'");
if (add)
l.add_item(item);
else
l.delete_item(item);
}
// Certified 99%
HIDDEN const char* copy_value(TToken_string& msg, const TString& val)
{
int from = msg.get_int()-1;
int to = -1;
if (from < 0) from = 0;
else to = msg.get_int();
return val.sub(from, to);
}
HIDDEN void run_app(TMask& mask, TToken_string& msg)
{
TFilename a;
for (const char* m = msg.get(1); m; m = msg.get())
{
if (a.not_empty())
a << ' ';
for (const char* f = m; *f; f++)
{
if (*f == '#')
{
const int id = atoi(++f);
a << mask.get(id);
break;
}
else
a << *f;
}
}
TExternal_app app(a);
app.run();
mask.set_focus();
}
// Certified 90%
bool TOperable_field::do_message(int num)
{
const int MAX_CMD = 18;
static const char* commands[MAX_CMD] =
{
"ADD", // 0
"CHECK", // 1
"CLEAR", // 2
"CO", // 3
"DEL", // 4
"DIRTY", // 5
"DISABLE", // 6
"ENABLE", // 7
"ENABLEDEF", // 8
"EXIT", // 9
"HIDE", // 10
"NORMAL", // 11
"PUSH", // 12
"REQUIRED", // 13
"RESET", // 14
"RU", // 15
"SHOW", // 16
"TAB", // 17
};
TToken_string* mess = message(num);
if (mess == NULL || mess->empty())
return FALSE;
TToken_string msg(16, ',');
TString256 value;
for (const char* m = mess->get(0); m && *m; m = mess->get())
{
KEY key = 0;
msg = m;
value = msg.get();
const char* dlg = msg.get();
int cmd = -1;
if (isalpha(value[0])) // binary search
{
int f = 0, l = MAX_CMD-1;
while (TRUE)
{
cmd = (f+l)>>1;
const int cmp = strcmp(value, commands[cmd]);
if (cmp == 0) break;
if (cmp > 0) f = cmd+1;
else l = cmd-1;
if (f > l)
{
cmd = -1;
break;
}
}
}
if (cmd == 9)
{
mask().stop_run(atoi(dlg));
continue;
} else
if (cmd == 15)
{
run_app(mask(), msg);
continue;
}
short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0;
const bool broadcast = dlg && strchr(dlg, '@');
if (broadcast) fld = -fld;
if (value[0] == '"')
value = value.strip("\"'");
else switch (cmd)
{
case 0:
modify_list(TRUE, mask().field(fld), msg);
continue;
case 1:
mask().field(fld).set_dirty();
mask().field(fld).on_key(K_TAB);
continue;
case 2:
mask().disable(fld);
mask().reset(fld);
continue;
case 3:
value = copy_value(msg, get()); break;
case 4:
modify_list(FALSE, mask().field(fld), msg); continue;
case 5:
mask().field(fld).set_dirty(); continue;
case 6:
mask().disable(fld); continue;
case 7:
mask().enable(fld); continue;
case 8:
mask().enable_default(fld); continue;
case 10:
mask().hide(fld); continue;
case 11:
mask().field(fld).check_type(CHECK_NORMAL); continue;
case 12:
mask().field(fld).on_hit(); continue;
case 13:
mask().field(fld).check_type(CHECK_REQUIRED); continue;
case 14:
key = K_F2; break;
case 16:
mask().show(fld); continue;
case 17:
mask().field(fld).on_key(K_TAB); continue;
default:
key = atoi(value);
break;
}
if (key)
{
if (key > 0)
send_key(key, fld);
}
else
{
// Setta a value il campo fld solo se ha un valore diverso da value
if (broadcast)
{
const int max = mask().fields();
for (int i = 0; i < max; i++)
{
TMask_field& f = mask().fld(i);
if (f.in_group((int)-fld))
{
const TString& prev = f.get();
if (value != prev)
{
f.set(value);
if (f.shown() || f.ghost())
f.on_hit();
}
}
}
}
else
{
TMask_field& f = mask().field(fld);
const char* prev = f.get();
if (value != prev)
{
f.set(value);
if (f.shown() || f.ghost())
f.on_hit();
}
}
}
}
return TRUE;
}
void TOperable_field::highlight() const
{
if (_ctl) _ctl->set_focus();
}
bool TOperable_field::handler(KEY k)
{
bool ok;
if (_handler)
ok = _handler(*this, k);
else
ok = TRUE;
return ok;
}
// Certified 90%
bool TOperable_field::on_hit()
{
const bool ok = handler(K_SPACE);
if (ok && has_message())
do_message(0);
return ok;
}
///////////////////////////////////////////////////////////
// Button_field
///////////////////////////////////////////////////////////
TButton_field::TButton_field(TMask* m)
: TOperable_field(m)
{
}
word TButton_field::class_id() const
{ return CLASS_BUTTON_FIELD; }
bool TButton_field::is_kind_of(word cid) const
{ return cid == CLASS_BUTTON_FIELD || TOperable_field::is_kind_of(cid); }
void TButton_field::parse_head(TScanner& scanner)
{
_ctl_data._width = scanner.integer();
if (_ctl_data._width <= 0) _ctl_data._width = 10;
_ctl_data._height = scanner.integer(); // Height
if (_ctl_data._height <= 0) _ctl_data._height = 1;
}
bool TButton_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "PI")
{
const short bmp = (short)scanner.integer();
if (_ctl_data._bmp_up == 0)
_ctl_data._bmp_up = bmp;
else
_ctl_data._bmp_dn = bmp;
return bmp > 0;
}
return TOperable_field::parse_item(scanner);
}
void TButton_field::create(WINDOW parent)
{
_exit_key = 0;
_virtual_key = 0;
switch (dlg())
{
case DLG_OK:
if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Conferma")
_ctl_data._prompt = "~Conferma";
_virtual_key = 'C';
_exit_key = K_ENTER;
if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == "~Conferma")
_ctl_data._bmp_up = BMP_OK;
break;
case DLG_CANCEL:
if (_ctl_data._prompt.empty())
_ctl_data._prompt = "Annulla";
_virtual_key = _exit_key = K_ESC;
if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == "Annulla")
_ctl_data._bmp_up = BMP_CANCEL;
break;
case DLG_DELREC:
if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Elimina")
_ctl_data._prompt = "~Elimina";
_virtual_key = 'E';
_exit_key = K_DEL;
if (_ctl_data._bmp_up == 0 && _ctl_data._prompt == "~Elimina")
{
_ctl_data._bmp_up = BMP_DELREC;
_ctl_data._bmp_dn = BMP_DELRECDN;
}
break;
case DLG_PRINT:
if (_ctl_data._prompt.empty() || _ctl_data._prompt == "Stampa")
_ctl_data._prompt = "~Stampa";
_virtual_key = 'S';
_exit_key = K_ENTER;
if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == "~Stampa")
_ctl_data._bmp_up = BMP_PRINT;
break;
case DLG_QUIT:
if (_ctl_data._prompt.empty())
_ctl_data._prompt = "Fine";
_virtual_key = K_F4;
_exit_key = K_QUIT;
if (_ctl_data._bmp_up <= 0 && _ctl_data._prompt == "Fine")
{
_ctl_data._bmp_up = BMP_QUIT;
_ctl_data._bmp_dn = BMP_QUITDN;
}
break;
case DLG_SELECT:
if (_ctl_data._bmp_up <= 0)
_ctl_data._bmp_up = BMP_SELECT;
_exit_key = K_ENTER;
break;
default:
break;
}
TToken_string* mess = message(0);
if (mess)
{
TToken_string msg(mess->get(0), ',');
const TString m(msg.get(0));
if (m == "EXIT")
_exit_key = msg.get_int();
else
if (msg.get_int() == 0) _exit_key = atoi(m);
}
if (_virtual_key == 0)
{
const int n = _ctl_data._prompt.find('~');
_virtual_key = (n >= 0) ? toupper(_ctl_data._prompt[n+1]) : _exit_key;
}
_ctl = new TPushbutton_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y,
_ctl_data._width+2, _ctl_data._height,
_ctl_data._flags, _ctl_data._prompt,
_ctl_data._bmp_up, _ctl_data._bmp_dn);
}
bool TButton_field::on_key(KEY key)
{
bool ok = TRUE;
if (key == K_SPACE)
{
if (dlg() != DLG_CANCEL && dlg() != DLG_QUIT)
{
const TMask& m = mask();
if (parent() == m.toolwin())
ok = m.focus_field().on_key(K_TAB);
}
if (ok)
{
ok = on_hit();
if (ok && _exit_key > 0 && !has_message())
mask().stop_run(_exit_key);
}
}
else
ok = TOperable_field::on_key(key);
return ok;
}
void TButton_field::set_bmp(short up, short dn)
{
((TPushbutton_control*)_ctl)->set_bmp(up, dn);
}
void TButton_field::set_icon(word icon)
{
((TPushbutton_control*)_ctl)->set_icon(icon);
}
///////////////////////////////////////////////////////////
// TEditable_field
///////////////////////////////////////////////////////////
TEditable_field::TEditable_field(TMask* m)
: TLoadable_field(m), _prompt(NULL), _field(NULL), _keys(NULL),
_validate(NULL), _warning(NULL)
{ }
TEditable_field::~TEditable_field()
{
if (_prompt) delete _prompt;
if (_field) delete _field;
if (_keys) delete _keys;
if (_validate) delete _validate;
if (_warning) delete _warning;
}
void TEditable_field::set_warning(const char* w)
{
if (_warning)
*_warning = w;
else
_warning = new TString(w);
if (_warning->empty())
{
delete _warning;
_warning = NULL;
}
}
// Certified 100%
const char* TEditable_field::prompt() const
{
return _prompt ? _prompt->caption() : "";
}
// Ritorna il messaggio d'errore associato al campo
const char* TEditable_field::get_warning() const
{ return _warning ? (const char*)*_warning : ""; }
bool TEditable_field::parse_item(TScanner& scanner)
{
const TString& k = scanner.key();
if (k == "FI") // FIELD
{
set_field(scanner.line());
return TRUE;
}
if (k == "KE") // KEY
{
if (_keys == NULL)
_keys = new TBit_array;
_keys->set(scanner.line());
_keys->set(0L);
return TRUE;
}
if (k == "CU") // CUSTOM DATA
{
if (_userdata == NULL)
_userdata = new TToken_string(scanner.string());
else
_userdata->add(scanner.string());
return TRUE;
}
if (scanner.key() == "VA")
{
#ifdef DBG
if (_validate)
return yesnofatal_box("VALIDATE duplicata nel campo %d", _ctl_data._dlg);
#endif
_validate = new TValidation_data;
const char* n = scanner.pop();
_validate->_func = isdigit(*n) ? atoi(n) : -1;
#ifdef DBG
if (_validate->_func < 0)
return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d",
n, _ctl_data._dlg);
#endif
const int nparms = scanner.integer();
#ifdef DBG
if (nparms < 0 || nparms > 100)
return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d: %d",
_ctl_data._dlg, nparms);
#endif
for (int i = 0; i < nparms; i++)
_validate->_parms.add(scanner.operand());
return TRUE;
}
if (scanner.key() == "WA")
{
set_warning(scanner.string());
return TRUE;
}
return TOperable_field::parse_item(scanner);
}
void TEditable_field::set_key(byte key)
{
if (_keys == NULL)
_keys = new TBit_array;
_keys->set(long(key));
_keys->set(0L);
}
// Certified 90%
word TEditable_field::last_key() const
{
long u = _keys ? _keys->last_one() : 0;
if (u < 0) u = 0;
return (word)u;
}
// Certified 70%
word TEditable_field::first_key() const
{
if (_keys == NULL)
return 0;
const int last = last_key();
for (int i = 1; i <= last; i++)
if (in_key(i) == TRUE)
break;
return (word)i;
}
// Certified 70%
bool TEditable_field::has_a_common_key(const TMask_field & f) const
{
const int last = last_key();
for (int i = 1; i <= last; i++)
if (in_key(i) && f.in_key(i))
return TRUE;
return FALSE;
}
bool TEditable_field::test_key_complete(bool normal) const
{
TMask& m = mask();
for (int k = 1; k <= MAX_KEYS; k++)
{
if (in_key(k) && m.key_valid(k))
{
bool complete = TRUE;
for (TEditable_field* e = m.get_key_field(k, TRUE); e; e = m.get_key_field(k, FALSE))
{
e->set_focusdirty(FALSE);
if (e->is_edit())
complete &= e->required();
}
if (normal && !complete)
m.set_test_field(dlg());
else
m.stop_run(K_AUTO_ENTER);
return TRUE;
}
}
return FALSE;
}
// Certified 90%
void TEditable_field::reset_key(byte key)
{
if (_keys)
{
_keys->reset(long(key));
if (key == 0 || last_key() == 0)
{
delete _keys; // Se non ci sono piu' chiavi azzera tutto
_keys = NULL;
}
}
}
// @doc EXTERNAL
// @mfunc Chiama l' eventuale funzione di validazione
//
// @rdesc Ritorna il risultato dell funzione di validazione:
//
// @flag TRUE | Se la validata ha avuto successo
// @flag FALSE | Se la validata no ha avuto successo
bool TEditable_field::validate(
KEY k) // @parm Tasto da passare alla funzione di validazione
{
bool ok = TRUE;
if (_validate)
ok = ::validate(_validate->_func, *this, k, _validate->_parms);
return ok;
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Crea il prompt del controllo
//
// @rdesc Ritorna la lunghezza del prompt creato
word TEditable_field::create_prompt(
WINDOW parent, // @parm Finestra padre alla quale assegnare il prompt del controllo
word width, // @parm Larghezza del controllo
word height) // @parm Altezza del controllo
{
if (_ctl_data._prompt.not_empty())
{
TString flags;
if (hidden()) flags << 'H';
if (height < 3)
{
width = _ctl_data._prompt.len();
for (word i = 0; i < width && _ctl_data._prompt[(int)i] == '@'; i += 2);
width -= i;
_prompt = new TText_control(parent, -1, _ctl_data._x, _ctl_data._y,
0, 1, flags, _ctl_data._prompt);
}
else
{
if (right_justified()) flags << 'R';
_prompt = new TGroupbox_control(parent, -1, _ctl_data._x, _ctl_data._y,
width, height, flags, _ctl_data._prompt);
}
}
return width;
}
void TEditable_field::show(bool on)
{
TOperable_field::show(on);
if (_prompt) _prompt->show(on);
}
void TEditable_field::set_prompt(const char* p)
{
CHECKD(_prompt, "Can't set prompt to control", dlg());
_prompt->set_caption(p);
}
// Certified 90%
void TEditable_field::set_field(const TString& fr)
{
if (_field != NULL)
{
if (fr.empty())
{
delete _field;
_field = NULL;
}
else
*_field = fr;
}
else
_field = new TFieldref(fr, 0);
}
// Certified 100%
// Legge il valore attuale del campo in formato RAW
const TString& TEditable_field::get() const
{
return _str;
}
// Certified 100%
// Aggiusta un valore letto da file in formato RAW
const char* TEditable_field::reformat(const char* data) const
{
return data;
}
// Certified 100%
// Setta il valore RAW e WIN del campo con un valore RAW
void TEditable_field::set(const char* data)
{
_str = reformat(data);
const TString& val = raw2win(_str);
set_window_data(val);
const TMask& m = mask();
if (m.is_running() || m.is_sheetmask())
set_dirty();
}
// Certified 100%
// Converte da formato RAW a formato WIN
const char* TEditable_field::raw2win(const char* data) const
{
return reformat(data);
}
// Certified 100%
// Converte da formato WIN a formato RAW
const char* TEditable_field::win2raw(const char* data) const
{
return reformat(data);
}
bool TEditable_field::autosave(TRelation& r)
{
if (_field)
_field->write(get(), r);
return _field != NULL;
}
bool TEditable_field::autoload(const TRelation& r)
{
if (_field)
set(_field->read(r));
return _field != NULL;
}
///////////////////////////////////////////////////////////
// Boolean_field
///////////////////////////////////////////////////////////
TBoolean_field::TBoolean_field(TMask* m)
: TEditable_field(m)
{}
word TBoolean_field::class_id() const
{ return CLASS_BOOLEAN_FIELD; }
void TBoolean_field::create(WINDOW parent)
{
_ctl = new TCheckbox_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y, 0,
_ctl_data._flags, _ctl_data._prompt);
}
void TBoolean_field::set_prompt(const char* p)
{
_ctl->set_caption(p);
}
const char* TBoolean_field::reformat(const char* data) const
{
return (data && *data > ' ' && *data != '0' && *data != 'N') ? "X" : "";
}
void TBoolean_field::set_window_data(const char* data)
{
if (_ctl)
((TCheckbox_control*)_ctl)->check(*data > ' ');
}
TString& TBoolean_field::get_window_data()
{
const bool on = _ctl ? ((TCheckbox_control*)_ctl)->checked() : FALSE;
_str = on ? "X" : "";
return _str;
}
bool TBoolean_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "ME")
{
const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE
TToken_string* ts = message(tf, TRUE);
ts->add(scanner.line().strip_spaces());
return TRUE;
}
return TEditable_field::parse_item(scanner);
}
bool TBoolean_field::on_hit()
{
const bool ok = handler(K_SPACE);
if (ok)
{
const bool on = get() == "X";
do_message(on);
}
return ok;
}
bool TBoolean_field::on_key(KEY key)
{
switch (key)
{
case K_SPACE:
get_window_data();
set_dirty();
on_hit();
return TRUE;
break;
case K_F2:
set("");
set_dirty();
return TRUE;
break;
default:
return TEditable_field::on_key(key);
}
return FALSE;
}
///////////////////////////////////////////////////////////
// TBrowse_button
///////////////////////////////////////////////////////////
TBrowse_button::TBrowse_button(TEdit_field* f)
: _fld(f)
{ }
TBrowse_button::~TBrowse_button()
{
}
// Certified 100%
TEditable_field& TBrowse_button::field(short id) const
{
if (id > 0)
{
TMask_field& f = _fld->mask().field(id);
CHECKD(f.is_editable(), "Can't use in a browse the field ", id);
return (TEditable_field&)f;
}
return *_fld;
}
///////////////////////////////////////////////////////////
// TList_sheet
///////////////////////////////////////////////////////////
// Certified 100%
TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
: TBrowse_button(f), _row(-1), _caption(caption), _head(head)
{ }
// Certified 100%
TList_sheet::~TList_sheet()
{ }
// Certified 100%
void TList_sheet::parse_input(TScanner& scanner)
{
_inp_id.add(scanner.pop());
}
// Certified 100%
void TList_sheet::parse_item(TScanner& scanner)
{
_data.add(new TToken_string(scanner.string()));
}
// Certified 100%
void TList_sheet::parse_output(TScanner& scanner)
{
_out_id.add(scanner.pop());
}
// il numero di riga selezionata
int TList_sheet::do_input()
{
if (_inp_id.empty_items())
return -2; // List empty!
_inp_id.restart();
TToken_string rowsel(80);
for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
{
if (*fld == '"')
{
rowsel.add(fld+1);
if (rowsel.not_empty()) rowsel.cut(rowsel.len()-1);
}
else
{
const short id = field().atodlg(fld);
if (id > 0)
{
const TMask_field& f = field(id);
if (f.class_id() == CLASS_ZOOM_FIELD)
{
const TZoom_field& z = (TZoom_field&)f;
rowsel.add(z.get_first_line());
}
else
rowsel.add(f.get());
}
else rowsel.add("");
}
}
TString fd, it;
for (int i = 0 ; i < _data.items(); i++)
{
TToken_string& ts =_data.row(i);
ts.restart();
for ( const char* item = rowsel.get(0); item ; item = rowsel.get())
{
it = item; it.trim();
fd = ts.get(); fd.trim();
if (fd != it) break;
}
if (!item) return i;
}
return -1; // Value not found!
}
// Certified 50%
void TList_sheet::do_output(CheckTime t)
{
if (_row < 0 || t == FINAL_CHECK)
return;
_out_id.restart();
TToken_string& rowsel = _data.row(_row);
rowsel.restart();
for (const char* fld = _out_id.get(); fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(id);
const char* val = rowsel.get();
if (t != STARTING_CHECK || f.field() == NULL)
{
const bool hit = f.get() != val;
f.set(val);
if (field().dlg() != id && hit)
{
f.on_hit();
if (t == RUNNING_CHECK)
f.check();
}
}
}
}
// Certified 100%
KEY TList_sheet::run()
{
TArray_sheet sci(3, 3, -3, -3, _caption, _head);
sci.rows_array() = _data;
_row = do_input();
sci.select(_row);
const KEY k = sci.run();
switch (k)
{
case K_ENTER:
_row = (int)sci.selected();
do_output();
break;
default:
break;
}
return k;
}
// Certified 100%
bool TList_sheet::check(CheckTime t)
{
_row = do_input();
const bool passed = _row != -1;
if (passed) do_output(t);
return passed;
}
///////////////////////////////////////////////////////////
// TBrowse
///////////////////////////////////////////////////////////
// Certified 100%
TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter)
: TBrowse_button(f),
_relation(r), _cursor(new TCursor (r, "", key)),
_filter(filter), _secondary(FALSE)
{}
// Certified 100%
TBrowse::TBrowse(TEdit_field* f, TCursor* c)
: TBrowse_button(f),
_relation(NULL), _cursor(c), _secondary(FALSE)
{}
// Certified 100%
TBrowse::~TBrowse()
{
// Se e' stato usato il primo costruttore devo distruggere la relazione ed il cursore
if (_relation)
{
delete _cursor;
delete _relation;
}
}
// Certified 100%
void TBrowse::parse_display(TScanner& scanner)
{
const char* s;
s = scanner.string();
_head.add(s);
s = scanner.line();
_items.add(s);
}
void TBrowse::parse_input(TScanner& scanner)
{
const char* s = scanner.pop();
_inp_fn.add(s);
s = scanner.pop();
if (*s == '"') // Constant string
{
scanner.push();
TString& str = scanner.line();
_inp_id.add(str);
}
else // Field on the mask
{
CHECKS(_inp_id.get_pos(s) < 0, "Duplicate input field ", s);
_inp_id.add(s);
if (scanner.popkey() == "SE") _inp_id << '@'; // Special FILTERing field
else scanner.push();
}
}
void TBrowse::parse_output(TScanner& scanner)
{
const char* s = scanner.pop();
#ifdef DBG
field().atodlg(s);
#endif
_out_id.add(s);
s = scanner.pop();
_out_fn.add(s);
_secondary = FALSE;
}
bool TBrowse::parse_copy(const TString& what, const TBrowse& b)
{
const bool all = what == "AL";
if (all || what == "US")
{
set_insert(b.get_insert());
_filter = b.get_filter();
if (!field().has_warning() && b.field().has_warning())
field().set_warning(b.field().get_warning());
if (!all) return TRUE;
}
if (all || what == "IN")
{
_inp_id = b._inp_id;
_inp_fn = b._inp_fn;
if (!all) return TRUE;
}
if (all || what == "DI")
{
_head = b._head;
_items = b._items;
if (!all) return TRUE;
}
if (all || what == "OU")
{
_out_id = b._out_id;
_out_fn = b._out_fn;
_secondary = b.field().has_check();
}
return TRUE;
}
void TBrowse::parse_join(TScanner& scanner)
{
TString80 j(scanner.pop()); // File or table
CHECKS(_relation, "Can't join to NULL relation ", (const char*)j);
int to;
if (scanner.popkey() == "TO") // TO keyword
{
const char* t = scanner.pop();
to = name2log(t);
}
else
{
to = 0; // _relation->lfile()->num();
scanner.push();
}
int key = 1;
if (scanner.popkey() == "KE")
key = scanner.integer();
else scanner.push();
int alias = 0;
if (scanner.popkey() == "AL")
alias = scanner.integer();
else scanner.push();
TToken_string exp(80);
if (scanner.pop() == "INTO")
{
const char* r = scanner.pop();
while (strchr(r, '=') != NULL)
{
exp.add(r);
r = scanner.pop();
}
}
scanner.push();
#ifdef DBG
if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
#endif
if (isdigit(j[0]))
_relation->add(atoi(j), exp, key, to, alias); // join file
else
{
#ifdef DBG
if (j.len() > 4)
yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j);
else
#endif
_relation->add(j, exp, key, to, alias); // join table
}
}
void TBrowse::parse_insert(TScanner& scanner)
{
const TString& key = scanner.popkey();
_insert.cut(0);
if (key != "NO")
{
_insert << key[0] << scanner.line();
_insert.trim();
}
}
// Ritorna il numero di inputs senza contare quelli che funzionano solo da filtro
int TBrowse::input_fields()
{
int inp = 0;
for (const char* fld = _inp_id.get(0); fld; fld = _inp_id.get())
{
if (*fld != '"' && strchr(fld, '@') == NULL)
{
TMask_field& f = field(f.atodlg(fld));
if (f.active() && f.is_editable())
inp++;
}
}
return inp;
}
const char* TBrowse::get_input_fields() const
{
return _inp_id;
}
const char* TBrowse::get_input_field_names() const
{
return _inp_fn;
}
const char* TBrowse::get_output_fields() const
{
return _out_id;
}
// @doc INTERNAL
// @mfunc Ritorna il numero di campi non vuoti e non filtrati
//
// @rdesc Numero di campi non vuoti e non filtrati
int TBrowse::do_input(
bool filter) // @parm Indica se effettuare il filtro sulla selezione
// @comm Questa funzione serve ai <c TCursor_sheet>
{
int ne = 0;
if (_inp_id.empty()) return ne;
TRectype& cur = _cursor->curr();
cur.zero();
TRectype filtrec(cur);
_inp_id.restart();
_inp_fn.restart();
TString256 val; // Value to output
bool tofilter;
for (const char* fld = _inp_id.get(); fld; fld = _inp_id.get())
{
if (*fld == '"')
{
val = (fld+1);
if (val.not_empty()) val.rtrim(1);
tofilter = filter;
}
else
{
const short id = field().atodlg(fld);
const bool filter_flag = strchr(fld, '@') != NULL;
tofilter = filter && filter_flag;
val = field(id).get();
const TMask_field& f = field(id);
if (f.class_id() == CLASS_DATE_FIELD && f.right_justified())
{
const TDate d(val);
val = d.string(ANSI);
}
if (f.is_edit() && val.not_empty() && !filter_flag)
ne++; // Increment not empty fields count
}
TFieldref fldref(_inp_fn.get(), 0); // Output field
fldref.write(val, *_cursor->relation());
if (tofilter)
{
if (val.empty()) val.fill('~', fldref.len(cur));
fldref.write(val, filtrec);
}
}
if (!filter) return ne;
TString work(_filter.size());
bool filter_update = FALSE;
for (int i = 0; _filter[i]; i++)
{
if (_filter[i] == '"')
{
do
{
work << _filter[i++];
} while (_filter[i] && _filter[i] != '"');
work << '"';
if (!_filter[i]) break;
}
else
if (_filter[i] == '#')
{
work << '"' << field(atoi(&_filter[++i])).get() << '"';
while (isspace(_filter[i])) i++;
while (isdigit(_filter[i])) i++;
i--;
}
else
{
work << _filter[i];
if (_filter[i] == '-' && _filter[i + 1] == '>')
filter_update = TRUE;
}
}
_cursor->setfilter(work, filter_update);
_cursor->setregion(filtrec, filtrec);
return ne;
}
static TBit_array s_checked;
static short s_checking = 0;
void TBrowse::do_output(CheckTime t)
{
if (t == FINAL_CHECK)
return;
const bool master = s_checking == 0;
if (master)
{
s_checking = field().dlg();
s_checked.reset();
// Rendo intoccabili i campi del MIO output
for (const char* fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
s_checked.set(id);
}
}
TString sum;
TToken_string flds(24, '+');
const TRelation& relation = *_cursor->relation();
TBit_array spotted;
_out_fn.restart();
const char* fld;
for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(id);
flds = _out_fn.get();
if (t != STARTING_CHECK || f.field() == NULL || f.mask().mode() == MODE_INS)
{
sum.cut(0);
for(const char* fr = flds.get(0); fr; fr = flds.get())
{
if (*fr == '"')
{
sum << (fr+1);
sum.rtrim(1);
}
else
{
const TFieldref fld(fr, 0);
sum << fld.read(relation);
}
}
bool hit = FALSE;
if (master)
{
f.set(sum);
hit = id != s_checking; // Il mio handler viene fatto nella on_key
}
else
{
if (!s_checked[id])
{
f.set(sum);
s_checked.set(id);
hit = TRUE;
}
}
/*
if (hit)
{
f.check();
f.on_hit();
}
*/
spotted.set(id, hit);
}
}
for (fld = _out_id.get(0); fld && *fld; fld = _out_id.get())
{
const short id = field().atodlg(fld);
if (spotted[id])
{
TMask_field& f = field(id);
f.check();
f.on_hit();
}
}
if (master)
s_checking = 0;
}
void TBrowse::do_clear(CheckTime t)
{
const bool master = s_checking == 0;
if (master)
{
s_checking = field().dlg();
s_checked.reset();
// Rendo intoccabili i campi del MIO input
for (const char* fld = _inp_id.get(0); fld && *fld; fld = _inp_id.get())
{
if (isdigit(*fld))
{
const short id = field().atodlg(fld);
s_checked.set(id);
}
}
}
for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get())
{
const short id = field().atodlg(fld);
TMask_field& f = field(atoi(fld));
if (f.field() == NULL && field().dlg() != id &&
!s_checked[id] && _inp_id.get_pos(fld) < 0)
{
f.reset();
s_checked.set(id);
f.on_hit();
f.check(t);
}
}
if (master)
s_checking = 0;
}
bool TBrowse::do_link(bool insert)
{
bool ok = FALSE;
TString app;
if (_insert[0] == 'M')
{
TString nm(_insert.mid(1));
// if (nm.compare("batb", 4, TRUE) == 0) // Programma gestione tabelle
if (nm.compare("tb", 2, TRUE) == 0) // Programma gestione tabelle
{
// app = format("ba3 -0 %s", (const char*)nm.mid(4));
const char* module = ((TTable&)_cursor->file()).module();
TString prg("ba3 -0");
if (strcmp(module,"ba")!=0)
{
TConfig c(CONFIG_STUDIO);
prg = c.get("TabPrg",module);
if (prg.empty())
prg = "ba3 -0";
}
app = format("%s %s", (const char*)prg,(const char*)nm.mid(2));
// Obbligatorio usare la format globale
}
else // Programma generico di browse/edit
app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file().num());
// Obbligatorio usare la format globale
}
else
{
app = &_insert[1];
}
if (app.find('#') != -1)
{
TString w(app);
app = "";
for (const char* f = w; *f; f++)
{
if (*f == '#')
{
const int id = atoi(++f);
app << field(id).get();
while (isspace(*f)) ++f;
while (isdigit(*f)) ++f;
if (*f)
app << ' ' << *f;
else
break;
}
else
app << *f;
}
}
TMailbox mail;
if (insert)
{
TMessage msg(app, MSG_AI, "");
mail.send(msg);
}
else
{
TToken_string body;
body.add(_cursor->key());
_inp_fn.restart();
for (const char* i = _inp_id.get(0); i; i = _inp_id.get())
{
TString inp_id(i);
TString16 field_name(_inp_fn.get());
TString s(field_name);
const int pos = s.find(",");
if (pos >= 0)
s.cut(pos);
s << "=";
if (inp_id[0] == '"')
{
inp_id.ltrim(1);
inp_id.rtrim(1);
s << inp_id;
}
else
{
const short id = field().atodlg(inp_id);
const TEditable_field & f = field(id);
TFieldref fldref(field_name, 0);
s << fldref.read(*_cursor->relation());
}
body.add(s);
}
TMessage msg(app, MSG_ED, body);
mail.send(msg);
}
TExternal_app a(app);
a.run();
field().mask().set_focus();
if (mail.check())
{
TMessage* rcv = mail.next_s(insert ? MSG_AI : MSG_LN);
if (rcv != NULL)
_rec = atol(rcv->body());
if (_rec > 0)
{
_cursor->file().readat(_rec);
ok = _cursor->ok();
if (ok) do_output();
#ifdef DBG
else yesnofatal_box("Selezione da programma esterno errata");
#endif
}
}
return ok;
}
TToken_string& TBrowse::create_siblings(TToken_string& siblings)
{
const TMask& mask = field().mask();
siblings = ""; // Azzera la lista dei campi associati
TBit_array key(4); // Elenco delle chiavi gia' utilizzate
key.set(_cursor->key());
TString fn; // Nome campo
// Scorre la lista dei campi di output
int n = 0;
for (const char* i = _out_id.get(0); i; i = _out_id.get(), n++)
{
const short id = field().atodlg(i);
const TEditable_field& f = field(id);
if (!f.active() || !f.is_edit()) // Scarta i campi non editabili
continue;
const TEdit_field& e = (const TEdit_field&)f;
const TBrowse* b = e.browse();
if (b == NULL)
continue; // Scarta i campi senza ricerca
const TCursor* c = b->cursor();
// Considera ricerche sullo stesso file ma con chiave diversa
if (c->file().num() == _cursor->file().num() &&
(key[c->key()] == FALSE || id == field().dlg()))
{
fn = _out_fn.get(n); // Legge nome del campo su file
int pos = _items.get_pos(fn); // Determina header corrispondente
if (pos < 0) // Se non lo trova identico ...
{
const int q = fn.find('[');
if (q > 0)
{
fn.cut(q);
pos = _items.get_pos(fn); // ... ritenta senza parentesi
}
}
if (pos >= 0)
{
siblings.add(id);
const char* h = _head.get(pos);
siblings.add(h);
const int et = siblings.find('@');
if (et > 0) siblings.cut(et);
key.set(c->key()); // Marca la chiave come usata
}
}
}
return siblings;
}
KEY TBrowse::run()
{
begin_wait();
do_input(TRUE);
_cursor->read(_isgteq);
//const TLocalisamfile& f = _cursor->file();
//TString caption(prefix().description(f.name()));
TString caption(_cursor->file().description());
if (!isalnum(caption[0]))
caption = "Selezione";
KEY k = K_ESC;
long selected = 0;
TToken_string siblings, vals;
create_siblings(siblings);
{
byte buttons = 0;
if (_insert.not_empty())
{
// Mette il bottone di gestione, a meno che ...
if (_cursor->items() == 0)
buttons = 2; // Non mette il bottone collega se non ci sono elementi
else
buttons = 3;
if (_insert[0] == 'M' || _insert[0] == 'R')
{
const TString& maskname = field().mask().source_file();
if (maskname.mid(2,2).compare("tb", 2, TRUE) == 0 && field().in_key(0))
{
const char* tabname = _cursor->file().name();
if (maskname.mid(4, 3).compare(tabname, 3, TRUE) == 0)
buttons = 0;
}
}
}
for (const char* i = _inp_id.get(0); i; i = _inp_id.get())
{
if (*i != '"' && strchr(i, '@') == NULL)
{
const short id = field().atodlg(i);
const TEditable_field& f = field(id);
if (f.active() && f.is_editable())
{
vals.add(i);
vals.add(f.get());
vals.add((int)f.dirty());
}
}
}
end_wait();
TBrowse_sheet s(_cursor, _items, caption, _head, buttons, &field(), siblings);
k = s.run();
selected = s.selected();
}
switch (k)
{
case K_CTRL+'G':
*_cursor = selected;
k = do_link(FALSE) ? K_ENTER : K_ESC;
break;
case K_INS:
k = do_link(TRUE) ? K_ENTER : K_ESC;
break;
case K_ENTER:
*_cursor = selected;
do_output();
break;
default:
{
for (const char* i = vals.get(0); i && *i; i = vals.get())
{
const short id = field().atodlg(i);
TEditable_field& f = field(id);
f.set(vals.get());
f.set_dirty(vals.get_int());
}
}
if (k >= K_CTRL)
{
TMask& m = field().mask();
const int tag = k - K_CTRL - K_F1;
const short id = siblings.get_int(tag * 2);
TEdit_field& ef = m.efield(id);
ef.set_focus();
k = K_F9;
if (m.is_running())
m.send_key(k, id);
}
break;
}
return k;
}
bool TBrowse::check(CheckTime t)
{
bool passed = TRUE;
if (_secondary == TRUE && t != RUNNING_CHECK)
return TRUE;
if (field().check_type() != CHECK_NONE)
{
const TMaskmode mode = (TMaskmode)field().mask().mode();
CheckType chk = field().check_type();
if (chk == CHECK_REQUIRED && (t == STARTING_CHECK || mode == MODE_QUERY))
chk = CHECK_NORMAL;
const int ne = do_input(TRUE);
if (ne || chk == CHECK_REQUIRED)
{
/* Guy: vecchio modo
_cursor->setkey();
_cursor->file().read(_isequal);
passed = _cursor->ok();
*/
passed = _cursor->test() == NOERR;
if (t != FINAL_CHECK)
{
if (passed)
{
_cursor->repos();
do_output(t);
}
else
{
if (chk == CHECK_SEARCH)
{
passed = TRUE;
}
else
{
do_clear(t);
if (!field().mask().query_mode() && field().check_enabled())
field().set_dirty(3);
}
}
}
else
{
if (chk == CHECK_SEARCH)
passed = TRUE;
}
}
else
{
if (chk == CHECK_SEARCH)
passed = TRUE;
else
{
if (t != FINAL_CHECK)
do_clear(t);
}
}
}
return passed;
}
bool TBrowse::empty_check()
{
if (field().mask().query_mode() || field().check_type() != CHECK_REQUIRED)
return TRUE;
else
return do_input() > 0;
}
///////////////////////////////////////////////////////////
// TEdit_field
///////////////////////////////////////////////////////////
TEdit_field::TEdit_field(TMask* mask)
: TEditable_field(mask), _browse(NULL),
_check(CHECK_NONE), _check_enabled(FALSE), _forced(FALSE)
{ }
TEdit_field::~TEdit_field()
{
if (_browse) delete _browse;
}
word TEdit_field::class_id() const
{ return CLASS_EDIT_FIELD; }
void TEdit_field::set_len(short w)
{
}
void TEdit_field::set_width(short width, short dwidth)
{
RCT rect;
get_rect(rect);
rect.right= rect.left+width;
set_rect(rect);
/* _ctl_data.reset();
_ctl_data._dlg = dlg();
_ctl_data._x = x;
_ctl_data._y = y;
_ctl_data._prompt = prompt();
_ctl_data._size = size();
_ctl_data._flags = flags;
_flags.update(flags);
_ctl_data._width = width;
create(parent()); */
}
void TEdit_field::parse_head(TScanner& scanner)
{
_ctl_data._size = scanner.integer();
#ifdef DBG
if (_ctl_data._size <= 0)
{
_ctl_data._size = 8;
yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)",
_ctl_data._dlg, _ctl_data._size);
}
#endif
_ctl_data._width = scanner.integer();
if (_ctl_data._width == 0)
_ctl_data._width = _ctl_data._size;
}
const TBrowse* TEdit_field::parse_browse(TScanner& scanner) const
{
const int id = scanner.integer();
const TEdit_field& f = mask().efield(id);
const TBrowse* b = f.browse();
return b;
}
bool TEdit_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "PI") // PICTURE
{
_picture = scanner.string();
return TRUE;
}
if (scanner.key() == "CH")
{
scanner.pop();
if (scanner.key() == "NO") _check = CHECK_NORMAL; else
if (scanner.key() == "RE") _check = CHECK_REQUIRED; else
if (scanner.key() == "FO") { _check = CHECK_REQUIRED; _forced = TRUE; } else
if (scanner.key() == "SE") _check = CHECK_SEARCH;
else _check = CHECK_NONE;
if (sheet())
{
#ifdef DBG
NFCHECK("Checktype inutile sul campo %d", dlg());
#endif
_check = CHECK_NONE;
}
return TRUE;
}
if (scanner.key() == "US") // USE
{
#ifdef DBG
if (_browse != NULL)
return yesnofatal_box("USE duplicata nel campo %d", dlg());
#endif
int key = 1;
TRelation* r = NULL;
const int logicnum = scanner.integer();
TString16 tabmaskname;
if (logicnum > 0)
{
TDir d; d.get(logicnum);
if (fexist(d.filename())) // Controlla l'esistenza del file
r = new TRelation(logicnum);
}
else
{
tabmaskname = scanner.pop();
#ifdef DBG
if (tabmaskname.len() > 4)
return yesnofatal_box("'%s' non e' una tabella valida: %d",
(const char*)tabmaskname, dlg());
#endif
TDir d; d.get(TTable::name2log(tabmaskname));
if (fexist(d.filename())) // Controlla l'esistenza del file
r = new TRelation(tabmaskname);
}
if (scanner.popkey() == "KE")
{
key = scanner.integer();
#ifdef DBG
if (key < 1 || key > MAX_KEYS)
{
yesnofatal_box("Chiave %d non valida nella USE del campo %d", key, dlg());
key = 1;
}
#endif
}
else scanner.push();
TString filter;
if (scanner.popkey() == "SE")
filter = (const char*)scanner.line();
else
scanner.push();
if (r != NULL)
{
_browse = new TBrowse(this, r, key, filter); // create browse with no filter ...
// ... complete relation by parsing all Join items ...
while (scanner.popkey() == "JO")
{
if (browse())
browse()->parse_join(scanner);
else
scanner.line();
}
scanner.push();
if (tabmaskname.not_empty())
{
// tabmaskname.insert("MBATB", 0);
tabmaskname.insert("MTB", 0);
browse()->set_insert(tabmaskname);
}
_check_enabled = TRUE;
}
return TRUE;
}
if (scanner.key() == "CO") // Copyuse
{
const TString16 what(scanner.popkey());
const TBrowse* b = parse_browse(scanner);
if (b)
{
if (what == "US" || what == "AL")
{
if (_browse == NULL)
_browse = new TBrowse(this, b->cursor());
else
NFCHECK("COPY USE e USE nel campo %d", _ctl_data._dlg);
}
if (_browse)
{
_check_enabled = TRUE;
return browse()->parse_copy(what, *b);
}
}
}
if (scanner.key() == "SH") // SHEET
{
#ifdef DBG
if (_browse)
return yesnofatal_box("SHEET duplicato nel campo %d", _ctl_data._dlg);
#endif
_browse = new TList_sheet(this, _ctl_data._prompt, scanner.string());
_check_enabled = TRUE;
return TRUE;
}
if (scanner.key() == "IT") // ITEM
{
#ifdef DBG
if (sheet() == NULL)
return yesnofatal_box("ITEM senza SHEET nel campo %d", _ctl_data._dlg);
else
#endif
sheet()->parse_item(scanner);
return TRUE;
}
if (scanner.key() == "IN")
{
if (_browse)
_browse->parse_input(scanner);
else
scanner.line();
return TRUE;
}
if (scanner.key() == "DI")
{
if (browse())
browse()->parse_display(scanner);
else
scanner.line();
return TRUE;
}
if (scanner.key() == "OU")
{
if (_browse)
_browse->parse_output(scanner);
else
scanner.line();
return TRUE;
}
if (scanner.key() == "AD")
{
if (browse())
browse()->parse_insert(scanner);
else
scanner.line();
return TRUE;
}
if (scanner.key() == "ME")
{
TString& l = scanner.line().strip_spaces();
int m = 0;
if (l[0] == '0')
{
l.ltrim(1);
l.ltrim();
m = 1;
}
message(m, TRUE)->add(l);
return TRUE;
}
return TEditable_field::parse_item(scanner);
}
void TEdit_field::create(WINDOW parent)
{
const int len = create_prompt(parent, 0, 0);
_size = _ctl_data._size;
_ctl_data._x += len;
if (_browse) // Decide se attivare o meno il bottone di ricerca
_ctl_data._flags << 'B';
_ctl = new TField_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y,
_ctl_data._width, _ctl_data._size,
_ctl_data._flags, "");
if (_browse && !enabled_default())
((TField_control*)_ctl)->show_button(FALSE);
}
const char* TEdit_field::reformat(const char* str) const
{
TString& s = _ctl_data._park;
s = str;
const byte trim_mode = _flags.trim;
smart_trim(s, trim_mode);
if (s.not_empty())
{
word len = s.len();
if (len > size())
{
#ifdef DBG
yesnofatal_box("Campo %d troppo lungo: %s > %d", dlg(), str, _size);
#endif
s.cut(len = size());
}
if (_flags.zerofilled)
{
if (len < size())
{
if (isdigit(s[0]) && real::is_natural(s))
s.right_just(size(), '0');
}
for (const char * w = (const char *) s; *w == '0'; w++) ;
if (*w == '\0')
s.cut(0);
}
if (_flags.uppercase)
s.upper();
}
return s;
}
const char* TEdit_field::raw2win(const char* raw) const
{
return reformat(raw);
}
const char* TEdit_field::win2raw(const char* win) const
{
return reformat(win);
}
void TEdit_field::set_window_data(const char* data)
{
_ctl->set_caption(data);
}
void TEdit_field::autoselect(bool on)
{
_ctl->autoselect(on);
}
TString& TEdit_field::get_window_data()
{
_str = win2raw(_ctl->caption());
return _str;
}
// Certified 90%
bool TEdit_field::on_hit()
{
const int vf = validate_func();
if (vf >= 0)
{
if (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC || vf == 21)
{
const bool ok = validate(K_TAB); // Check validation expression
if (!ok) return FALSE;
}
}
const bool ok = handler(K_TAB);
if (ok && has_message())
{
if (empty() && message(1))
do_message(1);
else
do_message(0);
}
return ok;
}
// @doc EXTERNAL
// @mfunc Mostra un messaggio di errore di default per il campo
//
// @rdesc Ritorna sempre FALSE
bool TEdit_field::default_error_box() const
// @comm Se il campo non possiede un warning particolare chiama la <f error_box>
// indicando genericamente che il valore immesso non e' valido, altrimenti
// riporta il warning associato al campo
{
if (!has_warning())
{
const TString p(prompt());
if (isalnum(p[0]))
{
const TString val(get());
error_box("Valore non valido per %s: %s", (const char*)p, (const char*)val);
}
else
error_box("Valore non valido: %s", (const char*)get());
}
else
error_box(get_warning());
return FALSE;
}
bool TEdit_field::on_key(KEY key)
{
const int vf = validate_func();
switch(key)
{
case K_CTRL+K_TAB:
set_focusdirty(FALSE);
break;
case K_TAB:
/*
if (vf >= 0 && (vf == AUTOEXIT_FUNC || vf == NUMCALC_FUNC || vf == STRCALC_FUNC))
set_focusdirty(); // Forza validate
*/
if (to_check(K_TAB, TRUE))
{
if (class_id() == CLASS_EDIT_FIELD) // Altrimenti l'ha gia' fatto
{
const TString& raw = get_window_data();
set_window_data(raw2win(raw));
}
bool ok = validate(key); // Check validation expression
if (!ok)
{
if (has_warning())
default_error_box();
return FALSE;
}
TMask& m = mask();
const bool query = m.query_mode();
const bool vuoto = empty();
if (_browse)
{
if (sheet())
{
ok = query || sheet()->check(); // Check consistency
}
else
{
// if (check_enabled() && (!query || forced()) && vf != 21)
if (check_enabled() && vf != 21)
{
if (!query || forced())
ok = browse()->check();
else
browse()->check();
}
}
}
if (ok)
ok = on_hit();
else
{
if (vuoto)
ok = TRUE;
else
default_error_box();
}
if (ok)
{
set_focusdirty(FALSE);
if (query && m.is_running() && in_key(0))
test_key_complete();
}
else
set_focusdirty(!vuoto);
return ok;
}
else
return handler(K_TAB);
break;
case K_ENTER:
// if (field() != NULL || mask().mode() == NO_MODE)
{
bool ok = validate(K_ENTER); // Check validation expression
if (!ok)
{
if (has_warning())
default_error_box();
return FALSE;
}
if (!mask().query_mode() /* || forced() */)
{
ok = !(check_type() == CHECK_REQUIRED && empty());
// check consistency
if (ok && _browse)
{
if (sheet())
ok = sheet()->check(FINAL_CHECK);
else
{
if (ok && check_enabled() && vf != 21) // 21 = NOT_EMPTY_CHECK_FIELD
{
if (dirty()) ok = browse()->check(FINAL_CHECK); // Check consistency
else ok = browse()->empty_check();
}
}
}
if (!ok) return default_error_box();
}
}
break;
case K_F2:
set("");
break;
case K_F9:
if (check_enabled())
{
if (focusdirty())
get_window_data();
KEY k = K_ESC;
if (_browse) k = _browse->run();
else beep();
if (k != K_F9)
set_focus();
if (k == K_ENTER)
{
bool ok = TRUE;
set_dirty();
// Controlla i validate che non vengono fatti da on_hit
const int vf = validate_func();
if (vf >= 0 && vf != AUTOEXIT_FUNC && vf != NUMCALC_FUNC &&
vf != STRCALC_FUNC && vf != 21)
{
ok = validate(K_TAB);
if (!ok && has_warning())
default_error_box();
}
// Esegue handler
if (ok)
ok = on_hit();
if (ok)
{
TMask & m = mask();
if (m.is_running())
{
set_focusdirty(FALSE); // Evita doppia esecuzione handlers!
if (m.query_mode() && in_key(0))
test_key_complete();
if (m.is_running())
{
set_focusdirty(FALSE);
send_key(K_TAB, 0); // Passa al campo successivo
}
}
}
return ok;
}
else
return FALSE;
}
else
if (_browse == NULL && has_button())
return handler(K_F9);
break;
case K_CTRL+K_SPACE:
set_dirty(TRUE);
return handler(K_SPACE);
default:
break;
}
return TEditable_field::on_key(key);
}
// @mfunc Controlla se il campo ha la necessita' di eseguire una ricerca sul cursore o
// sulla tabella associata al momento della sua inizializzazione
//
// @rdesc Ritorna TRUE se il campo ha un TArray_sheet associato oppure un TCursor_sheet
// con check_type non nullo.
bool TEdit_field::has_check() const
{
bool ok = FALSE;
if (_browse)
ok = browse() == NULL || check_type() != CHECK_NONE;
return ok;
}
bool TEdit_field::check(CheckTime t)
{
bool ok = TRUE;
if (check_enabled() || (t == STARTING_CHECK && shown()))
{
if (_browse && validate_func() != 21)
ok = _browse->check(t);
}
return ok;
}
void TEdit_field::set_query_button(TBrowse_button * brw)
{
if (_browse)
delete _browse;
_browse=brw;
}
// @doc EXTERNAL
void TEdit_field::enable(bool on)
{
TEditable_field::enable(on);
if (_browse)
((TField_control*)_ctl)->show_button(on);
}
// @mfunc Permette di abilitare/disabilitare un check di un campo
void TEdit_field::enable_check(
bool on) // @parm Operazione da svolgere
//
// @flag TRUE | Abilita il check del campo (default)
// @flag FALSE | Disabilita il check del campo
{
_check_enabled = on;
((TField_control*)_ctl)->show_button(on);
}
///////////////////////////////////////////////////////////
// Date_field
///////////////////////////////////////////////////////////
TDate_field::TDate_field(TMask* m) : TEdit_field(m)
{ }
word TDate_field::class_id() const
{ return CLASS_DATE_FIELD; }
// Certified 100%
bool TDate_field::is_kind_of(word cid) const
{ return cid == CLASS_DATE_FIELD || TEdit_field::is_kind_of(cid); }
void TDate_field::create(WINDOW w)
{
// Elimina il flag R che si interpreta come salva in formato ANSI
_ctl_data._flags.strip("AR");
TEdit_field::create(w);
if (automagic())
{
TDate d(TODAY);
set(d.string());
}
}
void TDate_field::parse_head(TScanner&)
{
_ctl_data._size = _ctl_data._width = 10;
}
// @doc EXTERNAL
// @mfunc Permette di formattare la data secondo i flag correnti
//
// @rdesc Ritorna la data formattata
const char* TDate_field::win2raw(
const char* datum) const // @parm Stringa contenenete la data da formattare
// @comm Permette di gestire anche alcuni date particolari come:
//
// @flag IERI | Inserisce la data del giorno precedente a quella del sistema
// @flag OGGI | Inserisce la data del sistema
// @flag DOMANI | Inserisce la data del giorno successivo a quella del sistema
// @flag PRIMO | Primo giorno dell'anno (01-01-aa)
// @flag ULTIMO | Ultimo giorno dell'anno (31-12-aa)
// @flag NATALE | Giorno di natale (25-12-aa)
{
TString& s = _ctl_data._park;
s = datum; s.trim();
if (s.not_empty())
{
if (isdigit(s[0]) && s.len() < 10)
{
long d;
int m, y;
const int items = sscanf(s, "%ld-%d-%d", &d, &m, &y);
switch(items)
{
case 1:
d = atoi(s.left(2));
m = atoi(s.mid(2, 2));
y = atoi(s.mid(4));
break;
case 2:
y = 0;
break;
case 3:
break;
default:
d = 0;
break;
}
if (d > 0)
{
if (m <= 0 || y <= 0)
{
const TDate oggi(TODAY);
if (m <= 0) m = oggi.month();
if (y <= 0) y = oggi.year();
}
if (y < 100)
y += (y <= 10) ? 2000 : 1900;
s.format("%02d-%02d-%4d", int(d), m, y);
}
}
else
{
bool ok = TRUE;
TDate g(TODAY);
s.upper();
if (s == "IERI")
{
--g;
} else
if (s == "DOMANI")
{
++g;
} else
if (s == "POSDOMANI")
{
g += 2;
} else
if (s == "ALTROIERI")
{
g -= 2;
} else
if (s == "PRIMO")
{
g.set_month(1);
g.set_day(1);
} else
if (s == "NATALE")
{
g.set_month(12);
g.set_day(25);
} else
if (s == "ULTIMO")
{
g.set_month(12);
g.set_day(31);
} else
if (s != "OGGI")
ok = FALSE;
if (ok)
s = g.string();
}
}
return s;
}
const char* TDate_field::reformat(const char* str) const
{
TString& s = _ctl_data._park;
s = str;
if (s.len() == 8)
s = TDate(str).string();
else
if (s.blank())
s.cut(0);
return s;
}
const char* TDate_field::raw2win(
const char* datum) const // @parm Stringa contenenete la data da formattare
{
return reformat(datum);
}
bool TDate_field::on_key(KEY key)
{
if (to_check(key))
{
const TString& data = get_window_data();
if (data.not_empty()) // data not empty
{
if (!TDate::isdate(data))
{
error_box("Data errata o formato non valido");
return FALSE;
}
else
{
#ifdef _DEMO_
TDate d(data);
int y = d.year();
if (y & 0x0001) y--;
y >>= 3;
y++;
y /= 10;
if (y >= 25)
{
int m = d.month();
if (m > 3)
d.set_month(rand() % 3 + 1);
}
set_window_data(d.string());
#else
set_window_data(data);
#endif
}
}
}
else
{
if (_ctl->is_edit_key(key))
{
const bool ok = strchr("-0123456789ADEGILMNOPRSTUadegilmnoprstu", key) != NULL;
if (!ok) beep();
return ok;
}
}
return TEdit_field::on_key(key);
}
bool TDate_field::autosave(TRelation& r)
{
if (field())
{
const char* td = get();
#ifdef _DEMO_
{
TDate d(td);
int y = d.year();
y += 8;
y /= 25;
y >>= 3;
if (y >= 10)
{
int m = d.month() >> 2;
if (m > 0)
d.set_month(rand() % 3 + 1);
}
td = d.string();
}
#endif
if (right_justified())
{
TDate d(td);
td = d.string(ANSI);
}
field()->write(td, r);
return TRUE;
}
return FALSE;
}
///////////////////////////////////////////////////////////
// Real_field
///////////////////////////////////////////////////////////
TReal_field::TReal_field(TMask* m) : TEdit_field(m)
{ }
word TReal_field::class_id() const
{ return CLASS_REAL_FIELD; }
// Certified 100%
bool TReal_field::is_kind_of(word cid) const
{ return cid == CLASS_REAL_FIELD || TEdit_field::is_kind_of(cid); }
void TReal_field::create(WINDOW w)
{
_ctl_data._flags.strip("AFM");
if (!roman())
_ctl_data._flags << 'R'; // Forza l'allineamento a destra per i numeri
TEdit_field::create(w);
if (_flags.firm)
TMask_field::set(main_app().get_firm());
else
if (automagic())
TMask_field::set(TDate(TODAY).year());
}
bool TReal_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "PI") // PICTURE
{
_picture = scanner.string();
if (_decimals == 0)
{
if (_picture[0] == '.')
_decimals = atoi(&_picture[1]);
else
{
const int comma = _picture.find(',');
if (comma >= 0)
_decimals = _picture.len() - comma - 1;
}
}
//#ifdef DBG
// const int preferred_size = 19;
// if (_ctl_data._size > 9 && _ctl_data._size != preferred_size)
// ::warning_box("Guy propone una dimensione di %d per il campo %d: %s\nMa probabilmente ha toppato ...",
// preferred_size, _ctl_data._dlg, (const char*)_ctl_data._prompt);
//#endif
return TRUE;
}
return TEdit_field::parse_item(scanner);
}
const char* TReal_field::reformat(const char* data) const
{
TString& str = _ctl_data._park;
if (!real::is_null(data))
{
str = data;
if (_flags.zerofilled)
{
word s = size();
if (roman())
{
s = decimals();
if (s <= 0) s = 4;
}
str.right_just(s, '0');
}
}
else
str.cut(0);
return str;
}
bool TReal_field::on_key(KEY key)
{
if (to_check(key))
{
const TString& n = get_window_data();
if (roman())
{
const int r = atoi(n);
if (r < 0) return error_box("Numero romano errato");
}
else
{
if (!real::is_real(n))
return error_box("Valore numerico non valido");
if (_flags.uppercase && real(n).sign() < 0)
return error_box("Il numero deve essere positivo");
if (key == K_TAB && _flags.firm)
{
const long f = atol(n);
if (f > 0 && prefix().exist(f))
main_app().set_firm(f);
}
}
set_window_data(raw2win(n));
}
else
{
if (_ctl->is_edit_key(key))
{
bool ok = TRUE;
switch (key)
{
case '.':
ok = !(_flags.zerofilled || _flags.roman || size() < 4);
break;
case ',':
ok = _decimals > 0;
break;
case '-':
ok = !_flags.uppercase;
break;
default :
if (_flags.roman)
ok = strchr("0123456789IVXLCDMivxlcdm", key) != NULL;
else
ok = strchr("0123456789", key) != NULL;
break;
}
if (!ok)
beep();
return ok;
}
}
return TEdit_field::on_key(key);
}
void TReal_field::parse_head(TScanner& scanner)
{
_ctl_data._size = scanner.integer();
#ifdef DBG
if (_ctl_data._size <= 0)
{
_ctl_data._size = 9;
yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", _ctl_data._dlg, _ctl_data._size);
}
#endif
_ctl_data._width = _ctl_data._size;
_decimals = scanner.integer();
}
const char* TReal_field::raw2win(const char* data) const
{
TString& s = _ctl_data._park;
if (data == NULL) data = "";
if (roman())
{
s = itor(atoi(data));
}
else
{
if (!real::is_null(data))
{
real n(data);
if (exchangeable() && decimals())
{
const real& e = mask().exchange();
n /= e;
}
if (_picture.empty())
{
if (_flags.zerofilled)
s = n.stringa(_size, _decimals, '0');
else
s = n.stringa(0, _decimals);
}
else
{
s = n.string(_picture);
}
}
else
s.cut(0);
}
return s;
}
const char* TReal_field::win2raw(const char* data) const
{
TString& str = _ctl_data._park;
if (roman())
{
int r = atoi(data);
if (r == 0) // Se non e' scritto in arabo converti da romano
r = rtoi(data);
if (r > 0)
{
int d = decimals();
if (d < 1) d = 4;
if (_flags.zerofilled)
str.format("%0*d", d, r);
else
str.format("%*d", d, r);
}
else
str.cut(0);
}
else
{
real n(real::ita2eng(data));
if (exchangeable() && decimals())
{
const real& e = mask().exchange();
n *= e;
}
if (n.is_zero())
str.cut(0);
else
{
if (_flags.zerofilled)
str = n.string(_size, _decimals, '0');
else
str = n.string();
}
}
return str;
}
void TReal_field::set_decimals(int d)
{
_decimals = d;
if (_picture[0] == '.')
{
if (d > 0) _picture.format(".%d", d);
else _picture = ".";
}
}
void TReal_field::exchange(bool show_value, const real& nuo)
{
const int dec = show_value ? 2 : 0; // Quanti decimali voglio
const bool value = decimals() != 0; // Sono attualmente in valuta ?
if (show_value == value && show_value) return; // Se cambio da valuta a valuta esco subito!
if (mask().is_running())
{
const char* n = get_window_data();
if (*n)
{
const real& vec = mask().exchange();
real r(n);
if (!show_value)
r *= nuo;
r /= vec;
r.round(dec);
set_decimals(dec);
TEdit_field::set_window_data(r.string(_picture));
}
}
if (decimals() != dec)
set_decimals(dec);
}
///////////////////////////////////////////////////////////
// List_field
///////////////////////////////////////////////////////////
TList_field::TList_field(TMask* m)
: TEditable_field(m), _size(0)
{ }
word TList_field::class_id() const
{ return CLASS_LIST_FIELD; }
void TList_field::read_item(TScanner& scanner)
{
TToken_string ts(scanner.string());
_codes.add(ts.get());
const char* v = ts.get();
_values.add(v);
CHECKS(v == NULL || strlen(v) <= (word)_ctl_data._width, "List item is too long:", v);
ts.cut(0);
while (scanner.popkey() == "ME")
ts.add(scanner.line().strip_spaces());
scanner.push();
*message(-1, TRUE) = ts;
}
void TList_field::parse_head(TScanner& scanner)
{
_ctl_data._size = scanner.integer();
_ctl_data._width = scanner.integer();
if (_ctl_data._width == 0)
_ctl_data._width = _ctl_data._size;
}
bool TList_field::parse_item(TScanner& scanner)
{
if (scanner.key() == "IT") // ITEM
{
read_item(scanner);
return TRUE;
}
return TEditable_field::parse_item(scanner);
}
int TList_field::items() const
{
return _codes.items();
}
// @doc EXTERNAL
// @mfunc Aggiunge delle voci al list sheet
void TList_field::add_item(
const char* s) // @parm Voci da aggiungere
// @comm Se il parametro <p s> e' passato con il formato di una <c TToken_string> vengono
// aggiunte tante voci quanti sono gli elementi.
{
TToken_string t(s);
TString item(t.get());
const int pos = _codes.get_pos(item);
if (pos < 0)
{
_codes.add(item);
item = t.get();
_values.add(item);
((TListbox_control*)_ctl)->set_values(_codes, _values);
}
}
void TList_field::delete_item(const char* s)
{
const TString t(s);
const int pos = _codes.get_pos(t);
if (pos >= 0 )
{
_codes.destroy(pos);
_values.destroy(pos);
((TListbox_control*)_ctl)->set_values(_codes, _values);
if (pos == current())
{
current(0);
if (active() || ghost())
on_hit();
}
}
}
void TList_field::add_list()
{
if (roman() && _codes.items() < 12)
{
TString csafe, vsafe;
if (atoi(_codes) > 0)
{
csafe = _codes; _codes = "";
vsafe = _values; _values = "";
}
_codes.add("01|02|03|04|05|06|07|08|09|10|11|12");
_values.add("Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno|"
"Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre");
if (atoi(csafe) > 0)
{
_codes.add(csafe);
_values.add(vsafe);
if (message(0))
{
*message(_codes.items()-1, TRUE) = *message(0);
message(0)->cut(0);
}
}
}
((TListbox_control*)_ctl)->set_values(_codes, _values);
if (roman() && automagic())
{
const char* init = format("%02d", TDate(TODAY).month());
set(init);
}
else
current(0);
}
const char* TList_field::win2raw(const char* data) const
{
// fool the compiler to keep const
TToken_string& codes = ((TList_field*)this)->_codes;
TToken_string& value = ((TList_field*)this)->_values;
_ctl_data._park = data; // data puo' venire da una TToken_string::get
int pos = 0;
if (_ctl_data._park.len() > 2) // E' veramente una descrizione
pos = value.get_pos(_ctl_data._park);
else // Oppure e' un codice
pos = codes.get_pos(_ctl_data._park);
if (pos < 0 && _ctl_data._park.blank())
{
_ctl_data._park = codes.get(0); // Uso codes come riferimento per blank
if (_ctl_data._park.blank())
pos = 0;
}
CHECKS(pos >= 0, "Unknown listbox value:", data);
return codes.get(pos);
}
const char* TList_field::raw2win(const char* data) const
{
// fool the compiler to keep const
TToken_string& codes = ((TList_field*)this)->_codes;
TToken_string& value = ((TList_field*)this)->_values;
_ctl_data._park = data; // data puo' venire da una TToken_string::get
int pos = codes.get_pos(_ctl_data._park);
if (pos < 0 && _ctl_data._park.blank())
{
_ctl_data._park = codes.get(0);
if (_ctl_data._park.blank())
pos = 0;
}
CHECKS(pos >= 0, "Unknown listbox code:", (const char*)_ctl_data._park);
return value.get(pos);
}
bool TList_field::select_by_ofs(int n)
{
const bool changed = ((TListbox_control*)_ctl)->select_by_ofs(n);
if (changed)
_str = _codes.get(current());
return changed;
}
bool TList_field::select_by_initial(char c)
{
const bool changed = ((TListbox_control*)_ctl)->select_by_initial(c);
if (changed)
_str = _codes.get(current());
return changed;
}
// @doc EXTERNAL
// @mfunc Sostituisce alle voci correnti quelle passate come parametri
void TList_field::replace_items(
const char* codes, // @parm Codici da sostituire ai correnti
const char* values) // @parm Voci da sostituire a quelle correnti
// @comm I parametri <p codes> e <p values> devono essere TToken_string se lo voci da sostiutire
// sono piu' di una
{
_codes = codes;
_values = values;
if (_ctl)
add_list();
}
void TList_field::create(WINDOW parent)
{
const int len = create_prompt(parent, 0, 0);
_ctl_data._x += len;
_size = _ctl_data._width;
_ctl = new TListbox_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y,
_ctl_data._width,
_ctl_data._flags, _ctl_data._prompt,
_codes, _values);
add_list();
}
int TList_field::str2curr(const char* data)
{
TString str(data);
if (roman() && str.len() < 2)
str.insert("0",0);
if (_flags.uppercase)
str.upper();
int i = str.blank() ? 0 : _codes.get_pos(str);
if (i < 0) // Se non trova il codice ritenta dopo trim
{
for (i = 0; str[i] == '0' || str[i] == ' '; i++);
if (i > 0)
{
str.ltrim(i);
i = _codes.get_pos(str);
}
}
if (i < 0)
{
if (items() && str.not_empty())
NFCHECK("'%s' non e' un valore valido per il campo %s: %d",
data, prompt(), dlg());
i = 0;
}
return i;
}
void TList_field::reset()
{
if (!_flags.persistent)
current(0);
}
void TList_field::set(const char* data)
{
const int i = str2curr(data);
current(i);
// if (mask().is_running())
set_dirty();
}
void TList_field::set_window_data(const char* data)
{
NFCHECK(0,"So' passato da 'sta stronza!!!");
const int i = str2curr(win2raw(data));
current(i);
}
void TList_field::current(int n)
{
if (_ctl)
((TListbox_control*)_ctl)->select(n);
_str = _codes.get(n);
_str.trim();
}
int TList_field::current() const
{
int c;
if (_ctl)
c = ((TListbox_control*)_ctl)->selected();
else
c = ((TList_field*)this)->_codes.get_pos(_str); // Fool the compiler for const sake
return c;
}
TString& TList_field::get_window_data()
{
const int c = current();
_str = ((TList_field*)this)->_codes.get(c);
_str.trim();
return _str;
}
bool TList_field::on_hit()
{
const bool ok = handler(K_SPACE);
if (ok)
{
const int n = current();
do_message(n);
}
return ok;
}
bool TList_field::on_key(KEY key)
{
switch(key)
{
case K_CTRL+K_TAB:
set_focusdirty(FALSE);
break;
case K_SPACE:
get_window_data();
set_dirty();
return on_hit();
case K_F2:
current(0);
break;
default:
if (to_check(key, TRUE) || key == K_ENTER)
{
bool ok = TRUE;
if (validate_func() >= 0)
{
ok = validate(key);
if (!ok)
{
if (has_warning())
return error_box(get_warning());
}
}
}
break;
}
return TEditable_field::on_key(key);
}
// Certified 100%
bool TList_field::is_kind_of(word cid) const
{ return cid == CLASS_LIST_FIELD || TEditable_field::is_kind_of(cid); }
///////////////////////////////////////////////////////////
// TRadio_field
///////////////////////////////////////////////////////////
TRadio_field::TRadio_field(TMask* mask)
: TList_field(mask)
{ }
// Annulla _ctl altrimenti verrebbe cancellato due volte essendo anche nell'array
TRadio_field::~TRadio_field()
{ }
word TRadio_field::class_id() const
{
return CLASS_RADIO_FIELD;
}
void TRadio_field::create(WINDOW parent)
{
const int items = _codes.items();
if (_ctl_data._prompt.not_empty())
{
const word dy = _flags.zerofilled ? 3 : items+2;
create_prompt(parent, _ctl_data._width, dy);
}
_ctl = new TRadiobutton_control(parent, _ctl_data._dlg,
_ctl_data._x + 1, _ctl_data._y + 1,
_ctl_data._width - 2, _flags.zerofilled ? 1 : items,
_ctl_data._flags, _values);
current(0);
}
int TRadio_field::current() const
{
int c;
if (_ctl)
c = ((TRadiobutton_control*)_ctl)->get_checked();
else
c = TList_field::current();
return c;
}
void TRadio_field::current(int n)
{
if (_ctl)
((TRadiobutton_control*)_ctl)->check_button(n);
_str = _codes.get(n);
_str.trim();
}
///////////////////////////////////////////////////////////
// TMemo_field
///////////////////////////////////////////////////////////
TMemo_field::TMemo_field(TMask* mask) : TEdit_field(mask)
{
}
TMemo_field::~TMemo_field()
{
}
void TMemo_field::parse_head(TScanner& scanner)
{
_ctl_data._width = scanner.integer();
_ctl_data._height = scanner.integer();
}
void TMemo_field::create(WINDOW parent)
{
create_prompt(parent, 0, 1);
if (_ctl_data._height > 1)
_ctl_data._height--;
_size = 8192;
_ctl = new TMultiline_control(parent, _ctl_data._dlg,
_ctl_data._x, _ctl_data._y+1,
_ctl_data._width, _ctl_data._height, _size,
_ctl_data._flags, "");
}
// Certified 100%
// Aggiusta un valore letto da file in formato RAW
const char* TMemo_field::reformat(const char* data) const
{
return data;
}
const char* TMemo_field::raw2win(const char* data) const
{
if (strchr(data, '\n') == NULL)
return data;
TString& s = _ctl_data._park;
s = data;
for (int i = 0; s[i]; i++)
if (s[i] == '\n') s[i] = '\r';
return s;
}
const char* TMemo_field::win2raw(const char* data) const
{
if (strchr(data, '\r') == NULL)
return data;
_ctl_data._park = data;
for (char* s = (char*)(const char*)_ctl_data._park; *s; s++)
if (*s == '\r') *s = '\n';
return _ctl_data._park;
}
bool TMemo_field::on_key(KEY k)
{
if (k == K_TAB && focusdirty())
get_window_data();
return TEdit_field::on_key(k);
}
///////////////////////////////////////////////////////////
// Zoom_field
///////////////////////////////////////////////////////////
TZoom_field::TZoom_field(TMask* mask)
: TEdit_field(mask)
{
}
TZoom_field::~TZoom_field( )
{
}
void TZoom_field::create(WINDOW parent)
{
_ctl_data._flags << 'B';
TEdit_field::create(parent);
}
bool TZoom_field::on_key( KEY key )
{
switch (key)
{
case K_TAB:
if (focusdirty())
get_window_data();
break;
case K_F9:
if (browse() != NULL)
break;
case K_F8:
{
get_window_data();
TMask m("Zoom", 1, 72, 18);
m.add_memo(101, 0, prompt(), 1, 0, -1, -3);
m.add_button(DLG_OK, 0, "Conferma", -12, -1, 9, 2);
m.add_button(DLG_CANCEL, 0, "Annulla", -22, -1, 9, 2);
m.set(101, _str);
if (m.run() != K_ESC)
{
_str = m.get(101);
set_window_data(raw2win(_str));
}
return TRUE;
}
break;
default:
break;
}
return TEdit_field::on_key(key);
}
// Certified 100%
// Aggiusta un valore letto da file in formato RAW
const char* TZoom_field::reformat(const char* data) const
{
return data;
}
const char* TZoom_field::raw2win(const char* data) const
{
TFixed_string str(data);
int a_capo = str.find('\n');
if (a_capo < 0 || a_capo > (int)size())
a_capo = min((int)size(), str.len());
const char c = str[a_capo];
str[a_capo] = '\0';
_ctl_data._park = str;
str[a_capo] = c;
return _ctl_data._park;
}
const char* TZoom_field::win2raw(const char* data) const
{
TString& str = _ctl_data._park;
str = data;
// Elimino improbabili righe successive da data
int a_capo = str.find('\r');
if (a_capo >= 0) str.cut(a_capo);
// Aggiungo le righe del memo a partire dalla seconda
a_capo = _str.find('\n');
if (a_capo < 0 || a_capo > (int)size())
a_capo = min((int) size(), _str.len());
const char* d = _str;
str << (d+a_capo);
return str;
}
const char* TZoom_field::get_first_line() const
{ return raw2win(_str); }