Patch level : 2.1 nopatch

Files correlati     : ba0 ba8
Ricompilazione Demo : [ ]
Commento            :

ba0 aggiunto meccanismo di chiusura automatica in caso di installazione modulo sys
ba8 aggiunto converitore di form primordiale


git-svn-id: svn://10.65.10.50/trunk@12048 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
guy 2004-05-04 08:25:23 +00:00
parent 5e9712217e
commit 2b0291afdb
22 changed files with 1471 additions and 226 deletions

View File

@ -66,7 +66,6 @@ protected: // TApplication
protected:
void deconnect_user();
bool dll_changed() const;
virtual void main_loop();
void test_temp();
@ -1021,7 +1020,7 @@ bool TMenu_application::test_programs()
user() = old_user; // Ripristino utente normale
more = TRUE; // ricontrolla
if (dll_changed()) //costringe ad uscire dal programma se si e' installato il modulo SY
if (sys_dll_changed()) //costringe ad uscire dal programma se si e' installato il modulo SY
return false;
}
_menu.set_dangerous_modules(dangerous);
@ -1092,19 +1091,11 @@ void TMenu_application::deconnect_user()
}
}
bool TMenu_application::dll_changed() const
{
TString_array list;
list_files("*.ex_", list);
list_files("*.dl_", list);
return (list.items() > 0);
}
bool TMenu_application::destroy()
{
deconnect_user();
if (dll_changed())
if (sys_dll_changed())
{
TExternal_app ba0close("ba0close.exe");
ba0close.run(TRUE,TRUE,TRUE); // run asynchronous...

View File

@ -12,6 +12,18 @@
#include "ba0101.h"
#include "ba0100.h"
///////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////
bool sys_dll_changed()
{
TString_array list;
list_files("*.ex_", list);
list_files("*.dl_", list);
return list.items() > 0;
}
///////////////////////////////////////////////////////////
// Menu management
///////////////////////////////////////////////////////////
@ -303,6 +315,10 @@ bool TMenuitem::perform_program() const
}
}
prefix().set("DEF"); // Aggiorna prefix
const bool install_app = _action.starts_with("ba1 -6", TRUE) == 0;
if (install_app && sys_dll_changed())
main_app().stop_run();
}
return ok;

View File

@ -168,5 +168,7 @@ public:
virtual ~TMenu();
};
bool sys_dll_changed();
#endif

View File

@ -8,6 +8,7 @@ int main(int argc, char** argv)
{
case 1: ba8200(argc, argv); break; // Query Generator
case 2: ba8300(argc, argv); break; // Report Generator
case 3: ba8400(argc, argv); break; // Form Converter
default: ba8100(argc, argv); break; // Record Selector
}
return 0;

View File

@ -1,5 +1,6 @@
int ba8100(int argc, char* argv[]);
int ba8200(int argc, char* argv[]);
int ba8300(int argc, char* argv[]);
int ba8400(int argc, char* argv[]);

View File

