Files correlati : ve0.exe Ricompilazione Demo : [ ] Commento : form.cpp Aggiunto supporto per custom/bitamp realtion.cpp Semplici sostituzioni di cose ripetute n volte con una singola variabile scanner.cpp Aggiunti apici in segnalazione di errore strings.cpp Corretta lettura di una stringa da file ad EOF tree.cpp Corretto disegno linee in presenza di header (Elaborazioni differite) git-svn-id: svn://10.65.10.50/trunk@11226 c028cbd2-c16b-5b4b-a496-9718f37d4682
4731 lines
119 KiB
C++
Executable File
4731 lines
119 KiB
C++
Executable File
#define __FORM_CPP
|
||
|
||
#include <applicat.h>
|
||
#include <currency.h>
|
||
#include <defmask.h>
|
||
#include <expr.h>
|
||
#include <form.h>
|
||
#include <msksheet.h>
|
||
#include <printer.h>
|
||
#include <relation.h>
|
||
#include <tabutil.h>
|
||
#include <utility.h>
|
||
|
||
#include "../ba/bafrm.h"
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Utility functions
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @func Funzione che converte dalla notazione carattere al corrispondente
|
||
// enum <t pagetype>
|
||
//
|
||
// @rdesc Ritorna il <t pagetype> corrispondente
|
||
pagetype char2page(
|
||
char c) // @parm Notazione carattere del tipo di pagina
|
||
|
||
{
|
||
pagetype pt;
|
||
switch(c)
|
||
{
|
||
case '1':
|
||
case 'E':
|
||
pt = even_page; break;
|
||
case '2':
|
||
case 'F':
|
||
pt = first_page; break;
|
||
case '3':
|
||
case 'L':
|
||
pt = last_page; break;
|
||
default:
|
||
pt = odd_page; break;
|
||
}
|
||
return pt;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_flags
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TForm_flags::TForm_flags()
|
||
{
|
||
automagic = dirty = finkr = finkl = memo = newpage = price = FALSE;
|
||
shown = enabled = TRUE;
|
||
}
|
||
|
||
// Read from string
|
||
// Certified 100%
|
||
bool TForm_flags::update(const char* s)
|
||
{
|
||
CHECK(s, "NULL flags string");
|
||
for (; *s; s++) switch(toupper(*s))
|
||
{
|
||
case 'A':
|
||
automagic = TRUE; break;
|
||
case 'D':
|
||
enabled = FALSE; break;
|
||
case 'H':
|
||
shown = FALSE; break;
|
||
case 'F':
|
||
finkl = TRUE; break;
|
||
case 'K':
|
||
finkr = TRUE; break;
|
||
case 'M':
|
||
memo = TRUE; break;
|
||
case 'N':
|
||
newpage = TRUE; break;
|
||
case 'U':
|
||
price = TRUE; break;
|
||
default :
|
||
error_box("Unknown form item flag '%c'", *s); break;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// Print on stream
|
||
// Certified 100%
|
||
void TForm_flags::print_on(ostream& out) const
|
||
{
|
||
TString16 s;
|
||
|
||
if (automagic) s << "A";
|
||
if (!enabled) s << "D";
|
||
if (!shown) s << "H";
|
||
if (memo) s << "M";
|
||
if (newpage) s << "N";
|
||
if (finkl) s << "F";
|
||
if (finkr) s << "K";
|
||
if (price) s << "U";
|
||
|
||
if (s.not_empty())
|
||
out << " FLAGS \"" << s << '"' << endl;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_item
|
||
///////////////////////////////////////////////////////////
|
||
TForm_item::TForm_item(TPrint_section* section)
|
||
: _section(section), _x(-1), _y(-1), _width(0),
|
||
_height(0),_effective_height(0), _id(0), _ofs(0),
|
||
_temp(FALSE)
|
||
{}
|
||
|
||
void TForm_item::copy_to_form_item(TForm_item* fi) const
|
||
{
|
||
fi->_flag = _flag; fi->_group = _group;
|
||
|
||
/* come copiarlo facendo una cosa orrenda...
|
||
fi->_special.destroy();
|
||
specials().restart();
|
||
int items = special_items();
|
||
for (int k = 0; k < items; k++)
|
||
{
|
||
THash_object* ho = specials().get_hashobj();
|
||
fi->_special.add(ho->key(),ho->obj());
|
||
}
|
||
*/
|
||
fi->_special = _special; // sarebbe utile avere un "operator =" per i TAssoc_array
|
||
|
||
fi->_temp = _temp; fi->_id = _id;
|
||
fi->_x = _x; fi->_y = _y;
|
||
fi->_width = _width; fi->_height = _height;
|
||
fi->_effective_height = _effective_height;
|
||
fi->_ofs = _ofs; fi->_prompt = _prompt;
|
||
fi->_desc = _desc; fi->_col_head = _col_head;
|
||
|
||
/* Anche qui... copia uno alla volta
|
||
items = _message.items();
|
||
for (k = 0; k < items; k++)
|
||
fi->_message.add(_message.row(k),k);
|
||
*/
|
||
fi->_message = _message; // sarebbe utile avere un "operator =" per i TString_array
|
||
}
|
||
|
||
TObject* TForm_item::dup() const
|
||
{
|
||
TForm_item * fi = new TForm_item(_section);
|
||
copy_to_form_item(fi);
|
||
return fi;
|
||
}
|
||
|
||
bool TForm_item::parse_head(TScanner& scanner)
|
||
{
|
||
_id = scanner.integer();
|
||
|
||
if (_id == 0) // Temporary
|
||
_id = _section->fields()+1;
|
||
|
||
_width = scanner.integer();
|
||
if (_width > 0)
|
||
_height = scanner.integer();
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void TForm_item::print_on(ostream& out) const
|
||
{
|
||
out << class_name() << ' ' << id();
|
||
if (_width > 0)
|
||
{
|
||
out << ' ' << _width;
|
||
if (_height > 0)
|
||
out << ' ' << _height;
|
||
}
|
||
out << "\nBEGIN\n";
|
||
|
||
print_body(out);
|
||
|
||
out << "END\n" << endl;
|
||
}
|
||
|
||
|
||
void TForm_item::print_body(ostream& out) const
|
||
{
|
||
out << " KEY \"" << _desc << "\"\n";
|
||
|
||
if (_y >= 0)
|
||
out << " PROMPT " << _x << ' ' << _y << " \"" << _prompt << "\"\n";
|
||
|
||
if (_group.ones())
|
||
out << " GROUP " << _group << "\n";
|
||
|
||
out << _flag;
|
||
|
||
if (_message.items() == 1)
|
||
{
|
||
const TToken_string& m = _message.row(0);
|
||
if (!m.empty_items())
|
||
out << " MESSAGE " << m << endl;
|
||
}
|
||
|
||
if (_special.items() > 0)
|
||
{
|
||
TAssoc_array& aa = specials();
|
||
aa.restart();
|
||
|
||
THash_object* op;
|
||
|
||
while ((op = aa.get_hashobj()) != NULL)
|
||
{
|
||
TToken_string& t = (TToken_string&)op->obj();
|
||
TString typ(t.get(0));
|
||
TString val(t.get(1));
|
||
TString des(t.get(2));
|
||
out << " SPECIAL " << typ << " " << op->key()
|
||
<< " \"" << val << "\" \"" << des << "\"\n";
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
bool TForm_item::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "PR")
|
||
{
|
||
_x = scanner.integer();
|
||
_y = scanner.integer();
|
||
_prompt = scanner.string();
|
||
return TRUE;
|
||
}
|
||
|
||
if (scanner.key() == "FL")
|
||
return _flag.update(scanner.string());
|
||
|
||
if (scanner.key() == "ME")
|
||
{
|
||
TFixed_string m(scanner.line());
|
||
m.strip_spaces();
|
||
int n = 0;
|
||
if (m.left(5) == "EMPTY")
|
||
{
|
||
n = 1;
|
||
m.ltrim(5);
|
||
}
|
||
if (!m.blank())
|
||
message(n).add(m);
|
||
return TRUE;
|
||
}
|
||
|
||
if (scanner.key() == "KE")
|
||
{
|
||
_desc = scanner.string();
|
||
return TRUE;
|
||
}
|
||
|
||
if (scanner.key() == "GR")
|
||
{
|
||
_group.set(scanner.line());
|
||
return TRUE;
|
||
}
|
||
|
||
if (scanner.key() == "SP")
|
||
{
|
||
TToken_string val(scanner.pop());
|
||
TString16 var = scanner.pop();
|
||
val.add(scanner.string());
|
||
val.add(scanner.string());
|
||
|
||
_special.add(var,val);
|
||
return TRUE;
|
||
}
|
||
|
||
yesnofatal_box("Unknown symbol in item '%s': '%s'",
|
||
(const char*)key(), (const char*)scanner.token());
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
bool TForm_item::parse(TScanner& scanner)
|
||
{
|
||
bool ok = parse_head(scanner);
|
||
|
||
if (ok && scanner.popkey() != "BE")
|
||
ok = yesnofatal_box("Missing BEGIN in form item %s", (const char*)key());
|
||
|
||
while (ok && scanner.popkey() != "EN")
|
||
ok = parse_item(scanner);
|
||
|
||
return ok;
|
||
}
|
||
|
||
bool TForm_item::read_from(const TRectype& prof)
|
||
{
|
||
CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
|
||
bool changed = FALSE;
|
||
|
||
int i = prof.get_int("X");
|
||
if (_x != i)
|
||
{
|
||
_x = i;
|
||
changed = TRUE;
|
||
}
|
||
i = prof.get_int("Y");
|
||
if (_y != i)
|
||
{
|
||
_y = i;
|
||
changed = TRUE;
|
||
}
|
||
i = prof.get_int("LEN");
|
||
if (_width != i)
|
||
{
|
||
_width = i;
|
||
changed = TRUE;
|
||
}
|
||
i = prof.get_int("HGT");
|
||
if (_height != i)
|
||
{
|
||
_height = i;
|
||
changed = TRUE;
|
||
}
|
||
TString p(prof.get("PROMPT"));
|
||
if (p.not_empty())
|
||
{
|
||
if (p[0] == '\xFE') p.cut(0);
|
||
const int l = p.len();
|
||
if (l > 0 && p[l-1] == '\xFF')
|
||
{
|
||
p[l-1] = ' ';
|
||
p << '\0';
|
||
}
|
||
_prompt = p;
|
||
changed = TRUE;
|
||
}
|
||
|
||
const bool s = prof.get_bool("ATTIVO");
|
||
if (_flag.shown != s)
|
||
{
|
||
_flag.shown = s;
|
||
changed = TRUE;
|
||
}
|
||
|
||
TToken_string special(prof.get("SPECIAL"),'\n');
|
||
special.rtrim();
|
||
const int sp_items = special.items();
|
||
for (i = 0; i < sp_items; i++)
|
||
{
|
||
TToken_string sp(special.get(i), '$');
|
||
TString key(sp.get(0));
|
||
TString val(sp.get(1));
|
||
|
||
if (!_special.is_key(key))
|
||
{
|
||
error_box("Variabile speciale non presente nel profilo: %s",
|
||
(const char*)key);
|
||
continue;
|
||
}
|
||
TToken_string& tt = (TToken_string&)_special[key];
|
||
tt.add(val,1);
|
||
// forza riscrittura su memo
|
||
if (tt.items() == 3) tt.add("X");
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_item::print_on(TRectype& prof)
|
||
{
|
||
CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
|
||
prof.put("ID", id());
|
||
prof.put("X", _x);
|
||
prof.put("Y", _y);
|
||
prof.put("LEN", width());
|
||
prof.put("HGT", height());
|
||
if (_prompt.empty()) _prompt << '\xFE' << '\0';
|
||
const int l = _prompt.len();
|
||
const char c = _prompt[l-1];
|
||
if (c==' ') _prompt[l-1]='\xFF';
|
||
prof.put("PROMPT", _prompt);
|
||
prof.put("ATTIVO", shown() ? "X" : " ");
|
||
|
||
// specials: se e' stato cambiato, la tokenstring del valore contiene
|
||
// una X alla fine (campo 3)
|
||
{
|
||
TToken_string special(128,'\n');
|
||
_special.restart();
|
||
|
||
for (int i = 0; i < _special.items(); i++)
|
||
{
|
||
THash_object* o = _special.get_hashobj();
|
||
|
||
TString key(o->key());
|
||
TToken_string& tt = (TToken_string&)o->obj();
|
||
|
||
if (tt.items() == 4)
|
||
{
|
||
TToken_string sp(key,'$');
|
||
TString val(tt.get(1));
|
||
sp.add(val);
|
||
special.add(sp);
|
||
}
|
||
}
|
||
special.rtrim();
|
||
prof.put("SPECIAL", special);
|
||
}
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Abilita/Disabilita il campo
|
||
void TForm_item::enable(
|
||
bool on) // @parm Operazione da svolgere sul campo:
|
||
// @flag TRUE | Il campo viene abiliato
|
||
// @flag FALSE | Il campo viene disabiliato
|
||
|
||
// @comm Viene automaticamente setta se il campo diventi visibile o nascosto (chiama <mf TForm_item::show>)
|
||
{
|
||
_flag.enabled = on;
|
||
show(on);
|
||
}
|
||
|
||
void TForm_item::set_special_value(const char* s, const char* val)
|
||
{
|
||
TToken_string& tt = (TToken_string&) _special[s];
|
||
tt.add(val,1);
|
||
if (tt.items()==3) tt.add("X");
|
||
}
|
||
|
||
const char* TForm_item::get_special_item(const char* s, int n) const
|
||
{
|
||
TAssoc_array& sp = (TAssoc_array&)_special;
|
||
if (sp.is_key(s))
|
||
{
|
||
TToken_string& tt = (TToken_string&) sp[s];
|
||
return tt.get(n);
|
||
} else return "";
|
||
}
|
||
|
||
void TForm_item::string_at(int x, int y, const char* s)
|
||
{
|
||
if (shown())
|
||
{
|
||
if (section().columnwise()) x += _ofs;
|
||
TPrintrow& row = section().row(y-1); // Seleziona riga di stampa
|
||
|
||
if (_width > 0 && strlen(s) > (word)_width) // Tronca testo se necessario
|
||
{
|
||
TString& tmp = get_tmp_string();
|
||
tmp.strncpy(s, _width);
|
||
s = tmp;
|
||
}
|
||
row.put(s, x-1); // Stampa testo
|
||
}
|
||
}
|
||
|
||
|
||
TToken_string& TForm_item::message(int m)
|
||
{
|
||
TToken_string* t = (TToken_string*)_message.objptr(m);
|
||
if (t == NULL)
|
||
{
|
||
t = new TToken_string(16);
|
||
_message.add(t, m);
|
||
}
|
||
return *t;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Manda il messaggio al campo <p dest>
|
||
void TForm_item::send_message(
|
||
const TString& cmd, // @parm Messaggio di comando
|
||
TForm_item& des) const // @parm Campo a cui destinare il messaggio
|
||
{
|
||
if (cmd == "ADD" || cmd == "INC")
|
||
{
|
||
if (form().message_add_enabled())
|
||
{
|
||
const real n((cmd[0] == 'I') ? "1.0" : get());
|
||
real r(des.get());
|
||
r += n;
|
||
des.set(r.string());
|
||
}
|
||
} else if (cmd == "COPY") {
|
||
des.set(get());
|
||
} else if (cmd == "APPEND") {
|
||
TString256 val = des.get();
|
||
if (val.not_empty()) val << ' ';
|
||
val << get();
|
||
des.set(val);
|
||
} else if (cmd == "RESET") {
|
||
des.set("");
|
||
} else if (cmd == "DISABLE") {
|
||
des.disable();
|
||
} else if (cmd == "ENABLE") {
|
||
des.enable();
|
||
} else if (cmd == "HIDE") {
|
||
des.hide();
|
||
} else if (cmd == "SHOW") {
|
||
des.show();
|
||
} else if (cmd == "SUB") {
|
||
const real n(get());
|
||
real r(des.get());
|
||
r -= n;
|
||
des.set(r.string());
|
||
} else if (cmd[0] == '"') {
|
||
TString256 val(cmd);
|
||
val.strip("\"");
|
||
des.set(val);
|
||
} else
|
||
error_box("Unknown message in item '%s': '%s'",
|
||
(const char*)key(), (const char*)cmd);
|
||
}
|
||
|
||
|
||
TForm_item& TForm_item::find_field(const TString& id) const
|
||
{
|
||
if (isdigit(id[0])) // Field in the same section
|
||
{
|
||
TForm_item& des = section().find_field(atoi(id));
|
||
return des;
|
||
}
|
||
|
||
const int freccia = id.find("->");
|
||
const pagetype pt = (freccia==2) ? char2page(id[1]) : section().page_type() ;
|
||
char se;
|
||
int id_num;
|
||
int pos_id;
|
||
if (freccia >= 0)
|
||
{
|
||
pos_id=freccia+2;
|
||
id_num=atoi(id.mid(pos_id));
|
||
se = id[0];
|
||
} else {
|
||
id_num=0;
|
||
se = section().section_type();
|
||
pos_id=0;
|
||
}
|
||
if (id_num) // id numerico: campo semplice
|
||
{
|
||
TForm_item& des = form().find_field(se, pt, id_num);
|
||
return des;
|
||
} else { // id stringa : campo sezione
|
||
TForm_item& des = form().find_field(se, pt, id.mid(pos_id));
|
||
return des;
|
||
}
|
||
}
|
||
|
||
// il parametro num serve per identificare il messaggio nelle listbox...
|
||
bool TForm_item::do_message(int num)
|
||
{
|
||
TToken_string& messaggio = message(num);
|
||
if (messaggio.empty_items())
|
||
return FALSE;
|
||
TToken_string msg(16, ',');
|
||
for (const char* m = messaggio.get(0); m; m = messaggio.get())
|
||
{
|
||
msg = m;
|
||
if (*m == '_')
|
||
form().validate(*this, msg);
|
||
else
|
||
{
|
||
const TString80 cmd(msg.get()); // Get command
|
||
const TString80 id = msg.get(); // Get destination
|
||
|
||
if (id.right(1) == "@")
|
||
{
|
||
const byte group = atoi(id);
|
||
// Send the message to all fields in local and upper sections with the given group
|
||
send_message_to_group(cmd,group,section(),§ion());
|
||
}
|
||
else
|
||
{
|
||
TForm_item& des = find_field(id);
|
||
send_message(cmd, des);
|
||
}
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_item::send_message_to_group(const char * cmd,byte id,const TPrint_section & section, const TPrint_section *starting_section)
|
||
{
|
||
TForm_item * f ;
|
||
// look into local section
|
||
for(word i = 0; i < section.fields(); i++)
|
||
{
|
||
f = §ion.field(i);
|
||
if (f->in_group(id))
|
||
send_message(cmd,*f);
|
||
}
|
||
// look into the section above ("father" )
|
||
if (section.section_above() && section.section_above()!=starting_section) {
|
||
send_message_to_group(cmd,id,*section.section_above(),§ion);
|
||
}
|
||
// look into sections beside ("brothers" )
|
||
for (int j = 0; j < section.subsections(); j++) {
|
||
const TPrint_section &bs=section.subsection(j)->printsection();
|
||
if (&bs!=starting_section) {
|
||
send_message_to_group(cmd,id,section.subsection(j)->printsection(),§ion);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
bool TForm_item::update()
|
||
{
|
||
if (_prompt.right(1) == "#")
|
||
{
|
||
TString prompt(_prompt);
|
||
for (int i = prompt.len()-2; i >= 0; i--)
|
||
if (prompt[i] != '#') break;
|
||
prompt.cut(i+1);
|
||
string_at(x(), _y, prompt);
|
||
}
|
||
else string_at(x(), _y, _prompt);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_item::print_on(TToken_string& row) const
|
||
{
|
||
row.cut(0);
|
||
row.add(id());
|
||
row.add(key());
|
||
row.add(_y);
|
||
row.add(_x);
|
||
row.add(shown() ? " " : "X");
|
||
|
||
if (form().edit_level() > 1)
|
||
{
|
||
const long fu = _group.first_one();
|
||
if (fu > 0) row.add(fu);
|
||
else row.add(" ");
|
||
}
|
||
}
|
||
|
||
|
||
const TString& TForm_item::picture() const
|
||
{
|
||
NFCHECK("Can't get the picture of a generic form item!");
|
||
return EMPTY_STRING;
|
||
}
|
||
|
||
void TForm_item::set_picture(const char*)
|
||
{
|
||
NFCHECK("Can't set the picture of a generic form item!");
|
||
}
|
||
|
||
TToken_string& TForm_item::memo_info()
|
||
{
|
||
NFCHECK("Can't get a memo of a generic form item!");
|
||
return (TToken_string &) EMPTY_STRING;
|
||
}
|
||
|
||
short TForm_item::x()
|
||
{
|
||
if (_section == NULL || !_section->columnwise())
|
||
return _x;
|
||
return _section->tab(_x-1) + _section->ofspc();
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_subsection
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
TForm_subsection::TForm_subsection(TPrint_section* s, const char* nm)
|
||
: TForm_item(s), _ssec(&(s->form()), s->section_type(), s->page_type()),
|
||
_file_id(-1), _name(nm), _condexpr(NULL),
|
||
_title_section(NULL),_qtitle_section(NULL),_title_type(type_notitle),_show_title(FALSE)
|
||
{
|
||
_ssec.set_subsection_above(this);
|
||
}
|
||
|
||
TForm_subsection::~TForm_subsection()
|
||
{
|
||
if (_condexpr) delete _condexpr;
|
||
// _title_section e _qtitle_section sono puntatori a subsection contenute nel corpo, quindi non vanno deallocati
|
||
}
|
||
|
||
TObject* TForm_subsection::dup() const
|
||
{
|
||
TForm_subsection* fs = new TForm_subsection(_section);
|
||
copy_to_form_item(fs);
|
||
fs->_ssec = _ssec;
|
||
fs->_name = _name;
|
||
fs->_file_id = _file_id;
|
||
fs->_title_type = _title_type;
|
||
fs->_show_title=_show_title;
|
||
if (_condexpr)
|
||
fs->_condexpr=new TExpression((const char *)_condexpr);
|
||
else
|
||
fs->_condexpr=NULL;
|
||
if (_title_section)
|
||
fs->_title_section=(TForm_subsection* )_title_section->dup();
|
||
else
|
||
fs->_title_section=NULL;
|
||
if (_qtitle_section)
|
||
fs->_qtitle_section=(TForm_subsection* )_qtitle_section->dup();
|
||
else
|
||
fs->_qtitle_section=NULL;
|
||
return fs;
|
||
}
|
||
|
||
int TForm_subsection::fileid()
|
||
{
|
||
return _file_id;
|
||
}
|
||
// restituisce la condizione della sottosezione
|
||
const char * TForm_subsection::condition()
|
||
{
|
||
if (_condexpr)
|
||
return (const char *)_condexpr->string();
|
||
else
|
||
return NULL;
|
||
}
|
||
|
||
// imposta la condizione della sottosezione
|
||
void TForm_subsection::setcondition(const char* cond,TTypeexp type)
|
||
{
|
||
if (_condexpr)
|
||
{
|
||
if (_file_id != -1)
|
||
printsection().set_subs_cond(_file_id,cond,_condexpr->string());
|
||
delete _condexpr;
|
||
}
|
||
_condexpr=new TExpression(cond,type);
|
||
}
|
||
|
||
|
||
// imposta la sottosezione titolo
|
||
void TForm_subsection::set_title_section(TForm_subsection* s)
|
||
{
|
||
if (_title_section) delete _title_section;
|
||
_title_section=s;
|
||
}
|
||
|
||
// imposta la sottosezione titolo di coda
|
||
void TForm_subsection::set_qtitle_section(TForm_subsection* s)
|
||
{
|
||
if (_qtitle_section) delete _qtitle_section;
|
||
_qtitle_section=s;
|
||
}
|
||
|
||
|
||
void TPrint_section::print_title()
|
||
{
|
||
TPrinter& pr = printer();
|
||
|
||
if (pr.current_row() > pr.headersize()+1)
|
||
if (word(height()) > pr.rows_left())
|
||
pr.formfeed();
|
||
word last_printed_row=0;
|
||
const word maxs=(word)subsections() ;
|
||
for (word s = 0; s < (word)maxs ;s++)
|
||
{
|
||
TForm_subsection &ssec=*subsection(s);
|
||
for (; last_printed_row < (word)ssec.y() -1;last_printed_row++)
|
||
pr.print(titlerow(last_printed_row));
|
||
if (ssec.shown())
|
||
ssec.printsection().print_title();
|
||
}
|
||
for (; last_printed_row < (word)height() ;last_printed_row++)
|
||
pr.print(titlerow(last_printed_row));
|
||
}
|
||
|
||
|
||
void TPrint_section::set_subs_cond(int file,const char *newcond,const char * oldcond)
|
||
{
|
||
TForm_subsection * s;
|
||
s=(TForm_subsection * )(_subsections.first_item());
|
||
while (s) {
|
||
TString newsubcond(s->condition());
|
||
if (file!=-1 && s->fileid()==file && newsubcond.not_empty()) {
|
||
// there's another file group subsection below....
|
||
newsubcond=newsubcond.mid(strlen(oldcond));
|
||
newsubcond.insert(newcond);
|
||
s->setcondition(newsubcond,_strexpr);
|
||
}
|
||
s=(TForm_subsection * )(_subsections.succ_item()) ;
|
||
}
|
||
}
|
||
|
||
// ritorna l'indirizzo della prima sottosezione condizionale di livello superiore alla corrente
|
||
TForm_subsection *TForm_subsection::upper_conditional() const
|
||
{
|
||
if (section().subsection_above())
|
||
{
|
||
if (section().subsection_above()->_condexpr && section().subsection_above()->_file_id>0)
|
||
return section().subsection_above();
|
||
else
|
||
return section().subsection_above()->upper_conditional();
|
||
} else
|
||
return NULL;
|
||
}
|
||
|
||
// Esegue una post visita dell'albero delle subsection, stampando tutte le section "Titolo"
|
||
bool TForm_subsection::print_titles()
|
||
{
|
||
if (section().subsection_above())
|
||
section().subsection_above()->print_titles();
|
||
bool ok=TRUE;
|
||
// print the title
|
||
if (_title_section != NULL && _title_section->_show_title)
|
||
{
|
||
if ( shown() && _title_section->shown() )
|
||
{
|
||
_title_section->printsection().print_title();
|
||
}
|
||
_title_section->show_title(FALSE);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TForm_subsection::print_qtitle()
|
||
{
|
||
bool ok=TRUE;
|
||
// print the title
|
||
if (_qtitle_section != NULL)
|
||
{
|
||
if (shown() && _qtitle_section->shown())
|
||
{
|
||
print_titles();
|
||
_qtitle_section->printsection().print_title();
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
|
||
|
||
bool TForm_subsection::parse(TScanner& s)
|
||
{
|
||
_section->add_subsection(this);
|
||
name(s.pop());
|
||
//_width = s.integer(); // ...unused
|
||
//_x = s.integer(); // ...unused
|
||
_y = s.integer(); // posizione rispetto ai campi della sezione "padre"
|
||
_height = s.integer(); // minima altezza (primo "header")
|
||
|
||
_ssec.parse_head(s);
|
||
s.popkey();
|
||
if (s.key() == "FI") // FI_LE su cui iterare con next_match
|
||
{
|
||
_file_id = name2log(s.pop());
|
||
if (s.popkey() == "GR" || s.key() == "BY")
|
||
{
|
||
// GR_OUP or BY group : gestione dei raggruppamenti o big skip
|
||
TString e;
|
||
TForm_subsection * uppersec=upper_conditional();
|
||
e = s.line();
|
||
if (uppersec && uppersec->_file_id==_file_id)
|
||
{
|
||
// se anche la sezione soprastante
|
||
const TString& eu = uppersec->_condexpr->string();
|
||
if (e != eu)
|
||
{
|
||
e.insert("+");
|
||
if (e != eu.right(e.len()))
|
||
e.insert(eu); // Aggiungo espressione precedente
|
||
else
|
||
e = eu; // Inutile aggiungere espressione gi<67> presente
|
||
}
|
||
}
|
||
_condexpr = new TExpression(e,_strexpr);
|
||
_bigskip = s.key() == "BY";
|
||
} else
|
||
s.push();
|
||
} else {
|
||
if (s.key() == "NU") // NU_MERIC CONDITION di gestione della sezione
|
||
_condexpr = new TExpression(s.line(),_numexpr); //
|
||
else if (s.key() == "ST") // ST_RING CONDITION di gestione della sezione
|
||
_condexpr = new TExpression(s.line(),_strexpr); //
|
||
else if (s.key() == "HE") // sottosezione HE_ADER (titolo), stampa solo se altr sotto sez verranno stampati
|
||
{
|
||
_title_type=type_title;
|
||
if (section().subsection_above())
|
||
section().subsection_above()->set_title_section(this);
|
||
}
|
||
else if (s.key() == "FO") // sottosezione FO_OOTER (titolo di coda), stampato solo se altr sotto sez verranno stampati
|
||
{
|
||
_title_type=type_qtitle;
|
||
if (section().subsection_above())
|
||
section().subsection_above()->set_qtitle_section(this);
|
||
}
|
||
else if (s.key() != "GR") // GR_OUP section (raggruppamento puro)
|
||
s.push();
|
||
}
|
||
if (s.popkey() == "FL")
|
||
_flag.update(s.string());
|
||
else s.push();
|
||
return(_ssec.parse_body(s)) ;
|
||
}
|
||
|
||
// nel caso di subsection viene chiamata la set_body anzich<63> la update
|
||
bool TForm_subsection::update()
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
bool TForm_subsection::print_body(sec_print_mode showfields)
|
||
{
|
||
bool at_newpage=(atnewpage() || printer().rows_left() < (word)minheight());
|
||
bool ok = FALSE;
|
||
TCursor* cur = form().cursor();
|
||
TRelation* rel = (TRelation* )form().relation();
|
||
|
||
set_effective_height(0); // resetta l'altezza della sottosezione al suo "minimo"
|
||
|
||
if (!enabled() )
|
||
return FALSE;
|
||
|
||
if (is_title())
|
||
{
|
||
show_title(TRUE);
|
||
showfields=printmode_title ; // calcola e bufferizza ora, rimanda la stampa dopo ...
|
||
}
|
||
if (!shown())
|
||
showfields = printmode_noprint;
|
||
|
||
if (cur == NULL || (_file_id == -1 && _condexpr==NULL)) // ...unused
|
||
ok = _ssec.update_and_print(showfields,at_newpage);
|
||
else if (_file_id == -1 && _condexpr!=NULL) // subsection condizionale
|
||
{
|
||
if ((bool)(_section->eval_expr(*_condexpr,_file_id)))
|
||
ok = _ssec.update_and_print(showfields,at_newpage);
|
||
}
|
||
else
|
||
{
|
||
_ssec.set_repeat_count(0);
|
||
if (_condexpr) { // sottosezione di raggruppamenti su file
|
||
int i = 0;
|
||
TString group_expr = _section->eval_expr(*_condexpr,_file_id).as_string();
|
||
bool again=TRUE;
|
||
while (again && group_expr==_section->eval_expr(*_condexpr,_file_id).as_string())
|
||
{
|
||
form().match_result(_file_id);
|
||
if (!_bigskip || i==0)
|
||
{
|
||
ok |= _ssec.update_and_print(showfields,at_newpage);
|
||
_ssec.set_repeat_count(++i);
|
||
}
|
||
if (form().next_match_done(_file_id))
|
||
{
|
||
again=form().last_match_result(_file_id); // continue if there WAS a match
|
||
} else {
|
||
again=cur->next_match(_file_id) ;
|
||
form().match_result(_file_id,again); // store if a match occoured
|
||
}
|
||
at_newpage=(atnewpage() || printer().rows_left() < (word)minheight());
|
||
}
|
||
// _ssec.set_repeat_count(0);
|
||
} else { // sottosezione di file
|
||
int i = 0;
|
||
if (cur->is_first_match(_file_id))
|
||
{
|
||
bool again;
|
||
do {
|
||
form().match_result(_file_id);
|
||
ok |= _ssec.update_and_print(showfields,at_newpage);
|
||
_ssec.set_repeat_count(++i);
|
||
if (form().next_match_done(_file_id))
|
||
again=form().last_match_result(_file_id);
|
||
else
|
||
again= cur->next_match(_file_id);
|
||
at_newpage=(atnewpage() || printer().rows_left() < (word)minheight());
|
||
} while (again);
|
||
ok |= (_ssec.repeat_count()>0); // (ovvero, sempre true: se c'e' un first match)
|
||
}
|
||
// _ssec.set_repeat_count(0);
|
||
}
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
|
||
|
||
|
||
// @mfunc Abilita (default) o disabilita la stampa di tutti i campi della sottosezione
|
||
/*void TForm_subsection::show(bool on)
|
||
{
|
||
TForm_item::show(on);
|
||
for (unsigned int i = 0; i < _ssec.fields(); i++)
|
||
_ssec.field(i).show(on);
|
||
}
|
||
|
||
// @mfunc Abilita (default) o disabilita la valutazione e la stampa di tutti i campi della sottosezione
|
||
void TForm_subsection::enable(bool on)
|
||
{
|
||
TForm_item::enable(on);
|
||
for (unsigned int i = 0; i < _ssec.fields(); i++)
|
||
_ssec.field(i).enable(on);
|
||
} */
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_string
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
TForm_string::TForm_string(TPrint_section* section)
|
||
: TForm_item(section), _memo("",'\n')
|
||
{}
|
||
|
||
TObject* TForm_string::dup() const
|
||
{
|
||
TForm_string* fs = new TForm_string(_section);
|
||
copy_to_form_item(fs);
|
||
fs->_str = _str;
|
||
fs->_picture = _picture;
|
||
fs->_field = _field;
|
||
fs->_memo = _memo;
|
||
return fs;
|
||
}
|
||
|
||
bool TForm_string::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "FI") // FIELD reference
|
||
{
|
||
TFieldref* fr = new TFieldref(scanner.line(), 0);
|
||
_field.add(fr);
|
||
return TRUE;
|
||
}
|
||
|
||
if (scanner.key() == "PI") // PICTURE def
|
||
{
|
||
set_picture(scanner.string());
|
||
return TRUE;
|
||
}
|
||
|
||
return TForm_item::parse_item(scanner);
|
||
}
|
||
|
||
bool TForm_string::set(const char* s)
|
||
{
|
||
_str = s;
|
||
return TRUE;
|
||
}
|
||
|
||
const char* TForm_string::get() const
|
||
{ return _str; }
|
||
|
||
|
||
// Se un campo e' abilitato ed ha almeno un riferimento su file leggilo
|
||
bool TForm_string::read()
|
||
{
|
||
const bool ok = enabled();
|
||
if (ok)
|
||
{
|
||
if (_field.items() != 0)
|
||
{
|
||
const char* s = "";
|
||
// !?!?!?!!
|
||
const TRelation* r = (TRelation* )form().relation();
|
||
CHECK(r, "Can't read from null relation");
|
||
for (int i = 0; i < _field.items() && *s == '\0'; i++)
|
||
s = field(i).read(*r);
|
||
set(s);
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
void TForm_string::put_paragraph(const char* s)
|
||
{
|
||
if (hidden()) return;
|
||
|
||
const int h = height();
|
||
|
||
if (h > 1)
|
||
{
|
||
TString lines;
|
||
if (_prompt.not_empty())
|
||
lines = _prompt;
|
||
lines << s;
|
||
TParagraph_string p(lines, width());
|
||
for (int i=0; (s = p.get()) != NULL && i < h; i++)
|
||
string_at(x(), _y+i, s);
|
||
_effective_height = i;
|
||
|
||
TForm_subsection *subsec= section().subsection_above();
|
||
if (subsec)
|
||
{
|
||
// aggiorno l'altezza effettiva della sottosezione
|
||
if (effective_height() > 1)
|
||
{
|
||
// il campo si <20> "espanso"
|
||
const int last_y=effective_height()+y()-1;
|
||
if (last_y > subsec->height())
|
||
subsec->set_effective_height(last_y);
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if (_prompt.empty())
|
||
string_at(x(), _y, s);
|
||
else
|
||
string_at(-1 , _y, s);
|
||
}
|
||
}
|
||
|
||
|
||
void TForm_string::apply_format(TString& s) const
|
||
{
|
||
TString tmp(s);
|
||
if (!picture().blank())
|
||
{
|
||
TToken_string delim(4, ','); // Stringa con i due delimitatori
|
||
const char * pic = picture(); // Picture senza delimitatori
|
||
|
||
if (pic[0] == '(') // Se ci sono i delimitatori ...
|
||
{
|
||
const int bra = picture().find(')');
|
||
if (bra > 0) // ... cerca la parentesi chiusa
|
||
{
|
||
delim = picture().sub(1, bra); // memorizza delimitatori
|
||
pic += bra+1; // toglili dalla picture
|
||
}
|
||
}
|
||
|
||
if (strcmp(class_name(),"DATA")==0 && s.empty())
|
||
tmp ="";
|
||
else
|
||
tmp.picture(pic, s); // riempi la stringa col valore pitturato
|
||
|
||
if (!delim.empty_items()) // Aggiungi delimitatori
|
||
{
|
||
TString16 d(delim.get(0));
|
||
const int ld = d.len();
|
||
|
||
if (ld > 0) // Se il primo delimitatore e' valido ...
|
||
{
|
||
for (int spc = 0;s[spc]==' ' ; spc++) ;
|
||
if (spc < ld)
|
||
{
|
||
TString16 spazi;
|
||
spazi.spaces(ld - spc);
|
||
tmp.insert(spazi,0);
|
||
spc = ld;
|
||
}
|
||
tmp.overwrite(d,spc - ld);
|
||
}
|
||
d = delim.get();
|
||
if (d.not_empty()) // Se il secondo delimitatore e' valido ...
|
||
tmp << d; // ... aggiungilo alla fine
|
||
}
|
||
s = tmp;
|
||
}
|
||
}
|
||
|
||
bool TForm_string::update()
|
||
{
|
||
if (read()) // valuta il campo
|
||
{
|
||
TForm_item::update();
|
||
// esegue i messaggi
|
||
const int n = (_message.objptr(1) != NULL && *get()=='\0' ? 1 : 0);
|
||
do_message(n);
|
||
// prende il campo e lo stampa
|
||
TString s(get());
|
||
apply_format(s);
|
||
put_paragraph(s);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
const char* TForm_string::example() const
|
||
{
|
||
TString& prova = get_tmp_string();
|
||
prova = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||
apply_format(prova);
|
||
const int w = width();
|
||
if (prova.size() > w && w > 0)
|
||
prova.cut(w);
|
||
return prova;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_number
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TForm_number : public TForm_string
|
||
{
|
||
|
||
protected: // TForm_string
|
||
virtual const char* class_name() const { return "NUMERO"; }
|
||
virtual bool parse_head(TScanner& scanner);
|
||
virtual bool update();
|
||
//virtual int height() const { return 0; }
|
||
|
||
protected:
|
||
int decimals() const { return _height; }
|
||
|
||
public:
|
||
|
||
void real2currency(const real& r, TString& str) const;
|
||
virtual TObject* dup() const;
|
||
void set_decimals(int d) { _height = d; }
|
||
virtual const char* example() const;
|
||
virtual void set_picture(const char* p);
|
||
virtual void apply_format(TString& s) const;
|
||
virtual void put_paragraph(const char * s);
|
||
|
||
TForm_number(TPrint_section* section) : TForm_string(section) {}
|
||
virtual ~TForm_number() {}
|
||
};
|
||
|
||
bool TForm_number::parse_head(TScanner& scanner)
|
||
{
|
||
return TForm_item::parse_head(scanner);
|
||
}
|
||
|
||
TObject* TForm_number::dup() const
|
||
{
|
||
TForm_number *fn = new TForm_number(_section);
|
||
copy_to_form_item(fn);
|
||
return fn;
|
||
}
|
||
|
||
void TForm_number::put_paragraph(const char* s)
|
||
{
|
||
if (hidden()) return;
|
||
|
||
int gap = 0;
|
||
if (section().columnwise())
|
||
{
|
||
const int w = width();
|
||
const int l = strlen(s);
|
||
if (w>l) gap = w-l;
|
||
}
|
||
if (_prompt.empty())
|
||
string_at(x()+gap, _y, s);
|
||
else
|
||
string_at(-1, _y, s); // se ha il prompt stampa all'ultima posizione raggiunta
|
||
}
|
||
|
||
void TForm_number::real2currency(const real& r, TString& str) const
|
||
{
|
||
TCurrency c(r);
|
||
c.set_price(_flag.price != 0);
|
||
|
||
const TExchange* oe = form().output_exchange();
|
||
if (oe && !c.get_exchange().same_value_as(*oe))
|
||
c.change_value(*oe);
|
||
|
||
const TString& pic = picture();
|
||
const int piclen = pic.len();
|
||
const bool dotted = pic.empty() || pic.find('.') >= 0;
|
||
str = c.string(dotted);
|
||
const int w = width();
|
||
if (w > piclen)
|
||
str.right_just(w);
|
||
}
|
||
|
||
bool TForm_number::update()
|
||
{
|
||
if (read()) // valuta il campo
|
||
{
|
||
TForm_item::update();
|
||
|
||
real n = get(); // Trasforma la stringa in numero reale
|
||
|
||
// Arrotonda intelligentemente il numero
|
||
int round_dec = decimals();
|
||
if (round_dec == 0 && width() > 9 && form().magic_currency()) // Magic currency?
|
||
round_dec = TCurrency::get_firm_dec();
|
||
n.round(round_dec);
|
||
|
||
if (_message.items() > 0)
|
||
{
|
||
const int nm = (_message.objptr(1) != NULL && n.is_zero()) ? 1 : 0;
|
||
do_message(nm);
|
||
n = get(); // Il numero potrebbe essere cambiato dal messaggio!
|
||
n.round(round_dec);
|
||
}
|
||
|
||
bool print = TRUE;
|
||
if (n.is_zero())
|
||
{
|
||
char sep = picture().find('E') >= 0 ? '.' :',';
|
||
int comma = picture().find(sep);
|
||
if (comma < 0 )
|
||
comma = picture().len();
|
||
print = comma > 0 && picture()[comma-1] == '@';
|
||
}
|
||
|
||
if (print)
|
||
{
|
||
TString80 print_string;
|
||
bool app_for = TRUE; // Apply format?
|
||
if (form().magic_currency())
|
||
{
|
||
const bool b1 = picture() == "." || (picture().len() >= 9 && picture().find(',') < 0);
|
||
const bool b2 = width() >= 9 && decimals() == 0;
|
||
if (b1 || b2)
|
||
{
|
||
real2currency(n, print_string);
|
||
app_for = FALSE; // La stringa <20> gi<67> belle che formattata!
|
||
}
|
||
}
|
||
if (app_for)
|
||
{
|
||
print_string = n.string();
|
||
apply_format(print_string);
|
||
}
|
||
put_paragraph(print_string);
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_number::apply_format(TString& s) const
|
||
{
|
||
if (!picture().blank())
|
||
{
|
||
real n(s);
|
||
TToken_string delim(4, ','); // Stringa con i due delimitatori
|
||
TString pic(picture()); // Picture senza delimitatori
|
||
int maxlen = -1;
|
||
|
||
if (pic[0] == '(') // Se ci sono i delimitatori ...
|
||
{
|
||
const int bra = pic.find(')');
|
||
if (bra > 0) // ... cerca la parentesi chiusa
|
||
{
|
||
delim = pic.sub(1, bra); // memorizza delimitatori
|
||
pic.ltrim(bra + 1); // toglili dalla picture
|
||
}
|
||
}
|
||
|
||
const int at = pic.find('@');
|
||
if (at > 0)
|
||
{
|
||
const int len = atoi(&pic[at+1]);
|
||
if (len > 0)
|
||
{
|
||
maxlen = len;
|
||
pic.cut(at);
|
||
}
|
||
}
|
||
|
||
s=n.string(pic); // riempi la stringa col valore pitturato
|
||
|
||
if (maxlen >= 0 && maxlen < s.size())
|
||
s.cut(maxlen);
|
||
if (!delim.empty_items()) // Aggiungi delimitatori
|
||
{
|
||
TString16 d(delim.get(0));
|
||
const int ld = d.len();
|
||
|
||
if (ld > 0) // Se il primo delimitatore e' valido ...
|
||
{
|
||
for (int spc = 0;s[spc]==' ' ; spc++) ;
|
||
if (spc < ld)
|
||
{
|
||
TString16 spazi;
|
||
spazi.spaces(ld - spc);
|
||
s.insert(spazi,0);
|
||
spc = ld;
|
||
}
|
||
s.overwrite(d,spc - ld);
|
||
}
|
||
d = delim.get();
|
||
if (d.not_empty()) // Se il secondo delimitatore e' valido ...
|
||
s << d; // ... aggiungilo alla fine
|
||
}
|
||
}
|
||
else
|
||
{
|
||
real n(s);
|
||
s = n.stringa(width(), decimals());
|
||
}
|
||
}
|
||
|
||
void TForm_number::set_picture(const char *p)
|
||
{
|
||
TForm_string::set_picture(p);
|
||
const int comma = picture().find(',');
|
||
if (comma > 0)
|
||
set_decimals(picture().len() - comma -1);
|
||
}
|
||
|
||
const char* TForm_number::example() const
|
||
{
|
||
TString& s = get_tmp_string();
|
||
s = "1234567890.123456";
|
||
apply_format(s);
|
||
return s;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_currency
|
||
///////////////////////////////////////////////////////////
|
||
class TForm_currency : public TForm_number
|
||
{
|
||
TForm_item* _driver;
|
||
|
||
protected: // TForm_string
|
||
virtual const char* class_name() const { return "VALUTA"; }
|
||
virtual bool parse_head(TScanner& scanner);
|
||
virtual bool parse_item(TScanner& scanner);
|
||
virtual bool update();
|
||
virtual const char* get() const;
|
||
// @cmember Manda il messaggio al campo <p dest>
|
||
virtual void send_message(const TString& cmd, TForm_item& dest) const;
|
||
public:
|
||
virtual TObject* dup() const;
|
||
virtual TCurrency get_currency() const;
|
||
|
||
TForm_currency(TPrint_section* section) : TForm_number(section), _driver(NULL) {}
|
||
virtual ~TForm_currency() {}
|
||
};
|
||
|
||
bool TForm_currency::parse_head(TScanner& scanner)
|
||
{
|
||
return TForm_item::parse_head(scanner);
|
||
}
|
||
|
||
bool TForm_currency::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "DR")
|
||
{
|
||
_driver = &find_field(scanner.pop());
|
||
return TRUE;
|
||
}
|
||
return TForm_number::parse_item(scanner);
|
||
}
|
||
|
||
TObject* TForm_currency::dup() const
|
||
{
|
||
TForm_currency *fn = new TForm_currency(_section);
|
||
copy_to_form_item(fn);
|
||
return fn;
|
||
}
|
||
|
||
const char* TForm_currency::get() const
|
||
{
|
||
const char* val = TForm_string::get();
|
||
return val;
|
||
}
|
||
|
||
TCurrency TForm_currency::get_currency() const
|
||
{
|
||
const TString& codval = _driver ? _driver->get() : form().get_curr_codval();
|
||
const real n(get());
|
||
return TCurrency(n, codval, ZERO, _exchange_undefined, _flag.price != 0);
|
||
}
|
||
|
||
bool TForm_currency::update()
|
||
{
|
||
if (read()) // valuta il campo
|
||
{
|
||
TForm_item::update();
|
||
|
||
if (_message.items() > 0)
|
||
{
|
||
const int nm = (_message.objptr(1) != NULL && real::is_null(get())) ? 1 : 0;
|
||
do_message(nm);
|
||
}
|
||
|
||
if (!real::is_null(get()))
|
||
{
|
||
TCurrency curr = get_currency();
|
||
if (!_driver)
|
||
{
|
||
const TExchange* oe = form().output_exchange();
|
||
if (oe != NULL && !curr.get_exchange().same_value_as(*oe))
|
||
curr.change_value(*oe);
|
||
}
|
||
|
||
// Niente apply_format(), la picture viene ignorata per i TForm_currency
|
||
TString80 v;
|
||
const TString& pic = picture();
|
||
if (pic.find("LETTERE") >= 0)
|
||
{
|
||
v = get();
|
||
apply_format(v);
|
||
const int slash = v.rfind('/');
|
||
TString16 tail;
|
||
for (int i = v.len()-1; i > 0 && !isalnum(v[i]); i--)
|
||
{
|
||
tail << v[i];
|
||
v.cut(i);
|
||
}
|
||
const int zeroes_needed = curr.decimals();
|
||
if (zeroes_needed > 0)
|
||
{
|
||
int zeroes_missing = 0;
|
||
if (slash >= 0)
|
||
{
|
||
const int decimals_already_there = v.len() - slash - 1;
|
||
zeroes_missing = zeroes_needed - decimals_already_there;
|
||
}
|
||
else
|
||
{
|
||
v << '/';
|
||
zeroes_missing = zeroes_needed;
|
||
}
|
||
for ( ; zeroes_missing > 0; zeroes_missing--)
|
||
v << '0';
|
||
}
|
||
else
|
||
{
|
||
if (slash >= 0)
|
||
v.cut(slash);
|
||
}
|
||
v << tail;
|
||
}
|
||
else
|
||
{
|
||
const bool dotted = pic.empty() || pic.find('.') > 0;
|
||
v = curr.string(dotted);
|
||
if (pic.right(3) == "^^^") // 770 only: to be improved
|
||
{
|
||
const int dec = curr.decimals();
|
||
if (dec == 0)
|
||
v.rtrim(3+dotted);
|
||
else
|
||
v.rtrim(dec+1);
|
||
}
|
||
const int w = width() - (_section->columnwise() ? _prompt.len() : 0);
|
||
if (w > v.len())
|
||
v.right_just(w);
|
||
}
|
||
put_paragraph(v);
|
||
}
|
||
else
|
||
{
|
||
const TString& pic = picture();
|
||
if (pic.right(1)[0] == '@')
|
||
{
|
||
TString80 v;
|
||
const int w = width() - (_section->columnwise() ? _prompt.len() : 0);
|
||
int d = 0;
|
||
if (_driver)
|
||
{
|
||
const TCurrency z(ZERO, _driver->get(), ZERO, _exchange_base, _flag.price != 0);
|
||
d = z.decimals();
|
||
}
|
||
else
|
||
{
|
||
const TExchange* oe = form().output_exchange();
|
||
if (oe != NULL)
|
||
{
|
||
const TCurrency z(ZERO, *oe, _flag.price != 0);
|
||
d = z.decimals();
|
||
}
|
||
else
|
||
d = TCurrency::get_firm_dec(_flag.price != 0);
|
||
}
|
||
|
||
if (d > 0)
|
||
{
|
||
v.format("%*.*lf", w, d, 0.0);
|
||
v.replace('.', ',');
|
||
}
|
||
else
|
||
v.format("%*d", w, 0);
|
||
|
||
put_paragraph(v);
|
||
}
|
||
else
|
||
put_paragraph("");
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_currency::send_message(const TString& cmd, TForm_item& dest) const
|
||
{
|
||
if (cmd == "ADD")
|
||
{
|
||
TCurrency total;
|
||
if (dest.class_name() != class_name()) // La destinazione non e' un TForm_currency
|
||
{
|
||
const real n = dest.get();
|
||
total.set_num(n);
|
||
}
|
||
else
|
||
total = ((TForm_currency&)dest).get_currency();
|
||
total += get_currency();
|
||
dest.set(total.get_num().string());
|
||
}
|
||
else
|
||
TForm_number::send_message(cmd, dest);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_date
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TForm_date : public TForm_string
|
||
{
|
||
TString16 _format;
|
||
|
||
protected:
|
||
virtual const char* class_name() const { return "DATA"; }
|
||
virtual bool read();
|
||
virtual bool set(const char*);
|
||
bool set(const TDate& d);
|
||
virtual bool parse_item(TScanner& scanner);
|
||
virtual void print_body(ostream& out) const;
|
||
|
||
virtual void print_on(TMask& m);
|
||
virtual void read_from(const TMask& m);
|
||
|
||
virtual bool read_from(const TRectype& rform);
|
||
virtual void print_on(TRectype& rform);
|
||
|
||
public:
|
||
|
||
virtual TObject* dup() const;
|
||
void set_format(const char* f) { _format = f; }
|
||
virtual bool edit(TMask& m);
|
||
virtual const char* example() const;
|
||
TForm_date(TPrint_section* section);
|
||
virtual ~TForm_date() {}
|
||
};
|
||
|
||
|
||
TForm_date::TForm_date(TPrint_section* section)
|
||
: TForm_string(section), _format("1444-")
|
||
{}
|
||
|
||
TObject* TForm_date::dup() const
|
||
{
|
||
TForm_date* fd = new TForm_date(_section);
|
||
copy_to_form_item(fd);
|
||
fd->_format = _format;
|
||
return fd;
|
||
}
|
||
|
||
bool TForm_date::read()
|
||
{
|
||
bool ok = TForm_string::read();
|
||
if (ok && !get()[0] && automagic())
|
||
set(printer().getdate());
|
||
return ok;
|
||
}
|
||
|
||
void TForm_date::print_body(ostream& out) const
|
||
{
|
||
TForm_string::print_body(out);
|
||
out << " FORMAT \"" << _format << "\"\n";
|
||
}
|
||
|
||
bool TForm_date::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "FO")
|
||
{
|
||
_format = scanner.string();
|
||
return TRUE;
|
||
}
|
||
return TForm_string::parse_item(scanner);
|
||
}
|
||
|
||
bool TForm_date::read_from(const TRectype& prof)
|
||
{
|
||
bool changed = TForm_string::read_from(prof);
|
||
|
||
const TString& df = prof.get("DATEFORM");
|
||
if (df.not_empty() && df != _format)
|
||
{
|
||
_format = df;
|
||
changed = TRUE;
|
||
}
|
||
|
||
return changed;
|
||
}
|
||
|
||
void TForm_date::print_on(TRectype& prof)
|
||
{
|
||
TForm_string::print_on(prof);
|
||
prof.put("DATEFORM", _format);
|
||
}
|
||
|
||
|
||
bool TForm_date::set(const char* s)
|
||
{
|
||
const TDate da(s);
|
||
return set(da);
|
||
}
|
||
|
||
bool TForm_date::set(const TDate& da)
|
||
{
|
||
TFormatted_date d(da); d.set_format(_format);
|
||
TForm_string::set(d.string());
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm_date::print_on(TMask& m)
|
||
{
|
||
const TDate dd(TODAY);
|
||
TFormatted_date d(dd); d.set_format(_format);
|
||
m.set(F_DEXAMPLE, d.string());
|
||
|
||
m.set(F_DFORMAT, _format.mid(0,1));
|
||
m.set(F_DDAY, _format.mid(1,1));
|
||
m.set(F_DMONTH, _format.mid(2,1));
|
||
m.set(F_DYEAR, _format.mid(3,1));
|
||
m.set(F_DSEP, _format.mid(4,1));
|
||
|
||
TForm_string::print_on(m);
|
||
}
|
||
|
||
void TForm_date::read_from(const TMask& m)
|
||
{
|
||
TForm_string::read_from(m);
|
||
|
||
// adjust format string
|
||
_format[0] = m.get(F_DFORMAT)[0];
|
||
_format[1] = m.get(F_DDAY )[0];
|
||
_format[2] = m.get(F_DMONTH )[0];
|
||
_format[3] = m.get(F_DYEAR )[0];
|
||
_format[4] = m.get(F_DSEP )[0];
|
||
_format[5] = '\0';
|
||
}
|
||
|
||
bool TForm_date::edit(TMask& m)
|
||
{
|
||
return TForm_string::edit(m);
|
||
}
|
||
|
||
const char* TForm_date::example() const
|
||
{
|
||
const TDate dd(TODAY);
|
||
TFormatted_date d(dd); d.set_format(_format);
|
||
TString& s = get_tmp_string();
|
||
s = d.string();
|
||
return s;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_list
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TForm_list : public TForm_string
|
||
{
|
||
TToken_string _codes;
|
||
TToken_string _values;
|
||
|
||
protected:
|
||
virtual const char* class_name() const { return "LISTA"; }
|
||
virtual bool parse_item(TScanner& scanner);
|
||
virtual void print_on(TMask& m);
|
||
virtual void read_from(const TMask& m);
|
||
virtual void print_body(ostream& out) const;
|
||
virtual bool update();
|
||
|
||
public:
|
||
virtual TObject* dup() const;
|
||
TForm_list(TPrint_section* section);
|
||
virtual ~TForm_list() {}
|
||
};
|
||
|
||
TForm_list::TForm_list(TPrint_section* section)
|
||
: TForm_string(section)
|
||
{}
|
||
|
||
TObject* TForm_list::dup() const
|
||
{
|
||
TForm_list* fl = new TForm_list(_section);
|
||
copy_to_form_item(fl);
|
||
fl->_codes = _codes;
|
||
fl->_values = _values;
|
||
return fl;
|
||
}
|
||
|
||
bool TForm_list::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "IT")
|
||
{
|
||
TToken_string s(scanner.string());
|
||
_codes.add(s.get());
|
||
_values.add(s.get());
|
||
|
||
while (scanner.popkey() == "ME")
|
||
{
|
||
TFixed_string m(scanner.line());
|
||
m.strip_spaces();
|
||
message(_values.items()-1).add(m);
|
||
}
|
||
scanner.push();
|
||
return TRUE;
|
||
}
|
||
|
||
return TForm_string::parse_item(scanner);
|
||
}
|
||
|
||
void TForm_list::print_on(TMask& m)
|
||
{
|
||
TForm_string::print_on(m);
|
||
TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
|
||
s.reset();
|
||
_codes.restart(); _values.restart();
|
||
for (int i = 0; i < _codes.items(); i++)
|
||
{
|
||
TToken_string& row = s.row(i);
|
||
row = _codes.get();
|
||
row.add(_values.get());
|
||
row.add(message(i));
|
||
}
|
||
// s.force_update();
|
||
}
|
||
|
||
void TForm_list::read_from(const TMask& m)
|
||
{
|
||
TForm_string::read_from(m);
|
||
|
||
TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
|
||
|
||
_codes = _values = "";
|
||
for (int i = 0; i < s.items(); i++)
|
||
{
|
||
TToken_string& row = s.row(i);
|
||
_codes.add(row.get(0));
|
||
_values.add(row.get());
|
||
message(i) = row.get();
|
||
}
|
||
}
|
||
|
||
void TForm_list::print_body(ostream& out) const
|
||
{
|
||
TForm_string::print_body(out);
|
||
|
||
TToken_string& cod = (TToken_string&)_codes; // Trick to skip const
|
||
TToken_string& val = (TToken_string&)_values;
|
||
|
||
int i = 0;
|
||
TString c(cod.get(0));
|
||
TString v(val.get(0));
|
||
|
||
for (; c[0]; c = cod.get(), v = val.get(), i++)
|
||
{
|
||
out << " ITEM \"" << c;
|
||
if (v.not_empty()) out << '|' << v;
|
||
out << '"';
|
||
|
||
const char* m = ((TForm_list*)this)->message(i);
|
||
if (*m) out << " MESSAGE " << m;
|
||
|
||
out << endl;
|
||
}
|
||
}
|
||
|
||
|
||
bool TForm_list::update()
|
||
{
|
||
bool ok = TRUE;
|
||
|
||
if (!read()) return ok;
|
||
|
||
const TString& val =get();
|
||
int pos = _codes.get_pos(val);
|
||
if (pos < 0)
|
||
{
|
||
TString def= _codes.get(0);
|
||
def.trim();
|
||
if (val == def) pos = 0; // Test default (first & empty) value
|
||
else
|
||
{
|
||
ok = yesno_box("Il campo '%s' non puo' valere '%s': continuare ugualmente",
|
||
(const char*)key(), (const char*)val);
|
||
set(_codes.get(pos = 0));
|
||
}
|
||
}
|
||
if (ok)
|
||
{
|
||
do_message(pos);
|
||
|
||
if (!hidden())
|
||
{
|
||
const char* c = _values.get(pos);
|
||
if (c == NULL) c = val;
|
||
if (c) string_at(x(), _y, c);
|
||
}
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm_group
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TForm_group : public TForm_item
|
||
{
|
||
protected:
|
||
virtual const char* class_name() const { return "GRUPPO"; }
|
||
virtual bool update() { return TRUE; }
|
||
|
||
public:
|
||
TForm_group(TPrint_section* section) : TForm_item(section) {};
|
||
virtual ~TForm_group() {}
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TGraphic_section
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TGraphic_section : public TPrint_section
|
||
{
|
||
TString _back;
|
||
|
||
protected:
|
||
// @cmember Crea un campo della classe specificata
|
||
virtual TForm_item* create_item(const TString& s);
|
||
|
||
virtual bool update();
|
||
|
||
public:
|
||
void append(const char* s) { _back << s; }
|
||
|
||
TGraphic_section(TForm* f, pagetype pt) : TPrint_section(f, 'G', pt) {}
|
||
virtual ~TGraphic_section() {}
|
||
};
|
||
|
||
class TForm_picture : public TForm_item
|
||
{
|
||
TFieldref _field;
|
||
|
||
protected:
|
||
virtual const char* class_name() const { return "FIGURA"; }
|
||
virtual bool parse_item(TScanner& scanner);
|
||
virtual bool update();
|
||
|
||
public:
|
||
TForm_picture(TPrint_section* section) : TForm_item(section) {}
|
||
virtual ~TForm_picture() {}
|
||
};
|
||
|
||
class TForm_line : public TForm_item
|
||
{
|
||
protected:
|
||
virtual const char* class_name() const { return "LINEA"; }
|
||
virtual bool update();
|
||
|
||
public:
|
||
TForm_line(TGraphic_section* section) : TForm_item(section) {}
|
||
virtual ~TForm_line() {}
|
||
};
|
||
|
||
class TForm_box : public TForm_item
|
||
{
|
||
protected:
|
||
virtual const char* class_name() const { return "BOX"; }
|
||
virtual bool update();
|
||
|
||
public:
|
||
TForm_box(TGraphic_section* section) : TForm_item(section) {}
|
||
virtual ~TForm_box() {}
|
||
};
|
||
|
||
bool TForm_picture::parse_item(TScanner& scanner)
|
||
{
|
||
if (scanner.key() == "FI") // FIELD reference
|
||
{
|
||
_field = scanner.line();
|
||
return TRUE;
|
||
}
|
||
return TForm_item::parse_item(scanner);
|
||
}
|
||
|
||
bool TForm_picture::update()
|
||
{
|
||
TFilename i;
|
||
if (_field.ok())
|
||
{
|
||
const TRelation* r = form().relation();
|
||
if (r)
|
||
{
|
||
TToken_string list(_field.read(*r), '\n');
|
||
FOR_EACH_TOKEN(list, tok)
|
||
{
|
||
i = tok;
|
||
const int pos = i.find('|');
|
||
if (pos >= 0)
|
||
i.cut(pos);
|
||
if (stricmp(i.ext(), "bmp") == 0)
|
||
{
|
||
i.replace('\\', '/');
|
||
i.trim();
|
||
break;
|
||
}
|
||
else
|
||
i.cut(0);
|
||
}
|
||
}
|
||
else
|
||
NFCHECK("Can't read picture from NULL relation");
|
||
}
|
||
else
|
||
i = _prompt;
|
||
i.custom_path();
|
||
bool ok = i.not_empty() && i.exist();
|
||
if (ok)
|
||
{
|
||
i << ',' << _x << ',' << _y << ',' << (_x+width()-1) << ',' << (_y+height()-1);
|
||
|
||
if (section().section_type() == 'G')
|
||
{
|
||
i.insert("i{", 0); i << '}';
|
||
((TGraphic_section&)section()).append(i);
|
||
}
|
||
else
|
||
{
|
||
i.insert("@F[", 0); i << ']';
|
||
TPrintrow& row = section().row(_y-1);
|
||
row.put(i);
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TForm_line::update()
|
||
{
|
||
int spessore = 1;
|
||
char codice = 'l';
|
||
for (int j = _prompt.len()-1; j >= 0; j--)
|
||
{
|
||
switch (_prompt[j])
|
||
{
|
||
case 'B':
|
||
case 'b':
|
||
spessore = 3; break;
|
||
case 'R':
|
||
case 'r':
|
||
codice = 'r'; break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Calcola la vera coordinata y della linea
|
||
const int y = _y >= 0 ? _y : (printer().formlen()+_y+1);
|
||
|
||
TString80 i;
|
||
i << 'W' << spessore << codice
|
||
<< '{' << _x << ',' << y << ','
|
||
<< (_x+width()-1) << ',' << (y+height()-1) << '}';
|
||
|
||
((TGraphic_section&)section()).append(i);
|
||
return TRUE;
|
||
}
|
||
|
||
bool TForm_box::update()
|
||
{
|
||
TString80 i;
|
||
const int w = _prompt[0] == '@' ? 3 : 1;
|
||
i << 'W' << w << "b{" << _x << ',' << _y << ','
|
||
<< (_x+width()-1) << ',' << (_y+height()-1) << '}';
|
||
|
||
((TGraphic_section&)section()).append(i);
|
||
return TRUE;
|
||
}
|
||
|
||
TForm_item* TGraphic_section::create_item(const TString& typ)
|
||
{
|
||
TForm_item* fff = NULL;
|
||
if (typ.compare("LINEA", 2, TRUE) == 0)
|
||
fff = new TForm_line(this); else
|
||
if (typ.compare("BOX", 2, TRUE) == 0)
|
||
fff = new TForm_box(this); else
|
||
if (typ.compare("FIGURA", 2, TRUE) == 0)
|
||
fff = new TForm_picture(this);
|
||
return fff;
|
||
}
|
||
|
||
bool TGraphic_section::update()
|
||
{
|
||
_back.cut(0);
|
||
const bool ok = TPrint_section::update();
|
||
|
||
int index;
|
||
switch(page_type())
|
||
{
|
||
case even_page : index = 1; break;
|
||
case first_page: index = 2; break;
|
||
case last_page : index = 3; break;
|
||
default : index = 0; break;
|
||
}
|
||
printer().setbackground(_back, index);
|
||
return ok;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TPrint_section
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TMask* TPrint_section::_msk = NULL;
|
||
|
||
|
||
word TPrint_section::height() const
|
||
{
|
||
word h = _height;
|
||
if (subsection_above() && (word)subsection_above()->effective_height() > h)
|
||
{
|
||
h = subsection_above()->effective_height();
|
||
}
|
||
if (short(h) < 0) // Can't write h < 0!
|
||
{
|
||
if (section_type() == 'F')
|
||
{
|
||
h += printer().formlen();
|
||
if (short(h) < 0) // Still < 0 ?? get out...
|
||
h = 0;
|
||
}
|
||
else
|
||
{
|
||
h = _rows.items();
|
||
if (h == 0)
|
||
h = 0xFFFF - _height + 1; // Same as abs(_height)
|
||
}
|
||
}
|
||
return h;
|
||
}
|
||
|
||
|
||
TExpression & TPrint_section::eval_expr(TExpression & expr,int defaultfile_id)
|
||
{
|
||
for (int j = 0; j < expr.numvar(); j++)
|
||
{ // scansione delle variabili dell'espressione di rvalue
|
||
TString var= expr.varname(j);
|
||
if (var[0]=='#')
|
||
{ // riferimento ad un campo del form
|
||
var.ltrim(1);
|
||
TForm_item &fi= find_field(atoi(var));
|
||
expr.setvar(j, fi.get()); // il valore corrente del campo viene settato nell'espressione
|
||
}
|
||
else
|
||
{ // riferimento ad un campo di file
|
||
TFieldref fr = TFieldref(var, 0);
|
||
int fileno=fr.file();
|
||
// choose logical file number
|
||
fileno= (fileno==0) ? (defaultfile_id>0 ? defaultfile_id : 0): fileno;
|
||
expr.setvar(j, fr.read( form().relation()->lfile(fileno).curr() ) ); // il valore corrente del campo viene settato nell'espressione
|
||
}
|
||
}
|
||
return expr;
|
||
}
|
||
|
||
TPrint_section::TPrint_section(TForm* f, char st, pagetype pt, TForm_subsection* father)
|
||
: _height(0), _form(f), _sec_type(st), _page_type(pt), _dirty(FALSE),
|
||
_upsection(father), _repeat_count(0), _ofspc(0), _ofsvr(0), _nfld(0), _temp(0),
|
||
_columnwise(FALSE)
|
||
{
|
||
reset_tabs();
|
||
}
|
||
|
||
TPrint_section::~TPrint_section()
|
||
{
|
||
if (_msk)
|
||
{
|
||
delete _msk;
|
||
_msk = NULL;
|
||
}
|
||
}
|
||
|
||
TForm_item* TPrint_section::create_item(const TString& s)
|
||
{
|
||
TForm_item* f = NULL;
|
||
if (s.compare("STRINGA", 2, TRUE) == 0)
|
||
f = new TForm_string(this); else
|
||
if (s.compare("NUMERO", 2, TRUE) == 0)
|
||
f = new TForm_number(this); else
|
||
if (s.compare("VALUTA", 2, TRUE) == 0)
|
||
f = new TForm_currency(this); else
|
||
if (s.compare("DATA", 2, TRUE) == 0)
|
||
f = new TForm_date(this); else
|
||
if (s.compare("LISTA", 2, TRUE) == 0)
|
||
f = new TForm_list(this); else
|
||
if (s.compare("GRUPPO", 2, TRUE) == 0)
|
||
f = new TForm_group(this); else
|
||
if (s.compare("SECTION", 2, TRUE) == 0)
|
||
f = new TForm_subsection(this); else
|
||
if (s.compare("FIGURA", 2, TRUE) == 0)
|
||
f = new TForm_picture(this);
|
||
|
||
return f;
|
||
}
|
||
|
||
void TPrint_section::change_field(int n, TForm_item* f)
|
||
{
|
||
_item.add(f,n);
|
||
}
|
||
|
||
void TPrint_section::insert_field(int n, TForm_item* f)
|
||
{
|
||
_item.insert(f,n);
|
||
}
|
||
|
||
void TPrint_section::add_field(TForm_item* f)
|
||
{
|
||
_item.add(f);
|
||
}
|
||
|
||
inline int TPrint_section::subsections()const
|
||
{
|
||
return _subsections.items();
|
||
}
|
||
|
||
inline TForm_subsection* TPrint_section::subsection(int n) const
|
||
{
|
||
return (TForm_subsection* )_subsections.objptr(n);
|
||
}
|
||
|
||
inline void TPrint_section::add_subsection(TForm_subsection* s)
|
||
{
|
||
_subsections.add(s);
|
||
}
|
||
|
||
const TPrint_section& TPrint_section::copy(const TPrint_section& ps)
|
||
{
|
||
_msk = ps._msk; _height = ps._height; _ofspc = ps._ofspc;
|
||
_ofsvr = ps._ofsvr; _nfld = ps._nfld; _dirty = ps._dirty;
|
||
_temp = ps._temp; _form = ps._form;
|
||
_sec_type = ps._sec_type; _page_type = ps._page_type;
|
||
_item = ps._item;
|
||
// subsections
|
||
_upsection = ps._upsection; _repeat_count = ps._repeat_count; _subsections=ps._subsections;
|
||
// columnwise
|
||
_columnwise = ps._columnwise;
|
||
for (int i = 0; i < MAXCOLUMNS; i++) _tab[i] = ps._tab[i];
|
||
return ps;
|
||
}
|
||
|
||
TPrintrow& TPrint_section::row(int num)
|
||
{
|
||
TPrintrow* pr = (TPrintrow*)_rows.objptr(num);
|
||
if (pr == NULL)
|
||
{
|
||
pr = new TPrintrow;
|
||
_rows.add(pr, num);
|
||
}
|
||
return *pr;
|
||
}
|
||
|
||
TPrintrow& TPrint_section::titlerow(int num)
|
||
{
|
||
TPrintrow* pr = (TPrintrow*)_titlerows.objptr(num);
|
||
if (pr == NULL)
|
||
{
|
||
pr = new TPrintrow;
|
||
_titlerows.add(pr, num);
|
||
}
|
||
return *pr;
|
||
}
|
||
|
||
void TPrint_section::reset_tabs()
|
||
{
|
||
for (int i = 0; i < MAXCOLUMNS; i++)
|
||
_tab[i] = -1;
|
||
}
|
||
|
||
int TPrint_section::tab(int col)
|
||
{
|
||
int ret = -1;
|
||
if (_columnwise)
|
||
{
|
||
if (_tab[0] == -1 && fields())
|
||
{
|
||
_tab[0] = 2;
|
||
{
|
||
int extraoff=0;
|
||
// compute column offset
|
||
_nfld = 0;
|
||
short maxcolreached = 0,mincolreached = MAXCOLUMNS+1;
|
||
for (word i = 0; i < fields(); i++)
|
||
{
|
||
if (!field(i).is_section() && field(i).shown())
|
||
{
|
||
const int curr_col=field(i)._x;
|
||
CHECKD (curr_col >=0 && curr_col < MAXCOLUMNS, "Colonna ammessa e non concessa: ", field(i)._x);
|
||
_tab[curr_col] = field(i)._width + 1; // one is for separation
|
||
if (curr_col < mincolreached) mincolreached = curr_col;
|
||
if (curr_col > maxcolreached) maxcolreached = curr_col;
|
||
_nfld++;
|
||
}
|
||
}
|
||
// cumulate offsets
|
||
|
||
if (_upsection)
|
||
{
|
||
if (mincolreached<=MAXCOLUMNS && mincolreached>0)
|
||
{
|
||
// print section of a subsection: extra offset
|
||
extraoff=_upsection->section().tab(mincolreached-1);
|
||
for (i = 1 ; i < (word)mincolreached; i++)
|
||
{
|
||
_tab[i]=_upsection->section()._tab[i];
|
||
}
|
||
if (extraoff== _tab[mincolreached-1])
|
||
extraoff=0;
|
||
else
|
||
extraoff-=_upsection->section().tab(0);
|
||
}
|
||
}
|
||
|
||
int last = 0;
|
||
for (i = mincolreached ; i <= (word)maxcolreached; i++)
|
||
{
|
||
if (_tab[i - 1] != -1)
|
||
last = i - 1;
|
||
if (_tab[i] != -1)
|
||
_tab[i] += _tab[last]+extraoff;
|
||
}
|
||
}
|
||
}
|
||
// se manca la colonna, vai a prendere quella immediatamente prima
|
||
while (_tab[col] == -1 && col > 0)
|
||
col--;
|
||
ret = _tab[col];
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
word TPrint_section::subs_height() const
|
||
{
|
||
TForm_subsection *fss;
|
||
word h=0;
|
||
if (subsections())
|
||
{
|
||
fss=subsection(0);
|
||
h=subsection(0)->minheight();
|
||
h+=subsection(0)->printsection().subs_height(); // ricorsione...
|
||
}
|
||
return h;
|
||
}
|
||
|
||
|
||
void TPrint_section::offset(int& x, int& y)
|
||
{
|
||
if (x >= 0)
|
||
{
|
||
if (_columnwise) x = tab(x-1) + _ofspc;
|
||
x += form().offset_x();
|
||
}
|
||
if (y >= 0)
|
||
y += form().offset_y() + (_height * _repeat_count);
|
||
}
|
||
|
||
|
||
TForm_item* TPrint_section::parse_item(const TString& s)
|
||
{
|
||
TForm_item* f = create_item(s);
|
||
#ifdef DBG
|
||
if (f == NULL)
|
||
yesnofatal_box("Tipo di campo del form non riconosciuto: '%s'", (const char*)s);
|
||
#endif
|
||
return f;
|
||
}
|
||
|
||
|
||
TForm_item* TPrint_section::parse_item(TScanner& scanner)
|
||
{
|
||
return parse_item(scanner.key());
|
||
}
|
||
|
||
bool TPrint_section::parse_head(TScanner& scanner)
|
||
{
|
||
_height = scanner.integer();
|
||
scanner.integer();scanner.integer(); // Eat offset X and Y of Print_section if present
|
||
|
||
if (scanner.popkey() == "CO") // COLUMNWISE attribute
|
||
_columnwise = TRUE;
|
||
else if (scanner.key() == "NO") // NORMAL (no COLUMNWISE) attribute
|
||
_columnwise = FALSE;
|
||
else
|
||
{
|
||
if (section_above())
|
||
_columnwise = section_above()->_columnwise;
|
||
else
|
||
_columnwise = FALSE;
|
||
scanner.push();
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
bool TPrint_section::parse_body(TScanner& scanner)
|
||
{
|
||
while (scanner.popkey() != "EN")
|
||
{
|
||
TForm_item *fi = parse_item(scanner);
|
||
if (fi == NULL) return FALSE;
|
||
|
||
if (fi->parse(scanner))
|
||
{
|
||
_item.add(fi);
|
||
} else
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
bool TPrint_section::parse(TScanner& scanner)
|
||
{
|
||
if (parse_head(scanner))
|
||
return parse_body(scanner);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
// Azzera tutte le righe della sezione di stampa
|
||
void TPrint_section::reset()
|
||
{
|
||
for (int i = _rows.last(); i >= 0; i--)
|
||
{
|
||
if (_height > 0xF000)
|
||
_rows.destroy(i);
|
||
else
|
||
row(i).reset();
|
||
}
|
||
}
|
||
|
||
// Aggiorna tutti i campi
|
||
bool TPrint_section::update()
|
||
{
|
||
bool ok = TRUE;
|
||
|
||
reset();
|
||
for (word i = 0; i < fields(); i++)
|
||
{
|
||
if (!field(i).is_section())
|
||
{
|
||
const bool esito = field(i).update();
|
||
if (!esito) ok = FALSE;
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
|
||
TForm_item* TPrint_section::exist_field(short id) const
|
||
{
|
||
TForm_item* f = find_field_everywhere(id,this);
|
||
return f;
|
||
}
|
||
|
||
TForm_item& TPrint_section::find_field(short id) const
|
||
{
|
||
TForm_item* f = exist_field(id);
|
||
if (f) return *f;
|
||
yesnofatal_box("Can't find item with id %d", id);
|
||
return field(0);
|
||
}
|
||
|
||
// Ricerca i campi verso l'alto:
|
||
// prima la sezione attuale, poi le sezioni sopra
|
||
TForm_item *TPrint_section::find_field_everywhere(short id,const TPrint_section *starting_section) const
|
||
{
|
||
TForm_item * f ;
|
||
for(word i = 0; i < fields(); i++)
|
||
{
|
||
f = &field(i);
|
||
if (f->id() == id) return f;
|
||
}
|
||
// look into the section above ("father" )
|
||
if (section_above() && section_above()!=starting_section) {
|
||
f=section_above()->find_field_everywhere(id,this);
|
||
if (f)
|
||
return f;
|
||
}
|
||
// look into sections beside ("brothers" )
|
||
for (int j = 0; j < subsections(); j++)
|
||
{
|
||
const TPrint_section &bs=subsection(j)->printsection();
|
||
if (&bs!=starting_section) {
|
||
f=bs.find_field_everywhere(id,this);
|
||
if (f)
|
||
return f;
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
TForm_item* TPrint_section::exist_field(const char *sec_name) const
|
||
{
|
||
TForm_item* f = find_field_everywhere(sec_name,this);
|
||
return f;
|
||
}
|
||
|
||
TForm_item& TPrint_section::find_field(const char *sec_name) const
|
||
{
|
||
TForm_item* f = exist_field(sec_name);
|
||
if (f) return *f;
|
||
yesnofatal_box("Can't find subsection '%s'", sec_name);
|
||
return field(0);
|
||
}
|
||
|
||
// Ricerca i campi verso il basso:
|
||
// prima la sezione attuale, poi le sottosezioni
|
||
TForm_item *TPrint_section::find_field_everywhere(const char *sec_name,const TPrint_section *starting_section) const
|
||
{
|
||
// search here
|
||
for (int j = 0; j < subsections(); j++) {
|
||
const char *n=subsection(j)->name();
|
||
if (strcmp(n,sec_name)==0)
|
||
return subsection(j);
|
||
}
|
||
// search down
|
||
for (j = 0; j < subsections(); j++) {
|
||
TForm_item *it=subsection(j)->printsection().find_field_everywhere(sec_name,starting_section);
|
||
if (it)
|
||
return it;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm
|
||
///////////////////////////////////////////////////////////
|
||
|
||
// classe per le informazioni sugli skip dei file del cursore del form
|
||
class TForm_skip_info : public TObject
|
||
{
|
||
protected:
|
||
virtual TObject * dup() const;
|
||
public :
|
||
bool _match_result;
|
||
int _match_number;
|
||
~TForm_skip_info(){};
|
||
TForm_skip_info();
|
||
};
|
||
|
||
TObject * TForm_skip_info ::dup() const
|
||
{
|
||
TForm_skip_info *p=new TForm_skip_info;
|
||
p->_match_result=_match_result;
|
||
p->_match_number=_match_number;
|
||
return p;
|
||
}
|
||
|
||
TForm_skip_info::TForm_skip_info()
|
||
{
|
||
_match_result=FALSE;
|
||
_match_number=0;
|
||
}
|
||
|
||
TForm_editor& TForm::editor() const
|
||
{ return (TForm_editor&)main_app(); }
|
||
|
||
//
|
||
bool TForm::parse_use(TScanner& scanner)
|
||
{
|
||
const int logicnum = scanner.integer();
|
||
const char* tab = NULL;
|
||
|
||
if (logicnum > 0)
|
||
_relation = new TRelation(logicnum);
|
||
else
|
||
{
|
||
tab = scanner.pop();
|
||
_relation = new TRelation(tab);
|
||
}
|
||
|
||
int key = 1; // key number
|
||
if (scanner.popkey() == "KE")
|
||
key = scanner.integer();
|
||
else
|
||
scanner.push();
|
||
|
||
if (scanner.popkey() == "BY" || scanner.key() == "FI") // file sorted or filtered
|
||
{
|
||
if (scanner.key() == "BY" ) { // "sort BY": user-defined sort
|
||
TToken_string ordexpr(parse_sortexpr(scanner));
|
||
_cursor = new TSorted_cursor(_relation, ordexpr,"", key);
|
||
} else {
|
||
TToken_string filter(parse_filter(scanner));
|
||
_cursor = new TCursor(_relation,filter, key);
|
||
}
|
||
} else {
|
||
scanner.push();
|
||
_cursor = new TCursor(_relation,"", key);
|
||
}
|
||
|
||
if (scanner.popkey() == "FI") // "FIlter" : sorted defined by the user
|
||
{
|
||
TToken_string filter(parse_filter(scanner));
|
||
_cursor->setfilter(filter);
|
||
} else {
|
||
scanner.push();
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
bool TForm::parse_join(TScanner& scanner)
|
||
{
|
||
TString16 j(scanner.pop()); // File or table
|
||
|
||
int to = 0;
|
||
if (scanner.popkey() == "TO") // TO keyword
|
||
{
|
||
const char* n = scanner.pop();
|
||
to = name2log(n);
|
||
}
|
||
else scanner.push();
|
||
return parse_join_param(scanner,_relation,j,to);
|
||
}
|
||
|
||
bool TForm::parse_join_param(TScanner& scanner,TRelation * rel, TString16 j, int to )
|
||
{
|
||
int key = 1;
|
||
if (scanner.popkey() == "KE")
|
||
key = scanner.integer();
|
||
else scanner.push();
|
||
|
||
int alias = 0;
|
||
if (scanner.popkey() == "AL")
|
||
alias = scanner.integer();
|
||
else scanner.push();
|
||
|
||
TToken_string exp(80);
|
||
if (scanner.pop() == "INTO")
|
||
{
|
||
exp=parse_filter(scanner);
|
||
}
|
||
if (exp.empty())
|
||
yesnofatal_box("JOIN senza espressioni INTO");
|
||
|
||
if (isdigit(j[0]))
|
||
rel->add(atoi(j), exp, key, to, alias); // join file
|
||
else
|
||
rel->add(j, exp, key, to, alias); // join table
|
||
return TRUE;
|
||
}
|
||
|
||
bool TForm::parse_sortedjoin(TScanner& scanner)
|
||
{
|
||
TToken_string filter,sortexp;
|
||
TString16 j(scanner.pop()); // File or table
|
||
if (scanner.popkey() == "BY" )
|
||
{
|
||
sortexp=parse_sortexpr(scanner);
|
||
} else scanner.push();
|
||
if (scanner.popkey() == "FI" ) {
|
||
filter=parse_filter(scanner);
|
||
} else scanner.push();
|
||
if (filter.empty() && sortexp.empty())
|
||
yesnofatal_box("Sort senza espressioni di ordinamento o filtri");
|
||
TRelation * sortrel=new TRelation(atoi(j));
|
||
while (ok() && scanner.popkey() != "JO" )
|
||
{
|
||
if (scanner.key() == "US") // USING keyword
|
||
{
|
||
TString16 subj(scanner.pop()); // File or table
|
||
parse_join_param(scanner,sortrel,subj,atoi(j));
|
||
} else
|
||
yesnofatal_box("Token non riconosciuto in SORT:%s",scanner.key());
|
||
}
|
||
|
||
int to = 0;
|
||
if (scanner.popkey() == "TO") // TO keyword
|
||
{
|
||
const char* n = scanner.pop();
|
||
to = name2log(n);
|
||
}
|
||
else scanner.push();
|
||
|
||
int key = 1;
|
||
if (scanner.popkey() == "KE")
|
||
key = scanner.integer();
|
||
else scanner.push();
|
||
|
||
int alias = 0;
|
||
if (scanner.popkey() == "AL")
|
||
alias = scanner.integer();
|
||
else scanner.push();
|
||
|
||
TToken_string exp(80);
|
||
if (scanner.pop() == "INTO")
|
||
{
|
||
const char* r = scanner.pop();
|
||
while (strchr(r, '=') != NULL)
|
||
{
|
||
exp.add(r);
|
||
r = scanner.pop();
|
||
}
|
||
}
|
||
if (exp.empty())
|
||
yesnofatal_box("JOIN senza espressioni INTO");
|
||
scanner.push();
|
||
|
||
TSortedfile *sf= new TSortedfile(atoi(j),sortrel,sortexp,filter,key);
|
||
|
||
_relation->add((TLocalisamfile *)sf, exp, key, to, alias,FALSE); // join table
|
||
return TRUE;
|
||
}
|
||
|
||
TToken_string TForm::parse_filter(TScanner& scanner)
|
||
{
|
||
TToken_string filter;
|
||
const char* r = scanner.pop();
|
||
while (strchr(r, '=') != NULL)
|
||
{
|
||
filter.add(r);
|
||
r = scanner.pop();
|
||
}
|
||
scanner.push();
|
||
return filter;
|
||
}
|
||
|
||
TToken_string TForm::parse_sortexpr(TScanner& scanner)
|
||
{
|
||
TToken_string sortexp;
|
||
TToken_string se(scanner.line(),' ');
|
||
const char * c;
|
||
while (c=se.get())
|
||
if (*c!='\0')
|
||
sortexp.add(c);
|
||
return sortexp;
|
||
}
|
||
|
||
TRelation_description& TForm::rel_desc() const
|
||
{
|
||
CHECK(_rel_desc, "No relation description");
|
||
return *_rel_desc;
|
||
}
|
||
|
||
bool TForm::parse_description(TScanner& scanner)
|
||
{
|
||
if (edit_level() > 0)
|
||
{
|
||
CHECK(_rel_desc == NULL, "Can't parse descriptions two times");
|
||
_rel_desc = new TRelation_description(*_relation);
|
||
}
|
||
|
||
bool ok = scanner.popkey() == "DE";
|
||
if (ok)
|
||
{
|
||
if (edit_level() > 0)
|
||
{
|
||
scanner.popkey(); // eat BEGIN
|
||
TFieldref fld;
|
||
while (scanner.pop() != "END")
|
||
{
|
||
fld = scanner.token();
|
||
_rel_desc->set_cur_file(fld.file());
|
||
if (fld.name() == "*")
|
||
_rel_desc->file_desc(scanner.string());
|
||
else
|
||
_rel_desc->set_field_description(fld.name(), scanner.string());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while (scanner.line() != "END");
|
||
ok = FALSE;
|
||
}
|
||
}
|
||
else scanner.push();
|
||
|
||
return ok;
|
||
}
|
||
|
||
void TForm::print_description(ostream& out) const
|
||
{
|
||
out << "DESCRIPTION\nBEGIN\n";
|
||
out << rel_desc();
|
||
out << "END\n" << endl;
|
||
}
|
||
|
||
bool TForm::parse_general(TScanner &scanner)
|
||
{
|
||
bool ok = scanner.popkey() == "GE";
|
||
if (ok)
|
||
{
|
||
while (scanner.pop() != "END")
|
||
{
|
||
if (scanner.key() == "OF") // Offsets
|
||
{
|
||
_x = scanner.integer();
|
||
_y = scanner.integer();
|
||
}
|
||
if (scanner.key() == "FO") // Font name
|
||
_fontname = scanner.string();
|
||
if (scanner.key() == "SI") // Font size
|
||
_fontsize = scanner.integer();
|
||
if (scanner.key() == "CA") // Carattere di posizionamento
|
||
_char_to_pos = scanner.string()[0];
|
||
if (scanner.key() == "IN") // Riga e colonna del posizionamento iniziale
|
||
{
|
||
_ipx = scanner.integer();
|
||
_ipy = scanner.integer();
|
||
}
|
||
if (scanner.key() == "FI") // Riga e colonna del posizionamento finale
|
||
_fpx = scanner.integer();
|
||
|
||
if (scanner.key() == "GR") // Carattere di fincatura
|
||
set_fincatura(scanner.string());
|
||
|
||
if (scanner.key() == "PA") // Numero di pagine fisso
|
||
_npages=scanner.integer();
|
||
|
||
if (scanner.key() == "VA") // Valuta/Divisa impiegata
|
||
{
|
||
_curr_codval=scanner.string(); // DA ELIMINARE
|
||
}
|
||
|
||
extended_parse_general(scanner); // Parse non-standard parameters
|
||
}
|
||
} else scanner.push();
|
||
|
||
return (ok);
|
||
}
|
||
|
||
void TForm::print_general(ostream& out) const
|
||
{
|
||
out << "GENERAL\nBEGIN\n";
|
||
out << " OFFSET " << _x << " " << _y << "\n";
|
||
out << " FONT " << "\"" << _fontname << "\"\n";
|
||
out << " SIZE " << _fontsize << "\n" ;
|
||
if (_char_to_pos != '\0')
|
||
{
|
||
out << " CARATTERE \"" << _char_to_pos << "\"\n" ;
|
||
out << " INIZIO_POS " << _ipx << " " << _ipy << "\n";
|
||
out << " FINE_POS " << _fpx << "\n";
|
||
}
|
||
out << " GRID \"" << _fink << "\"\n";
|
||
out << "END\n" << endl;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Controlla se esiste una sezione di stampa
|
||
//
|
||
// @rdesc Ritorna la <c TPrint_section> trovata o creata
|
||
TPrint_section* TForm::exist(
|
||
char s, // @parm Indica in quale parte deve cercare:
|
||
//
|
||
// @flag F | Tra i footers
|
||
// @flag G | Tra gli sfondi
|
||
// @flag H | Tra gli headers
|
||
// @flag B | Tra i bodies (default)
|
||
pagetype t, // @parm Tipo di pagina (vedi <t pagetype>)
|
||
bool create) // @parm Indica se creare la sezione nel caso non esista
|
||
{
|
||
TArray* a;
|
||
switch (toupper(s))
|
||
{
|
||
case 'F':
|
||
a = &_foot; break;
|
||
case 'G':
|
||
a = &_back; break;
|
||
case 'H':
|
||
a = &_head; break;
|
||
default:
|
||
a = &_body; break;
|
||
}
|
||
|
||
TPrint_section* sec = (TPrint_section*)a->objptr(t);
|
||
if (sec == NULL && create)
|
||
{
|
||
sec = (s == 'G') ? new TGraphic_section(this, t) : new TPrint_section(this, s, t);
|
||
a->add(sec, t);
|
||
}
|
||
|
||
return sec;
|
||
}
|
||
|
||
TForm_item* TForm::exist_field(char s, pagetype t, short id) const
|
||
{
|
||
const TPrint_section* ps = ((TForm*)this)->exist(s, t);
|
||
CHECKD(ps, "Can't find section for field ", id);
|
||
return ps->exist_field(id);
|
||
}
|
||
|
||
TForm_subsection* TForm::exist_field(char s, pagetype t, const char *section) const
|
||
{
|
||
const TPrint_section* ps = ((TForm*)this)->exist(s, t);
|
||
CHECKS(ps, "Can't find section for field ", section);
|
||
return (TForm_subsection*)ps->exist_field(section);
|
||
}
|
||
|
||
|
||
TForm_item& TForm::find_field(char s, pagetype t, short id) const
|
||
{
|
||
const TPrint_section* ps = ((TForm*)this)->exist(s, t);
|
||
CHECKD(ps, "Can't find section for field ", id);
|
||
return ps->find_field(id);
|
||
}
|
||
|
||
TForm_subsection& TForm::find_field(char s, pagetype t, const char *section) const
|
||
{
|
||
const TPrint_section* ps = ((TForm*)this)->exist(s, t);
|
||
CHECKS(ps, "Can't find section for field ", section);
|
||
return (TForm_subsection&)ps->find_field(section);
|
||
}
|
||
|
||
TPrint_section& TForm::section(char s, pagetype pos)
|
||
{
|
||
TPrint_section* sec = exist(s, pos, TRUE);
|
||
return *sec;
|
||
}
|
||
|
||
TPrint_section& TForm::section(char s, word pagenum)
|
||
{
|
||
pagetype pt = odd_page;
|
||
if (pagenum == 0 && exist(s, last_page))
|
||
pt = last_page;
|
||
if (pagenum == 1 && exist(s, first_page))
|
||
pt = first_page;
|
||
if (pt == odd_page && (pagenum & 0x1) == 0 && exist(s, even_page))
|
||
pt = even_page;
|
||
|
||
return section(s, pt);
|
||
}
|
||
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Rilegge la sezione specificata
|
||
//
|
||
// @rdesc Ritorna se ce l'ha fatta
|
||
bool TForm::reread(
|
||
char sec, // @parm Sezione da rileggere
|
||
pagetype p, // @parm Posizione della pagina
|
||
bool force) // @parm Forza rilettura anche se nessun campo e' cambiato
|
||
{
|
||
TPrint_section* s = exist(sec,p);
|
||
bool ok = force;
|
||
if (s != NULL)
|
||
for (word j = 0; j < s->fields(); j++)
|
||
ok |= s->field(j).dirty();
|
||
if (s != NULL && ok)
|
||
{
|
||
s->destroy_fields(); // Distrugge tutti gli items...
|
||
// ...si posiziona nel file sorgente alla sezione opportuna...
|
||
TFilename n(_name); n.ext("frm");
|
||
TScanner scanner(n);
|
||
bool ok = FALSE;
|
||
while (!ok)
|
||
{
|
||
while (TRUE) // ...scans searching for a section...
|
||
{
|
||
const TString& key = scanner.popkey();
|
||
if (key == "SE" || key == "") // ..if section or end of file...
|
||
break;
|
||
}
|
||
const char secr = scanner.popkey()[0]; // Section name (GRAPH, HEAD, BODY, FOOT)
|
||
if (secr=='\0') break;
|
||
const pagetype pr = char2page(scanner.popkey()[0]); // Section type (odd, even, first, last)
|
||
if (secr==sec && pr==p) ok = TRUE; // L'ha trovata...
|
||
}
|
||
// ...riesegue la parse della sezione leggendo dal file sorgente
|
||
if(ok && s->parse(scanner))
|
||
{
|
||
// Legge le modifiche su archivio e poi e' finita.
|
||
s->set_dirty(FALSE);
|
||
TLocalisamfile rprof(LF_RFORM);
|
||
const char sez[3] = {sec,p+'0','\0'};
|
||
rprof.zero();
|
||
rprof.put("TIPOPROF", _name);
|
||
rprof.put("CODPROF", _code);
|
||
rprof.put("SEZ", sez);
|
||
const TRectype filter(rprof.curr());
|
||
|
||
for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next())
|
||
{
|
||
const short id = rprof.get_int("ID");
|
||
|
||
if (id == 0)
|
||
{
|
||
TPrint_section& se = section(sec, p);
|
||
se.read_from(rprof.curr());
|
||
}
|
||
else
|
||
{
|
||
TForm_item& item = find_field(sec, p, id);
|
||
item.read_from(rprof.curr());
|
||
}
|
||
}
|
||
set_compulsory_specials();
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TForm
|
||
///////////////////////////////////////////////////////////
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Cambia il formato di tutte le date nel form
|
||
//
|
||
// @rdesc Ritorna sempre TRUE
|
||
bool TForm::ps_change_date_format(
|
||
TPrint_section& s, // @parm Sezione nella quale modificare le date
|
||
const char* f) // @parm Nuovo formato delle date
|
||
|
||
// @comm Ha le stesse funzioni di <mf TForm::change_date_format>, ma per <c TPrint_section>,
|
||
// all'uopo di chiamarla con ricorsiva insistenza
|
||
|
||
{
|
||
for (word i = 0; i < s.fields(); i++)
|
||
{
|
||
TForm_item& fi = s.field(i);
|
||
if (fi.is_section())
|
||
{
|
||
TPrint_section& ps = ((TForm_subsection&)fi).printsection();
|
||
ps_change_date_format(ps, f);
|
||
}
|
||
else if (strcmp(fi.class_name(), "DATA") == 0)
|
||
{
|
||
((TForm_date&)fi).set_format(f);
|
||
if (!s.dirty()) s.set_dirty();
|
||
if (!fi.dirty()) fi.set_dirty();
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Cambia il formato di tutti i numeri nel form
|
||
//
|
||
// @rdesc Ritorna sempre TRUE
|
||
bool TForm::ps_change_number_format(
|
||
TPrint_section& s, // @parm Sezione nella quale modificare i numeri
|
||
int w, // @parm Dimensione massima del fomato numerico
|
||
int dec, // @parm Numero di decimali
|
||
const char* p) // @parm Picture del nuovo formato
|
||
|
||
// @comm Ha le stesse funzioni di <mf TForm::change_number_format>, ma per <c TPrint_section>,
|
||
// all'uopo di chiamarla con ricorsiva insistenza
|
||
{
|
||
for (word i = 0; i < s.fields(); i++)
|
||
{
|
||
TForm_item& fi = s.field(i);
|
||
if (fi.is_section())
|
||
{
|
||
TPrint_section& ps = ((TForm_subsection&)fi).printsection();
|
||
ps_change_number_format(ps, w, dec, p);
|
||
}
|
||
else if (strcmp(fi.class_name(), "NUMERO") == 0)
|
||
{
|
||
TForm_number& fn = (TForm_number&)fi;
|
||
fn.width() = w;
|
||
fn.set_decimals(dec);
|
||
fn.set_picture(p);
|
||
if (!s.dirty()) s.set_dirty();
|
||
if (!fn.dirty()) fn.set_dirty();
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void TForm::change_date_format(const char* f)
|
||
{
|
||
char secs[] = { "FHGB" };
|
||
char ptyp[] = { "LOEF" };
|
||
TPrint_section* ps;
|
||
|
||
for (int sc = 0; sc < 4; sc++)
|
||
for (int pt = 0; pt < 4; pt++)
|
||
if ((ps = exist(secs[sc], char2page(ptyp[pt]), FALSE)) != NULL)
|
||
ps_change_date_format(*ps, f);
|
||
}
|
||
|
||
void TForm::change_number_format(int w, int dec, const char* p)
|
||
{
|
||
char secs[] = { "FHGB" };
|
||
char ptyp[] = { "LOEF" };
|
||
TPrint_section* ps;
|
||
|
||
for (int sc = 0; sc < 4; sc++)
|
||
for (int pt = 0; pt < 4; pt++)
|
||
if ((ps = exist(secs[sc], char2page(ptyp[pt]), FALSE)) != NULL)
|
||
ps_change_number_format(*ps, w, dec, p);
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Effettua l'update della sezione grafica background
|
||
//
|
||
// @rdesc Ritorna la lunghezza della pagina da stampare
|
||
word TForm::set_background(
|
||
word p, // @parm Numero pagina
|
||
bool u) // @parm Indica se aggiornare lo sfondo nella stampante corrente
|
||
|
||
// @xref <mf TForm::set_header> <mf TForm::set_body> <mf TForm::set_footer>
|
||
{
|
||
word len = 0;
|
||
|
||
if (u && _back.items())
|
||
{
|
||
TPrint_section& graph = section('G', p);
|
||
graph.update();
|
||
len = printer().formlen();
|
||
}
|
||
|
||
return len;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Effettua l'update della sezione header
|
||
//
|
||
// @rdesc Ritorna l'altezza dell'header settato
|
||
word TForm::set_header(
|
||
word p, // @parm Numero pagina
|
||
bool u) // @parm Indica se cambiare l'eventuale header o solo ritornare l'altezza
|
||
|
||
// @xref <mf TForm::set_background> <mf TForm::set_body> <mf TForm::set_footer>
|
||
{
|
||
TPrinter& pr = printer();
|
||
pr.resetheader();
|
||
|
||
TPrint_section& head = section('H', p);
|
||
|
||
if (u) head.update();
|
||
else
|
||
{
|
||
head.reset();
|
||
pr.headerlen(head.height());
|
||
}
|
||
|
||
for (word j = 0; j < head.height(); j++)
|
||
pr.setheaderline(j, head.row(j));
|
||
|
||
return head.height();
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Effettua l'update della sezione body e la sua stampa su Printer
|
||
//
|
||
// @rdesc Ritorna l'altezza del body settato
|
||
word TForm::set_body(
|
||
word p, // @parm Numero pagina
|
||
bool u) // @parm Indica se effettuare l'update (TRUE) o fare il reset (FALSE)
|
||
|
||
// @xref <mf TForm::set_background> <mf TForm::set_header> <mf TForm::set_footer>
|
||
|
||
{
|
||
TPrint_section& body = section('B', p);
|
||
|
||
if (u) body.update_and_print(printmode_normal);
|
||
else body.reset();
|
||
|
||
return body.height();
|
||
}
|
||
|
||
TPrint_section * TPrint_section::section_above() const
|
||
{
|
||
if (_upsection)
|
||
return &_upsection->section();
|
||
return NULL;
|
||
}
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Compone e stampa tutte le righe della sezione (valida in caso di BODY)
|
||
// ritorna se c'e' stata una valutazione
|
||
bool TPrint_section::update_and_print(const sec_print_mode show_fields, bool new_page)
|
||
{
|
||
bool ok=FALSE;
|
||
TPrinter& pr = printer();
|
||
word last_printed_row=0;
|
||
|
||
reset();
|
||
|
||
if (show_fields == printmode_normal
|
||
&& pr.current_row() > pr.headersize()+1
|
||
&& new_page)
|
||
{
|
||
pr.formfeed();
|
||
}
|
||
int repeat_count=0; // numero di sottosezioni stampate o numero di stampe della stessa sottosezione
|
||
int last_hpos=0;
|
||
for (word i = 0; i < fields(); i++)
|
||
{
|
||
if (!field(i).is_section())
|
||
{
|
||
// compose rows using "simple" fields
|
||
field(i).update();
|
||
}
|
||
else
|
||
{
|
||
last_hpos=min(word(field(i).y()-1), height());
|
||
// found a subsection
|
||
TForm_subsection & ss=(TForm_subsection & )field(i);
|
||
|
||
last_printed_row=print_rows(show_fields,last_printed_row,last_hpos);
|
||
|
||
// process subsection
|
||
if (ss.enabled())
|
||
ok |= ss.print_body(show_fields) ;
|
||
}
|
||
} // ... loop for each field
|
||
|
||
const word hgt = height();
|
||
|
||
if (print_rows(show_fields,last_printed_row,hgt) > 0 && show_fields==printmode_normal)
|
||
ok = TRUE;
|
||
// print footers
|
||
if (subsection_above()!=NULL && !subsection_above()->is_title() && ok)
|
||
subsection_above()->print_qtitle();
|
||
return ok;
|
||
}
|
||
|
||
word TPrint_section::print_rows(const sec_print_mode show_fields, word from, word to)
|
||
{
|
||
TPrinter& pr = printer();
|
||
if (show_fields!=printmode_noprint && to>from)
|
||
{
|
||
// print preceeding rows:are all those rows which have Y coord <= than subsection's Y
|
||
if (subsection_above()!=NULL && !subsection_above()->is_title())
|
||
{
|
||
// find some to print: print titles.....
|
||
if (show_fields == printmode_normal)
|
||
subsection_above()->print_titles();
|
||
}
|
||
if (pr.current_row() > pr.headersize()+1)
|
||
if ((to-from+1) > pr.rows_left() && show_fields==printmode_normal )
|
||
pr.formfeed();
|
||
for (word j = from; j < to ;j++)
|
||
switch (show_fields)
|
||
{
|
||
case printmode_normal:
|
||
pr.print(row(j)); break; // print to printer
|
||
default:
|
||
_titlerows.add(row(j),j); break; // print to buffer
|
||
}
|
||
return to;
|
||
}
|
||
return from;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Effettua l'update della sezione footer
|
||
//
|
||
// @rdesc Ritorna l'altezza del footer settato
|
||
word TForm::set_footer(
|
||
word p, // @parm Numero pagina
|
||
bool u) // @parm Indica se cambiare l'eventuale footer corrente!!!
|
||
|
||
// @xref <mf TForm::set_background> <mf TForm::set_header> <mf TForm::set_body>
|
||
|
||
{
|
||
TPrinter& pr = printer();
|
||
pr.resetfooter();
|
||
|
||
TPrint_section& foot = section('F', p);
|
||
|
||
if (u) foot.update();
|
||
else
|
||
{
|
||
foot.reset();
|
||
pr.footerlen(foot.height());
|
||
}
|
||
|
||
for (word j = 0; j < foot.height(); j++)
|
||
pr.setfooterline(j, foot.row(j));
|
||
|
||
return foot.height();
|
||
}
|
||
|
||
void TForm::header_handler(TPrinter& p)
|
||
{
|
||
TForm& f = *_cur_form;
|
||
if (f.firstpage_is_lastpage())
|
||
{
|
||
f.set_background(1, TRUE);
|
||
f.set_header(1, TRUE);
|
||
f.set_footer(0, FALSE);
|
||
}
|
||
else
|
||
{
|
||
const word page = f.page(p);
|
||
f.set_background(page, TRUE);
|
||
f.set_header(page, TRUE);
|
||
f.set_footer(page, FALSE);
|
||
}
|
||
}
|
||
|
||
void TForm::footer_handler(TPrinter& p)
|
||
{
|
||
TForm& f = *_cur_form;
|
||
if (f.firstpage_is_lastpage())
|
||
{
|
||
f.set_footer(0, TRUE);
|
||
}
|
||
else
|
||
{
|
||
const word currp = f.page(p);
|
||
f.set_footer(currp, TRUE);
|
||
if (currp)
|
||
f.set_header(f.next_page(p), FALSE);
|
||
}
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna se la prima pagina coincide conl'ultima
|
||
bool TForm::firstpage_is_lastpage() const
|
||
{
|
||
return _first_eq_last;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna il numero di pagina correntemente in stampa
|
||
//
|
||
// @rdesc Se <md _TForm::lastpage> e' TRUE (sta stampando l'ultima pagina)
|
||
// ritorna 0, altrimenti ritorna il numero della pagina corrente da stampare
|
||
// (chiam <mf TPrinter::getcurrentepage>).
|
||
word TForm::page(
|
||
const TPrinter& p) const // @parm Operazione corrente di stampa
|
||
{
|
||
return _lastpage || fixed_pages() && p.getcurrentpage()==_npages ? 0 : p.getcurrentpage();
|
||
}
|
||
|
||
word TForm::next_page(
|
||
const TPrinter& p) const // @parm Operazione corrente di stampa
|
||
{
|
||
return _lastpage || fixed_pages() && p.getcurrentpage()+1==_npages ? 0 : p.getcurrentpage()+1;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Effettua il posizionamento manuale del modulo
|
||
void TForm::arrange_form()
|
||
|
||
// @comm Nota: siccome si scrive direttamente sulla porta, sarebbe necessario
|
||
// mandare una stringa di reset alla stampante, o per lo meno far si' che
|
||
// ogni volta che si fa il posizionamento il font col quale scrive sia sempre
|
||
// lo stesso. Tutto cio' non e' possibile con la generica solo testo, o meglio
|
||
// ad ogni stampa col posizionamento e' necessario che la stampante sia resettata.
|
||
// <nl>Riassumendo, come regola generale, i posizionamenti devono essere fatti con il
|
||
// font di default della stampante (tipicamente 10 cpi). Accade pero' (con la generica
|
||
// solo testo) che rimanga settato l'ultimo font, di conseguenza quando si effettua una
|
||
// seconda stampa con posizionamento, stampera' tali caratteri in 17"! Per questo
|
||
// motivo e' necessario settare a 17 cpi, almeno la prima volta, la stampante!.
|
||
// <nl>Quindi, per ovviare a tutto cio, visto che <mf TForm::arange_form> ha senso solo su
|
||
// stampanti ad aghi, che le stampanti ad aghi possono andare in emulazione EPSON o IBM,
|
||
// che il codice per settare il font draft 17cpi e' lo stesso sia per EPSON che IBM
|
||
// CHR(15), allora prima del posizionamento scrivo il chr(15) sulla stampante!
|
||
|
||
{
|
||
/*
|
||
int i, x;
|
||
TString str_pos;
|
||
TMask m("ba2100c");
|
||
|
||
// _ipy viene assunto uguale per entrambi i posizionamneti
|
||
str_pos = "\017"; // Questo e' 15 in ottale...
|
||
for (i=1; i < _ipy; i++) str_pos << "\n";
|
||
os_open_spool_row(printer().printername());
|
||
os_spool_row(str_pos);
|
||
os_close_spool_row();
|
||
str_pos = ""; //Azzera la stringa di posizionamento
|
||
for (i=1; i < _ipx; i++) str_pos << " "; //Aggiunge gli spazi necessari...
|
||
if (_ipx > 0)
|
||
str_pos << _char_to_pos; // aggiunge il primo carattere di posizionamento...
|
||
x = _fpx - _ipx ; // calcola quanti spazi aggiungere...
|
||
for (i=1; i < x; i++) str_pos << " ";
|
||
if (_fpx > 0)
|
||
str_pos << _char_to_pos; // aggiunge il secondo carattere di posizionamento
|
||
str_pos << '\r';
|
||
// TString bspc; bspc.fill('\b',str_pos.len()); // Questi servono per tornare indietro...
|
||
do
|
||
{
|
||
os_open_spool_row(printer().printername());
|
||
os_spool_row(str_pos);
|
||
os_close_spool_row();
|
||
} while (m.run() == K_ESC); // cicla sulla stampa posizionamento...
|
||
printer().set_offset(-(_ipy-1), printer().get_column_offset());
|
||
*/
|
||
}
|
||
|
||
long TForm::records() const
|
||
{
|
||
const long r = cursor() ? cursor()->items() : 0;
|
||
return r;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Genera automaticamente la sezione grafica con colonne fincate
|
||
//
|
||
// @rdesc Ritorna FALSE se non c'e' il body per quella pagina
|
||
bool TForm::genera_fincatura(
|
||
pagetype p, // @parm Posizione della pagina (vedi <t pagetype>)
|
||
int y1, // @parm Prima y per le righe verticali
|
||
int y2, // @parm Ultima y per le righe verticali
|
||
const int* rows) // @parm Array di posizioni riga con 0 per finire
|
||
|
||
|
||
{
|
||
TPrint_section* body = exist('B', p);
|
||
if (body == NULL) return FALSE;
|
||
|
||
body->reset_tabs();
|
||
|
||
bool istemp = exist('G', p) == NULL;
|
||
|
||
TGraphic_section* grs = (TGraphic_section*)exist('G', p, TRUE);
|
||
grs->temp() = istemp;
|
||
|
||
int j = 0, start = 999, end = 0, wlast = 0;
|
||
int cols[MAXCOLUMNS];
|
||
|
||
for (word k = grs->fields(); k > 0; k--)
|
||
if (grs->field(k-1).temp())
|
||
grs->destroy_field(k-1);
|
||
|
||
for (int i = 0; i < (int)body->fields(); i++)
|
||
{
|
||
TForm_item& f = body->field(i);
|
||
if (!f.shown() || f.is_section())
|
||
continue;
|
||
|
||
int x = f.x();
|
||
|
||
if (x < start) start = x;
|
||
if (x > end) { end = x; wlast = f.width(); }
|
||
cols[j++] = f.finkl() ? -x : x;
|
||
}
|
||
|
||
// inner lines
|
||
for (i = 0; i < j; i++)
|
||
{
|
||
if (cols[i] != start && cols[i] > 0)
|
||
{
|
||
TForm_line* l = new TForm_line(grs);
|
||
l->set_x(cols[i]-1);
|
||
l->y() = (word)y1;
|
||
l->id() = -1;
|
||
l->width() = 1;
|
||
l->height() = (int)(y2 - y1 + 1);
|
||
l->set("@R");
|
||
l->temp() = TRUE;
|
||
grs->add_field(l);
|
||
}
|
||
}
|
||
|
||
// box around
|
||
if (start != 999 && end != 0)
|
||
{
|
||
TForm_box* l = new TForm_box(grs);
|
||
l->set_x(start-1);
|
||
l->y() = (word)y1;
|
||
l->id() = -1;
|
||
l->width() = (int)(end + wlast - start + 2);
|
||
l->height() = (int)(y2 - y1 + 1);
|
||
l->set("@B@R");
|
||
l->temp() = TRUE;
|
||
grs->add_field(l);
|
||
}
|
||
|
||
// horizontal lines
|
||
if (start != 999 && end != 0)
|
||
for (i = 0; rows[i]; i++)
|
||
{
|
||
TForm_line* l = new TForm_line(grs);
|
||
l->set_x(start-1);
|
||
l->y() = (word)rows[i];
|
||
l->id() = -1;
|
||
l->width() = (int)(end + wlast - start + 2);
|
||
l->height() = 1;
|
||
l->set("@R");
|
||
l->temp() = TRUE;
|
||
grs->add_field(l);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Genera le righe di intestazione colonna alla riga indicata, vale per COLUMNWISE
|
||
//
|
||
// @rdesc Ritorna FALSE se non esiste body (o non e' COLUMNWISE) o se non esiste l'header
|
||
bool TForm::genera_intestazioni(
|
||
pagetype p, // @parm Posizione della pagina (vedi <t pagetype>)
|
||
short y) // @parm Riga dell'header in cui vanno inserite
|
||
|
||
// @comm I form_items di intestazione vengono aggiunti alla sezione header di tipo <p p> con ID -1
|
||
|
||
{
|
||
TPrint_section* body = exist('B', p);
|
||
if (body == NULL || !body->columnwise())
|
||
return FALSE;
|
||
|
||
TPrint_section* header = exist('H', p);
|
||
if (header == NULL)
|
||
return FALSE;
|
||
body->reset_tabs();
|
||
|
||
// Elimina eventuali campi temporanei precedenti
|
||
for (int k = header->fields()-1; k >= 0; k--)
|
||
if (header->field(k).temp())
|
||
header->destroy_field(k);
|
||
|
||
const word items = body->fields();
|
||
TForm_string* s;
|
||
for (word j=0;j<items;j++)
|
||
{// Scans all body items to print, and append header items...
|
||
TForm_item& fi = body->field(j);
|
||
if (!fi.shown() || fi.is_section())
|
||
continue;
|
||
char align='\0';
|
||
if (fi.col_head()[0]=='@')
|
||
{
|
||
switch (fi.col_head()[1])
|
||
{
|
||
case 'C': // centered
|
||
case 'c':
|
||
align='c';
|
||
break;
|
||
case 'R': // right just
|
||
case 'r':
|
||
align='r';
|
||
break;
|
||
default: // left just
|
||
align='l';
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Paragraph_string has as many items as lines needed...
|
||
TParagraph_string prompts(fi.col_head().mid(align ? 2:0),fi.width());
|
||
TString p;
|
||
for (int c=0;c < prompts.items(); c++)
|
||
{
|
||
p = prompts.get(c);
|
||
switch (align)
|
||
{
|
||
case 'c':
|
||
p.center_just(fi.width());
|
||
break;
|
||
case 'r':
|
||
p.right_just(fi.width());
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
s = new TForm_string(header);
|
||
s->id() = -1;
|
||
s->set_x(fi.x());
|
||
s->y() = y+c;
|
||
s->set_prompt(p);
|
||
s->temp() = TRUE;
|
||
header->add_field(s);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
void TForm::remove_temp_items(char sec, pagetype p)
|
||
{
|
||
TPrint_section* s = exist(sec,p);
|
||
if (s!=NULL)
|
||
{
|
||
const word items = s->fields();
|
||
for (word j=0;j<items; j++)
|
||
{
|
||
if (s->field(j).temp())
|
||
s->destroy_field(j,FALSE);
|
||
}
|
||
s->field_array().pack();
|
||
}
|
||
}
|
||
|
||
|
||
void TForm::put_examples(char sez, pagetype p)
|
||
{
|
||
TPrint_section* s = exist(sez,p);
|
||
if (s!=NULL)
|
||
{
|
||
const word items = s->fields();
|
||
for (word i=0;i<items;i++)
|
||
{
|
||
TForm_item& fi = s->field(i);
|
||
if (fi.fields()!=0) continue;
|
||
if (fi.memo())
|
||
fi.set(fi.memo_info());
|
||
else
|
||
if (fi.prompt().empty())
|
||
{
|
||
if (fi.class_name() == "DATA")
|
||
{
|
||
const TDate d(TODAY);
|
||
fi.set(d);
|
||
}
|
||
else
|
||
if (fi.class_name() == "NUMERO")
|
||
{
|
||
fi.set_prompt(fi.example());
|
||
fi.temp() = TRUE;
|
||
}
|
||
else
|
||
fi.set(fi.key());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void TForm::remove_examples(char sez, pagetype p)
|
||
{
|
||
TPrint_section* s = exist(sez,p);
|
||
if (s!=NULL)
|
||
{
|
||
const word items = s->fields();
|
||
for (word i=0;i<items;i++)
|
||
{
|
||
TForm_item& fi = s->field(i);
|
||
if (fi.fields()!=0) continue;
|
||
if (fi.memo())
|
||
fi.set("");
|
||
else
|
||
if (fi.class_name() == "NUMERO" && fi.temp())
|
||
{
|
||
fi.set_prompt("");
|
||
fi.temp() = FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
|
||
bool TForm::has_subsections()
|
||
{
|
||
const TPrint_section& b = section('B', odd_page);
|
||
return b.subsections() > 0 ;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Stampa gli items da <p form> a <p to>
|
||
//
|
||
// @rdesc Ritorna se ha effettuato correttamente la stampa
|
||
bool TForm::print(
|
||
long from, // @parm Primo item da stampare (default 0l)
|
||
long to) // @parm Ultimo da stampare (se <lt>0 stampa fino alla fine del file, default -1l)
|
||
|
||
// @comm Se i parametri di posizionamento sono settati e cosi' pure gli offset genera un <f error_box>.
|
||
{
|
||
_cur_form = this;
|
||
|
||
if ((_char_to_pos != '\0' || ((_ipx +_ipy+_fpx) != 0)) && // Se i parametri di posizionamento sono settati e
|
||
(_x != 0 || _y != 0)) // cosi' pure gli offset genera un errore.
|
||
{
|
||
error_box("Non e' possibile settare contemporaneamente gli offset"
|
||
" e i parametri di posizionamento del modulo.");
|
||
return FALSE;
|
||
}
|
||
TPrinter& pr = printer();
|
||
if (_frompage) pr.set_from_page(_frompage);
|
||
if (_topage) pr.set_to_page(_topage);
|
||
|
||
if (_char_to_pos != '\0' || (_ipx +_ipy+_fpx) != 0) // Effettua il posizionamento del form...
|
||
{
|
||
if (_arrange && pr.printtype() == winprinter)
|
||
arrange_form();
|
||
}
|
||
else
|
||
pr.set_offset(_y,_x);
|
||
|
||
pr.setheaderhandler(header_handler); // Setta handlers
|
||
pr.setfooterhandler(footer_handler);
|
||
if (!pr.is_generic())
|
||
{
|
||
for (pagetype t = odd_page; t <= last_page; t = pagetype(t+1))
|
||
{
|
||
if (height(t)> (word)pr.formlen())
|
||
{
|
||
TString s("La lunghezza totale della sezione ");
|
||
switch ( t )
|
||
{
|
||
case odd_page:
|
||
s << "standard"; break;
|
||
case even_page:
|
||
s << "pagine pari"; break;
|
||
case first_page:
|
||
s << "prima pagina"; break;
|
||
case last_page:
|
||
s << "ultima pagina"; break;
|
||
default:
|
||
break;
|
||
}
|
||
s << " eccede la lunghezza reale del foglio.";
|
||
message_box(s);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pr.formlen(height());
|
||
}
|
||
if (_fontsize != 0)
|
||
pr.set_char_size(_fontsize); // Set font name and size
|
||
if (_fontname.not_empty())
|
||
pr.set_fontname(_fontname); // according to current form
|
||
const bool was_open = pr.isopen();
|
||
|
||
set_last_page(FALSE); // non e' l'ultima pagina
|
||
|
||
set_background(1, TRUE);
|
||
|
||
if (!was_open && !pr.open())
|
||
return FALSE;
|
||
do_events();
|
||
|
||
long lastrec= records()-1;
|
||
|
||
if (to < 0) to = lastrec;
|
||
|
||
// controlla i casi di stampa
|
||
_first_eq_last=FALSE;
|
||
if (!fixed_pages() && !has_subsections() && set_body(1,FALSE) * word(to-from+1) <= pr.formlen()- set_header(1,FALSE) - set_footer(0,FALSE))
|
||
// tutta la stampa sta in una pagina
|
||
_first_eq_last=TRUE;
|
||
// if (to == lastrec) to--; // l'ultima pagina <20> gestita come caso particolare
|
||
|
||
bool ok = TRUE;
|
||
|
||
for (long i = from; i <= to && ok;)
|
||
{
|
||
if (pr.frozen())
|
||
break;
|
||
|
||
if (from < 0)
|
||
to = from;
|
||
else if (cursor())
|
||
{
|
||
*cursor()=i;
|
||
match_result();
|
||
}
|
||
|
||
if (pr.current_row() > pr.headersize()+1)
|
||
{
|
||
const word h = set_body(page(pr), FALSE);
|
||
if (h > pr.rows_left())
|
||
{
|
||
pr.formfeed();
|
||
// quanto resta da stampare sta nell'ultima pagina
|
||
if (!fixed_pages() && !has_subsections() && set_body(0,FALSE) * word(to-i+1) <= pr.formlen()- set_header(1,FALSE) - set_footer(0,FALSE))
|
||
{
|
||
while (i <= to && from >= 0) // stampa l'ultima pagina
|
||
{
|
||
set_last_page(TRUE);
|
||
set_background(0, TRUE);
|
||
set_header(0, TRUE);
|
||
if (cursor())
|
||
{
|
||
*cursor() = i;
|
||
set_body(0, TRUE);
|
||
}
|
||
i++;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
set_body(page(pr), TRUE);
|
||
if (cursor())
|
||
{
|
||
if (next_match_done())
|
||
i=cursor()->pos();
|
||
else
|
||
i++;
|
||
}
|
||
else
|
||
i++;
|
||
} // fine ciclo di stampa
|
||
|
||
while (fixed_pages() && page(pr) % _npages !=0)
|
||
{
|
||
pr.formfeed();
|
||
/*
|
||
static TPrintrow empty_line;
|
||
pr.print(empty_line);
|
||
*/
|
||
pr.skip(1); // No static when possible
|
||
}
|
||
|
||
if (from >= 0)
|
||
{
|
||
if (!_lastpage)
|
||
{
|
||
TPrint_section* last_foot = exist('F', last_page, FALSE);
|
||
if (last_foot != NULL)
|
||
{
|
||
const word lfh = last_foot->height();
|
||
const word left = pr.rows_left() + pr.footersize();
|
||
if (lfh > left) // Se l'ultimo footer e' troppo grande ...
|
||
pr.formfeed(); // Stampa il footer normale
|
||
pr.footerlen(lfh); // Fondamentale!
|
||
}
|
||
set_last_page(TRUE);
|
||
}
|
||
pr.formfeed();
|
||
}
|
||
if (!was_open)
|
||
pr.close();
|
||
|
||
pr.setheaderhandler(NULL);
|
||
pr.setfooterhandler(NULL);
|
||
|
||
return ok;
|
||
}
|
||
|
||
/*bool TForm::print(
|
||
long from, // @parm Primo item da stampare (default 0l)
|
||
long to) // @parm Ultimo da stampare (se <lt>0 stampa fino alla fine del file, default -1l)
|
||
|
||
// @comm Se i parametri di posizionamento sono settati e cosi' pure gli offset genera un <f error_box>.
|
||
{
|
||
_cur_form = this;
|
||
|
||
if ((_char_to_pos != '\0' || ((_ipx +_ipy+_fpx) != 0)) && // Se i parametri di posizionamento sono settati e
|
||
(_x != 0 || _y != 0)) // cosi' pure gli offset genera un errore.
|
||
{
|
||
error_box("Non e' possibile settare contemporaneamente gli offset"
|
||
" e i parametri di posizionamento del modulo.");
|
||
return FALSE;
|
||
}
|
||
TPrinter& pr = printer();
|
||
if (_frompage) pr.set_from_page(_frompage);
|
||
if (_topage) pr.set_to_page(_topage);
|
||
|
||
if (_char_to_pos != '\0' || (_ipx +_ipy+_fpx) != 0) // Effettua il posizionamento del form...
|
||
{
|
||
if (_arrange && pr.printtype() == winprinter)
|
||
arrange_form();
|
||
}
|
||
else
|
||
pr.set_offset(_y,_x);
|
||
|
||
pr.setheaderhandler(header_handler); // Setta handlers
|
||
pr.setfooterhandler(footer_handler);
|
||
if (!pr.is_generic())
|
||
{
|
||
for (pagetype t = odd_page; t <= last_page; t = pagetype(t+1))
|
||
{
|
||
if (height(t)> (word)pr.formlen())
|
||
{
|
||
TString s("La lunghezza totale della sezione ");
|
||
switch ( t )
|
||
{
|
||
case odd_page:
|
||
s << "standard"; break;
|
||
case even_page:
|
||
s << "pagine pari"; break;
|
||
case first_page:
|
||
s << "prima pagina"; break;
|
||
case last_page:
|
||
s << "ultima pagina"; break;
|
||
default:
|
||
break;
|
||
}
|
||
s << " eccede la lunghezza reale del foglio.";
|
||
message_box(s);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pr.formlen(height());
|
||
}
|
||
pr.set_char_size(_fontsize); // Set font name and size
|
||
pr.set_fontname(_fontname); // according to current form
|
||
const bool was_open = pr.isopen();
|
||
|
||
set_last_page(FALSE); // non e' l'ultima pagina
|
||
|
||
set_background(1, TRUE);
|
||
|
||
if (!was_open && !pr.open())
|
||
return FALSE;
|
||
do_events();
|
||
|
||
long lastrec= records()-1;
|
||
|
||
if (to < 0) to = lastrec;
|
||
if (to == lastrec) to--; // l'ultima pagina <20> gestita come caso particolare
|
||
|
||
bool ok = TRUE;
|
||
|
||
for (long i = from; i <= to && ok;)
|
||
{
|
||
if (from < 0) to = from;
|
||
else if (cursor())
|
||
*cursor()=i;
|
||
match_result();
|
||
|
||
if (pr.current_row() > pr.headersize()+1)
|
||
{
|
||
const word h = set_body(page(pr), FALSE);
|
||
if (h > pr.rows_left()) {
|
||
pr.formfeed();
|
||
}
|
||
}
|
||
|
||
set_body(page(pr), TRUE);
|
||
if (cursor()) {
|
||
if (next_match_done())
|
||
i=cursor()->pos();
|
||
else
|
||
i++;
|
||
}
|
||
}
|
||
|
||
if (i >= lastrec && from >= 0) // stampa l'ultima pagina (garantisce il footer diverso)
|
||
{
|
||
set_last_page(TRUE);
|
||
set_background(0, TRUE);
|
||
set_header(0, TRUE);
|
||
if (cursor() && i == lastrec) {
|
||
*cursor() = i;
|
||
set_body(0, TRUE);
|
||
}
|
||
pr.formfeed();
|
||
}
|
||
|
||
if (!was_open)
|
||
pr.close();
|
||
|
||
pr.setheaderhandler(NULL);
|
||
pr.setfooterhandler(NULL);
|
||
|
||
return ok;
|
||
} */
|
||
|
||
|
||
void TForm::print_section(ostream& out, char s) const
|
||
{
|
||
for (pagetype t = odd_page; t <= last_page; t = pagetype(t+1))
|
||
{
|
||
const TPrint_section* sec = ((TForm*)this)->exist(s, t);
|
||
if (sec && sec->ok() && !sec->temp())
|
||
{
|
||
const char* name;
|
||
switch (s)
|
||
{
|
||
case 'F':
|
||
name = "FOOTER"; break;
|
||
case 'G':
|
||
name = "GRAPHICS"; break;
|
||
case 'H':
|
||
name = "HEADER"; break;
|
||
default :
|
||
name = "BODY"; break;
|
||
}
|
||
out << "SECTION " << name;
|
||
out << *sec;
|
||
out << "END\n" << endl;
|
||
}
|
||
}
|
||
}
|
||
|
||
// funzione di validazione delle macro
|
||
bool TForm::validate(TForm_item &cf, TToken_string &s)
|
||
{
|
||
const TString code(s.get(0)); // prende il primo parametro, il codice del messaggio
|
||
TString valore;
|
||
|
||
if (code=="_ISAMREAD")
|
||
{
|
||
// lettura generica di un file del database
|
||
// sintassi: _ISAMREAD,<file>,<espressione input>[!<espressione input>!...],{<campo file>|<espressione output>[!<espressione output>!...]}
|
||
// dove: <file> <20> il numero logico del file o il nome della tabella
|
||
// <espressione input> <20> un'espressione del tipo <campo file>=<espressione campi form>
|
||
// <espressione campi form> <20> un'espressione di costanti numeriche, stringhe e valori di campi della form (indicati con il loro numero preceduto da #)
|
||
// <espressione output> <20> un'espressione del tipo <campo form o gruppo>=<campo file> (se <20> un gruppo deve essere seguito da @) oppure solo <campo file> (il campo della form <20> quello corrente)
|
||
int i, j, poseq, posrv, itms;
|
||
pagetype pt;
|
||
char sec;
|
||
TLocalisamfile *file;
|
||
TString f_code(s.get()); // prende il codice del file da leggere
|
||
if (atoi(f_code) != 0) file= new TLocalisamfile(atoi(f_code)); // se il codice <20> numerico allora <20> un file
|
||
else file= new TTable(f_code); // altrimenti <20> una tabella
|
||
file->zero(); // vuota il record corrente del file
|
||
TToken_string in(s.get(), '!');
|
||
for (i=0; i<in.items(); i++)
|
||
{ // scansione sugli elementi dell'input
|
||
TString curr(in.get(i));
|
||
poseq= curr.find("=="); // divide la stringa corrente in lvalue e rvalue
|
||
if (poseq== -1)
|
||
{
|
||
poseq= curr.find('=');
|
||
if (poseq != -1) posrv= poseq+1;
|
||
}
|
||
else
|
||
posrv= poseq+2;
|
||
TString fld(curr.left(poseq)); // preleva il nome del campo del file alla sinistra dell'uguale
|
||
TString expr(curr.mid(posrv)); // preleva l'espressione di assegnamento alla destra dell'uguale
|
||
TExpression rval(expr, _strexpr);
|
||
for (j=0; j<rval.numvar(); j++)
|
||
{ // scansione delle variabili dell'espressione di rvalue
|
||
TString var= rval.varname(j);
|
||
if (var[0]=='#') var.ltrim(1); // rimuove dalla stringa il primo carattere
|
||
TForm_item &fi= cf.find_field(var);
|
||
rval.setvar(j, fi.get()); // il valore corrente del campo viene settato nell'espressione
|
||
}
|
||
file->put(fld, rval.as_string()); // scrive il risultato dell'espressione nel campo del file
|
||
}
|
||
if (file->read()== NOERR)
|
||
{ // tenta una lettura del file
|
||
TToken_string out(s.get(), '!');
|
||
for (i=0; i<out.items(); i++)
|
||
{ // scansione sugli elementi dell'output
|
||
TString curr(out.get(i));
|
||
poseq= curr.find("=="); // divide la stringa corrente in lvalue e rvalue
|
||
if (poseq== -1)
|
||
{
|
||
poseq= curr.find('=');
|
||
if (poseq != -1) posrv= poseq+1;
|
||
}
|
||
else
|
||
posrv= poseq+2;
|
||
if (poseq== -1)
|
||
{
|
||
const TString &dat= file->get(curr); // preleva il nome del campo del file e lo legge dal record
|
||
cf.set(dat);
|
||
}
|
||
else
|
||
{
|
||
TString fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale
|
||
const TString &dat= file->get(curr.mid(posrv)); // preleva il nome del campo del file alla destra dell'uguale e lo legge dal record
|
||
if (fld[0]=='#') fld.ltrim(1);
|
||
if (fld.right(1)== "@")
|
||
{ // se c'<27> la a-commerciale <20> un gruppo
|
||
if (fld.find("->") != -1)
|
||
{ // se nel gruppo c'<27> la freccia si riferisce ad un'altra sezione
|
||
sec= fld[0];
|
||
if (fld[1] != '-') pt= char2page(fld[1]);
|
||
else pt= even_page;
|
||
itms= section(sec, pt).fields();
|
||
}
|
||
else
|
||
{ // altrimenti si riferisce alla sezione corrente
|
||
sec= cf.section().section_type();
|
||
pt= cf.section().page_type();
|
||
itms= cf.section().fields();
|
||
}
|
||
for (j=0; j<itms; j++)
|
||
{ // per ogni campo della sezione specificata (o sottointesa)...
|
||
TForm_item &fi= section(sec, pt).field(j);
|
||
fi.set(dat);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TForm_item &fi= cf.find_field(fld);
|
||
fi.set(dat);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
delete file;
|
||
return TRUE;
|
||
// fine _ISAMREAD
|
||
}
|
||
|
||
if (code== "_TABLEREAD")
|
||
{
|
||
// lettura generica di un campo di una tabella
|
||
// sintassi: _TABLEREAD,<tabella>,<chiave>,<campo file>
|
||
// dove: <tabella> nome tabella da leggere
|
||
// <chiave> costante stringa o riferimento a campo della form (preceduto da '#') da usare come chiave di ricerca
|
||
// <campo file> identificativo del campo da leggere dalla tabella
|
||
TTable tab(s.get()); // prende il nome della tabella
|
||
tab.zero(); // vuota il record corrente della tabella
|
||
TString in(s.get()); // prende il valore o il campo da usare come codice di ricerca
|
||
if (in[0]== '#')
|
||
{
|
||
in.ltrim(1);
|
||
TForm_item &fi= cf.find_field(in);
|
||
in= fi.get();
|
||
}
|
||
tab.put("CODTAB", in); // setta la chiave nella tabella
|
||
if (tab.read()== NOERR)
|
||
{
|
||
const TString &fld= s.get(); // prende il nome del campo da leggere...
|
||
valore = tab.get(fld);
|
||
cf.set(valore);
|
||
}
|
||
return TRUE;
|
||
} // fine _TABLEREAD
|
||
|
||
if (code== "_ALIGN")
|
||
{
|
||
// allineamento della posizione di un campo rispetto ad un altro
|
||
// sintassi: _ALIGN,<campo form>[,<allineamento>][,<allineamento>...]
|
||
// dove: <campo form> <20> il campo della form (preceduto da '#') da cui prendere l'allineamento
|
||
// <allineamento> <20> uno dei seguenti valori:
|
||
// TOP allinea sulla riga d'inizio
|
||
// MIDDLE allinea al centro (effettivo)
|
||
// BOTTOM allinea sulla riga di fine (effettiva, non preimpostata)
|
||
// LEFT allinea sulla colonna d'inizio
|
||
// RIGHT allinea sulla colonna di fine
|
||
TString in(s.get());
|
||
if (in[0]== '#') in.ltrim(1);
|
||
TForm_item &fi= cf.find_field(in);
|
||
|
||
int i= 2;
|
||
for (const char * cmd = s.get(); cmd != NULL; cmd = s.get())
|
||
{ // Calcola la nuova posizione
|
||
TString align(cmd);
|
||
if (align[0]=='!')
|
||
align.ltrim(1);
|
||
|
||
if (align== "TOP") cf.y()= fi.y();
|
||
else
|
||
if (align== "MIDDLE") cf.y()= fi.y()+ fi.effective_height()/2;
|
||
else
|
||
if (align== "BOTTOM") cf.y()= fi.y()+ (fi.effective_height() ? fi.effective_height()-1 : 0);
|
||
else
|
||
if (align== "LEFT") cf.set_x(fi.x());
|
||
else
|
||
if (align== "RIGHT") cf.set_x(fi.x()+ fi.width());
|
||
}
|
||
// altrimenti stampa la stringa cosi' com'e'
|
||
return TRUE;
|
||
} // fine _ALIGN
|
||
|
||
if (code== "_PAGENO") // Messaggio per stampare il numero di pagina corrente
|
||
{
|
||
TString16 pg; pg << int(printer().getcurrentpage() );
|
||
cf.set(pg);
|
||
return TRUE;
|
||
}
|
||
|
||
if (code== "_TODAY")// Messaggio per stampare la data di oggi
|
||
{
|
||
TString16 dt(TDate(TODAY).string());
|
||
cf.set(dt);
|
||
return TRUE;
|
||
}
|
||
|
||
if (code== "_NUMEXPR" || code== "_STREXPR")
|
||
{
|
||
// Messaggio per la valutazione di espressioni numeriche e stringhe
|
||
int comma = s.find(',');
|
||
TExpression rval(s.mid(comma+1),code[1]=='N' ? _numexpr:_strexpr,TRUE);
|
||
cf.section().eval_expr(rval);
|
||
if (!rval.error())
|
||
cf.set(rval.as_string());
|
||
return TRUE;
|
||
}
|
||
|
||
if (code== "_DITTA")
|
||
{
|
||
// lettura dei dati della ditta
|
||
// sintassi: _DITTA,{<campo relazione>|<macro>}
|
||
// dove: <campo relazione> <20> un riferimento alla relazione di gestione dei dati della ditta (es. 113@->DENCOM <20> la denominazione del comune di residenza della ditta)
|
||
// <macro> <20> uno delle macro seguenti:
|
||
// !RAGSOC ragione sociale
|
||
// !IND indirizzo (fiscale se c'<27>, oppure di residenza)
|
||
// !NUM numero civico (fiscale se c'<27>, oppure di residenza)
|
||
// !CAP CAP (fiscale se c'<27>, oppure di residenza)
|
||
// !COM comune (fiscale se c'<27>, oppure di residenza)
|
||
// !PROV provincia (fiscale se c'<27>, oppure di residenza)
|
||
// !IVA partita iva
|
||
// !CF codice fiscale
|
||
// !TEL numero di telefono (con prefisso)
|
||
// !FAX numero di fax (con prefisso)
|
||
// !REGSOC numero di registrazione presso il Tribunale
|
||
// !CCIAA numero di registrazione presso la camera di commercio
|
||
// nota: la relazione della ditta <20> cos<6F> strutturata:
|
||
// %NDITTE (9) Dati ditte
|
||
// + %ANAGR (6) Anagrafica generale (indirizzo, ecc.)
|
||
// + %COMUNI (113@) Comune di residenza
|
||
// + %COMUNI (213@) Comune di residenza fiscale
|
||
TLocalisamfile firm(LF_NDITTE);
|
||
TLocalisamfile anag(LF_ANAG);
|
||
firm.put("CODDITTA",main_app().get_firm());
|
||
firm.read();
|
||
anag.put("TIPOA",firm.get("TIPOA"));
|
||
anag.put("CODANAGR",firm.get("CODANAGR"));
|
||
anag.read();
|
||
TString in(s.get());
|
||
if (in[0]=='!') {
|
||
in.ltrim(1);
|
||
bool _fisc= anag.get("INDRF").not_empty();
|
||
if (in=="RAGSOC")
|
||
valore = anag.get("RAGSOC");
|
||
if (in=="IND") {
|
||
if (_fisc)
|
||
valore = anag.get("INDRF");
|
||
else
|
||
valore = anag.get("INDRES");
|
||
}
|
||
if (in=="NUM") {
|
||
if (_fisc)
|
||
valore = anag.get("CIVRF");
|
||
else
|
||
valore = anag.get("CIVRES");
|
||
}
|
||
if (in=="CAP") {
|
||
if (_fisc)
|
||
valore = anag.get("CAPRF");
|
||
else
|
||
valore = anag.get("CAPRES");
|
||
}
|
||
/*if (in=="COM") {
|
||
if (_fisc)
|
||
valore = _firmrel.lfile(-213).get("DENCOM");
|
||
else
|
||
valore = _firmrel.lfile(-113).get("DENCOM");
|
||
}
|
||
if (in=="PROV") {
|
||
if (_fisc)
|
||
valore = _firmrel.lfile(-213).get("PROVCOM");
|
||
else
|
||
valore = _firmrel.lfile(-113).get("PROVCOM");
|
||
}*/
|
||
if (in=="IVA")
|
||
valore = anag.get("PAIV");
|
||
if (in=="CF")
|
||
valore = anag.get("COFI");
|
||
if (in=="TEL") {
|
||
valore = anag.get("PTEL");
|
||
valore << "/" << anag.get("TEL");
|
||
}
|
||
if (in=="FAX") {
|
||
valore = anag.get("PFAX");
|
||
valore << "/" << anag.get("FAX");
|
||
}
|
||
/*if (in=="REGSOC") {
|
||
valore = _firmrel[LF_UNLOC].get("REGTRIB");
|
||
valore << " Vol. " << _firmrel[LF_UNLOC].get("VOLTRIB");
|
||
valore << " Fasc. " << _firmrel[LF_UNLOC].get("FASCTRIB");
|
||
}
|
||
if (in=="CCIAA") {
|
||
valore = _firmrel[LF_UNLOC].get("NUMCCIAA");
|
||
valore << " del " << _firmrel[LF_UNLOC].get("DATAICCIAA");
|
||
} */
|
||
} else {
|
||
TFieldref fref(s.get(), 0);
|
||
valore = fref.read(anag.curr());
|
||
}
|
||
cf.set(valore);
|
||
return TRUE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm::print_on(ostream& out) const
|
||
{
|
||
if (relation())
|
||
{
|
||
out << *relation() << "\nEND" << endl;
|
||
print_description(out);
|
||
}
|
||
|
||
print_general(out);
|
||
|
||
print_section(out, 'G');
|
||
print_section(out, 'H');
|
||
print_section(out, 'B');
|
||
print_section(out, 'F');
|
||
|
||
out << "END" << endl;
|
||
}
|
||
|
||
|
||
word TForm::height(word page)
|
||
{
|
||
const pagetype t = (page == 1) ? first_page : ((page & 0x1) ? odd_page : even_page);
|
||
|
||
word h = 0;
|
||
if (_back.items() == 0)
|
||
{
|
||
if (_head.items() && exist('H', t) != NULL)
|
||
h += section('H', page).height();
|
||
if (_body.items() && exist('B', t) != NULL)
|
||
h += section('B', page).height();
|
||
if (_foot.items() && exist('F', t) != NULL)
|
||
h += section('F', page).height();
|
||
}
|
||
else
|
||
h = printer().formlen();
|
||
|
||
return h;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Legge un profilo
|
||
//
|
||
// @rdesc Ritorna se e' riuscito nell'operazione:
|
||
// @flag TRUE | E' riuscito a leggere il prfilo
|
||
// @flag FALSE | Non ha letto il profilo
|
||
bool TForm::read_profile()
|
||
// @comm Per la lettura del profilo procede leggendo prima la definizione del
|
||
// profilo base e successivamente le modifiche relative.
|
||
{
|
||
TLocalisamfile prof(LF_FORM);
|
||
TLocalisamfile rprof(LF_RFORM);
|
||
|
||
prof.zero();
|
||
prof.put("TIPOPROF",_name);
|
||
prof.put("CODPROF",_code);
|
||
if (prof.read(_isequal) == NOERR)
|
||
{
|
||
rprof.zero();
|
||
rprof.put("TIPOPROF", _name);
|
||
rprof.put("CODPROF", _code);
|
||
const TRectype filter(rprof.curr());
|
||
TString set("HGBF");
|
||
|
||
for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next())
|
||
{
|
||
// controllo lingua per codici profilo
|
||
char cl = rprof.curr().get("CODPROF").right(1)[0];
|
||
char cp = _code.right(1)[0];
|
||
|
||
// stop se il codice letto e' di un profilo EC in lingua e
|
||
// il corrente e' ec non in lingua
|
||
if (!isdigit(cl) && cl != cp) break;
|
||
|
||
const TString& s = rprof.get("SEZ");
|
||
const char sec = s[0];
|
||
if (set.find(sec)<0) continue; // Se non fa parte di una sezione standard la salta
|
||
const pagetype pt = char2page(s[1]);
|
||
const short id = rprof.get_int("ID");
|
||
|
||
if (id == 0)
|
||
{
|
||
TPrint_section& se = section(sec, pt);
|
||
se.read_from(rprof.curr());
|
||
}
|
||
else
|
||
{
|
||
TForm_item& item = find_field(sec, pt, id);
|
||
item.read_from(rprof.curr());
|
||
}
|
||
}
|
||
if (_code.not_empty()&& !_isnew)
|
||
{
|
||
_x = prof.get_int("OFFX");
|
||
_y = prof.get_int("OFFY");
|
||
_fontname = prof.get("FONTNAME");
|
||
_fontsize = prof.get_int("FONTSIZE");
|
||
_char_to_pos = prof.get("CTP")[0];
|
||
_ipx = prof.get_int("IPX");
|
||
_ipy = prof.get_int("IPY");
|
||
_fpx = prof.get_int("FPX");
|
||
set_fincatura(prof.get("GRID"));
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
bool TForm::write_profile()
|
||
{
|
||
const char sechar[4] = { 'B', 'F', 'G', 'H' };
|
||
|
||
get_compulsory_specials();
|
||
TLocalisamfile form(LF_FORM);
|
||
form.zero();
|
||
form.put("TIPOPROF",_name);
|
||
form.put("CODPROF",_code);
|
||
if (form.read(_isequal,_lock) == NOERR)
|
||
{
|
||
if (_dirty)
|
||
{
|
||
form.put("OFFY",_y);
|
||
form.put("OFFX",_x);
|
||
form.put("FONTNAME",_fontname);
|
||
form.put("FONTSIZE",_fontsize);
|
||
form.put("CTP",_char_to_pos);
|
||
form.put("IPX", _ipx);
|
||
form.put("IPY", _ipy);
|
||
form.put("FPX", _fpx);
|
||
form.put("GRID", _fink);
|
||
form.rewrite();
|
||
_dirty=FALSE;
|
||
}
|
||
}
|
||
|
||
TLocalisamfile rform(LF_RFORM);
|
||
TRectype& cur = rform.curr();
|
||
|
||
int err = NOERR;
|
||
for (int sn = 0; sn < 4 && err == NOERR; sn++) // For each section
|
||
{
|
||
const char sc = sechar[sn];
|
||
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1)) // For each section type
|
||
{
|
||
TPrint_section* sec = exist(sc, pt);
|
||
if (sec != NULL && sec->dirty())
|
||
{
|
||
const char codsez[3] = { sc, pt+'0', '\0' };
|
||
cur.zero();
|
||
cur.put("TIPOPROF", name());
|
||
cur.put("CODPROF", code());
|
||
cur.put("SEZ", codsez);
|
||
sec->print_on(cur);
|
||
sec->set_dirty(FALSE);
|
||
|
||
err = _isnew ? rform.write() : rform.rewrite();
|
||
if (err != NOERR)
|
||
err = _isnew ? rform.rewrite() : rform.write();
|
||
|
||
for (word i = 0; i < sec->fields() && err == NOERR; i++)
|
||
{
|
||
TForm_item& fi = sec->field(i);
|
||
if (fi.dirty())
|
||
{
|
||
fi.print_on(cur);
|
||
err = _isnew ? rform.write() : rform.rewrite();
|
||
if (err != NOERR)
|
||
err = _isnew ? rform.rewrite() : rform.write();
|
||
fi.set_dirty(FALSE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
form.reread(_unlock);
|
||
if (err != NOERR)
|
||
return error_box("Errore di salvataggio profilo: %d", err);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void TForm::init()
|
||
{
|
||
_npages=0;
|
||
_relation= NULL;
|
||
_cursor= NULL;
|
||
_rel_desc= NULL;
|
||
_isnew= FALSE;
|
||
_fontname= "";
|
||
_fontsize= 0;
|
||
_x= 0;
|
||
_y= 0;
|
||
_char_to_pos= '\0';
|
||
_ipx= 0;
|
||
_ipy= 0;
|
||
_fpx= 0;
|
||
_arrange= TRUE;
|
||
set_fincatura("+++++++++-|");
|
||
set_fink_mode(TRUE);
|
||
_dirty= FALSE;
|
||
_msg_add_enabled = TRUE;
|
||
_magic_currency = FALSE;
|
||
_exchange = NULL;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Carica il form dal file specificato
|
||
void TForm::read(
|
||
const char* name, // @parm Nome del profilo di stampa da leggere
|
||
const char* code, // @parm Codice del profilo di stampa da leggere
|
||
int lev, // @parm Permessi di stampa
|
||
const char* desc) // @parm Descrizione del formato da leggere
|
||
{
|
||
_name= name;
|
||
|
||
_code= code;
|
||
_editlevel= lev;
|
||
_desc= desc;
|
||
|
||
if (_code.not_empty())
|
||
{
|
||
// extract base form name
|
||
TLocalisamfile forms(LF_FORM);
|
||
forms.zero();
|
||
|
||
forms.put("TIPOPROF", _name);
|
||
forms.put("CODPROF", _code);
|
||
_isnew = forms.read() != NOERR;
|
||
if (_isnew)
|
||
{
|
||
// create new form
|
||
forms.put("TIPOPROF", _name);
|
||
forms.put("CODPROF", _code);
|
||
forms.put("DESC", _desc);
|
||
forms.put("OFFY",_y);
|
||
forms.put("OFFX",_x);
|
||
forms.put("FONTNAME",_fontname);
|
||
forms.put("FONTSIZE",_fontsize);
|
||
forms.put("CTP", _char_to_pos);
|
||
forms.put("IPX", _ipx);
|
||
forms.put("IPY", _ipy);
|
||
forms.put("FPX", _fpx);
|
||
forms.put("GRID", _fink);
|
||
forms.write();
|
||
}
|
||
else
|
||
if (forms.status() == NOERR)
|
||
{
|
||
_desc = forms.get("DESC");
|
||
if (desc && *desc && _desc != desc ) // Controlla se la descrizione e' diversa, in questo caso l'aggiorna
|
||
{
|
||
forms.reread(_lock);
|
||
forms.put("DESC",desc);
|
||
forms.rewrite();
|
||
}
|
||
}
|
||
}
|
||
|
||
// read base form
|
||
TFilename n(_name); n.ext("frm");
|
||
n.custom_path();
|
||
if (!n.exist())
|
||
fatal_box("Il form '%s' non esiste.",(const char*)n);
|
||
TScanner scanner(n);
|
||
|
||
bool ok = TRUE;
|
||
if (scanner.popkey() == "US") // Parse relation
|
||
{
|
||
ok = parse_use(scanner);
|
||
while (ok && scanner.popkey() == "JO" || scanner.key() == "SO")
|
||
{
|
||
if (scanner.key() == "JO")
|
||
ok = parse_join(scanner);
|
||
else // join a sorted file
|
||
{
|
||
ok= parse_sortedjoin(scanner);
|
||
}
|
||
}
|
||
|
||
parse_description(scanner); // Parse description
|
||
}
|
||
else scanner.push();
|
||
|
||
if (ok) parse_general(scanner); // Parse general
|
||
|
||
while (ok)
|
||
{
|
||
if (scanner.popkey() != "SE") // SECTION or END
|
||
break;
|
||
const char sec = scanner.popkey()[0]; // Section name (GRAPH, HEAD, BODY, FOOT)
|
||
const pagetype p = char2page(scanner.popkey()[0]); // Section type (odd, even, first, last)
|
||
TPrint_section* ps = exist(sec, p, TRUE); // Create section
|
||
ok = ps->parse(scanner); // Parse section
|
||
}
|
||
|
||
if (_code.not_empty())
|
||
read_profile(); // read from LF_RFORM file
|
||
|
||
set_compulsory_specials();
|
||
TPrinter& pr = printer();
|
||
pr.set_offset(_y,_x);
|
||
if (_fontname.not_empty())
|
||
{
|
||
pr.set_char_size(_fontsize);
|
||
pr.set_fontname(_fontname);
|
||
}
|
||
else
|
||
{
|
||
_fontname = pr.fontname();
|
||
_fontsize = pr.get_char_size();
|
||
}
|
||
set_fink_mode(TRUE);
|
||
}
|
||
|
||
void TForm::set_compulsory_specials()
|
||
{
|
||
const char sechar[3] = { 'B', 'F', 'H' };
|
||
|
||
for (int sn = 0; sn < 3; sn++)
|
||
{
|
||
const char sc = sechar[sn];
|
||
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
|
||
{
|
||
const TPrint_section* sec = exist(sc, pt);
|
||
if (sec != NULL && sec->columnwise())
|
||
{
|
||
const word fields = sec->fields();
|
||
for (word i = 0; i < fields; i++)
|
||
{
|
||
TForm_item& fi = sec->field(i);
|
||
if (fi.special_items() > 0)
|
||
{
|
||
fi.set_col_head(fi.get_special_value("INTESTAZIONE"));
|
||
fi.ofs() = (short)atoi(fi.get_special_value("OFFSET"));
|
||
const TString& fnk = fi.get_special_value("FINCATURA");
|
||
if (fnk.not_empty())
|
||
{
|
||
fi.set_finkl(fnk[0]!='X'); // !finkl significa fincatura abilitata
|
||
fi.set_finkr(fnk[1]!='X'); // !finkr significa fincatura abilitata
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void TForm::get_compulsory_specials()
|
||
{
|
||
const char sechar[3] = { 'B', 'F', 'H' };
|
||
|
||
for (int sn = 0; sn < 3; sn++)
|
||
{
|
||
const char sc = sechar[sn];
|
||
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
|
||
{
|
||
TPrint_section* sec = exist(sc, pt);
|
||
if (sec != NULL)
|
||
{
|
||
const word fields = sec->fields();
|
||
const bool col_wise = sec->columnwise();
|
||
for (word i = 0; col_wise && i < fields; i++)
|
||
{
|
||
TForm_item& fi = sec->field(i);
|
||
if (fi.special_items()>0)
|
||
{
|
||
fi.set_special_value("INTESTAZIONE", fi.col_head());
|
||
fi.set_special_value("OFFSET", format("%d",fi.ofs()));
|
||
TString fnk(fi.finkl()? " " : "X");
|
||
fnk << (fi.finkr() ? " " : "X");
|
||
fi.set_special_value("FINCATURA",fnk);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void TForm::set_fincatura(const char* s)
|
||
{
|
||
_fink = s; _fink.cut(11);
|
||
printer().set_fincatura(_fink);
|
||
}
|
||
|
||
void TForm::set_fink_mode(bool f)
|
||
{
|
||
printer().set_fink_mode(f);
|
||
}
|
||
|
||
bool TForm::get_fink_mode()
|
||
{
|
||
return printer().get_fink_mode();
|
||
}
|
||
|
||
// @cmember Indica se ignorare il prossimo skip del ciclo sul file
|
||
void TForm::match_result(int file,int val)
|
||
{
|
||
if (file==0)
|
||
file=cursor()->file().num();
|
||
if (val <0)
|
||
_skip_info.destroy(file);
|
||
else
|
||
{
|
||
TForm_skip_info info;
|
||
if (next_match_done(file))
|
||
info._match_number=((TForm_skip_info &)_skip_info[file])._match_number;
|
||
if (val)
|
||
info._match_number++;
|
||
info._match_result= val != 0;
|
||
_skip_info.add(info,file);
|
||
}
|
||
}
|
||
// @cmember Indica se ignorare (default) o non ignorare il prossimo skip del ciclo sul file
|
||
bool TForm::last_match_result(int file)
|
||
{
|
||
if (file==0)
|
||
file=cursor()->file().num();
|
||
if (next_match_done(file))
|
||
return ((TForm_skip_info &)_skip_info[file])._match_result;
|
||
return fatal_box("Tryed to get result of a never executed skip in file %d",file);
|
||
}
|
||
// @mfunc Memorizza l'avvenuto next_match sul file passato
|
||
bool TForm::next_match_done(int file)
|
||
{
|
||
if (file==0)
|
||
file=cursor()->file().num();
|
||
return _skip_info.objptr(file)!=NULL;
|
||
}
|
||
|
||
// @mfunc Indica l'avvenuto next_match sul file passato
|
||
int TForm::matches_done(int file)
|
||
{
|
||
if (file==0)
|
||
file=cursor()->file().num();
|
||
if (next_match_done(file))
|
||
return ((TForm_skip_info &)_skip_info[file])._match_number;
|
||
return 0;
|
||
}
|
||
|
||
void TForm::set_output_exchange(const char* codval, real exchange, exchange_type et)
|
||
{
|
||
if (_exchange == NULL)
|
||
_exchange = new TExchange;
|
||
_exchange->set(codval, exchange, et);
|
||
}
|
||
|
||
TForm::TForm()
|
||
{
|
||
init();
|
||
_frompage=_topage=0;
|
||
_magic_currency = FALSE;
|
||
}
|
||
|
||
TForm::TForm(const char* name, const char* code, int lev, const char* desc)
|
||
{
|
||
init();
|
||
read(name, code, lev, desc);
|
||
_frompage=_topage=0;
|
||
_magic_currency = FALSE;
|
||
}
|
||
|
||
TForm::~TForm()
|
||
{
|
||
if (_cursor)
|
||
{
|
||
delete _cursor;
|
||
delete _relation;
|
||
if (_rel_desc)
|
||
delete _rel_desc;
|
||
}
|
||
if (_exchange)
|
||
delete _exchange;
|
||
}
|