#include #include #if XVT_OS == XVT_OS_WIN #define STRICT #include #endif #include #include #include #include #include #include #include #include "../ba/ba2100.h" /////////////////////////////////////////////////////////// // Utility functions /////////////////////////////////////////////////////////// // Current form (edit, print) HIDDEN TForm* _cur_form = NULL; HIDDEN TForm& form() { CHECK(_cur_form, "Can't print NULL form"); return *_cur_form; } // Translate char to pagetype (visible outside here, no more HIDDEN) pagetype char2page(char c) { 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_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()); 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_SPACE) { TRelation_description& r = form().rel_desc(); TEdit_field& e = f.mask().efield(f.dlg()-4); 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 TFormatted_date ex(TODAY, 0, 0, fmt); m.set(F_DEXAMPLE, ex.string()); } return TRUE; } /////////////////////////////////////////////////////////// // TForm_flags /////////////////////////////////////////////////////////// TForm_flags::TForm_flags() { automagic = dirty = 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; 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 (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" : " "); } // 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); } /////////////////////////////////////////////////////////// // TForm_item /////////////////////////////////////////////////////////// TForm_item::TForm_item(TPrint_section* section) : _section(section), _x(-1), _y(-1), _width(0), _height(0), _id(0) {} 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; } } 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; } 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; } const bool s = prof.get_bool("ATTIVO"); if (_flag.shown != s) { _flag.shown = s; changed = TRUE; } 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()); prof.put("ATTIVO", shown() ? "X" : " "); } void TForm_item::enable(bool on) { _flag.enabled = on; show(on); } void TForm_item::string_at(int x, int y, const char* s) { if (shown()) { section().offset(x, y); 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; } void TForm_item::send_message(const TString& cmd, TForm_item& des) const { if (cmd == "ADD" || cmd == "INC") { const real n((cmd[0] == 'I') ? "1.0" : get()); real r(des.get()); r += n; des.set(r.string()); } else if (cmd == "COPY") { des.set(get()); } else if (cmd == "APPEND") { TString256 val = des.get(); if (val.not_empty()) val << ' '; val << get(); des.set(val); } else if (cmd == "DISABLE") { des.disable(); } else if (cmd == "ENABLE") { des.enable(); } else if (cmd == "HIDE") { des.hide(); } else if (cmd == "RESET") { des.set(""); } else if (cmd == "SHOW") { des.show(); } else if (cmd[0] == '"') { TString256 val(cmd); val.strip("\""); des.set(val); } else error_box("Unknown message in item '%s': '%s'", (const char*)key(), (const char*)cmd); } TForm_item& TForm_item::find_field(const TString& id) const { if (isdigit(id[0])) // Field in the same section { TForm_item& des = section().find_field(atoi(id)); return des; } const pagetype pt = (id[1] == '-') ? section().page_type() : char2page(id[1]); const int freccia = id.find("->"); CHECKS(freccia > 0, "Non trovo la freccia nel campo ", (const char*)id); TForm_item& des = form().find_field(id[0], pt, atoi(id.mid(freccia+2))); return des; } 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 TString16 cmd(msg.get()); // Get command const TString16 id = msg.get(); // Get destination if (id.right(1) == "@") { const word group = atoi(id); // Send the message to all fields with the given group for (word i = 0; i < section().fields(); i++) { TForm_item& des = section().field(i); if (des.in_group(group)) send_message(cmd, des); } } else { TForm_item& des = find_field(id); send_message(cmd, des); } } } return TRUE; } 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(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); m.set(F_HEIGHT, _height); _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)); _height = atoi(m.get(F_HEIGHT)); _id = atoi(m.get(F_ID)); _flag.read_from(m); _group.reset(); for (int g = 1; g <= 24; g++) _group.set(g, m.get_bool(F_GROUP+g)); } 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); const bool dirty = m.run() == K_ENTER; if (dirty) { read_from(m); set_dirty(); } return dirty; } /////////////////////////////////////////////////////////// // TForm_subsection /////////////////////////////////////////////////////////// class TForm_subsection : public TForm_item { TPrint_section _ssec; TString _name; int _file_id; // ID del file su cui iterare in stampa se previsto protected: virtual void print_on(ostream& out) const; public: virtual bool parse(TScanner& s); virtual bool update(); virtual bool edit(TMask& m); virtual const char* class_name() const { return "SEZIONE"; } TPrint_section& subsection() { return _ssec; } virtual void show(bool on = TRUE); virtual void enable(bool on = TRUE); void hide() { show(FALSE); } void disable() { enable(FALSE); } void name(const char* s) { _name = s; _desc << "Sottosezione " << s; } const char* name() const { return _name; } TForm_subsection(TPrint_section* section, const char* name = ""); virtual ~TForm_subsection() {} }; TForm_subsection::TForm_subsection(TPrint_section* s, const char* nm) : TForm_item(s), _ssec(&(s->form()), s->section_type(), s->page_type(), TRUE), _file_id(-1), _name(nm) {} bool TForm_subsection::parse(TScanner& s) { name(s.pop()); _width = s.integer(); _height = s.integer(); _x = s.integer(); _y = s.integer(); if (s.popkey() == "FI") // FILE su cui iterare con next_match _file_id = s.integer(); // TBI controllo alias else s.push(); return _ssec.parse(s); } bool TForm_subsection::update() { bool ok = FALSE; TRelation* rel = form().relation(); if (rel == NULL || _file_id == -1) ok = _ssec.update(); else { int i = 0; if (rel->is_first_match(_file_id)) do { if (!(ok = _ssec.update())) break; _ssec.set_repeat_count(++i); } while (rel->next_match(_file_id)); _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"; } // ??? void TForm_subsection::show(bool on) { for (unsigned int i = 0; i < _ssec.fields(); i++) _ssec.field(i).show(on); } // ??? void TForm_subsection::enable(bool on) { for (unsigned int i = 0; i < _ssec.fields(); i++) _ssec.field(i).enable(on); } /////////////////////////////////////////////////////////// // TForm_string /////////////////////////////////////////////////////////// class TForm_string : public TForm_item { TString _str, _picture; TArray _field; protected: virtual const char* class_name() const { return "STRINGA"; } 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); virtual void print_on(TToken_string& row) const; virtual bool parse_item(TScanner&); virtual bool read(); virtual bool update(); virtual const char* get() const; bool set(const char*); const TString& picture() const { return _picture; } TFieldref& field(int i) const { return (TFieldref&)_field[i]; } void put_paragraph(const char* s); public: void set_picture(const char* p) { _picture = p; } virtual bool edit(TMask& m); TForm_string(TPrint_section* section) : TForm_item(section) {} virtual ~TForm_string() {} }; 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") { TFieldref* fr = new TFieldref(scanner.line(), 0); _field.add(fr); return TRUE; } if (scanner.key() == "PI") { _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; } return changed; } void TForm_string::print_on(TToken_string& row) const { 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); } 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); 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); 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 = 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; if (height() > 1) { TParagraph_string p(s, width()); int i = _prompt.not_empty() ? 1 : 0; for (; (s = p.get()) != NULL && i < height(); i++) string_at(_x, _y+i, s); } else string_at(-1, _y, s); } bool TForm_string::update() { if (read()) { TString s; TForm_item::update(); 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" && _str.empty()) s =""; else s.picture(pic, get()); // 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); 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 } put_paragraph(s); } else put_paragraph(s=get()); // Stampa immediata senza picture const int n = (_message.objptr(1) != NULL && s.empty() ? 1 : 0); do_message(n); } return TRUE; } /////////////////////////////////////////////////////////// // TForm_number /////////////////////////////////////////////////////////// class TForm_number : public TForm_string { protected: // TForm_string virtual const char* class_name() const { return "NUMERO"; } virtual bool parse_head(TScanner& scanner); virtual bool update(); virtual int height() const { return 0; } protected: int decimals() const { return _height; } public: void set_decimals(int d) { _height = d; } TForm_number(TPrint_section* section) : TForm_string(section) {} virtual ~TForm_number() {} }; bool TForm_number::parse_head(TScanner& scanner) { TForm_item::parse_head(scanner); _height = _width; // Decimals _width = 0; return TRUE; } bool TForm_number::update() { if (read()) { TForm_item::update(); real n(get()); n.round(decimals()); TString s; if (!n.is_zero()) { if (!picture().blank()) { TToken_string delim(4, ','); // Stringa con i due delimitatori TString pic(picture()); // Picture senza delimitatori int maxlen = -1; int at = pic.find('@'); if (at >= 0) { maxlen = atoi(&pic[at+1]); pic.cut(at); } 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 } } s=n.string(pic); // riempi la stringa col valore pitturato if (maxlen >= 0) 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 } put_paragraph(s); } else put_paragraph(n.string()); do_message(); } else { const int n = (_message.objptr(1) != NULL ? 1 : 0); do_message(n); } } return TRUE; } /////////////////////////////////////////////////////////// // 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: void set_format(const char* f) { _format = f; } virtual bool edit(TMask& m); TForm_date(TPrint_section* section); virtual ~TForm_date() {} }; TForm_date::TForm_date(TPrint_section* section) : TForm_string(section), _format("1444-") {} 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::read_from(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 TFormatted_date d(TODAY, 0, 0, _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); } /////////////////////////////////////////////////////////// // 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: TForm_list(TPrint_section* section); virtual ~TForm_list() {} }; TForm_list::TForm_list(TPrint_section* section) : TForm_string(section) {} 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() {} }; /////////////////////////////////////////////////////////// // 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; TPrint_section::TPrint_section(TForm* f, char st, pagetype pt, bool sub) : _height(0), _form(f), _sec_type(st), _page_type(pt), _dirty(FALSE), _subsection(sub), _repeat_count(0) {} TPrint_section::~TPrint_section() { if (_msk) { delete _msk; _msk = NULL; } } const TPrint_section& TPrint_section::copy(const TPrint_section& ps) { _item = ps._item; _height = ps._height; 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::offset(int& x, int& y) const { if (x >= 0) 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(TScanner& scanner) { _height = scanner.integer(); scanner.integer();scanner.integer(); // Eat offset X and Y of Print_section if present 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; } // Azzera tutte le righe della sezione di stampa void TPrint_section::reset() { for (word i = 0; i < height(); i++) row(i).reset(); } // Aggiorna tutti i campi e li stampa bool TPrint_section::update() { bool ok = TRUE; reset(); for (word i = 0; i < fields(); i++) { const bool esito = field(i).update(); if (!esito) ok = FALSE; } return ok; } bool TPrint_section::read_from(const TRectype& prof) { CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM"); bool changed = FALSE; const word h = (word)prof.get_int("HGT"); if (_height != h) { _height = h; 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", 0); 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 double 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::edit(const char* title) { _cur_form = _form; if (!_subsection) { TMask m("ba2100s"); m.set_caption(title); m.set(F_HEIGHT, _height); 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()); { const int MAX_FAMILIES = 128; char* family[MAX_FAMILIES]; const int num_families = (int)xvt_fmap_get_families(printer().get_printrcd(), family, MAX_FAMILIES); bool font_found = FALSE; 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); lst.replace_items(pn1, pn2); if (!font_found) warning_box("Il font %s non esiste per la stampante di default.",(const char*) form().fontname()); lst.set(form().fontname()); } printer().set_char_size(form().fontsize()); m.set_handler(F_FONT,font_handler); if (m.run() == K_ESC) return FALSE; bool dirty = m.dirty() != 0; if (dirty) { if (_height != (word)m.get_int(F_HEIGHT) ) { _height = m.get_int(F_HEIGHT); _dirty=TRUE; } if (m.get_int(F_X) != form().offset_x() || m.get_int(F_Y) != form().offset_y()) { form().offset_x() = m.get_int(F_X); form().offset_y() = m.get_int(F_Y); form().set_dirty(); _dirty = TRUE; } if (m.get(F_CTP)[0] != form().char_to_pos() || m.get_int(F_IPX) != form().ipx() || m.get_int(F_IPY) != form().ipy() || m.get_int(F_IPX) != form().fpx()) { form().char_to_pos() = m.get(F_CTP)[0]; form().ipx() = m.get_int(F_IPX); form().ipy() = m.get_int(F_IPY); form().fpx() = m.get_int(F_FPX); _dirty = TRUE; } TString80 name(m.get(F_FONT)); int size = m.get_int(F_SIZE); if (name != form().fontname() || size != form().fontsize()) { if (!form().dirty()) form().set_dirty(); _dirty = TRUE; s_data prm; prm.size_1=form().fontsize(); strcpy(prm.name_1,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(); form().fontname() = name; form().fontsize() = size; 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 = form().exist(sc, pt); if (sec != NULL) { sec->set_dirty(); for (word i = 0; i < sec->fields() ; i++) { TForm_item& fi = sec->field(i); if (fi.x() > 0 && (prm.ratio != 1.0)) { real x_pos; x_pos = fi.x() * prm.ratio; x_pos.round(); fi.x() = (short)x_pos.integer(); fi.set_dirty(); } } } } } } } } if ((_dirty || form()._isnew) && 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; } } const word flags = 0x08 | (form().edit_level() > 1 ? 0x06 : 0x00); TString80 caption("ID@4|Descrizione@40|Riga@R|Col.@R|Non stampare"); if (form().edit_level() > 1) caption << "|Gr.@R|Campo@16"; TArray_sheet a(-1, -1, 0, 0, title, caption, flags); for (word i = 0; i < fields(); i++) { TToken_string* s = new TToken_string(128); field(i).print_on(*s); a.add(s); } KEY k; while ((k = a.run()) != K_ESC) { i = (word)a.selected(); if (_msk == NULL && (k == K_ENTER || k == K_INS || k == K_CTRL + 'N')) { _msk = new TMask("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_BUT_FILE1, but_file_handler); _msk->set_handler(F_BUT_FIELD1, but_field_handler); _msk->set_handler(F_FROM1, from_handler); _msk->set_handler(F_TO1, to_handler); _msk->set_handler(F_BUT_FILE2, but_file_handler); _msk->set_handler(F_BUT_FIELD2, but_field_handler); _msk->set_handler(F_FROM2, from_handler); _msk->set_handler(F_TO2, to_handler); } TForm_string dummy(this); switch(k) { case K_ENTER: _msk->set_mode(MODE_MOD); if (field(i).edit(*_msk)) { field(i).print_on(a.row(i)); _dirty = TRUE; } break; case K_CTRL + 'N': case K_INS: _msk->set_mode(MODE_INS); if (dummy.edit(*_msk)) { const TString& c = _msk->get(F_CLASS).left(2); TForm_item* item = parse_item(c); if (item != NULL) { item->read_from(*_msk); _item.insert(item, i); TToken_string s(128); item->print_on(s); a.insert(s, i); _dirty = TRUE; } } break; case K_DEL: if (yesno_box("Confermare la cancellazione")) { _item.destroy(i, TRUE); a.destroy(i); _dirty = TRUE; } break; default: break; } } set_dirty(_dirty); return _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 << endl << endl; for(word i = 0; i < fields(); i++) out << field(i); } TForm_item& TPrint_section::find_field(short id) const { for(word i = 0; i < fields(); i++) { TForm_item& f = field(i); if (f.id() == id) return f; } yesnofatal_box("Can't find item whit id %d", id); return field(0); } /////////////////////////////////////////////////////////// // 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() {} }; 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() { TString80 i; const int w = _prompt[0] == '@' ? 3 : 1; i << 'W' << w << "l{" << _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); 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(); printer().setbackground(_back); return ok; } /////////////////////////////////////////////////////////// // TForm /////////////////////////////////////////////////////////// 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; if (scanner.popkey() == "KE") key = scanner.integer(); else scanner.push(); _cursor = new TCursor(_relation, "", key); 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(); 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(); if (isdigit(j[0])) _relation->add(atoi(j), exp, key, to, alias); // join file else _relation->add(j, exp, key, to, alias); // join table return TRUE; } 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.popkey() == "OF") // Offsets { _x = scanner.integer(); _y = scanner.integer(); } else scanner.push(); if (scanner.popkey() == "FO") // Font name _fontname = scanner.string(); else scanner.push(); if (scanner.popkey() == "SI") // Font size _fontsize = scanner.integer(); else scanner.push(); if (scanner.popkey() == "CA") // Carattere di posizionamento _char_to_pos = scanner.string()[0]; else scanner.push(); if (scanner.popkey() == "IN") // Riga e colonna del posizionamento iniziale { _ipx = scanner.integer(); _ipy = scanner.integer(); } else scanner.push(); if (scanner.popkey() == "FI") // Riga e colonna del posizionamento finale { _fpx = scanner.integer(); } else scanner.push(); if (scanner.popkey() == "GR") // Carattere di posizionamento _fink = scanner.string(); else scanner.push(); 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 \"" << (const char*)_fink << "\"\n"; out << "END\n" << endl; } TPrint_section* TForm::exist(char s, pagetype t, bool create) { 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 %d", id); return ps->find_field(id); } TPrint_section& TForm::section(char s, word p) { pagetype pos = odd_page; // It was p==0 if (p == 3 && exist(s, last_page)) pos = last_page; // It was p==1 if (p == 2 && exist(s, first_page)) pos = first_page; // It was pos == odd_page && (p & 0x1) == 0 if (p == 1 && exist(s, even_page)) pos = even_page; TPrint_section* sec = exist(s, pos, TRUE); return *sec; } // =========================================== // TForm // =========================================== bool TForm::ps_change_date_format(TPrint_section& s, const char* f) { for (word i = 0; i < s.fields(); i++) { TForm_item& fi = s.field(i); if (strcmp(fi.class_name(), "SEZIONE") == 0) { TPrint_section& ps = ((TForm_subsection&)fi).subsection(); ps_change_date_format(ps, f); } else if (strcmp(fi.class_name(), "DATA") == 0) ((TForm_date&)fi).set_format(f); } return TRUE; } bool TForm::ps_change_number_format(TPrint_section& s, int w, int dec, const char* p) { for (word i = 0; i < s.fields(); i++) { TForm_item& fi = s.field(i); if (strcmp(fi.class_name(), "SEZIONE") == 0) { TPrint_section& ps = ((TForm_subsection&)fi).subsection(); ps_change_number_format(ps, w, dec, p); } else if (strcmp(fi.class_name(), "NUMERO") == 0) { TForm_number& fn = (TForm_number&)fi; fn.set_width(w); fn.set_decimals(dec); fn.set_picture(p); } } 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); } word TForm::set_background(word p, bool u) { word len = 0; if (u && _back.items()) { TPrint_section& graph = section('G', p); graph.update(); len = printer().formlen(); } return len; } word TForm::set_header(word p, bool u) { 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(); } word TForm::set_body(word p, bool u) { TPrint_section& body = section('B', p); if (u) body.update(); else body.reset(); if (u) { TPrinter& pr = printer(); for (word j = 0; j < body.height(); j++) pr.print(body.row(j)); } return body.height(); } word TForm::set_footer(word p, bool u) { TPrinter& pr = printer(); pr.resetfooter(); TPrint_section& foot = section('F', p); if (u) foot.update(); else { foot.reset(); pr.footerlen(foot.height()); } for (word j = 0; j < foot.height(); j++) pr.setfooterline(j, foot.row(j)); return foot.height(); } void TForm::header_handler(TPrinter& p) { const word page = form().page(p); form().set_background(page, TRUE); form().set_header(page, TRUE); form().set_footer(page, FALSE); } void TForm::footer_handler(TPrinter& p) { const word page = form().page(p); form().set_footer(page, TRUE); if (page) form().set_header(page+1, FALSE); } word TForm::page(const TPrinter& p) const { return _lastpage ? 0 : p.getcurrentpage(); } void TForm::arrange_form() { TString device; #if XVT_OS == XVT_OS_WIN 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... #endif FILE* lpt = fopen(device,"w"); // 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 TForm::arange_form() ha senso solo su // stampanti ad aghi, che le stampanti ad aghi possono andare in emulazione EPSON o IBM, // che il codice per settare il font draft 17cpi e' lo stesso sia per EPSON che IBM // CHR(15), allora prima del posizionamento scrivo il chr(15) sulla stampante! int i, x; TString str_pos; if (lpt == NULL) fatal_box("Non rieso ad aprire il device %s.",device); TMask m("ba2100c"); // _ipy viene assunto uguale per entrambi i posizionamneti str_pos << "\017"; // Questo e' 15 in ottale... for (i=1; i < _ipy; i++) str_pos << "\n"; fprintf(lpt,"%s",(const char*) str_pos); fflush(lpt); // Salta le righe... fclose(lpt); str_pos.cut(0); //Azzera la stringa di posizionamento for (i=1; i < _ipx; i++) str_pos << " "; //Aggiunge gli spazi necessari... if (_ipx > 0 && _ipy > 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 TString bspc; bspc.fill('\b',str_pos.len()); // Questi servono per tornare indietro... do { lpt = fopen(device,"w"); if (lpt == NULL) fatal_box("Non rieso ad aprire il device %s.",device); // fprintf(lpt,"%s",(const char*) bspc); fprintf(lpt,"%s\n",(const char*) str_pos); fflush(lpt); fclose(lpt); } 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); #if XVT_OS != XVT_OS_WIN #pragma message ("Voglio proprio vedere come fai a gestire il posizionamento sotto Unix!") #endif } long TForm::records() const { const long r = cursor() ? cursor()->items() : 0; return r; } // Stampa gli items dal from a to // se to < 0 stampa fino alla fine del file bool TForm::print(long from, long to) { _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 (_char_to_pos != '\0' || (_ipx +_ipy+_fpx) != 0) // Effettua il posizionamento del form... { if (pr.printtype() == screenvis) error_box("Stampa a video selezionata. Non e' possibile effettuare il posizionamento."); else if (_arrange) arrange_form(); } 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(odd_page)); } pr.set_char_size(_fontsize); // Set font name and size pr.set_fontname(_fontname); // according to current form const bool was_open = pr.isopen(); _lastpage = 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; i++) { if (from < 0) to = from; else if (cursor()) *cursor() = i; const word h = set_body(page(pr), FALSE); if (h > pr.rows_left()) pr.formfeed(); set_body(page(pr), TRUE); } if (i == lastrec) { if (cursor()) *cursor() = i; _lastpage = TRUE; set_background(0, TRUE); set_header(0, TRUE); 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()) { 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; } } } bool TForm::validate(TForm_item& f, TToken_string&) { return FALSE; } void TForm::print_on(ostream& out) const { main_app().begin_wait(); if (relation()) { out << *relation() << "\nEND" << endl; print_description(out); } print_general(out); print_section(out, 'G'); print_section(out, 'H'); print_section(out, 'B'); print_section(out, 'F'); out << "END" << endl; main_app().end_wait(); } word TForm::height(word page) { word h = 0; if (_back.items() == 0) { if (_head.items() && exist('H', pagetype(page)) != NULL) h += section('H', page).height(); if (_body.items() && exist('B', pagetype(page)) != NULL) h += section('B', page).height(); if (_foot.items() && exist('F', pagetype(page)) != NULL) h += section('F', page).height(); } else h = printer().formlen(); return h; } bool TForm::read_profile() { 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()); for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next()) { const TString& s = rprof.get("SEZ"); const char sec = s[0]; 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"); } } return TRUE; } bool TForm::write_profile() { const char sechar[4] = { 'B', 'F', 'G', 'H' }; 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.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; } TForm::TForm(const char* name, const char* code, int lev, const char* desc) : _name(name), _code(code), _relation(NULL), _cursor(NULL), _rel_desc(NULL), _isnew(FALSE), _editlevel(lev), _desc(desc), _fontname("Roman 17cpi"), _fontsize(12), _x(0), _y(0), _char_to_pos('\0'), _ipx(0), _ipy(0), _fpx(0), _arrange(TRUE), _fink("+,+,+,+,+,+,+,+,+,-,|",','), _dirty(FALSE) { 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.write(); } else _desc = forms.get("DESC"); } // read base form TFilename n(_name); n.ext("frm"); TScanner scanner(n); bool ok = TRUE; if (scanner.popkey() == "US") // Parse relation { ok = parse_use(scanner); while (ok && scanner.popkey() == "JO") ok = parse_join(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 main_app().end_wait(); } TForm::~TForm() { if (_cursor) { delete _cursor; delete _relation; if (_rel_desc) delete _rel_desc; } }