@ -300,6 +300,7 @@ protected:
protected:
bool add_file_to_tree();
void add_field_to_sheet(const char* fld, bool update);
void add_field_to_sheet(bool update = true);
void add_asterisk_to_sheet();
bool edit_file_in_tree();
@ -311,7 +312,9 @@ protected:
void move_curr_field(int dir);
void tree2sql(TString& from, TString& where);
void tree2isam(TString_array& a);
void sheet2sql();
void sheet2isam();
void edit_query();
bool select_query();
@ -521,53 +524,64 @@ void TQuery_mask::fill_fields()
enable_field_buttons();
}
// Aggiunge il campo selezionato nello spredasheet F_FIELDS allo spreadsheet F_SHEET
void TQuery_mask::add_field_to_sheet(bool update)
// Aggiunge un cmapo allo spreadsheet F_SHEET
void TQuery_mask::add_field_to_sheet(const char* fld, bool update)
{
const TRelation_node* n = curr_node();
if (n != NULL)
{
TSheet_field& sf = sfield(F_FIELDS);
const int r = sf.selected();
if (r >= 0)
TSheet_field& ff = sfield(F_SHEET);
TToken_string& row = ff.row(-1);
row = n->id();
row.add(fld);
_is_dirty = true;
if (update)
{
TToken_string& rowsel = sf.row(r);
TSheet_field& ff = sfield(F_SHEET);
TToken_string& row = ff.row(-1);
row = n->id();
row.add(rowsel.get(0));
_is_dirty = true;
if (update)
{
ff.force_update();
enable_sql_button();
}
ff.force_update();
enable_sql_button();
}
}
}
// Aggiunge il campo selezionato nello spredasheet F_FIELDS allo spreadsheet F_SHEET
void TQuery_mask::add_field_to_sheet(bool update)
{
TSheet_field& sf = sfield(F_FIELDS);
const int r = sf.selected();
if (r >= 0)
{
TToken_string& rowsel = sf.row(r);
add_field_to_sheet(rowsel.get(0), update);
}
}
// Aggiunge tutte le colonne allo sheet
void TQuery_mask::add_asterisk_to_sheet()
{
const TRelation_node* n = curr_node();
if (n != NULL)
{
TSheet_field& sf = sfield(F_FIELDS);
const int nLast = sf.items()-1;
for (int i = 0; i <= nLast; i++)
if (yesno_box("Si desisdera aggiungere tutti i campi singolarmente?"))
{
sf.select(i);
add_field_to_sheet(i == nLast);
TSheet_field& sf = sfield(F_FIELDS);
const int nLast = sf.items()-1;
for (int i = 0; i <= nLast; i++)
{
sf.select(i);
add_field_to_sheet(i == nLast);
}
sf.select(0);
}
sf.select(0);
else
add_field_to_sheet("*", true);
}
}
// Decide se attivare o meno il bottone SQL
void TQuery_mask::enable_sql_button()
{
const TSheet_field& s = sfield(F_SHEET);
enable(F_GENSQL, s.items() > 0);
const bool yes = sfield(F_SHEET).items() > 0;
enable(F_GENSQL, yes);
}
// Decide se attivare o meno i bottoni di aggiunta campi
@ -637,6 +651,37 @@ void TQuery_mask::tree2sql(TString& from, TString& where)
}
}
static bool isam_tree_handler(TTree& tree, void* jolly, word flags)
{
TRelation_node* rn = (TRelation_node*)tree.curr_node();
TString_array* a = (TString_array*)jolly;
TToken_string row;
if (a->items() == 0)
{
row << "USE " << rn->name();
}
else
{
row << "JOIN " << rn->name();
if (rn->father()->name() != a->row(0).mid(4))
row << " TO " << rn->father()->name();
if (!rn->alias().blank())
row << " ALIAS " << rn->alias();
row << " INTO ";
FOR_EACH_ARRAY_ROW(rn->join(), i, r)
row << *r << ' ';
}
a->add(row);
return false;
}
// Riempie una stringa ISAM con la relazione tra le tabelle
void TQuery_mask::tree2isam(TString_array& a)
{
if (_tree.goto_root())
_tree.scan_depth_first(isam_tree_handler, &a);
}
inline bool tok_get_bool(TToken_string& tok, int pos)
{
const char* str = tok.get(pos);
@ -719,26 +764,43 @@ void TQuery_mask::sheet2sql()
fs.set_focusdirty(false); // Evita di scatenare eventi inutili
}
static int select_callback(void* jolly, int argc, char** value, char** field)
// Genera una query ISAM a partire dallo spreadsheet F_SHEET
void TQuery_mask::sheet2isam()
{
TArray_sheet* sht = (TArray_sheet*)jolly;
TToken_string row;
for (int i = 0; i < argc; i++)
row.add(value[i], i);
sht->add(row);
return SQLITE_OK;
TString_array rel;
tree2isam(rel);
TString use;
FOR_EACH_ARRAY_ROW(rel, i, row)
{
use << *row << '\n';
}
set(F_SQL, use, true);
_sql_dirty = false;
TEdit_field& fs = efield(F_SQL);
fs.set_focusdirty(false); // Evita di scatenare eventi inutili
}
void TQuery_mask::edit_query()
{
TSQL_recordset qry(get(F_SQL));
if (qry.columns() > 0)
const TString& sql = get(F_SQL);
TRecordset* rex = NULL;
if (sql.starts_with("SELECT "))
rex = new TSQL_recordset(sql);
else
rex = new TISAM_recordset(sql);
if (rex->columns() > 0)
{
TRecordset_sheet sht(qry);
TRecordset_sheet sht(*rex);
sht.run();
}
else
warning_box(TR("Nessuna riga risultato"));
delete rex;
}
@ -785,11 +847,15 @@ bool TQuery_mask::get_qry_path(TFilename& path) const
const bool ok = name.not_empty();
if (ok)
{
path = firm2dir(-1);
path.add("custom");
if (!path.exist())
xvt_fsys_mkdir(path);
path.add(name);
path = name;
if (!path.is_absolute_path())
{
path = firm2dir(-1);
path.add("custom");
if (!path.exist())
xvt_fsys_mkdir(path);
path.add(name);
}
path.ext("qry");
}
return ok;
@ -1098,6 +1164,7 @@ bool TQuery_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
add_asterisk_to_sheet();
break;
case F_GENSQL:
case F_GENISAM:
if (e == fe_button)
{
next_page(1001);
@ -1107,7 +1174,12 @@ bool TQuery_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
"annullando eventuali modifiche manuali.\n"
"Si desidera proseguire?"));
if (ok)
sheet2sql();
{
if (o.dlg() == F_GENSQL)
sheet2sql();
else
sheet2isam();
}
}
break;
case F_EDITQUERY:
@ -1258,15 +1330,34 @@ TQuery_mask::TQuery_mask() : TAutomask("ba8200a"), _curr_num(0), _is_dirty(false
class TSQL_recordset_app : public TSkeleton_application
{
TQuery_mask* _msk;
public:
virtual bool create();
virtual void main_loop();
virtual bool destroy();
};
bool TSQL_recordset_app::create()
{
_msk = new TQuery_mask;
xvt_sys_sleep(500);
return TSkeleton_application::create();
}
void TSQL_recordset_app::main_loop()
{
TQuery_mask* msk = new TQuery_mask;
msk->run();
delete msk;
_msk->run();
}
bool TSQL_recordset_app::destroy()
{
if (_msk != NULL)
{
delete _msk;
_msk = NULL;
}
return true;
}
int ba8200(int argc, char* argv[])

View File

@ -7,11 +7,12 @@
#define F_EDITFILE 302
#define F_ASTERISK 303
#define F_GENSQL 304
#define F_EDITQUERY 305
#define F_EXPORT_HTML 306
#define F_EXPORT_EXCEL 307
#define F_EXPORT_TXT 308
#define F_EXPORT_CAMPO 309
#define F_GENISAM 305
#define F_EDITQUERY 306
#define F_EXPORT_HTML 307
#define F_EXPORT_EXCEL 308
#define F_EXPORT_TXT 309
#define F_EXPORT_CAMPO 310
#define F_SHEET 400
#define F_MOVEUP 401
#define F_MOVEDN 402

View File

@ -68,32 +68,38 @@ END
BUTTON F_ADDFILE 10 2
BEGIN
PROMPT -15 11 "~Tabella"
PROMPT -16 11 "~Tabella"
END
BUTTON F_EDITFILE 10 2
BEGIN
PROMPT -25 11 "~Edit"
PROMPT -26 11 "~Edit"
PICTURE BMP_EDIT
END
BUTTON DLG_USER 10 2
BEGIN
PROMPT -35 11 "~Campo"
PROMPT -36 11 "~Campo"
GROUP 1
END
BUTTON F_ASTERISK 10 2
BEGIN
PROMPT -45 11 "Campo ~*"
PROMPT -46 11 "Campo ~*"
GROUP 1
END
BUTTON F_GENSQL 10 2
BEGIN
PROMPT -55 11 "~SQL"
PROMPT -56 11 "~SQL"
END
BUTTON F_GENISAM 10 2
BEGIN
PROMPT -66 11 "~ISAM"
END
SPREADSHEET F_SHEET -5
BEGIN
PROMPT 0 13 ""

View File

@ -11,6 +11,7 @@
#include <utility.h>
#include <xml.h>
#include <statbar.h>
#include "ba8201.h"
///////////////////////////////////////////////////////////
@ -301,11 +302,19 @@ int TTable_names::logic_num(const TString& name)
if (str == NULL)
{
if (isdigit(name[0]))
add_file(atoi(name), name); else
if (name[0] == '%')
add_file(LF_TABCOM, name); else
if (name.len() == 3)
add_file(LF_TAB, name); else
{
if (name.right(1) == '@')
add_file(-atoi(name), name);
else
add_file(atoi(name), name);
}
else
{
if (name[0] == '%')
add_file(LF_TABCOM, name); else
if (name.len() == 3)
add_file(LF_TAB, name);
}
str = (TString*)_names.objptr(name);
}
@ -364,7 +373,7 @@ const TString& TRecordset::query_text() const
const TToken_string& TRecordset::sheet_head() const
{
TToken_string& head = get_tmp_string();
TToken_string head;
TToken_string tablefield(32, '.');
for (unsigned int c = 0; c < columns(); c++)
{
@ -382,10 +391,14 @@ const TToken_string& TRecordset::sheet_head() const
maxlen = len;
}
head << '@' << max(ci._width, maxlen);
if (ci._type == _longfld || ci._type == _realfld)
if (ci._type == _wordfld || ci._type == _intfld || ci._type == _longfld || ci._type == _realfld)
head << 'R';
}
return head;
// Creo la stringa temporanea solo ora, altrimenti puo' essere sovrascritta!
TToken_string& h = get_tmp_string();
h = head;
return h;
}
bool TRecordset::save_as_html(const char* path)
@ -661,6 +674,65 @@ bool TRecordset::set_var(const char* name, const TVariant& var, bool create)
return ok;
}
bool is_var_separator(char c)
{
if (isspace(c))
return true;
return strchr("<=>,", c) != NULL;
}
// Cerca le variabili nel testo SQL:
// Una variabile comincia per # ed e' composta da soli caratteri alfanumerici.
// Prima del simbolo # e dopo il nome della variabile deve esserci un separatore o blank
void TRecordset::find_and_reset_vars()
{
_var.destroy();
_varnames.destroy();
const TString& sql = query_text();
int diesis = sql.find('#'); // cerco il primo #
for ( ; diesis > 0; diesis = sql.find('#', diesis+1)) // Cerco tutti i #
{
if (is_var_separator(sql[diesis-1])) // Controllo che ci sia un separatore prima del #
{
int i = diesis+1;
for ( ; sql[i] && (isalnum(sql[i]) || sql[i] == '_'); i++);
if (i > diesis+1)
{
const TString& name = sql.sub(diesis, i);
set_var(name, NULL_VARIANT, true);
}
}
}
}
void TRecordset::parsed_text(TString& sql) const
{
sql = query_text();
const bool vars = ((TSQL_recordset*)this)->ask_variables(false);
if (vars) // Se ci sono variabili faccio le sostituzioni
{
const TString_array& names = variables();
FOR_EACH_ARRAY_ROW(names, i, name) // Scandisco tutte le variabili
{
TVariant var = get_var(*name);
int pos = sql.find(*name);
for ( ; pos > 0; pos = sql.find(*name, pos+1))
{
const TString& after = sql.mid(pos+name->len());
sql.cut(pos);
TString s = var.as_string();
if ((var.is_string() && s[0] != '\'') || var.is_null())
{
s.insert("'");
s << '\'';
}
sql << s << after;
}
}
}
}
bool ask_variable(const char* name, TVariant& var)
{
TMask m("Richiesta variabile", 1, 52, 4);
@ -1054,13 +1126,6 @@ bool TSQLite::import(int logicnum)
return true;
}
bool is_var_separator(char c)
{
if (isspace(c))
return true;
return strchr("<=>,", c) != NULL;
}
bool TSQLite::parse_select_from(const char* szSql)
{
test_path();
@ -1170,44 +1235,20 @@ static int query_get_items(void* jolly, int argc, char** values, char** columns)
return q->on_get_items(argc, values, columns);
}
void TSQL_recordset::parsed_sql_text(TString& sql) const
{
sql = _sql;
const bool vars = ((TSQL_recordset*)this)->ask_variables(false);
if (vars) // Se ci sono variabili faccio le sostituzioni
{
const TString_array& names = variables();
FOR_EACH_ARRAY_ROW(names, i, name) // Scandisco tutte le variabili
{
TVariant var = get_var(*name);
int pos = sql.find(*name);
for ( ; pos > 0; pos = sql.find(*name, pos+1))
{
const TString& after = sql.mid(pos+name->len());
sql.cut(pos);
TString s = var.as_string();
if ((var.is_string() && s[0] != '\'') || var.is_null())
{
s.insert("'");
s << '\'';
}
sql << s << after;
}
}
}
}
bool TSQL_recordset::ask_variables(bool all)
{
_page.destroy();
return TRecordset::ask_variables(all);
const bool ok = TRecordset::ask_variables(all);
if (ok)
_page.destroy();
return ok;
}
TRecnotype TSQL_recordset::items() const
{
if (_items == 0)
{
TString sql; parsed_sql_text(sql);
TString sql; parsed_text(sql);
TProfiler prof("SQL query");
_TheDataBase.exec("PRAGMA show_datatypes = ON;", NULL, NULL);
_TheDataBase.exec(sql, query_get_items, (TSQL_recordset*)this);
_TheDataBase.exec("PRAGMA show_datatypes = OFF;", NULL, NULL);
@ -1277,7 +1318,7 @@ bool TSQL_recordset::move_to(TRecnotype n)
if (n < _first_row || n >= _first_row+_page.items())
{
TString sql; parsed_sql_text(sql);
TString sql; parsed_text(sql);
if (sql.find("LIMIT ") < 0)
{
const int semicolon = sql.rfind(';');
@ -1324,24 +1365,7 @@ void TSQL_recordset::set(const char* sql)
if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0)
{
_TheDataBase.parse_select_from(_sql);
// Cerca le variabili nel testo SQL:
// Una variabile comincia per # ed e' composta da soli caratteri alfanumerici.
// Prima del simbolo # e dopo il nome della variabile deve esserci un separatore o blank
int diesis = _sql.find('#'); // cerco il primo #
for ( ; diesis > 0; diesis = _sql.find('#', diesis+1)) // Cerco tutti i #
{
if (is_var_separator(_sql[diesis-1])) // Controllo che ci sia un separatore prima del #
{
int i = diesis+1;
for ( ; _sql[i] && (isalnum(_sql[i]) || _sql[i] == '_'); i++);
if (i > diesis+1)
{
const TString& name = _sql.sub(diesis, i);
set_var(name, NULL_VARIANT, true);
}
}
}
find_and_reset_vars();
}
}
@ -1350,6 +1374,573 @@ TSQL_recordset::TSQL_recordset(const char* sql)
set(sql);
}
///////////////////////////////////////////////////////////
// TCursor_parser
///////////////////////////////////////////////////////////
class TCursor_parser
{
istream& _instr;
TArray& _column;
TString _pushed;
TString _token;
TRelation* _relation;
TCursor* _cursor;
protected:
const TString& pop();
void push();
void add_column_info(const char* table, const TRectype& rec);
void parse_sortexpr(TToken_string& se);
void parse_filter(TToken_string& filter);
void parse_region(TRectype& rec);
void parse_join_param(TRelation* rel, const TString& j, int to);
void parse_join();
void parse_sortedjoin();
public:
TRelation* get_relation() { return _relation; }
TCursor* get_cursor() { return _cursor; }
TCursor_parser(istream& instr, TArray& column);
};
const TString& TCursor_parser::pop()
{
if (_pushed.not_empty())
{
_token = _pushed;
_pushed.cut(0);
}
else
{
_token.cut(0);
_instr.eatwhite();
if (_instr.eof())
return _token;
char c;
_instr.get(c);
while (!isspace(c) && c != EOF)
{
_token << c;
_instr.get(c);
}
}
return _token;
}
void TCursor_parser::push()
{
CHECK(_pushed.empty(), "Repushing?");
_pushed = _token;
}
void TCursor_parser::add_column_info(const char* table, const TRectype& rec)
{
for (int i = 0; i < rec.items(); i++)
{
TRecordset_column_info* info = new TRecordset_column_info;
const char* name = rec.fieldname(i);
info->_name << table << '.' << name;
info->_type = rec.type(name);
switch (info->_type)
{
case _datefld: info->_width = 10; break;
case _memofld: info->_width = 50; break;
default : info->_width = rec.length(name); break;
}
_column.add(info);
}
}
void TCursor_parser::parse_sortexpr(TToken_string& se)
{
const char sep = se.separator();
se.separator(' ');
_instr.getline(se.get_buffer(), se.size());
se.strip_d_spaces();
se.replace(' ', sep);
se.separator(sep);
}
void TCursor_parser::parse_filter(TToken_string& filter)
{
const TString& str = pop();
while (str.find('=') > 0)
{
filter.add(str);
pop();
}
push();
}
void TCursor_parser::parse_region(TRectype& rec)
{
TString16 field;
TString value;
while (true)
{
const TString& ass = pop();
const int equal = ass.find('=');
if (equal > 0)
{
field = ass.left(equal);
value = ass.mid(equal+1);
if (value[0] == '"' || value[0] == '\'')
{
value.rtrim(1);
value.ltrim(1);
}
rec.put(field, value);
}
else
break;
}
push();
}
void TCursor_parser::parse_join_param(TRelation* rel, const TString& j, int to)
{
int key = 1;
const TString& tok = pop();
if (tok.starts_with("KE"))
{
pop();
key = atoi(tok);
}
else
push();
int alias = 0;
pop();
if (tok.starts_with("AL"))
{
pop();
alias = atoi(tok);
}
else
push();
TToken_string exp(80);
pop();
if (tok == "INTO")
{
parse_filter(exp);
}
if (exp.empty())
yesnofatal_box("JOIN senza espressioni INTO");
const int logicnum = table2logic(j);
if (logicnum != LF_TAB && logicnum != LF_TABCOM)
rel->add(logicnum, exp, key, to, alias); // join file
else
rel->add(j, exp, key, to, alias); // join table
TString16 tabname;
if (alias > 0)
tabname << alias << '@';
else
tabname = j;
const TRectype& rec = rel->curr(logicnum);
add_column_info(tabname, rec);
}
void TCursor_parser::parse_join()
{
const TString j = pop(); // File or table
int to = 0;
const TString& tok = pop();
if (tok == "TO") // TO keyword
{
pop();
to = table2logic(tok);
}
else
push();
parse_join_param(_relation, j, to);
}
void TCursor_parser::parse_sortedjoin()
{
TToken_string filter,sortexp;
const TString j = pop(); // File or table
const TString& tok = pop();
if (tok == "BY" )
{
parse_sortexpr(sortexp);
}
else
push();
pop();
if (tok.starts_with("FI") || tok.starts_with("SE"))
{
parse_filter(filter);
}
else
push();
TRelation* sortrel = new TRelation(table2logic(j));
while (true)
{
pop();
if (tok.empty() || tok.starts_with("JO"))
{
push();
break;
}
if (tok.starts_with("US")) // USING keyword
{
const TString subj = pop(); // File or table
parse_join_param(sortrel, subj, table2logic(j));
}
}
int to = 0;
pop();
if (tok == "TO") // TO keyword
{
pop();
to = table2logic(tok);
}
else
push();
int key = 1;
pop();
if (tok.starts_with("KE"))
{
pop();
key = atoi(tok);
}
else
push();
int alias = 0;
pop();
if (tok.starts_with("AL"))
{
pop();
alias = atoi(tok);
}
else
push();
TToken_string exp(80);
if (pop() == "INTO")
{
pop();
while (tok.find('=') > 0)
{
exp.add(tok);
pop();
}
}
push();
TSortedfile *sf= new TSortedfile(atoi(j),sortrel,sortexp,filter,key);
_relation->add((TLocalisamfile *)sf, exp, key, to, alias, false); // join table
TString16 tabname = j;
if (alias > 0)
tabname.cut(0) << alias << '@';
add_column_info(tabname, sf->curr());
}
TCursor_parser::TCursor_parser(istream& instr, TArray& col)
: _instr(instr), _column(col), _relation(NULL), _cursor(NULL)
{
_column.destroy();
const TString& tok = pop();
if (!tok.starts_with("US"))
push();
pop();
if (tok.blank())
return;
const int logicnum = table2logic(tok);
const char* tab = NULL;
if (logicnum != LF_TAB && logicnum != LF_TABCOM)
_relation = new TRelation(logicnum);
else
_relation = new TRelation(tok);
add_column_info(tok, _relation->curr());
int key = 1; // key number
pop();
if (tok.starts_with("KE"))
{
pop();
key = atoi(tok);
}
else
push();
pop();
if (tok.starts_with("BY")) // "sort BY": user-defined sort
{
TToken_string ordexpr(256);
parse_sortexpr(ordexpr);
_cursor = new TSorted_cursor(_relation, ordexpr,"", key);
}
else
push();
pop();
if (tok.starts_with("FI") || tok.starts_with("SE"))
{
TToken_string filter;
parse_filter(filter);
if (_cursor == NULL)
_cursor = new TCursor(_relation, filter, key);
else
_cursor->setfilter(filter);
}
else
push();
if (_cursor == NULL)
_cursor = new TCursor(_relation, "", key);
TRectype rec_start(_relation->curr());
TRectype rec_stop(_relation->curr());
pop();
if (tok.starts_with("FR"))
parse_region(rec_start);
else
push();
pop();
if (tok.starts_with("TO"))
parse_region(rec_stop);
else
push();
if (!rec_start.empty() || !rec_stop.empty())
_cursor->setregion(rec_start, rec_stop, 0x2);
while (true)
{
pop();
if (tok.starts_with("JO"))
parse_join(); else
if (tok.starts_with("SO"))
parse_sortedjoin();
else
break;
}
push();
if (_relation->items() == 0) // Non ci sono anche tabelle collegate
{
FOR_EACH_ARRAY_ITEM(_column, i, obj)
{
TRecordset_column_info* info = (TRecordset_column_info*)obj;
const int arrow = info->_name.find('.');
if (arrow > 0)
info->_name = info->_name.mid(arrow+1);
}
}
}
///////////////////////////////////////////////////////////
// TISAM_recordset
///////////////////////////////////////////////////////////
TVariant& TISAM_recordset::get_tmp_var() const
{
static TArray _page; // Variants to be returned by get
static int _next_var = 0; // Index of next variant to be returned
if (_next_var >= 32)
_next_var = 0;
TVariant* var = (TVariant*)_page.objptr(_next_var);
if (var == NULL)
{
var = new TVariant;
_page.add(var, _next_var);
}
_next_var++;
return *var;
}
const TVariant& TISAM_recordset::get(int logic, const char* name) const
{
char* square = strchr(name, '[');
if (square != NULL) *square = '\0'; // Per il momento tronco il nome
const TRectype& rec = _relation->curr(logic);
const TFieldtypes ft = rec.type(name);
if (square != NULL) *square = '['; // Ripristino il nome
if (ft == _nullfld)
return NULL_VARIANT;
TVariant& var = get_tmp_var();
switch (ft)
{
case _datefld: var.set(rec.get_date(name)); break;
case _realfld: var.set(rec.get_real(name)); break;
case _intfld :
case _longfld:
case _wordfld: var.set(rec.get_long(name)); break;
default : var.set(rec.get(name)); break;
}
if (square != NULL)
{
int from = 0, to = -1;
sscanf(square, "[%d,%d]", &from, &to);
var.set(var.as_string().sub(from-1, to));
}
return var;
}
const TVariant& TISAM_recordset::get(size_t c) const
{
const TRecordset_column_info* info = (const TRecordset_column_info*)_column.objptr(c);
if (info != NULL)
{
int logic = 0;
const char* field = info->_name;
const int dot = info->_name.find('.');
if (dot > 0)
{
logic = table2logic(info->_name.left(dot));
field += dot+1;
}
return get(logic, field);
}
return NULL_VARIANT;
}
const TVariant& TISAM_recordset::get(const char* name) const
{
const TFixed_string fldname(name);
int table_end = fldname.find('.');
int field_start = table_end+1;
if (table_end < 0)
{
table_end = fldname.find('-');
if (table_end > 0)
field_start++;
}
int logic = 0;
const char* field = name;
if (table_end > 0)
{
logic = table2logic(fldname.left(table_end));
field += field_start;
}
return get(logic, field);
}
const TRecordset_column_info& TISAM_recordset::column_info(size_t i) const
{
return (const TRecordset_column_info&)_column[i];
}
TRecnotype TISAM_recordset::current_row() const
{
return _cursor != NULL ? _cursor->pos() : -1;
}
bool TISAM_recordset::ask_variables(bool all)
{
bool ok = TRecordset::ask_variables(all);
if (ok)
reset();
return ok;
}
TRecnotype TISAM_recordset::items() const
{
if (_cursor == NULL)
{
TString use; parsed_text(use);
TProfiler prof("ISAM query");
TISAM_recordset* my = (TISAM_recordset*)this;
istrstream instr(use.get_buffer(), use.len());
TCursor_parser parser(instr, my->_column);
my->_relation = parser.get_relation();
my->_cursor = parser.get_cursor();
if (_cursor != NULL)
{
_cursor->items();
_cursor->freeze();
}
}
return _cursor != NULL ? _cursor->items() : 0;
}
unsigned int TISAM_recordset::columns() const
{
if (_cursor == NULL)
items();
return _column.items();
}
bool TISAM_recordset::move_to(TRecnotype pos)
{
bool ok = _cursor != NULL;
if (ok)
{
*_cursor = pos;
ok = pos >= 0 && pos < items();
}
return ok;
}
void TISAM_recordset::reset()
{
_column.destroy();
if (_relation != NULL)
{
delete _relation;
_relation = NULL;
}
if (_cursor != NULL)
{
delete _cursor;
_cursor = NULL;
}
}
void TISAM_recordset::set(const char* use)
{
reset();
_use = use;
find_and_reset_vars();
}
TISAM_recordset::TISAM_recordset(const char* use)
: _relation(NULL), _cursor(NULL)
{
set(use);
}
TISAM_recordset::~TISAM_recordset()
{
reset();
}
///////////////////////////////////////////////////////////
// TRecordset_sheet
///////////////////////////////////////////////////////////
@ -1378,3 +1969,60 @@ TRecordset_sheet::TRecordset_sheet(TRecordset& query)
: TSheet(-1, -1, -2, -4, "Query", query.sheet_head()), _query(query)
{
}
///////////////////////////////////////////////////////////
// TProfiler
///////////////////////////////////////////////////////////
TProfiler::TProfiler(const char* desc)
: _desc(desc)
{
#ifdef DBG
_start = clock();
TString80 msg;
msg << "Profiling " << desc << "...";
statbar_set_title(TASK_WIN, msg);
while (true)
{
const clock_t clk = clock();
if (clk != _start)
{
_start = clk;
break;
}
}
#endif
}
void TProfiler::show() const
{
#ifdef DBG
const double s = double(clock() - _start) / CLOCKS_PER_SEC;
int hour = 0, min = 0;
int sec = int(s);
const int cent = int((s - sec)*100);
if (sec >= 3600)
{
hour = sec / 3600;
sec -= hour * 3600;
}
if (sec >= 60)
{
min = sec / 60;
sec -= min * 60;
}
TString80 msg = _desc;
msg.format("%s %02d:%02d:%02d.%02d", (const char*)_desc, hour, min, sec, cent);
statbar_set_title(TASK_WIN, msg);
#endif
}
TProfiler::~TProfiler()
{
show();
}

View File

@ -15,7 +15,7 @@
struct TRecordset_column_info : public TObject
{
TString _name;
TString _name; // Table.Column
int _width;
TFieldtypes _type;
};
@ -93,6 +93,9 @@ protected:
bool save_as_silk(const char* path);
bool save_as_text(const char* path);
bool save_as_campo(const char* path);
void find_and_reset_vars();
void parsed_text(TString& sql) const;
public: // Absolutely needed methods
virtual TRecnotype items() const pure;
@ -161,6 +164,40 @@ public:
virtual ~TSQL_recordset() { }
};
///////////////////////////////////////////////////////////
// TISAM_recordset
///////////////////////////////////////////////////////////
class TISAM_recordset : public TRecordset
{
TString _use;
TRelation* _relation;
TCursor* _cursor;
TArray _column; // Column infos
protected:
void reset();
TVariant& get_tmp_var() const;
const TVariant& get(int logic, const char* field) const;
public:
void set(const char* use);
virtual TRecnotype items() const;
virtual bool move_to(TRecnotype pos);
virtual TRecnotype current_row() const;
virtual unsigned int columns() const;
virtual const TRecordset_column_info& column_info(unsigned int c) const;
virtual const TVariant& get(unsigned int column) const;
virtual const TVariant& get(const char* column_name) const;
virtual bool ask_variables(bool all);
virtual const TString& query_text() const { return _use; }
TISAM_recordset(const char* use);
virtual ~TISAM_recordset();
};
///////////////////////////////////////////////////////////
// TRecordset_sheet
///////////////////////////////////////////////////////////
@ -181,6 +218,18 @@ public:
// Utility
///////////////////////////////////////////////////////////
class TProfiler : public TObject
{
TString _desc;
clock_t _start;
public:
void show() const;
TProfiler(const char* desc = "");
~TProfiler();
};
bool select_custom_file(TFilename& path, const char* ext);
const TString& logic2table(int logic_num);
int table2logic(const TString& name);

