diff --git a/ba/ba8201.cpp b/ba/ba8201.cpp index 3f6d8b9ae..854843e4e 100755 --- a/ba/ba8201.cpp +++ b/ba/ba8201.cpp @@ -959,8 +959,8 @@ bool TSQLite::import(int logicnum) sql << rd.Fd[i].Name << ' '; switch (rd.Fd[i].TypeF) { - case _alfafld: - case _memofld: sql << "TEXT"; break; + case _alfafld: sql << "TEXT"; break; + case _memofld: sql << "BLOB"; break; case _datefld: sql << "DATE"; break; default : sql << "NUMERIC"; break; } @@ -1103,6 +1103,11 @@ int TSQL_recordset::on_get_items(int argc, char** values, char** columns) if (xvt_str_compare_ignoring_case(fldtype, "NUMERIC") == 0) { info->_type = _realfld; + } else + if (xvt_str_compare_ignoring_case(fldtype, "BLOB") == 0) + { + info->_type = _memofld; + info->_width = 50; } } _column.add(info); @@ -1113,9 +1118,12 @@ int TSQL_recordset::on_get_items(int argc, char** values, char** columns) for (int i = 0; i < argc; i++) if (values[i] && *values[i]) { TRecordset_column_info& info = (TRecordset_column_info&)_column[i]; - const int len = strlen(values[i]); - if (len > info._width) - info._width = len; + if (info._type == _alfafld || info._type == _realfld) + { + const int len = strlen(values[i]); + if (len > info._width) + info._width = len; + } } } @@ -1186,6 +1194,7 @@ const TRecordset_column_info& TSQL_recordset::column_info(unsigned int c) const return (const TRecordset_column_info&)_column[c]; } +// Funzione chiamata per riempire la pagina corrente delle righe della query int TSQL_recordset::on_get_rows(int argc, char** values, char** columns) { TArray* a = new TArray; @@ -1194,9 +1203,22 @@ int TSQL_recordset::on_get_rows(int argc, char** values, char** columns) TVariant* var = new TVariant; switch (column_info(c)._type) { - case _alfafld: var->set(values[c]); break; - case _datefld: var->set(TDate(values[c])); break; - default : var->set(real(values[c])); break; + case _alfafld: + var->set(values[c]); + break; + case _memofld: + { + TFixed_string memo(values[c]); + memo.replace(char(0xB6), '\n'); + var->set(memo); + } + break; + case _datefld: + var->set(TDate(values[c])); + break; + default: + var->set(real(values[c])); + break; } a->add(var, c); } diff --git a/ba/ba8300.cpp b/ba/ba8300.cpp index be3f1da63..a74f70879 100755 --- a/ba/ba8300.cpp +++ b/ba/ba8300.cpp @@ -429,7 +429,7 @@ class TSection_properties_mask : public TFont_button_mask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); - void set_num(short id, short num); + void set_num(short id, long num); short get_num(short id) const; void vedo_non_vedo(); @@ -441,7 +441,7 @@ public: TSection_properties_mask(); }; -void TSection_properties_mask::set_num(short id, short num) +void TSection_properties_mask::set_num(short id, long num) { set(id, num2str(num)); } @@ -455,6 +455,8 @@ void TSection_properties_mask::vedo_non_vedo() { const char type = get(F_TYPE)[0]; const int level = get_int(F_LEVEL); + show(F_X, level == 0 && type != 'H'); + show(F_Y, level == 0 && type != 'H'); show(F_GROUP_BY, type == 'H' && level > 1); show(F_HIDE_IF_NEEDED, level == 0 && type != 'B'); enable(DLG_DELREC, level > 1); @@ -489,6 +491,11 @@ void TSection_properties_mask::set_section(const TReport_section& rs) set(F_TYPE, s); set(F_LEVEL, rs.level()); + if (rs.level() == 0) + { + set_num(F_X, rs.pos().x); + set_num(F_Y, rs.pos().y); + } set_num(F_DX, rs.width()); set_num(F_DY, rs.height()); @@ -506,6 +513,11 @@ void TSection_properties_mask::set_section(const TReport_section& rs) void TSection_properties_mask::get_section(TReport_section& rs) const { + if (rs.level() == 0) + { + const TPoint pos(get_num(F_X), get_num(F_Y)); + rs.set_pos(pos); + } rs.set_width(get_num(F_DX)); rs.set_height(get_num(F_DY)); rs.show(!get_bool(F_HIDDEN)); @@ -901,6 +913,7 @@ void TReport_mask::section_properties() _is_dirty = true; break; case K_DEL: + if (yesno_box(TR("Confermare l'eliminazione della sezione"))) { const char t = rs.type(); const int l = rs.level(); diff --git a/ba/ba8300c.uml b/ba/ba8300c.uml index 6d955f039..baaab2b9b 100755 --- a/ba/ba8300c.uml +++ b/ba/ba8300c.uml @@ -17,6 +17,18 @@ BEGIN FLAGS "D" END +STRING F_Y 6 +BEGIN + PROMPT 1 2 "Riga " + FLAGS "R" +END + +STRING F_X 6 +BEGIN + PROMPT 21 2 "Colonna " + FLAGS "R" +END + STRING F_DX 6 BEGIN PROMPT 1 3 "Larghezza " diff --git a/ba/ba8302.cpp b/ba/ba8302.cpp index 2e4ae9cfa..afde54af3 100755 --- a/ba/ba8302.cpp +++ b/ba/ba8302.cpp @@ -570,6 +570,8 @@ void TReport_section::save(TXmlItem& root) const } item.SetAttr("type", tipo); item.SetAttr("level", level()); + set_num_attr(item, "x", pos().x); + set_num_attr(item, "y", pos().y); set_num_attr(item, "width", width()); set_num_attr(item, "height", height()); item.SetAttr("hidden", _hidden); @@ -592,6 +594,8 @@ void TReport_section::save(TXmlItem& root) const void TReport_section::load(const TXmlItem& sec) { + _pos.x = get_num_attr(sec, "x"); + _pos.y = get_num_attr(sec, "y"); set_width(get_num_attr(sec, "width")); set_height(get_num_attr(sec, "height")); force_page_break(sec.GetBoolAttr("pagebreak")); @@ -633,7 +637,7 @@ void TReport_section::load(const TXmlItem& sec) TReport_section::TReport_section(TReport& r, char t, int l) : _report(r), _type(t), _level(l), _font(NULL), - _size(0,0), _page_break(false), _hidden_if_needed(false), + _size(0,0), _pos(0,0), _page_break(false), _hidden_if_needed(false), _hidden(false), _deactivated(false) { } @@ -989,7 +993,7 @@ void TReport_field::draw_text(TWindow& win, const char* text, TReport_draw_mode if (rct.height() > 100) { - const int columns = rct.width() / 100; + const unsigned columns = rct.width() / 100; int rows = rct.height() / 100; TParagraph_string str(text, columns); if (str.items() < rows) @@ -1010,9 +1014,10 @@ void TReport_field::draw_text(TWindow& win, const char* text, TReport_draw_mode rctline.y = ybase + 100*row; rctline.set_height(100); win.log2dev(rctline, r); - if (halign == 'J' && row == rows-1) + const char* line = str.get(); + if (halign == 'J' && (row == rows-1 || strlen(line) < columns/2)) halign = 'L'; - advanced_draw_text(win, str.get(), r, halign, valign); + advanced_draw_text(win, line, r, halign, valign); } } else @@ -1416,7 +1421,14 @@ TReport_section* TReport::find_section(char type, int level) const bool TReport::kill_section(char type, int level) { TString4 key; build_section_key(type, level, key); - return _sections.remove(key); + const bool ok = _sections.remove(key); + if (ok && level > 1 && type != 'B') + { + // Cancello anche testa/coda corrispondente + build_section_key(type == 'H' ? 'F' : 'H', level, key); + _sections.remove(key); + } + return ok; } int TReport::find_max_level(char type) const @@ -1464,7 +1476,7 @@ TReport_section& TReport::section(char type, int level) if (sec == NULL) { sec = new TReport_section(*this, type, level); - TString4 key; key.format("%c%d", type, level); + TString4 key; build_section_key(type, level, key); _sections.add(key, sec); } return *sec; @@ -1691,6 +1703,8 @@ bool TReport::execute_prescript() { TString80 str; ok = _prescript.execute(*this, str); + if (recordset() != NULL) + recordset()->ask_variables(false); } else { diff --git a/ba/ba8302.h b/ba/ba8302.h index 856e967c7..92405031b 100755 --- a/ba/ba8302.h +++ b/ba/ba8302.h @@ -139,7 +139,8 @@ class TReport_section : public TArray char _type; // Head,Body,Tail int _level; // 0,1,2,... - TPoint _size; // In centesimi + TPoint _pos; // Posizione assoluta in centesimi, default (0,0) + TPoint _size; // Dimensioni in centesimi, default (0,0) TString _groupby; bool _page_break, _hidden_if_needed, _hidden, _deactivated; TReport_script _prescript, _postscript; @@ -168,6 +169,8 @@ public: const TPoint& size() const { return _size; } TPoint compute_size() const; bool compute_rect(TRectangle& rct) const; + const TPoint& pos() const { return _pos; } + void set_pos(const TPoint& p) { _pos = p; } bool page_break() const { return _page_break; } void force_page_break(bool pb) { _page_break = pb; } diff --git a/ba/ba8303.cpp b/ba/ba8303.cpp index 301f2be03..6e9274721 100755 --- a/ba/ba8303.cpp +++ b/ba/ba8303.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "ba8201.h" @@ -43,8 +44,8 @@ PNT TPrint_preview_window::log2dev(long lx, long ly) const pnt.v = short(ly * _zoom / 1000); const TPoint orig = origin(); - pnt.h -= short(orig.x); - pnt.v -= short(orig.y); + pnt.h -= short(orig.x*10); + pnt.v -= short(orig.y*10); return pnt; } @@ -52,7 +53,12 @@ PNT TPrint_preview_window::log2dev(long lx, long ly) const void TPrint_preview_window::update() { if (!_locked) + { _printer->print_page(_page); + TString80 str; + str.format(FR("Pagina %u di %u"), _page, _last); + statbar_set_title(TASK_WIN, str); + } } #define POPUP_FIRST 20883 @@ -174,11 +180,10 @@ TPrint_preview_window::TPrint_preview_window(int x, int y, int dx, int dy, WINDO : TField_window(x, y, dx, dy, parent, owner), _printer(printer), _page(1), _last(0), _zoom(100) { - RCT r; xvt_vobj_get_client_rect(win(), &r); - _zoom = 100 * r.right / 800; + RCT rct; xvt_vobj_get_client_rect(win(), &rct); + _zoom = 100 * rct.right / 800; - const TPoint ps = printer->page_size(); - set_scroll_max(ps.x/4, ps.y/4); + set_scroll_max(rct.right, rct.bottom); } /////////////////////////////////////////////////////////// @@ -645,19 +650,30 @@ bool TReport_printer::open_page() _report.set_curr_page(_page); - _delta.x = _delta.y = 0; + _delta.reset(); _page_break_allowed = false; if (ok && preview_mode()) // Clear page needed draw_preview_page(); - print_section('B', 0); + TReport_section* page_background = _report.find_section('B', 0); + if (page_background != NULL) + { + _delta = page_background->pos(); + print_section(*page_background); + _delta.reset(); + } + if (_page == 1) _delta.y += print_section('H', 1); TReport_section* page_head = _report.find_section('H', 0); if (page_head != NULL && (_page > 1 || !page_head->hidden_if_needed())) + { + _delta += page_head->pos(); _delta.y += print_section(*page_head); + _delta.x = 0; + } return ok; } @@ -669,7 +685,7 @@ bool TReport_printer::close_page() TReport_section* page_foot = _report.find_section('F', 0); if (page_foot != NULL && (!_is_last_page || !page_foot->hidden_if_needed())) { - _delta.x = 0; + _delta.x = page_foot->pos().x; _delta.y = _logical_foot_pos; print_section(*page_foot); } @@ -736,7 +752,7 @@ long TReport_printer::print_section(TReport_section& rs) rs.execute_postscript(); - if (_page_is_open && preview_mode()) + if (_page_is_open && height > 0 && preview_mode()) create_links(rs); return height; @@ -744,10 +760,8 @@ long TReport_printer::print_section(TReport_section& rs) bool TReport_printer::print_loop() { - if (_report.recordset() == NULL) - return false; - TRecordset& rex = *_report.recordset(); - if (rex.items() <= 0) + TRecordset* rex = _report.recordset(); + if (rex == NULL || rex->items() <= 0) return false; const TPoint siz = page_size(); @@ -760,8 +774,13 @@ bool TReport_printer::print_loop() const double colonne_pagina = pollici_pagina_x * _report.cpi(); _logical_page_width = long(colonne_pagina*100.0); - const long logical_footer_height = _report.section('F',0).compute_size().y; - _logical_foot_pos = _logical_page_height - logical_footer_height; + const TReport_section& footer = _report.section('F',0); + _logical_foot_pos = footer.pos().y; + if (_logical_foot_pos <= 0) + { + const long logical_footer_height = footer.compute_size().y; + _logical_foot_pos = _logical_page_height - logical_footer_height; + } _report.unmap_font(); // Gestire bene le riscalature @@ -778,7 +797,7 @@ bool TReport_printer::print_loop() _is_last_page = false; open_page(); bool aborted = false; - for (bool ok = rex.move_to(0); ok; ok = rex.move_next()) + for (bool ok = rex->move_to(0); ok; ok = rex->move_next()) { if (_pageto >= _pagefrom && _page > _pageto || _print_aborted) // out of range { @@ -796,7 +815,7 @@ bool TReport_printer::print_loop() _report.evaluate(expr, var, _alfafld); const TString& grp = var.as_string(); newgroup.add(grp, g); - if (newgroup.row(g) != oldgroup.row(g) || rex.current_row() == 0) + if (newgroup.row(g) != oldgroup.row(g) || rex->current_row() == 0) changed = g; } if (changed) @@ -807,7 +826,7 @@ bool TReport_printer::print_loop() _delta.y += last_body_height; _delta.x = 0; - if (rex.current_row() > 0) + if (rex->current_row() > 0) { for (int g = 2; g <= changed; g++) _delta.y += print_section('F', g); @@ -851,7 +870,7 @@ bool TReport_printer::print_loop() _delta.y += print_section('F', g); } - if (rex.eof()) + if (rex->eof()) print_section('F', 1); _is_last_page = true; close_page(); diff --git a/ba/ba8304.cpp b/ba/ba8304.cpp index 8b0e53d33..4de2c78c6 100755 --- a/ba/ba8304.cpp +++ b/ba/ba8304.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "ba8303.h" #include "ba8304.h" @@ -35,7 +36,7 @@ void TVariant_stack::roll(int depth) const int sp = _sp-depth-1; if (sp >= 0) { - TObject* var = _var.remove(sp); + TObject* var = _var.remove(sp, true); _var.insert(var, _sp-1); } } @@ -87,16 +88,17 @@ enum AVM_opcode avm_cmp_eq, avm_cmp_gt, avm_cmp_gteq, avm_cmp_lt, avm_cmp_lteq, avm_cmp_noteq, avm_div, avm_do, avm_dot, avm_drop, avm_dup, avm_else, avm_execute, - avm_false, avm_fetch, - avm_if, + avm_false, avm_fetch, avm_fload, + avm_i, avm_if, + avm_j, avm_loop, - avm_mon, avm_mul, + avm_mod, avm_mon, avm_mul, avm_or, avm_over, - avm_push, + 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, - avm_usrword, + avm_until, avm_usrword, avm_warm, avm_while, avm_zzz }; @@ -110,16 +112,17 @@ const char* AVM_TOKENS[avm_zzz+1] = "=", ">", ">=", "<", "<=", "<>", "/", "DO", ".", "DROP", "DUP", "ELSE", "EXECUTE", - "FALSE", "@", - "IF", + "FALSE", "@", "FLOAD", + "I", "IF", + "J", "LOOP", - "MON", "*", + "MOD", "MON", "*", "OR", "OVER", - "PUSH", + "+LOOP", "PUSH", "REPEAT", "R>", "R@", ">R", "ROT", "!", "-", "SWAP", "THEN", "TRUE", - "#", + "UNTIL", "#", "WARM", "WHILE" }; @@ -127,6 +130,7 @@ class TAVM_op : public TObject { AVM_opcode _op; TVariant _var; + bool _break_pointer; public: const TVariant& var() const { return _var; } @@ -140,19 +144,19 @@ public: }; TAVM_op::TAVM_op(AVM_opcode o, const TString& str) - : _op(o), _var(str) + : _op(o), _var(str), _break_pointer(false) { } TAVM_op::TAVM_op(AVM_opcode o, const real& num) - : _op(o), _var(num) + : _op(o), _var(num), _break_pointer(false) { } TAVM_op::TAVM_op(AVM_opcode o, const long num) - : _op(o), _var(num) + : _op(o), _var(num), _break_pointer(false) { } TAVM_op::TAVM_op(AVM_opcode o) - : _op(o) + : _op(o), _break_pointer(false) { } /////////////////////////////////////////////////////////// @@ -184,9 +188,8 @@ void TAVM_list_window::update() TString str; int tab = 6; - const int first = origin().y; - const int last = min(_bc->items(), first+rows()); - for (int i = first; i < last; i++) + const int last = min(_bc->items(), rows()); + for (int i = 0; i < last; i++) { if (_ip == i) { @@ -199,7 +202,9 @@ void TAVM_list_window::update() const AVM_opcode co = op.op(); const TVariant& var = op.var(); - if (co == avm_else || co == avm_then) + 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) { @@ -219,7 +224,8 @@ void TAVM_list_window::update() str << " (" << var.as_string() << ')'; } printat(tab, i, str); - if (co == avm_if || co == avm_else) + if (co == avm_if || co == avm_else || + co == avm_do || co == avm_begin || co == avm_while) tab += 2; } } @@ -311,6 +317,7 @@ protected: public: TAVM_list_window& monitor() { return (TAVM_list_window&)((TAVM_list_field&)field(101)).win(); } TAVM_stack_window& stacker() { return (TAVM_stack_window&)((TAVM_list_field&)field(102)).win(); } + TAVM_stack_window& rstacker() { return (TAVM_stack_window&)((TAVM_list_field&)field(103)).win(); } TAVM_monitor(); }; @@ -442,7 +449,6 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode) { TString str(256); bytecode.destroy(); - while (get_token(instr, str)) { TAVM_op* op = NULL; @@ -505,12 +511,26 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode) } op = new TAVM_op(oc); break; + case avm_loop: + case avm_plus_loop: + { + const do_pos = find_matching(bytecode, avm_do); + if (do_pos < 0) + { + _last_error.cut(0) << str << " without matching DO"; + log_error(_last_error); + return false; + } + op = new TAVM_op(oc, do_pos); + } + break; case avm_repeat: + case avm_until: { const int begin_pos = find_matching(bytecode, avm_begin); if (begin_pos < 0) { - _last_error = "REPEAT without matching BEGIN"; + _last_error.cut(0) << str << " without matching BEGIN"; log_error(_last_error); return false; } @@ -579,6 +599,7 @@ void TAVM::execute(const TAVM_op& op) v0.set(r); } 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_cmp_eq : _stack.push(compare_tos_nos() == 0); break; @@ -597,7 +618,19 @@ void TAVM::execute(const TAVM_op& op) _stack.push(n); } break; - case avm_do: break; + case avm_do: + { + const TVariant& start = _stack.pop(); + const TVariant& limit = _stack.pop(); + if (start.compare(limit) < 0) + { + _rstack.push(limit); + _rstack.push(start); + } + else + _ip = op.var().as_int(); + } + break; case avm_dot: /* *_outstr << _stack.pop().as_string(); */ break; case avm_drop: _stack.drop(); break; case avm_dup: _stack.push(_stack.peek()); break; @@ -619,11 +652,36 @@ 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 + } + 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_loop: break; + case avm_j: _stack.push(_rstack.peek(2)); break; + case avm_loop: + { + TVariant& start = _rstack.pop(); + const TVariant& limit = _rstack.pop(); + start.add(TVariant(UNO)); + _stack.push(limit); + _stack.push(start); + _ip = op.var().as_int()-1; + } + break; + case avm_mod: + { + const long i0 = _stack.pop().as_int(); + const long i1 = _stack.pop().as_int(); + _stack.push(i1 % i0); + } + break; case avm_mon: { lock_preview_update(true); @@ -650,6 +708,16 @@ void TAVM::execute(const TAVM_op& op) } break; case avm_over: _stack.push(_stack.peek(1)); break; + case avm_plus_loop: + { + TVariant& start = _rstack.pop(); + const TVariant& limit = _rstack.pop(); + start.add(_stack.pop()); + _stack.push(limit); + _stack.push(start); + _ip = op.var().as_int()-1; + } + break; case avm_push: _stack.push(op.var()); break; case avm_repeat: _ip = op.var().as_int(); break; case avm_rdrop: _stack.push(_rstack.pop()); break; @@ -678,6 +746,10 @@ void TAVM::execute(const TAVM_op& op) case avm_swap: _stack.roll(1); break; case avm_then: break; case avm_true: _stack.push(1L); break; + case avm_until: + if (_stack.pop().is_zero()) + _ip = op.var().as_int(); + break; case avm_usrword: { const long usrword = op.var().as_int(); @@ -722,10 +794,12 @@ bool TAVM::execute(const TBytecode& cmdline, ostream& outstr) monitor.set_bytecode(_bc, _ip); TAVM_stack_window& stacker = _mon.stacker(); stacker.set_stack(_stack); + TAVM_stack_window& rstacker = _mon.rstacker(); + rstacker.set_stack(_rstack); const KEY k = _mon.run(); switch (k) { - case K_NEXT: monitor.force_update(); stacker.force_update(); break; + case K_NEXT: monitor.force_update(); stacker.force_update(); rstacker.force_update(); break; case K_DEL : abort_printing(); case K_QUIT: _mon.close(); lock_preview_update(false); break; default: break; @@ -815,10 +889,9 @@ void TAlex_virtual_machine::cold_restart() // Ripartenza a freddo bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) const { - if (name == "#TODAY") + if (name == "#ADMINISTATOR") { - const TDate oggi(TODAY); - var.set(oggi); + var.set(dongle().administrator()); return true; } if (name == "#FIRM") @@ -831,6 +904,17 @@ bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) cons 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; + } return false; } diff --git a/ba/ba8304.uml b/ba/ba8304.uml index b9baefbfa..a599991d0 100755 --- a/ba/ba8304.uml +++ b/ba/ba8304.uml @@ -1,13 +1,18 @@ -PAGE "Monitor" -1 -1 40 20 +PAGE "Monitor" -1 -1 50 20 -LIST 101 -3 13 +LIST 101 24 -3 BEGIN PROMPT 0 0 "" END -STACK 102 -3 -3 +STACK 102 -3 10 BEGIN - PROMPT 0 14 "" + PROMPT 27 0 "" +END + +STACK 103 -3 -3 +BEGIN + PROMPT 27 11 "" END BUTTON DLG_NEXTREC 10 2