From dbc8341d80a271857f9091d52ebe1a8dfc8f240a Mon Sep 17 00:00:00 2001 From: guy Date: Tue, 27 Apr 2004 15:36:39 +0000 Subject: [PATCH] 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 --- ba/ba8201.cpp | 41 +++++++- ba/ba8201.h | 5 +- ba/ba8300.cpp | 30 +++++- ba/ba8300.h | 1 + ba/ba8300b.uml | 55 ++++++++++- ba/ba8302.cpp | 235 ++++++++++++++++++++++++++++++++++++++------ ba/ba8302.h | 43 ++++++--- ba/ba8304.cpp | 258 +++++++++++++++++++++++++++++++++++-------------- ba/ba8304.uml | 19 +++- 9 files changed, 560 insertions(+), 127 deletions(-) diff --git a/ba/ba8201.cpp b/ba/ba8201.cpp index 854843e4e..0d33f460c 100755 --- a/ba/ba8201.cpp +++ b/ba/ba8201.cpp @@ -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 << '\''; diff --git a/ba/ba8201.h b/ba/ba8201.h index d6c4baddf..27aea0c2c 100755 --- a/ba/ba8201.h +++ b/ba/ba8201.h @@ -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; diff --git a/ba/ba8300.cpp b/ba/ba8300.cpp index a74f70879..88b83938a 100755 --- a/ba/ba8300.cpp +++ b/ba/ba8300.cpp @@ -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()); + } } /////////////////////////////////////////////////////////// diff --git a/ba/ba8300.h b/ba/ba8300.h index e93755eeb..84d5df363 100755 --- a/ba/ba8300.h +++ b/ba/ba8300.h @@ -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 diff --git a/ba/ba8300b.uml b/ba/ba8300b.uml index 42a78adb6..2a9978ca2 100755 --- a/ba/ba8300b.uml +++ b/ba/ba8300b.uml @@ -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 diff --git a/ba/ba8302.cpp b/ba/ba8302.cpp index afde54af3..d74315a0c 100755 --- a/ba/ba8302.cpp +++ b/ba/ba8302.cpp @@ -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() diff --git a/ba/ba8302.h b/ba/ba8302.h index 92405031b..763a43821 100755 --- a/ba/ba8302.h +++ b/ba/ba8302.h @@ -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(); diff --git a/ba/ba8304.cpp b/ba/ba8304.cpp index 4de2c78c6..55c89ec0f 100755 --- a/ba/ba8304.cpp +++ b/ba/ba8304.cpp @@ -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; } diff --git a/ba/ba8304.uml b/ba/ba8304.uml index a599991d0..22dfdde31 100755 --- a/ba/ba8304.uml +++ b/ba/ba8304.uml @@ -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