Patch level : 2.1 nopatch

Files correlati     : ba8.exe
Ricompilazione Demo : [ ]
Commento            :

Ultime correzioni per nuovi report


git-svn-id: svn://10.65.10.50/trunk@12003 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
guy 2004-04-27 15:36:39 +00:00
parent e34627d5d6
commit dbc8341d80
9 changed files with 560 additions and 127 deletions

View File

@ -579,6 +579,17 @@ bool TRecordset::save_as(const char* path, TRecordsetExportFormat fmt)
return ok;
}
int TRecordset::find_column(const char* column_name) const
{
for (int i = columns()-1; i >= 0; i--)
{
const TRecordset_column_info& info = column_info(i);
if (info._name == column_name)
break;
}
return i;
}
const TVariant& TRecordset::get(const char* column_name) const
{
if (*column_name == '#')
@ -592,12 +603,34 @@ const TVariant& TRecordset::get(const char* column_name) const
column_name++;
}
for (unsigned int i = 0; i < columns(); i++)
char* dot = strchr(column_name, ':');
if (dot != NULL)
{
const TRecordset_column_info& info = column_info(i);
if (info._name == column_name)
*dot = '\0';
const int i = find_column(column_name);
*dot = ':';
if (i >= 0)
{
const TString& str = get(i).as_string();
TString subfield; subfield << (dot+1) << '=';
int s = str.find(subfield);
if (s == 0 || (s > 0 && str[s-1] < ' '))
{
static TVariant var;
s += subfield.len();
const int e = str.find('\n', s);
var.set(str.sub(s, e));
return var;
}
}
}
else
{
const int i = find_column(column_name);
if (i >= 0)
return get(i);
}
return NULL_VARIANT;
}
@ -1153,7 +1186,7 @@ void TSQL_recordset::parsed_sql_text(TString& sql) const
const TString& after = sql.mid(pos+name->len());
sql.cut(pos);
TString s = var.as_string();
if ((var.type() == _alfafld && s[0] != '\'') || var.is_null())
if ((var.is_string() && s[0] != '\'') || var.is_null())
{
s.insert("'");
s << '\'';

View File

@ -34,8 +34,8 @@ protected:
void copy(const TVariant& var);
public:
TFieldtypes type() const { return _type; }
TFieldtypes type() const { return _type; } // Internal use only
bool is_string() const { return _type == _alfafld; }
bool is_null() const { return _type == _nullfld; }
bool is_zero() const;
void set_null();
@ -116,6 +116,7 @@ public: // Absolutely needed methods
virtual bool ask_variables(bool all);
virtual const TString& query_text() const;
virtual int find_column(const char* column_name) const;
virtual const TVariant& get(const char* column_name) const;
virtual const TToken_string& sheet_head() const;

View File

@ -210,7 +210,7 @@ void TReport_field_mask::vedo_non_vedo()
const char type = get(F_TYPE)[0];
const bool is_currency = type == 'P' || type == 'V';
const bool is_numeric = is_currency || type == 'N';
const bool is_text = is_numeric || strchr("DST", type) != NULL;
const bool is_text = is_numeric || strchr("ADST", type) != NULL;
show(F_HIDE_ZEROES, is_numeric || type == 'D'),
show(F_HALIGN, is_text);
@ -230,6 +230,9 @@ void TReport_field_mask::vedo_non_vedo()
show(F_SOURCE, (is_text || type == 'I') && type != 'T');
show(F_CODVAL, is_currency); // Codice valuta di riferimento
show(F_LINK, strchr("DNS", type) != NULL); // Chi puo' essere un link?
show(F_PRESCRIPT, is_text);
show(F_POSTSCRIPT, is_text);
enable_page(3, type == 'A');
if (is_running())
force_update();
@ -267,6 +270,20 @@ bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long
force_update();
}
break;
case F_LIST:
if (e == fe_close)
{
TSheet_field& sheet = sfield(F_LIST);
TAssoc_array ass;
FOR_EACH_SHEET_ROW(sheet, i, row)
{
if (ass.add(row->get(0)))
return error_box(TR("E' necessario specificare codici diversi"));
}
if (ass.items() < 2)
return error_box(TR("Specificare almeno due codici"));
}
break;
default:
break;
}
@ -304,6 +321,12 @@ void TReport_field_mask::set_field(const TReport_field& rf)
set(F_PRESCRIPT, rf.prescript());
set(F_POSTSCRIPT, rf.postscript());
if (rf.type() == 'A')
{
TSheet_field& list = sfield(F_LIST);
rf.get_list(list.rows_array());
}
}
void TReport_field_mask::get_field(TReport_field& rf) const
@ -331,6 +354,11 @@ void TReport_field_mask::get_field(TReport_field& rf) const
rf.set_prescript(get(F_PRESCRIPT));
rf.set_postscript(get(F_POSTSCRIPT));
if (rf.type() == 'A')
{
TSheet_field& list = sfield(F_LIST);
rf.set_list(list.rows_array());
}
}
///////////////////////////////////////////////////////////

