7fc9ac8d8e
riga ed esegue il ciclo per il numero effettivo di item nella TToken_string. git-svn-id: svn://10.65.10.50/trunk@3183 c028cbd2-c16b-5b4b-a496-9718f37d4682
3354 lines
78 KiB
C++
Executable File
3354 lines
78 KiB
C++
Executable File
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
|
||
#define __ISAM_CPP
|
||
|
||
#ifndef FOXPRO
|
||
#include <applicat.h>
|
||
#include <expr.h>
|
||
#include <execp.h>
|
||
#include <progind.h>
|
||
#endif
|
||
|
||
#include <config.h>
|
||
#include <extcdecl.h>
|
||
#include <mailbox.h>
|
||
#include <prefix.h>
|
||
#include <relation.h>
|
||
#include <scanner.h>
|
||
#include <utility.h>
|
||
#include <memo.h>
|
||
#include <codeb.h>
|
||
|
||
#if XVT_OS==XVT_OS_WIN
|
||
#include <process.h>
|
||
#else
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <unistd.h>
|
||
#endif
|
||
|
||
|
||
#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(@)
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @func Ritorna una Token_string con in nome dell'indice
|
||
void get_idx_names(
|
||
int logicnum, // @parm Numero logico del file di cui riconoscere l'indice
|
||
TToken_string& i_names) // @parm Token_string in cui inserire il nome dell'indice
|
||
|
||
// @comm Ritorna il nome con il prefisso corrente
|
||
{
|
||
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 bool lf_has_memo( const TTrec& r )
|
||
{
|
||
|
||
bool ret = FALSE;
|
||
int nfields = r.fields( );
|
||
for( int i = 0; i < nfields && !ret; i ++ )
|
||
{
|
||
TToken_string s( r.fielddef( i ) );
|
||
if ( s.get_int( 1 ) == _memofld )
|
||
ret = TRUE;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
HIDDEN bool lf_has_memo( const int lffile )
|
||
{
|
||
TDir d;
|
||
|
||
d.get(lffile);
|
||
if (d.len() == 0)
|
||
return FALSE;
|
||
TTrec r;
|
||
|
||
r.get( lffile );
|
||
bool ret = FALSE;
|
||
int nfields = r.fields( );
|
||
for( int i = 0; i < nfields && !ret; i ++ )
|
||
{
|
||
TToken_string s( r.fielddef( i ) );
|
||
if ( s.get_int( 1 ) == _memofld )
|
||
ret = TRUE;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
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;
|
||
|
||
#ifdef DBG
|
||
isfd = NULL; // Per provocare errori
|
||
#endif
|
||
}
|
||
|
||
|
||
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 */
|
||
{
|
||
CHECKD(numkey > 0, "Can't build key ", numkey);
|
||
|
||
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];
|
||
const TFieldtypes f = (TFieldtypes) rf.TypeF;
|
||
|
||
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);
|
||
}
|
||
if (f == _boolfld /* && build_x_cb */)
|
||
{
|
||
const bool on = *(recin + off) > ' ' && strchr("STXY", *(recin + off)) != NULL;
|
||
key[l] = on ? 'T' : 'F';
|
||
}
|
||
else
|
||
{
|
||
strncpy((key + l), (recin + off), len);
|
||
}
|
||
|
||
if (recin[off] == '\0')
|
||
{
|
||
memset(key + l, ' ', len);
|
||
if (build_x_cb && ((f == _intfld) || (f == _longfld) || (f == _wordfld) ||
|
||
(f == _intzerofld) || (f == _longzerofld)))
|
||
key[l + len - 1] = '0';
|
||
}
|
||
else
|
||
if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || (f == _intzerofld) || (f == _longzerofld))
|
||
{
|
||
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;
|
||
}
|
||
|
||
// rtrim
|
||
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");
|
||
|
||
char key[128];
|
||
int err = NOERR ;
|
||
|
||
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 (rmode == _isgreat && err == NOERR)
|
||
err = DB_next(isfd->fhnd);
|
||
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 (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 (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(@)
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @func Setta il valore della variabile <p __autoload>
|
||
void set_autoload_new_files(
|
||
bool on) // @parm Valore da assegnare
|
||
|
||
// @comm Il valore di <p __autoload> indica il caricamento dei valori standard dei file
|
||
|
||
{
|
||
__autoload = on;
|
||
}
|
||
|
||
void TMemo_info::put( const char * fieldname, const char * data )
|
||
{
|
||
int index( findfld( rec_des( ), ( char * ) fieldname ) );
|
||
_dirty.set( index );
|
||
_data.add( data, index );
|
||
}
|
||
|
||
TMemo_info::TMemo_info( const TRectype * owner, const TRecnotype recno )
|
||
: _owner(owner), _recno(recno)
|
||
{
|
||
}
|
||
|
||
TMemo_info::~TMemo_info( )
|
||
{
|
||
}
|
||
|
||
RecDes * TMemo_info::rec_des( ) const
|
||
{
|
||
return _owner->rec_des() ;
|
||
}
|
||
|
||
int TMemo_info::num() const
|
||
{
|
||
return _owner->num() ;
|
||
}
|
||
|
||
TString& TMemo_info::get( const char * fieldname )
|
||
{
|
||
int index( findfld( rec_des( ), ( char * )fieldname ) );
|
||
if ( _data.objptr( index ) )
|
||
{
|
||
if( _dirty[ index ] )
|
||
return _data.row( index );
|
||
}
|
||
if( _recno >= 0 )
|
||
{
|
||
TLocalisamfile posfile( num() );
|
||
isdef * def = posfile.filehnd( );
|
||
DB_go( def->fhnd, _recno );
|
||
_data.add( DB_memoptr( def->fhnd, fieldname ), index );
|
||
}
|
||
else
|
||
_data.add( "", index );
|
||
return _data.row( index );
|
||
}
|
||
|
||
void TMemo_info::write_data( isdef * def )
|
||
{
|
||
CHECK( _recno > 0, "Maiale! Non fare le GO con _recno < 0 " );
|
||
DB_go( def->fhnd, _recno );
|
||
RecDes *r = rec_des( );
|
||
for( int i = _data.last( ); i > 0; i = _data.pred( i ) )
|
||
DB_memowrite( def->fhnd, r->Fd[ i ].Name, ( char * )( const char * )_data.row( i ) );
|
||
reset( );
|
||
}
|
||
|
||
bool TMemo_info::memo_loaded( const char * fieldname )
|
||
{
|
||
int index( findfld( rec_des( ), ( char * )( const char * )fieldname ) );
|
||
return ( _data.objptr( index ) != NULL );
|
||
}
|
||
|
||
TMemo_info::TMemo_info( const TRectype * owner, TMemo_info& memoinfo)
|
||
: _owner(owner)
|
||
{
|
||
_recno = memoinfo._recno;
|
||
_data = memoinfo._data;
|
||
_dirty = memoinfo._dirty;
|
||
}
|
||
|
||
void TMemo_info::reset( )
|
||
{
|
||
_data.destroy( );
|
||
_dirty.reset( );
|
||
}
|
||
|
||
void TRectype::init_memo_info(const TRecnotype recnum )
|
||
{
|
||
if( _memoinfo )
|
||
{
|
||
_memoinfo->reset();
|
||
_memoinfo->recno( recnum);
|
||
// delete _memoinfo;
|
||
}
|
||
else
|
||
_memoinfo = new TMemo_info( this, recnum );
|
||
}
|
||
|
||
void TRectype::write_memo_info( isdef * def ) const
|
||
{
|
||
CHECK( _memoinfo, "Tentativo di registrare una TMemo_info vuota," );
|
||
_memoinfo->write_data( def );
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// 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(r.num())
|
||
|
||
{
|
||
delete _rec;
|
||
_length = r.len();
|
||
_rec = new char [ _length ];
|
||
_rd = r.rec();
|
||
if( lf_has_memo(r))
|
||
init_memo_info(RECORD_NON_FISICO );
|
||
zero();
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// 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;
|
||
_has_memo = lf_has_memo( _logicnum );
|
||
}
|
||
|
||
|
||
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 = RECORD_NON_FISICO, wr1 = RECORD_NON_FISICO;
|
||
|
||
if ((wr0 == flf.ptr()) == RECORD_NON_FISICO) 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
|
||
{
|
||
NOT_OPEN();
|
||
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.filename());
|
||
}
|
||
else
|
||
{
|
||
strcpy(_isam_string, _isamfile->d->SysName);
|
||
strcat(_isam_string, ".dbf");
|
||
}
|
||
return _isam_string;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
bool TBaseisamfile::has_memo( )
|
||
{
|
||
return _has_memo;
|
||
}
|
||
|
||
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();
|
||
CHECKD(DB_tagget(_isamfile->fhnd) == _isamfile->knum, "Chiave inconsistente sul file ", _logicnum);
|
||
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;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_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;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_recno);
|
||
return _lasterr;
|
||
}
|
||
|
||
|
||
int TBaseisamfile::next(word lockop)
|
||
|
||
{
|
||
NOT_OPEN();
|
||
curr().setdirty();
|
||
if (_recno != DB_recno(_isamfile->fhnd))
|
||
{
|
||
_lasterr = cisread(_isamfile, curr(), _isgteq + lockop);
|
||
if (_lasterr != NOERR)
|
||
{
|
||
_lasterr = get_error(_lasterr);
|
||
if (_lasterr != _islocked && _lasterr != _iseof)
|
||
fatal_box("Errore nella next %d : non posso riposizionarmi", _lasterr);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_lasterr=cisread(_isamfile, curr(), _isnext + lockop);
|
||
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
|
||
}
|
||
_recno = _isamfile->RecNo;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_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();
|
||
if (_recno != DB_recno(_isamfile->fhnd))
|
||
{
|
||
_lasterr = DB_go(_isamfile->fhnd, _recno);
|
||
if (_lasterr != NOERR)
|
||
{
|
||
_lasterr = get_error(_lasterr);
|
||
if (_lasterr != _islocked)
|
||
fatal_box("Errore nella prev %d : non posso riposizionarmi", _lasterr);
|
||
}
|
||
}
|
||
_lasterr=cisread(_isamfile, curr(), _isprev + lockop);
|
||
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
|
||
_recno = _isamfile->RecNo;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_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;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_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;
|
||
if( has_memo( ) )
|
||
rec.init_memo_info(_recno);
|
||
return _lasterr;
|
||
}
|
||
|
||
|
||
int TBaseisamfile::skip(TRecnotype nrec, word lockop)
|
||
|
||
{
|
||
char key[128];
|
||
|
||
NOT_OPEN();
|
||
if (!nrec) return NOERR;
|
||
curr().setdirty();
|
||
if (_recno != DB_recno(_isamfile->fhnd))
|
||
{
|
||
_lasterr = DB_go(_isamfile->fhnd, _recno);
|
||
if (_lasterr != NOERR)
|
||
{
|
||
_lasterr = get_error(_lasterr);
|
||
if (_lasterr != _islocked)
|
||
fatal_box("Errore nella skip %d : non posso riposizionarmi", _lasterr);
|
||
}
|
||
}
|
||
_lasterr=DB_skip(_isamfile->fhnd,nrec);
|
||
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
|
||
do {
|
||
if (_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 (_lasterr ==_islocked);
|
||
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_recno);
|
||
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;
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_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;
|
||
if( has_memo( ) )
|
||
rec.init_memo_info(_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);
|
||
if( has_memo( ) )
|
||
curr( ).init_memo_info(_recno);
|
||
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 = DB_recno(_isamfile->fhnd);
|
||
if( has_memo( ) )
|
||
rec.init_memo_info( _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));
|
||
|
||
setkey(1);
|
||
memcpy(DB_getrecord(_isamfile->fhnd),curr().string(),DB_reclen(_isamfile->fhnd));
|
||
_lasterr = DB_add(_isamfile->fhnd);
|
||
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
|
||
setkey(oldkey);
|
||
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
|
||
if( _lasterr == NOERR && has_memo( ) )
|
||
{
|
||
curr( ).memo_info( ).recno( _recno );
|
||
curr( ).write_memo_info( _isamfile);
|
||
}
|
||
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));
|
||
|
||
setkey(1);
|
||
memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd));
|
||
_lasterr = DB_add(_isamfile->fhnd);
|
||
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
|
||
setkey(oldkey);
|
||
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
|
||
if (_lasterr == NOERR )
|
||
{
|
||
if( has_memo( ) )
|
||
{
|
||
rec.memo_info( ).recno( _recno );
|
||
rec.write_memo_info( _isamfile );
|
||
}
|
||
}
|
||
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)
|
||
{
|
||
browse_null(curr().string(),DB_reclen(_isamfile->fhnd));
|
||
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);
|
||
if( _lasterr == NOERR && has_memo( ) )
|
||
{
|
||
curr( ).memo_info( ).recno( _recno );
|
||
curr( ).write_memo_info( _isamfile );
|
||
}
|
||
}
|
||
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)
|
||
{
|
||
browse_null(rec.string(),DB_reclen(_isamfile->fhnd));
|
||
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);
|
||
if( _lasterr == NOERR && has_memo( ) )
|
||
{
|
||
rec.memo_info( ).recno( _recno );
|
||
rec.write_memo_info( _isamfile );
|
||
}
|
||
}
|
||
return _lasterr;
|
||
}
|
||
|
||
|
||
int TBaseisamfile::rewriteat(TRecnotype nrec)
|
||
|
||
{
|
||
NOT_OPEN();
|
||
if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR)
|
||
{
|
||
browse_null(curr().string(),DB_reclen(_isamfile->fhnd));
|
||
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);
|
||
if( _lasterr == NOERR && has_memo( ) )
|
||
{
|
||
curr( ).memo_info( ).recno( _recno );
|
||
curr( ).write_memo_info( _isamfile );
|
||
}
|
||
return _lasterr;
|
||
}
|
||
|
||
|
||
int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec)
|
||
{
|
||
NOT_OPEN();
|
||
if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR)
|
||
{
|
||
browse_null(rec.string(),DB_reclen(_isamfile->fhnd));
|
||
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);
|
||
if( _lasterr == NOERR && has_memo( ) )
|
||
{
|
||
rec.memo_info( ).recno( _recno );
|
||
rec.write_memo_info( _isamfile );
|
||
}
|
||
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 + _nolock)) == 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);
|
||
}
|
||
}
|
||
}
|
||
if(_lasterr == NOERR && has_memo())
|
||
curr().memo_info().recno(RECORD_NON_FISICO);
|
||
|
||
_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 + _nolock))==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);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(_lasterr == NOERR && has_memo())
|
||
curr().memo_info().recno(RECORD_NON_FISICO);
|
||
|
||
_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()
|
||
|
||
{
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Apre il file isam di base con lock
|
||
//
|
||
// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore
|
||
// generato (vedi <t TIsamerr>).
|
||
int TBaseisamfile::_open(
|
||
unsigned int mode) // @parm Indica il modo di apertura del file (default _manulock)
|
||
|
||
// @comm Il parametro <p mode> puo' assumere i valori:
|
||
//
|
||
// @flag _manulock | Il lock dei record viene fatto manualmente
|
||
// @flag _exclock | Il file viene aperte in modo esclusivo
|
||
// @flag _autolock | Il lock dei record viene fatto in modo automatico
|
||
|
||
{
|
||
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(),_nolock,_nordir,_sysdirop);
|
||
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
|
||
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,_sysdirop);
|
||
else
|
||
d.put(num(),_nordir,_sysdirop);
|
||
}
|
||
filehnd()->ln = num();
|
||
openf[num() - 1] = filehnd();
|
||
_recno = RECORD_NON_FISICO;
|
||
|
||
CHECKD(filehnd()->r->NKeys > 0, "File senza indici: ", num());
|
||
setkey(1);
|
||
_lasterr = NOERR;
|
||
}
|
||
else
|
||
{
|
||
TString e_msg;
|
||
_lasterr = get_error(filehnd()->fhnd);
|
||
if (_lasterr == -60)
|
||
{
|
||
int rc = access(filename(),0); // check for existance
|
||
if (rc!=0)
|
||
e_msg.format("Il file %d(%s) non esiste, errore %d",num(),filename(),_lasterr);
|
||
else
|
||
e_msg.format("Il file %d(%s) e' aperto in modo esclusivo da un'altra applicazione",
|
||
num(), filename());
|
||
}
|
||
if (e_msg.empty())
|
||
e_msg.format("Il file %d(%s) non puo' essere aperto, errore %d",num(),filename(),_lasterr);
|
||
relisfd(_isamfile);
|
||
fatal_box((const char*) e_msg);
|
||
}
|
||
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(),_nolock,_nordir,_sysdirop);
|
||
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
|
||
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,_sysdirop);
|
||
else
|
||
d.put(num(),_nordir,_sysdirop);
|
||
}
|
||
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();
|
||
}
|
||
}
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
int TBaseisamfile::is_valid()
|
||
{ // Ritorna 0 se il file puo' essere aperto senza errori
|
||
CHECKS(filehnd() == NULL, "File already open ", (const char*)filename());
|
||
int err = NOERR;
|
||
getisfd(_isamfile,num());
|
||
if ((filehnd()->fhnd = DB_open(filehnd()->d->SysName,0)) >= 0)
|
||
{
|
||
if (DB_tagget(filehnd()->fhnd) == -1) err = _ispatherr;
|
||
DB_close(filehnd()->fhnd);
|
||
}
|
||
else
|
||
err = get_error(filehnd()->fhnd);
|
||
relisfd(_isamfile);
|
||
return err;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TLocalisamfile
|
||
///////////////////////////////////////////////////////////
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Costruttore
|
||
//
|
||
// @rdesc Ritorna l'oggetto <c TLocalisamfile>
|
||
TLocalisamfile::TLocalisamfile(
|
||
int logicnum, // @parm Numero del logico del file
|
||
bool linkrecinst) // @parm Puo assumere i valori:
|
||
//
|
||
// @flag 0 | Istanzio un nuovo file fisico (default)
|
||
// @flag 1 | Utilizza, se possibile, un file gia' esistente
|
||
// @flag 2 | Crea un file temporaneo
|
||
: TBaseisamfile(logicnum, linkrecinst == TRUE)
|
||
|
||
// @comm ATTENZIONE: <p linkrecinst> puo' valere 0, 1, 2.
|
||
// Se vale 2 significa che si sta costruendo un file temporaneo
|
||
// per cui linkrecinst va' considerato FALSE
|
||
|
||
{
|
||
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(),_nolock,_nordir,_sysdirop);
|
||
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
|
||
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,_sysdirop);
|
||
else
|
||
d.put(num(),_nordir,_sysdirop);
|
||
}
|
||
err = DB_close(_isamfile->fhnd);
|
||
_isamfile->fhnd = -1;
|
||
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;
|
||
}
|
||
|
||
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();
|
||
}
|
||
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Aggiorna i flags associati al file
|
||
//
|
||
// @rdesc Ritorna NOERR se e' riuscita ad eseguiore l'operazione, altrimenti ritorna il numero
|
||
// di errore generato (vedi <t TIsamerr>).
|
||
int TIsamfile::flags(
|
||
bool updateeod) // @parm Indica se aggiornare anche l'EOD del file
|
||
|
||
{
|
||
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();
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Apre il file
|
||
//
|
||
// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore
|
||
// generato (vedi <t TIsamerr>).
|
||
int TIsamtempfile::open(
|
||
const char* radix, // @parm Radice del path del file
|
||
bool create, // @parm Indica se va creatoun nuovo file (se FALSE il file esiste gia')
|
||
TRecnotype eod, // @parm Numero di record presenti nel file
|
||
TRecnotype eox) // @parm Numero di record da aggiungere al file
|
||
|
||
// @comm Nel case <p create> sia TRUE allora viene settato automaticamente il valore di <p _autodel>
|
||
// a TRUE, cioe' viene abilitata l'eliminazione del file in chiusura.
|
||
|
||
{
|
||
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", err);
|
||
}
|
||
}
|
||
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 ",err);
|
||
}
|
||
else
|
||
{
|
||
filehnd()->ln = -num();
|
||
filehnd()->knum = 1;
|
||
}
|
||
_recno = RECORD_NON_FISICO;
|
||
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();
|
||
}
|
||
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());
|
||
CHECK(r.len() != 0, "Can't create a file with empty field info");
|
||
|
||
TFilename f(d.name());
|
||
|
||
f = f.path(); if (!is_not_slash(f.right(1)[0])) f.rtrim(1);
|
||
if (!fexist(f))
|
||
make_dir(f);
|
||
if (r.len() != 0)
|
||
{
|
||
err=DB_build(d.name(),r.rec());
|
||
if (err == NOERR)
|
||
{
|
||
isfdptr i;
|
||
getisfd(i,num());
|
||
i->d->EOX = eox;
|
||
i->fhnd = 0; // So relisfd() will record the EOX just set
|
||
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;
|
||
i->fhnd = 0; // So relisfd() will write the EOX just set.
|
||
}
|
||
}
|
||
relisfd(i);
|
||
setstatus(err);
|
||
clearfilehnd();
|
||
return err;
|
||
}
|
||
|
||
|
||
long TSystemisamfile::size(TRecnotype eox)
|
||
{
|
||
return 51200L;
|
||
}
|
||
|
||
#ifndef FOXPRO
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Esegue la conversione del file
|
||
//
|
||
// @rdesc Ritorna il rusultato dell'operazione
|
||
int TSystemisamfile::exec_convapp(
|
||
long flev, // @parm Livello a cui aggiornare l'archivio
|
||
const bool before) // @parm Indica se viene chiamata prima o dopo la conversione
|
||
|
||
{
|
||
const char * const v = before ? "BCNV" : "ACNV";
|
||
int err = 0;
|
||
|
||
if (flev == 0) flev = 199401;
|
||
else flev++;
|
||
for (long l = flev; err == 0 && l <= get_std_level(); l++)
|
||
{
|
||
TString16 paragraph(format("%06ld", l));
|
||
TConfig conv(CONFIG_FCONV, paragraph);
|
||
|
||
if (!conv.new_paragraph() && conv.exist(v, num()))
|
||
{
|
||
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 && err != 8)
|
||
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 err;
|
||
}
|
||
|
||
// @doc INTERNAL
|
||
|
||
// @mfunc Recupera le conversioni logiche da effettuare sul file
|
||
//
|
||
// @rdesc Ritorna TRUE se occorre effettuare la conversione sul file
|
||
bool TSystemisamfile::getlcf(
|
||
long flev) // @parm livello archivi di partenza della convesione
|
||
|
||
// @comm Recupera le conversioni logiche da effettuare sul file per per passare dal
|
||
// livello archivi <p flev> a quello attuale degli archivi standard.
|
||
|
||
{
|
||
_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);
|
||
}
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Esegue la conversione del tracciato record del file
|
||
//
|
||
// @rdesc Ritorna il risulato della conversione, altrimenti il codice di errore generato
|
||
// (vedi <t TIsamerr>)
|
||
int TSystemisamfile::update(
|
||
TTrec& newrec, // @parm Nuovo tracciato record con cui aggiornare il file
|
||
bool vis) // @parm Indica se visualizzare lo stato dell'operazione
|
||
|
||
{
|
||
CHECKS(filehnd() == NULL, "Can't update open file", (const char*)filename());
|
||
CHECK(newrec.len() != 0, "Can't update to file with empty field info");
|
||
|
||
TDir dir;
|
||
|
||
dir.get(num(), _unlock, _nordir, _sysdirop);
|
||
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());
|
||
if (newrec.len() != 0)
|
||
{
|
||
const long lev = prefix().filelevel();
|
||
const bool lcf = getlcf(lev);
|
||
|
||
err = exec_convapp(lev, TRUE);
|
||
if (err != NOERR)
|
||
{
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
if (!lcf && newrec == oldrec)
|
||
{
|
||
err = exec_convapp(lev, FALSE);
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
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);
|
||
browse_null(nrec.string(),DB_reclen(i0->fhnd));
|
||
memcpy(DB_getrecord(i0->fhnd),nrec.string(),DB_reclen(i0->fhnd));
|
||
err=DB_add(i0->fhnd);
|
||
if ( nrec.has_memo())
|
||
{
|
||
nrec.memo_info( ).recno( DB_recno(i0->fhnd) );
|
||
nrec.write_memo_info( i0);
|
||
}
|
||
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)
|
||
tmpfname.ext("fpt");
|
||
else
|
||
tmpfname.ext("dbt");
|
||
if (fexist((const char *) tmpfname))
|
||
{
|
||
if (c & 1)
|
||
fname.ext("fpt");
|
||
else
|
||
fname.ext("dbt");
|
||
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();
|
||
if (err == NOERR)
|
||
err = exec_convapp(lev, FALSE);
|
||
}
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Rimuove fisicamente i record cancellati
|
||
//
|
||
// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di
|
||
// di errore generato (vedi <t TIsamerr>).
|
||
int TSystemisamfile::packfile(
|
||
bool vis) // @parm Indica se visualizzare lo stato dell'operazione
|
||
|
||
// @xref <mf TSystemisamfile::packindex>
|
||
|
||
{
|
||
int err=NOERR;
|
||
TDir d;
|
||
|
||
d.get(num(),_nolock, _nordir,_sysdirop);
|
||
d.get(num(),_nolock, (d.is_com()) ? _comdir : _nordir);
|
||
CHECKS(filehnd() == NULL, "Can't pack open file", (const char*)filename());
|
||
err=DB_packfile(vis,d.name(),d.eod());
|
||
if (err == NOERR && has_memo())
|
||
err = DB_packmemo(vis,d.name());
|
||
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;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Rimuove fisicamente gli indici cancellati
|
||
//
|
||
// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di
|
||
// di errore generato (vedi <t TIsamerr>).
|
||
int TSystemisamfile::packindex(
|
||
bool vis, // @parm Indica se visualizzare lo stato dell'operazione
|
||
bool ask) // @parm Indica se chiedere il recupero dei record duplicati
|
||
|
||
// @xref <mf TSystemisamfile::packfile>
|
||
|
||
{
|
||
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(),_nolock, _nordir,_sysdirop);
|
||
bool is_com = d.is_com();
|
||
d.get(num(),_nolock, is_com ? _comdir : _nordir);
|
||
err=DB_packindex(vis,d.name(),r.rec(),&peod,ask);
|
||
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(), is_com ? _comdir : _nordir);
|
||
}
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
int TSystemisamfile::pack(bool vis, bool ask)
|
||
{
|
||
int err=NOERR;
|
||
|
||
if ((err=packfile(vis))==NOERR)
|
||
err=packindex(vis,ask);
|
||
setstatus(err);
|
||
return err;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Importa un file ascii
|
||
//
|
||
// @rdesc Ritorna NOERR se l'operazione di lettura e' riuscita, altrimenti il codice di
|
||
// di errore generato (vedi <t TIsamerr>).
|
||
int TSystemisamfile::load(
|
||
const char* from, // @parm Nome del file da importare
|
||
char fs, // @parm Carattere separatore di campo (default <pipe>)
|
||
char fd, // @parm Carattere delimitatore di campi (default '\\0')
|
||
char rs, // @parm Carattere separatore di record (default '\\n')
|
||
bool vis, // @parm Indica se visualizzare lo stato dell'operazione (default TRUE)
|
||
bool extended) // @parm Indica se interpretare alcune stringhe come macro (default FALSE)
|
||
|
||
// @comm Se <p extended> e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%)
|
||
// ne sostituisce i valori (es. ditta corrente).
|
||
|
||
// @xref <mf TSystemisamfile::dump>
|
||
|
||
{
|
||
FILE* fl = fopen(from, "r");
|
||
int err=NOERR;
|
||
if (fl == NULL)
|
||
{
|
||
error_box("Non riesco ad aprire il file %s",from);
|
||
return 2;
|
||
}
|
||
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
|
||
{
|
||
#ifdef DBG
|
||
yesnofatal_box("Numero linea relativa all'errore: %ld",r+e+1);
|
||
#endif
|
||
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;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Esporta VERSO un file ascii.
|
||
//
|
||
// @rdesc Ritorna NOERR se l'operazione di esportazione e' riuscita, altrimenti il codice di
|
||
// di errore generato (vedi <t TIsamerr>).
|
||
int TSystemisamfile::dump(
|
||
const char* to, // @parm Nome del file verso quale esportare
|
||
int nkey, // @parm Numero della chiave di ordinamento con cui scaricare i dati (defualt 1)
|
||
char fs, // @parm Carattere seperatore di campo (defualt <pipe>)
|
||
char fd, // @parm Carattere delimitatore di campo (default '\\0')
|
||
char rs, // @parm Carattere separatore di record (default '\\n')
|
||
bool vis, // @parm Indica se visualizzare lo stato dell'operazione (defualt TRUE)
|
||
bool withdeleted) // @parm Indica se scaricare anche i record cancellati (dafault FALSE)
|
||
|
||
// @xref <mf TSystemisamfile::load>
|
||
|
||
{
|
||
FILE* f = fopen(to, "w");
|
||
|
||
if (f == NULL)
|
||
{
|
||
setstatus(2);
|
||
return 2;
|
||
}
|
||
|
||
if (withdeleted) nkey = 0;
|
||
int err = ferror(f);
|
||
|
||
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;
|
||
_memoinfo = NULL;
|
||
if (openf[_logicnum - 1] != NULL)
|
||
_length = DB_reclen(openf[logicnum - 1]->fhnd);
|
||
else
|
||
{
|
||
TDir wdir;
|
||
wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
|
||
if (wdir.is_com())
|
||
wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
|
||
_length = wdir.len();
|
||
}
|
||
_rec = new char [ _length ];
|
||
*_tab = '\0';
|
||
if (_length)
|
||
zero();
|
||
else
|
||
setempty(TRUE);
|
||
}
|
||
|
||
TRectype::TRectype(const TBaseisamfile* i): _cod(NULL)
|
||
{
|
||
_logicnum = i->num();
|
||
_memoinfo = NULL;
|
||
if (i->filehnd() != NULL)
|
||
_length = DB_reclen(i->filehnd()->fhnd);
|
||
else
|
||
{
|
||
TDir wdir;
|
||
|
||
wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
|
||
if (wdir.is_com())
|
||
wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
|
||
_length = wdir.len();
|
||
}
|
||
*_tab = '\0';
|
||
_rec = new char [ _length ];
|
||
if (_length)
|
||
zero();
|
||
else
|
||
setempty(TRUE);
|
||
}
|
||
|
||
|
||
TRectype::TRectype(const TRectype& r)
|
||
: _cod(NULL)
|
||
|
||
{
|
||
_logicnum = r._logicnum;
|
||
if ( r._memoinfo )
|
||
_memoinfo = new TMemo_info( this, *r._memoinfo);
|
||
else
|
||
_memoinfo = NULL;
|
||
_length = r.len();
|
||
_rec = new char [ _length ];
|
||
_rec[0] = r._rec[0];
|
||
memcpy(_rec + 1, r._rec + 1, _length - 1);
|
||
strcpy(_tab, r._tab);
|
||
if (r._cod != NULL)
|
||
_cod = new TRecfield(*this, "COD");
|
||
setempty(r.empty());
|
||
}
|
||
|
||
TRectype::~TRectype()
|
||
|
||
{
|
||
if (_cod != NULL) delete _cod;
|
||
if (_rec != NULL) delete _rec;
|
||
if (_memoinfo != NULL ) delete _memoinfo;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
const char* TRectype::build_key(int num) const
|
||
{
|
||
CBuildKey(rec_des(), num, string(), __tmp_string, TRUE);
|
||
return __tmp_string;
|
||
}
|
||
|
||
const char* TRectype::last_key_field(int key) const
|
||
{
|
||
const KeyDes& kd = rec_des()->Ky[key];
|
||
const int last = kd.NkFields-1;
|
||
const bool upp = kd.FieldSeq[last] > MaxFields;
|
||
const int nf = upp ? kd.FieldSeq[last] - MaxFields : kd.FieldSeq[last];
|
||
const RecFieldDes& rf = rec_des()->Fd[nf];
|
||
return rf.Name;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Confronta le chiavi di due record
|
||
//
|
||
// @rdesc Ritorna il risultato di una <f strcmp>:
|
||
//
|
||
// @flag 0 | Se le due chiavi sono uguali
|
||
// @flag <lt><gt>0 | Se le due chiavi sono diverse
|
||
int TRectype::compare_key(
|
||
const TRectype& rec, // @parm Record di cui confrontare le chiavi
|
||
int key, // @parm Numero della chiave del presente record (defautl 1)
|
||
int skip_last) const // @parm Numero di campi di ignorare nella comparazione a partire dall'ultimo
|
||
|
||
// @xref <mf TRectype::build_key>
|
||
{
|
||
TString256 key1= build_key(key);
|
||
TString256 key2 = rec.build_key(key);
|
||
if (skip_last > 0)
|
||
{
|
||
const KeyDes& kd = rec_des()->Ky[key-1];
|
||
const int last = kd.NkFields-1;
|
||
CHECKD(last >= skip_last, "Can't ignore so many fields in key: ", skip_last);
|
||
for (int l = 0; l < skip_last; l++)
|
||
{
|
||
int nf = kd.FieldSeq[last-l];
|
||
if (nf > MaxFields) nf -= MaxFields;
|
||
const RecFieldDes& rf = rec_des()->Fd[nf];
|
||
key1.rtrim(rf.Len);
|
||
key2.rtrim(rf.Len);
|
||
}
|
||
}
|
||
const int res = strcmp(key1, key2);
|
||
return res;
|
||
}
|
||
|
||
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];
|
||
CHECKD(i, "Can't use a record of closed file ", _logicnum);
|
||
RecDes* r = i->r;
|
||
CHECKD(r, "Missing record description of file", _logicnum);
|
||
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;
|
||
|
||
const RecDes& rd = *rec_des();
|
||
for (int i = 0; i < items() ; i++)
|
||
{
|
||
const char* b = br.start(i);
|
||
const char* a = start(i);
|
||
const byte typ = rd.Fd[i].TypeF;
|
||
const int sz = rd.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
|
||
|
||
{
|
||
return (TFieldtypes) CFieldType((char*) fieldname, rec_des());
|
||
}
|
||
|
||
|
||
int TRectype::length(const char* fieldname) const
|
||
|
||
{
|
||
return CFieldSize((char*) fieldname, rec_des());
|
||
}
|
||
|
||
|
||
int TRectype::ndec(const char* fieldname) const
|
||
|
||
{
|
||
return CFieldDec((char*) fieldname, rec_des());
|
||
}
|
||
|
||
|
||
bool TRectype::exist(const char* fieldname) const
|
||
{
|
||
return findfld(rec_des(), (char*)fieldname) != FIELDERR;
|
||
}
|
||
|
||
|
||
const char* TRectype::fieldname(int i) const
|
||
{
|
||
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) == FIELDERR)
|
||
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));
|
||
if( _memoinfo && type( fieldname ) == _memofld )
|
||
{
|
||
const TString16 fn( fieldname );
|
||
return _memoinfo->get( fn );
|
||
}
|
||
get_str(fieldname);
|
||
return tmp;
|
||
}
|
||
|
||
int TRectype::get_int(const char* fieldname) const
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
return atoi(_isam_string);
|
||
}
|
||
|
||
|
||
long TRectype::get_long(const char* fieldname) const
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
return atol(_isam_string);
|
||
}
|
||
|
||
|
||
word TRectype::get_word(const char* fieldname) const
|
||
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
return (word)atoi(_isam_string);
|
||
}
|
||
|
||
real TRectype::get_real(const char* fieldname) const
|
||
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
real r(_isam_string);
|
||
return r;
|
||
}
|
||
|
||
|
||
char TRectype::get_char(const char* fieldname) const
|
||
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
return *_isam_string;
|
||
}
|
||
|
||
|
||
bool TRectype::get_bool(const char* fieldname) const
|
||
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == FIELDERR)
|
||
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;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna il contenuto di un campo memo
|
||
//
|
||
// @rdesc Ritorna sempre TRUE
|
||
bool TRectype::get_memo(
|
||
const char* fieldname, // @parm Nome del campo da cui estrarre il contenuto
|
||
TTextfile& txt) const // @parm Reference della variabile a cui assegnare il contenuto dell campo
|
||
{
|
||
TToken_string memo( get( fieldname ), '\n' );
|
||
const int last = memo.items( );
|
||
for( int i = 0; i < last; i ++ )
|
||
{
|
||
TString m(memo.get(i));
|
||
const int l = m.len() > 0 ? m.len()-1 : 0;
|
||
if (m[l] == '\r') m.cut(l);
|
||
txt.append( m );
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
#endif // FOXPRO
|
||
|
||
|
||
TDate TRectype::get_date(const char* fieldname) const
|
||
|
||
{
|
||
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
TDate d(_isam_string);
|
||
return d;
|
||
}
|
||
|
||
#ifndef FOXPRO
|
||
|
||
void TRectype::put(const char* fieldname, int val)
|
||
|
||
{
|
||
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
|
||
void TRectype::put(const char* fieldname, long val)
|
||
|
||
{
|
||
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == FIELDERR)
|
||
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 ? FIELDERR : val);
|
||
if (isnew) val = id;
|
||
TString16 str; str << val;
|
||
|
||
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)(const char*)str, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
|
||
void TRectype::put(const char* fieldname, word val)
|
||
|
||
{
|
||
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
void TRectype::put(const char* fieldname, const real& val)
|
||
{
|
||
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)(const char*)val.string(), _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
void TRectype::put(const char* fieldname, const TDate& val)
|
||
{
|
||
TRecfield f(*this, fieldname);
|
||
f = val.string(full);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
void TRectype::put(const char* fieldname, char val)
|
||
|
||
{
|
||
char w[2] = {val, '\0'};
|
||
|
||
if (CPutFieldBuff((char*) fieldname, rec_des(), w, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
|
||
void TRectype::put(const char* fieldname, bool val)
|
||
|
||
{
|
||
char s[2] = { val ? 'T' : 'F', '\0'};
|
||
if (CPutFieldBuff((char*) fieldname, rec_des(), s, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
setempty(FALSE);
|
||
}
|
||
|
||
#endif // FOXPRO
|
||
|
||
|
||
void TRectype::put(const char* fieldname, const char* val)
|
||
{
|
||
const TFieldtypes ft = (TFieldtypes)CFieldType((char*) fieldname, rec_des());
|
||
|
||
if (val == NULL) val = "";
|
||
|
||
if (ft == _boolfld)
|
||
val = (*val > ' ' && strchr("STXY", toupper(*val)) != NULL) ? "T" : "F";
|
||
|
||
if (*val == '\0') // Da provare
|
||
{
|
||
TRecfield f(*this, fieldname);
|
||
if (*f.pos() == '\0') return;
|
||
}
|
||
|
||
if (ft == _datefld)
|
||
{
|
||
TRecfield f(*this, fieldname);
|
||
f = val;
|
||
return;
|
||
}
|
||
|
||
if(ft == _memofld)
|
||
{
|
||
// Qui registro il campo memo
|
||
CHECK( _memoinfo, "La struttura TMemo_info non <20> stata allocata!" );
|
||
_memoinfo->put( fieldname, val );
|
||
}
|
||
else
|
||
{
|
||
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)val, _rec) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
}
|
||
setempty(FALSE);
|
||
}
|
||
|
||
|
||
void TRectype::zero(const char* fieldname)
|
||
|
||
{
|
||
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) == FIELDERR)
|
||
UNKNOWN_FIELD(num(), fieldname);
|
||
}
|
||
if( lf_has_memo( _logicnum ) )
|
||
init_memo_info(RECORD_NON_FISICO );
|
||
}
|
||
|
||
|
||
void TRectype::zero()
|
||
|
||
{
|
||
zero('\0');
|
||
}
|
||
|
||
|
||
void TRectype::zero(char c)
|
||
|
||
{
|
||
recall();
|
||
memset(_rec + 1, c, len() - 1);
|
||
|
||
if (_cod != NULL)
|
||
*_cod = _tab;
|
||
|
||
if( lf_has_memo( _logicnum ) )
|
||
init_memo_info( RECORD_NON_FISICO );
|
||
setempty(TRUE);
|
||
}
|
||
|
||
|
||
// Certified 99%
|
||
TRectype& TRectype::operator =(const TRectype& rec)
|
||
|
||
{
|
||
CHECK(num() == rec.num(), "Can't assign records of different file");
|
||
|
||
memcpy(_rec, rec._rec, _length); // Copy contents
|
||
if (_memoinfo)
|
||
{
|
||
TTrec r;
|
||
r.get(_logicnum);
|
||
RecDes* rd = r.rec();
|
||
const int nfields = r.fields( );
|
||
for( int i = 0; i < nfields; i ++ )
|
||
{
|
||
const char* name = rd->Fd[i].Name;
|
||
const unsigned int offset = rd->Fd[i].RecOff;
|
||
#ifndef FOXPRO
|
||
if ( rd->Fd[i].TypeF == _memofld )
|
||
_memoinfo->put(name,rec.get(name)); // Copy memo fields
|
||
#endif
|
||
}
|
||
}
|
||
setempty(rec.empty()); // Copy emptiness status
|
||
return *this;
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
TRectype& TRectype::operator =(const TBaseisamfile& f)
|
||
{
|
||
return *this = f.curr();
|
||
}
|
||
|
||
// Certified 100%
|
||
int TRectype::read(TBaseisamfile& f, word op)
|
||
{ return f.read(*this, op); }
|
||
|
||
// Certified 100%
|
||
int TRectype::next(TBaseisamfile& f)
|
||
{
|
||
const int err = f.next();
|
||
*this = f.curr();
|
||
return err;
|
||
}
|
||
|
||
// Certified 100%
|
||
int TRectype::write(TBaseisamfile& f) const
|
||
{ return f.write(*this); }
|
||
|
||
// Certified 100%
|
||
int TRectype::rewrite(TBaseisamfile& f) const
|
||
{
|
||
return f.rewrite(*this);
|
||
}
|
||
|
||
// Certified 100%
|
||
int TRectype::remove(TBaseisamfile& f) const
|
||
{
|
||
return f.remove(*this);
|
||
}
|
||
|
||
void TRectype::renum_key(const char* field, const char* val)
|
||
{
|
||
put(field, val);
|
||
}
|
||
|
||
// Certified 99%
|
||
TRectype& TRectype::operator =(const char* rec)
|
||
{
|
||
memcpy(_rec, rec, _length);
|
||
setempty(FALSE);
|
||
return *this;
|
||
}
|
||
|
||
|
||
const char* TRectype::key(int numkey) const
|
||
{
|
||
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)) == FIELDERR)
|
||
{
|
||
_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 = (TFieldtypes)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)
|
||
|
||
{
|
||
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)
|
||
{
|
||
if (t == _intzerofld || t == _longzerofld)
|
||
{
|
||
byte i = 0;
|
||
for (char* c = (char*)recin; i < l; c++, i++)
|
||
if (*c == ' ') *c = '0';
|
||
else break;
|
||
if (i == l)
|
||
l = 0;
|
||
}
|
||
else
|
||
{
|
||
while ((*recin == ' ') && (l))
|
||
{
|
||
recin++;
|
||
l--;
|
||
}
|
||
if ((t != _realfld) && (t != _charfld))
|
||
{
|
||
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 (*s)
|
||
{
|
||
if (t == _datefld)
|
||
{
|
||
const TDate dt(atol(s));
|
||
strcpy(s, dt.string(full));
|
||
} else
|
||
if (t == _boolfld)
|
||
{
|
||
const char ok = toupper(*s);
|
||
if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == '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)
|
||
{
|
||
const TDate dt(s2);
|
||
sprintf(s2,"%8s", dt.string(ANSI));
|
||
}
|
||
}
|
||
else
|
||
if (t == _boolfld)
|
||
{
|
||
const char ok = toupper(*s2);
|
||
if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X')
|
||
strcpy(s2, "T");
|
||
else
|
||
strcpy(s2, "F");
|
||
}
|
||
else
|
||
if (t == _realfld) setdec(s2, d);
|
||
|
||
len = strlen(s2);
|
||
|
||
if (len > l)
|
||
{
|
||
yesnofatal_box("Impossibile scrivere %d caratteri su di un campo di %d", (int)len, (int)l);
|
||
return;
|
||
}
|
||
|
||
if ((t == _intfld) ||
|
||
(t == _longfld) ||
|
||
(t == _wordfld) ||
|
||
(t == _realfld) ||
|
||
(t == _intzerofld) ||
|
||
(t == _longzerofld)
|
||
)
|
||
{
|
||
if (len == 0)
|
||
{
|
||
strcpy(s2, "0");
|
||
len = 1;
|
||
}
|
||
|
||
const char c = (t == _intzerofld || t == _longzerofld) ? '0' : ' ';
|
||
i = 0;
|
||
while (i < l - len - 1) recout[i++] = c;
|
||
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
|
||
{
|
||
__getfieldbuff(_len, _type, _p, _isam_string);
|
||
TDate d(_isam_string);
|
||
return d;
|
||
}
|
||
|
||
|
||
TRecfield::operator const char*() const
|
||
{
|
||
if (_type == _memofld)
|
||
return _rec->get(_name);
|
||
|
||
__getfieldbuff(_len, _type, _p, _isam_string);
|
||
return _isam_string;
|
||
}
|
||
|
||
|
||
TRecnotype TRecfield::ptr() const
|
||
{
|
||
if (_p == NULL) return(RECORD_NON_FISICO);
|
||
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;
|
||
}
|
||
|