View File

@ -55,9 +55,9 @@ class TReport_base_mask : public TAutomask
{
TReport_font _font;
bool _font_changed;
TReport& _report;
protected:
TReport& _report;
char _halign, _valign;
COLOR _fgcolor, _bgcolor;
@ -239,6 +239,7 @@ void TReport_field_mask::vedo_non_vedo()
show(F_BGCOLOR, type != 'L');
show(F_FONT_SELECT, is_text);
show(F_SOURCE, (is_text || type == 'I') && type != 'T');
show(DLG_FINDREC, field(F_SOURCE).active());
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);
@ -295,6 +296,39 @@ bool TReport_field_mask::on_field_event(TOperable_field& o, TField_event e, long
return error_box(TR("Specificare almeno due codici"));
}
break;
case DLG_FINDREC:
if (e == fe_button)
{
TRecordset* rex = _report.recordset();
if (rex != NULL && rex->columns() > 0)
{
TArray_sheet sheet(-1, -1, -1, 20, "Colonne Query", "Nome@16|Tipo@8|Dimensoni@R");
TToken_string row;
for (size_t i = 0; i < rex->columns(); i++)
{
const TRecordset_column_info& info = rex->column_info(i);
row = info._name;
switch (info._type)
{
case _alfafld: row.add("Stringa"); break;
case _boolfld: row.add("Logico"); break;
case _datefld: row.add("Data"); break;
case _memofld: row.add("Memo"); break;
default : row.add("Numero"); break;
}
row.add(info._width);
sheet.add(row);
}
if (sheet.run() == K_ENTER)
{
row = sheet.row(-1);
set(F_SOURCE, row.get(0));
}
}
else
warning_box("Query non definita");
}
break;
default:
break;
}
@ -716,11 +750,15 @@ bool TReport_mask::get_rep_path(TFilename& path) const
const bool ok = name.not_empty();
if (ok)
{
path = firm2dir(-1);
path.add("custom");
if (!path.exist())
xvt_fsys_mkdir(path);
path.add(name);
path = name;
if (!path.is_absolute_path())
{
path = firm2dir(-1);
path.add("custom");
if (!path.exist())
xvt_fsys_mkdir(path);
path.add(name);
}
path.ext("rep");
}
return ok;
@ -826,6 +864,7 @@ void TReport_mask::add_field()
{
TReport_section& rs = curr_section();
TReport_field* rf = new TReport_field(&rs);
rf->set_pos(0, rs.compute_size().y);
TReport_field_mask m(*rf);
m.disable(DLG_DELREC);
if (m.run() == K_ENTER)
@ -1062,12 +1101,23 @@ bool TReport_mask::on_field_event(TOperable_field& o, TField_event e, long jolly
case F_SHOW_QRY:
if (e == fe_button)
{
TSQL_recordset qry(get(F_SQL));
if (qry.columns() > 0)
TRecordset* rex = NULL;
const TString& sql = get(F_SQL);
if (sql.starts_with("SELECT "))
rex = new TSQL_recordset(sql);
else
rex = new TISAM_recordset(sql);
if (rex->columns() > 0)
{
TRecordset_sheet sheet(qry);
sheet.run();
TRecordset_sheet sht(*rex);
sht.run();
}
else
warning_box(TR("Nessuna riga risultato"));
delete rex;
}
break;
case DLG_PRINT:
@ -1146,8 +1196,13 @@ class TReporter_app : public TSkeleton_application
TReport_mask* _msk;
protected:
virtual void print();
virtual bool create();
virtual void main_loop();
virtual bool destroy();
virtual void print();
public:
TReporter_app() : _msk(NULL) { }
};
void TReporter_app::print()
@ -1156,12 +1211,26 @@ void TReporter_app::print()
_msk->on_print();
}
void TReporter_app::main_loop()
bool TReporter_app::create()
{
_msk = new TReport_mask;
xvt_sys_sleep(500);
return TSkeleton_application::create();
}
bool TReporter_app::destroy()
{
if (_msk != NULL)
{
delete _msk;
_msk = NULL;
}
return true;
}
void TReporter_app::main_loop()
{
_msk->run();
delete _msk;
_msk = NULL;
}
int ba8300(int argc, char* argv[])

