#include #include #define STRICT #define XVT_INCL_NATIVE #include #include #include #include #include #include #include #include #include #include #ifndef __DEFMASK_H #include #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 // // @rdesc Ritorna il 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 ) { _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

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 == "SUB") { const real n(get()); real r(des.get()); r -= n; des.set(r.string()); } else if (cmd[0] == '"') { TString256 val(cmd); val.strip("\""); des.set(val); } else error_box("Unknown message in item '%s': '%s'", (const char*)key(), (const char*)cmd); } TForm_item& TForm_item::find_field(const TString& id) const { if (isdigit(id[0])) // Field in the same section { TForm_item& des = section().find_field(atoi(id)); return des; } const int freccia = id.find("->"); const pagetype pt = (freccia==2) ? char2page(id[1]) : section().page_type() ; char se; int id_num; int pos_id; if (freccia) { pos_id=freccia+2; id_num=atoi(id.mid(pos_id)); se = id[0]; } else { id_num=0; se = section().section_type(); pos_id=0; } if (id_num) // id numerico: campo semplice { TForm_item& des = form().find_field(se, pt, id_num); return des; } else { // id stringa : campo sezione TForm_item& des = form().find_field(se, pt, id.mid(pos_id)); return des; } } // il parametro num serve per identificare il messaggio nelle listbox... bool TForm_item::do_message(int num) { TToken_string& messaggio = message(num); if (messaggio.empty_items()) return FALSE; TToken_string msg(16, ','); for (const char* m = messaggio.get(0); m; m = messaggio.get()) { msg = m; if (*m == '_') form().validate(*this, msg); else { const TString80 cmd(msg.get()); // Get command const TString80 id = msg.get(); // Get destination if (id.right(1) == "@") { const byte group = atoi(id); // Send the message to all fields in local and upper sections with the given group send_message_to_group(cmd,group,section(),§ion()); } else { TForm_item& des = find_field(id); send_message(cmd, des); } } } return TRUE; } void TForm_item::send_message_to_group(const char * cmd,byte id,const TPrint_section & section, const TPrint_section *starting_section) { TForm_item * f ; // look into local section for(word i = 0; i < section.fields(); i++) { f = §ion.field(i); if (f->in_group(id)) send_message(cmd,*f); } // look into the section above ("father" ) if (section.section_above() && section.section_above()!=starting_section) { send_message_to_group(cmd,id,*section.section_above(),§ion); } // look into sections beside ("brothers" ) for (int j = 0; j < section.subsections(); j++) { const TPrint_section &bs=section.subsection(j)->subsection(); if (&bs!=starting_section) { send_message_to_group(cmd,id,section.subsection(j)->subsection(),§ion); } } } bool TForm_item::update() { if (_prompt.right(1) == "#") { TString prompt(_prompt); for (int i = prompt.len()-2; i >= 0; i--) if (prompt[i] != '#') break; prompt.cut(i+1); string_at(x(), _y, prompt); } else string_at(x(), _y, _prompt); return TRUE; } void TForm_item::print_on(TToken_string& row) const { row.cut(0); row.add(id()); row.add(key()); row.add(_y); row.add(_x); row.add(shown() ? " " : "X"); if (form().edit_level() > 1) { const long fu = _group.first_one(); if (fu > 0) row.add(fu); else row.add(" "); } } 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è 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ù righe con prompt ora non pone più 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 { if (_prompt.empty()) string_at(x(), _y, s); else string_at(-1 , _y, s); } } void TForm_string::apply_format(TString& s) const { TString tmp(s); if (!picture().blank()) { TToken_string delim(4, ','); // Stringa con i due delimitatori const char * pic = picture(); // Picture senza delimitatori if (pic[0] == '(') // Se ci sono i delimitatori ... { const int bra = picture().find(')'); if (bra > 0) // ... cerca la parentesi chiusa { delim = picture().sub(1, bra); // memorizza delimitatori pic += bra+1; // toglili dalla picture } } if (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 { TForm_item::update(); // esegue i messaggi const int n = (_message.objptr(1) != NULL && *get()=='\0' ? 1 : 0); do_message(n); // prende il campo e lo stampa TString s(get()); apply_format(s); put_paragraph(s); } return TRUE; } const char* TForm_string::example() const { TString prova("XXXXXXXXXXXXXXXXXXXXXXXXXX"); apply_format(prova); 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 { 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 apply_format(TString& s) const; virtual void put_paragraph(const char * s); TForm_number(TPrint_section* section) : TForm_string(section) {} virtual ~TForm_number() {} }; bool TForm_number::parse_head(TScanner& scanner) { return TForm_item::parse_head(scanner); } TObject* TForm_number::dup() const { TForm_number *fn = new TForm_number(_section); copy_to_form_item(fn); return fn; } void TForm_number::put_paragraph(const char* s) { if (hidden()) return; int gap = 0; if (section().columnwise()) { const int w = width(); const int l = strlen(s); if (w>l) gap = w-l; } if (_prompt.empty()) string_at(x()+gap, _y, s); else string_at(-1, _y, s); // se ha il prompt stampa all'ultima posizione raggiunta } 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(get()); apply_format(s); put_paragraph(s); } } return TRUE; } void TForm_number::apply_format(TString& s) const { if (!picture().blank()) { real n(s); TToken_string delim(4, ','); // Stringa con i due delimitatori TString pic(picture()); // Picture senza delimitatori int maxlen = -1; if (pic[0] == '(') // Se ci sono i delimitatori ... { const int bra = pic.find(')'); if (bra > 0) // ... cerca la parentesi chiusa { delim = pic.sub(1, bra); // memorizza delimitatori pic.ltrim(bra + 1); // toglili dalla picture } } const int at = pic.find('@'); if (at > 0) { const int len = atoi(&pic[at+1]); if (len > 0) { maxlen = len; pic.cut(at); } } s=n.string(pic); // riempi la stringa col valore pitturato if (maxlen >= 0 && maxlen < s.size()) s.cut(maxlen); if (!delim.empty_items()) // Aggiungi delimitatori { TString16 d(delim.get(0)); const int ld = d.len(); if (ld > 0) // Se il primo delimitatore e' valido ... { for (int spc = 0;s[spc]==' ' ; spc++) ; if (spc < ld) { TString16 spazi; spazi.spaces(ld - spc); s.insert(spazi,0); spc = ld; } s.overwrite(d,spc - ld); } d = delim.get(); if (d.not_empty()) // Se il secondo delimitatore e' valido ... s << d; // ... aggiungilo alla fine } } // else 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 { TString s("123456789120.00"); apply_format(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.cut(0); const bool ok = TPrint_section::update(); int index; switch(page_type()) { case even_page : index = 1; break; case first_page: index = 2; break; case last_page : index = 3; break; default : index = 0; break; } printer().setbackground(_back, index); return ok; } /////////////////////////////////////////////////////////// // TPrint_section /////////////////////////////////////////////////////////// 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 { word h = _height; if (int(h) < 0) // Can't write h < 0! { if (section_type() == 'F') { h += printer().formlen(); } else { h = items(); if (h == 0) h = 0xFFFF - _height + 1; // Same as abs(_height) } } return h; } TExpression & TPrint_section::eval_expr(TExpression & expr,int defaultfile_id) { for (int j = 0; j < expr.numvar(); j++) { // scansione delle variabili dell'espressione di rvalue TString var= expr.varname(j); if (var[0]=='#') { // riferimento ad un campo del form var.ltrim(1); TForm_item &fi= find_field(atoi(var)); expr.setvar(j, fi.get()); // il valore corrente del campo viene settato nell'espressione } else { // riferimento ad un campo di file TFieldref fr = TFieldref(var, 0); int fileno=fr.file(); // choose logical file number fileno= (fileno==0) ? (defaultfile_id>0 ? defaultfile_id : 0): fileno; expr.setvar(j, fr.read( form().relation()->lfile(fileno).curr() ) ); // il valore corrente del campo viene settato nell'espressione } } return expr; } TPrint_section::TPrint_section(TForm* f, char st, pagetype pt, TForm_subsection* father) : _height(0), _form(f), _sec_type(st), _page_type(pt), _dirty(FALSE), _upsection(father), _repeat_count(0), _ofspc(0), _ofsvr(0), _nfld(0), _temp(0), _columnwise(FALSE) { reset_tabs(); } TPrint_section::~TPrint_section() { if (_msk) { delete _msk; _msk = NULL; } } 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 && fields()) { _tab[0] = 2; { int extraoff=0; // compute column offset _nfld = 0; short maxcolreached = 0,mincolreached = MAXCOLUMNS+1; for (word i = 0; i < fields(); i++) { if (!field(i).is_section() && field(i).shown()) { const int curr_col=field(i)._x; CHECKD (curr_col >=0 && curr_col < MAXCOLUMNS, "Colonna ammessa e non concessa: ", field(i)._x); _tab[curr_col] = field(i)._width + 1; // one is for separation if (curr_col < mincolreached) mincolreached = curr_col; if (curr_col > maxcolreached) maxcolreached = curr_col; _nfld++; } } // cumulate offsets if (_upsection) { if (mincolreached<=MAXCOLUMNS && mincolreached>0) { // print section of a subsection: extra offset extraoff=_upsection->section().tab(mincolreached-1); for (i = 1 ; i < (word)mincolreached; i++) { _tab[i]=_upsection->section()._tab[i]; } if (extraoff== _tab[mincolreached-1]) extraoff=0; else extraoff-=_upsection->section().tab(0); } } int last = 0; for (i = mincolreached ; i <= (word)maxcolreached; i++) { if (_tab[i - 1] != -1) last = i - 1; if (_tab[i] != -1) _tab[i] += _tab[last]+extraoff; } } } // se manca la colonna, vai a prendere quella immediatamente prima while (_tab[col] == -1 && col > 0) col--; ret = _tab[col]; } return ret; } word TPrint_section::subs_height() const { TForm_subsection *fss; word h=0; if (subsections()) { fss=subsection(0); h=subsection(0)->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--) { if (_height > 0xF000) destroy(i); else row(i).reset(); } } // Aggiorna tutti i campi bool TPrint_section::update() { bool ok = TRUE; reset(); for (word i = 0; i < fields(); i++) { if (!field(i).is_section()) { const bool esito = field(i).update(); if (!esito) ok = FALSE; } } return ok; } // @doc EXTERNAL // @mfunc Legge dal record

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 . { 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 = §ion; } 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; ipost_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()); if (scanner.key() == "PA") // Numero di pagine fisso _npages=scanner.integer(); 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 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 ) 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_subsection& TForm::find_field(char s, pagetype t, const char *section) const { const TPrint_section* ps = ((TForm*)this)->exist(s, t); CHECKS(ps, "Can't find section for field ", section); return (TForm_subsection&)ps->find_field(section); } TPrint_section& TForm::section(char s, pagetype pos) { TPrint_section* sec = exist(s, pos, TRUE); return *sec; } TPrint_section& TForm::section(char s, word pagenum) { pagetype pt = odd_page; if (pagenum == 0 && exist(s, last_page)) pt = last_page; if (pagenum == 1 && exist(s, first_page)) pt = first_page; if (pt == odd_page && (pagenum & 0x1) == 0 && exist(s, even_page)) pt = even_page; return section(s, pt); } // @doc EXTERNAL // @mfunc Rilegge la sezione specificata // // @rdesc Ritorna se ce l'ha fatta bool TForm::reread( char sec, // @parm Sezione da rileggere pagetype p, // @parm Posizione della pagina bool force) // @parm Forza rilettura anche se nessun campo e' cambiato { TPrint_section* s = exist(sec,p); bool ok = force; if (s != NULL) for (word j = 0; j < s->fields(); j++) ok |= s->field(j).dirty(); if (s != NULL && ok) { s->destroy_fields(); // Distrugge tutti gli items... // ...si posiziona nel file sorgente alla sezione opportuna... TFilename n(_name); n.ext("frm"); TScanner scanner(n); bool ok = FALSE; while (!ok) { while (TRUE) // ...scans searching for a section... { const TString& key = scanner.popkey(); if (key == "SE" || key == "") // ..if section or end of file... break; } const char secr = scanner.popkey()[0]; // Section name (GRAPH, HEAD, BODY, FOOT) if (secr=='\0') break; const pagetype pr = char2page(scanner.popkey()[0]); // Section type (odd, even, first, last) if (secr==sec && pr==p) ok = TRUE; // L'ha trovata... } // ...riesegue la parse della sezione leggendo dal file sorgente if(ok && s->parse(scanner)) { // Legge le modifiche su archivio e poi e' finita. s->set_dirty(FALSE); TLocalisamfile rprof(LF_RFORM); const char sez[3] = {sec,p+'0','\0'}; rprof.zero(); rprof.put("TIPOPROF", _name); rprof.put("CODPROF", _code); rprof.put("SEZ", sez); const TRectype filter(rprof.curr()); for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next()) { const short id = rprof.get_int("ID"); if (id == 0) { TPrint_section& se = section(sec, p); se.read_from(rprof.curr()); } else { TForm_item& item = find_field(sec, p, id); item.read_from(rprof.curr()); } } set_compulsory_specials(); } } return ok; } /////////////////////////////////////////////////////////// // TForm /////////////////////////////////////////////////////////// // @doc EXTERNAL // @mfunc Cambia il formato di tutte le date nel form // // @rdesc Ritorna sempre TRUE bool TForm::ps_change_date_format( TPrint_section& s, // @parm Sezione nella quale modificare le date const char* f) // @parm Nuovo formato delle date // @comm Ha le stesse funzioni di , ma per , // all'uopo di chiamarla con ricorsiva insistenza { for (word i = 0; i < s.fields(); i++) { TForm_item& fi = s.field(i); if (fi.is_section()) { TPrint_section& ps = ((TForm_subsection&)fi).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 , ma per , // all'uopo di chiamarla con ricorsiva insistenza { for (word i = 0; i < s.fields(); i++) { TForm_item& fi = s.field(i); if (fi.is_section()) { TPrint_section& ps = ((TForm_subsection&)fi).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 { word len = 0; if (u && _back.items()) { TPrint_section& graph = section('G', p); graph.update(); len = printer().formlen(); } return len; } // @doc EXTERNAL // @mfunc Effettua l'update della sezione header // // @rdesc Ritorna l'altezza dell'header settato word TForm::set_header( word p, // @parm Numero pagina bool u) // @parm Indica se cambiare l'eventuale header o solo ritornare l'altezza // @xref { 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 { 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 (!field(i).is_section()) { // 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) ; } } const word hgt = height(); if (show_fields && last_printed_row < hgt && pr.current_row() > pr.headersize()+1) { if (hgt-last_printed_row > pr.rows_left()) pr.formfeed(); } if (show_fields) { for (word j = last_printed_row; j < hgt; 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 { 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) { if (form().firstpage_is_lastpage()) { form().set_background(1, TRUE); form().set_header(1, TRUE); form().set_footer(0, FALSE); } else { 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) { if (form().firstpage_is_lastpage()) { form().set_footer(0, TRUE); } else { const word currp = form().page(p); form().set_footer(currp, TRUE); if (currp) form().set_header(form().next_page(p), FALSE); } } // @doc EXTERNAL // @mfunc Ritorna se la prima pagina coincide conl'ultima bool TForm::firstpage_is_lastpage() const { return _first_eq_last; } // @doc EXTERNAL // @mfunc Ritorna il numero di pagina correntemente in stampa // // @rdesc Se e' TRUE (sta stampando l'ultima pagina) // ritorna 0, altrimenti ritorna il numero della pagina corrente da stampare // (chiam ). word TForm::page( const TPrinter& p) const // @parm Operazione corrente di stampa { return _lastpage || fixed_pages() && p.getcurrentpage()==_npages ? 0 : p.getcurrentpage(); } word TForm::next_page( const TPrinter& p) const // @parm Operazione corrente di stampa { return _lastpage || fixed_pages() && p.getcurrentpage()+1==_npages ? 0 : p.getcurrentpage()+1; } // @doc EXTERNAL // @mfunc Effettua il posizionamento manuale del modulo void TForm::arrange_form() // @comm Nota: siccome si scrive direttamente sulla porta, sarebbe necessario // mandare una stringa di reset alla stampante, o per lo meno far si' che // ogni volta che si fa il posizionamento il font col quale scrive sia sempre // lo stesso. Tutto cio' non e' possibile con la generica solo testo, o meglio // ad ogni stampa col posizionamento e' necessario che la stampante sia resettata. // 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!. // Quindi, per ovviare a tutto cio, visto che 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 ) int y1, // @parm Prima y per le righe verticali int y2, // @parm Ultima y per le righe verticali const int* rows) // @parm Array di posizioni riga con 0 per finire { TPrint_section* body = exist('B', p); if (body == NULL) return FALSE; body->reset_tabs(); bool istemp = exist('G', p) == NULL; TGraphic_section* grs = (TGraphic_section*)exist('G', p, TRUE); grs->temp() = istemp; int j = 0, start = 999, end = 0, wlast = 0; int cols[MAXCOLUMNS]; for (word k = grs->fields(); k > 0; k--) if (grs->field(k-1).temp()) grs->destroy_field(k-1); for (int i = 0; i < (int)body->fields(); i++) { TForm_item& f = body->field(i); if (!f.shown() || f.is_section()) continue; int x = f.x(); if (x < start) start = x; if (x > end) { end = x; wlast = f.width(); } cols[j++] = f.finkl() ? -x : x; } // inner lines for (i = 0; i < j; i++) { if (cols[i] != start && cols[i] > 0) { TForm_line* l = new TForm_line(grs); l->set_x(cols[i]-1); l->y() = (word)y1; l->id() = -1; l->width() = 1; l->height() = (int)(y2 - y1 + 1); l->set("@R"); l->temp() = TRUE; grs->add_field(l); } } // box around if (start != 999 && end != 0) { TForm_box* l = new TForm_box(grs); l->set_x(start-1); l->y() = (word)y1; l->id() = -1; l->width() = (int)(end + wlast - start + 2); l->height() = (int)(y2 - y1 + 1); l->set("@B@R"); l->temp() = TRUE; grs->add_field(l); } // horizontal lines if (start != 999 && end != 0) for (i = 0; rows[i]; i++) { TForm_line* l = new TForm_line(grs); l->set_x(start-1); l->y() = (word)rows[i]; l->id() = -1; l->width() = (int)(end + wlast - start + 2); l->height() = 1; l->set("@R"); l->temp() = TRUE; grs->add_field(l); } return TRUE; } // @doc EXTERNAL // @mfunc Genera le righe di intestazione colonna alla riga indicata, vale per COLUMNWISE // // @rdesc Ritorna FALSE se non esiste body (o non e' COLUMNWISE) o se non esiste l'header bool TForm::genera_intestazioni( pagetype p, // @parm Posizione della pgaina (vedi ) short y) // @parm Riga dell'header in cui vanno inserite // @comm I form_items di intestazione vengono aggiunti alla sezione header di tipo

