2769 lines
56 KiB
C++
Executable File
2769 lines
56 KiB
C++
Executable File
// $Id: maskfld.cpp,v 1.1.1.1 1994-08-12 10:52:00 alex Exp $
|
|
#include <xvt.h>
|
|
|
|
#include <applicat.h>
|
|
#include <defmask.h>
|
|
#include <execp.h>
|
|
#include <mailbox.h>
|
|
#include <sheet.h>
|
|
#include <mask.h>
|
|
#include <relation.h>
|
|
#include <tabutil.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <validate.h>
|
|
#include <xvtility.h>
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
HIDDEN const int MAXSTR = 128;
|
|
HIDDEN char __fpark[MAXSTR]; // Temporary for get/set window data
|
|
HIDDEN TFixed_string fpark(__fpark, MAXSTR);
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Field Flags
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Certified 100%
|
|
TMask_field::TField_Flags::TField_Flags()
|
|
{
|
|
automagic = persistent = FALSE;
|
|
enabled = enable_default = TRUE;
|
|
showed = show_default = TRUE;
|
|
uppercase = rightjust = FALSE;
|
|
zerofilled = FALSE;
|
|
dirty = focusdirty = FALSE;
|
|
roman = exchange = FALSE;
|
|
firm = ghost = FALSE;
|
|
}
|
|
|
|
// Certified 100%
|
|
char TMask_field::TField_Flags::update(const char* s)
|
|
{
|
|
const char* kk = s;
|
|
for (; *s; s++)
|
|
switch(toupper(*s))
|
|
{
|
|
case 'A': automagic = persistent = TRUE; break;
|
|
case 'D': enable_default = enabled = FALSE; break;
|
|
case 'F': firm = persistent = TRUE; break;
|
|
case 'G': ghost = TRUE; break;
|
|
case 'H': show_default = showed = FALSE; break;
|
|
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;
|
|
#ifdef DBG
|
|
default : ::warning_box("FLAG sconosciuto in %s: %c", kk, *s); break;
|
|
#endif
|
|
}
|
|
return *s;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMask_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
int TMask_field::_x; // Position of the field
|
|
int TMask_field::_y;
|
|
int TMask_field::_width;
|
|
TFixed_string TMask_field::_prompt(__fpark, MAXSTR); // Prompt of the field
|
|
|
|
TMask_field::TMask_field(TMask* m)
|
|
: _mask(m), _win(NULL_WIN), _promptwin(NULL_WIN), _dlg(0),
|
|
_keys(0), _groups(0), _help(0), _handler(NULL),
|
|
_validate_func(-1), _validate_parms(1), _field(NULL)
|
|
{}
|
|
|
|
// Certified 100%
|
|
TMask_field::~TMask_field()
|
|
{
|
|
if (_field) delete _field;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
bool TMask_field::is_edit() const
|
|
{
|
|
const word c = class_id();
|
|
return c == CLASS_EDIT_FIELD || c == CLASS_REAL_FIELD || c == CLASS_DATE_FIELD;
|
|
}
|
|
|
|
|
|
// 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::ok() const
|
|
{ return win() != NULL_WIN && dlg() >= -1; }
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::parse_head(TScanner&)
|
|
{}
|
|
|
|
|
|
// Certified 100%
|
|
short TMask_field::atodlg(const char* s) const
|
|
{
|
|
short d = s ? atoi(s) : 0;
|
|
|
|
#ifdef DBG
|
|
if (d == 0 || d < -1 || d > 1000)
|
|
{
|
|
yesnofatal_box("Identificatore non valido nel campo %d: '%s'", dlg(), s);
|
|
d = -1;
|
|
}
|
|
#endif
|
|
|
|
return d;
|
|
}
|
|
|
|
void TMask_field::construct(short id, const char* prompt, int x, int y,
|
|
int len, WINDOW parent, const char* flags, int width)
|
|
{
|
|
_x = x; _y = y;
|
|
_prompt = prompt;
|
|
_size = len;
|
|
if (class_id() == CLASS_REAL_FIELD)
|
|
{
|
|
((TReal_field*)this)->set_decimals(width);
|
|
_width = _size;
|
|
}
|
|
else _width = width < 1 ? _size : width;
|
|
_dlg = id;
|
|
_flags.update(flags);
|
|
|
|
create(parent);
|
|
}
|
|
|
|
|
|
void TMask_field::construct(TScanner& scanner, WINDOW parent)
|
|
{
|
|
_dlg = atodlg(scanner.pop());
|
|
parse_head(scanner);
|
|
_prompt.cut(0);
|
|
|
|
scanner.popkey(); // BEGIN
|
|
#ifdef DBG
|
|
if (scanner.key() != "BE")
|
|
{
|
|
yesnofatal_box("Testata errata o BEGIN mancante nel campo %d", _dlg);
|
|
scanner.push();
|
|
}
|
|
#endif
|
|
|
|
while(scanner.popkey() != "EN") // END of control
|
|
parse_item(scanner);
|
|
create(parent);
|
|
}
|
|
|
|
bool TMask_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "PR") // PROMPT
|
|
{
|
|
_x = scanner.integer();
|
|
_y = scanner.integer();
|
|
_prompt = scanner.string();
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "FL") // FLAG
|
|
{
|
|
const char* f = scanner.string();
|
|
return _flags.update(f) == '\0';
|
|
}
|
|
|
|
if (scanner.key() == "FI") // FIELD
|
|
{
|
|
CHECKD(_field == NULL, "Only one FIELD, please: ", dlg());
|
|
_field = new TFieldref(scanner.line(), 0);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "HE") // HELP
|
|
{
|
|
_help = scanner.string();
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "KE") // KEY
|
|
{
|
|
_keys.set(scanner.line());
|
|
_keys.set(0L);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "ME")
|
|
{
|
|
if (_message.objptr(0) == 0)
|
|
_message.add(new TToken_string(64), 0);
|
|
TToken_string& ts = (TToken_string&)_message[0];
|
|
ts.add(scanner.line().strip_spaces());
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "GR")
|
|
{
|
|
_groups.set(scanner.line());
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
long TMask_field::default_flags() const
|
|
{
|
|
long f = CTL_FLAG_NATIVE_JUST;
|
|
|
|
if (_flags.show_default == FALSE) f |= CTL_FLAG_INVISIBLE;
|
|
if (_flags.enable_default == FALSE) f |= CTL_FLAG_DISABLED;
|
|
|
|
return f;
|
|
}
|
|
|
|
// Certified 100%
|
|
WINDOW TMask_field::wincreate(WIN_TYPE ct, short dx, short dy,
|
|
const char* title, WINDOW parent,
|
|
long flags)
|
|
{
|
|
_win = xvt_create_control(ct,
|
|
_x, _y, dx, dy,
|
|
(char*)title,
|
|
parent,
|
|
flags | default_flags(),
|
|
PTR_LONG(this),
|
|
_dlg);
|
|
|
|
return _win;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
WINDOW TMask_field::parent() const
|
|
{ return get_parent(win()); }
|
|
|
|
|
|
// Certified 90%
|
|
int TMask_field::create_prompt(WINDOW parent, int width, int heigth)
|
|
{
|
|
const WIN_TYPE wt = (heigth < 3) ? WC_TEXT : WC_GROUPBOX;
|
|
if (width < 1) width = strlen(_prompt);
|
|
_prompt.rtrim(); // Could save some bytes
|
|
|
|
if (width)
|
|
{
|
|
// Static controls shouldn't be grayed
|
|
const long flags = default_flags() & (~CTL_FLAG_DISABLED);
|
|
#if XVT_OS == XVT_OS_WIN
|
|
char* k = strchr(_prompt, '~');
|
|
if (k != NULL) *k = '&';
|
|
#endif
|
|
_promptwin = xvt_create_control
|
|
(
|
|
wt,
|
|
_x, _y, width, heigth,
|
|
_prompt,
|
|
parent,
|
|
flags,
|
|
0L,
|
|
-1
|
|
);
|
|
}
|
|
return width;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::destroy()
|
|
{
|
|
if (_win)
|
|
{ close_window(_win); _win = NULL_WIN; }
|
|
if (_promptwin)
|
|
{ close_window(_promptwin); _promptwin = NULL_WIN; }
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::create(WINDOW parent)
|
|
{
|
|
_width = strlen(_prompt);
|
|
if (_width)
|
|
wincreate(WC_TEXT, _width, 1, _prompt, parent, CTL_FLAG_LEFT_JUST);
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::enable(bool on)
|
|
{
|
|
const word c = class_id();
|
|
if (c != CLASS_FIELD)
|
|
{
|
|
enable_window(_win, on);
|
|
_flags.enabled = on;
|
|
}
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::enable_default()
|
|
{
|
|
const bool ed = _flags.enable_default;
|
|
enable(ed);
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::show(bool on)
|
|
{
|
|
show_window(_win, on);
|
|
if (_promptwin != NULL_WIN)
|
|
show_window(_promptwin, on);
|
|
_flags.showed = on;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::show_default()
|
|
{
|
|
const bool sd = _flags.show_default;
|
|
show(sd);
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
bool TMask_field::active() const
|
|
{
|
|
return enabled() && showed() && class_id() != CLASS_FIELD;
|
|
};
|
|
|
|
|
|
// Certified 90%
|
|
word TMask_field::last_key() const
|
|
{
|
|
long u = _keys.last_one();
|
|
if (u < 0) u = 0;
|
|
return (word)u;
|
|
}
|
|
|
|
|
|
// Certified 99%
|
|
const char* TMask_field::get_window_data() const
|
|
{
|
|
get_title(win(), __fpark, MAXSTR);
|
|
return __fpark;
|
|
}
|
|
|
|
|
|
// Certified 99%
|
|
void TMask_field::set_window_data(const char* data)
|
|
{
|
|
if (data != NULL)
|
|
set_title(win(), (char*)data);
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::set_field_data(const char*)
|
|
{}
|
|
|
|
|
|
// Certified 100%
|
|
const char* TMask_field::get_field_data() const
|
|
{ return NULL; }
|
|
|
|
|
|
const char* TMask_field::picture_data(const char* data, bool video)
|
|
{
|
|
fpark = data;
|
|
if (video) fpark.trim();
|
|
return fpark;
|
|
}
|
|
|
|
|
|
// Certified 90%
|
|
const char* TMask_field::prompt() const
|
|
{
|
|
if (_promptwin != NULL_WIN)
|
|
_prompt = xvt_get_title(_promptwin);
|
|
else
|
|
_prompt = "";
|
|
|
|
return _prompt;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::reset()
|
|
{
|
|
if (!_flags.persistent && class_id() != CLASS_FIELD)
|
|
set("");
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TMask_field::set_prompt(const char* p)
|
|
{
|
|
if (_promptwin != NULL_WIN)
|
|
set_title(_promptwin, (char*) p);
|
|
}
|
|
|
|
|
|
void TMask_field::set(const char* s)
|
|
{
|
|
if (mask().is_running())
|
|
{
|
|
set_window_data(s);
|
|
set_dirty();
|
|
}
|
|
else
|
|
set_field_data(s);
|
|
}
|
|
|
|
TString& TMask_field::get() const
|
|
{
|
|
static TString80 gpark;
|
|
|
|
if (mask().is_running())
|
|
gpark = get_window_data();
|
|
else
|
|
gpark = get_field_data();
|
|
|
|
return gpark.trim();
|
|
}
|
|
|
|
|
|
void TMask_field::undo()
|
|
{
|
|
set_window_data(get_field_data());
|
|
}
|
|
|
|
|
|
bool TMask_field::autoload(const TRelation* r)
|
|
{
|
|
if (_field)
|
|
{
|
|
set(_field->read(r));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
bool TMask_field::autosave(TRelation* r) const
|
|
{
|
|
if (_field)
|
|
{
|
|
_field->write(get(), r);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Certified 50%
|
|
HIDDEN void modify_list(bool add, TMask_field& f, TToken_string& msg)
|
|
{
|
|
#ifdef DBG
|
|
if (f.class_id() != CLASS_LIST_FIELD)
|
|
{
|
|
error_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 90%
|
|
HIDDEN const char* copy_value(TToken_string& msg, const TString& val)
|
|
{
|
|
int from = msg.get_int()-1;
|
|
int to = 0;
|
|
if (from < 0) from = 0;
|
|
else to = msg.get_int();
|
|
return val.sub(from, to);
|
|
}
|
|
|
|
|
|
// Certified 50%
|
|
bool TMask_field::do_message(int num)
|
|
{
|
|
TToken_string* message = (TToken_string*)_message.objptr(num);
|
|
if (message == NULL || message->empty()) return FALSE;
|
|
|
|
TToken_string msg(16, ',');
|
|
TString value(16);
|
|
|
|
for (const char* m = message->get(0); m && *m; m = message->get())
|
|
{
|
|
KEY key = 0;
|
|
msg = m;
|
|
value = msg.get();
|
|
value.trim();
|
|
const char* dlg = msg.get();
|
|
|
|
if (value == "EXIT")
|
|
{
|
|
mask().stop_run(atoi(dlg));
|
|
continue;
|
|
}
|
|
|
|
short fld = (dlg && dlg[0] > ' ') ? atodlg(dlg) : 0;
|
|
bool broadcast = dlg && strchr(dlg, '@');
|
|
if (value[0] == '"') value = value.strip("\"'");
|
|
else
|
|
{
|
|
if (value == "CO") value = copy_value(msg, get()); else
|
|
if (value == "CLEAR") key = 11000+'c'; else
|
|
if (value == "DISABLE") key = 11000+'d'; else
|
|
if (value == "ENABLE") key = 11000+'e'; else
|
|
if (value == "SHOW") key = 11000+'s'; else
|
|
if (value == "HIDE") key = 11000+'h'; else
|
|
if (value == "ENABLEDEF")key = 11000+'E'; else
|
|
if (value == "PUSH") key = K_SPACE; else
|
|
if (value == "RESET") key = K_F2; else
|
|
if (value == "UNDO") key = K_F3; else
|
|
if (value == "ADD") { modify_list(TRUE, mask().field(fld), msg); continue; } else
|
|
if (value == "DEL") { modify_list(FALSE, mask().field(fld), msg); continue; }
|
|
else key = atoi(value);
|
|
}
|
|
|
|
if (key)
|
|
{
|
|
if (key > 0)
|
|
{
|
|
if (broadcast) fld = -fld;
|
|
mask().send_key(key, fld);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Setta a value il campo fld solo se ha un valore diverso da value
|
|
if (broadcast)
|
|
{
|
|
for (int i = 0; i < mask().fields(); i++)
|
|
{
|
|
TMask_field& f = mask().fld(i);
|
|
if (f.in_group((int)fld))
|
|
{
|
|
const char* prev = f.get();
|
|
if (value != prev)
|
|
{
|
|
f.set(value);
|
|
if (f.showed() || 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.showed())
|
|
f.on_hit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Certified 90%
|
|
bool TMask_field::on_hit()
|
|
{
|
|
if (_handler)
|
|
{
|
|
bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE);
|
|
if (!ok) return FALSE;
|
|
}
|
|
do_message(0);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
bool TMask_field::to_check(KEY k, bool checkrun) const
|
|
{
|
|
bool yes = (k == K_TAB && focusdirty()) || (k == K_ENTER && dirty());
|
|
|
|
if (!yes && checkrun)
|
|
yes = k == K_TAB && !mask().is_running();
|
|
|
|
return yes;
|
|
}
|
|
|
|
// Certified 90%
|
|
bool TMask_field::on_key(KEY key)
|
|
{
|
|
if (key > 11000)
|
|
{
|
|
switch(key-11000)
|
|
{
|
|
case 'E':enable_default(); break;
|
|
case 'c':reset(); on_hit();
|
|
case 'd':disable(); break;
|
|
case 'e':enable(); break;
|
|
case 'h':hide(); break;
|
|
case 's':show(); break;
|
|
#ifdef DBG
|
|
default :return yesnofatal_box("Invalid key sent to field %d: %d", dlg(), key);
|
|
#endif
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
switch(key)
|
|
{
|
|
case K_SPACE:
|
|
set_dirty();
|
|
break;
|
|
case K_PREV:
|
|
case K_NEXT:
|
|
dispatch_e_char(parent(), key);
|
|
break;
|
|
case K_F1:
|
|
if (_help.not_empty())
|
|
message_box(_help);
|
|
else
|
|
beep();
|
|
break;
|
|
case K_F2:
|
|
reset();
|
|
set_dirty();
|
|
break;
|
|
case K_F3:
|
|
undo();
|
|
set_dirty();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (_handler)
|
|
return _handler(*this, key);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void TMask_field::set_focus() const
|
|
{
|
|
const bool force = mask().is_running();
|
|
mask().set_focus_win(win(), force);
|
|
}
|
|
|
|
HIDDEN char* const _msg = &__tmp_string[512];
|
|
#define build_msg() va_list argptr;va_start(argptr,fmt);vsprintf(_msg,fmt,argptr);va_end(argptr)
|
|
|
|
bool TMask_field::error_box(const char* fmt, ...) const
|
|
{
|
|
set_focus();
|
|
build_msg();
|
|
::error_box("%s", _msg);
|
|
set_focus();
|
|
return FALSE;
|
|
}
|
|
|
|
bool TMask_field::message_box(const char* fmt, ...) const
|
|
{
|
|
set_focus();
|
|
build_msg();
|
|
::message_box("%s", _msg);
|
|
set_focus();
|
|
return FALSE;
|
|
}
|
|
|
|
bool TMask_field::warning_box(const char* fmt, ...) const
|
|
{
|
|
set_focus();
|
|
build_msg();
|
|
::warning_box("%s", _msg);
|
|
set_focus();
|
|
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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TList_sheet
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TList_sheet
|
|
{
|
|
TEdit_field* _fld; // The field owning the sheet
|
|
TArray_sheet _sheet; // sheet with data;
|
|
int _row;
|
|
|
|
TToken_string _inp_id;
|
|
TToken_string _out_id;
|
|
|
|
protected:
|
|
int do_input();
|
|
void do_output(CheckTime = RUNNING_CHECK);
|
|
bool do_insert();
|
|
TMask_field& field(short id) const;
|
|
|
|
public:
|
|
TList_sheet(TEdit_field* f, const char* caption, const char* head);
|
|
~TList_sheet() {}
|
|
|
|
void parse_input(TScanner& scanner);
|
|
void read_item(TScanner& scanner);
|
|
void parse_output(TScanner& scanner);
|
|
|
|
TEdit_field& field() const { return *_fld; }
|
|
|
|
bool check(CheckTime = RUNNING_CHECK);
|
|
|
|
KEY run();
|
|
};
|
|
|
|
|
|
// Certified 100%
|
|
TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
|
|
: _fld(f), _sheet(-1, -1, 0, 0, caption, head), _row(-1)
|
|
{}
|
|
|
|
|
|
// Certified 100%
|
|
TMask_field& TList_sheet::field(short id) const
|
|
{ return field().mask().field(id); }
|
|
|
|
|
|
// Certified 100%
|
|
void TList_sheet::read_item(TScanner& scanner)
|
|
{
|
|
TToken_string ts(scanner.string());
|
|
_sheet.add(ts);
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
void TList_sheet::parse_input(TScanner& scanner)
|
|
{
|
|
_inp_id.add(scanner.pop());
|
|
}
|
|
|
|
|
|
// 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()) return -1;
|
|
|
|
_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 = _fld->atodlg(fld);
|
|
if (id > 0) rowsel.add(field().mask().get(id));
|
|
else rowsel.add("");
|
|
}
|
|
}
|
|
|
|
TString fd(16), it(16);
|
|
for (int i = 0 ; i < _sheet.items(); i++)
|
|
{
|
|
TToken_string& ts =_sheet.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;
|
|
}
|
|
|
|
|
|
// Certified 50%
|
|
void TList_sheet::do_output(CheckTime t)
|
|
{
|
|
if (_row == -1 || t == FINAL_CHECK)
|
|
return;
|
|
|
|
_out_id.restart();
|
|
TToken_string& rowsel = _sheet.row(_row);
|
|
rowsel.restart();
|
|
for (const char* fld = _out_id.get(); fld; fld = _out_id.get())
|
|
{
|
|
const short id = _fld->atodlg(fld);
|
|
if (t != STARTING_CHECK || field().field() == NULL)
|
|
{
|
|
TMask_field& f = field(id);
|
|
f.set(rowsel.get());
|
|
if (field().dlg() != id)
|
|
f.on_hit();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
KEY TList_sheet::run()
|
|
{
|
|
_row = do_input();
|
|
|
|
_sheet.select(_row);
|
|
|
|
const KEY k = _sheet.run();
|
|
|
|
switch (k)
|
|
{
|
|
case K_ENTER:
|
|
_row = (int)_sheet.selected();
|
|
do_output();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return k;
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
bool TList_sheet::check(CheckTime t)
|
|
{
|
|
const bool passed = (_row = do_input()) != -1;
|
|
if (passed) do_output(t);
|
|
return passed;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TBrowse
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Certified 100%
|
|
TBrowse::TBrowse(TEdit_field* f, TRelation* r, int key, const char* filter)
|
|
: _relation(r), _cursor(new TCursor (r, filter, key)),
|
|
_fld(f), _filter(filter), _secondary(FALSE),
|
|
_checked(FALSE)
|
|
{}
|
|
|
|
|
|
// Certified 100%
|
|
TBrowse::TBrowse(TEdit_field* f, TCursor* c)
|
|
: _relation(NULL), _cursor(c), _fld(f)
|
|
{}
|
|
|
|
|
|
// Certified 100%
|
|
TBrowse::~TBrowse()
|
|
{
|
|
if (_relation)
|
|
{
|
|
delete _relation;
|
|
delete _cursor;
|
|
}
|
|
}
|
|
|
|
|
|
// 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();
|
|
_inp_id.add(scanner.line());
|
|
}
|
|
else // Field on the mask
|
|
{
|
|
TString80 str(s);
|
|
if (scanner.popkey() == "SE") str << '@'; // Special FILTERing field
|
|
else scanner.push();
|
|
_inp_id.add(str);
|
|
}
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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 (!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 = TRUE;
|
|
}
|
|
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();
|
|
|
|
byte 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)
|
|
{
|
|
if (scanner.popkey() == "RU")
|
|
{
|
|
_insert = "R";
|
|
_insert << scanner.line();
|
|
}
|
|
else
|
|
{
|
|
_insert = "M";
|
|
_insert << scanner.line();
|
|
}
|
|
_insert.trim();
|
|
}
|
|
|
|
|
|
// Certified 100%
|
|
TMask_field& TBrowse::field(short n) const
|
|
{ return _fld->mask().field(n); }
|
|
|
|
// Ritorna il numero di campi non vuoti e non filtrati
|
|
int TBrowse::do_input(bool filter)
|
|
{
|
|
int ne = 0;
|
|
if (_inp_id.empty()) return ne;
|
|
|
|
TRectype& cur = _cursor->curr();
|
|
|
|
cur.zero();
|
|
TRectype filtrec(cur);
|
|
|
|
_inp_id.restart();
|
|
_inp_fn.restart();
|
|
|
|
TString80 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 = _fld->atodlg(fld);
|
|
const bool filter_flag = strchr(fld, '@') != NULL;
|
|
tofilter = filter && filter_flag;
|
|
val = field(id).get();
|
|
if (field(id).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());
|
|
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];
|
|
}
|
|
|
|
const char* w = work.empty() ? NULL : (const char*) work;
|
|
|
|
if (filtrec.empty()) _cursor->filter(w);
|
|
else _cursor->filter(w, &filtrec, &filtrec);
|
|
|
|
return ne;
|
|
}
|
|
|
|
|
|
void TBrowse::do_output(CheckTime t)
|
|
{
|
|
if (t == FINAL_CHECK)
|
|
return;
|
|
|
|
TString80 sum;
|
|
TToken_string flds(24, '+');
|
|
|
|
_out_fn.restart();
|
|
for (const char* 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(); fr; fr = flds.get())
|
|
{
|
|
TFieldref fld(fr, 0);
|
|
const char* val = fld.read(_cursor->relation());
|
|
sum << val;
|
|
}
|
|
|
|
f.set(sum);
|
|
if (field().dlg() != id)
|
|
f.on_hit();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void TBrowse::do_clear()
|
|
{
|
|
for (TString16 fld = _out_id.get(0); fld.not_empty(); fld = _out_id.get())
|
|
{
|
|
TMask_field& f = field(atoi(fld));
|
|
if (f.field() == NULL && _inp_id.get_pos(fld) < 0)
|
|
f.reset();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool TBrowse::do_insert()
|
|
{
|
|
bool ok = FALSE;
|
|
TString app;
|
|
|
|
if (_insert[0] == 'M')
|
|
{
|
|
TString nm(_insert.mid(1));
|
|
if (strncmp(nm, "BATB", 4) == 0) // Programma gestione tabelle
|
|
app = format("ba3 -0 %s", (const char*)nm.mid(4));
|
|
else // Programma generico di browse/edit
|
|
app = format("ba3 -3 %s %d", (const char*)nm, _cursor->file()->num());
|
|
}
|
|
else
|
|
{
|
|
app = _insert.mid(1);
|
|
#if XVT_OS == XVT_OS_WIN
|
|
app.insert("a", 3);
|
|
#endif
|
|
}
|
|
|
|
TMailbox mail;
|
|
TMessage msg(cmd2name(app), MSG_AI, "");
|
|
mail.send(msg);
|
|
|
|
TExternal_app a(app);
|
|
a.run();
|
|
|
|
if (mail.check())
|
|
{
|
|
TMessage* rcv = mail.next_s(MSG_AI);
|
|
if (rcv != NULL) _rec = atoi(rcv->body());
|
|
if (_rec > 0)
|
|
{
|
|
_cursor->file()->readat(_rec);
|
|
ok = _cursor->ok();
|
|
if (ok) do_output();
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
TToken_string& TBrowse::create_siblings(TToken_string& siblings)
|
|
{
|
|
const TMask& mask = field().mask();
|
|
TBit_array key(4); // Elenco delle chiavi gia' utilizzate
|
|
|
|
siblings = ""; // Azzera la lista dei campi associati
|
|
|
|
// 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 = atoi(i);
|
|
const TMask_field& f = mask.field(id);
|
|
if (!f.showed() || !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 (improbabile)
|
|
|
|
const TCursor* c = b->cursor();
|
|
|
|
// Considera ricerche sullo stesso file ma con chiave diversa
|
|
if (c && c->file()->num() == _cursor->file()->num() &&
|
|
key[c->key()] == FALSE)
|
|
{
|
|
const TString16 fn(_out_fn.get(n)); // Legge nome del campo su file
|
|
const int pos = _items.get_pos(fn); // Determina header corrispondente
|
|
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()
|
|
{
|
|
do_input(TRUE);
|
|
_cursor->read();
|
|
|
|
const char* caption = field().prompt();
|
|
if (!isalnum(*caption)) caption = "Selezione";
|
|
|
|
KEY k = K_ESC;
|
|
long selected = 0;
|
|
|
|
TToken_string siblings; create_siblings(siblings);
|
|
|
|
{
|
|
TToken_string* sib = siblings.empty() ? NULL : &siblings;
|
|
const byte buttons = _insert.empty() ? 0 : 1;
|
|
TBrowse_sheet s(_cursor, _items, caption, _head, buttons, _fld, sib);
|
|
k = s.run();
|
|
selected = s.selected();
|
|
}
|
|
|
|
switch (k)
|
|
{
|
|
case K_INS:
|
|
k = do_insert() ? K_ENTER : K_ESC;
|
|
break;
|
|
case K_ENTER:
|
|
*_cursor = selected;
|
|
do_output();
|
|
break;
|
|
default:
|
|
if (k >= K_CTRL)
|
|
{
|
|
const short id = siblings.get_int((k - K_CTRL) << 1);
|
|
TEdit_field& ef = (TEdit_field&)_fld->mask().field(id);
|
|
if (ef.mask().is_running()) ef.set_focus();
|
|
else ef.mask().first_focus(-ef.dlg());
|
|
ef.mask().send_key(k = K_F9, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return k;
|
|
}
|
|
|
|
bool TBrowse::check(CheckTime t)
|
|
{
|
|
bool passed = TRUE;
|
|
|
|
if (_secondary && t != RUNNING_CHECK)
|
|
return TRUE;
|
|
// if (_checked && t == FINAL_CHECK)
|
|
// return TRUE;
|
|
// _checked = TRUE;
|
|
if (_fld->check_type() != CHECK_NONE)
|
|
{
|
|
const TMaskmode mode = (TMaskmode)field().mask().mode();
|
|
|
|
CheckType chk = _fld->check_type();
|
|
const int ne = do_input(TRUE);
|
|
if (t == STARTING_CHECK || mode == MODE_QUERY) chk = CHECK_NORMAL;
|
|
if (ne || chk == CHECK_REQUIRED)
|
|
{
|
|
_cursor->setkey();
|
|
_cursor->file()->read(_isequal);
|
|
passed = _cursor->ok();
|
|
|
|
if (t != FINAL_CHECK)
|
|
{
|
|
if (passed)
|
|
{
|
|
_cursor->repos();
|
|
do_output(t);
|
|
}
|
|
else do_clear();
|
|
}
|
|
if (mode == MODE_SEARCH) return TRUE;
|
|
}
|
|
else
|
|
if (t != FINAL_CHECK) do_clear();
|
|
}
|
|
// _checked = passed;
|
|
return passed;
|
|
}
|
|
|
|
bool TBrowse::empty_check()
|
|
{
|
|
const TMaskmode mode = (TMaskmode)field().mask().mode();
|
|
const bool no_check = mode == MODE_SEARCH || field().mask().query_mode();
|
|
|
|
if ( no_check || _fld->check_type() == CHECK_NONE ||
|
|
_fld->check_type() == CHECK_NORMAL)
|
|
return TRUE;
|
|
else
|
|
return do_input() > 0;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TEdit_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TEdit_field::TEdit_field(TMask* mask)
|
|
: TMask_field(mask), _browse(NULL), _sheet(NULL),
|
|
_buttonwin(NULL_WIN), _check(CHECK_NONE), _check_enabled(TRUE),
|
|
_forced(FALSE)
|
|
{}
|
|
|
|
TEdit_field::~TEdit_field()
|
|
{
|
|
if (_browse) delete _browse; else
|
|
if (_sheet) delete _sheet;
|
|
}
|
|
|
|
word TEdit_field::class_id() const
|
|
{ return CLASS_EDIT_FIELD; }
|
|
|
|
|
|
void TEdit_field::enable(bool on)
|
|
{
|
|
TMask_field::enable(on);
|
|
if (_buttonwin != NULL_WIN)
|
|
show_window(_buttonwin, on && _check_enabled && showed());
|
|
}
|
|
|
|
void TEdit_field::show(bool on)
|
|
{
|
|
TMask_field::show(on);
|
|
if (_buttonwin != NULL_WIN)
|
|
show_window(_buttonwin, on && _check_enabled && enabled());
|
|
}
|
|
|
|
|
|
void TEdit_field::parse_head(TScanner& scanner)
|
|
{
|
|
_size = scanner.integer();
|
|
if (_size < 1)
|
|
{
|
|
_size = 8;
|
|
error_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size);
|
|
}
|
|
|
|
_width = scanner.integer();
|
|
if (_width == 0) _width = _size;
|
|
}
|
|
|
|
|
|
const TBrowse* TEdit_field::get_browse(TScanner& scanner) const
|
|
{
|
|
const int id = scanner.integer();
|
|
TMask_field& m = mask().field(id);
|
|
if (!m.is_edit())
|
|
{
|
|
error_box("Il campo %d non puo' fare una COPY del campo %d",
|
|
dlg(), id);
|
|
return NULL;
|
|
}
|
|
|
|
TEdit_field& f = (TEdit_field&)m ;
|
|
TBrowse* b = (TBrowse*) f.browse();
|
|
if (b == NULL)
|
|
error_box("La USE del campo %d non puo' essere copiata da %d",
|
|
id, dlg());
|
|
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 _check = CHECK_NONE;
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "US") // USE
|
|
{
|
|
if (_browse != NULL)
|
|
return error_box("USE duplicata nel campo %d", dlg());
|
|
|
|
int key = 1;
|
|
TRelation* r;
|
|
|
|
const int logicnum = scanner.integer();
|
|
TString16 tabmaskname;
|
|
|
|
if (logicnum > 0)
|
|
r = new TRelation(logicnum);
|
|
else
|
|
{
|
|
tabmaskname = scanner.pop();
|
|
if (tabmaskname.len() > 4)
|
|
return error_box("'%s' non e' una tabella valida: %d",
|
|
(const char*)tabmaskname, dlg());
|
|
r = new TRelation(tabmaskname);
|
|
}
|
|
|
|
if (scanner.popkey() == "KE")
|
|
{
|
|
key = scanner.integer();
|
|
if (key < 1)
|
|
{
|
|
error_box("Chiave %d non valida nella USE del campo %d", key, dlg());
|
|
key = 1;
|
|
}
|
|
}
|
|
else scanner.push();
|
|
|
|
const char* filter = "";
|
|
if (scanner.popkey() == "SE")
|
|
filter = (const char*)scanner.line();
|
|
else
|
|
scanner.push();
|
|
|
|
_browse = new TBrowse(this, r, key, filter);
|
|
|
|
if (tabmaskname.not_empty())
|
|
{
|
|
if (strncmp(MainApp()->name(), "ba3", 3) != 0)
|
|
{
|
|
tabmaskname.insert("MBATB", 0);
|
|
_browse->set_insert(tabmaskname);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "CO") // Copyuse
|
|
{
|
|
const TString16 what(scanner.popkey());
|
|
|
|
const TBrowse* b = get_browse(scanner);
|
|
#ifdef DBG
|
|
if (b == NULL)
|
|
return yesnofatal_box("Impossibile COPYare la browse nel campo %d", dlg());
|
|
#endif
|
|
if (what == "US" || what == "AL")
|
|
_browse = new TBrowse(this, b->cursor());
|
|
|
|
if (_browse)
|
|
return _browse->parse_copy(what, b);
|
|
|
|
#ifdef DBG
|
|
return yesnofatal_box("Impossibile COPY senza USE nel campo %d", dlg());
|
|
#endif
|
|
}
|
|
|
|
if (scanner.key() == "JO")
|
|
{
|
|
#ifdef DBG
|
|
if(!_browse) return yesnofatal_box("JOIN senza USE nel campo %d", dlg());
|
|
#endif
|
|
_browse->parse_join(scanner);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "SH") // SHEET
|
|
{
|
|
if (_sheet) return error_box("SHEET duplicato nel campo %d", dlg());
|
|
_sheet = new TList_sheet(this, _prompt, scanner.string());
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "IT") // ITEM
|
|
{
|
|
if (_sheet == NULL)
|
|
return error_box("ITEM senza SHEET nel campo %d", dlg());
|
|
_sheet->read_item(scanner);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "IN")
|
|
{
|
|
if (_browse) _browse->parse_input(scanner); else
|
|
if (_sheet) _sheet->parse_input(scanner);
|
|
else error_box("INPUT senza USE o SHEET nel campo %d", dlg());
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "DI")
|
|
{
|
|
if(!_browse)
|
|
return error_box("DISPLAY senza USE nel campo %d", dlg());
|
|
_browse->parse_display(scanner);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "OU")
|
|
{
|
|
if (_browse) _browse->parse_output(scanner);
|
|
else if (_sheet) _sheet->parse_output(scanner);
|
|
else return error_box("OUTPUT senza USE nel campo %d", dlg());
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "AD")
|
|
{
|
|
if(!_browse) return error_box("ADD senza USE nel campo %d", dlg());
|
|
_browse->parse_insert(scanner);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "VA")
|
|
{
|
|
const char* n = scanner.pop();
|
|
_validate_func = isdigit(*n) ? atoi(n) : -1;
|
|
if (_validate_func < 0)
|
|
return yesnofatal_box("Funzione di validazione '%s' errata nel campo %d", n, dlg());
|
|
|
|
const int _nparms = scanner.integer();
|
|
if (_nparms < 0)
|
|
return yesnofatal_box("Numero di parametri VALIDATE errato nel campo %d", dlg());
|
|
|
|
for(int i = 0; i < _nparms; i++)
|
|
_validate_parms.add(scanner.operand());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "WA")
|
|
{
|
|
_warning = scanner.string();
|
|
return TRUE;
|
|
}
|
|
if (scanner.key() == "ME")
|
|
{
|
|
TFixed_string l(scanner.line().strip_spaces());
|
|
int m = 0;
|
|
if (l[0] == '0')
|
|
{
|
|
l.ltrim(1);
|
|
l.ltrim();
|
|
m = 1;
|
|
}
|
|
if (_message.objptr(m) == 0)
|
|
_message.add(new TToken_string(64), m);
|
|
TToken_string& ts = (TToken_string&)_message[m];
|
|
ts.add(l);
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
|
|
void TEdit_field::create(WINDOW parent)
|
|
{
|
|
const int len = create_prompt(parent);
|
|
|
|
long align = _flags.rightjust ? CTL_FLAG_RIGHT_JUST : CTL_FLAG_LEFT_JUST;
|
|
_x += len;
|
|
|
|
#if XVTWS == WMWS
|
|
const int delta = 2;
|
|
#else
|
|
const int delta = 1;
|
|
#endif
|
|
|
|
wincreate(WC_EDIT, _width+delta, 1, _str, parent, align);
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
HWND hwnd = (HWND)get_value(win(), ATTR_NATIVE_WINDOW);
|
|
SendMessage(hwnd, EM_LIMITTEXT, _size, 0L); // Limita il testo
|
|
long style = GetWindowLong(hwnd, GWL_STYLE);
|
|
if (_flags.uppercase) style != ES_UPPERCASE; // Edit in maiuscolo
|
|
SetWindowLong(hwnd, GWL_STYLE, style);
|
|
#endif
|
|
|
|
if (_browse || _sheet)
|
|
{
|
|
long flags = default_flags();
|
|
if (flags & CTL_FLAG_DISABLED)
|
|
{
|
|
flags &= ~CTL_FLAG_DISABLED;
|
|
flags |= CTL_FLAG_INVISIBLE;
|
|
}
|
|
_buttonwin = xvt_create_control(WC_PUSHBUTTON, _x+_width+delta, _y,
|
|
2, 1, "*", parent, flags, PTR_LONG(this), DLG_F9);
|
|
}
|
|
}
|
|
|
|
void TEdit_field::destroy()
|
|
{
|
|
if (_buttonwin)
|
|
{ close_window(_buttonwin); _buttonwin = NULL_WIN; }
|
|
TMask_field::destroy();
|
|
}
|
|
|
|
|
|
void TEdit_field::set_window_data(const char* data)
|
|
{
|
|
TMask_field::set_window_data(format(data));
|
|
}
|
|
|
|
|
|
void TEdit_field::set_field_data(const char* data)
|
|
{ _str = data; }
|
|
|
|
const char* TEdit_field::get_field_data() const
|
|
{ return _str; }
|
|
|
|
|
|
const char* TEdit_field::format(const char* d)
|
|
{
|
|
fpark = d;
|
|
fpark.trim();
|
|
|
|
if (fpark.not_empty())
|
|
{
|
|
#ifdef DBG
|
|
if (fpark.len() > _size)
|
|
{
|
|
error_box("Campo %d troppo lungo: %d > %d", dlg(), fpark.len(), _size);
|
|
fpark.cut(_size);
|
|
}
|
|
#endif
|
|
|
|
if (_flags.uppercase)
|
|
fpark.upper();
|
|
|
|
if (_flags.zerofilled)
|
|
fpark.right_just(_size, '0');
|
|
else
|
|
if (_flags.rightjust)
|
|
fpark.right_just(_size);
|
|
}
|
|
|
|
return fpark;
|
|
}
|
|
|
|
|
|
const char* TEdit_field::picture_data(const char* data, bool video)
|
|
{
|
|
if (video)
|
|
{
|
|
set_title(win(), (char*)data);
|
|
return get_window_data();
|
|
}
|
|
|
|
set_window_data(data);
|
|
TMask_field::get_window_data();
|
|
fpark.trim();
|
|
return fpark;
|
|
}
|
|
|
|
|
|
bool TEdit_field::validate(KEY k)
|
|
{
|
|
return ::validate(_validate_func, *this, k, _validate_parms);
|
|
}
|
|
|
|
// Certified 90%
|
|
bool TEdit_field::on_hit()
|
|
{
|
|
if (_handler)
|
|
{
|
|
bool ok = _handler(*this, is_edit() ? K_TAB : K_SPACE);
|
|
if (!ok) return FALSE;
|
|
}
|
|
if (_message.objptr(1) && get() == "") do_message(1);
|
|
else do_message(0);
|
|
return TRUE;
|
|
}
|
|
|
|
bool TEdit_field::on_key(KEY key)
|
|
{
|
|
switch(key)
|
|
{
|
|
case K_TAB:
|
|
if (_validate_func == AUTOEXIT_FUNC || _validate_func == NUMCALC_FUNC ||
|
|
_validate_func == STRCALC_FUNC)
|
|
set_focusdirty();
|
|
if (to_check(K_TAB, TRUE))
|
|
{
|
|
set(get());
|
|
bool ok = validate(key); // Check validation expression
|
|
|
|
if (!ok)
|
|
{
|
|
if (_warning.not_empty()) error_box(_warning);
|
|
return FALSE;
|
|
}
|
|
|
|
TMask& m = mask();
|
|
const bool query = m.query_mode();
|
|
|
|
if (_sheet) ok = query || _sheet->check(); // Check consistency
|
|
else
|
|
if (check_enabled() && _browse && (!query || forced()))
|
|
ok = _browse->check(); // Check consistency
|
|
|
|
if (!ok)
|
|
{
|
|
if (_warning.not_empty()) error_box(_warning);
|
|
else error_box("Valore non consistente: %s", (const char*)get());
|
|
return FALSE;
|
|
}
|
|
|
|
ok = on_hit();
|
|
if (!ok)
|
|
return FALSE;
|
|
|
|
if (query && required() && in_key(0))
|
|
{
|
|
const byte keys = m.num_keys();
|
|
|
|
for (int i = 1; i <= keys; i++)
|
|
if (in_key(i) && m.key_valid(i))
|
|
{
|
|
for (int fld = m.get_key_field(i, TRUE); fld != -1; fld = m.get_key_field(i, FALSE))
|
|
m.field(fld).set_dirty(FALSE);
|
|
dispatch_e_char(get_parent(win()), K_SHIFT_ENTER);
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case K_ENTER:
|
|
if (field() != NULL || mask().mode() == NO_MODE)
|
|
{
|
|
if (focusdirty()) set(get());
|
|
|
|
bool ok = validate(K_ENTER); // Check validation expression
|
|
if (!ok)
|
|
{
|
|
if (_warning.not_empty()) error_box(_warning);
|
|
return FALSE;
|
|
}
|
|
|
|
const bool query = mask().query_mode();
|
|
|
|
// check consistency
|
|
if (_sheet) ok = query || _sheet->check(FINAL_CHECK);
|
|
else if (_browse && check_enabled())
|
|
{
|
|
if (!query || forced())
|
|
{
|
|
if (dirty()) ok = _browse->check(FINAL_CHECK); // Check consistency
|
|
else ok = _browse->empty_check();
|
|
}
|
|
}
|
|
else
|
|
ok = query || !(check_type() == CHECK_REQUIRED && get().empty());
|
|
|
|
if (!ok)
|
|
{
|
|
if (_warning.not_empty()) error_box(_warning);
|
|
else error_box("Campo non consistente: '%s'", (const char*)get());
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
case K_F9:
|
|
if (check_enabled())
|
|
{
|
|
if (dirty()) set(get());
|
|
KEY k = K_ESC;
|
|
if (_browse) k = _browse->run();
|
|
else if (_sheet) k = _sheet->run();
|
|
else beep();
|
|
if (mask().is_running() && k != K_F9) set_focus();
|
|
if (k == K_ENTER)
|
|
{
|
|
set_dirty();
|
|
if (mask().is_running())
|
|
mask().send_key(K_TAB, 0);
|
|
else
|
|
on_hit();
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TMask_field::on_key(key);
|
|
}
|
|
|
|
|
|
bool TEdit_field::has_check() const
|
|
{
|
|
if (_browse) return check_type() != CHECK_NONE;
|
|
return _sheet != NULL;
|
|
}
|
|
|
|
bool TEdit_field::check(CheckTime t)
|
|
{
|
|
if (check_enabled() || (t == STARTING_CHECK && showed()))
|
|
{
|
|
if (_browse) return _browse->check(t); else
|
|
if (_sheet) return _sheet->check(t);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TEdit_field::enable_check(bool on)
|
|
{
|
|
_check_enabled = on;
|
|
if (_buttonwin != NULL_WIN)
|
|
show_window(_buttonwin, on);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Boolean_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
TBoolean_field::TBoolean_field(TMask* m)
|
|
: TMask_field(m), _on(FALSE)
|
|
{}
|
|
|
|
|
|
word TBoolean_field::class_id() const
|
|
{ return CLASS_BOOLEAN_FIELD; }
|
|
|
|
|
|
void TBoolean_field::create(WINDOW parent)
|
|
{
|
|
wincreate(WC_CHECKBOX, strlen(_prompt)+4, 1, _prompt, parent, 0);
|
|
}
|
|
|
|
|
|
const char* TBoolean_field::get_window_data() const
|
|
{
|
|
CHECK(win(), "Control window not initialized");
|
|
fpark[0] = xvt_get_checked_state(win()) ? 'X' : ' ';
|
|
fpark[1] = '\0';
|
|
return fpark;
|
|
}
|
|
|
|
|
|
void TBoolean_field::set_window_data(const char* data)
|
|
{
|
|
CHECK(win(), "Control window not initialized");
|
|
|
|
if (data == NULL) data = "";
|
|
const bool b = toupper(*data) == 'X';
|
|
xvt_check_box(win(), b);
|
|
}
|
|
|
|
|
|
void TBoolean_field::set_field_data(const char* data)
|
|
{
|
|
if (data == NULL) data = "";
|
|
_on = toupper(*data) == 'X';
|
|
}
|
|
|
|
const char* TBoolean_field::get_field_data() const
|
|
{
|
|
return _on ? "X" : " ";
|
|
}
|
|
|
|
|
|
bool TBoolean_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "ME")
|
|
{
|
|
const bool tf = scanner.integer() ? TRUE : FALSE; // Message TRUE or FALSE
|
|
|
|
if (_message.items() == 0)
|
|
{
|
|
_message.add(new TToken_string(16));
|
|
_message.add(new TToken_string(16));
|
|
}
|
|
TToken_string& ts = (TToken_string&)_message[tf];
|
|
ts.add(scanner.line().strip_spaces());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
void TBoolean_field::enable(bool on)
|
|
{
|
|
_flags.enabled = on;
|
|
xvt_enable_control(_win, on);
|
|
}
|
|
|
|
|
|
bool TBoolean_field::on_hit()
|
|
{
|
|
if (_handler)
|
|
{
|
|
bool ok = _handler(*this, K_SPACE);
|
|
if (!ok) return FALSE;
|
|
}
|
|
const int n = mask().is_running() ? xvt_get_checked_state(win()) : _on;
|
|
do_message(n);
|
|
return TRUE;
|
|
}
|
|
|
|
bool TBoolean_field::on_key(KEY key)
|
|
{
|
|
if (key == K_SPACE)
|
|
{
|
|
on_hit();
|
|
set_dirty();
|
|
return TRUE;
|
|
}
|
|
return TMask_field::on_key(key);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Button_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TButton_field::TButton_field(TMask* m)
|
|
: TMask_field(m)
|
|
{
|
|
_flags.persistent = TRUE;
|
|
}
|
|
|
|
|
|
word TButton_field::class_id() const
|
|
{ return CLASS_BUTTON_FIELD; }
|
|
|
|
void TButton_field::parse_head(TScanner& scanner)
|
|
{
|
|
_width = scanner.integer();
|
|
if (_width < 1) _width = 9;
|
|
_size = scanner.integer(); // Height
|
|
if (_size < 1) _size = 1;
|
|
}
|
|
|
|
|
|
bool TButton_field::parse_item(TScanner& scanner)
|
|
{
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
|
|
void TButton_field::create(WINDOW parent)
|
|
{
|
|
long flags = CTL_FLAG_CENTER_JUST;
|
|
|
|
if (_prompt.empty()) switch (dlg())
|
|
{
|
|
case DLG_OK:
|
|
_prompt = "Conferma";
|
|
flags |= CTL_FLAG_DEFAULT;
|
|
break;
|
|
case DLG_CANCEL:
|
|
_prompt = "Annulla";
|
|
break;
|
|
case DLG_PGUP:
|
|
_prompt = "Pag <<"; break;
|
|
case DLG_PGDN:
|
|
_prompt = "Pag >>"; break;
|
|
case DLG_SAVEREC:
|
|
_prompt = "Registra"; break;
|
|
case DLG_QUIT:
|
|
_prompt = "Fine"; break;
|
|
default:
|
|
break;
|
|
}
|
|
#if XWTWS == WMWS
|
|
_prompt.center_just(_width);
|
|
#endif
|
|
wincreate(WC_PUSHBUTTON, _width + 2, _size, _prompt, parent, flags);
|
|
}
|
|
|
|
void TButton_field::enable(bool on)
|
|
{
|
|
_flags.enabled = on;
|
|
xvt_enable_control(_win, on);
|
|
}
|
|
|
|
void TButton_field::show(bool on)
|
|
{
|
|
TMask_field::show(on);
|
|
}
|
|
|
|
|
|
bool TButton_field::on_key(KEY key)
|
|
|
|
{
|
|
if (key == K_SPACE)
|
|
{
|
|
on_hit();
|
|
return TRUE;
|
|
}
|
|
return TMask_field::on_key(key);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Date_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
word TDate_field::class_id() const
|
|
{ return CLASS_DATE_FIELD; }
|
|
|
|
void TDate_field::create(WINDOW w)
|
|
{
|
|
TEdit_field::create(w);
|
|
if (automagic())
|
|
{
|
|
TDate d(TODAY);
|
|
set(d.string());
|
|
}
|
|
}
|
|
|
|
void TDate_field::parse_head(TScanner&) {}
|
|
|
|
TDate_field::TDate_field(TMask* m) : TEdit_field(m)
|
|
{
|
|
_size = _width = 10;
|
|
}
|
|
|
|
|
|
bool TDate_field::on_key(KEY key)
|
|
{
|
|
if (to_check(key))
|
|
{
|
|
TFixed_string data(get_window_data(), 15);
|
|
data.trim();
|
|
if (data.not_empty() || required())
|
|
{
|
|
bool changed = FALSE;
|
|
if (isdigit(data[0]))
|
|
{
|
|
if (data.len() == 6) // Fix century (for this millenium only)
|
|
{
|
|
data.insert("19", 4);
|
|
changed = TRUE;
|
|
}
|
|
for (int meno = 2; meno <= 5; meno += 3)
|
|
if (data[meno] != '-')
|
|
{
|
|
data.insert("-", meno);
|
|
changed = TRUE;
|
|
}
|
|
if (data.len() == 8) // Fix century (for this millenium only)
|
|
{
|
|
data.insert("19", 6);
|
|
changed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TDate g(TODAY);
|
|
data.upper();
|
|
if (data == "IERI") --g; else
|
|
if (data == "DOMANI") ++g;
|
|
TString16 gstring(g.string());
|
|
if (data == "PRIMO") { gstring.overwrite("01-01", 0); } else
|
|
if (data == "ULTIMO") { gstring.overwrite("31-12", 0); }
|
|
data = gstring;
|
|
changed = TRUE;
|
|
}
|
|
|
|
TDate d(data);
|
|
if (!d.ok())
|
|
{
|
|
// error_box("La data deve essere nel formato gg-mm-aaaa");
|
|
error_box("Data errata o formato non valido");
|
|
return FALSE;
|
|
}
|
|
else
|
|
if (changed)
|
|
TMask_field::set_window_data(d.string());
|
|
}
|
|
}
|
|
|
|
return TEdit_field::on_key(key);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Real_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TReal_field::TReal_field(TMask* m) : TEdit_field(m)
|
|
{}
|
|
|
|
word TReal_field::class_id() const
|
|
{ return CLASS_REAL_FIELD; }
|
|
|
|
void TReal_field::create(WINDOW w)
|
|
{
|
|
TEdit_field::create(w);
|
|
|
|
if (_flags.firm)
|
|
set(::format("%ld", MainApp()->get_firm())); else
|
|
if (automagic())
|
|
{
|
|
TDate d(TODAY);
|
|
set(::format("%d", d.year()));
|
|
}
|
|
}
|
|
|
|
bool TReal_field::on_key(KEY key)
|
|
{
|
|
if (to_check(key))
|
|
{
|
|
if (roman())
|
|
{
|
|
const int r = atoi(get_window_data());
|
|
if (r < 0) return error_box("Numero romano errato");
|
|
}
|
|
else
|
|
{
|
|
const char* n = get();
|
|
if (*n && !real::is_real(n))
|
|
return error_box("Numero non valido");
|
|
|
|
const int segno = real(n).sign();
|
|
if (required() && segno == 0 && !mask().query_mode())
|
|
return error_box("Manca un valore indispensabile");
|
|
|
|
if (_flags.uppercase && segno < 0)
|
|
return error_box("Il numero deve essere positivo");
|
|
}
|
|
}
|
|
|
|
return TEdit_field::on_key(key);
|
|
}
|
|
|
|
void TReal_field::parse_head(TScanner& scanner)
|
|
{
|
|
_size = scanner.integer();
|
|
|
|
#ifdef DBG
|
|
if (_size < 1)
|
|
{
|
|
_size = 9;
|
|
yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)", dlg(), _size);
|
|
}
|
|
#endif
|
|
|
|
_width = _size;
|
|
_decimals = scanner.integer();
|
|
}
|
|
|
|
void TReal_field::set_window_data(const char* data)
|
|
{
|
|
if (data == NULL) data = "";
|
|
|
|
if (roman())
|
|
{
|
|
data = itor(atoi(data));
|
|
TMask_field::set_window_data(data);
|
|
}
|
|
else
|
|
{
|
|
real n(data);
|
|
if (!n.is_zero())
|
|
{
|
|
if (_flags.exchange)
|
|
{
|
|
const real& e = mask().exchange();
|
|
if (e != 1.0) n /= e;
|
|
}
|
|
if (_picture.empty())
|
|
data = n.stringa(_size, _decimals);
|
|
else
|
|
data = n.string(_picture);
|
|
} else data = "";
|
|
TEdit_field::set_window_data(data);
|
|
}
|
|
}
|
|
|
|
const char* TReal_field::get_window_data() const
|
|
{
|
|
TEdit_field::get_window_data();
|
|
if (roman())
|
|
{
|
|
int r = atoi(fpark);
|
|
if (r == 0) r = rtoi(fpark);
|
|
if (r > 0)
|
|
{
|
|
int s = decimals();
|
|
if (s < 1) s = 4;
|
|
fpark.format("%*d", s, r);
|
|
}
|
|
else fpark.cut(0);
|
|
}
|
|
else
|
|
{
|
|
fpark = real::ita2eng(fpark);
|
|
if (_flags.exchange)
|
|
{
|
|
const real& e = mask().exchange();
|
|
if (e != 1.0)
|
|
{
|
|
real n(fpark);
|
|
n *= e;
|
|
if (n.is_zero()) fpark.cut(0);
|
|
else fpark = n.string();
|
|
}
|
|
}
|
|
}
|
|
|
|
return fpark;
|
|
}
|
|
|
|
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(const real& vec, const real& nuo)
|
|
{
|
|
const int dec = (nuo != 1.0) ? 2 : 0;
|
|
|
|
if (decimals() != dec)
|
|
set_decimals(dec);
|
|
else
|
|
if (dec == 2)
|
|
return;
|
|
|
|
if (mask().is_running())
|
|
{
|
|
const char* n = real::ita2eng(TEdit_field::get_window_data());
|
|
if (*n)
|
|
{
|
|
real r(n);
|
|
r *= vec;
|
|
r /= nuo;
|
|
r.round(dec);
|
|
TEdit_field::set_window_data(r.string(_picture));
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// List_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TList_field::TList_field(TMask* m) : TMask_field(m)
|
|
{}
|
|
|
|
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());
|
|
_values.add(ts.get());
|
|
|
|
ts = "";
|
|
while (scanner.popkey() == "ME")
|
|
ts.add(scanner.line().strip_spaces());
|
|
scanner.push();
|
|
|
|
_message.add(ts);
|
|
}
|
|
|
|
|
|
void TList_field::parse_head(TScanner& scanner)
|
|
{
|
|
_size = scanner.integer();
|
|
_width = scanner.integer();
|
|
if (_width < 1) _width = _size+3;
|
|
}
|
|
|
|
|
|
bool TList_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "IT") // ITEM
|
|
{
|
|
read_item(scanner);
|
|
return TRUE;
|
|
}
|
|
|
|
if (scanner.key() == "LI") // LISTITEM
|
|
{
|
|
TScanner sc(scanner.pop());
|
|
while (sc.popkey() == "IT") // ITEM
|
|
read_item(sc);
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
|
|
int TList_field::items() const
|
|
{
|
|
return _codes.items();
|
|
}
|
|
|
|
void TList_field::add_item(const char* s)
|
|
{
|
|
TToken_string t(s);
|
|
const TString16 item(t.get());
|
|
const int pos = _codes.get_pos(item);
|
|
|
|
if (pos < 0 )
|
|
{
|
|
_codes.add(item);
|
|
win_list_add(win(), -1, (char*)t.get());
|
|
}
|
|
}
|
|
|
|
|
|
void TList_field::delete_item(const char* s)
|
|
{
|
|
TString16 t(s);
|
|
const int pos = _codes.get_pos(t);
|
|
|
|
if (pos >= 0 )
|
|
{
|
|
_codes.destroy(pos);
|
|
win_list_delete(win(), pos);
|
|
if (mask().is_running())
|
|
{
|
|
win_list_set_sel(win(), 0, TRUE);
|
|
if (showed()) 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");
|
|
_values.add("Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre");
|
|
if (atoi(csafe) > 0)
|
|
{
|
|
_codes.add(csafe);
|
|
_values.add(vsafe);
|
|
if (_message.objptr(0))
|
|
{
|
|
_message.add(_message[0], _codes.items()-1);
|
|
_message.add(NULL, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
SLIST lst = slist_new();
|
|
for (const char* item = _values.get(0); item; item = _values.get())
|
|
slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L);
|
|
win_list_add(win(), -1, (char*)lst);
|
|
slist_dispose(lst);
|
|
|
|
const char* init = "";
|
|
if (roman() && automagic())
|
|
init = format("%02d", TDate(TODAY).month());
|
|
set_field_data(init);
|
|
}
|
|
|
|
|
|
void TList_field::replace_items(const char* codes, const char* values)
|
|
{
|
|
_codes = codes;
|
|
_values = values;
|
|
|
|
if (win() != NULL_WIN)
|
|
{
|
|
win_list_clear(win());
|
|
add_list();
|
|
current(0);
|
|
}
|
|
}
|
|
|
|
|
|
void TList_field::create(WINDOW parent)
|
|
{
|
|
const int len = create_prompt(parent);
|
|
_x += len;
|
|
|
|
wincreate(WC_LISTBUTTON, _width, 5, "", parent,0);
|
|
add_list();
|
|
}
|
|
|
|
|
|
int TList_field::str2curr(const char* data)
|
|
{
|
|
TString16 str(data);
|
|
|
|
if (roman() && str.len() < 2)
|
|
str.insert("0",0);
|
|
if (_flags.uppercase)
|
|
str.upper();
|
|
|
|
int i = _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())
|
|
yesnofatal_box("'%s' non e' un valore valido per il campo %s: %d",
|
|
data, prompt(), dlg());
|
|
i = 0;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
void TList_field::set_window_data(const char* data)
|
|
{
|
|
CHECKD(win(), "Control window not initialized ", dlg());
|
|
int i = str2curr(data);
|
|
current(i);
|
|
}
|
|
|
|
|
|
void TList_field::current(int n)
|
|
{
|
|
win_list_set_sel(win(), n, TRUE);
|
|
}
|
|
|
|
int TList_field::current() const
|
|
{
|
|
int sel = win_list_get_sel_index(win());
|
|
#ifdef DBG
|
|
if (sel < 0 && items() > 0)
|
|
error_box("Lista senza selezione nel campo %d", dlg());
|
|
#endif
|
|
return sel;
|
|
}
|
|
|
|
const char* TList_field::get_window_data() const
|
|
{
|
|
return ((TList_field*)this)->_codes.get(current());
|
|
}
|
|
|
|
void TList_field::set_field_data(const char* data)
|
|
{
|
|
if (data == NULL || *data == '\0') data = _codes.get(0);
|
|
_str = data;
|
|
}
|
|
|
|
bool TList_field::on_hit()
|
|
{
|
|
if (_handler)
|
|
{
|
|
bool ok = _handler(*this, K_SPACE);
|
|
if (!ok) return FALSE;
|
|
}
|
|
const int n = mask().is_running() ? current() : str2curr(_str);
|
|
do_message(n);
|
|
return TRUE;
|
|
}
|
|
|
|
const char* TList_field::get_field_data() const
|
|
{
|
|
return _str;
|
|
}
|
|
|
|
bool TList_field::on_key(KEY key)
|
|
{
|
|
if (key >= '0' && key <= 'z')
|
|
{
|
|
const int index = win_list_get_sel_index(win());
|
|
CHECK(index >= 0, "List with no selection!");
|
|
int newindex = -1;
|
|
|
|
#if XVTWS == WMWS
|
|
if (key >= 'A' && key <= 'z')
|
|
{
|
|
for (int i = index+1; i != index; i++)
|
|
{
|
|
char item[16];
|
|
bool flag;
|
|
|
|
do
|
|
{
|
|
flag = win_list_get_elt(win(), i, item, 16);
|
|
if (!flag)
|
|
{
|
|
CHECK(i, "La lista e' vuota!");
|
|
i = -1;
|
|
break;
|
|
}
|
|
} while (!flag);
|
|
if (flag && toupper(*item) == toupper(key))
|
|
{
|
|
newindex = i;
|
|
break;
|
|
}
|
|
} // for
|
|
} // alphabetic
|
|
#endif
|
|
|
|
if (key >= '0' && key <= '9')
|
|
{
|
|
newindex = (key == '0') ? 10 : key - '1';
|
|
if (newindex > items())
|
|
{
|
|
newindex = -1;
|
|
beep();
|
|
}
|
|
}
|
|
|
|
if (newindex >= 0)
|
|
{
|
|
win_list_suspend(win());
|
|
win_list_set_sel(win(), index, FALSE);
|
|
win_list_set_sel(win(), newindex, TRUE);
|
|
win_list_resume(win());
|
|
}
|
|
} // alphanumeric
|
|
|
|
#if XVTWS == VMWS
|
|
if (key == K_TAB && class_id() == CLASS_LIST_FIELD)
|
|
dispacth_e_char(win(), K_F9);
|
|
#endif
|
|
|
|
if (key == K_SPACE) on_hit();
|
|
|
|
return TMask_field::on_key(key);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TRadio_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TRadio_field::TRadio_field(TMask* mask)
|
|
: TList_field(mask), _nitems(0), _active_item(0)
|
|
{}
|
|
|
|
|
|
word TRadio_field::class_id() const
|
|
{
|
|
return CLASS_RADIO_FIELD;
|
|
}
|
|
|
|
|
|
void TRadio_field::create(WINDOW parent)
|
|
{
|
|
const short id = dlg(); // Salva il control id
|
|
|
|
if (_prompt.not_empty())
|
|
{
|
|
const int dy = _codes.items()+2;
|
|
create_prompt(parent, _width, dy);
|
|
}
|
|
_x++; _y++;
|
|
_values.restart();
|
|
|
|
const char* s;
|
|
for(_nitems = 0; (s = _values.get()) != NULL; _nitems++, _y++)
|
|
{
|
|
CHECKD(_nitems < MAX_RADIO, "Too many items in radio button ", id);
|
|
|
|
wincreate(WC_RADIOBUTTON, _width-2, 1, s, parent,0);
|
|
_radio_ctl_win[_nitems] = _win;
|
|
_dlg += 1000;
|
|
}
|
|
_radio_ctl_win[_nitems] = NULL_WIN; // Comodo per debug
|
|
|
|
_dlg = id; // Ripristina control id
|
|
|
|
set_field_data("");
|
|
}
|
|
|
|
void TRadio_field::destroy()
|
|
{
|
|
if (_promptwin)
|
|
{ close_window(_promptwin); _promptwin = NULL_WIN; }
|
|
|
|
for(int i = 0; i < _nitems; i++)
|
|
{
|
|
close_window(_radio_ctl_win[i]);
|
|
_radio_ctl_win[i] = NULL_WIN;
|
|
}
|
|
}
|
|
|
|
|
|
int TRadio_field::current() const
|
|
{
|
|
return xvt_get_checked_radio(_radio_ctl_win, _nitems);
|
|
}
|
|
|
|
|
|
void TRadio_field::current(int n)
|
|
{
|
|
_active_item = n;
|
|
xvt_check_radio_button(win(), _radio_ctl_win, _nitems);
|
|
}
|
|
|
|
|
|
void TRadio_field::check_radiobutton(WINDOW checked)
|
|
{
|
|
for(int i = 0; i < _nitems && checked != _radio_ctl_win[i]; i++);
|
|
CHECK(i < _nitems, "Trying to check an invalid radio button");
|
|
current(i);
|
|
}
|
|
|
|
|
|
void TRadio_field::enable(bool on)
|
|
{
|
|
_flags.enabled = on;
|
|
for(int i = 0; i < _nitems; i++)
|
|
xvt_enable_control(_radio_ctl_win[i], on);
|
|
}
|
|
|
|
|
|
void TRadio_field::show(bool on)
|
|
{
|
|
if (_promptwin)
|
|
show_window(_promptwin, on);
|
|
|
|
for(int i = 0; i < _nitems; i++)
|
|
show_window(_radio_ctl_win[i], on);
|
|
_flags.showed = on;
|
|
}
|
|
|
|
// Return TRUE if focus has left the radio
|
|
bool TRadio_field::move_focus(int d)
|
|
{
|
|
const int act = _active_item + d;
|
|
if (act >= _nitems || act < 0)
|
|
{
|
|
_active_item = current();
|
|
return TRUE;
|
|
}
|
|
xvt_set_front_control(_radio_ctl_win[_active_item = act]);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGroup_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TGroup_field::TGroup_field(TMask* mask) : TMask_field(mask)
|
|
{
|
|
_flags.persistent = TRUE;
|
|
}
|
|
|
|
// _size means _heigth
|
|
void TGroup_field::parse_head(TScanner& scanner)
|
|
{
|
|
_width = scanner.integer();
|
|
_size = scanner.integer();
|
|
}
|
|
|
|
|
|
void TGroup_field::create(WINDOW parent)
|
|
{
|
|
const long f = _flags.rightjust ? CTL_FLAG_MULTIPLE : 0;
|
|
wincreate(WC_GROUPBOX, _width, _size, _prompt, parent, f);
|
|
}
|
|
|