View File

@ -89,6 +89,12 @@ BEGIN
PROMPT 1 10 "@bSorgente"
END
BUTTON DLG_FINDREC 10 2
BEGIN
PROMPT -33, 9 ""
PICTURE BMP_FINDREC
END
BUTTON DLG_CANCEL 10 2
BEGIN
PROMPT -13 -1 ""

View File

@ -392,7 +392,7 @@ bool TReport_window::get_selection_rect(TRectangle& rct) const
const TReport_field& f = *(const TReport_field*)o;
if (f.selected())
{
const TRectangle& fr = f.get_rect();
const TRectangle fr = f.get_draw_rect();
if (!full)
{
rct = fr;

View File

@ -495,7 +495,7 @@ TPoint TReport_section::compute_size() const
const TReport_field& rf = field(i);
if (rf.shown())
{
const TRectangle& r = rf.get_rect();
const TRectangle r = rf.get_draw_rect();
if (_size.x <= 0 && r.right() > s.x) // Richiesto calcolo larghezza
s.x = r.right();
if (_size.y <= 0 && r.bottom() > s.y) // Richiesto calcolo altezza
@ -677,7 +677,8 @@ TString& TReport_script::translate_message() const
{
TToken_string source(_src, '\n');
TToken_string line(256, '|');
TString cmd, arg, fld;
TToken_string args(256, ',');
TString cmd, fld;
TString& alex = get_tmp_string();
FOR_EACH_TOKEN(source, srcrow)
{
@ -699,26 +700,29 @@ TString& TReport_script::translate_message() const
if (comma > 0)
{
cmd = msg.left(comma);
arg = msg.mid(comma+1);
fld = arg;
args = msg.mid(comma+1);
fld = args.get(0);
if (fld[0] != '#')
fld.insert("#", 0);
fld.insert("REPORT.", 1);
}
else
{
cmd = msg;
arg.cut(0);
args.cut(0);
fld.cut(0);
}
if (cmd.starts_with("AL")) // ALIGN
{
alex << fld << " ALIGN_FIELD_" << args.get(1) << ' ';
} else
if (cmd.starts_with("CO")) // COPY
{
alex << "#REPORT.THIS @ " << fld << " ! ";
alex << "#THIS @ " << fld << " ! ";
} else
if (cmd.starts_with("AD")) // ADD
{
alex << "#REPORT.THIS @ " << fld << " @ + "<< fld << " ! ";
alex << "#THIS @ " << fld << " @ + "<< fld << " ! ";
} else
if (cmd.starts_with("IN")) // INC
{
@ -867,6 +871,51 @@ void TReport_field::offset(const TPoint& pt)
_rct.y += pt.y;
}
void TReport_field::set_draw_pos(long x, long y)
{
_rct_draw.x = x;
_rct_draw.y = y;
}
void TReport_field::set_draw_size(long w, long h)
{
_rct_draw.set_width(w);
_rct_draw.set_height(h);
}
void TReport_field::compute_draw_rect() const
{
TRectangle& rct = ((TReport_field*)this)->_rct_draw;
rct = get_rect();
if (type() == 'S')
{
if (rct.width() <= 0)
{
TString text = formatted_text(); text.rtrim();
TToken_string str(text, '\n');
int maxlen = 1;
FOR_EACH_TOKEN(str, line)
{
const int len = strlen(line);
if (len > maxlen)
maxlen = len;
}
rct.set_width(maxlen * 100);
}
if (rct.height() <= 0)
{
if (rct.width() >= 100)
{
TString text = formatted_text(); text.rtrim();
TParagraph_string str(text, rct.width()/100);
rct.set_height(str.items() * 100);
}
if (rct.height() <= 0)
rct.set_height(100);
}
}
}
const TReport_font& TReport_field::font() const
{
return _font != NULL ? *_font : _section->font();
@ -1010,6 +1059,8 @@ bool TReport_field::load_field()
else
_var.set_null();
}
compute_draw_rect();
return ok;
}
@ -1039,7 +1090,7 @@ COLOR TReport_field::link_color() const
void TReport_field::draw_text(TWindow& win, const char* text, TReport_draw_mode rdm) const
{
const TRectangle& rct = get_rect();
const TRectangle& rct = get_draw_rect();
RCT r; win.log2dev(rct, r);
advanced_draw_rect(win, r, border(), fore_color(), back_color());
@ -1176,6 +1227,9 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const
if (rdm != rdm_edit && hidden())
return;
if (rdm == rdm_edit)
compute_draw_rect();
PAT_STYLE back_pattern = PAT_HOLLOW;
if (rdm == rdm_edit)
{
@ -1251,7 +1305,7 @@ void TReport_field::draw(TWindow& win, TReport_draw_mode rdm) const
{
if (border() <= 0) // Rendi piu' visibile il bordo dei campi che non ce l'hanno
{
RCT r; win.log2dev(get_rect(), r);
RCT r; win.log2dev(get_draw_rect(), r);
advanced_draw_rect(win, r, 1, COLOR_LTGRAY, COLOR_WHITE);
}
if (id() > 0)
@ -1378,6 +1432,7 @@ bool TReport_field::load(const TXmlItem& fld)
set_row(get_num_attr(fld, "y"));
set_width(get_num_attr(fld, "width"));
set_height(get_num_attr(fld, "height", 100));
_rct_draw = _rct;
show(!fld.GetBoolAttr("hidden"));
activate(!fld.GetBoolAttr("deactivated"));
hide_zeroes(fld.GetBoolAttr("zeroes_hidden"));
@ -1461,6 +1516,7 @@ TReport_field::TReport_field(TReport_section* sec)
{
set_pos(0,0);
set_size(1600,100);
_rct_draw = _rct;
}
TReport_field::TReport_field(const TReport_field& rf) : _font(NULL)
@ -1592,8 +1648,10 @@ bool TReport::set_recordset(TRecordset* rs)
bool TReport::set_recordset(const TString& sql)
{
bool ok = false;
if (sql.compare("SELECT", 6, true) == 0)
if (sql.compare("SELECT ", 7, true) == 0)
ok = set_recordset(new TSQL_recordset(sql));
else
ok = set_recordset(new TISAM_recordset(sql));
return ok;
}
@ -1952,16 +2010,17 @@ bool TReport::set_usr_val(const TString& name, const TVariant& var)
return TAlex_virtual_machine::set_usr_val(name, var);
}
unsigned int TReport::compile_usr_word(const TString& name) const
size_t TReport::get_usr_words(TString_array& words) const
{
const int words = 10;
const char* const names[words] = { NULL, "DISABLE", "ENABLE", "GET_SIZE", "HIDE",
"RUN_FORM", "SET_BACK_COLOR", "SET_FORE_COLOR",
"SET_SIZE", "SHOW" };
int i;
for (i = words-1; i > 0; i--)
if (name == names[i])
break;
const char* const name[] =
{
"***", "DISABLE", "ENABLE", "GET_POS",
"GET_SIZE", "HIDE", "RUN_FORM", "SET_BACK_COLOR", "SET_FORE_COLOR",
"SET_POS", "SET_SIZE", "SHOW", NULL
};
size_t i;
for (i = 0; name[i] != NULL; i++)
words.add(name[i]);
return i;
}
@ -1971,10 +2030,16 @@ static void do_show(TReport_field& rf, void* jolly)
static void do_enable(TReport_field& rf, void* jolly)
{ rf.activate(jolly != NULL); }
static void do_set_pos(TReport_field& rf, void* jolly)
{
const TPoint& pt = *(const TPoint*)jolly;
rf.set_draw_pos(pt.x, pt.y);
}
static void do_set_size(TReport_field& rf, void* jolly)
{
const TPoint& pt = *(const TPoint*)jolly;
rf.set_size(pt.x, pt.y);
rf.set_draw_size(pt.x, pt.y);
}
static void do_set_back_color(TReport_field& rf, void* jolly)
@ -2082,47 +2147,70 @@ bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
{
switch (opcode)
{
case 1: // DISABLE
case 1: // Placeholder
break;
case 2: // DISABLE
do_message(stack.pop(), do_enable, NULL);
break;
case 2: // ENABLE
case 3: // ENABLE
do_message(stack.pop(), do_enable, (void*)1);
break;
case 3: // GET_SIZE
case 4: // GET_POS
{
const TReport_field* fld = field(stack.pop().as_string());
real x, y;
if (fld != NULL)
{
const TRectangle& r = fld->get_draw_rect();
x = r.x / CENTO; y = r.y / CENTO;
}
stack.push(x); stack.push(y);
}
break;
case 5: // GET_SIZE
{
const TReport_field* fld = field(stack.pop().as_string());
real w, h;
if (fld != NULL)
{
const TRectangle& r = fld->get_rect();
const TRectangle& r = fld->get_draw_rect();
w = r.width() / CENTO; h = r.height() / CENTO;
}
stack.push(w); stack.push(h);
}
break;
case 4: // HIDE
case 6: // HIDE
do_message(stack.pop(), do_show, NULL);
break;
case 5: // RUN_FORM
case 7: // RUN_FORM
{
const TString& msk = stack.pop().as_string();
const KEY key = run_form(msk);
stack.push(key);
}
break;
case 6: // SET_BACK_COLOR
case 8: // SET_BACK_COLOR
{
const COLOR rgb = stack.pop().as_color();
do_message(stack.pop(), do_set_back_color, (void*)rgb);
}
break;
case 7: // SET_FORE_COLOR
case 9: // SET_FORE_COLOR
{
const COLOR rgb = stack.pop().as_color();
do_message(stack.pop(), do_set_fore_color, (void*)rgb);
}
break;
case 8: // SET_SIZE
case 10: // SET_POS
{
const TVariant& fld = stack.pop();
const real y = stack.pop().as_real() * CENTO;
const real x = stack.pop().as_real() * CENTO;
const TPoint pt(x.integer(), y.integer());
do_message(fld, do_set_pos, (void*)&pt);
}
break;
case 11: // SET_SIZE
{
const TVariant& fld = stack.pop();
const real h = stack.pop().as_real() * CENTO;
@ -2131,7 +2219,7 @@ bool TReport::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
do_message(fld, do_set_size, (void*)&sz);
}
break;
case 9: // SHOW
case 12: // SHOW
do_message(stack.pop(), do_show, (void*)1);
break;
default:
@ -2161,9 +2249,9 @@ bool TReport::on_link(const TReport_link& lnk)
TReport::TReport() : _lpi(6), _recordset(NULL), _curr_field(NULL)
{
// Brutte inizializzazioni, ma inevitabili
_expressions.set_report(this);
fload("report.alx");
_prescript.set_description("PRESCRIPT");
_postscript.set_description("POSTSCRIPT");
}

View File

@ -226,7 +226,7 @@ class TReport_field : public TSortable
TReport_section* _section;
int _id;
char _type; // Text, String, Numeric, Price, Valuta, Date, Line, Rectangle, Image
TRectangle _rct; // In centesimi
TRectangle _rct, _rct_draw; // In centesimi
COLOR _fgcolor, _bgcolor;
short _border;
char _halign, _valign;
@ -246,6 +246,7 @@ protected:
TFieldtypes var_type() const;
const TString& formatted_text() const;
void get_currency(TCurrency& cur) const;
void compute_draw_rect() const;
public:
virtual TObject* dup() const { return new TReport_field(*this); }
@ -288,6 +289,10 @@ public:
void set_width(long dx) { _rct.set_width(dx); }
void set_height(long dy) { _rct.set_height(dy); }
const TRectangle& get_rect() const { return _rct; }
void set_draw_pos(long x, long y);
void set_draw_size(long x, long y);
const TRectangle& get_draw_rect() const { return _rct_draw; }
bool hidden() const { return _hidden; }
bool shown() const { return !hidden(); }
@ -382,7 +387,7 @@ class TReport : public TAlex_virtual_machine
protected:
virtual const char* class_name() const { return "Report"; }
virtual unsigned int compile_usr_word(const TString& name) const;
virtual size_t get_usr_words(TString_array& words) const;
virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack);
virtual bool get_usr_val(const TString& name, TVariant& var) const;
virtual bool set_usr_val(const TString& name, const TVariant& var);

View File

@ -515,6 +515,7 @@ bool TPage_printer::do_preview()
set_win(_preview_window->win());
_pagefrom = _pageto = _page = 1;
_print_aborted = false;
const KEY key = _preview_mask->run();
set_win(NULL_WIN);

View File

@ -86,8 +86,8 @@ enum AVM_opcode
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_div, avm_do, avm_dot, avm_drop, avm_dup,
avm_else, avm_execute,
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_j,
@ -95,8 +95,8 @@ enum AVM_opcode
avm_mod, avm_mon, avm_mul,
avm_negate,
avm_or, avm_over,
avm_pick, avm_plus_loop, avm_push,
avm_repeat, avm_rdrop, avm_rpeek, avm_rpush, avm_rot,
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_until, avm_usrword,
@ -111,8 +111,8 @@ const char* AVM_TOKENS[avm_zzz+1] =
"BEGIN",
"$CALL_WORD$", "COLD",
"=", ">", ">=", "<", "<=", "<>",
"/", "DO", ".", "DROP", "DUP",
"ELSE", "EXECUTE",
"DIV", "/", "DO", ".", "DROP", "DUP",
"ELSE",
"FALSE", "@", "FLOAD",
"I", "IF",
"J",
@ -120,8 +120,8 @@ const char* AVM_TOKENS[avm_zzz+1] =
"MOD", "MON", "*",
"NEGATE",
"OR", "OVER",
"PICK", "+LOOP", "PUSH",
"REPEAT", "R>", "R@", ">R", "ROT",
"PERFORM", "PICK", "+LOOP", "PUSH",
"REPEAT", "R>", "R@", ">R", "ROLL", "ROT",
"!", "-", "SWAP",
"THEN", "TRUE",
"UNTIL", "#",
@ -189,13 +189,14 @@ class TAVM_list_window : public TField_window
{
TBytecode* _bc;
int _ip;
const TString_array* _user_words;
protected:
virtual void update();
virtual void handler(WINDOW win, EVENT* ep);
public:
void set_bytecode(const TBytecode* bc, int ip);
void set_bytecode(const TBytecode* bc, int ip, const TString_array& uw);
TAVM_list_window(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner);
};
@ -263,6 +264,11 @@ void TAVM_list_window::update()
if (co == avm_call_word)
{
str = var.as_string();
} else
if (co == avm_usrword)
{
str = _user_words->row(var.as_int());
str << " (#" << var.as_int() << ')';
}
else
{
@ -278,10 +284,11 @@ void TAVM_list_window::update()
}
}
void TAVM_list_window::set_bytecode(const TBytecode* bc, int ip)
void TAVM_list_window::set_bytecode(const TBytecode* bc, int ip, const TString_array& uw)
{
_bc = (TBytecode*)bc;
_ip = ip;
_user_words = &uw;
set_scroll_max(80, _bc->items() - rows());
}
@ -403,6 +410,7 @@ class TAVM
ostream* _outstr;
TAssoc_array _words;
TString_array _user_words;
TAVM_monitor _mon;
protected:
@ -413,7 +421,9 @@ 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);
const TString_array& get_user_words();
int compile_user_word(const TString& n);
public:
const TString& get_last_error() const { return _last_error; }
@ -421,6 +431,7 @@ 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);
TAVM(TAlex_virtual_machine* vm);
virtual ~TAVM();
@ -494,6 +505,23 @@ int TAVM::find_matching(const TBytecode& bytecode, AVM_opcode op1, AVM_opcode op
return i;
}
const TString_array& TAVM::get_user_words()
{
if (_user_words.items() == 0)
{
_user_words.add("***");
_vm->get_usr_words(_user_words);
}
return _user_words;
}
int TAVM::compile_user_word(const TString& w)
{
const TString_array& uw = get_user_words();
const int i = uw.find(w);
return i > 0 ? i : 0;
}
bool TAVM::compile(istream& instr, TBytecode& bytecode)
{
TString str(256);
@ -610,7 +638,7 @@ bool TAVM::compile(istream& instr, TBytecode& bytecode)
}
else
{
const unsigned int oc = _vm->compile_usr_word(str);
const int oc = compile_user_word(str);
if (oc > 0)
op = new TAVM_op(avm_usrword, oc);
}
@ -647,16 +675,18 @@ void TAVM::do_call(const TString& func)
_bc = (TBytecode*)_words.objptr(func);
}
void TAVM::do_fload(const char* fname)
bool TAVM::do_fload(const char* fname)
{
TFilename name = fname;
if (name.custom_path())
bool ok = name.custom_path();
if (ok)
{
TBytecode bc;
ifstream inf(name);
if (compile(inf, bc))
execute(bc);
}
return ok;
}
void TAVM::execute(const TAVM_op& op)
@ -687,14 +717,31 @@ void TAVM::execute(const TAVM_op& op)
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_div:
case avm_div:
{
const long r0 = _stack.pop().as_int();
const long r1 = _stack.pop().as_int();
if (r0 != 0)
{
const long n = r1 / r0;
_stack.push(n);
}
else
_stack.push(NULL_VARIANT);
}
break;
case avm_divide:
{
const real& r0 = _stack.pop().as_real();
const real& r1 = _stack.pop().as_real();
real n;
if (!r0.is_zero())
n = r1 / r0;
_stack.push(n);
{
const real n = r1 / r0;
_stack.push(n);
}
else
_stack.push(NULL_VARIANT);
}
break;
case avm_do:
@ -719,15 +766,6 @@ void TAVM::execute(const TAVM_op& op)
case avm_else:
_ip = op.var().as_int();
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:
{
@ -794,12 +832,16 @@ void TAVM::execute(const TAVM_op& op)
}
break;
case avm_over: _stack.push(_stack.peek(1)); break;
case avm_pick:
case avm_perform:
{
const int depth = _stack.pop().as_int();
_stack.push(_stack.peek(depth));
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_pick: _stack.push(_stack.peek(_stack.pop().as_int())); break;
case avm_plus_loop:
{
TVariant& start = _rstack.pop();
@ -815,6 +857,7 @@ void TAVM::execute(const TAVM_op& op)
case avm_rdrop: _stack.push(_rstack.pop()); break;
case avm_rpeek: _stack.push(_rstack.peek()); break;
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:
{
@ -869,7 +912,7 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
_outstr = outstr;
while (_bc != NULL)
{
if (_ip >= _bc->items()) // Fine funzione
while (_ip >= _bc->items()) // Fine funzione
{
if (_rstack.items() >= 2) // Controllo il return stack
{
@ -881,10 +924,13 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
_bc = (const TBytecode*)_words.objptr(str);
}
else
{
_bc = NULL;
break; // Fine esecuzione
if (_bc == NULL)
break;
}
}
if (_bc == NULL || _ip > _bc->items())
break;
TAVM_op& op = *(TAVM_op*)_bc->objptr(_ip);
if (op.has_break() && !_mon.is_open())
@ -898,7 +944,7 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
{
lock_preview_update(true);
TAVM_list_window& monitor = _mon.monitor();
monitor.set_bytecode(_bc, _ip);
monitor.set_bytecode(_bc, _ip, _user_words);
TAVM_stack_window& stacker = _mon.stacker();
stacker.set_stack(_stack);
TAVM_stack_window& rstacker = _mon.rstacker();
@ -915,8 +961,8 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
op.set_auto_break(true);
}
break;
case K_DEL : abort_printing();
case K_QUIT: _mon.close_modal(); lock_preview_update(false); break;
case K_QUIT: abort_printing();
case K_F5 : _mon.close_modal(); lock_preview_update(false); break;
default: break;
}
}
@ -932,23 +978,28 @@ bool TAVM::execute(const TBytecode& cmdline, ostream* outstr)
lock_preview_update(false);
}
const bool ok = _bc != NULL; // Not aborted
//const bool ok = _bc != NULL; // Not aborted
_bc = old_bc;
_ip = old_ip;
return ok;
return true;
}
void TAVM::restart(bool cold)
{
_stack.reset();
_rstack.reset();
if (cold)
{
_words.destroy();
do_fload("alex.alx");
}
}
TAVM::TAVM(TAlex_virtual_machine* vm)
: _vm(vm), _outstr(NULL)
{
do_fload("alex.alx");
restart(true);
}
TAVM::~TAVM()
@ -1017,6 +1068,12 @@ bool TAlex_virtual_machine::get_usr_val(const TString& name, TVariant& var) cons
var.set(dongle().administrator());
return true;
}
if (n == "CLOCK")
{
const long msec = clock() / (CLOCKS_PER_SEC / 1000);
var.set(msec);
return true;
}
if (n == "FIRM")
{
var.set(prefix().get_codditta());
@ -1055,7 +1112,7 @@ bool TAlex_virtual_machine::set_usr_val(const TString& name, const TVariant& var
return false;
}
unsigned int TAlex_virtual_machine::compile_usr_word(const TString& name) const
unsigned int TAlex_virtual_machine::get_usr_words(TString_array&) const
{
return 0;
}
@ -1065,6 +1122,11 @@ bool TAlex_virtual_machine::execute_usr_word(unsigned int opcode, TVariant_stack
return false;
}
bool TAlex_virtual_machine::fload(const char* fname)
{
return avm().do_fload(fname);
}
TAlex_virtual_machine::TAlex_virtual_machine() : _avm(NULL)
{
}

View File

@ -49,7 +49,7 @@ protected:
TAVM& avm();
public:
virtual unsigned int compile_usr_word(const TString& name) const;
virtual size_t get_usr_words(TString_array& names) const;
virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack);
virtual bool get_usr_val(const TString& name, TVariant& var) const;
virtual bool set_usr_val(const TString& name, const TVariant& var);
@ -59,6 +59,7 @@ 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);
void warm_restart();
void cold_restart();

View File

@ -15,31 +15,31 @@ BEGIN
PROMPT 27 11 ""
END
BUTTON DLG_NEXTREC 10 2
BUTTON DLG_NEXTREC 9 2
BEGIN
PROMPT -14 -1 ""
PICTURE 124
MESSAGE EXIT,K_F11
END
BUTTON DLG_LASTREC 10 2
BUTTON DLG_LASTREC 9 2
BEGIN
PROMPT -24 -1 ""
PICTURE 1671
MESSAGE EXIT,K_F10
END
BUTTON DLG_ELABORA 10 2
BUTTON DLG_ELABORA 9 2
BEGIN
PROMPT -34 -1 ""
PICTURE BMP_LASTREC
MESSAGE EXIT,K_QUIT
MESSAGE EXIT,K_F5
END
BUTTON DLG_DELREC 10 2
BUTTON DLG_QUIT 9 2
BEGIN
PROMPT -44 -1 "Abort"
MESSAGE EXIT,K_DEL
PROMPT -44 -1 ""
MESSAGE EXIT,K_QUIT
END

168
ba/ba8400.cpp Executable file
View File

@ -0,0 +1,168 @@
#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <execp.h>
#include <form.h>
#include <prefix.h>
#include <scanner.h>
#include "ba8302.h"
#include "ba8400.h"
///////////////////////////////////////////////////////////
// TFormer_mask
///////////////////////////////////////////////////////////
class TFormer_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
void import();
public:
TFormer_mask();
};
void TFormer_mask::import_use()
{
}
void TFormer_mask::import_use(TReport& rep) const
{
TScanner scan(get(F_FORM));
TString use;
int parse_use = 0;
while (scan.ok())
{
const TString& line = scan.line();
if (line.empty())
break;
if (parse_use == 0 && line.starts_with("US"))
parse_use = 1;
if (parse_use == 1)
{
if (line.starts_with("EN"))
{
parse_use = 2;
break;
}
else
use << line << '\n';
}
}
if (!use.blank())
rep.set_recordset(use);
}
void TFormer_mask::import_sections(TReport& rep) 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);
}
void TFormer_mask::import()
{
TReport rep;
import_use(rep);
import_sections(rep);
rep.save(get(F_REPORT));
}
bool TFormer_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_FORM:
if (e == fe_modify)
{
TFilename output = get(F_REPORT);
TFilename path = output.path();
if (path.empty())
{
path = firm2dir(-1);
path.add("custom");
}
const TFilename input = o.get();
output = path;
output.add(input.name());
output.ext("rep");
output.lower();
set(F_REPORT, output);
enable(DLG_ELABORA, input.exist());
}
break;
case F_REPORT:
if (e == fe_modify)
{
const TFilename output = get(F_REPORT);
enable(DLG_PRINT, output.exist());
}
break;
case DLG_ELABORA:
if (e == fe_button)
{
const TFilename output = get(F_REPORT);
if (output.exist())
{
if (!yesno_box(TR("Il file %s esiste gia':\nSi desidera sovrascriverlo?"), (const char*)output))
return false;
}
import();
enable(DLG_PRINT, output.exist());
}
break;
case DLG_PRINT:
if (e == fe_button)
{
const TFilename output = get(F_REPORT);
if (output.exist())
{
TString cmd;
cmd << "ba8 -2 " << output;
TExternal_app app(cmd);
app.run();
return false; // Altrimenti esce dalla maschera
}
else
return error_box(TR("Il file %s non esiste"), (const char*)output);
}
break;
default:
break;
}
return true;
}
TFormer_mask::TFormer_mask() : TAutomask("ba8400a")
{
}
///////////////////////////////////////////////////////////
// TFormer_app
///////////////////////////////////////////////////////////
class TFormer_app : public TSkeleton_application
{
protected:
virtual void main_loop();
};
void TFormer_app::main_loop()
{
TFormer_mask m;
m.run();
}
int ba8400(int argc, char* argv[])
{
TFormer_app app;
app.run(argc, argv, TR("Form Converter"));
return 0;
}

2
ba/ba8400.h Executable file
View File

@ -0,0 +1,2 @@
#define F_FORM 101
#define F_REPORT 102

37
ba/ba8400a.uml Executable file
View File

@ -0,0 +1,37 @@
#include "ba8400.h"
PAGE "Conversione Form in Report" -1 -1 62 6
STRINGA F_FORM 256 50
BEGIN
PROMPT 1 1 "Form "
FSELECT "*.frm"
END
STRINGA F_REPORT 256 50
BEGIN
PROMPT 1 2 "Report "
END
BUTTON DLG_ELABORA 10 2
BEGIN
PROMPT -13 -1 "~Elabora"
PICTURE BMP_ELABORA
FLAGS "D"
END
BUTTON DLG_PRINT 10 2
BEGIN
PROMPT -23 -1 "~Stampa"
PICTURE BMP_PRINT
FLAGS "D"
END
BUTTON DLG_QUIT 10 2
BEGIN
PROMPT -33 -1 ""
END
ENDPAGE
ENDMASK