campo-sirio/include/form.cpp
guy 52fd0bd544 anafis.h Tolto campo inesistente TIPOA
anagiu.h     Tolto campo inesistente TIPOA
form.cpp     Modificato costruttore delle subsection per non dare warning
msksheet.cpp Tolta riga vuota
utility.cpp  Tolto errore fatale nella funzione copyfile
filetext.* Aggiunta gestione file di testo della Paola


git-svn-id: svn://10.65.10.50/trunk@4974 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-07-30 12:36:24 +00:00

5154 lines
131 KiB
C++
Executable File
Raw Blame History

#include <ctype.h>
#include <stdlib.h>
#define STRICT
#define XVT_INCL_NATIVE
#include <applicat.h>
#include <form.h>
#include <msksheet.h>
#include <printer.h>
#include <relation.h>
#include <sheet.h>
#include <utility.h>
#include <spool.h>
#include <expr.h>
#include <tabutil.h>
#ifndef __DEFMASK_H
#include <defmask.h>
#endif
#include "../ba/bafrm.h"
// per lo sheet di edit campi
HIDDEN const int idt_id = 101;
HIDDEN const int dsc_id = 102;
HIDDEN const int prn_id = 103;
HIDDEN const int yps_id = 104;
HIDDEN const int xps_id = 105;
HIDDEN const int len_id = 106;
HIDDEN const int col_id = 107;
HIDDEN const int int_id = 108;
HIDDEN const int spc_id = 109;
HIDDEN const int fnl_id = 110;
HIDDEN const int fnr_id = 111;
HIDDEN const int typ_id = 112;
HIDDEN const int frm_id = 113;
///////////////////////////////////////////////////////////
// Utility functions
///////////////////////////////////////////////////////////
// Current form (edit, print)
HIDDEN TForm* _cur_form = NULL;
HIDDEN TPrint_section* _cur_sect = NULL;
HIDDEN TMask* _special_mask = NULL;
HIDDEN TForm& form()
{
CHECK(_cur_form, "Can't print NULL form");
return *_cur_form;
}
HIDDEN TPrint_section& section()
{
CHECK(_cur_sect, "Can't print NULL section");
return *_cur_sect;
}
HIDDEN TMask& special_mask()
{
CHECK(_special_mask, "Can't access NULL mask");
return *_special_mask;
}
// @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;
}
///////////////////////////////////////////////////////////
// Gestione TFieldref su maschera
// ID CAMPO ATTIVO
// xx0 Stringa completa del TFieldref
// xx1 Descrizione file
// xx2 Bottone selezione file X
// xx3 Descrizione campo
// xx4 Bottone selezione campo X
// xx5 Primo carattere campo X
// xx6 Ultimo carattere campo X
///////////////////////////////////////////////////////////
HIDDEN void put_fieldref(const TFieldref& fr, TMask_field& f)
{
TRelation_description& rd = form().rel_desc();
rd.set_cur_file(fr.file());
TString80 desc; desc << fr;
f.set(desc);
TMask& m = f.mask();
const short id = f.dlg(); // Campo contenente il TFieldref
m.set(id+1, rd.file_desc());
m.set(id+3, rd.get_field_description(fr.name()));
m.set(id+5, (fr.from() > 0 || fr.to() > 0) ? fr.from()+1 : 0);
m.set(id+6, fr.to() > fr.from() ? fr.to() : 0);
}
// Handler of F_BUT_FILE field on mask
HIDDEN bool but_file_handler(TMask_field& f, KEY k)
{
if (k == K_F9)
{
TRelation_description& r = form().rel_desc();
TEdit_field& e = f.mask().efield(f.dlg()-1);
TFieldref ref; ref = e.get();
if (r.choose_file(ref.file()))
{
ref.set_file(r.file_num());
put_fieldref(ref, e);
}
}
return TRUE;
}
HIDDEN bool but_file_handler_sub(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TRelation_description& r = form().rel_desc();
TEdit_field& e = f.mask().efield(f.dlg()-2);
TFieldref ref; ref = e.get();
if (r.choose_file(ref.file()))
{
ref.set_file(r.file_num());
f.mask().set(F_FILE1,r.file_desc());
}
}
return TRUE;
}
// Handler of F_BUT_FIELD field on mask
HIDDEN bool but_field_handler(TMask_field& f, KEY k)
{
if (k == K_F9)
{
TRelation_description& r = form().rel_desc();
TEdit_field& e = f.mask().efield(f.dlg()-3); // TBC
TFieldref ref; ref = e.get();
if (r.choose_field(ref.name()))
{
ref.set_name(r.field_name());
put_fieldref(ref, e);
}
}
return TRUE;
}
// Handler of F_FROM field on mask
HIDDEN bool from_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
TEdit_field& e = f.mask().efield(f.dlg()-5);
TFieldref ref; ref = e.get();
ref.set_from(atoi(f.get()));
put_fieldref(ref, e);
}
return TRUE;
}
// Handler of F_TO field on mask
HIDDEN bool to_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
TEdit_field& e = f.mask().efield(f.dlg()-6);
TFieldref ref; ref = e.get();
ref.set_to(atoi(f.get()));
put_fieldref(ref, e);
}
return TRUE;
}
HIDDEN bool dateformat_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TMask& m = f.mask();
char fmt[8];
fmt[0] = m.get(F_DFORMAT)[0];
fmt[1] = m.get(F_DDAY)[0];
fmt[2] = m.get(F_DMONTH)[0];
fmt[3] = m.get(F_DYEAR)[0];
fmt[4] = m.get(F_DSEP)[0];
fmt[5] = '\0';
const TDate d(TODAY);
const TFormatted_date ex(d,fmt);
m.set(F_DEXAMPLE, ex.string());
}
return TRUE;
}
HIDDEN bool fmt_handler(TMask_field& f, KEY k)
{
if (k==K_ENTER || k==K_TAB)
{
TMask& m = f.mask();
TPrint_section& s = ::section();
if (s.columnwise())
{
const int fmt_len = m.get(F_PICTURE).len(); // length of picture
m.set(F_LENFMT,fmt_len);
m.set(F_NUMCOL,s.fields());
}
else
m.set(F_NUMCOL,999);
}
return TRUE;
}
///////////////////////////////////////////////////////////
// TForm_flags
///////////////////////////////////////////////////////////
TForm_flags::TForm_flags()
{
automagic = dirty = finkr = finkl = memo = newpage = 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;
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 (s.not_empty())
out << " FLAGS \"" << s << '"' << endl;
}
// Set mask fields
// Certified 100%
void TForm_flags::print_on(TMask& m)
{
m.set(F_DISABLED, enabled ? " " : "X");
m.set(F_HIDDEN, shown ? " " : "X");
m.set(F_AUTOMAGIC, automagic ? "X" : " ");
m.set(F_FINKL, finkl ? " " : "X");
m.set(F_FINKR, finkr ? " " : "X");
}
// Get mask fields
// Certified 100%
void TForm_flags::read_from(const TMask& m)
{
shown = !m.get_bool(F_HIDDEN);
enabled = !m.get_bool(F_DISABLED);
automagic = m.get_bool(F_AUTOMAGIC);
finkl = !m.get_bool(F_FINKL);
finkr = !m.get_bool(F_FINKR);
}
///////////////////////////////////////////////////////////
// TForm_item
///////////////////////////////////////////////////////////
TForm_item::TForm_item(TPrint_section* section)
: _section(section), _x(-1), _y(-1), _width(0), _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
{
strncpy(__tmp_string, s, width());
__tmp_string[_width] = '\0';
s = __tmp_string;
}
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 == "DISABLE") {
des.disable();
} else if (cmd == "ENABLE") {
des.enable();
} else if (cmd == "HIDE") {
des.hide();
} else if (cmd == "RESET") {
des.set("");
} else if (cmd == "SHOW") {
des.show();
} 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)
{
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(),&section());
}
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 = &section.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(),&section);
}
// look into sections beside ("brothers" )
for (int j = 0; j < section.subsections(); j++) {
const TPrint_section &bs=section.subsection(j)->subsection();
if (&bs!=starting_section) {
send_message_to_group(cmd,id,section.subsection(j)->subsection(),&section);
}
}
}
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(" ");
}
}
void TForm_item::print_on_sheet_row(TToken_string& tt) const
{
TString tmp(80);
tt.add(_id, idt_id - 101);
tt.add(_desc, dsc_id - 101);
tt.add(_x, _section->columnwise() ? col_id - 101 : xps_id - 101);
tt.add(_width, len_id - 101);
if (!_section->columnwise())
tt.add(_y, yps_id - 101);
tt.add(class_name(), typ_id - 101);
tt.add(shown() ? " " : "X", prn_id - 101);
tmp = example(); tt.add(tmp, frm_id - 101);
if (_section->columnwise())
{
tt.add(_ofs, spc_id -101);
tt.add(finkl() ? " " : "X", fnl_id -101);
tt.add(finkr() ? " " : "X", fnr_id -101);
tt.add(_col_head, int_id - 101);
}
}
void TForm_item::print_on(TMask& m)
{
m.set(F_CLASS, class_name());
m.set(F_ID, id());
m.set(F_KEY, key());
m.set(F_X, _x);
m.set(F_Y, _y);
m.set(F_PROMPT, _prompt);
m.set(F_WIDTH, _width);
if (_section->columnwise())
m.set(F_INTEST, _col_head);
m.set(F_HEIGHT, _height);
m.set(F_SPACES, _ofs);
_flag.print_on(m);
for (int g = 1; g <= 24; g++)
m.set(F_GROUP+g, _group[g] ? "X" : " ");
}
void TForm_item::read_from(const TMask& m)
{
_desc = m.get(F_KEY);
_x = atoi(m.get(F_X));
_y = atoi(m.get(F_Y));
_prompt = m.get(F_PROMPT);
_width = atoi(m.get(F_WIDTH));
if (_section->columnwise())
_col_head = m.get(F_INTEST);
_height = atoi(m.get(F_HEIGHT));
_id = atoi(m.get(F_ID));
_ofs = atoi(m.get(F_SPACES));
_flag.read_from(m);
_group.reset();
for (int g = 1; g <= 24; g++)
_group.set(g, m.get_bool(F_GROUP+g));
}
void TForm_item::read_from(TToken_string& s)
{
_id = s.get_int(idt_id - 101);
_desc = s.get(dsc_id - 101);
_x = _section->columnwise() ? s.get_int(col_id - 101) : s.get_int(xps_id - 101);
_width = s.get_int(len_id - 101);
if (!_section->columnwise())
_y = s.get_int(yps_id - 101);
_flag.set_shown(s.get(prn_id - 101)[0] != 'X');
if (_section->columnwise())
{
_ofs = s.get_int(spc_id - 101);
_flag.set_finkl(s.get(fnl_id - 101)[0] != 'X');
_flag.set_finkr(s.get(fnr_id - 101)[0] != 'X');
_col_head = s.get(int_id - 101);
}
set_dirty();
}
bool TForm_item::edit(TMask& m)
{
m.enable(F_CLASS, m.insert_mode());
m.reset();
if (m.insert_mode())
{
short id = 0;
for (word i = 0; i < section().fields(); i++)
{
const TForm_item& f = section().field(i);
if (f.id() > id) id = f.id();
}
_id = id+1;
}
print_on(m);
const bool godmode = form().edit_level() > 1;
m.enable_page(1, godmode);
m.enable(-7, godmode);
m.enable(F_ID, godmode);
m.enable(F_KEY,godmode);
m.enable(F_Y,!_section->columnwise());
m.enable(F_INTEST,_section->columnwise());
if (_flag.memo)
{
m.disable(F_PROMPT);
m.hide(F_PROMPT);
m.enable(F_MEMO);
m.show(F_MEMO);
m.enable(F_HEIGHT);
m.show(F_HEIGHT);
}
else
{
m.hide(F_MEMO);
m.disable(F_MEMO);
}
const bool dirty = m.run() == K_ENTER;
if (dirty)
{
read_from(m);
set_dirty();
}
return dirty;
}
const TString& TForm_item::picture() const
{
CHECK(0, "Can't get the picture of a generic form item!");
return _prompt;
}
void TForm_item::set_picture(const char*)
{
CHECK(0, "Can't set the picture of a generic form item!");
}
TToken_string& TForm_item::memo_info()
{
CHECK(0, "Can't get a memo of a generic form item!");
return TToken_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)
{
_ssec.set_subsection_above(this);
}
TForm_subsection::~TForm_subsection()
{
if (_condexpr) delete _condexpr;
}
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->_condexpr=new TExpression((const char *)_condexpr);
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)
subsection().set_subs_cond(_file_id,cond,_condexpr->string());
delete _condexpr;
}
_condexpr=new TExpression(cond,type);
}
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;
}
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();
if (uppersec && uppersec->_file_id==_file_id)
// se anche la sezione soprastante
e << uppersec->_condexpr->string() << "+" ;
e << s.line();
_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() != "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::set_body(bool showfields)
{
bool ok = FALSE;
TCursor* cur = form().cursor();
TRelation* rel = (TRelation* )form().relation();
if (!enabled()) return FALSE;
if (cur == NULL || (_file_id == -1 && _condexpr==NULL)) // ...unused
ok = _ssec.update_and_print(showfields && shown(),atnewpage());
else if (_file_id == -1 && _condexpr!=NULL) // subsection condizionale
{
if ((bool)(_section->eval_expr(*_condexpr,_file_id)))
ok = _ssec.update_and_print(showfields && shown(),atnewpage());
}
else
{
if (_condexpr) { // sottosezione di raggruppamenti su file
int i = 0;
TString group_expr((const char *)(_section->eval_expr(*_condexpr,_file_id)));
bool again=TRUE;
while (again && group_expr==(const char *)(_section->eval_expr(*_condexpr,_file_id)))
{
form().match_result(_file_id);
if (!_bigskip || i==0)
{
if (!(ok = _ssec.update_and_print(showfields && shown(),atnewpage())))
break;
_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
}
}
_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);
if (!(ok = _ssec.update_and_print(showfields && shown(),atnewpage())))
break;
_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);
} while (again);
}
_ssec.set_repeat_count(0);
}
}
return ok;
}
bool TForm_subsection::edit(TMask& m)
{
// mask con nome e bottone edit contents / annulla
TMask mu("ba2100u");
mu.set(F_CAPTION, _name);
mu.set(F_WIDTH, _width);
mu.set(F_HEIGHT, _height);
mu.set(F_X, _x);
mu.set(F_Y, _y);
mu.set_handler(F_BUT_FILE1, but_file_handler_sub);
if (_file_id != -1)
{
// set file description
form().rel_desc().set_cur_file(_file_id);
TString80 desc; desc << form().rel_desc().file_desc();
mu.set(F_FILE1, desc);
}
KEY k;
// vedere se e' nuova etc.
// gestire aggiunta / modifica menu
while ((k = mu.run()) != K_ESC)
{
if (mu.field(F_CAPTION).dirty())
_name = mu.get(F_CAPTION);
if (mu.field(F_WIDTH).dirty())
_width = mu.get_int(F_WIDTH);
if (mu.field(F_HEIGHT).dirty())
_height = mu.get_int(F_HEIGHT);
if (mu.field(F_X).dirty())
_x = mu.get_int(F_X);
if (mu.field(F_Y).dirty())
_y = mu.get_int(F_Y);
if (mu.field(F_FILE1).dirty())
{
if (mu.get(F_FILE1).empty())
_file_id = -1;
else
_file_id = form().rel_desc().file_num();
}
if (k == K_INS)
_ssec.edit(_name);
else if (k == K_DEL)
{
// remove myself
}
else if (k == K_ENTER)
break;
}
return k != K_ESC;
}
void TForm_subsection::print_on(ostream& out) const
{
out << "SEZIONE " << _name << ' ' << _width << ' ' << _height
<< ' ' << _x << ' ' << _y;
if (_file_id != -1)
out << " FILE " << _file_id;
out << "\n";
for (word i = 0; i < _ssec.fields(); i++)
out << _ssec.field(i);
out << "\nEND" << "\n";
}
// @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::edit(TMask& m)
{
const bool godmode = form().edit_level() > 1;
m.enable(F_PROMPT, godmode ? TRUE : (_field.items()==0));
return TForm_item::edit(m);
}
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);
}
void TForm_string::print_body(ostream& out) const
{
TForm_item::print_body(out);
if (_picture.not_empty())
out << " PICTURE \"" << _picture << "\"" << endl;
for (int i = 0; i < _field.items(); i++)
out << " FIELD " << field(i) << endl;
}
bool TForm_string::read_from(const TRectype& prof)
{
bool changed = TForm_item::read_from(prof);
const TString& pict = prof.get("PICT");
if (_picture != pict)
{
_picture = pict;
changed = TRUE;
}
if (has_memo())
{
const TString& m = prof.get("TESTO");
if (_memo != m)
{
_memo = m;
changed = TRUE;
}
}
return changed;
}
void TForm_string::print_on(TToken_string& row)
{
TForm_item::print_on(row);
if (_field.items() && form().edit_level() > 1)
row << '|' << field(0);
}
void TForm_string::print_on(TRectype& prof)
{
TForm_item::print_on(prof);
prof.put("PICT", _picture);
if (has_memo())
{
prof.put("TESTO", _memo);
}
}
void TForm_string::print_on(TMask& m)
{
TForm_item::print_on(m);
for (int i = 0; i < _field.items(); i++)
put_fieldref(field(i), m.field(i == 0 ? F_FIELDREF1 : F_FIELDREF2));
m.set(F_PICTURE, _picture);
m.set(F_MEMO, _memo);
TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
s.reset();
if (_message.items() > 0)
{
TToken_string& row = s.row(0);
row = " | ";
row.add(message(0));
}
}
void TForm_string::read_from(const TMask& m)
{
TForm_item::read_from(m);
_picture = m.get(F_PICTURE);
_memo = m.get(F_MEMO);
for (int i = 0; i < 2; i++)
{
const TString& f = m.get(i == 0 ? F_FIELDREF1 : F_FIELDREF2);
if (f.not_empty())
{
TFieldref* fr = (TFieldref*)_field.objptr(i);
if (fr == NULL)
{
fr = new TFieldref(f, 0);
_field.add(fr, i);
}
*fr = f;
}
else
_field.destroy(i);
}
TSheet_field& f = (TSheet_field&)m.field(F_ITEMS);
TToken_string& msg = f.row(0);
if (msg.empty_items())
_message.destroy(0);
else
_message.add(msg.get(2), 0);
}
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)
{
/*
const int w = width();
TParagraph_string p(s, w);
int i = _prompt.not_empty() ? 1 : 0;
for (; (s = p.get()) != NULL && i < h; i++)
string_at(x(), _y+i, s);
_effective_height = i;
*/
const int w = width();
int plen=_prompt.len();
TString prompt(plen,'-');
TParagraph_string p(prompt << s, w);
#ifdef DBG
if (plen>0 && *s)
yesno_box("Nei form la stampa di un item su pi<70> righe con prompt ora non pone pi<70> il prompt isolato sulla prima riga ma allinea a sinistra del prompt ");
#endif
for (int i=0; (s = p.get()) != NULL && i < h; i++)
{
string_at(x()+plen, _y+i, s+plen);
}
_effective_height = i;
}
else
string_at(-1, _y, s);
}
void TForm_string::apply_format(TString& s, const TString& p) const
{
TString tmp(s);
if (!p.blank())
{
TToken_string delim(4, ','); // Stringa con i due delimitatori
const char* pic = p; // Picture senza delimitatori
if (pic[0] == '(') // Se ci sono i delimitatori ...
{
const int bra = p.find(')');
if (bra > 0) // ... cerca la parentesi chiusa
{
delim = p.sub(1, bra); // memorizza delimitatori
pic += bra+1; // toglili dalla picture
}
}
if (class_name() == "DATA" && 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
{
TString s;
TForm_item::update();
// esegue i messaggi
const int n = (_message.objptr(1) != NULL && s.empty() ? 1 : 0);
do_message(n);
// prende il campo e lo stampa
s = get();
apply_format(s, picture());
put_paragraph(s);
}
return TRUE;
}
const char* TForm_string::example() const
{
TString prova("XXXXXXXXXXXXXXXXXXXXXXXXXX");
apply_format(prova, picture());
const int w = width();
if (prova.size() > w && w > 0) prova.cut(w);
return strcpy(__tmp_string, prova);
}
///////////////////////////////////////////////////////////
// TForm_number
///////////////////////////////////////////////////////////
class TForm_number : public TForm_string
{
void apply_format(real& r, TString& s) const;
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:
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 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
}
bool TForm_number::update()
{
if (read()) // valuta il campo
{
TForm_item::update();
const int nm = (_message.objptr(1) != NULL ? 1 : 0);
do_message(nm);
real n(get());
n.round(decimals());
if (!n.is_zero())
{
TString s;
real n(get());
apply_format(n,s);
put_paragraph(s);
// do_message();
}
else
{
// const int nm = (_message.objptr(1) != NULL ? 1 : 0);
// do_message(nm);
}
}
return TRUE;
}
void TForm_number::apply_format(real& n , TString& s) const
{
if (!picture().blank())
{
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 s = n.string();
}
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
{
real n("123456789120.00"); n.round(2);
TString s;
apply_format(n,s);
return strcpy(__tmp_string, s);
}
///////////////////////////////////////////////////////////
// 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(d.string());
return strcpy(__tmp_string, 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:
TForm_item* parse_item(const TString& s);
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
{
protected:
virtual const char* class_name() const { return "FIGURA"; }
virtual bool update();
public:
TForm_picture(TGraphic_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::update()
{
const bool ok = _prompt.not_empty();
if (ok)
{
TString80 i;
i << "i{" << _prompt << ',' << _x << ',' << _y << ','
<< (_x+width()-1) << ',' << (_y+height()-1) << '}';
((TGraphic_section&)section()).append(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;
}
}
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::parse_item(const TString& s)
{
if (s == "FI")
return new TForm_picture(this);
else if (s == "LI")
return new TForm_line(this);
else if (s == "BO")
return new TForm_box(this);
error_box("Campo di stampa non ammesso per lo sfondo: %s", (const char*)s);
return NULL;
}
bool TGraphic_section::update()
{
_back = "";
const bool ok = TPrint_section::update();
printer().setbackground(_back);
return ok;
}
///////////////////////////////////////////////////////////
// TPrint_section
///////////////////////////////////////////////////////////
HIDDEN bool font_handler(TMask_field& f, KEY key)
{
if (key == K_SPACE)
{
main_app().begin_wait();
const char* family = f.get();
const int MAXSIZES = 16;
long sizes[MAXSIZES];
BOOLEAN scalable;
const int num_sizes = (int)xvt_fmap_get_family_sizes(printer().get_printrcd(),
(char*)family, sizes, &scalable, MAXSIZES);
TToken_string pn1(80), pn2(80);
if (scalable)
{
for (int i = 4; i <= 32; i++)
{
pn1.add(i);
pn2.add(i);
}
}
else
{
if (num_sizes > 0)
{
for (int i = 0; i < num_sizes; i++)
pn1.add(sizes[i]);
}
else pn1.add(printer().get_char_size());
pn2 = pn1;
}
TList_field& lst = (TList_field&)f.mask().field(F_SIZE);
lst.replace_items(pn1, pn2);
lst.set(format("%d",printer().get_char_size()));
main_app().end_wait();
}
return TRUE;
}
TMask* TPrint_section::_msk = NULL;
word TPrint_section::height() const
{
if (_height<0)
return printer().formlen()+_height;
else
return _height;
}
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();
fileno=fileno==0 ? defaultfile_id: 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;
}
}
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);
}
inline 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;
_columnwise = ps._columnwise; _temp = ps._temp; _form = ps._form;
_sec_type = ps._sec_type; _page_type = ps._page_type; _upsection = ps._upsection;
_item = ps._item; _repeat_count = ps._repeat_count;
_subsections=ps._subsections;
for (int i = 0; i < MAXCOLUMNS; i++) _tab[i] = ps._tab[i];
return ps;
}
TPrintrow& TPrint_section::row(int num)
{
TPrintrow* pr = (TPrintrow*)objptr(num);
if (pr == NULL)
{
pr = new TPrintrow;
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)
{
// compute column offset
_nfld = 0;
_tab[0] = 2;
short maxcolreached = 0;
for (word i = 0; i < fields(); i++)
{
if (field(i).shown())
{
CHECKD (field(i)._x < MAXCOLUMNS, "Colonna ammessa e non concessa: ", field(i)._x);
_tab[field(i)._x] = field(i)._width + 1; // one is for separation
if (field(i)._x > maxcolreached) maxcolreached = field(i)._x;
_nfld++;
}
}
// cumulate offsets
int last = 0;
for (i = 1; i <= (word)maxcolreached; i++)
{
if (_tab[i - 1] != -1)
last = i - 1;
if (_tab[i] != -1)
_tab[i] += _tab[last];
}
}
// 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)->height();
h+=subsection(0)->subsection().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)
{
if (s == "ST")
return new TForm_string(this);
if (s == "NU")
return new TForm_number(this);
if (s == "DA")
return new TForm_date(this);
if (s == "LI")
return new TForm_list(this);
if (s == "GR")
return new TForm_group(this);
if (s == "SE")
return new TForm_subsection(this);
yesnofatal_box("Campo di stampa non ammesso per la sezione di stampa: %s", (const char*)s);
return NULL;
}
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 = last(); i >= 0; i--)
row(i).reset();
}
// Aggiorna tutti i campi
bool TPrint_section::update()
{
bool ok = TRUE;
reset();
for (word i = 0; i < fields(); i++)
{
if (strcmp(field(i).class_name(),"SEZIONE")!=0)
{
const bool esito = field(i).update();
if (!esito) ok = FALSE;
}
}
return ok;
}
// @doc EXTERNAL
// @mfunc Legge dal record <p rec> altezza e offset prima colonna della sezione
//
// @rdesc Ritorna se i valori letti hanno modificato quelli attuali
bool TPrint_section::read_from(
const TRectype& prof) // @parm Record dal quela leggere i valori
// @comm Nel caso il record non sia LF_RFORM viene dato un messaggio di <f CHECK>.
{
CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
bool changed = FALSE;
const word h = (word)prof.get_int("HGT");
const word l = (word)prof.get_int("LEN");
const word y = (word)prof.get_int("Y");
if (_height != h)
{
_height = h;
changed = TRUE;
}
if (_ofspc != l)
{
_ofspc = l;
changed = TRUE;
}
if (_ofsvr != y)
{
_ofsvr = y;
changed = TRUE;
}
return changed;
}
void TPrint_section::print_on(TRectype& prof)
{
CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
prof.put("ID", 0);
prof.put("X", 0);
prof.put("Y", _ofsvr);
prof.put("LEN", _ofspc);
prof.put("HGT", _height);
}
typedef struct {
char name_1[80]; // Fontname old
char name_2[80]; // Fontname new
int size_1; // size (height) of old font
int size_2; // size (height) of new font
real ratio; // ratio (width_old_font/width_new_font)
} s_data;
BOOLEAN XVT_CALLCONV1 wpr (long data)
{
s_data* st =(s_data*)data;
WINDOW prwin = xvt_print_create_win(printer().get_printrcd(),"");
long width_old,width_new;
TString spc(100);
spc.fill('m');
xvt_set_font(prwin,st->name_1, XVT_FS_NONE, st->size_1);
width_old = xvt_dwin_get_text_width(prwin,(char*)(const char*)spc, 100);
xvt_set_font(prwin,st->name_2, XVT_FS_NONE, st->size_2);
width_new = xvt_dwin_get_text_width(prwin,(char*)(const char*)spc, 100);
st->ratio = (double)width_old / (double)width_new;
xvt_vobj_destroy(prwin);
return FALSE;
}
bool TPrint_section::special_field_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE && _special_mask != NULL)
_special_mask->run();
return TRUE;
}
bool TPrint_section::repos_fields(const char* name, int size)
{
TPrint_section& ps = ::section();
bool rt = FALSE;
if (ps.form().fontname() != name ||
ps.form().fontsize() != size)
{
if (!ps.form().dirty()) ps.form().set_dirty();
ps.set_dirty();
if (yesno_box("E' stato cambiato il font o la dimensione del carattere.\nSi desidera aggiornare le coordinate dei campi?"))
{
rt = TRUE;
s_data prm;
prm.size_1=ps.form().fontsize();
strcpy(prm.name_1,ps.form().fontname());
prm.size_2=size;
strcpy(prm.name_2,name);
prm.ratio = 1.0;
// Next 3 lines may be changed
xvt_print_open();
xvt_print_start_thread (wpr, (long)&prm);
xvt_print_close();
if (ps.form().edit_level() > 1)
{
TMask rm("Rapporto tra i caratteri", 1, 30, 4);
rm.add_number(DLG_USER, 0, "Rapporto ", 1, 1, 8, "", 4);
rm.add_button(DLG_OK, 0, "Conferma", -12, -1, 10, 2);
rm.add_button(DLG_CANCEL, 0, "Annulla", -22, -1, 10, 2);
real ratio = prm.ratio;
rm.set(DLG_USER, ratio);
if (rm.run() == K_ENTER)
{
ratio = rm.get_real(DLG_USER);
prm.ratio = ratio;
}
}
const char sechar[4] = { 'B', 'F', 'G', 'H' };
for (int sn = 0; sn < 4 ; sn++)
{
const char sc = sechar[sn];
for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
{
TPrint_section* sec = ps.form().exist(sc, pt);
if (sec != NULL && !sec->columnwise())
{
sec->set_dirty();
for (word i = 0; i < sec->fields() ; i++)
{
TForm_item& fi = sec->field(i);
short value = fi.x();
if (value > 0 && (prm.ratio != 1.0))
{
real x_pos;
x_pos = value * prm.ratio;
x_pos.round();
fi.set_x((short)x_pos.integer());
fi.set_dirty();
}
}
}
}
}
}
ps.form().fontname() = name;
ps.form().fontsize() = size;
// Aggiorna lo spreadsheet
TSheet_field& ms = (TSheet_field&)ps._msk->field(F_FIELDS);
TToken_string tt(128);
const word flds = ps.fields();
for (word i = 0; i < flds; i++)
{
TForm_item& f = ps.field(i);
ps.field(i).print_on_sheet_row(tt);
ms.row(i) = tt;
}
}
return rt;
}
// handlers for section editing
bool TPrint_section::detail_field_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
if (_cur_form && TString(_cur_form->section_mask()).left(2) == "ba")
{
TString80 name(_msk->get(F_FONT));
int size = _msk->get_int(F_SIZE);
repos_fields(name, size);
}
bool consider_sheet_mask = FALSE;
if (f.mask().is_running()) // Se la maschera di editing dello sheet e' running
consider_sheet_mask = TRUE; // allora deve tener conto anche di essa per l'I/O
// to avoid kasinations with recursion
TPrint_section& section = ::section();
TSheet_field& ms = *f.mask().get_sheet();
int field = ms.selected();
TToken_string& tt = ms.row(field);
TToken_string tt_mask(tt);
if (consider_sheet_mask)
{
TMask& msheet = f.mask();
tt_mask.add(msheet.get(idt_id), idt_id - 101);
tt_mask.add(msheet.get(dsc_id), dsc_id - 101);
tt_mask.add(msheet.get(len_id), len_id - 101);
tt_mask.add(msheet.get(prn_id), prn_id - 101);
if (section.columnwise())
{
tt_mask.add(msheet.get(col_id), col_id - 101);
tt_mask.add(msheet.get(spc_id), spc_id -101);
tt_mask.add(msheet.get(int_id), int_id - 101);
tt_mask.add(msheet.get(fnl_id), fnl_id -101);
tt_mask.add(msheet.get(fnr_id), fnr_id -101);
}
else
{
tt_mask.add(msheet.get(xps_id), xps_id - 101);
tt_mask.add(msheet.get(yps_id), yps_id - 101);
}
}
TMask msk("ba2100f");
msk.set_handler(F_DFORMAT, dateformat_handler);
msk.set_handler(F_DYEAR, dateformat_handler);
msk.set_handler(F_DMONTH, dateformat_handler);
msk.set_handler(F_DDAY, dateformat_handler);
msk.set_handler(F_DSEP, dateformat_handler);
msk.set_handler(F_FILE1, but_file_handler);
msk.set_handler(F_FIELD1, but_field_handler);
msk.set_handler(F_FROM1, from_handler);
msk.set_handler(F_TO1, to_handler);
msk.set_handler(F_FILE2, but_file_handler);
msk.set_handler(F_FIELD2, but_field_handler);
msk.set_handler(F_FROM2, from_handler);
msk.set_handler(F_TO2, to_handler);
msk.set_handler(F_PICTURE,fmt_handler);
// TBI set_mode etc, vedi sotto
// gna'
TForm_item& fi = section.field(field);
msk.enable(F_OPTIONS, fi.special_items() > 3);
msk.enable(F_SPACES, section.columnwise());
msk.enable(F_FINKL, section.columnwise());
msk.enable(F_FINKR, section.columnwise());
// build option mask
if (fi.special_items() > 3)
{
msk.set_handler(F_OPTIONS, special_field_handler);
CHECK(fi.special_items() < 18, "Quanti special! Non ho nessuna voglia di "
" farti una maschera a piu' pagine. Ripensaci e riprova");
_special_mask = new TMask("Variabili personalizzate", 1, 78, fi.special_items() + 3);
_special_mask->add_button(DLG_OK, 0, "", -12, -1, 10, 2);
_special_mask->add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
fi.specials().restart();
for (int k = 0; k < fi.special_items(); k++)
{
THash_object* ho = fi.specials().get_hashobj();
TToken_string& tt = (TToken_string&)(ho->obj());
TString type = tt.get(0);
TString val = tt.get(1);
TToken_string des(tt.get(2),'/');
TString prompt(des.get(0));
if (type == "STRINGA")
{
_special_mask->add_string(101+k, 0, prompt, 1, k+1, des.get_int(1),"");
_special_mask->set(101+k, val);
}
else if (type == "NUMERO")
{
_special_mask->add_number(101+k, 0, prompt, 1, k+1, des.get_int(1),"",des.get_int(2));
_special_mask->set(101+k, val);
}
else if (type == "LISTA")
{
TToken_string codes(128);
TToken_string value(128);
for (int jj = 2; jj < des.items(); jj++)
{
CHECK (jj < (des.items() - 1), "AAARGH! 'Sta LISTA special e' fatta male");
TString t1(des.get(jj++));
TString t2(des.get(jj));
codes.add(t1);
value.add(t2);
}
_special_mask->add_list(101+k, 0, prompt, 1, k+1, des.get_int(1), "", codes, value);
_special_mask->set(101+k, val);
}
else if (type == "BOOLEAN")
{
_special_mask->add_boolean(101+k, 0, prompt, 1, k+1);
_special_mask->set(101+k, val);
}
else if (type == "DATA")
{
_special_mask->add_date(101+k, 0, prompt, 1, k+1);
_special_mask->set(101+k, val);
}
}
}
if (consider_sheet_mask)
fi.read_from(tt_mask);
else
fi.read_from(tt);
fi.edit(msk);
// check specials
if (_special_mask != NULL)
{
if (_special_mask->last_key() == K_ENTER)
{
fi.specials().restart();
for (int k = 0; k < fi.special_items(); k++)
{
THash_object* ho = fi.specials().get_hashobj();
TToken_string& tt = (TToken_string&)(ho->obj());
TString val = tt.get(1);
TString nvl = _special_mask->get(k + 101);
if (nvl != val)
{
tt.add(nvl, 1);
if (tt.items() == 3) tt.add("X");
fi.set_dirty();
}
}
}
if (_special_mask != NULL)
{
delete _special_mask;
_special_mask = NULL;
}
}
if (!consider_sheet_mask)
fi.print_on_sheet_row(tt);
else
{
TMask& msheet = f.mask();
fi.print_on_sheet_row(tt_mask);
msheet.set(idt_id, tt_mask.get_int(idt_id - 101));
msheet.set(dsc_id, tt_mask.get(dsc_id - 101));
msheet.set(len_id, tt_mask.get_int(len_id - 101));
msheet.set(prn_id, tt_mask.get(prn_id - 101));
msheet.set(frm_id, fi.example());
if (section.columnwise())
{
msheet.set(spc_id, tt_mask.get_int(spc_id - 101));
msheet.set(col_id, tt_mask.get_int(col_id - 101));
msheet.set(int_id, tt_mask.get(int_id - 101));
msheet.set(fnl_id, tt_mask.get(fnl_id - 101));
msheet.set(fnr_id, tt_mask.get(fnr_id - 101));
}
else
{
msheet.set(xps_id, tt_mask.get_int(xps_id - 101));
msheet.set(yps_id, tt_mask.get_int(yps_id - 101));
}
}
ms.force_update();
_cur_sect = &section;
}
return TRUE;
}
bool TPrint_section::detail_field_notify (TSheet_field& s, int r, KEY k)
{
TPrint_section& sec = ::section();
if (k == K_DEL || k == K_INS)
{
if (::form().edit_level() <= 1)
return FALSE;
if (k == K_DEL)
{
// elimina campo
sec.destroy_field(r);
sec.set_dirty();
}
}
else if (k == (K_INS + K_CTRL))
{
// new field: set defaults and create field
TForm_string* f = new TForm_string(&sec);
sec.insert_field(r, f);
TToken_string& tt = s.row(r);
f->print_on_sheet_row(tt);
tt.add("Nuovo campo", sec.columnwise() ? int_id : dsc_id);
if (sec.columnwise()) tt.add(r+1, col_id - 101);
s.force_update();
sec.set_dirty();
}
else if (k == K_ENTER)
{
// modify field
TForm_item* fld = &sec.field(r);
TToken_string& tt = s.row(r);
if (sec.columnwise() && ((word)tt.get_int(col_id - 101) <= 0 ||
(word)tt.get_int(col_id - 101) > sec.fields()))
{
warning_box("Numero di colonna non accettabile (deve essere da 1 a %u)", sec.fields());
return FALSE;
}
// ??? type changed ???
if (strcmp(tt.get(typ_id - 101), fld->class_name()) != 0)
{
// so'ccazzi: crea nuovo campo del tipo dato e
// copia gli special (e il resto)
TString typ(tt.get(typ_id - 101));
TForm_item* fff = NULL;
if (typ == "NUMERO")
fff = new TForm_number(&sec);
else if (typ == "STRINGA")
fff = new TForm_string(&sec);
else if (typ == "DATA")
fff = new TForm_date(&sec);
else if (typ == "LISTA")
fff = new TForm_list(&sec);
else if (typ == "GRUPPO")
fff = new TForm_group(&sec);
else if (typ == "LINEA")
fff = new TForm_line((TGraphic_section*)&sec);
else if (typ == "BOX")
fff = new TForm_box((TGraphic_section*)&sec);
else if (typ == "FIGURA")
fff = new TForm_picture((TGraphic_section*)&sec);
// copia SPECIALS
TAssoc_array& aa = fld->specials();
TAssoc_array& bb = fff->specials();
THash_object* oo = NULL;
aa.restart();
for (int i = 0; i < aa.items(); i++)
{
oo = aa.get_hashobj();
bb.add(oo->key(), oo->obj());
}
sec.change_field(r, fld = fff);
fld->set_dirty();
}
// modifica valori
fld->read_from(tt);
}
else
if (k == K_SPACE)
{
if (_cur_form && TString(_cur_form->section_mask()).left(2) == "ba")
{
TString80 name(s.mask().get(F_FONT));
int size = s.mask().get_int(F_SIZE);
if (repos_fields(name,size))
s.force_update();
}
}
return TRUE;
}
// @doc EXTERNAL
// @mfunc Esegue l'edit della sezione di stampa
//
// @rdesc Ritorna TRUE se e' stata modificata effettivamente
bool TPrint_section::edit(
const char* title) // @parm Titolo della maschera di edit
{
const bool is_ba_editor = TString(_form->section_mask()).left(2) == "ba";
bool nstd_dirty = FALSE;
bool font_found = FALSE;
_cur_form = _form;
_cur_sect = this;
if (!_upsection)
{
TMask m(_form->section_mask());
_msk = &m;
m.set_caption(title);
m.set(F_HEIGHT, _height);
m.set(F_OFSPC, _ofspc);
m.set(F_OFSVR, _ofsvr);
if (is_ba_editor)
{
m.set(F_X, form().offset_x());
m.set(F_Y, form().offset_y());
m.set(F_CTP, format("%c",form().char_to_pos()));
m.set(F_IPX, form().ipx());
m.set(F_IPY, form().ipy());
m.set(F_FPX, form().fpx());
m.set(F_FLEN, printer().formlen());
}
else
_form->pre_edit_checks(m,_cur_sect);
TSheet_field& ms = (TSheet_field&)m.field(F_FIELDS);
m.hide(F_OFSVR);//Offset verticale, per _columnwise. Non ancora usato.
if (_columnwise)
{
m.disable(F_HEIGHT);
ms.delete_column(xps_id); ms.sheet_mask().hide(xps_id);
ms.delete_column(yps_id); ms.sheet_mask().hide(yps_id);
}
else
{
m.hide(F_OFSPC);
ms.delete_column(int_id); ms.sheet_mask().hide(int_id);
ms.delete_column(col_id); ms.sheet_mask().hide(col_id);
ms.delete_column(spc_id); ms.sheet_mask().hide(spc_id);
ms.delete_column(fnl_id); ms.sheet_mask().hide(fnl_id);
ms.delete_column(fnr_id); ms.sheet_mask().hide(fnr_id);
}
ms.enable_column(frm_id - 101, FALSE);
if (form().edit_level() <= 1)
{
ms.enable_column(idt_id - 101, FALSE);
ms.enable_column(typ_id - 101, FALSE);
}
// handlers
ms.set_notify(detail_field_notify);
ms.sheet_mask().set_handler(100, detail_field_handler);
if (_form->edit_level()<=1) ms.sheet_mask().disable(DLG_DELREC);
TToken_string tt(128);
const word flds = fields();
// fill sheet
for (word i = 0; i < flds; i++)
{
TForm_item& f = field(i);
field(i).print_on_sheet_row(tt);
// TBI colorare se specials (e vedi se colorare solo se non standard)
ms.row(-1) = tt;
}
if (is_ba_editor)
{
const int MAX_FAMILIES = 128;
char* family[MAX_FAMILIES];
const int num_families = (int)xvt_fmap_get_families(printer().get_printrcd(), family, MAX_FAMILIES);
TToken_string pn1(256), pn2(256);
for (int i = 0; i < num_families; i++)
{
pn1.add(family[i]);
pn2.add(family[i]);
if (!font_found)
if (form().fontname() == family[i]) font_found = TRUE;
xvt_mem_free(family[i]);
}
TList_field& lst = (TList_field&)m.field(F_FONT);
if (!font_found)
{
warning_box("Il font %s non esiste per la stampante di default.",(const char*) form().fontname());
pn1.add(form().fontname());
pn2.add(form().fontname());
}
lst.replace_items(pn1, pn2);
lst.set(form().fontname());
printer().set_char_size(form().fontsize());
m.set_handler(F_FONT,font_handler);
}
if(_columnwise)
{
bool ok = FALSE;
while (m.run() != K_ESC)
{
TSheet_field& ms = (TSheet_field&)m.field(F_FIELDS);
const int items = ms.items();
for (int i=0; i<items && !ok; i++)
{
TToken_string& tt = ms.row(i);
ok = tt.get_char(prn_id - 101)==' ';
}
if (i==items && !ok) error_box("Selezionare almeno una colonna stampabile.");
if (ok) break;
}
_msk = NULL;
if (!ok) return FALSE;
}
else
if (m.run() == K_ESC)
{
// Se premo Annulla ed il form e' nuovo lo devo cancellare.
if (form()._isnew)
{
TLocalisamfile frm(LF_FORM);
frm.zero();
frm.put("TIPOPROF",form().name());
frm.put("CODPROF",form().code());
frm.remove();
}
_msk = NULL;
return FALSE;
}
bool dirty = m.dirty() != 0;
if (dirty)
{
// Controlli da fare sempre a prescindere dal form editor
if (_height != (word)m.get_int(F_HEIGHT) )
{
_height = m.get_int(F_HEIGHT);
_dirty=TRUE;
}
if (_ofspc != (word)m.get_int(F_OFSPC) )
{
_ofspc = m.get_int(F_OFSPC);
_dirty=TRUE;
}
if (_ofsvr != (word)m.get_int(F_OFSVR) )
{
_ofsvr = m.get_int(F_OFSVR);
_dirty=TRUE;
}
if (is_ba_editor)
{ // Controlli solo se il form editor e' quello base
if (m.get_int(F_X) != form().offset_x() || m.get_int(F_Y) != form().offset_y())
{
form().offset_x() = m.get_int(F_X);
form().offset_y() = m.get_int(F_Y);
form().set_dirty();
_dirty = TRUE;
}
if (m.get(F_CTP)[0] != form().char_to_pos() ||
m.get_int(F_IPX) != form().ipx() ||
m.get_int(F_IPY) != form().ipy() ||
m.get_int(F_IPX) != form().fpx())
{
form().char_to_pos() = m.get(F_CTP)[0];
form().ipx() = m.get_int(F_IPX);
form().ipy() = m.get_int(F_IPY);
form().fpx() = m.get_int(F_FPX);
_dirty = TRUE;
}
TString80 name(m.get(F_FONT));
int size = m.get_int(F_SIZE);
repos_fields(name,size);
} else // controlli se l'editor non e' quello base
nstd_dirty = _form->post_edit_checks(m,_cur_sect);
}
_msk = NULL;
}
if (is_ba_editor)
if (form()._isnew || (_dirty && yesno_box("Dati generali modificati. Salvare?")))
{
TLocalisamfile frm(LF_FORM);
frm.zero();
frm.put("TIPOPROF",form().name());
frm.put("CODPROF",form().code());
if (frm.read(_isequal,_lock) == NOERR)
{
frm.put("OFFY",form().offset_y());
frm.put("OFFX",form().offset_x());
frm.put("FONTNAME",form().fontname());
frm.put("FONTSIZE",form().fontsize());
frm.put("CTP",form().char_to_pos());
frm.put("IPX", form().ipx());
frm.put("IPY", form().ipy());
frm.put("FPX", form().fpx());
frm.rewrite();
_dirty = FALSE;
}
}
if (!_dirty)
for (word j = 0; j < fields(); j++)
_dirty |= field(j).dirty();
set_dirty(_dirty);
return (_dirty || nstd_dirty);
}
void TPrint_section::print_on(ostream& out) const
{
out << ' ';
switch (page_type())
{
case even_page:
out << "EVEN"; break;
case first_page:
out << "FIRST"; break;
case last_page:
out << "LAST"; break;
default:
out << "ODD"; break;
}
out << ' ' << _height;
if (_columnwise) out << " COLUMNWISE";
out << endl << endl;
for(word i = 0; i < fields(); i++)
if (!field(i).temp()) out << field(i);
}
TForm_item& TPrint_section::find_field(short id) const
{
TForm_item * f = find_field_everywhere(id,this);
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)->subsection();
if (&bs!=starting_section) {
f=subsection(j)->subsection().find_field_everywhere(id,this);
if (f)
return f;
}
}
return NULL;
}
TForm_item& TPrint_section::find_field(const char *sec_name) const
{
TForm_item * f = find_field_everywhere(sec_name,this);
if (f) return *f;
yesnofatal_box("Can't find item with id %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)->subsection().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());
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::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_item& 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 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 (strcmp(fi.class_name(), "SEZIONE") == 0)
{
TPrint_section& ps = ((TForm_subsection&)fi).subsection();
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 (strcmp(fi.class_name(), "SEZIONE") == 0)
{
TPrint_section& ps = ((TForm_subsection&)fi).subsection();
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 corrente!!!
// @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(TRUE);
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)
//
bool TPrint_section::update_and_print(bool show_fields, bool new_page)
{
bool ok=TRUE;
TPrinter& pr = printer();
word last_printed_row=0;
reset();
if (show_fields
&& pr.current_row() > pr.headersize()+1
&& new_page)
{
pr.formfeed();
}
for (word i = 0; i < fields(); i++)
{
if (strcmp(field(i).class_name(),"SEZIONE")!=0)
{ // compose rows using "simple" fields
const bool esito = field(i).update();
if (!esito) ok = FALSE;
} else
{
TForm_subsection & ss=(TForm_subsection & )field(i);
int last_hpos=min(word(field(i).y()-1), height());
// found a subsection:print preceeding rows
// preceeding rows are all section rows which have Y coord <= than subsection's Y
if (show_fields && pr.current_row() > pr.headersize()+1)
{
if (word(last_hpos+ss.height()) > pr.rows_left())
pr.formfeed();
}
for (word j = last_printed_row; show_fields && j < (word)last_hpos ;j++)
{
pr.print(row(j));
}
last_printed_row=j;
// process subsection
if (ss.enabled())
ss.set_body(show_fields) ;
}
}
if (show_fields &&
last_printed_row< height() &&
pr.current_row() > pr.headersize()+1)
{
if (height()-last_printed_row> pr.rows_left())
pr.formfeed();
}
for (word j = last_printed_row; show_fields && j < height() ;j++)
{
pr.print(row(j));
}
return ok;
}
// @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)
{
const word page = form().page(p);
form().set_background(page, TRUE);
form().set_header(page, TRUE);
form().set_footer(page, FALSE);
}
void TForm::footer_handler(TPrinter& p)
{
const word page = form().page(p);
form().set_footer(page, TRUE);
if (page)
form().set_header(page+1, FALSE);
}
// @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 pagian corrente da stampare
// (chiam <mf TPrinter::getcurrentepage>).
word TForm::page(
const TPrinter& p) const // @parm Operazione corrente di stampa
{
return _lastpage ? 0 : p.getcurrentpage();
}
// @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");
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
/*
char defPrinter[80];
char szDevice[50];
// get default printer driver
GetProfileString ("windows", "device", ",,,", defPrinter, sizeof(defPrinter));
TToken_string pdev (defPrinter, ',');
GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice));
pdev.add(szDevice);
device = pdev.get(2);
device = device.left(4); //Legge solo LPTx...
*/
#else
TString device(printer.printername());
FILE* lpt = fopen(device,"w");
if (lpt == NULL)
fatal_box("Impossibile aprire il device %s.",device);
#endif
// _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";
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
SpoolRow((char *) (const char *) str_pos, str_pos.len());
#else
fprintf(lpt,"%s",(const char*) str_pos);
fflush(lpt); // Salta le righe...
fclose(lpt);
#endif
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
{
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
SpoolRow((char *)(const char *) str_pos, str_pos.len());
#else
lpt = fopen(device,"w");
if (lpt == NULL) fatal_box("Impossibile aprire il device %s.",device);
// fprintf(lpt,"%s",(const char*) bspc);
fprintf(lpt,"%s\r",(const char*) str_pos);
fflush(lpt);
fclose(lpt);
#endif
} while (m.run() == K_ESC); // cicla sulla stampa posizionamento...
/* const int h = height(odd_page);
str_pos.cut(0);
for (i=0; i < h; i++) str_pos << "\n";
lpt = fopen(device,"w");
if (lpt == NULL) fatal_box("Non rieso ad aprire il device %s.",device);
fprintf(lpt, "%s", (const char*) str_pos); // Salta tante righe quanto e' lungo il form standard
fclose (lpt); */
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()) 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 pgaina (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();
const word items = body->fields();
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())
continue;
TForm_string* s = new TForm_string(header);
s->id() = -1;
s->set_x(fi.x());
s->y() = y;
s->set_prompt(fi.col_head());
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;
}
}
}
}
*/
// @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());
}
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, (const char *)rval); // 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.put_paragraph(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.put_paragraph(dat);
}
} else {
TForm_item &fi= cf.find_field(fld);
fi.put_paragraph(dat);
}
}
}
}
delete file;
return (TRUE);
// fine _ISAMREAD
} else 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);
cf.put_paragraph(valore);
}
return (TRUE);
} // fine _TABLEREAD
else 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);
const int width = cf.width();
valore = cf.get();
TString clear(width);
TString picture(cf.picture());
clear.spaces();
int i= 2;
short save_x = cf.x();
short save_y = cf.y();
short save_height = cf.height();
cf.height() = 2; // Solo temporaneamente per far si' che stampi alla giusta posizione
cf.set(clear);
cf.put_paragraph(clear);
while (i<s.items()) { // Calcola la nuova posizione
TString align(s.get());
if (align[0]=='!') align.ltrim(1);
if (align== "TOP") cf.y()= fi.y();
if (align== "MIDDLE") cf.y()= fi.y()+ fi.effective_height()/2;
if (align== "BOTTOM") cf.y()= fi.y()+ fi.effective_height()-1;
if (align== "LEFT") cf.set_x(fi.x());
if (align== "RIGHT") cf.set_x(fi.x()+ fi.width());
i++;
}
real x(valore);
if (x.is_real(valore)) // se e' un numero controlla che non sia uguale 0
{
if (x != 0.0)
valore = x.string(picture);
else
valore = "";
}
// altrimenti stampa la stringa cosi' com'e'
cf.set(valore);
cf.put_paragraph(valore);
cf.y() = save_y;
cf.set_x(save_x);
cf.height() = save_height;
return (TRUE);
} // fine _ALIGN
else if (code== "_PAGENO") // Messaggio per stampare il numero di pagina corrente
{
TString16 pg; pg << int(printer().getcurrentpage() );
//cf.put_paragraph(pg);
cf.set(pg);
return (TRUE);
}
else if (code== "_TODAY")// Messaggio per stampare la data di oggi
{
TString16 dt(TDate(TODAY).string());
cf.set(dt);
//cf.put_paragraph(pg);
return (TRUE);
}
else if (code== "_NUMEXPR" || code== "_STREXPR") {
// Messaggio per la valutazione di espressioni numeriche e stringhe
TExpression rval(s.get(),code[1]=='N' ? _numexpr:_strexpr,TRUE);
cf.section().eval_expr(rval);
const char *res=(const char *)rval;
if (!rval.error())
cf.set(res);
return (TRUE);
}
else 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 FALSE;
}
void TForm::print_on(ostream& out) const
{
main_app().begin_wait();
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;
main_app().end_wait();
}
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()
{
_relation= NULL;
_cursor= NULL;
_rel_desc= NULL;
_isnew= FALSE;
_fontname= "Roman 17cpi";
_fontsize= 12;
_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;
}
// @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;
main_app().begin_wait();
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 != "") // 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");
if (!fexist(n)) fatal_box("Il file %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);
pr.set_char_size(_fontsize);
pr.set_fontname(_fontname);
set_fink_mode(TRUE);
main_app().end_wait();
}
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))
{
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_col_head(fi.get_special_value("INTESTAZIONE"));
fi.ofs() = (short)atoi(fi.get_special_value("OFFSET"));
TString fnk(fi.get_special_value("FINCATURA"));
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;
_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;
}
TForm::TForm()
{
init();
_frompage=_topage=0;
}
TForm::TForm(const char* name, const char* code, int lev, const char* desc)
{
init();
read(name, code, lev, desc);
_frompage=_topage=0;
}
TForm::~TForm()
{
if (_cursor)
{
delete _cursor;
delete _relation;
if (_rel_desc)
delete _rel_desc;
}
}