View File

@ -31,6 +31,7 @@
#define F_GROUPS 139
#define F_CODVAL 140
#define F_LINK 141
#define F_LIST 142
#define F_LEVEL 160
#define F_GROUP_BY 161

View File

@ -11,6 +11,7 @@ BEGIN
ITEM "V|Valuta"
ITEM "P|Prezzo"
ITEM "D|Data"
ITEM "A|Array"
ITEM "I|Immagine"
ITEM "L|Linea"
ITEM "R|Rettangolo"
@ -181,7 +182,59 @@ BEGIN
PROMPT -33 -1 ""
END
ENDMASK
ENDPAGE
PAGE "Lista" -1 -1 72 16
SPREADSHEET F_LIST -1 -3
BEGIN
PROMPT 1 1 ""
ITEM "Codice"
ITEM "Decodifica@50"
FLAGS "H"
END
BUTTON DLG_CANCEL 10 2
BEGIN
PROMPT -13 -1 ""
END
BUTTON DLG_OK 10 2
BEGIN
PROMPT -33 -1 ""
END
ENDPAGE
ENDMASK
PAGE "List" -1 -1 72 11
STRING 101 3
BEGIN
PROMPT 1 0 "Codice "
END
STRING 102 50
BEGIN
PROMPT 13 0 "Decodifica "
END
BUTTON DLG_CANCEL 10 2
BEGIN
PROMPT -13 -1 ""
END
BUTTON DLG_DELREC 10 2
BEGIN
PROMPT -23 -1 ""
END
BUTTON DLG_OK 10 2
BEGIN
PROMPT -33 -1 ""
END
ENDPAGE
ENDMASK

View File