con ID -1 { TPrint_section* body = exist('B', p); if (body == NULL || !body->columnwise()) return FALSE; TPrint_section* header = exist('H', p); if (header == NULL) return FALSE; body->reset_tabs(); // Elimina eventuali campi temporanei precedenti for (int k = header->fields()-1; k >= 0; k--) if (header->field(k).temp()) header->destroy_field(k); const word items = body->fields(); TForm_string* s; for (word j=0;jfield(j); if (!fi.shown() || fi.is_section()) continue; char align='\0'; if (fi.col_head()[0]=='@') { switch (fi.col_head()[1]) { case 'C': // centered case 'c': align='c'; break; case 'R': // right just case 'r': align='r'; break; default: // left just align='l'; break; } } TParagraph_string prompts(fi.col_head().mid(align ? 2:0),fi.width()); // Paragraph_string has as many items as lines needed... for (int c=0;c < prompts.items(); c++) { TString p(prompts.get(c)); switch (align) { case 'c': p.center_just(fi.width()); break; case 'r': p.right_just(fi.width()); break; } s = new TForm_string(header); s->id() = -1; s->set_x(fi.x()); s->y() = y+c; s->set_prompt(p); s->temp() = TRUE; header->add_field(s); } } return TRUE; } /* void TForm::remove_temp_items(char sec, pagetype p) { TPrint_section* s = exist(sec,p); if (s!=NULL) { const word items = s->fields(); for (word j=0;jfield(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;ifield(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;ifield(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

a

// // @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 0 stampa fino alla fine del file, default -1l) // @comm Se i parametri di posizionamento sono settati e cosi' pure gli offset genera un . { _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; // controlla i casi di stampa _first_eq_last=FALSE; if (!fixed_pages() && set_body(1,FALSE) * word(to-from+1) <= pr.formlen()- set_header(1,FALSE) - set_footer(0,FALSE)) // tutta la stampa sta in una pagina _first_eq_last=TRUE; // if (to == lastrec) to--; // l'ultima pagina è 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(); // quanto resta da stampare sta nell'ultima pagina if (!fixed_pages() && set_body(0,FALSE) * word(to-i+1) <= pr.formlen()- set_header(1,FALSE) - set_footer(0,FALSE)) { while (i < to && from >= 0) // stampa l'ultima pagina { i++; set_last_page(TRUE); set_background(0, TRUE); set_header(0, TRUE); if (cursor()) { *cursor() = i; set_body(0, TRUE); } } } break; } } set_body(page(pr), TRUE); if (cursor()) { if (next_match_done()) i=cursor()->pos(); else i++; } } // fine ciclo di stampa while (fixed_pages() && page(pr) % _npages !=0) { static TPrintrow empty_line; pr.formfeed(); pr.print(empty_line); } pr.formfeed(); if (!was_open) pr.close(); pr.setheaderhandler(NULL); pr.setfooterhandler(NULL); return ok; } /*bool TForm::print( long from, // @parm Primo item da stampare (default 0l) long to) // @parm Ultimo da stampare (se 0 stampa fino alla fine del file, default -1l) // @comm Se i parametri di posizionamento sono settati e cosi' pure gli offset genera un . { _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 è 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,,[!!...],{|[!!...]} // dove: è il numero logico del file o il nome della tabella // è un'espressione del tipo = // è un'espressione di costanti numeriche, stringhe e valori di campi della form (indicati con il loro numero preceduto da #) // è un'espressione del tipo = (se è un gruppo deve essere seguito da @) oppure solo (il campo della form è 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 è numerico allora è un file else file= new TTable(f_code); // altrimenti è una tabella file->zero(); // vuota il record corrente del file TToken_string in(s.get(), '!'); for (i=0; iput(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; iget(curr); // preleva il nome del campo del file e lo legge dal record cf.set(dat); } else { TString fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale const TString &dat= file->get(curr.mid(posrv)); // preleva il nome del campo del file alla destra dell'uguale e lo legge dal record if (fld[0]=='#') fld.ltrim(1); if (fld.right(1)== "@") { // se c'è la a-commerciale è un gruppo if (fld.find("->") != -1) { // se nel gruppo c'è 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,, // dove: nome tabella da leggere // costante stringa o riferimento a campo della form (preceduto da '#') da usare come chiave di ricerca // identificativo del campo da leggere dalla tabella TTable tab(s.get()); // prende il nome della tabella tab.zero(); // vuota il record corrente della tabella TString in(s.get()); // prende il valore o il campo da usare come codice di ricerca if (in[0]== '#') { in.ltrim(1); TForm_item &fi= cf.find_field(in); in= fi.get(); } tab.put("CODTAB", in); // setta la chiave nella tabella if (tab.read()== NOERR) { const TString &fld= s.get(); // prende il nome del campo da leggere... valore = tab.get(fld); cf.set(valore); } return TRUE; } // fine _TABLEREAD if (code== "_ALIGN") { // allineamento della posizione di un campo rispetto ad un altro // sintassi: _ALIGN,[,][,...] // dove: è il campo della form (preceduto da '#') da cui prendere l'allineamento // è uno dei seguenti valori: // TOP allinea sulla riga d'inizio // MIDDLE allinea al centro (effettivo) // BOTTOM allinea sulla riga di fine (effettiva, non preimpostata) // LEFT allinea sulla colonna d'inizio // RIGHT allinea sulla colonna di fine TString in(s.get()); if (in[0]== '#') in.ltrim(1); TForm_item &fi= cf.find_field(in); int i= 2; for (const char * cmd = s.get(); cmd != NULL; cmd = s.get()) { // Calcola la nuova posizione TString align(cmd); if (align[0]=='!') align.ltrim(1); if (align== "TOP") cf.y()= fi.y(); else if (align== "MIDDLE") cf.y()= fi.y()+ fi.effective_height()/2; else if (align== "BOTTOM") cf.y()= fi.y()+ fi.effective_height()-1; else if (align== "LEFT") cf.set_x(fi.x()); else if (align== "RIGHT") cf.set_x(fi.x()+ fi.width()); } // altrimenti stampa la stringa cosi' com'e' return TRUE; } // fine _ALIGN if (code== "_PAGENO") // Messaggio per stampare il numero di pagina corrente { TString16 pg; pg << int(printer().getcurrentpage() ); cf.set(pg); return TRUE; } if (code== "_TODAY")// Messaggio per stampare la data di oggi { TString16 dt(TDate(TODAY).string()); cf.set(dt); return TRUE; } if (code== "_NUMEXPR" || code== "_STREXPR") { // Messaggio per la valutazione di espressioni numeriche e stringhe 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; } if (code== "_DITTA") { // lettura dei dati della ditta // sintassi: _DITTA,{|} // dove: è un riferimento alla relazione di gestione dei dati della ditta (es. 113@->DENCOM è la denominazione del comune di residenza della ditta) // è uno delle macro seguenti: // !RAGSOC ragione sociale // !IND indirizzo (fiscale se c'è, oppure di residenza) // !NUM numero civico (fiscale se c'è, oppure di residenza) // !CAP CAP (fiscale se c'è, oppure di residenza) // !COM comune (fiscale se c'è, oppure di residenza) // !PROV provincia (fiscale se c'è, 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 è così strutturata: // %NDITTE (9) Dati ditte // + %ANAGR (6) Anagrafica generale (indirizzo, ecc.) // + %COMUNI (113@) Comune di residenza // + %COMUNI (213@) Comune di residenza fiscale TLocalisamfile firm(LF_NDITTE); TLocalisamfile anag(LF_ANAG); firm.put("CODDITTA",main_app().get_firm()); firm.read(); anag.put("TIPOA",firm.get("TIPOA")); anag.put("CODANAGR",firm.get("CODANAGR")); anag.read(); TString in(s.get()); if (in[0]=='!') { in.ltrim(1); bool _fisc= anag.get("INDRF").not_empty(); if (in=="RAGSOC") valore = anag.get("RAGSOC"); if (in=="IND") { if (_fisc) valore = anag.get("INDRF"); else valore = anag.get("INDRES"); } if (in=="NUM") { if (_fisc) valore = anag.get("CIVRF"); else valore = anag.get("CIVRES"); } if (in=="CAP") { if (_fisc) valore = anag.get("CAPRF"); else valore = anag.get("CAPRES"); } /*if (in=="COM") { if (_fisc) valore = _firmrel.lfile(-213).get("DENCOM"); else valore = _firmrel.lfile(-113).get("DENCOM"); } if (in=="PROV") { if (_fisc) valore = _firmrel.lfile(-213).get("PROVCOM"); else valore = _firmrel.lfile(-113).get("PROVCOM"); }*/ if (in=="IVA") valore = anag.get("PAIV"); if (in=="CF") valore = anag.get("COFI"); if (in=="TEL") { valore = anag.get("PTEL"); valore << "/" << anag.get("TEL"); } if (in=="FAX") { valore = anag.get("PFAX"); valore << "/" << anag.get("FAX"); } /*if (in=="REGSOC") { valore = _firmrel[LF_UNLOC].get("REGTRIB"); valore << " Vol. " << _firmrel[LF_UNLOC].get("VOLTRIB"); valore << " Fasc. " << _firmrel[LF_UNLOC].get("FASCTRIB"); } if (in=="CCIAA") { valore = _firmrel[LF_UNLOC].get("NUMCCIAA"); valore << " del " << _firmrel[LF_UNLOC].get("DATAICCIAA"); } */ } else { TFieldref fref(s.get(), 0); valore = fref.read(anag.curr()); } cf.set(valore); return TRUE; } return TRUE; } void TForm::print_on(ostream& out) const { 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() { _npages=0; _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); if (_fontname.not_empty()) { pr.set_char_size(_fontsize); pr.set_fontname(_fontname); } else { _fontname = pr.fontname(); _fontsize = pr.get_char_size(); } set_fink_mode(TRUE); 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; } }