#include #include #define __ISAM_CPP #ifndef FOXPRO #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #if XVT_OS==XVT_OS_WIN #include #else #include #include #include #endif #define NOT_LINKED(i,f) CHECKS(i != NULL, "Record senza tracciato: impossibile eseguire ", f) #define NOT_OPEN() CHECKS(_isamfile != NULL, "File chiuso: ", (const char*)name()) //#define INTTLOCK 0x600 #define RECLOCKTYPES 0xFF00 #define READTYPES 0x00FF isfdptr* openf; Str80 cprefix; HIDDEN int error_codes_g[] = {-1,_isnotopen,-1,-1,-1,_islocked,-1,-1,-1,-1,-1,-1,_isfilefull, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,_iskeynotfound,_ispatherr,-1,-1,_isdupkey}; HIDDEN int error_codes_ra[] = {NOERR,NOERR,_iskeynotfound,_iseof,_isbof,_isnrecerr} ; // Codici da 0 a 9 HIDDEN int error_codes_rb[] = {-1,-1,_isreinsert,-1,-1,_islocked,-1,_isalropen,_iskeyerr } ; // Codici da 10 a ... extern "C" { void CUpString(char*); void crtrim(char*); }; HIDDEN char _isam_string[257]; HIDDEN void UNKNOWN_FIELD(int num, const char* name) { yesnofatal_box("Il campo '%s' non appartiene al file %d", name, num); } #define NOALLOC (char **) -1 HIDDEN bool __autoload = TRUE; //////////////////////////////////////////////////////////////////////////////////////////////////// // Funzioni implementate per la gestione file dati tramite Codebase //////////////////////////////////////////////////////////////////////////////////////////////////// // Inizio(@) void get_idx_names(int logicnum, TToken_string& i_names) // Returns a Token_string with the index names. (Current prefix!) { long c = DB_getconf(); TDir d; TTrec r; d.get(logicnum); r.get(logicnum); TFilename f(d.name()); if ( c & 1) f.ext("cdx"); if ( c & 4) f.ext("mdx"); i_names.cut(0); i_names.add(f); f.ext(""); f.rtrim(1); if (c & 2 || c & 8) // DBIII or CLIPPER format, returns f_name + .cgp, f_nameX + .n{d|t}x for (int j=1; j<=r.keys();j++) { TString xx=f.name(); if (xx.len()<8) f << ('0' + j); else f[8] = ('0' + j); if (c & 2) // CLIPPER f.ext("ndx"); else // DBIII f.ext("ntx"); i_names.add(f); } i_names.restart(); } int get_error(int err) { if (err > 0) { if (err >= 10) { if (err > 80 || error_codes_rb[err/10]==-1) return err; else return(error_codes_rb[err/10]); } else return(error_codes_ra[err]); } else if (err < 0) { int ierr = DB_get_error(); if (ierr < 0) ierr = -ierr; if (ierr > 340 || error_codes_g[ierr/10]==-1) return (-ierr); return (error_codes_g[ierr/10]); } DB_zero_error(); return(NOERR); } HIDDEN void browse_null(char *start, int nc) { for (int i = nc - 1; i >= 0 ; i--) // Anche il primo byte(deletion flag) deve essere cambiato. nc comprende il primo byte if (start[i] == '\0') start[i] = ' '; } HIDDEN void getisfd(isfdptr & isfd, int logicnum) { isfd = new isdef ; isfd->r = new RecDes ; isfd->d = new FileDes ; CGetFile(logicnum, isfd->d, _nolock, _nordir); const TFixed_string name(isfd->d->SysName); if (name.not_empty() && name[0] == '%') isfd->ft = _comdir; else isfd->ft = _nordir; COpenFile(logicnum, isfd->d, _nolock, isfd->ft); CGetRec(logicnum, isfd->r, isfd->ft); isfd->ln = logicnum; } HIDDEN void relisfd(isfdptr & isfd) { if (isfd->ln > 0 && isfd->fhnd >= 0) { TDir d; d.get(isfd->ln, _lock, (TDirtype) isfd->ft, _sysdirop); d.eod() = isfd->d->EOD; d.eox() = isfd->d->EOX; d.put(isfd->ln, (TDirtype) isfd->ft, _sysdirop); } delete isfd->d; delete isfd->r; delete isfd; } HIDDEN int CBuildKey(RecDes *recd, int numkey, RecType recin, char *key, bool build_x_cb) /* *recd; descrittore record */ /* numkey; numero chiave */ /* recin; buffer contenente il record */ /* *key; valore della chiave */ /* build_x_cb flag di costruzione per codebase */ { key[0] = '\0'; if (numkey-- <= recd->NKeys) { int l = 0; for (int i = 0; i < recd->Ky[numkey].NkFields; i++) { const KeyDes& kd = recd->Ky[numkey]; const bool upp = kd.FieldSeq[i] > MaxFields; const int nf = upp ? kd.FieldSeq[i] - MaxFields : kd.FieldSeq[i]; const RecFieldDes& rf = recd->Fd[nf]; int off, len; if (kd.FromCh[i] == 255) { off = rf.RecOff; len = rf.Len; } else { off = rf.RecOff + kd.FromCh[i]; len = kd.ToCh[i] - kd.FromCh[i] + 1; } if ((l + len) > 80) { key[0] = '\0'; return(_iskeylenerr); } strncpy((key + l), (recin + off), len); const TFieldtypes f = (TFieldtypes) rf.TypeF; if (recin[off] == '\0') { memset(key + l, ' ', len); if (build_x_cb && ((f == _intfld) || (f == _longfld) || (f == _wordfld))) key[l + len - 1] = '0'; } else if ((f == _intfld) || (f == _longfld) || (f == _wordfld)) { int w = l, j = l + len; while (w < j && key[w] == ' ') w++; while (w < j && key[w] == '0') key[w++] = ' '; if (build_x_cb && (w == j)) key[w-1] = '0'; } if (upp) for (int i = l+len-1; i >= l; i--) key[i] = toupper(key[i]); l += len; } while (l > 0 && key[l-1] == ' ') l--; key[l] = '\0'; return(NOERR); } return(_ispatherr); } HIDDEN int cisstart(isfdptr isfd, int keynum, TRectype & record, unsigned int mode) { // It seems quite unuseful... Quando cambio la chiave con setkey, la d4tagselect // seleziona gia' l'indice, rendendo inutile il senso della cisstart return NOERR; } HIDDEN int cisread(isfdptr isfd, TRectype & record, int mode) { int rmode = (mode & READTYPES), lmode = (mode & RECLOCKTYPES); // Non usare mai _isnextn o _isprevn, usare il metodo skip! CHECK (rmode !=_isnextn && rmode !=_isprevn, "_isnextn and _isprevn not supported in cisread"); // BOOLEAN nolock = (lmode == _nolock); // BOOLEAN unlock = (lmode == _unlock); // BOOLEAN tlock = (lmode == INTTLOCK); char key[128]; int err = NOERR ; // if (nolock || unlock /* || tlock */) lmode = 0; do { if (rmode>=_isequal && rmode<=_isgteq) { err=CBuildKey(isfd->r, isfd->knum, record.string(),key,TRUE); if (err == NOERR) { err=DB_seek(isfd->fhnd,key); if (err != NOERR)err=get_error(err); } if (rmode != _isequal && err == _iskeynotfound) err = NOERR; } else { if (rmode==_isfirst) err=DB_first(isfd->fhnd); else if (rmode==_islast) err=DB_last(isfd->fhnd); else if (rmode==_isnext) err=DB_next(isfd->fhnd); else if (rmode==_isprev) err=DB_prev(isfd->fhnd); else if (rmode==_iscurr) err=DB_go(isfd->fhnd,DB_recno(isfd->fhnd)); if (err != NOERR) err=get_error(err); } if (err == _iseof) DB_last(isfd->fhnd); if (err == NOERR && (lmode == _lock || lmode == _testandlock)) // _lock e _testandlock { err=DB_lock(isfd->fhnd); if (err != NOERR) err=get_error(err); if (err == _islocked && lmode == _testandlock) break; } if (/* !tlock && */ err == _islocked) { memcpy(record.string(),DB_getrecord(isfd->fhnd),DB_reclen(isfd->fhnd)); CBuildKey(isfd->r, isfd->knum, record.string(), key, TRUE); message_box("Codice %s in uso da parte\ndi un altro utente.", key); } } while (/* !tlock && */ err ==_islocked); if (err == NOERR && lmode == _unlock) { err=DB_unlock(isfd->fhnd); if (err != NOERR) err=get_error(err); } memcpy(record.string(),DB_getrecord(isfd->fhnd),DB_reclen(isfd->fhnd)); isfd->RecNo = DB_recno(isfd->fhnd); return err; } HIDDEN int delkeys(isfdptr fd, char* record,long recno) { int rt=NOERR,oldkey = fd->knum; for (int i=1; i<=fd->r->NKeys;i++) { char key[128]; DB_tagselect(fd->fhnd,i); rt=CBuildKey(fd->r,i,record,key,TRUE); if (rt!=NOERR) break; rt=DB_delkey(fd->fhnd,key,recno); if (rt!=NOERR) break; } DB_tagselect(fd->fhnd,oldkey); return(rt); } //////////////////////////////////////////////////////////////////////////////////////////////////// // Funzioni implementate per la gestione file dati tramite Codebase //////////////////////////////////////////////////////////////////////////////////////////////////// // Fine(@) void set_autoload_new_files(bool on) { __autoload = on; } /////////////////////////////////////////////////////////// // TExtrectype /////////////////////////////////////////////////////////// class TExtrectype : public TRectype { RecDes* _rd; protected: // TRectype virtual RecDes* rec_des() const { return _rd; } public: // FPUB TExtrectype(const TTrec& r); // Costruisce il record a partire da r virtual ~TExtrectype(); }; TExtrectype::TExtrectype(const TTrec& r) : TRectype(6) { delete _rec; _length = r.len(); _rec = new char [ _length ]; // _i = new isdef; // _i->r = r.rec(); _rd = r.rec(); zero(); } TExtrectype::~TExtrectype() { // delete _rec; // delete _i; } /////////////////////////////////////////////////////////// // TBaseisamfile /////////////////////////////////////////////////////////// TBaseisamfile::TBaseisamfile(int logicnum, bool linkrecinst) { _isamfile = NULL; _logicnum = logicnum; _lasterr = NOERR; _delopenrec = FALSE; if ((openrec[_logicnum - 1] == NULL) || (!linkrecinst)) { _current = new TRectype(this); if (openrec[_logicnum - 1] == NULL) { openrec[_logicnum - 1] = _current; _delopenrec = TRUE; } _delrec = TRUE; } else { _current = openrec[_logicnum - 1]; _delrec = FALSE; } // _historicfile = ((r.field(RFLD_SYS_DATE) != FIELDERR) && // (r.field(RFLD_SYS_FIRST) != FIELDERR) && // (r.field(RFLD_SYS_LAST) != FIELDERR)); _historicfile = FALSE; } TBaseisamfile::~TBaseisamfile() { if (_delrec) { if (_delopenrec) openrec[_logicnum - 1] = NULL; delete _current; } if (_isamfile != NULL) delete _isamfile; } int TBaseisamfile::gethr(TRectype& rec, TDate& atdate) { TRecfield fd0(rec, RFLD_SYS_DATE); TDate d0((const TDate&) fd0); if (d0 < atdate) { atdate = eotime; return NOERR; } TRectype wr(rec); TRecfield flf(wr, RFLD_SYS_FIRST), fll(wr, RFLD_SYS_LAST), fd1(wr, RFLD_SYS_DATE); TDate d1; TRecnotype wr0 = -1L, wr1 = -1L; if ((wr0 == flf.ptr()) == -1L) return _iskeynotfound; _hf.read(wr.string(), wr0); if ((d1 = (const TDate&) fd1) > atdate) { rec = wr; atdate = d0 - 1L; return _iskeynotfound; } while ((d1 < atdate) && (wr0 > 0)) { rec = wr; wr1 = wr0; if ((wr0 = fll.ptr()) > 0) { _hf.read(wr.string(), wr0); d1 = (const TDate&) fd1; } } if (wr0 <= 0) atdate = d0 - 1L; else atdate = d1 - 1L; return NOERR; } int TBaseisamfile::addhr(const TRectype& rec, TDate& atdate) { return NOERR; } int TBaseisamfile::rewhr(const TRectype& rec, TDate& atdate) { return NOERR; } int TBaseisamfile::delhr(const TRectype& rec, TDate& atdate) { return NOERR; } long TBaseisamfile::items() const { return(DB_reccount(filehnd()->fhnd)); } const char* TBaseisamfile::name() const { sprintf(_isam_string, "%d", num()); return _isam_string; } const char* TBaseisamfile::filename() const { if (_isamfile == NULL) { TDir d; d.get(num()); strcpy(_isam_string, d.name()); return _isam_string; } return _isamfile->d->SysName; } const char* TBaseisamfile::description() const { if (_isamfile == NULL) { TDir d; d.get(num()); strcpy(_isam_string, d.des()); return _isam_string; } return _isamfile->d->Des; } TRecnotype TBaseisamfile::eod() const { NOT_OPEN(); return(DB_reccount(_isamfile->fhnd)); } void TBaseisamfile::setkey(int nkey) { CHECKD(nkey > 0 && nkey-1 <= _isamfile->r->NKeys, "Chiave non valida ", nkey); NOT_OPEN(); int rt = DB_tagselect(_isamfile->fhnd,nkey); if (rt>=0) _isamfile->knum=nkey; if (rt!=NOERR) rt=get_error(rt); if (_lasterr == NOERR) setstatus(rt); } int TBaseisamfile::getkey() const { NOT_OPEN(); CHECK(DB_tagget(_isamfile->fhnd) == _isamfile->knum, "Chiave inconsistente"); return _isamfile->knum; } int TBaseisamfile::first(word lockop) { NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), _isfirst + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::last(word lockop) { NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), _islast + lockop ); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::next(word lockop) { NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), _isnext + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::next(TDate& atdate) { error_box("TBaseisamfile::next(TDate&) is no more available"); return NOERR; } int TBaseisamfile::prev(word lockop) { NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), _isprev + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::prev(TDate& atdate) { error_box("TBaseisamfile::prev(TDate&) is no more available"); return NOERR; } int TBaseisamfile::reread(word lockop, TDate& atdate) { NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), _iscurr + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::reread(TRectype& rec, word lockop, TDate& atdate) { NOT_OPEN(); rec.setdirty(); _lasterr=cisread(_isamfile, rec, _iscurr + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::skip(TRecnotype nrec, word lockop) { int rmode = (lockop & READTYPES), lmode = (lockop & RECLOCKTYPES); // BOOLEAN nolock = (lmode == _nolock); // BOOLEAN unlock = (lmode == _unlock); // BOOLEAN tlock = (lmode == INTTLOCK); char key[128]; NOT_OPEN(); if (!nrec) return NOERR; curr().setdirty(); _lasterr=DB_skip(_isamfile->fhnd,nrec); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); do { if (/* !tlock && */ _lasterr == _islocked) { CBuildKey(_isamfile->r, DB_tagget(_isamfile->fhnd), curr().string(), key,TRUE); message_box("Codice %s in uso da parte\ndi un altro utente.", key); } _lasterr=cisread(_isamfile,curr(),_iscurr + lockop); } while (/* !tlock && */ _lasterr ==_islocked); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::read(word op, word lockop, TDate& atdate) { CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op); NOT_OPEN(); curr().setdirty(); _lasterr=cisread(_isamfile, curr(), op + lockop); if (_lasterr != NOERR) _lasterr=get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::read(TRectype& rec, word op, word lockop, TDate& atdate) { CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op); NOT_OPEN(); rec.setdirty(); _lasterr=cisread(_isamfile, rec, op + lockop); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::readat(TRecnotype nrec, word lockop) { NOT_OPEN(); curr().setdirty(); _lasterr=DB_go(_isamfile->fhnd,nrec); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); else memcpy(curr().string(),DB_getrecord(_isamfile->fhnd),DB_reclen(_isamfile->fhnd)); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop) { NOT_OPEN(); rec.setdirty(); _lasterr=DB_go(_isamfile->fhnd,nrec); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); else memcpy(rec.string(),DB_getrecord(_isamfile->fhnd),DB_reclen(_isamfile->fhnd)); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::write(TDate& atdate) { CHECK(!curr().empty(), "Can't write an empty record"); NOT_OPEN(); int oldkey=getkey(); browse_null(curr().string(),DB_reclen(_isamfile->fhnd)); TRectype r(curr()); setkey(1); // if (cisread(_isamfile, r, _isequal + _nolock) != NOERR) // { memcpy(DB_getrecord(_isamfile->fhnd),curr().string(),DB_reclen(_isamfile->fhnd)); _lasterr = DB_add(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); // } // else // _lasterr=_isreinsert; setkey(oldkey); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::write(const TRectype& rec, TDate& atdate) { CHECK(!rec.empty(), "Can't write an empty record"); NOT_OPEN(); int oldkey=getkey(); browse_null(rec.string(),DB_reclen(_isamfile->fhnd)); TRectype r(rec); setkey(1); // if (cisread(_isamfile, r, _isequal + _nolock) != NOERR) // { memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd)); _lasterr = DB_add(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); // } // else // _lasterr=_isreinsert; setkey(oldkey); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::rewrite(TDate& atdate) { CHECK(!curr().empty(), "Can't rewrite an empty record"); NOT_OPEN(); TRectype save_rec(curr()); _lasterr = cisread(_isamfile, save_rec, _isequal + _nolock); // Si Posiziona per sicurezza... if (_lasterr == NOERR) { memcpy(DB_getrecord(_isamfile->fhnd), curr().string(),DB_reclen(_isamfile->fhnd)); _lasterr = DB_rewrite(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); } return _lasterr; } int TBaseisamfile::rewrite(const TRectype& rec, TDate& atdate) { CHECK(!rec.empty(), "Can't write an empty record"); NOT_OPEN(); TRectype save_rec(rec); _lasterr = cisread(_isamfile, save_rec, _isequal + _nolock); // Si Posiziona per sicurezza... if (_lasterr == NOERR) { memcpy(DB_getrecord(_isamfile->fhnd), rec.string(),DB_reclen(_isamfile->fhnd)); _lasterr = DB_rewrite(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); } return _lasterr; } int TBaseisamfile::rewriteat(TRecnotype nrec) { NOT_OPEN(); if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR) { memcpy(DB_getrecord(_isamfile->fhnd),curr().string(),DB_reclen(_isamfile->fhnd)); _lasterr=DB_rewrite(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); } else _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec) { NOT_OPEN(); if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR) { memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd)); _lasterr=DB_rewrite(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); } else _lasterr = get_error(_lasterr); _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::remove(TDate& atdate) { CHECK(!curr().empty(), "Can't remove empty record"); NOT_OPEN(); // rimozione campi memo #ifndef FOXPRO TMemo_file* memo = NULL; for (int i = 0; i < curr().items(); i++) { if (curr().type(curr().fieldname(i)) == _memofld) { long val = curr().get_long(curr().fieldname(i)); if (val > 0l) { if (memo == NULL) memo = new TMemo_file(filename()); memo->remove_field(val); } } } if (memo != NULL) delete memo; #endif if ((_lasterr=cisread(_isamfile, curr(), _isequal + _lock)) == NOERR) { _lasterr = DB_delete(_isamfile->fhnd); // Put only deletion flag on record, must remove keys too! if (_lasterr != NOERR) _lasterr = get_error(_lasterr); else { _lasterr=delkeys(_isamfile,curr().string(), _isamfile->RecNo); if (_lasterr != NOERR) { DB_recall(_isamfile->fhnd); _lasterr = get_error(_lasterr); } } } _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::remove(const TRectype& rec, TDate& atdate) { CHECK(!rec.empty(), "Can't remove an empty record"); NOT_OPEN(); memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd)); if ((_lasterr=cisread(_isamfile, (TRectype&) rec, _isequal + _lock))==NOERR) { _lasterr = DB_delete(_isamfile->fhnd); // Put only deletion flag on record, must remove keys too! if (_lasterr != NOERR) _lasterr = get_error(_lasterr); else { _lasterr=delkeys(_isamfile,rec.string(),_isamfile->RecNo); if (_lasterr != NOERR) { DB_recall(_isamfile->fhnd); _lasterr = get_error(_lasterr); } } } _recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd); return _lasterr; } int TBaseisamfile::lock() { NOT_OPEN(); _lasterr = DB_lockfile(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); return _lasterr; } int TBaseisamfile::unlock() { NOT_OPEN(); _lasterr = DB_unlock(_isamfile->fhnd); if (_lasterr != NOERR) _lasterr = get_error(_lasterr); return (_lasterr); } void TBaseisamfile::indexon() { } bool TBaseisamfile::empty() { return (DB_reccount(_isamfile->fhnd) == 0); } void TBaseisamfile::indexoff() { } int TBaseisamfile::_open(unsigned int mode) { CHECKS(filehnd() == NULL, "File already open ", (const char*)filename()); getisfd(_isamfile,num()); if ((filehnd()->fhnd = DB_open(filehnd()->d->SysName,mode==_excllock)) >= 0) { TRecnotype n=DB_reccount(filehnd()->fhnd); TDir d; // d.get(num()); d.get(num(),_nolock,_nordir,_sysdirop); if (d.is_com()) d.get(num(),_nolock,_comdir); if ((filehnd()->d->EOD != n && n > 0) || (n >= d.eox())) { filehnd()->d->EOD = d.eod() = n; filehnd()->d->EOX = d.eox() = (TRecnotype) (n*1.2); if (d.is_com()) d.put(num(),_comdir); else d.put(num()); } filehnd()->ln = num(); openf[num() - 1] = filehnd(); _recno = -1L; CHECKD(filehnd()->r->NKeys > 0, "File senza indici: ", num()); setkey(1); _lasterr = NOERR; } else { _lasterr = get_error(filehnd()->fhnd); relisfd(_isamfile); fatal_box("Il file %d non puo' essere aperto, errore %d",num(),_lasterr); } return (_lasterr); } int TBaseisamfile::_close() { int err = NOERR; if (filehnd() != NULL) { if (num() > 0) { TDir d; TRecnotype n=DB_reccount(filehnd()->fhnd); //d.get(num()); d.get(num(),_nolock,_nordir,_sysdirop); if (d.is_com()) d.get(num(),_nolock,_comdir); if ((filehnd()->d->EOD != n && n > 0) || (n >= d.eox())) { filehnd()->d->EOD=d.eod()=n; filehnd()->d->EOX = d.eox() = (TRecnotype) (n*1.2); if (d.is_com()) d.put(num(),_comdir); else d.put(num()); } CHECK(openf[num() - 1] != NULL, "Open file array corrupted"); err=DB_close(filehnd()->fhnd); if (err != NOERR) err = get_error(err); if ((err == NOERR) && (num() > 0)) openf[num() - 1] = NULL ; } else if (filehnd() == NULL) { err = _isnotopen; error_box("File n. %d close : Error n. %d ", num(), err); } if (err == NOERR) { relisfd(_isamfile); clearfilehnd(); } } // _current->_i = NULL; setstatus(err); return err; } /////////////////////////////////////////////////////////// // TLocalisamfile /////////////////////////////////////////////////////////// // Attenzione linkrecinst puo' valere 0, 1, 2. // Se vale 2 significa che si sta costruendo un file temporaneo // per cui linkrecinst va' considerato FALSE TLocalisamfile::TLocalisamfile(int logicnum, bool linkrecinst) : TBaseisamfile(logicnum, linkrecinst == TRUE) { if (linkrecinst <= TRUE) { open(); if (_was_open) _oldkey = getkey(); setkey(1); } else _was_open = FALSE; } TLocalisamfile::~TLocalisamfile() { if (_was_open) setkey(_oldkey); close(); } int TLocalisamfile::close() { int err = NOERR; if (!_was_open) { clearfilehnd(); } else { if (_isamfile) { TRecnotype n = DB_reccount(filehnd()->fhnd); TDir d; //d.get(num()); d.get(num(),_nolock,_nordir,_sysdirop); if (d.is_com()) d.get(num(),_nolock,_comdir); if ((filehnd()->d->EOD!=n && n > 0) || (n > d.eox())) { filehnd()->d->EOD = d.eod() = n; filehnd()->d->EOX = d.eox() = n; if (d.is_com()) d.put(num(),_comdir); else d.put(num()); } err = DB_close(_isamfile->fhnd); if (err != NOERR) err = get_error(err); relisfd(_isamfile); _isamfile=NULL; } openf[num() -1] = NULL; } setstatus(err); return err; } int TLocalisamfile::open(unsigned int mode) { int err = NOERR; const int logicnum = num(); if (openf[logicnum - 1] != NULL) { _was_open = FALSE; _isamfile = openf[logicnum - 1]; } else { err = _open(); _was_open = TRUE; } // _current->_i = filehnd(); setstatus(err); return err; } int TLocalisamfile::operator +=(const TRecnotype npos) { skip(npos); return status(); } int TLocalisamfile::operator -=(const TRecnotype npos) { skip(-npos); return status(); } int TLocalisamfile::operator ++() { next(); return status(); } int TLocalisamfile::operator --() { prev(); return status(); } TIsamfile::TIsamfile(int logicnum, bool linkrecinst) : TBaseisamfile(logicnum, linkrecinst) {} TIsamfile::~TIsamfile() { close(); } int TIsamfile::flags(bool updateeod) { TDir d; int err = NOERR; if (filehnd()->ln <= 0) return NOERR ; NOT_OPEN(); const TDirtype dirtype = (TDirtype) filehnd()->ft; d.get(num(), _lock, dirtype); if ((err = d.status(dirtype)) == NOERR) { d.flags() = filehnd()->d->Flags; if (updateeod) d.eod() = filehnd()->d->EOD; d.put(num(), dirtype); } setstatus(err); return err; } /////////////////////////////////////////////////////////// // TIsamtempfile /////////////////////////////////////////////////////////// TIsamtempfile::TIsamtempfile(int logicnum, const char* radix, bool create) : TLocalisamfile(logicnum, 2) { TRecnotype eod = 0; TRecnotype eox = 100; TFilename n; if (radix && *radix) { if (*radix == '%') n = radix; else { n.tempdir(); n << '/' << radix; } } n.ext("dbf"); if (!create) { TDir dir; dir.get(logicnum); const word& len = dir.len(); // Tolgo il % senno' che fa la fopen ? if (n[0] == '%') n = n.sub(1); FILE* f = fopen(n, "r"); #if XVT_OS == XVT_OS_WIN CHECKS(f, "Can't open temporary file ", (const char*)strerror(NULL)); #else CHECKS(f, "Can't open temporary file ", (const char*)n); #endif fseek(f, 0, SEEK_END); eod = eox = ftell(f) / len; fclose(f); } _autodel = create > TRUE; n.ext(""); // Ci rimetto il % se prima l'avevo tolto, senno' che fa la open ? // if (*radix == '%') if (n[0] != '%') n.insert("%", 0); open(n, create, eod, eox); } TIsamtempfile::~TIsamtempfile() { close(); } int TIsamtempfile::open(const char* radix, bool create, TRecnotype eod, TRecnotype eox) { int err = NOERR; TFilename tmpname; CHECKS(filehnd() == NULL, "File already open", (const char*)filename()); if (radix[0] == '%') tmpname << &radix[1] ; else tmpname.temp(radix); getisfd (_isamfile, num()); strcpy(filehnd()->d->SysName, (const char*)tmpname); filehnd()->d->EOX = eox; if (create) { err=DB_build(filehnd()->d->SysName, filehnd()->r) ; if (err == NOERR) filehnd()->d->EOD = 0L; else { err = get_error(err); relisfd(_isamfile); fatal_box("Create temporary file: Error n. %d ", errno); } } else filehnd()->d->EOD = eod; filehnd()->fhnd = DB_open(filehnd()->d->SysName, 0); if (filehnd()->fhnd < 0) err = get_error(filehnd()->fhnd); if (err != NOERR) { relisfd(_isamfile); fatal_box("Open temporary file: Error n. %d ",errno); } else { filehnd()->ln = -num(); filehnd()->knum = 1 ; } // _current->_i = filehnd(); _recno = -1L; setstatus(err); return err; } int TIsamtempfile::close() { int err = NOERR; if (filehnd() != NULL) { err=DB_close(filehnd()->fhnd); if (err != NOERR) err = get_error(err); if (_autodel && err==NOERR) { TFilename f(filehnd()->d->SysName); long c = DB_getconf(); f.ext("dbf"); ::remove((const char*)f); if (c & 1) // FOXPRO format f.ext("cdx"); if (c & 4) // DBIV format f.ext("mdx"); if (c & 8 || c & 2) // CLIPPER and DBIII format { f.ext("cgp"); FILE *fp=fopen((const char*)f,"r"); char in[16]; while (fgets(in,16,fp)!=NULL) { TFilename a(in); if (c & 8) // DBIII format a.ext("ndx"); else a.ext("ntx"); // CLIPPER format ::remove((const char *)a); } fclose(fp); } ::remove((const char *)f); } relisfd(_isamfile); clearfilehnd(); } // _current->_i = NULL; setstatus(err); return err; } /////////////////////////////////////////////////////////// // TSystemsamfile /////////////////////////////////////////////////////////// int TSystemisamfile::build(TRecnotype eox) { CHECKS(filehnd() == NULL, "Can't build open file", (const char*)filename()); int err=NOERR; TDir d; TTrec r; d.get(num()); r.get(num()); TFilename f(d.name()); f = f.path(); if (!is_not_slash(f.right(1)[0])) f.rtrim(1); if (!fexist(f)) make_dir(f); err=DB_build(d.name(),r.rec()); if (err == NOERR) { isfdptr i; getisfd(i,num()); i->d->EOX = eox; relisfd(i); } else err = get_error(err); setstatus(err); clearfilehnd(); #ifndef FOXPRO if (err == NOERR && __autoload) { TFilename lf; lf.format("%sstd/lf%04d.txt", __ptprf, num()); if (fexist(lf)) load(lf, '|', '\0', '\n', TRUE, TRUE); } #endif return err; } int TSystemisamfile::extend(TRecnotype eox) { int err = NOERR; isfdptr i; CHECKS(filehnd() == NULL, "Can't extend open file ", (const char*)filename()); getisfd(i,num()); if (num() > 0) { if (eox < i->d->EOD) err = _ispathfull; else i->d->EOX = eox; } relisfd(i); setstatus(err); clearfilehnd(); return err; } long TSystemisamfile::size(TRecnotype eox) { const long size = (100 * (unsigned)512); return size; } #ifndef FOXPRO bool TSystemisamfile::exec_convapp(long flev, const bool before) { const char * const v = before ? "BCNV" : "ACNV"; if (flev == 0) flev = 199401; else flev++; for (long l = flev; l <= get_std_level(); l++) { TString16 paragraph(format("%06ld", l)); TConfig conv(CONFIG_FCONV, paragraph); if (!conv.new_paragraph() && conv.exist(v, num())) { int err = 0; TString80 s(conv.get(v, NULL, num())); s << " " << main_app().get_firm(); TExternal_app app(s); if (app.can_run()) { app.run(); err = app.error(); TMailbox mail; TMessage* msg = mail.next(TRUE); if (err == 0 && msg != NULL) err = atoi(msg->body()); } else err = 16; if (err) return error_box("Impossibile eseguire il programma di %sconversione\ndel livello %ld/%ld\nErrore n.ro %d", before ? "pre" : "post", l / 100, l % 100, err); } } return TRUE; } bool TSystemisamfile::getlcf(long flev) { _flds.destroy(); _exps.destroy(); if (flev == 0) flev = 199401; else flev++; for (long l = flev; l <= get_std_level(); l++) { TString16 paragraph(format("%06ld", l)); TConfig conv(CONFIG_FCONV, paragraph); if (!conv.new_paragraph() && conv.exist("F", num())) { TToken_string exprline(conv.get("F", NULL, num())); if (exprline.empty()) return FALSE; TToken_string w("", '='); const char * wexprs = exprline.get(); while (wexprs != NULL) { w = wexprs; TFixed_string fld(w.get()); _flds.add(new TFieldref(fld, 0)); _exps.add(new TExpression(w.get(), _strexpr)); wexprs = exprline.get(); } } } return _flds.items() > 0; } void TSystemisamfile::makelc(TRectype& rec) { for (int i = 0 ; i < _flds.items(); i++) { TFieldref& f = (TFieldref&) _flds[i]; TExpression& e = (TExpression & )_exps[i]; for (int k = 0; k < e.numvar(); k++) e.setvar(k, get(e.varname(k))); f.write(e, rec); } } int TSystemisamfile::update(TTrec& newrec, bool vis) { CHECKS(filehnd() == NULL, "Can't update open file", (const char*)filename()); TDir dir; dir.get(num(), _unlock, _nordir, _sysdirop); const char p = *dir.name(); const bool is_com = prefix().is_com(); const bool toconvert = is_com ? dir.is_com() : dir.is_firm(); int err = NOERR; TTrec oldrec; oldrec.get(num()); const long lev = prefix().filelevel(); const bool lcf = getlcf(lev); exec_convapp(lev, TRUE); if (!lcf && newrec == oldrec) { exec_convapp(lev, FALSE); return NOERR; } const TRecnotype nitems = dir.eod(); const unsigned int lenr = newrec.len(); if (!toconvert && dir.eox() > 0L) { dir.eod() = 0L; dir.eox() = 0L; } if (toconvert && dir.eox() > 0L) { TRecnotype ni = 0L; isfdptr i0; TFilename tmpfname("tmpf"); open(_excllock); getisfd(i0, num()); err=DB_build((const char*) tmpfname, newrec.rec()); if (err != NOERR) { err=get_error(err); return (err); } i0->fhnd=DB_open((const char*)tmpfname,0); if (i0->fhnd < 0 ) err=get_error(i0->fhnd); TFilename fname(filename()); TString s(80); s.format("Aggiornamento archivio %s", (const char*) fname); TProgind p(nitems ? nitems : 1, s, TRUE, TRUE, 70); int nflds = curr().items(); TArray fld(nflds); TExtrectype nrec(newrec); TRecnotype i = 0; for (int j = 0; j < nflds; j++) fld.add(TString(curr().fieldname(j)), j); for (first(); good(); next()) { if ((i++ % 50) == 0) p.setstatus(i + 1); nrec.zero(); ni++; for (j = 0; j < nflds; j++) if (nrec.exist((const TString&) fld[j])) nrec.put((const TString&) fld[j], get((const TString&) fld[j])); if (lcf) makelc((TRectype &)nrec); memcpy(DB_getrecord(i0->fhnd),nrec.string(),DB_reclen(i0->fhnd)); err=DB_add(i0->fhnd); if (err != NOERR) err=get_error(err); setstatus(err); } err=DB_close(i0->fhnd); close(); if (err!=NOERR) err=get_error(err); relisfd(i0); p.setstatus(nitems); if (err == NOERR) { long c = DB_getconf(); fname.ext("dbf"); tmpfname.ext("dbf"); fcopy((const char*)tmpfname,(const char*)fname); ::remove((const char*)tmpfname); if (c & 1) // FOXPRO format tmpfname.ext("cdx"); if (c & 4) // DBIV format tmpfname.ext("mdx"); if (c & 8 || c & 2) { tmpfname.ext("cgp"); char in[16]; FILE *fp=fopen((const char *) tmpfname,"r"); while (fgets(in,16,fp)!=NULL) { TFilename a(in); a.rtrim(1); // Cut \n if (c & 8) // DBIII format a.ext("ndx"); else a.ext("ntx"); // CLIPPER format ::remove((const char *)a); } fclose(fp); } ::remove((const char*)tmpfname); dir.eod() = ni; } } dir.set_len(lenr); dir.put(num(), _nordir, _sysdirop); newrec.put(num()); if (toconvert && dir.eox() > 0L) packindex(); exec_convapp(lev, FALSE); setstatus(err); return err; } int TSystemisamfile::packfile(bool vis) { int err=NOERR; TDir d; d.get(num()); CHECKS(filehnd() == NULL, "Can't pack open file", (const char*)filename()); err=DB_packfile(vis,d.name(),d.eod()); if (err != NOERR) err = get_error(err); if (err != NOERR) error_box("Errore in compattamento dati.\nFile %d : %d", num(),err); setstatus(err); return err; } int TSystemisamfile::packindex(bool vis) { int err=NOERR; TRecnotype peod; TTrec r; TDir d; CHECKS(filehnd() == NULL, "Can't pack index of open file", (const char*)filename()); r.get(num()); d.get(num()); err=DB_packindex(vis,d.name(),r.rec(),&peod); if (err != NOERR) err = get_error(err); if (err != NOERR) error_box("Errore in compattamento indici.\nFile %d : %d", num(),err); else if (peod >= 0 && peod != d.eod()) { d.eod() = peod; d.put(num()); } setstatus(err); return err; } int TSystemisamfile::pack(bool vis) { int err=NOERR; if ((err=packfile(vis))==NOERR) err=packindex(vis); setstatus(err); return err; } int TSystemisamfile::load(const char* from, char fs, char fd, char rs, bool vis, bool extended) { FILE* fl = fopen(from, "r+"); int err = ferror(fl); TRecnotype r = 0, e = 0, nitems = 0, nread = 0; TString16 firm, year, attprev("00000"); if (extended) { TDate d(TODAY); TLocalisamfile ditte(LF_NDITTE); firm.format("%05ld", main_app().get_firm()); year.format("%04d", d.year()); ditte.zero(); ditte.put("CODDITTA", firm); if (ditte.read() == NOERR) attprev = ditte.get("CODATTPREV"); } if (fl == NULL) { clearerr(fl); setstatus(err); return err; } char w[80]; while ((fgets(w, 80, fl) != NULL)) { if (strncmp(w, "[Data]", 6) == 0) { nitems = ftell(fl); break; } } fseek(fl, 0L, SEEK_END); nitems = ftell(fl) - nitems; fclose(fl); TScanner f(from); open(); TToken_string s(1024, fs); bool fixedlen = (fs == '\0'); int nflds = curr().items(); TArray fld(nflds); int len[MaxFields]; TString sfd(3); TString s1(64); bool lcf = FALSE; if (f.paragraph("Header")) { f.equal(); const long level = atol(f.line()); if (level > get_std_level()) error_box("L'archivio %s e' stato generato con gli archivi di livello %ld%/%ld.\n Il livello attuale e' %ld/%ld.\n Convertire gli archivi e ripetere l' operazione.", from, level/100, level%100, get_std_level()/100, get_std_level()%100); lcf = getlcf(level); nflds = 0; TToken_string s2(f.line()); int p = s2.find('='); if (p > 0) { s1 = s2.left(p); s2.ltrim(p+1); } else s1.cut(0); while (s1 == "Fields") { for (const char * fd = s2.get(); fd != NULL; fd = s2.get()) { TToken_string wfd(fd, ','); fld.add(new TString(wfd.get())); len[nflds] = wfd.get_int(); nflds++; } s2 = f.line(); p = s2.find('='); if (p > 0) { s1 = s2.left(p); s2.ltrim(p+1); } else s1.cut(0); } } else { for (int j = 0; j < nflds; j++) { fld.add(TString(curr().fieldname(j)), j); const TString & wfld = (const TString & ) fld[j]; len[j] = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld); } } if (!f.paragraph("Data")) { error_box("Formato dei dati non valido"); close(); err = 1; setstatus(err); return err; } if (fd) sfd << fd; int last = NOERR; s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last); TProgind p(nitems, s1, TRUE, TRUE, 70); s = f.line(); while (s.not_empty() && !p.iscancelled()) { if (extended) { int p, i; while ((p = s.find("%yr%")) >= 0) for (i = 0; i < 4; i++) s[p + i] = year[i]; while ((p = s.find("%frm%")) >= 0) for (i = 0; i < 5; i++) s[p + i] = firm[i]; while ((p = s.find("%att%")) >= 0) for (i = 0; i < 5; i++) s[p + i] = attprev[i]; } if ((r + e) % 50 == 0) { s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last); p.set_text(s1); } p.setstatus(nread + 1); nread += s.len() + 1; zero(); if (fixedlen) { int pos = 0; for (int j = 0; j < nflds; j++) { s1 = s.mid(pos,len[j]); s1.rtrim(); put((const TString&) fld[j], s1); pos += len[j]; } } else { s.restart(); for (int j = 0; j < nflds; j++) { char* s2 = (char*) s.get(); if (fd) { s2++; s2[strlen(s2) - 1] = '\0'; } put((const TString&) fld[j], s2); } } if (write() == NOERR) r++; else { e++; last = status(); } s = f.line(); } s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last); p.set_text(s1); close(); setstatus(err); return err; } int TSystemisamfile::dump(const char* to, int nkey, char fs, char fd, char rs, bool vis, bool withdeleted) { FILE* f = fopen(to, "w"); int err = ferror(f); if (withdeleted) nkey = 0; if (f == NULL) { clearerr(f); setstatus(err); return err; } open(); TString s(512); bool fixedlen = (fs == '\0'); int nflds = curr().items(); TArray fld(nflds); TBit_array rjust(nflds); int len[MaxFields]; for (int j = 0; j < nflds; j++) { fld.add(TString(curr().fieldname(j)), j); const TString & wfld = (const TString&) fld[j]; const TFieldtypes t = curr().type(wfld); rjust.set(j, t == _intfld || t == _longfld || t == _realfld || t == _wordfld || t == _intzerofld || t == _longzerofld); len[j] = (t == _datefld) ? 10 : curr().length(wfld); } TRecnotype i = 0; const TRecnotype nitems = nkey ? items() : filehnd()->d->EOD; s.format("Esportazione archivio %s", filename()); TProgind p(nitems, s, TRUE, TRUE, 70); TString s1; fprintf(f, "[Header]\nVersion=%ld", prefix().filelevel()); for (int k = 0; k < nflds; k++) { if ((k % 10) == 0) fprintf(f, "\nFields="); else fprintf(f, "|"); fprintf(f, "%s,%d", (const char *) (const TString&) fld[k], len[k]); } fprintf(f, "\n\n[Data]\n"); if (nkey) { setkey(nkey); for ( first(); status() == NOERR && !p.iscancelled(); next(), i++) { p.setstatus(i + 1); s = ""; for (j = 0; j < nflds; j++) { if (fixedlen) { s1 = get((const TString&)fld[j]); if (rjust[j]) s1.right_just(len[j]); else s1.left_just(len[j]); } else { s1 = ""; if (j && fs) s1 << fs; if (fd) s1 << fd; s1 << get((const TString&)fld[j]); if (fd) s1 << fd; } s << s1; } fprintf(f, "%s%c", (const char*) s, rs); } } else { for (i = 0; i < nitems && !p.iscancelled(); i++) { zero(); p.setstatus(i + 1); readat(i + 1); s=""; if (withdeleted || curr().valid()) { for (j = 0; j < nflds; j++) { if (fixedlen) { s1 = get((const TString&)fld[j]); if (rjust[j]) s1.right_just(len[j]); else s1.left_just(len[j]); } else { s1 = ""; if (j && fs) s1 << fs; if (fd) s1 << fd; s1 << get((const TString&)fld[j]); if (fd) s1 << fd; } s << s1; } fprintf(f, "%s%c", (const char*) s, rs); } } } p.setstatus(nitems); close(); fclose(f); setstatus(err); return err; } #endif // FOXPRO void TBaseisamfile::recover() { } //////////////////////////////////////////////////////////// // TRectype //////////////////////////////////////////////////////////// TRectype::TRectype(int logicnum) : _cod(NULL) { _logicnum = logicnum; // _i = openf[_logicnum - 1]; if (openf[_logicnum - 1] != NULL) _length = DB_reclen(openf[logicnum - 1]->fhnd); else { TDir wdir; wdir.get(_logicnum, _nolock, _nordir, _sysdirop); if (wdir.name()[0] == '%') wdir.get(_logicnum, _nolock, _comdir, _sysdirop); _length = wdir.len(); } _rec = new char [ _length ]; *_tab = '\0'; setempty(TRUE); } TRectype::TRectype(const TBaseisamfile* i): _cod(NULL) { _logicnum = i->num(); if (i->filehnd() != NULL) _length = DB_reclen(i->filehnd()->fhnd); else { TDir wdir; wdir.get(_logicnum, _nolock, _nordir, _sysdirop); if (wdir.name()[0] == '%') wdir.get(_logicnum, _nolock, _comdir, _sysdirop); _length = wdir.len(); } *_tab = '\0'; _rec = new char [ _length ]; //_i = i->filehnd(); setempty(TRUE); } TRectype::TRectype(const TRectype& r) : _cod(NULL) { _logicnum = r._logicnum; _length = r.len(); _rec = new char [ _length ]; _rec[0] = r._rec[0]; memcpy(_rec + 1, r._rec + 1, _length - 1); // _i = r._i; strcpy(_tab, r._tab); if (r._cod != NULL) _cod = new TRecfield(*this, "COD"); setempty(r.empty()); } TRectype::~TRectype() { if (_cod != NULL) delete _cod; delete _rec; } void TRectype::settab(const char *tab) { if (_cod != NULL) { delete _cod; _cod = NULL; } strcpy(_tab, tab); if (*_tab != '\0') _cod = new TRecfield(*this, "COD"); zero(); } TObject* TRectype::dup() const { TRectype* o = new TRectype(*this); return o; } HIDDEN bool fld_empty(const char* s, int len, bool number) { /*if (number) { for (; len; s++, len--) if (strchr(" 0.", *s) == NULL) return FALSE; } else */ if (*s) { for (; len; s++, len--) if (*s != ' ') return FALSE; } return TRUE; } HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number) { for (int i = 0; i < len && *a == *b; b++, a++, i++); if (i == len) return 0; int res = *a - *b; if (number) { b -= i; i = 0; } return fld_empty(b, len - i, number) ? 0 : res; } /////////////////////////////////////////////////////////// // TRectype (record di un file) /////////////////////////////////////////////////////////// RecDes* TRectype::rec_des() const { const isdef* i = openf[_logicnum-1]; NOT_LINKED(i, "Record description"); RecDes* r = i->r; CHECK(r, "Missing record description"); return r; } int TRectype::items() const { return rec_des()->NFields; } const char* TRectype::start(int nf) const { return string() + rec_des()->Fd[nf].RecOff; } int TRectype::compare(const TSortable& s) const { const TRectype& br = (const TRectype&) s; int res = 0; if (br.empty()) return UNDEFINED; for (int i = 0; i < items() ; i++) { const char* b = br.start(i); const char* a = start(i); const byte typ = rec_des()->Fd[i].TypeF; /* if (typ == _boolfld) res = *a - *b; else { */ const int sz = rec_des()->Fd[i].Len; const bool number = (typ == _intfld) || (typ == _realfld) || (typ == _longfld) || (typ == _wordfld) || (typ == _intzerofld) || (typ == _longzerofld) || (typ == _datefld) ; if (fld_empty(b, sz, number)) continue; res = ::fld_cmp(a, b, sz, number); /* } */ if (res) return res; } return 0; } TFieldtypes TRectype::type(const char* fieldname) const { // NOT_LINKED(_i, "type"); return (TFieldtypes) CFieldType((char*) fieldname, rec_des()); } int TRectype::length(const char* fieldname) const { // NOT_LINKED(_i, "length"); return CFieldSize((char*) fieldname, rec_des()); } int TRectype::ndec(const char* fieldname) const { // NOT_LINKED(_i, "dec"); return CFieldDec((char*) fieldname, rec_des()); } bool TRectype::exist(const char* fieldname) const { // NOT_LINKED(_i, "exist"); return findfld(rec_des(), (char*)fieldname) != -1; } const char* TRectype::fieldname(int i) const { // NOT_LINKED(_i, "fieldname"); RecDes* rd = rec_des(); return i >= 0 && i < rd->NFields ? rd->Fd[i].Name : NULL; } const char* TRectype::get_str(const char* fieldname) const { RecDes* rd = rec_des(); if (CFieldType((char*) fieldname, rd) == _datefld) { const TRecfield f((TRectype&)*this, fieldname); strcpy(_isam_string, (const char*) f); } else { if (CGetFieldBuff((char*) fieldname, rd, _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); if (CFieldType((char*) fieldname,rd) == _boolfld) { if (toupper(*_isam_string) == 'T' || toupper(*_isam_string) == 'Y' || toupper(*_isam_string) == 'S' || toupper(*_isam_string) == 'X') strcpy(_isam_string,"X"); else strcpy(_isam_string," "); } } return _isam_string; } #ifndef FOXPRO const TString& TRectype::get(const char* fieldname) const { static TFixed_string tmp(_isam_string, sizeof(_isam_string)); get_str(fieldname); return tmp; } int TRectype::get_int(const char* fieldname) const { // NOT_LINKED(_i, "get_int"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); return atoi(_isam_string); } long TRectype::get_long(const char* fieldname) const { // NOT_LINKED(_i, "get_long"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); return atol(_isam_string); } word TRectype::get_word(const char* fieldname) const { // NOT_LINKED(_i, "get_word"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); return (word)atoi(_isam_string); } real TRectype::get_real(const char* fieldname) const { // NOT_LINKED(_i, "get_real"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); real r(_isam_string); return r; } char TRectype::get_char(const char* fieldname) const { // NOT_LINKED(_i, "get_char"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); return *_isam_string; } bool TRectype::get_bool(const char* fieldname) const { // NOT_LINKED(_i, "get_bool"); if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1) UNKNOWN_FIELD(num(), fieldname); if (toupper(*_isam_string) == 'T' || toupper(*_isam_string) == 'Y' || toupper(*_isam_string) == 'S' || toupper(*_isam_string) == 'X') return TRUE; else return FALSE; } bool TRectype::get_memo(const char* fieldname, TTextfile& txt) const { long val = get_long(fieldname); bool ok = FALSE; if (ok = (val != 0l)) { TLocalisamfile f(_logicnum); TMemo_file memo(f.filename()); ok |= memo.get_field(txt, val); } return ok; } #endif // FOXPRO TDate TRectype::get_date(const char* fieldname) const { // NOT_LINKED(_i, "get_date"); const TRecfield f((TRectype&)*this, fieldname); return (TDate) f; } #ifndef FOXPRO void TRectype::put(const char* fieldname, int val) { // NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, long val) { // NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, TTextfile& txt) { long val = get_long(fieldname); bool isnew = val == 0; TLocalisamfile f(_logicnum); TMemo_file memo(f.filename()); long id = memo.set_field(txt, isnew ? -1 : val); if (isnew) val = id; TString16 str; str << val; if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)(const char*)str, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, word val) { // NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, const real& val) { // NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, rec_des(), val.ptr(), _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, const TDate& val) { // NOT_LINKED(_i, "put"); TRecfield f(*this, fieldname); f = val.string(full); setempty(FALSE); } void TRectype::put(const char* fieldname, char val) { // NOT_LINKED(_i, "put"); char w[2] = {val, '\0'}; if (CPutFieldBuff((char*) fieldname, rec_des(), w, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, bool val) { // NOT_LINKED(_i, "put"); char* s = val ? "T" : "F"; if (CPutFieldBuff((char*) fieldname, rec_des(), s, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } #endif // FOXPRO void TRectype::put(const char* fieldname, const char* val) { // NOT_LINKED(_i, "put"); if (val == NULL || *val == '\0') // Da provare { TRecfield f(*this, fieldname); if (*f.pos() == '\0') return; } if (CFieldType((char*) fieldname, rec_des()) == _datefld) { TRecfield f(*this, fieldname); f = val; } else { TString wval; wval=val; if (CFieldType((char*) fieldname,rec_des()) == _boolfld) { if (toupper(*val) == 'T' || toupper(*val) == 'Y' || toupper(*val) == 'S' || toupper(*val) == 'X') wval="T"; else wval="F"; } if (CPutFieldBuff((char*) fieldname, rec_des(), (char*) (const char*)wval, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); } setempty(FALSE); } void TRectype::zero(const char* fieldname) { // NOT_LINKED(_i, "zero"); if (_cod != NULL && strcmp(fieldname , "COD") == 0) *_cod = _tab; else { if (CFieldType((char*) fieldname, rec_des()) == _datefld) { TRecfield f(*this, fieldname); f = ""; } else if (CZeroField((char*) fieldname, rec_des(), _rec) == -1) UNKNOWN_FIELD(num(), fieldname); } } void TRectype::zero() { zero('\0'); } void TRectype::zero(char c) { // NOT_LINKED(_i, "zero"); recall(); memset(_rec + 1, c, len() - 1); if (_cod != NULL) *_cod = _tab; setempty(TRUE); } // Certified 99% TRectype& TRectype::operator =(const TRectype& rec) { CHECK(num() == rec.num(), "Can't assign records of different file"); // _i = rec._i; // Copy filehndl memcpy(_rec, rec._rec, _length); // Copy contents setempty(rec.empty()); // Copy emptiness status return *this; } // Certified 100% TRectype& TRectype::operator =(const TBaseisamfile& f) { return *this = f.curr(); } // Certified 99% TRectype& TRectype::operator =(const char* rec) { memcpy(_rec, rec, _length); setempty(FALSE); return *this; } const char* TRectype::key(int numkey) const { // NOT_LINKED(_i, "key"); CBuildKey(rec_des(), numkey, _rec, _isam_string,FALSE); return _isam_string; } /////////////////////////////////////////////////////////// // TRecfield (campo/sottocampo di un record) /////////////////////////////////////////////////////////// void TRecfield::set(int from, int to) { int nf; RecDes* rd = _rec->rec_des(); if ((nf = findfld(rd, _name)) == -1) { _p = NULL; _len = 0; _dec = 0; _type = _nullfld; yesnofatal_box("File n. %d unknown field %s", _rec->num(), _name); } else { CHECK(from >= 0, "Invalid Start"); _p = _rec->string() + rd->Fd[nf].RecOff + from; _dec = rd->Fd[nf].Dec; _type = rd->Fd[nf].TypeF; if (to >= 0) { CHECK(from <= to && to <= rd->Fd[nf].Len, "Invalid Range"); _len = to - from + 1; } else _len = rd->Fd[nf].Len - from; } } TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to) { // NOT_LINKED(rec.filehnd(), "TRecfield"); strcpy(_name, name); _rec = &rec; set(from, to); } HIDDEN void __getfieldbuff(byte l, byte t, const char* recin, char *s) { if (recin == NULL) { *s = '\0'; return; } if ((t != _alfafld) && (t != _datefld)) { while ((*recin == ' ') && (l)) { recin++; l--; } if ((t != _realfld) && (t != _charfld) && (t != _intzerofld) && (t != _longzerofld)) { while ((*recin == '0') && (l)) { recin++; l--; } } } if (l) { strncpy(s, recin, l); for (int i = l-1; i >= 0 && s[i] == ' '; i--); l = byte(i+1); } s[l] = '\0'; if (t == _datefld && *s) { TDate dt(atol(s)); strcpy(s, dt.string(full)); } if (t == _boolfld && *s) { if (toupper(*s) == 'T' || toupper(*s) == 'Y' || toupper(*s) == 'S' || toupper(*s) == 'X') strcpy(s,"X"); else strcpy(s," "); } } HIDDEN void __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout) { int len, i; if (recout == NULL) return; char s2[256]; strcpy(s2, s); if (t == _datefld) { if (*s2) { TDate dt(s2); sprintf(s2,"%8s", dt.string(ANSI)); } } else if (t == _boolfld) { if (toupper(*s2) == 'T' || toupper(*s2) == 'Y' || toupper(*s2) == 'S' || toupper(*s2) == 'X') strcpy(s2,"T"); else strcpy(s2,"F"); } else if (t == _realfld) setdec(s2, d); len = strlen(s2); if (len > l) return ; if ((t == _intfld) || (t == _longfld) || (t == _wordfld) || (t == _realfld)) { if (len == 0) { strcpy(s2, "0"); len = 1; } i = 0; while (i < l - len - 1) recout[i++] = ' '; strncpy(&recout[l - len - 1], s2, len) ; } else { strncpy(recout, s2, len) ; while (len < l) recout[len++] = ' '; } } int TRecfield::operator =(int i) { if (_type == _intzerofld) sprintf(_isam_string, "%0*d", _len, i); else sprintf(_isam_string, "%d", i); __putfieldbuff( _len, _dec, _type, _isam_string, _p); _rec->setempty(FALSE); return i; } long TRecfield::operator =(long l) { if (_type == _longzerofld) sprintf(_isam_string, "%0*ld", _len, l); else sprintf(_isam_string, "%ld", l); __putfieldbuff( _len, _dec, _type, _isam_string, _p); _rec->setempty(FALSE); return l; } #ifndef FOXPRO const real& TRecfield::operator =(const real& r) { strcpy(_isam_string, r.string()); __putfieldbuff( _len, _dec, _type, _isam_string, _p); _rec->setempty(FALSE); return r; } #endif // FOXPRO const TDate& TRecfield::operator =(const TDate& d) { strcpy(_isam_string, (const char*)d); __putfieldbuff( _len, _dec, _type, _isam_string, _p); _rec->setempty(FALSE); return d; } const char* TRecfield::operator =(const char* s) { __putfieldbuff( _len, _dec, _type, s, _p); _rec->setempty(FALSE); return s; } void TRecfield::setptr(TRecnotype r) { if (_p == NULL) return; bool n = r < 0; unsigned char* wp = (unsigned char*) _p; if (n) r = -r; while(wp - (unsigned char*) _p <= 3) { *wp = r && 0x000000FF; r >>= 8; wp++; } if (n) *wp += 128; } TRecfield::operator int() const { __getfieldbuff( _len, _type, _p, _isam_string); return atoi(_isam_string); } TRecfield::operator long() const { __getfieldbuff( _len, _type, _p, _isam_string); return atol(_isam_string); } #ifndef FOXPRO TRecfield::operator const real() const { __getfieldbuff( _len, _type, _p, _isam_string); real r(_isam_string); return r; } #endif // FOXPRO TRecfield::operator TDate() const { static TDate d; __getfieldbuff( _len, _type, _p, _isam_string); d = _isam_string; return d; } TRecfield::operator const char*() const { __getfieldbuff( _len, _type, _p, _isam_string); return _isam_string; } TRecnotype TRecfield::ptr() const { if (_p == NULL) return(-1L); unsigned char* wp = (unsigned char*) _p + 3; TRecnotype r = *wp; bool n = r > 127; if (n) r -= 128; while(wp-- > (unsigned char*) _p) r = r << 8 + *wp; return n ? -r : r; } void TTransaction::begin() { } void TTransaction::end(bool success) { if (success) ; else ; }