diff --git a/ba/alex.alx b/ba/alex.alx new file mode 100755 index 000000000..234078996 --- /dev/null +++ b/ba/alex.alx @@ -0,0 +1,23 @@ +: 2DUP ( n1 n2 -- n1 n2 n1 n2 ) + OVER OVER +; + +: NIP ( n1 n2 -- n2 ) + SWAP DROP +; + +: -ROT ( n1 n2 n3 -- n3 n1 n2 ) + ROT ROT +; + +: TUCK ( n1 n2 -- n2 n1 n2 ) + SWAP OVER +; + +: +! ( n1 a1 -- ) + DUP @ ROT + ! +; + +: INCR ( a1 -- ) + 1 SWAP +! +; diff --git a/ba/ba3100.cpp b/ba/ba3100.cpp index 1d8977a07..1c0924ce8 100755 --- a/ba/ba3100.cpp +++ b/ba/ba3100.cpp @@ -21,7 +21,7 @@ #define TAB_REGISTRI "REG" #define TAB_VALUTE "%VAL" #define TAB_VERSAMENTI "%VER" -#define TAB_MAGAZZINI "MAG" +// #define TAB_MAGAZZINI "MAG" // Spostato in mg0 -0 #define TAB_GRMERC "GMC" class TGeneric_table_app : public TTable_application @@ -636,8 +636,8 @@ bool TGeneric_table_app::user_create() if (name == TAB_BANCHE) mask.set_handler(102, codcab_handler); - if (name == TAB_MAGAZZINI) - mask.set_handler(101, codmag_handler); +// if (name == TAB_MAGAZZINI) // Spostato in mg0 -0 +// mask.set_handler(101, codmag_handler); if (name == TAB_GRMERC) mask.set_handler(101, codgmc_handler); diff --git a/ba/ba8201.cpp b/ba/ba8201.cpp index 706a7b44d..06e81b5a9 100755 --- a/ba/ba8201.cpp +++ b/ba/ba8201.cpp @@ -33,14 +33,19 @@ void TVariant::set_null() void TVariant::set(const char* str) { - if (_type == _alfafld) - *((TString*)_ptr) = str; - else + if (str != NULL) { - set_null(); - _type = _alfafld; - _ptr = new TString(str); + if (_type == _alfafld) + *((TString*)_ptr) = str; + else + { + set_null(); + _type = _alfafld; + _ptr = new TString(str); + } } + else + set_null(); } void TVariant::set(const real& r) @@ -257,6 +262,7 @@ class TTable_names : public TObject { TAssoc_array _names; TArray _ids; + long _filled; protected: void fill(); @@ -265,6 +271,8 @@ protected: public: const TString& name(int logic_num); int logic_num(const TString& name); + + TTable_names() : _filled(0) { } } _table_names; void TTable_names::add_file(int logic, const TString& table) @@ -277,24 +285,28 @@ void TTable_names::add_file(int logic, const TString& table) void TTable_names::fill() { - FileDes dir; - CGetFile(LF_DIR, &dir, _nolock, NORDIR); - const int nfiles = (int)dir.EOD; + if (_filled != prefix().get_codditta()) + { + FileDes dir; + CGetFile(LF_DIR, &dir, _nolock, NORDIR); + const int nfiles = (int)dir.EOD; - TFilename n; - for (int logic = LF_USER; logic < nfiles; logic++) - { - const FileDes& fd = prefix().get_filedes(logic); - n = fd.SysName; n = n.name(); n.upper(); - if (_names.objptr(n) == NULL) - add_file(logic, n); + TFilename n; + for (int logic = LF_USER; logic < nfiles; logic++) + { + const FileDes& fd = prefix().get_filedes(logic); + n = fd.SysName; n = n.name(); n.upper(); + if (_names.objptr(n) == NULL) + add_file(logic, n); + } + _filled = prefix().get_codditta(); } } int TTable_names::logic_num(const TString& name) { TString* str = (TString*)_names.objptr(name); - if (str == NULL) + if (str == NULL && isalpha(name[0])) { fill(); str = (TString*)_names.objptr(name); @@ -303,7 +315,7 @@ int TTable_names::logic_num(const TString& name) { if (isdigit(name[0])) { - if (name.right(1) == '@') + if (name.right(1) == "@") add_file(-atoi(name), name); else add_file(atoi(name), name); @@ -1836,7 +1848,7 @@ const TVariant& TISAM_recordset::get(const char* name) const { table_end = fldname.find('-'); if (table_end > 0) - field_start++; + field_start = table_end+2; } int logic = 0; const char* field = name; diff --git a/ba/ba8300.cpp b/ba/ba8300.cpp index 456eab06a..0dfa6fadc 100755 --- a/ba/ba8300.cpp +++ b/ba/ba8300.cpp @@ -135,7 +135,9 @@ bool TReport_base_mask::on_field_event(TOperable_field& o, TField_event e, long { TReport_script s; s.set(o.get()); + _report.set_interactive(true); s.compile(_report); + _report.set_interactive(false); } break; default: diff --git a/ba/ba8300.h b/ba/ba8300.h index c213d0809..ceb3e0490 100755 --- a/ba/ba8300.h +++ b/ba/ba8300.h @@ -32,6 +32,7 @@ #define F_CODVAL 140 #define F_LINK 141 #define F_LIST 142 +#define F_INCLUDE 143 #define F_LEVEL 160 #define F_GROUP_BY 161 diff --git a/ba/ba8300d.uml b/ba/ba8300d.uml index d9e139a88..52da41e84 100755 --- a/ba/ba8300d.uml +++ b/ba/ba8300d.uml @@ -27,14 +27,19 @@ ENDPAGE PAGE "Avanzate" -1 -1 50 16 -MEMO F_PRESCRIPT 48 6 +MEMO F_INCLUDE 48 2 BEGIN - PROMPT 1 0 "Script iniziale" + PROMPT 1 0 "Librerie (,) " END -MEMO F_POSTSCRIPT 48 5 +MEMO F_PRESCRIPT 48 6 BEGIN - PROMPT 1 6 "Script finale" + PROMPT 1 2 "Script iniziale" +END + +MEMO F_POSTSCRIPT 48 3 +BEGIN + PROMPT 1 8 "Script finale" END BUTTON DLG_CANCEL 10 2 diff --git a/ba/ba8302.cpp b/ba/ba8302.cpp index 290e07545..2277f8693 100755 --- a/ba/ba8302.cpp +++ b/ba/ba8302.cpp @@ -691,7 +691,7 @@ TString& TReport_script::translate_message() const { line.ltrim(6); line.trim(); - alex << "0 = IF "; + alex << "#THIS @ 0= IF "; } FOR_EACH_TOKEN(line, tok) { @@ -702,8 +702,11 @@ TString& TReport_script::translate_message() const cmd = msg.left(comma); args = msg.mid(comma+1); fld = args.get(0); - if (fld[0] != '#') + if (isdigit(fld[0]) && isdigit(fld[fld.len()-1])) + { fld.insert("#", 0); + args.add(fld, 0); + } } else { @@ -712,42 +715,7 @@ TString& TReport_script::translate_message() const fld.cut(0); } - if (cmd.starts_with("AL")) // ALIGN - { - alex << fld << " ALIGN_FIELD_" << args.get(1) << ' '; - } else - if (cmd.starts_with("CO")) // COPY - { - alex << "#THIS @ " << fld << " ! "; - } else - if (cmd.starts_with("AD")) // ADD - { - alex << "#THIS @ " << fld << " @ + "<< fld << " ! "; - } else - if (cmd.starts_with("IN")) // INC - { - alex << fld << " @ 1 + "<< fld << " ! "; - } else - if (cmd.starts_with("RE")) // RESET - { - alex << "\"\" " << fld << " ! "; - } else - if (cmd.starts_with("SH")) // SHOW - { - alex << fld << " SHOW "; - } else - if (cmd.starts_with("EN")) // EN - { - alex << fld << " ENABLE "; - } else - if (cmd.starts_with("DI")) // DISABLE - { - alex << fld << " DISABLE "; - } else - if (cmd.starts_with("HI")) // HIDE - { - alex << fld << " HIDE "; - } + alex << args << " MESSAGE_" << cmd << ' '; } if (msg_empty) alex << "THEN "; @@ -1224,7 +1192,7 @@ const TString& TReport_field::formatted_text() const void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const { - if (rdm != rdm_edit && hidden()) + if (rdm != rdm_edit && (hidden() || deactivated())) return; if (rdm == rdm_edit) @@ -1708,8 +1676,8 @@ int TReport::parse_field(const char* code, char& type, int& level, int& id) cons TReport_field* TReport::field(const TString& code) { - char type; - int level, id; + char type = ' '; + int level = -1, id = 0; const int k = parse_field(code, type, level, id); TReport_field* rf = NULL; @@ -1717,8 +1685,9 @@ TReport_field* TReport::field(const TString& code) { if (id > 0) { - TReport_section& sec = section(type, level); - rf = sec.find_field(id); + TReport_section* sec = find_section(type, level); + if (sec != NULL) + rf = sec->find_field(id); } else rf = curr_field(); @@ -1816,6 +1785,10 @@ bool TReport::load(const char* fname) set_recordset(str); } + _include = xml.GetAttr("libraries"); + FOR_EACH_TOKEN(_include, lib) + include(lib); + _prescript.load(xml, "prescript"); _postscript.load(xml, "postscript"); } @@ -1834,6 +1807,7 @@ bool TReport::save(const char* fname) const xml.SetAttr("name", name); xml.SetAttr("lpi", lpi()); xml.AddChild("description") << _description; + xml.SetAttr("libraries", _include); _font.save(xml); const char* sectype = "HBF"; @@ -2247,11 +2221,12 @@ bool TReport::on_link(const TReport_link& lnk) return false; } -TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL) +TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL), _include(15, ',') { _expressions.set_report(this); - fload("report.alx"); + include("report.alx"); // Include base libraries + _prescript.set_description("PRESCRIPT"); _postscript.set_description("POSTSCRIPT"); } diff --git a/ba/ba8302.h b/ba/ba8302.h index 5d0ce2da1..b3346382d 100755 --- a/ba/ba8302.h +++ b/ba/ba8302.h @@ -378,6 +378,7 @@ class TReport : public TAlex_virtual_machine TString _description; TReport_font _font; int _lpi; // Lines per inch + TToken_string _include; TReport_script _prescript, _postscript; TRecordset* _recordset; TReport_expr_cache _expressions; @@ -434,6 +435,9 @@ public: bool execute_prescript(); bool execute_postscript(); + void set_libraries(const char* inc) { _include = inc; } + TToken_string& get_libraries() { return _include; } + void set_description(const char* d) { _description = d; } const TString& description() const { return _description; } TImage* image(const TString& name) { return _images.image(name); } diff --git a/ba/ba8304.cpp b/ba/ba8304.cpp index 0fdc9e3a8..2952ab3b8 100755 --- a/ba/ba8304.cpp +++ b/ba/ba8304.cpp @@ -5,6 +5,8 @@ #include #include #include +#include + #include "ba8303.h" #include "ba8304.h" @@ -41,40 +43,43 @@ void TVariant_stack::roll(int depth) } } -bool TVariant_stack::push(const TVariant& var) +void TVariant_stack::push(const TVariant& var) { if (_var.objptr(_sp) == NULL) _var.add(var, _sp); else (TVariant&)_var[_sp] = var; _sp++; - return _sp < 1024; } -bool TVariant_stack::push(long n) +void TVariant_stack::push(long n) { const TVariant var(n); - return push(var); + push(var); } -bool TVariant_stack::push(const real& n) +void TVariant_stack::push(const real& n) { const TVariant var(n); - return push(var); + push(var); } -bool TVariant_stack::push(const TString& str) +void TVariant_stack::push(const TString& str) { const TVariant var(str); - return push(var); + push(var); } - void TVariant_stack::reset() { _sp = 0; } +bool TVariant_stack::overflow() const +{ + return _sp > 2048; +} + /////////////////////////////////////////////////////////// // TAVM_op /////////////////////////////////////////////////////////// @@ -85,21 +90,23 @@ enum AVM_opcode avm_add, avm_and, avm_begin, avm_call_word, avm_cold, - avm_cmp_eq, avm_cmp_gt, avm_cmp_gteq, avm_cmp_lt, avm_cmp_lteq, avm_cmp_noteq, + avm_cmp_eq, avm_cmp_gt, avm_cmp_gteq, avm_cmp_lt, avm_cmp_lteq, avm_cmp_noteq, avm_cmp_nulleq, avm_cmp_zeroeq, avm_div, avm_divide, avm_do, avm_dot, avm_drop, avm_dup, avm_else, - avm_false, avm_fetch, avm_fload, - avm_i, avm_if, + avm_fetch, avm_forget, + avm_i, avm_if, avm_include, avm_j, avm_loop, avm_mod, avm_mon, avm_mul, - avm_negate, + avm_negate, avm_null, avm_or, avm_over, avm_perform, avm_pick, avm_plus_loop, avm_push, avm_repeat, avm_rdrop, avm_rpeek, avm_rpush, avm_roll, avm_rot, avm_store, avm_sub, avm_swap, - avm_then, avm_true, + avm_then, avm_tok_fetch, avm_tok_store, + avm_strlen, avm_strmid, avm_until, avm_usrword, + avm_variable, avm_warm, avm_while, avm_zzz }; @@ -110,11 +117,11 @@ const char* AVM_TOKENS[avm_zzz+1] = "+", "AND", "BEGIN", "$CALL_WORD$", "COLD", - "=", ">", ">=", "<", "<=", "<>", + "=", ">", ">=", "<", "<=", "<>", "NULL=", "0=", "DIV", "/", "DO", ".", "DROP", "DUP", "ELSE", - "FALSE", "@", "FLOAD", - "I", "IF", + "FALSE", "@", "FORGET", + "I", "IF", "INCLUDE", "J", "LOOP", "MOD", "MON", "*", @@ -122,8 +129,8 @@ const char* AVM_TOKENS[avm_zzz+1] = "OR", "OVER", "PERFORM", "PICK", "+LOOP", "PUSH", "REPEAT", "R>", "R@", ">R", "ROLL", "ROT", - "!", "-", "SWAP", - "THEN", "TRUE", + "STRLEN", "STRMID", "!", "-", "SWAP", + "THEN", "TOK@", "TOK!", "TRUE", "UNTIL", "#", "WARM", "WHILE" }; @@ -367,6 +374,7 @@ class TAVM_monitor : public TAutomask protected: TMask_field* parse_field(TScanner& scanner); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + virtual bool on_key(KEY k); public: TAVM_list_window& monitor() { return (TAVM_list_window&)((TAVM_list_field&)field(101)).win(); } @@ -380,6 +388,19 @@ bool TAVM_monitor::on_field_event(TOperable_field& o, TField_event e, long jolly return true; } +bool TAVM_monitor::on_key(KEY k) +{ + switch (k) + { + case K_F10: + case K_F11: + stop_run(k); + return true; + default: break; + } + return TAutomask::on_key(k); +} + TMask_field* TAVM_monitor::parse_field(TScanner& scanner) { if (scanner.token().starts_with("LI")) @@ -403,6 +424,7 @@ TAVM_monitor::TAVM_monitor() class TAVM { TAlex_virtual_machine* _vm; + bool _interactive; TString _last_error; TVariant_stack _stack, _rstack; const TBytecode* _bc; // Current word (or command line) @@ -410,6 +432,7 @@ class TAVM ostream* _outstr; TAssoc_array _words; + TAssoc_array _vars; TString_array _user_words; TAVM_monitor _mon; @@ -430,8 +453,12 @@ public: bool compile(istream& instr, TBytecode& bc); bool execute(const TBytecode& bc, ostream* outstr = NULL); - void restart(bool cold); - bool do_fload(const char* fname); + void do_restart(bool cold); + bool do_include(const char* fname); + TVariant& do_fetch(const TString& name); + void do_store(const TString& name); + + void set_interactive(bool inter) { _interactive = inter; } TAVM(TAlex_virtual_machine* vm); virtual ~TAVM(); @@ -440,7 +467,12 @@ public: void TAVM::log_error(const char* str) { _last_error = str; - error_box(str); + if (_interactive) + error_box(str); +#ifdef DBG + else + statbar_set_title(TASK_WIN, str); +#endif } bool TAVM::get_token(istream& instr, TString& str) const @@ -669,13 +701,29 @@ int TAVM::compare_tos_nos() void TAVM::do_call(const TString& func) { - _rstack.push(_bc->name()); - _rstack.push(_ip+1); - _ip = -1; // will be incremented! - _bc = (TBytecode*)_words.objptr(func); + if (_stack.overflow()) + { + log_error("Stack overflow"); + _bc = NULL; + return; + } + TBytecode* bc = (TBytecode*)_words.objptr(func); + if (bc != NULL) + { + _rstack.push(_bc->name()); + _rstack.push(_ip+1); + _ip = -1; // will be incremented! + _bc = bc; + } + else + { + _last_error = func; _last_error << " ???"; + log_error(_last_error); + _bc = NULL; + } } -bool TAVM::do_fload(const char* fname) +bool TAVM::do_include(const char* fname) { TFilename name = fname; bool ok = name.custom_path(); @@ -683,12 +731,47 @@ bool TAVM::do_fload(const char* fname) { TBytecode bc; ifstream inf(name); - if (compile(inf, bc)) + ok = compile(inf, bc); + if (ok) execute(bc); } return ok; } +// Mette sullo stack il valore della variabile name +TVariant& TAVM::do_fetch(const TString& name) +{ + if (name[0] == '#') + { + TVariant var; + _vm->get_usr_val(name, var); + _stack.push(var); + } + else + { + const TVariant* var = (const TVariant*)_vars.objptr(name); + if (var != NULL) + _stack.push(*var); + else + _stack.push(NULL_VARIANT); + } + return _stack.peek(); +} + +// Legge dallo stack il valore da asseganre alla variabile name +void TAVM::do_store(const TString& name) +{ + const TVariant& var = _stack.pop(); + if (name[0] == '#') + _vm->set_usr_val(name, var); + else + { + TVariant* v = (TVariant*)_vars.objptr(name); + if (v != NULL) + *v = var; + } +} + void TAVM::execute(const TAVM_op& op) { switch(op.op()) @@ -710,13 +793,15 @@ void TAVM::execute(const TAVM_op& op) break; case avm_begin: break; case avm_call_word: do_call(op.var().as_string()); break; - case avm_cold: restart(true); _bc = NULL; break; + case avm_cold: do_restart(true); _bc = NULL; break; case avm_cmp_eq : _stack.push(compare_tos_nos() == 0); break; case avm_cmp_gt : _stack.push(compare_tos_nos() > 0); break; case avm_cmp_gteq : _stack.push(compare_tos_nos() >= 0); break; case avm_cmp_lt : _stack.push(compare_tos_nos() < 0); break; case avm_cmp_lteq : _stack.push(compare_tos_nos() <= 0); break; case avm_cmp_noteq: _stack.push(compare_tos_nos() != 0); break; + case avm_cmp_nulleq:_stack.push(_stack.pop().is_null()); break; + case avm_cmp_zeroeq:_stack.push(_stack.pop().is_zero()); break; case avm_div: { const long r0 = _stack.pop().as_int(); @@ -761,32 +846,31 @@ void TAVM::execute(const TAVM_op& op) if (_outstr != NULL) *_outstr << _stack.pop().as_string(); break; - case avm_drop: _stack.drop(); break; + case avm_drop: + if (!_stack.drop()) + { + log_error("Stack underflow"); + _bc = NULL; + } + break; case avm_dup: _stack.push(_stack.peek()); break; case avm_else: _ip = op.var().as_int(); break; - case avm_false: _stack.push(0L); break; - case avm_fetch: + case avm_fetch: do_fetch(_stack.pop().as_string()); break; + case avm_forget: { const TString& name = _stack.pop().as_string(); - TVariant var; - if (name[0] == '#') - _vm->get_usr_val(name, var); - else - { - // TBI: Get global var - } - _stack.push(var); + _vars.remove(name); + _words.remove(name); } break; - case avm_fload: do_fload(_stack.pop().as_string()); break; - break; case avm_i: _stack.push(_rstack.peek()); break; case avm_if: if (_stack.pop().is_zero()) _ip = op.var().as_int(); break; + case avm_include: do_include(_stack.pop().as_string()); break; case avm_j: _stack.push(_rstack.peek(2)); break; case avm_loop: { @@ -823,6 +907,7 @@ void TAVM::execute(const TAVM_op& op) tos.set(~tos.as_int()); } break; + case avm_null: _stack.push(NULL_VARIANT); break; case avm_or: { const TVariant& tos = _stack.pop(); @@ -832,15 +917,7 @@ void TAVM::execute(const TAVM_op& op) } break; case avm_over: _stack.push(_stack.peek(1)); break; - case avm_perform: - { - 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_perform: do_call(_stack.pop().as_string()); break; case avm_pick: _stack.push(_stack.peek(_stack.pop().as_int())); break; case avm_plus_loop: { @@ -859,16 +936,14 @@ void TAVM::execute(const TAVM_op& op) case avm_rpush: _rstack.push(_stack.pop()); break; case avm_roll: _stack.roll(_stack.pop().as_int()); break; case avm_rot: _stack.roll(2); break; - case avm_store: + case avm_store: do_store(_stack.pop().as_string()); break; + case avm_strlen: _stack.push(_stack.peek().as_string().len()); break; + case avm_strmid: { - const TString& name = _stack.pop().as_string(); - const TVariant& var = _stack.pop(); - if (name[0] == '#') - _vm->set_usr_val(name, var); - else - { - // TBI: Set global var - } + const int len = _stack.pop().as_int(); + const int frm = _stack.pop().as_int(); + const TString& str = _stack.peek().as_string(); + _stack.push(str.mid(frm, len)); break; } break; case avm_sub : @@ -880,7 +955,28 @@ void TAVM::execute(const TAVM_op& op) break; case avm_swap: _stack.roll(1); break; case avm_then: break; - case avm_true: _stack.push(1L); break; + case avm_tok_fetch: + { + const int pos = _stack.pop().as_int(); + const TString& name = _stack.pop().as_string(); + TVariant& var = do_fetch(name); + TToken_string str(var.as_string(), (char)0xB6); + const char* tok = str.get(pos); + var.set(tok); + } + break; + case avm_tok_store: + { + const int pos = _stack.pop().as_int(); + const TString& tok = _stack.pop().as_string(); + const TString name = _stack.pop().as_string(); + TVariant& var = do_fetch(name); + TToken_string str(var.as_string(), (char)0xB6); + str.add(tok, pos); + var.set(str); + do_store(name); + } + break; case avm_until: if (_stack.pop().is_zero()) _ip = op.var().as_int(); @@ -891,7 +987,8 @@ void TAVM::execute(const TAVM_op& op) _vm->execute_usr_word(usrword, _stack); } break; - case avm_warm: restart(false); _bc = NULL; break; + case avm_variable: _vars.add(_stack.pop().as_string(), NULL_VARIANT); break; + case avm_warm: do_restart(false); _bc = NULL; break; case avm_while: _ip = op.var().as_int(); break; // Jump to BEGIN default: _last_error << "Unimplemented op code: " << op.op() << '\n'; @@ -905,7 +1002,7 @@ 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) @@ -985,21 +1082,22 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr) return true; } -void TAVM::restart(bool cold) +void TAVM::do_restart(bool cold) { _stack.reset(); _rstack.reset(); if (cold) { _words.destroy(); - do_fload("alex.alx"); + _vars.destroy(); + do_include("alex.alx"); } } TAVM::TAVM(TAlex_virtual_machine* vm) - : _vm(vm), _outstr(NULL) + : _vm(vm), _outstr(NULL), _interactive(false) { - restart(true); + do_restart(true); } TAVM::~TAVM() @@ -1050,12 +1148,12 @@ bool TAlex_virtual_machine::execute(const TBytecode& bc, TString& outs) void TAlex_virtual_machine::warm_restart() // Ripartenza a caldo { - avm().restart(false); + avm().do_restart(false); } void TAlex_virtual_machine::cold_restart() // Ripartenza a freddo { - avm().restart(true); + avm().do_restart(true); } bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) const @@ -1122,11 +1220,14 @@ bool TAlex_virtual_machine::execute_usr_word(unsigned int opcode, TVariant_stack return false; } -bool TAlex_virtual_machine::fload(const char* fname) +bool TAlex_virtual_machine::include(const char* fname) { - return avm().do_fload(fname); + return avm().do_include(fname); } +void TAlex_virtual_machine::set_interactive(bool inter) +{ avm().set_interactive(inter); } + TAlex_virtual_machine::TAlex_virtual_machine() : _avm(NULL) { } diff --git a/ba/ba8304.h b/ba/ba8304.h index dc6605c0e..0f881a2ce 100755 --- a/ba/ba8304.h +++ b/ba/ba8304.h @@ -17,11 +17,12 @@ public: TVariant& peek(int depth = 0); void roll(int depth); - bool push(const TVariant& var); - bool push(long n); - bool push(const real& n); - bool push(const TString& str); + void push(const TVariant& var); + void push(long n); + void push(const real& n); + void push(const TString& str); void reset(); + bool overflow() const; TVariant_stack() : _sp(0) { } }; @@ -59,9 +60,10 @@ public: bool compile(const char* cmd, TBytecode& bc); bool execute(const TBytecode& bc, ostream& outstr); bool execute(const TBytecode& bc, TString& outstr); - bool fload(const char* fname); + bool include(const char* fname); void warm_restart(); void cold_restart(); + void set_interactive(bool inter); TAlex_virtual_machine(); virtual ~TAlex_virtual_machine(); diff --git a/ba/ba8400.cpp b/ba/ba8400.cpp index 1df245cff..6febda9b4 100755 --- a/ba/ba8400.cpp +++ b/ba/ba8400.cpp @@ -15,23 +15,23 @@ class TFormer_mask : public TAutomask { + bool _doc; + protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + void parse_field_line(const TString& line, TReport_field& rf) const; + void import_section(TScanner& scan, TReport_section& rs) const; + void import_sections(TScanner& scan, TReport& rep) const; + void import_use(TScanner& scan, TReport& rep) const; void import(); public: TFormer_mask(); }; -void TFormer_mask::import_use() +void TFormer_mask::import_use(TScanner& scan, TReport& rep) const { -} - -void TFormer_mask::import_use(TReport& rep) const -{ - TScanner scan(get(F_FORM)); - TString use; int parse_use = 0; while (scan.ok()) @@ -53,25 +53,214 @@ void TFormer_mask::import_use(TReport& rep) const else use << line << '\n'; } - } if (!use.blank()) + { + if (_doc) + { + int pos = use.find(" 33"); + if (pos >= 0 && pos < 10) + use.overwrite("4", pos+2); + pos = use.find("JOIN 34"); + if (pos >= 0) + use.overwrite("3", pos+6); + } rep.set_recordset(use); + } } -void TFormer_mask::import_sections(TReport& rep) const +void TFormer_mask::parse_field_line(const TString& line, TReport_field& rf) const { - TExportable_form frm(get(F_FORM)); - frm.export_section('G', odd_page, rep, 'B', 0); - frm.export_section('B', odd_page, rep, 'B', 2); + TToken_string head(line, ' '); + head.trim(); + head.strip_d_spaces(); + + if (head.starts_with("FI")) + { + rf.set_field(head.get(1)); + } else + if (head.starts_with("FL")) + { + const TString& flags = head.get(1); + for (int i = 0; flags[i]; i++) + { + switch (flags[i]) + { + case 'D': rf.hide(); rf.deactivate(); break; + case 'H': rf.hide(); break; + default: break; + } + } + } else + if (head.starts_with("ME")) + { + head.add("MESSAGE", 0); + TString me = rf.prescript(); + me << head << '\n'; + rf.set_prescript(head); + } else + if (head.starts_with("PR")) + { + const int x = 100*(head.get_int(1)-1); + const int y = 100*(head.get_int()-1); + rf.set_pos(x, y); + if (rf.type() == 'I') + rf.set_field(head.get()); + } +} + +void TFormer_mask::import_section(TScanner& scan, TReport_section& rs) const +{ + TToken_string head(256, ' '); + + int in_field = 0; + TReport_field* cur_field = NULL; + + while (scan.ok()) + { + TString& line = scan.line(); + if (line.empty()) + break; + + if (line.starts_with("BE")) + { + in_field++; + if (in_field == 1) + { + head.trim(); + head.strip_d_spaces(); + const TString16 str_type = head.get(0); + char type = ' '; + if (str_type.starts_with("FI")) + type = 'I'; + if (str_type.starts_with("ST")) + type = 'S'; + + if (type > ' ') + { + const int id = head.get_int(1); + const int width = 100*head.get_int(); + const int height = 100*head.get_int(); + + cur_field = new TReport_field(&rs); + cur_field->set_type(type); + if (id > 0) + cur_field->set_id(id); + if (width > 0) + cur_field->set_width(width); + if (height > 0) + { + if (_doc && type == 'S' && height >= 5 && rs.type() == 'B') + cur_field->set_height(0); + else + cur_field->set_height(height); + } + + rs.add(cur_field); + } + } + } else + if (line.starts_with("EN")) + { + if (in_field >= 0) + { + in_field--; // END of field + cur_field = NULL; + } + if (in_field < 0) + break; // END of section + } else + if (cur_field != NULL) + { + parse_field_line(line, *cur_field); + } + + head = line; + } +} + +void TFormer_mask::import_sections(TScanner& scan, TReport& rep) const +{ + while (scan.ok()) + { + TString& line = scan.line(); + if (line.empty()) + break; + + if (line.starts_with("SE")) + { + line.trim(); + line.strip_d_spaces(); + TToken_string head(line, ' '); + const TString16 str_name = head.get(1); + const TString16 str_type = head.get(); + int height = 100*head.get_int(); + char type = ' '; + int level = 0; + if (str_name.starts_with("BO")) + { + if (str_type.starts_with("OD")) + { type = 'B'; level = 1; height = 0; } + } + if (str_name.starts_with("FO")) + { + if (str_type.starts_with("LA")) + { type = 'F'; level = 1; } + if (str_type.starts_with("OD")) + { type = 'F'; level = 0; } + } else + if (str_name.starts_with("GR")) + { + if (str_type.starts_with("OD")) + { type = 'B'; level = 0; } + } else + if (str_name.starts_with("HE")) + { + if (str_type.starts_with("FI")) + { type = 'H'; level = 1; } + if (str_type.starts_with("OD")) + { type = 'H'; level = 0; } + } + if (type > ' ') + { + TReport_section& cur_sec = rep.section(type, level); + if (height >= 0) + cur_sec.set_height(height); + else + { + if (type == 'F') + { + const TPoint abolute_footer_pos(0, -height); + cur_sec.set_pos(abolute_footer_pos); + } + } + import_section(scan, cur_sec); + } + } + } + + const char* hf = "HF"; + for (int i = 0; hf[i]; i++) + { + TReport_section* sec = rep.find_section(hf[i], 0); + if (sec != NULL) + { + const bool yes = rep.find_section(hf[i], 1) != NULL; + sec->hide_if_needed(yes); + } + } } void TFormer_mask::import() { + _doc = get_bool(F_DOC); + TScanner scan(get(F_FORM)); TReport rep; - import_use(rep); - import_sections(rep); + import_use(scan, rep); + import_sections(scan, rep); + if (_doc) + rep.set_libraries("ve1100.alx"); rep.save(get(F_REPORT)); } diff --git a/ba/ba8400.h b/ba/ba8400.h index 263cbdf90..0a972aedc 100755 --- a/ba/ba8400.h +++ b/ba/ba8400.h @@ -1,2 +1,4 @@ #define F_FORM 101 #define F_REPORT 102 +#define F_DOC 103 + diff --git a/ba/ba8400a.uml b/ba/ba8400a.uml index 41b6a7425..bad81ba29 100755 --- a/ba/ba8400a.uml +++ b/ba/ba8400a.uml @@ -2,17 +2,22 @@ PAGE "Conversione Form in Report" -1 -1 62 6 -STRINGA F_FORM 256 50 +STRING F_FORM 256 50 BEGIN PROMPT 1 1 "Form " FSELECT "*.frm" END -STRINGA F_REPORT 256 50 +STRING F_REPORT 256 50 BEGIN PROMPT 1 2 "Report " END +BOOLEAN F_DOC +BEGIN + PROMPT 1 3 "Documento del modulo vendite" +END + BUTTON DLG_ELABORA 10 2 BEGIN PROMPT -13 -1 "~Elabora" diff --git a/ba/report.alx b/ba/report.alx new file mode 100755 index 000000000..c6fb80af1 --- /dev/null +++ b/ba/report.alx @@ -0,0 +1,78 @@ +\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +\ Funzioni di aiuto per implementazione messaggi +\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +: GET_POS.X ( f1 -- n1 ) GET_POS DROP ; + +: GET_POS.Y ( f1 -- n1 ) GET_POS NIP ; + +: GET_SIZE.Y ( f1 -- n1 ) GET_SIZE NIP ; + +: GET_BOTTOM ( f1 -- n1 ) + DUP + GET_POS.Y + SWAP + GET_SIZE.Y + + +; + +: OFFSET_FIELD_POS.X ( n1 -- ) + #THIS GET_POS.X \ Legge posizione x + + \ La incrementa di n1 + #THIS GET_POS.Y \ Legge posizione y + #THIS SET_POS \ Aggiorna posizione +; + +: OFFSET_FIELD_POS.Y ( n1 -- ) + #THIS GET_POS.Y \ Legge posizione y + + \ La incrementa di n1 + #THIS GET_POS.X \ Legge posizione x + SWAP \ Scambia le coordinate + #THIS SET_POS \ Aggiorna posizione +; + +: MESSAGE_ALIGN_BOTTOM ( f1 -- ) + GET_BOTTOM \ Calcola fondo di f1 + #THIS GET_BOTTOM \ Calcola fondo del campo corrente + - \ Calcola offset come differenza dei due + OFFSET_FIELD_POS.Y \ Incrementa posizione y del campo corrente +; + +: MESSAGE_ALIGN_TOP ( f1 -- ) + GET_POS.Y \ Legge posizione y del capo f1 + #THIS GET_POS.X \ Legge posizione x del campo corrente + SWAP \ Scambia le coordinate + #THIS SET_POS \ Aggiorna posizione del campo corrente +; + +: MESSAGE_ALIGN_CENTER ( f1 -- ) + GET_BOTTOM \ Calcola fondo del campo f1 + #THIS GET_BOTTOM \ Calcola fonp del campo corrente + - 2 / \ Calcola offset verticale + OFFSET_FIELD_POS.Y \ Aggiorna posizione del campo corrente +; + +\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +\ Implementazione dei vari messaggi standard +\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +: MESSAGE_ADD ( f1 -- ) + #THIS @ SWAP ! +; + +: MESSAGE_ALIGN ( s1 -- ) + "MESSAGE_ALIGN_" SWAP + \ Si crea il nome della funzione da chiamare + PERFORM +; + +: MESSAGE_COPY ( f1 -- ) + #THIS @ SWAP ! +; + +: MESSAGE_INC ( f1 -- ) + DUP @ 1 + SWAP ! +; + +: MESSAGE_RESET ( f1 -- ) + NULL SWAP ! +; diff --git a/ba/ve1100.alx b/ba/ve1100.alx new file mode 100755 index 000000000..08191dc7d --- /dev/null +++ b/ba/ve1100.alx @@ -0,0 +1,9 @@ +: _DESCRIGA +#34->DESCR @ +#DESCLUNGA @ IF + #34->DESCEST @ + + +THEN +#THIS ! +; + \ No newline at end of file