#include #include #include // Ritorna TRUE se la stringa e' piena di zero static bool zero_only(const TString& v) { for (int i = v.len()-1; i>=0 && v[i]=='0'; i--); return i<0; } //////////////////////////////////////// TTracciato_Campo //////////////////////////////////////// TTracciato_campo::TTracciato_campo(int position, int length, int decimal, const char align, const char filler) : _position(position), _length(length), _decimal(decimal), _datatype('S'), _align(align), _filler(filler) {} TObject* TTracciato_campo::dup() const { TTracciato_campo* t = new TTracciato_campo(*this); return t; } const TTracciato_campo& TTracciato_campo::operator =(const TTracciato_campo& tc) { copy(tc); return *this; } void TTracciato_campo::copy(const TTracciato_campo& tc) { set_name(tc._name); set_datatype(tc._datatype); set_type(tc._type); set_field(tc._field); set_ftype(tc._ftype); set_position(tc._position); set_length(tc._length); set_decimal(tc._decimal); set_align(tc._align); set_filler(tc._filler); set_picture(tc._picture); set_message(tc._message); } // determina la lunghezza del campo da scrivere su file isam const int TFile_text::flength(const TTracciato_campo &tc , const TRectype & record ) const { if (tc.ftype().empty()) return tc.field().len(record); // il default è la lunghezza del campo isam else return ((TTracciato_campo &)_tipi[tc.ftype()]).length(); // altrimenti è quella definita nel FTYPE } const int TFile_text::fdecimal(const TTracciato_campo &tc ) const { if (tc.ftype().empty()) return tc.decimal(); else return ((TTracciato_campo &)_tipi[tc.ftype()]).decimal(); } const char TFile_text::falign(const TTracciato_campo &tc ) const { if (tc.ftype().empty()) return tc.align(); else return ((TTracciato_campo &)_tipi[tc.ftype()]).align(); } const char TFile_text::ffiller(const TTracciato_campo &tc ) const { if (tc.ftype().empty()) return tc.filler(); else return ((TTracciato_campo &)_tipi[tc.ftype()]).filler(); } const TString& TFile_text::fpicture(const TTracciato_campo &tc ) const { if (tc.ftype().empty()) return tc.picture(); else return ((TTracciato_campo &)_tipi[tc.ftype()]).picture(); } //////////////////////////////////////// TTracciato_record //////////////////////////////////////// void TTracciato_record::set_relation(TRelation* rel) { if (_rel) delete _rel; _rel = rel; } TObject* TTracciato_record::dup() const { TTracciato_record* t = new TTracciato_record(*this); return t; } TTracciato_record::TTracciato_record(const TTracciato_record& tr) : _rel(NULL) { set_relation(tr.relation()); set_type(tr.type()); _tracciati_campo = tr._tracciati_campo; } TTracciato_record::~TTracciato_record() { if (_rel) delete _rel; } void TTracciato_record::add(const TTracciato_campo& tc, int pos) { _tracciati_campo.add(tc,pos); } void TTracciato_record::add(TTracciato_campo* tc, int pos) { _tracciati_campo.add(tc,pos); } int TTracciato_record::get_pos(const char* name) const { for (int i = _tracciati_campo.last(); i >= 0; i = _tracciati_campo.pred(i)) { const TTracciato_campo& tc = get(i); if (tc.name() == name) break; } return i; } TTracciato_campo& TTracciato_record::get(int n) { if (TTracciato_record::ptr(n) == NULL)//se non esiste lo creo { TTracciato_campo* t = new TTracciato_campo(); add(t, n); } return (TTracciato_campo&)_tracciati_campo[n]; } //////////////////////////////////////// TRecord_text //////////////////////////////////////// const TString& TRecord_text::row(int pos) const { return _array.row(pos); } TString& TRecord_text::row(int pos) { return _array.row(pos); } void TRecord_text::add(const TString& c, int pos) { _array.add(c, pos); } //////////////////////////////////////// TFile_text //////////////////////////////////////// TTracciato_record* TFile_text::t_rec(const char* type) const { return (TTracciato_record*)_tracciati_record.objptr(type); } TTracciato_record* TFile_text::t_rec(int mainfile, const char * tabname) const { if (tabname) mainfile=(tabname[0] != '%') ? LF_TAB: LF_TABCOM; TTracciato_record *trrd; TAssoc_array &tr= ((TFile_text *)this)->_tracciati_record; tr.restart(); while (trrd=(TTracciato_record *)tr.get()) { if (trrd->relation() && trrd->relation()->lfile().num()==mainfile) if (tabname) { TTable & tab=(TTable & )trrd->relation()->lfile(); if (tabname == tab.name() ) break; } else break; } return trrd; } void TFile_text::set_gen_parm(TConfig& config, const TString& section) { _decsep = config.get_char("DECSEP",section); _recordsize = config.get_int("RECORDSIZE",section); // solo se a lung. fissa _fieldsep = config.get_char("FIELDSEP",section); // solo se a lung. variabile _recordsep = config.get("RECORDSEP",section); // solo se a lung. variabile if (_recordsize <= 0 && _recordsep.empty()) // separatore di record standard _recordsep = "\r\n"; if (_recordsep[0] == '\\') { if (_recordsep == "\\r") _recordsep = "\r"; else if (_recordsep == "\\n") _recordsep = "\n"; else if (_recordsep == "\\n\\r") _recordsep = "\n\r"; } _skiplines = config.get_int("SKIPLINES",section); // righe iniziali da ignorare _typefield = config.get_int("TYPEFIELD",section); // Numero del campo tipo (puo' essere -1) _fixedlen = _fieldsep <= ' '; // && _recordsep.blank(); _typepos = config.get_int("TYPEPOS", section, -1, -1); _typelen = config.get_int("TYPELEN", section, -1, 0); if (_typelen > 16) NFCHECK("Tipo record di lunghezza spropositata: %d", _typelen); } void TFile_text::set_type_parm(TConfig& config, TString& section) { TString lavoro = section; lavoro.ltrim(4);//elimino la parola 'TYPE' e gli spazi vuoti lavoro.trim();//per avere solo il nome del tipo predefinito TTracciato_campo tipo; tipo.set_type(lavoro); tipo.set_length(config.get_int("LENGTH", section)); tipo.set_decimal(config.get_int("DECIMAL", section)); tipo.set_align(config.get_char("ALIGN", section)); const char datatype=config.get_char("DATA", section); if (datatype>' ') tipo.set_datatype(datatype); else tipo.set_datatype('S'); TString s = config.get("FILLER", section); if (s.len() > 1) tipo.set_filler(s[1]); else tipo.set_filler(s[0]); tipo.set_picture(config.get("PICTURE", section)); _tipi.add(lavoro, tipo);// aggiungo il tracciato campo all'assoc_array dei tipi predefiniti } void TFile_text::set_rec_parm(TConfig& config, const char* section) { TString sectkey = section; sectkey.ltrim(6);//elimino la parola 'RECORD' o 'HEADER' o 'FOOTER' e gli spazi vuoti sectkey.trim();//per avere solo il nome del tipo del record TTracciato_record *tr=new TTracciato_record(sectkey);//istanzio un tracciato_record del tipo corrente //setto tutti i dati relatvi ai tipi predefini nei tracciati campo per i diversi campi del record TRelation *tmprel=NULL; // relazione associata al tracciato record config.set_paragraph(section); TString lavoro; TString_array variables; const int numvar = config.list_variables(variables, TRUE);//scarico tutte le variabili della sezione variables.sort(FALSE); TBit_array indici(numvar); indici.reset(); for (int j = 0; j < numvar; j++)//scandisco tutte le variabili della sezione { const TString key = variables.row(j).get(0);//estraggo nome const TString& obj = variables.row(j).get(1);//estraggo valore lavoro = key.left(3); int pos = key.find('('); int n = atoi(key.mid(pos+1, -1));//estraggo l'indice if (!indici[n]) { if (config.exist("TYPE", n)) { TString tipo = config.get("TYPE", section, n); if (!tipo.empty()) { TTracciato_campo& tc = (TTracciato_campo&)_tipi[tipo]; tr->add(tc, n); } } indici.set(n); } if (lavoro == "USE") // setta la relazione { CHECKS(tmprel==NULL,"Relazione già definita per il tracciato: %s",sectkey); if (atoi((const char *)obj)!=0) tmprel= new TRelation(atoi((const char *)obj)); else tmprel= new TRelation((const char *)obj); } if (lavoro == "JOI") // setta i join { CHECKS(tmprel, "Can't join to NULL relation %s", (const char*)j); TToken_string join_expr((const char *)obj,' '); // Join expression int token=0; TString16 j(join_expr.get(token++)); // file or table int to=0; // 'to' default: _relation->lfile()->num(); if (strcmp(join_expr.get(token++),"TO")==0) // TO keyword { const char* t = join_expr.get(token++); to = name2log(t); } else token --; int nkey = 1; if (strcmp(join_expr.get(token++),"KEY")==0) nkey = join_expr.get_int(token++); else token--; int alias = 0; if (strcmp(join_expr.get(token++),"ALIAS")==0) alias = join_expr.get_int(token++); else token--; TToken_string exp(80); if (strcmp(join_expr.get(token++),"INTO")==0) { const char* r = join_expr.get(token++); while (r && strchr(r, '=') != NULL) { exp.add(r); r = join_expr.get(token++); } } #ifdef DBG if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); #endif if (j[0] >= '0' && j[0] <= '9') { tmprel->add(atoi(j), exp, nkey, to, alias); // join file tmprel->write_enable(atoi(j),key.left(6)!="JOINRO"); } else { #ifdef DBG if (j.len() > 4) yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j); else #endif { tmprel->add(j, exp, nkey, to, alias); // join table tmprel->write_enable(j,key.left(6)!="JOINRO"); } } continue; } TTracciato_campo& tc = tr->get(n);//prendo il tracciato campo con indice if (lavoro == "NAM") { tc.set_name(obj); continue; } if (lavoro == "FIE") { TFieldref field; field = obj; tc.set_field(field); continue; } if (lavoro == "FTY") // field type { CHECKS(_tipi.objptr(obj)!=NULL,"Riferimento a campo inesistente:%s",obj); tc.set_ftype(obj); continue; } if (lavoro == "POS") { const int pos = atoi(obj); if (pos >= 0) { tc.set_position(pos); if (_typepos < 0 && n == _typefield) _typepos = pos; } continue; } if (lavoro == "LEN") { const int len = atoi(obj); if (tc.length() <= 0 && len > 0) { tc.set_length(len); if (_typelen < 0 && n == _typefield) _typelen = len; } continue; } if (lavoro == "DEC") { int dec = atoi(obj); if (tc.decimal() <= 0 && dec >= 0 && tc.decimal() != dec) tc.set_decimal(dec); continue; } if (lavoro == "ALI") { bool condition = tc.align() != obj[0]; if (condition) tc.set_align(obj[0]); continue; } if (lavoro == "FIL") { if (!obj.blank()) { bool condition = tc.filler() != obj[1]; if (condition) { if (obj.len() > 1) tc.set_filler(obj[1]); else tc.set_filler(obj[0]); } } continue; } if (lavoro == "PIC") { if (tc.picture().blank() && (!obj.blank())) tc.set_picture(obj); continue; } if (lavoro == "MES") { tc.set_message(obj); continue; } if (_fixedlen && _typelen < 0 && n == _typefield) _typelen = tc.length(); } tr->set_relation(tmprel); //aggiungo il tracciato record all'assoc_array dei tracciati record _tracciati_record.add(sectkey, tr); } TFile_text::TFile_text(const char* file_name, const char* config_name) : _name(file_name), _skiplines(0), _kill_zeroes(FALSE), _force_record_separator(FALSE) { _read_file = NULL; _write_file = NULL; TConfig config(config_name); TString_array paragraphs; config.list_paragraphs(paragraphs);//scarico la lista dei paragrafi int items = paragraphs.items();//quanti paragrafi ho scaricato TString section, sec; for (int i = 0; i < items; i++)//scandisco tutti i paragrafi { section = paragraphs.row(i) ;//prendo il nome del paragrafo sec = section.left(3);//prendo le prime tre lettere del nome if (sec == "MAI") //inizializzo i parametri generali del file { set_gen_parm(config,section); continue; } if (sec == "TYP") { set_type_parm(config, section); continue; } if (sec == "FTY") // field type { set_type_parm(config, section); continue; } if ((sec == "REC")||(sec == "HEA")||(sec == "FOO")) { set_rec_parm(config, section); continue; } } } TFile_text::~TFile_text() { if (_read_file) delete _read_file; if (_write_file) delete _write_file; _tipi.destroy(); _tracciati_record.destroy(); } //Legge da file il record text int TFile_text::read(TRecord_text& rec) { if (_read_file == NULL) open('r'); TToken_string buffer; if (_recordsize > 0) { if (buffer.size() < _recordsize) buffer.spaces(_recordsize); _read_file->read(buffer.get_buffer(), _recordsize); if (!ok_r()) return 1; //non ritorna errore se fine file ed il record e' completo! } else { if (_recordsep == "\r\n" || _recordsep == "\n\r") { const int maxsize = 1024*16; char* buf = buffer.get_buffer(maxsize); _read_file->get(buf, maxsize, _recordsep[0]); if (buffer.empty()) return EOF; char c = _read_file->get(); c = _read_file->get(); } else { //legge carattere per carattere fino a quando non si trova il separatore di record char c = _read_file->get(); if (c == EOF) return EOF; while (c != _recordsep[0]) { buffer << c; c = _read_file->get(); if (!ok_r()) return EOF; //non ritorna errore se fine file ed il record e' completo! } for (int j = _recordsep.len()-1; j > 0; j--) c = _read_file->get(); } } if (_fieldsep > ' ') { buffer.separator(_fieldsep); const char* tipo = _typefield >= 0 ? buffer.get(_typefield) : ""; TTracciato_record& tr = *t_rec(tipo); rec.set_type(tipo);//istanzio il tipo del record text TArray& a_tc = tr.tracciati_campo(); const int items = a_tc.items(); buffer.restart(); TString lavoro; for (int i = 0; i < items; i++) { buffer.get(i, lavoro); rec.add(lavoro, i); } } else { TString16 tipo; if (_typepos >= 0 && _typelen > 0) { tipo = buffer.mid(_typepos, _typelen); tipo.trim(); } rec.set_type(tipo);//istanzio il tipo del record text TTracciato_record* tr = t_rec(tipo); if (tr != NULL) { //ora che ho il tracciato record devo scandire i tracciati campo e caricare il record text const TArray& a_tc = tr->tracciati_campo(); const int items = a_tc.items(); for (int i = 0; i < items; i++) { TTracciato_campo& tc = tr->get(i); const int pos = tc.position(); const int len = tc.length(); const TString& lavoro = buffer.mid(pos, len); rec.add(lavoro, i); } } } return 0; } //Scrive su file il record_text (valido anche per header e footer) int TFile_text::write(TRecord_text& rec) { TString campo; TToken_string buffer; const TString& type = rec.type(); TTracciato_record& tr = *t_rec(type); TArray& a_tc = tr.tracciati_campo(); const int items = rec.items(); if (_typepos>=0) rec.add(type,_typepos); if (_fixedlen) // campi a lunghezza fissa { for (int i = 0; i < items; i++) { TTracciato_campo& tc = tr.get(i); campo = rec.row(i); format_textfield(tc, campo); buffer.overwrite(campo, tc.position()); } CHECK(_write_file, "Impossibile scrivere su un file chiuso."); if (_recordsize<=0) { // Record a lunghezza var *_write_file << buffer; *_write_file << _recordsep; } else { // Record a lunghezza fissa buffer.rpad(_recordsize); buffer.cut(_recordsize); *_write_file << buffer; if (_force_record_separator) *_write_file << _recordsep; } if (!ok_w()) return 1; } else { buffer.separator(_fieldsep); for (int i = 0; i < items; i++) { TTracciato_campo& tc = tr.get(i); campo = format_textfield(tc, rec.row(i)); buffer.add(campo); } CHECK(_write_file, "Impossibile scrivere su un file chiuso."); *_write_file << buffer; *_write_file << _recordsep; if (!ok_w()) return 1; } return 0; } // Carica tutti i dati del tracciato record (anche header o footer) // nel record_text bool TFile_text::autoload(TRecord_text& rec, int mainfile) { TTracciato_record* tr = t_rec(mainfile); if (tr) { // esiste il tracciato e posso fare l'autoload TCursor cur(tr->relation()); rec.set_type(tr->type()); return _autoload(rec,cur,*tr); } //CHECK (FALSE,"Il tracciato record non esiste"); return FALSE; } // Carica tutti i dati del tracciato record (anche header o footer) // nel record_text bool TFile_text::autoload(TRecord_text& rec, const char * tabname) { TTracciato_record* tr = t_rec(tabname); if (tr) { // esiste il tracciato e posso fare l'autoload TCursor cur(tr->relation()); rec.set_type(tr->type()); return _autoload(rec,cur,*tr); } //CHECK (FALSE,"Il tracciato record non esiste"); return FALSE; } //Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text bool TFile_text::autoload(TRecord_text& rec, TCursor& cur , const TString* tipo) { const TString& type = rec.type(); if (tipo == NULL) tipo = &type; TTracciato_record* tr = t_rec(*tipo); CHECKS(tr!=NULL,"Tracciato record file di testo non trovato ",(const char *)*tipo); return _autoload(rec,cur,*tr); } bool TFile_text::autoload(TCursor& cur, const TString* tipo) { CHECK(_current,"Record corrente non settato"); return autoload(*_current, cur, tipo); } //Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text bool TFile_text::_autoload(TRecord_text& rec, TCursor& cur , TTracciato_record& tr ) { TString campo; TRelation& rel = *cur.relation(); TArray& a_tc = tr.tracciati_campo(); int items = a_tc.items(); for (int i = 0; i < items; i++) { TTracciato_campo& tc = tr.get(i); const TFieldref& field = tc.field(); if (field.name().empty()) campo = field.read(rel); const TString& message = tc.message(); if (!message.empty()) { TToken_string msg (message, ','); if (!msg.blank()) validate(cur, rec, msg, campo); } rec.add(campo, i); campo.cut(0); } return can_write(rec,rel); } int TFile_text::autosave(const TRecord_text& rec, int mainfile ) { const TString& type = rec.type();//prendo il tracciato record del tipo del record_text TTracciato_record* tr = t_rec(type); if (tr) { TRelation* rel = tr->relation(); if (rel && (mainfile==0 || rel->lfile().num()==mainfile)) return _autosave(*rel,rec, *tr); } return NOERR; // l'assenza del tracciato non significa un errore } int TFile_text::autosave(TRelation& rel, const TRecord_text& rec) { const TString& type = rec.type();//prendo il tracciato record del tipo del record_text TTracciato_record& tr = *t_rec(type); return _autosave(rel,rec, tr); } int TFile_text::autosave(int mainfile) { CHECK(_current,"Record corrente non settato"); return autosave(*_current,mainfile); } //Carico la relazione con i dati del record text int TFile_text::_autosave(TRelation& rel, const TRecord_text& rec, TTracciato_record& tr ) { TArray& a_tc = tr.tracciati_campo(); int items = a_tc.items(); TString valore; for (int i = 0; i < items; i++) { const TTracciato_campo& tc = tr.get(i); if (tc.field().name().not_empty()) { const TFieldref& field = tc.field(); // if (field.file()==0) // field.set_file(rel.lfile().num()); valore = rec.row(i); // formatta il campo del file di testo secondo le specifiche del campo su file isam preformat_field(field,valore,rel,tr.type()); const TRectype& rel_rec = rel.curr(field.file()); TFieldtypes tipo_campo = rel_rec.type(field.name()); switch(tipo_campo) { case _datefld: { if (real::is_null(valore)) valore.cut(0); TDate data(valore); format_date(data, fpicture(tc), valore);//formatta la data secondo le specifiche del tracciato } break; case _realfld: case _intfld: case _longfld: { real numero(valore); valore = numero.string(fpicture(tc));//formatta il numero secondo le specifiche del tracciato int length = flength(tc,rel_rec); if (falign(tc) == 'L') valore.left_just(length, ffiller(tc)); else valore.right_just(length, ffiller(tc)); int j = valore.replace('.', _decsep); //!?!?! consento decsep diversi per isam e text ? CHECK(j >= 0 && j <= 1 , "Impossibile scrivere più separatori decimali."); } break; default: if (_kill_zeroes && zero_only(valore)) valore = ""; valore = format_field(tc, rel.lfile().num(), valore);//formatta il campo secondo le specifiche del record break; } if (rel.exist(field.file())) field.write(valore, rel);//faccio una write sulla relazione del fieldref } } if (pre_writerel(rel,rec)) { int err= rel.write(); if (err == _isdupkey || err ==_isreinsert) err = rel.rewrite(); return err; } return NOERR; } //Scarica dal record_text il campo alla posizione const TString& TFile_text::get_field(const TRecord_text& rec, int ncampo) { /* Guy was here const TString& type = rec.type();//prendo il tracciato record del tipo del record_text TTracciato_record tr(type); TTracciato_campo& tc = tr.get(ncampo); */ return rec.row(ncampo); } //Scarica dal record_text il campo const TString& TFile_text::get_field(const TRecord_text& rec, const char* name) { TTracciato_record* tr = t_rec(rec.type()); if (tr != NULL) { const int ncampo = tr->get_pos(name); if (ncampo >= 0) return rec.row(ncampo); } NFCHECK("Campo inesistente %s", name); return EMPTY_STRING; } //Carica nel record_text il campo alla posizione con il valore già formattato void TFile_text::add_field(TRecord_text& rec, const int ncampo, const char* val) { TTracciato_record* tr = t_rec(rec.type()); CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type()); TTracciato_campo& tc = tr->get(ncampo); rec.add(val, ncampo); } //Carica nel record_text il campo con il valore già formattato void TFile_text::add_field(TRecord_text& rec, const char* name, const char* val) { TTracciato_record* tr = t_rec(rec.type()); CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type()); int ncampo = tr->get_pos(name); CHECKS(ncampo >= 0, "Campo inesistente ", name); rec.add(val, ncampo); } //Formatta la data in base al tracciato void TFile_text::format_date(const TDate& data, const TString& form, TString& data_str) { int i = 1, cnt = 0; char x = form[0]; do { char k = x; if (k != 'a' && k != 'm'&& k != 'g') data_str << k; else cnt++; x = form[i]; i++; if (k != x) switch (k) { case 'g': CHECKD(cnt >= 1 && cnt <= 4, "Formato per giorno non valido ", cnt); if (cnt == 1) data_str << data.day(); if (cnt == 2) { TString16 s; s.format("%02d", data.day()); data_str << s; } if (cnt == 3) { TString16 s = itow(data.wday()); s.cut(3); data_str << s; } if (cnt == 4) data_str << itow(data.wday()); cnt = 0; break; case 'm': CHECKD(cnt >= 1 && cnt <= 4, "Formato per mese non valido ", cnt); if (cnt == 1) data_str << data.month(); if (cnt == 2) { TString16 s; s.format("%02d", data.month()); data_str << s; } if (cnt == 3) { TString16 s = itom(data.month()); s.cut(3); data_str << s; } if (cnt == 4) data_str << itom(data.month()); cnt = 0; break; case 'a': CHECKD(cnt >= 2 && cnt <= 4, "Formato per anno non valido ", cnt); if (cnt == 2) {TString s;s << data.year();s.ltrim(2);data_str << s;} if (cnt == 3) {TString s;s << data.year();s.ltrim(1);data_str << s;} if (cnt == 4) data_str << data.year(); cnt = 0; break; } } while (i <= form.len()); } // Formatta la stringa in base alle definizioni del tracciato // La stringa ritornata rappresenta il valore del campo nel filetext e i parametri di fomattazione // sono quelli associati al campo nel filetext TString& TFile_text::format_textfield(const TTracciato_campo& tc, TString& campo) { //int pos = tc.position(); int length = tc.length(); char fillch=tc.filler(); if (!tc.picture().blank()) { switch (tc.datatype()) { case 'N': // number { real tmp(campo); campo=tmp.string(tc.picture()); } break; case 'D': //data { TFormatted_date tmp(TDate (campo),tc.picture()); campo=tmp.string(); } break; default: { TString tmp; tmp.picture(tc.picture(), campo); campo=tmp; } } } if (length > campo.len()) { if (fillch == '\0' && _fixedlen) fillch=' '; if (tc.align() == 'R') campo.right_just(length,fillch); else campo.left_just(length, fillch); } else { if (length > 0) { if (tc.align() == 'R') campo=campo.right(length); else campo.cut(length); } } return campo; } // Formatta la stringa passata in base al field del file isam // La stringa ritornata rappresenta il valore del campo nel file isam e i parametri di fomattazione // sono quelli associati al campo nel file isam (metodi fpicture, falign ecc.) TString& TFile_text::format_field(const TTracciato_campo& tc, short lfile, TString& campo) { const TRectype record(tc.field().file() ? tc.field().file() : lfile); int length = flength(tc,record); const bool is_memo = record.type(tc.field().name()) == _memofld; if (!fpicture(tc).blank()) { TString tmp; tmp.picture(fpicture(tc), campo); campo=tmp; } if (length > campo.len() || is_memo) // Se il field di destinazione e' un memo... si scrive tutto! { if (falign(tc) == 'R') campo.right_just(length, ffiller(tc)); else campo.left_just(length, ffiller(tc)); } else { if (length > 0) { if (falign(tc) == 'R') campo=campo.right(length); else campo.cut(length); } } return campo; } int TFile_text::open(char mode) { if (mode == 'r')//apertura in lettura { if (_read_file) delete _read_file; _read_file = new ifstream(_name, ios::binary | ios::nocreate); if (!ok_r()) { error_box("Impossibile aprire il file %s in lettura", (const char *)_name); return _read_file->rdstate() != ios::goodbit; } if (_skiplines > 0) { if (_recordsize > 0) { streamoff bytestoskip = streamoff(_recordsize) * _skiplines; _read_file->seekg(bytestoskip, ios::beg); } else if (_recordsep.not_empty()) { int s = _skiplines; for (int c = _read_file->get(); c != EOF; c = _read_file->get()) { if (c == _recordsep[0]) { for (int k = _recordsep.len()-1; k > 0; k--) c = _read_file->get(); if (--s == 0) break; } } if (c == EOF) return 1; } } } if (mode == 'w')//apertura in scrittura { if (_write_file) delete _write_file; _write_file = new ofstream(_name, ios::binary|ios::app); } return 0; } int TFile_text::open(const char* name, char mode) { set_name(name); return open(mode); } int TFile_text::close() { _name = ""; _current = NULL; if (_read_file) _read_file->close(); if (_write_file) _write_file->close(); return 0; }