@ -422,6 +422,26 @@ void TReport_section::set_font(const TReport_font& f)
_font = new TReport_font(f);
}
const TString& TReport_section::prescript() const
{ return _prescript.get(); }
void TReport_section::set_prescript(const char* src)
{
TString desc; desc << type() << level() << " PRESCRIPT";
_prescript.set_description(desc);
_prescript.set(src);
}
const TString& TReport_section::postscript() const
{ return _postscript.get(); }
void TReport_section::set_postscript(const char* src)
{
TString desc; desc << type() << level() << " POSTSCRIPT";
_postscript.set_description(desc);
_postscript.set(src);
}
void TReport_section::unmap_font()
{
if (_font != NULL)
@ -681,6 +701,7 @@ TString& TReport_script::translate_message() const
fld = arg;
if (fld[0] != '#')
fld.insert("#", 0);
fld.insert("REPORT.", 1);
}
else
{
@ -691,11 +712,11 @@ TString& TReport_script::translate_message() const
if (cmd.starts_with("CO")) // COPY
{
alex << "#THIS @ " << fld << " ! ";
alex << "#REPORT.THIS @ " << fld << " ! ";
} else
if (cmd.starts_with("AD")) // ADD
{
alex << "#THIS @ " << fld << " @ + "<< fld << " ! ";
alex << "#REPORT.THIS @ " << fld << " @ + "<< fld << " ! ";
} else
if (cmd.starts_with("IN")) // INC
{
@ -738,6 +759,10 @@ void TReport_script::set(const char* source)
}
}
void TReport_script::copy(const TReport_script& rs)
{
set(rs.get());
}
bool TReport_script::execute(TReport& rep, TString& output)
{
@ -751,6 +776,7 @@ bool TReport_script::execute(TReport& rep, TString& output)
good = rep.compile(translate_message(), *_bc);
else
good = rep.compile(_src, *_bc);
_bc->set_name(_desc);
}
if (good)
good = rep.execute(*_bc, output);
@ -786,6 +812,7 @@ void TReport_script::save(TXmlItem& root, const char* tag) const
if (ok())
{
TXmlItem& script = root.AddChild(tag);
script.SetAttr("description", _desc);
script << _src;
}
}
@ -795,7 +822,10 @@ bool TReport_script::load(const TXmlItem& root, const char* tag)
destroy();
TXmlItem* script = root.FindFirstChild(tag);
if (script != NULL)
{
_desc = script->GetAttr("description");
script->GetEnclosedText(_src);
}
return ok();
}
@ -849,6 +879,26 @@ void TReport_field::unmap_font()
_font->unmap();
}
const TString& TReport_field::prescript() const
{ return _prescript.get(); }
void TReport_field::set_prescript(const char* src)
{
TString desc; desc << section().type() << section().level() << '.' << id() << " PRESCRIPT";
_prescript.set_description(desc);
_prescript.set(src);
}
const TString& TReport_field::postscript() const
{ return _postscript.get(); }
void TReport_field::set_postscript(const char* src)
{
TString desc; desc << section().type() << section().level() << '.' << id() << " POSTSCRIPT";
_postscript.set_description(desc);
_postscript.set(src);
}
void TReport_field::copy(const TReport_field& rf)
{
_section = rf._section;
@ -863,6 +913,10 @@ void TReport_field::copy(const TReport_field& rf)
_deactivated = rf.deactivated();
_hide_zeroes = rf._hide_zeroes;
_selected = false;
_prescript = rf._prescript;
_postscript = rf._postscript;
_list = rf._list;
set_font(rf.font());
}
@ -871,6 +925,7 @@ const char* TReport_field::type_name() const
const char* n = NULL;
switch (_type)
{
case 'A': n = "Array"; break;
case 'D': n = "Data"; break;
case 'E': n = "Ellisse"; break;
case 'I': n = "Immagine"; break;
@ -896,6 +951,7 @@ TFieldtypes TReport_field::var_type() const
case 'V': // Valuta
case 'N': ft = _realfld; break;
case 'I':
case 'A':
case 'S': ft = _alfafld; break;
default : ft = _nullfld; break;
}
@ -1043,6 +1099,23 @@ const TString& TReport_field::formatted_text() const
switch (_type)
{
case 'A':
{
const TString& val = _var.as_string();
TString_array list; get_list(list);
int i;
for (i = list.last(); i > 0; i--)
if (val == list.row(i).get(0))
break;
if (i >= 0)
{
TString& fmt = get_tmp_string();
TToken_string& tok = list.row(i);
tok.get(1, fmt);
return fmt;
}
}
break;
case 'D':
{
const TDate d = _var.as_date();
@ -1270,12 +1343,26 @@ void TReport_field::save(TXmlItem& root) const
fld.AddChild("source") << field();
_prescript.save(fld, "prescript");
_postscript.save(fld, "postscript");
if (_type == 'A')
{
TString_array arr; get_list(arr);
TXmlItem& list = fld.AddChild("list");
FOR_EACH_ARRAY_ROW(arr, i, row)
{
TXmlItem& li = list.AddChild("li");
li.SetAttr("Code", row->get(0));
li << row->get();
}
}
}
bool TReport_field::load(const TXmlItem& fld)
{
set_type(get_chr_attr(fld, "type", 'T'));
const TString& t = fld.GetAttr("type");
set_type(t[0]);
set_id(fld.GetIntAttr("id"));
set_column(get_num_attr(fld, "x"));
set_row(get_num_attr(fld, "y"));
@ -1309,9 +1396,39 @@ bool TReport_field::load(const TXmlItem& fld)
_prescript.load(fld, "prescript");
_postscript.load(fld, "postscript");
_list.cut(0);
if (_type == 'A')
{
TXmlItem* list = fld.FindFirstChild("list");
TToken_string tok;
TString str;
for (int i = 0; i < list->GetChildren(); i++)
{
const TXmlItem* li = list->GetChild(i);
tok = li->GetAttr("Code");
tok.add(li->GetEnclosedText(str));
_list.add(tok);
}
}
return true;
}
void TReport_field::get_list(TString_array& list) const
{
list.destroy();
TToken_string& toklst = (TToken_string&)_list;
FOR_EACH_TOKEN(toklst, tok)
list.add(tok);
}
void TReport_field::set_list(const TString_array& list)
{
_list.cut(0);
FOR_EACH_ARRAY_ROW(list, i, row)
_list.add(*row);
}
int TReport_field::compare(const TSortable& s) const
{
const TReport_field& rf = (TReport_field&)s;
@ -1330,7 +1447,7 @@ TReport_field::TReport_field(TReport_section* sec)
: _section(sec), _id(0), _type('T'),
_font(NULL), _halign('L'), _valign('T'),
_selected(false), _hidden(false), _deactivated(false), _hide_zeroes(false),
_border(0), _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE)
_border(0), _fgcolor(COLOR_BLACK), _bgcolor(COLOR_WHITE), _list(32, '\n')
{
set_pos(0,0);
set_size(1600,100);
@ -1491,7 +1608,7 @@ int TReport::parse_field(const char* code, char& type, int& level, int& id) cons
if (code[0] == '#')
code++;
if (isdigit(code[0]) || strcmp(code, "THIS") == 0) // Niente sezione davanti
if (isdigit(code[0]) || strncmp(code, "THIS", 4) == 0) // Niente sezione davanti
{
TReport_field* rf = curr_field();
if (rf != NULL)
@ -1548,11 +1665,10 @@ bool TReport::evaluate(const char* expr, TVariant& var, TFieldtypes force_type)
// Caso semplice nonche' standard
if (e.numvar() == 1)
{
const char* name = e.varname(0);
if (strcmp(name, expr) == 0)
const TFixed_string name(e.varname(0));
if (name == expr)
{
const TFixed_string usr(name);
if (get_usr_val(usr, var))
if (get_usr_val(name, var))
{
if (force_type != _nullfld)
var.convert_to(force_type);
@ -1563,21 +1679,11 @@ bool TReport::evaluate(const char* expr, TVariant& var, TFieldtypes force_type)
for (int i = 0; i < e.numvar(); i++)
{
const char* name = e.varname(i);
bool ok = false;
if (name[0] == '#')
{
const TFixed_string usr(name+1);
ok = get_usr_val(usr, var);
}
else
{
const TFixed_string usr(name);
ok = get_usr_val(usr, var);
}
const TFixed_string name(e.varname(i));
const bool ok = get_usr_val(name, var);
if (!ok)
var = name;
if (var.type() == _alfafld)
if (var.is_string())
e.setvar(i, var.as_string());
else
e.setvar(i, var.as_real());
@ -1694,6 +1800,22 @@ void TReport::unmap_font()
}
}
const TString& TReport::prescript() const
{ return _prescript.get(); }
void TReport::set_prescript(const char* src)
{
_prescript.set(src);
}
const TString& TReport::postscript() const
{ return _postscript.get(); }
void TReport::set_postscript(const char* src)
{
_postscript.set(src);
}
bool TReport::execute_prescript()
{
bool ok = true;
@ -1732,39 +1854,91 @@ bool TReport::execute_postscript()
return _postscript.execute(*this, str);
}
bool TReport::get_usr_val(const TString& name, TVariant& var) const
bool TReport::get_report_field(const TString& name, TVariant& var) const
{
if (name == "#PAGE")
bool found = false;
const char* str = name;
if (name[0] == '#')
{
if (name.starts_with("#REPORT."))
{
str += 8;
found = true;
}
else
str++;
}
const TFixed_string n(str);
if (n == "PAGE")
{
var = curr_page();
return true;
}
TReport_field* fld = ((TReport*)this)->field(name);
TReport_field* fld = ((TReport*)this)->field(n);
if (fld != NULL)
{
var = fld->get();
return true;
}
return found;
}
bool TReport::get_record_field(const TString& name, TVariant& var) const
{
bool found = false;
if (_recordset != NULL)
{
var = _recordset->get(name);
const char* str = name;
if (name[0] == '#')
{
if (name.starts_with("#RECORD."))
{
str += 8;
found = true;
}
else
str++;
}
var = _recordset->get(str);
if (!var.is_null())
return true;
}
return found;
}
bool TReport::get_usr_val(const TString& name, TVariant& var) const
{
if (get_report_field(name, var))
return true;
if (get_record_field(name, var))
return true;
return TAlex_virtual_machine::get_usr_val(name, var);
}
bool TReport::set_usr_val(const TString& name, const TVariant& var)
{
TReport_field* fld = field(name);
const char* str = name;
if (name[0] == '#')
{
if (name.starts_with("#REPORT."))
str += 8;
else
str++;
}
const TFixed_string n(str);
TReport_field* fld = field(n);
if (fld != NULL)
{
fld->set(var);
return true;
}
return TAlex_virtual_machine::set_usr_val(name, var);
}
@ -1979,6 +2153,9 @@ TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL)
{
// Brutte inizializzazioni, ma inevitabili
_expressions.set_report(this);
_prescript.set_description("PRESCRIPT");
_postscript.set_description("POSTSCRIPT");
}
TReport::~TReport()

View File

@ -107,23 +107,28 @@ public:
class TReport_script : public TObject
{
TBytecode* _bc; // Chesire's cat class
TString _src;
TString _src, _desc;
protected:
void destroy();
TString& translate_message() const;
void copy(const TReport_script& rs);
public:
virtual bool ok() const { return !_src.blank(); }
void set(const char* source);
const TString& get() const { return _src; }
void set_description(const char* d) { _desc = d; }
bool execute(TReport& report, TString& output);
bool execute(TReport_field& rf);
void save(TXmlItem& root, const char* tag) const;
bool load(const TXmlItem& root, const char* tag);
TReport_script& operator =(const TReport_script& rs) { copy(rs); return *this; }
TReport_script();
TReport_script(const TReport_script& rs) { copy(rs); }
virtual ~TReport_script();
};
@ -131,7 +136,7 @@ public:
// TReport_section
///////////////////////////////////////////////////////////
enum TReport_draw_mode { rdm_edit, rdm_print, rdm_print_preview };
enum TReport_draw_mode { rdm_edit, rdm_print, rdm_print_preview, rdm_spooler, rdm_textonly };
class TReport_section : public TArray
{
@ -148,6 +153,7 @@ class TReport_section : public TArray
TReport_font* _font;
protected:
virtual const char* class_name() const { return "ReportSection"; }
TReport_section* father_section() const;
public:
@ -189,10 +195,10 @@ public:
void activate(bool on) { _deactivated = !on; }
void deactivate() { activate(false); }
const TString& prescript() const { return _prescript.get(); }
void set_prescript(const char* src) { _prescript.set(src); }
const TString& postscript() const { return _postscript.get(); }
void set_postscript(const char* src) { _postscript.set(src); }
const TString& prescript() const;
void set_prescript(const char* src);
const TString& postscript() const;
void set_postscript(const char* src);
bool has_font() const { return _font != NULL; }
const TReport_font& font() const;
@ -224,11 +230,13 @@ class TReport_field : public TSortable
TString _picture, _field, _codval, _link;
TVariant _var;
TReport_script _prescript, _postscript;
TToken_string _list; // Elementi di un campo lista
TReport_font* _font;
bool _hidden, _deactivated, _hide_zeroes, _selected;
protected:
virtual const char* class_name() const { return "ReportField"; }
virtual int compare(const TSortable& s) const;
void copy(const TReport_field& rf);
TFieldtypes var_type() const;
@ -261,6 +269,9 @@ public:
bool execute_prescript();
bool execute_postscript();
void get_list(TString_array& list) const;
void set_list(const TString_array& list);
int id() const { return _id; }
void set_id(int id) { _id = id; }
char type() const { return _type; }
@ -305,10 +316,10 @@ public:
void set_vertical_alignment(char a) { _valign = a; }
char vertical_alignment() const { return _valign; }
const TString& prescript() const { return _prescript.get(); }
void set_prescript(const char* src) { _prescript.set(src); }
const TString& postscript() const { return _postscript.get(); }
void set_postscript(const char* src) { _postscript.set(src); }
const TString& prescript() const;
void set_prescript(const char* src);
const TString& postscript() const;
void set_postscript(const char* src);
void select(bool ok = true) { _selected = ok; }
bool selected() const { return _selected; }
@ -366,6 +377,7 @@ class TReport : public TAlex_virtual_machine
TReport_field* _curr_field;
protected:
virtual const char* class_name() const { return "Report"; }
virtual unsigned int compile_usr_word(const TString& name) const;
virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack);
virtual bool get_usr_val(const TString& name, TVariant& var) const;
@ -381,6 +393,9 @@ protected:
void load_sections(const TXmlItem& xml);
void save_section(const TReport_section& rs, TXmlItem& item) const;
bool get_report_field(const TString& name, TVariant& var) const;
bool get_record_field(const TString& name, TVariant& var) const;
public:
TReport_section* find_section(char type, int level) const;
TReport_section& section(char type, int level);
@ -403,10 +418,10 @@ public:
bool evaluate_atom(const char* atom, TVariant& var);
bool evaluate(const char* expr, TVariant& var, TFieldtypes force_type);
const TString& prescript() const { return _prescript.get(); }
void set_prescript(const char* src) { _prescript.set(src); }
const TString& postscript() const { return _postscript.get(); }
void set_postscript(const char* src) { _postscript.set(src); }
const TString& prescript() const;
void set_prescript(const char* src);
const TString& postscript() const;
void set_postscript(const char* src);
bool execute_prescript();
bool execute_postscript();

View File

@ -93,8 +93,9 @@ enum AVM_opcode
avm_j,
avm_loop,
avm_mod, avm_mon, avm_mul,
avm_negate,
avm_or, avm_over,
avm_plus_loop, avm_push,
avm_pick, avm_plus_loop, avm_push,
avm_repeat, avm_rdrop, avm_rpeek, avm_rpush, avm_rot,
avm_store, avm_sub, avm_swap,
avm_then, avm_true,
@ -117,8 +118,9 @@ const char* AVM_TOKENS[avm_zzz+1] =
"J",
"LOOP",
"MOD", "MON", "*",
"NEGATE",
"OR", "OVER",
"+LOOP", "PUSH",
"PICK", "+LOOP", "PUSH",
"REPEAT", "R>", "R@", ">R", "ROT",
"!", "-", "SWAP",
"THEN", "TRUE",
@ -126,16 +128,22 @@ const char* AVM_TOKENS[avm_zzz+1] =
"WARM", "WHILE"
};
enum TBreakpointType { brk_none = 0x0, brk_user = 0x1, brk_auto = 0x2 };
class TAVM_op : public TObject
{
AVM_opcode _op;
TVariant _var;
bool _break_pointer;
int _break_pointer;
public:
const TVariant& var() const { return _var; }
TVariant& var() { return _var; }
AVM_opcode op() const { return _op; }
bool has_break() const { return _break_pointer != brk_none; }
bool has_auto_break() const { return (_break_pointer & brk_auto) != 0; }
void set_user_break(bool on);
void set_auto_break(bool on);
TAVM_op(AVM_opcode o, const TString& str);
TAVM_op(AVM_opcode o, const real& num);
@ -143,6 +151,20 @@ public:
TAVM_op(AVM_opcode o);
};
void TAVM_op::set_user_break(bool on)
{
_break_pointer = on ? brk_user : brk_none;
}
void TAVM_op::set_auto_break(bool on)
{
if (on)
_break_pointer |= brk_auto;
else
_break_pointer &= ~brk_auto;
}
TAVM_op::TAVM_op(AVM_opcode o, const TString& str)
: _op(o), _var(str), _break_pointer(false)
{ }
@ -165,25 +187,45 @@ TAVM_op::TAVM_op(AVM_opcode o)
class TAVM_list_window : public TField_window
{
const TBytecode* _bc;
TBytecode* _bc;
int _ip;
protected:
virtual void update();
virtual void handler(WINDOW win, EVENT* ep);
public:
void set_bytecode(const TBytecode* bc, int ip);
TAVM_list_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner);
};
void TAVM_list_window::handler(WINDOW win, EVENT* ep)
{
if (ep->type == E_MOUSE_DOWN)
{
const TPoint pt = dev2log(ep->v.mouse.where);
if (pt.x <= 5)
{
TAVM_op& op = *(TAVM_op*)_bc->objptr(pt.y-1);
op.set_user_break(ep->v.mouse.button == 0);
force_update();
}
}
TField_window::handler(win, ep);
}
void TAVM_list_window::update()
{
clear(NORMAL_BACK_COLOR);
if (_bc != NULL)
{
autoscroll(false);
set_brush(DISABLED_BACK_COLOR);
bar(0, 0, 5, _bc->items());
bar(0, 0, columns()+1, 1);
bar(0, 0, 5, rows()+1);
set_brush(NORMAL_BACK_COLOR);
printat(0, 0, _bc->name());
autoscroll(true);
TString str;
int tab = 6;
@ -191,24 +233,29 @@ void TAVM_list_window::update()
const int last = min(_bc->items(), rows());
for (int i = 0; i < last; i++)
{
const int y = i+1;
if (_ip == i)
{
set_brush(FOCUS_BACK_COLOR);
bar(0, i, 80, i+1);
bar(0, y, 80, y+1);
set_brush(NORMAL_BACK_COLOR);
}
printat(0, i, "%04d", i);
printat(0, y, "%04d", i);
const TAVM_op& op = *(const TAVM_op*)_bc->objptr(i);
const AVM_opcode co = op.op();
const TVariant& var = op.var();
if (op.has_break())
printat(4, y, "<");
if (co == avm_else || co == avm_then ||
co == avm_loop || co == avm_plus_loop ||
co == avm_repeat || co == avm_until)
tab -= 2;
if (co == avm_push)
{
if (var.type() == _alfafld && var.as_string()[0] != '#')
if (var.is_string() && var.as_string()[0] != '#')
str.cut(0) << '"' << var.as_string() << '"';
else
str = var.as_string();
@ -223,7 +270,7 @@ void TAVM_list_window::update()
if (!var.is_null())
str << " (" << var.as_string() << ')';
}
printat(tab, i, str);
printat(tab, y, str);
if (co == avm_if || co == avm_else ||
co == avm_do || co == avm_begin || co == avm_while)
tab += 2;
@ -233,7 +280,7 @@ void TAVM_list_window::update()
void TAVM_list_window::set_bytecode(const TBytecode* bc, int ip)
{
_bc = bc;
_bc = (TBytecode*)bc;
_ip = ip;
set_scroll_max(80, _bc->items() - rows());
}
@ -353,6 +400,7 @@ class TAVM
TVariant_stack _stack, _rstack;
const TBytecode* _bc; // Current word (or command line)
int _ip; // Current instruction pointer
ostream* _outstr;
TAssoc_array _words;
TAVM_monitor _mon;
@ -365,12 +413,13 @@ protected:
int find_matching(const TBytecode& bytecode, AVM_opcode op1, AVM_opcode op2 = avm_nop) const;
void execute(const TAVM_op& op);
void do_call(const TString& func);
void do_fload(const char* fname);
public:
const TString& get_last_error() const { return _last_error; }
bool compile(istream& instr, TBytecode& bc);
bool execute(const TBytecode& bc, ostream& outstr);
bool execute(const TBytecode& bc, ostream* outstr = NULL);
void restart(bool cold);
TAVM(TAlex_virtual_machine* vm);
@ -457,7 +506,7 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode)
str.rtrim(1); str.ltrim(1);
op = new TAVM_op(avm_push, str);
} else
if (isdigit(str[0]) || (str[0]=='-' && isdigit(str[1])))
if ((isdigit(str[0]) || (str[0]=='-')) && isdigit(str[str.len()-1]))
{
const real r(str);
op = new TAVM_op(avm_push, r);
@ -474,6 +523,7 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode)
bc->set_name(str);
_words.add(str, bc);
compile(instr, *bc);
op = new TAVM_op(avm_nop);
}
else
{
@ -554,7 +604,12 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode)
}
}
if (op != NULL)
bytecode.add(op);
{
if (op->op() != avm_nop)
bytecode.add(op);
else
delete op;
}
else
{
_last_error.cut(0) << "Unknown WORD: " << str;
@ -567,9 +622,9 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode)
int TAVM::compare_tos_nos()
{
const TVariant& v0 = _stack.pop();
const TVariant& v1 = _stack.pop();
return v1.compare(v0);
const TVariant& tos = _stack.pop();
const TVariant& nos = _stack.pop();
return nos.compare(tos);
}
void TAVM::do_call(const TString& func)
@ -580,6 +635,18 @@ void TAVM::do_call(const TString& func)
_bc = (TBytecode*)_words.objptr(func);
}
void TAVM::do_fload(const char* fname)
{
TFilename name = fname;
if (name.custom_path())
{
TBytecode bc;
ifstream inf(name);
if (compile(inf, bc))
execute(bc);
}
}
void TAVM::execute(const TAVM_op& op)
{
switch(op.op())
@ -631,13 +698,24 @@ void TAVM::execute(const TAVM_op& op)
_ip = op.var().as_int();
}
break;
case avm_dot: /* *_outstr << _stack.pop().as_string(); */ break;
case avm_dot:
if (_outstr != NULL)
*_outstr << _stack.pop().as_string();
break;
case avm_drop: _stack.drop(); break;
case avm_dup: _stack.push(_stack.peek()); break;
case avm_else:
_ip = op.var().as_int();
break;
case avm_execute: do_call(_stack.pop().as_string()); break;
case avm_execute:
{
const TString& cmd = _stack.pop().as_string();
istrstream instr((char*)(const char*)cmd, cmd.len());
TBytecode bc;
if (compile(instr, bc))
execute(bc);
}
break;
case avm_false: _stack.push(0L); break;
case avm_fetch:
{
@ -652,12 +730,7 @@ void TAVM::execute(const TAVM_op& op)
_stack.push(var);
}
break;
case avm_fload:
{
const TString& name = _stack.pop().as_string();
ifstream inf(name); TBytecode bc;
compile(inf, bc); // Loads new words but desn't execute statements
}
case avm_fload: do_fload(_stack.pop().as_string()); break;
break;
case avm_i: _stack.push(_rstack.peek()); break;
case avm_if:
@ -683,13 +756,8 @@ void TAVM::execute(const TAVM_op& op)
}
break;
case avm_mon:
{
lock_preview_update(true);
TAVM_list_window& monitor = _mon.monitor();
monitor.set_bytecode(_bc, _ip);
if (!_mon.is_open())
_mon.open();
}
if (!_mon.is_open())
_mon.open_modal();
break;
case avm_mul:
{
@ -699,15 +767,27 @@ void TAVM::execute(const TAVM_op& op)
v0.set(m);
}
break;
case avm_negate:
{
TVariant& tos = _stack.peek();
tos.set(~tos.as_int());
}
break;
case avm_or:
{
const TVariant& v1 = _stack.pop();
TVariant& v0 = (TVariant&)_stack.peek();
const long r = v0.as_int() | v1.as_int();
v0.set(r);
const TVariant& tos = _stack.pop();
TVariant& nos = (TVariant&)_stack.peek();
const long r = nos.as_int() | tos.as_int();
nos.set(r);
}
break;
case avm_over: _stack.push(_stack.peek(1)); break;
case avm_pick:
{
const int depth = _stack.pop().as_int();
_stack.push(_stack.peek(depth));
}
break;
case avm_plus_loop:
{
TVariant& start = _rstack.pop();
@ -766,10 +846,15 @@ void TAVM::execute(const TAVM_op& op)
}
}
bool TAVM::execute(const TBytecode& cmdline, ostream& outstr)
bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
{
const TBytecode* old_bc = _bc;
const int old_ip = _ip;
_bc = &cmdline;
_ip = 0;
if (outstr != NULL)
_outstr = outstr;
while (_bc != NULL)
{
if (_ip >= _bc->items()) // Fine funzione
@ -778,13 +863,23 @@ bool TAVM::execute(const TBytecode& cmdline, ostream& outstr)
{
_ip = _rstack.pop().as_int();
const TString& str = _rstack.pop().as_string();
if (str.blank())
if (str == cmdline.name())
_bc = &cmdline;
else
_bc = (const TBytecode*)_words.objptr(str);
}
else
break; // Fine esecuzione
if (_bc == NULL)
break;
}
TAVM_op& op = *(TAVM_op*)_bc->objptr(_ip);
if (op.has_break() && !_mon.is_open())
{
if (op.has_auto_break())
op.set_auto_break(false);
_mon.open_modal();
}
if (_mon.is_open()) // Gestione debugger
@ -799,14 +894,21 @@ bool TAVM::execute(const TBytecode& cmdline, ostream& outstr)
const KEY k = _mon.run();
switch (k)
{
case K_NEXT: monitor.force_update(); stacker.force_update(); rstacker.force_update(); break;
case K_F11: monitor.force_update(); stacker.force_update(); rstacker.force_update(); break;
case K_F10:
if (_ip < _bc->items()-1)
{
_mon.close_modal();
TAVM_op& op = *(TAVM_op*)_bc->objptr(_ip+1);
op.set_auto_break(true);
}
break;
case K_DEL : abort_printing();
case K_QUIT: _mon.close(); lock_preview_update(false); break;
case K_QUIT: _mon.close_modal(); lock_preview_update(false); break;
default: break;
}
}
const TAVM_op& op = *(const TAVM_op*)_bc->objptr(_ip);
execute(op);
_ip++;
@ -814,11 +916,15 @@ bool TAVM::execute(const TBytecode& cmdline, ostream& outstr)
if (_mon.is_open()) // Chiudi debugger
{
_mon.close();
_mon.close_modal();
lock_preview_update(false);
}
const bool ok = _bc != NULL; // Not aborted
_bc = old_bc;
_ip = old_ip;
return _bc != NULL;
return ok;
}
void TAVM::restart(bool cold)
@ -828,8 +934,10 @@ void TAVM::restart(bool cold)
}
TAVM::TAVM(TAlex_virtual_machine* vm)
: _vm(vm)
{ }
: _vm(vm), _outstr(NULL)
{
do_fload("alex.alx");
}
TAVM::~TAVM()
{
@ -860,7 +968,7 @@ bool TAlex_virtual_machine::compile(istream& instr, TBytecode& bc)
bool TAlex_virtual_machine::execute(const TBytecode& bc, ostream& outstr)
{
return avm().execute(bc, outstr);
return avm().execute(bc, &outstr);
}
bool TAlex_virtual_machine::compile(const char* cmd, TBytecode& bc)
@ -889,40 +997,48 @@ void TAlex_virtual_machine::cold_restart() // Ripartenza a freddo
bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) const
{
if (name == "#ADMINISTATOR")
if (name.starts_with("#SYSTEM."))
{
var.set(dongle().administrator());
return true;
}
if (name == "#FIRM")
{
var.set(prefix().get_codditta());
return true;
}
if (name == "#STUDY")
{
var.set(firm2dir(-1));
return true;
}
if (name == "#TODAY")
{
const TDate oggi(TODAY);
var.set(oggi);
return true;
}
if (name == "#USER")
{
var.set(user());
return true;
const TFixed_string n((const char*)name+8);
if (n == "ADMINISTATOR")
{
var.set(dongle().administrator());
return true;
}
if (n == "FIRM")
{
var.set(prefix().get_codditta());
return true;
}
if (n == "STUDY")
{
var.set(firm2dir(-1));
return true;
}
if (n == "DATE")
{
const TDate oggi(TODAY);
var.set(oggi);
return true;
}
if (n == "USER")
{
var.set(user());
return true;
}
}
return false;
}
bool TAlex_virtual_machine::set_usr_val(const TString& name, const TVariant& var)
{
if (name == "#FIRM")
if (name.starts_with("#SYSTEM."))
{
return prefix().set_codditta(var.as_int());
const TFixed_string n((const char*)name+8);
if (n == "FIRM")
{
return prefix().set_codditta(var.as_int());
}
}
return false;
}

View File

@ -17,19 +17,28 @@ END
BUTTON DLG_NEXTREC 10 2
BEGIN
PROMPT -13 -1 ""
PROMPT -14 -1 ""
PICTURE 124
MESSAGE EXIT,K_NEXT
MESSAGE EXIT,K_F11
END
BUTTON DLG_QUIT 10 2
BUTTON DLG_LASTREC 10 2
BEGIN
PROMPT -23 -1 ""
PROMPT -24 -1 ""
PICTURE 1671
MESSAGE EXIT,K_F10
END
BUTTON DLG_ELABORA 10 2
BEGIN
PROMPT -34 -1 ""
PICTURE BMP_LASTREC
MESSAGE EXIT,K_QUIT
END
BUTTON DLG_DELREC 10 2
BEGIN
PROMPT -33 -1 "Abort"
PROMPT -44 -1 "Abort"
MESSAGE EXIT,K_DEL
END