angelo 8285ab7fec Ripristinata correzione sul lock esclusivo dei file (r 1.8).
Questo commit e' servito anche a togliere i ^M


git-svn-id: svn://10.65.10.50/trunk@1611 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-07-19 08:53:29 +00:00

1021 lines
30 KiB
C
Executable File

/*
Attenzione!. Per costruire la DLL accertarsi che siano attivati i seguenti switch:
1) S4DLL_BUILD definito da command line del compilatore
2) Uno solo tra S4FOX S4CLIPPER S4NDX e S4MDX, definito in d4all.h
Gli altri switch di configurazione generale sono a piacere (S4DEBUG, S4ERROR_HOOK, ecc.)
Per costruire WINUNO.LIB Accertarsi che d4all.h non abbia definito S4DLL o S4UNIX,
e tanto meno S4DLL_BUILD, altrimenti per costruire la library di UNIX e' necessario
cambiare ogni volta. La definizione di tali simboli avviene qui dentro.
Inoltre deve essere attivo uno solo degli switch di selezione formato database
(S4FOX, S4MDX ecc.); nel caso si faccia uso della DLL non importa quale si e' definito.
E' importante solo in caso di utilizzo di una static Library.
Per costruire l'aga.fll e' necessario togliere le funzioni progind* e definire S4DLL.
*/
#if XVT_OS == XVT_OS_SCOUNIX
#define S4UNIX
#else
#define S4DLL
#endif
#ifdef XVT /* This not recommended in Unix!*/
#undef S4UNIX
#define S4DLL
#endif
#ifdef FOXPRO
#undef S4UNIX
#define S4DLL
#endif
#include <d4all.h>
#include <x4filter.h>
#include <i4chang.h>
#include <codeb.h>
#include <rectypes.h>
#include <progind.h>
#define MAXLEN 128 /* Lunghezza massima chiave */
extern char* CUpString(char *);
static CODE4 code_base;
static DATA4 *dbdata[CB4FILES];
static X4FILTER xdb[CB4FILES];
static char * find_slash_backslash(char * str)
{
int l=strlen(str);
static char * xstr ;
xstr = str + l;
while (xstr-- && l--)
if (*xstr == '\\' || *xstr == '/')
break;
if (l == 0)
return NULL;
else
return xstr;
}
/*--------------------------------------------------------------------------
funzione di filtro usata su tutti i database
--------------------------------------------------------------------------*/
int S4CALL notdelete(void *fd)
{
if(d4deleted(fd)) return r4ignore;
else return r4keep;
}
/*--------------------------------------------------------------------------
inizializzazione di CodeBase e delle variabili necessarie
questa funzione deve essere chiamata SOLO una volta all'interno
di ciascun eseguibile
--------------------------------------------------------------------------*/
void DB_init(void)
{
int i;
for(i=0;i<CB4FILES;i++) {
dbdata[i]=(DATA4 *) 0;
}
d4init(&code_base);
code_base.read_lock=0;
code_base.default_unique_error=e4unique;
code_base.safety=0;
code_base.lock_attempts=1;
// code_base.optimize_write = 0;
u4ncpy(code_base.date_format,"CCYYMMDD",sizeof(code_base.date_format));
}
/*--------------------------------------------------------------------------
reset di CodeBase
questa funzione dovrebbe essere chiamata prima di uscire da un eseguibile
per una questione di correttezza formale. Non usandola comunque non acca-
de niente di drammatico
--------------------------------------------------------------------------*/
void DB_exit(void)
{
d4init_undo(&code_base);
}
/*-------------------------------------------------------------------------
apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura
esclusiva
--------------------------------------------------------------------------*/
int DB_open(const char *filename,int mode)
{
int i,found;
if (mode) code_base.exclusive=1;
/* cerca il primo posto libero nel vettore dbdata */
found=-1;
for(i=0;i<CB4FILES;i++) {
if(dbdata[i]==(DATA4 *) 0) {
found=i;
break;
}
}
/* se non ci sono posti liberi torna -1 */
if(found==-1) return(found);
code_base.error_code=0;
dbdata[found]=d4open(&code_base,(char*)filename);
if(dbdata[found]==0) return(-1);
x4init(&xdb[found],dbdata[found],notdelete,dbdata[found]);
code_base.exclusive=0;
d4tag_select(dbdata[found],d4tag_default(dbdata[found]));
if (d4reccount(dbdata[found]) > 0)
x4top(&xdb[found]);
return(found);
}
/*-------------------------------------------------------------------------
chiusura del database inviduato da handle
torna -1 se il database non puo essere chiuso
--------------------------------------------------------------------------*/
int DB_close(int handle)
{
if(dbdata[handle]==0) return(-1);
d4close(dbdata[handle]);
dbdata[handle]=(DATA4 *) 0;
code_base.error_code=0;
return(0);
}
/*-------------------------------------------------------------------------
torna il puntatore al buffer del record del database individuato da
handle. In caso di errore torna (char *) 0
--------------------------------------------------------------------------*/
char *DB_getrecord(int handle)
{
if(dbdata[handle]==0) return((char *) 0);
return(d4record(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza del record
--------------------------------------------------------------------------*/
int DB_reclen(int handle)
{
if(dbdata[handle]==0) return(-1);
return((int) d4record_width(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza della chiave corrente
--------------------------------------------------------------------------*/
int DB_keylen(int handle)
{
TAG4 *t;
if (dbdata[handle]==0) return(-1);
if ((t=d4tag_default(dbdata[handle]))== NULL) return (-1);
return(expr4key_len(t->expr));
}
/*-------------------------------------------------------------------------
torna il numero del record attuale
--------------------------------------------------------------------------*/
long int DB_recno(int handle)
{
if(dbdata[handle]==0) return(-1L);
return(d4recno(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna il numero complessivo dei records presenti nell'archivio
--------------------------------------------------------------------------*/
long int DB_reccount(int handle)
{
if(dbdata[handle]==0) return(-1L);
return(d4reccount(dbdata[handle]));
}
/*-------------------------------------------------------------------------
seleziona un indice sul database specificato
torna -1 se errore, altrimenti 0
--------------------------------------------------------------------------*/
int DB_tagselect(int handle,int index_no)
{
TAG4 *tt;
int i;
if(dbdata[handle]==0) return(-1);
/* si posiziona sul primo indice */
tt=d4tag_next(dbdata[handle],NULL);
if(tt==NULL) return(-1);
for(i=1;i<index_no;i++) {
tt=d4tag_next(dbdata[handle],tt);
if(tt==NULL) return(-1);
}
d4tag_select(dbdata[handle],tt);
return(0);
}
/*-------------------------------------------------------------------------
torna il numero dell'indice selezionato
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_tagget(int handle)
{
TAG4 *tt,*tt1;
int i;
if(dbdata[handle]==0) return(-1);
/* si posiziona sul primo indice */
tt=d4tag_selected(dbdata[handle]);
if(tt==NULL) return(-1);
tt1=d4tag_next(dbdata[handle],NULL);
i=1;
while(tt!=tt1 && tt1!=NULL) {
tt1=d4tag_next(dbdata[handle],tt1);
i++;
}
return(i);
}
/*-------------------------------------------------------------------------
si posiziona sul primo record
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_first(int handle)
{
if(dbdata[handle]==0) return(-1);
return(x4top(&xdb[handle]));
}
/*-------------------------------------------------------------------------
si posiziona sull'ultimorecord
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_last(int handle)
{
if(dbdata[handle]==0) return(-1);
return(x4bottom(&xdb[handle]));
}
/*-------------------------------------------------------------------------
skip avanti di un record
--------------------------------------------------------------------------*/
int DB_next(int handle)
{
if(dbdata[handle]==0) return(-1);
return(x4skip(&xdb[handle],1L));
}
/*-------------------------------------------------------------------------
skip indietro di un record
--------------------------------------------------------------------------*/
int DB_prev(int handle)
{
if(dbdata[handle]==0) return(-1);
return(x4skip(&xdb[handle],-1L));
}
/*-------------------------------------------------------------------------
skip di n records
--------------------------------------------------------------------------*/
int DB_skip(int handle,long int recno)
{
if(dbdata[handle]==0) return(-1);
return(x4skip(&xdb[handle],recno));
}
/*-------------------------------------------------------------------------
locka il record attuale
--------------------------------------------------------------------------*/
int DB_lock(int handle)
{
if(dbdata[handle]==0) return(-1);
return(d4lock(dbdata[handle],d4recno(dbdata[handle])));
}
/*-------------------------------------------------------------------------
slocka il record attuale
--------------------------------------------------------------------------*/
int DB_unlock(int handle)
{
if(dbdata[handle]==0) return(-1);
return(d4unlock(dbdata[handle]));
}
/*-------------------------------------------------------------------------
cerca la chiave, torna r4after se not found ma si e' posizionato sul record
successivo, se torna r4eof e' su eof
--------------------------------------------------------------------------*/
int DB_seek(int handle,char *key)
{
int rc, len;
TAG4 * tt;
char * k;
if(dbdata[handle]==0) return(-1);
rc = x4seek(&xdb[handle],key);
if (rc)
return rc;
tt = d4tag_selected(dbdata[handle]);
len = expr4key_len(tt->expr);
k = t4key(tt);
while (len > 0 && k[len-1] == ' ') len--;
rc = strncmp(key, k, len);
if (rc == 0)
return 0;
else
if (rc < 0)
return r4after;
else
return r4eof;
}
/*-------------------------------------------------------------------------
torna 1 se eof, 0 altrimenti
--------------------------------------------------------------------------*/
int DB_eof(int handle)
{
if(dbdata[handle]==0) return(-1);
return(d4eof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna 1 se tof, 0 altrimenti
--------------------------------------------------------------------------*/
int DB_bof(int handle)
{
if(dbdata[handle]==0) return(-1);
return(d4bof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
legge un record per numero record
--------------------------------------------------------------------------*/
int DB_go(int handle,long int recno)
{
if(dbdata[handle]==0) return(-1);
return(x4go(&xdb[handle],recno));
}
/*-------------------------------------------------------------------------
cancella il record attuale. Non cancella le chiavi.
--------------------------------------------------------------------------*/
int DB_delete(int handle)
{
if(dbdata[handle]==0) return(-1);
d4delete(dbdata[handle]);
return(0);
}
/*-------------------------------------------------------------------------
ripristina il record attuale
--------------------------------------------------------------------------*/
int DB_recall(int handle)
{
if(dbdata[handle]==0) return(-1);
d4recall(dbdata[handle]);
return(0);
}
/*-------------------------------------------------------------------------
cancella dall'indice corrente la chiave specificata
--------------------------------------------------------------------------*/
int DB_delkey(int handle, char* key, long recno)
{
INDEX4* i;
TAG4* t;
int rt=0;
char fn[64];
if(dbdata[handle]==0) return(-1);
t=d4tag_default(dbdata[handle]);
if (u4switch() & 2 || u4switch() & 8) /* Clipper & DBIII */
u4name_piece(fn,64,dbdata[handle]->file.name,0,0);
else
strcpy(fn,dbdata[handle]->file.name);
if ((i=d4index(dbdata[handle],fn)) == NULL)
return(e4index);
while ((rt=i4lock(i)) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_delkeys");
#else
u4delay_sec();
#endif
if (rt == 0)
rt=t4remove_calc(t,recno);
i4unlock(i);
return(rt);
}
/*-------------------------------------------------------------------------
cancella dall'indice corrente la chiave specificata
--------------------------------------------------------------------------*/
int DB_flush(int handle)
{
int rt;
while ((rt = d4flush(dbdata[handle])) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add (d4append)");
#else
u4delay_sec();
#endif
return rt;
}
/*-------------------------------------------------------------------------
riscrive il record attuale
--------------------------------------------------------------------------*/
int DB_rewrite(int handle)
{
int rt;
if(dbdata[handle]==0) return(-1);
while ((rt=d4write(dbdata[handle],d4recno(dbdata[handle]))) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_rewrite");
#else
u4delay_sec();
#endif
if (rt == 0)
{
while ((rt = d4flush(dbdata[handle])) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add (d4append)");
#else
u4delay_sec();
#endif
}
if (rt == e4unique)
{
DB_get_error();
fatal_box("Errore : chiave duplicata nell' indice %d", dbdata[handle]->rec_num + 1);
}
rt=DB_unlock(handle);
return (rt);
}
/*-------------------------------------------------------------------------
appende il record attuale
--------------------------------------------------------------------------*/
int DB_add(int handle)
{
int rt;
DATA4 * data = dbdata[handle];
if (data==0) return(-1);
while (file4lock(&data->file, L4LOCK_POS_OLD, 1L) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add");
#else
u4delay_sec();
#endif
while ((rt = d4append_start(data,0)) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add (d4append_start)");
#else
u4delay_sec();
#endif
if (rt == 0)
{
d4recall(data);
while ((rt = d4append(data)) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add (d4append)");
#else
u4delay_sec();
#endif
if (rt == e4unique)
{
DB_get_error();
if (data->rec_num > 0)
fatal_box("Errore : chiave duplicata nell' indice %d", data->rec_num + 1);
else
rt = _isreinsert;
}
else
if (rt == 0)
{
while ((rt = d4flush(data)) == r4locked)
#ifdef DBG
message_box("Sono in attesa nella DB_add (d4append)");
#else
u4delay_sec();
#endif
}
}
DB_unlock(handle);
file4unlock(&data->file, L4LOCK_POS_OLD, 1L);
return(rt);
}
/*-------------------------------------------------------------------------
Blocca in modo esclusivo il file dati ed indice
--------------------------------------------------------------------------*/
int DB_lockfile(int handle)
{
int rt;
if(dbdata[handle]==0) return(-1);
rt = d4lock_file(dbdata[handle]);
if (rt==0) rt=d4lock_index(dbdata[handle]);
return(rt);
}
HIDDEN int is_inkey(RecDes *r, int numfield)
{
int found=0,i,j;
for (i=0; ((i < MaxKeys) && (i < r->NKeys) && !found); i++)
for (j=0; ((j < r->Ky[i].NkFields) && !found); j++)
if (numfield == r->Ky[i].FieldSeq[j])
found=1;
return(found);
}
HIDDEN void do_key(char *fname, RecDes *r, TAG4INFO *tag_info)
{
int i,j;
char tiname[9]; /* Tag name, max 8 characters long! */
strcpy(tiname,fname);
CUpString(tiname);
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
{
tag_info[i].name=(char *)u4alloc(9);
tag_info[i].expression=(char *)u4alloc(128);
tag_info[i].filter=(char*)u4alloc(20);
tag_info[i].descending=0;
if (r->Ky[i].DupKeys)
tag_info[i].unique=0;
else
tag_info[i].unique=e4unique;
strcpy(tag_info[i].filter,""); /* Not available for DBIII and CLIPPER */
strcpy(tag_info[i].name,tiname) ;
if (strlen(tiname) < 8)
strcat(tag_info[i].name," ");
tag_info[i].name[strlen(tag_info[i].name)-1] = '0' + i + 1;
for (j=0; j < r->Ky[i].NkFields; j++)
{
int nf= r->Ky[i].FieldSeq[j];
if (nf > MaxFields) /* When Upper field is specified */
{
nf -= MaxFields;
strcat(tag_info[i].expression,"UPPER(");
}
if (r->Ky[i].FromCh[j] != 255) /* When partial field is specified */
strcat(tag_info[i].expression,"SUBSTR(");
switch (r->Fd[nf].TypeF) /* When numeric field in key is specified */
{
case _intfld:
case _longfld:
case _realfld:
case _wordfld:
case _intzerofld:
case _longzerofld:
strcat(tag_info[i].expression,"STR(");
break;
case _datefld:
strcat(tag_info[i].expression,"DTOS(");
break;
case _boolfld:
strcat(tag_info[i].expression,"IIF("); /* Logical fields are in key too.. */
break;
default: /* It's a non sense to keep _realfld in key... */
break; /* however it's possible to have it... */
} /* Le chiavi composte da campi data non necessitano di funzioni di traduzione. */
strcat(tag_info[i].expression,r->Fd[nf].Name); /* Append field name */
if (r->Ky[i].FromCh[j] != 255) /* If partial field was specified */
{ /* add parameters to SUBSTR */
char ts[8];
strcat(tag_info[i].expression,",");
sprintf(ts,"%d",r->Ky[i].FromCh[j]);
strcat(tag_info[i].expression,ts);
strcat(tag_info[i].expression,",");
sprintf(ts,"%d",r->Ky[i].ToCh[j] - r->Ky[i].FromCh[j] + 1);
strcat(tag_info[i].expression,ts);
strcat(tag_info[i].expression,")");
}
switch (r->Fd[nf].TypeF) /* If numeric field was specified */
{ /* add parameters to STR */
case _intfld:
case _longfld:
case _realfld: /* Questo tipo di campo(real) non ha senso in un a chiave... */
case _wordfld:
case _intzerofld:
case _longzerofld:
{
char ts[8];
strcat(tag_info[i].expression,",");
sprintf(ts,"%d",r->Fd[nf].Len);
strcat(tag_info[i].expression,ts);
strcat(tag_info[i].expression,",0)");
}
break;
case _boolfld:
strcat(tag_info[i].expression,",\"T\",\"F\")");
break;
default:
break;
}
/* Close parentheses if UPPER or DTOS operators were used: */
if (r->Ky[i].FieldSeq[j] > MaxFields || (r->Fd[nf].TypeF == _datefld))
strcat(tag_info[i].expression,")");
/* If there's another field in key adds "+" operator: */
if (j < (r->Ky[i].NkFields-1))
strcat(tag_info[i].expression,"+");
}
}
tag_info[i].name=NULL;
tag_info[i].expression=NULL;
tag_info[i].filter=NULL;
tag_info[i].unique=0;
tag_info[i].descending=0;
}
/*-------------------------------------------------------------------------
Compatta il file dati
--------------------------------------------------------------------------*/
int DB_packfile(short vis, const char * filename, long eod)
{
int rt=0,handle;
/*
if(dbdata[handle]==0) return(-1);
codebase.auto_open = 0 cosi' non apre gli indici
*/
code_base.auto_open = 0;
handle=DB_open(filename,1); /* Exclusive mode open! */
if (handle > -1)
{
char s[81];
if (vis)
{
strcpy(s,"Compattamento dati file : ");
strcat(s,(char*)filename);
#ifndef FOXPRO
progind_create(10L,s,1,1,1);
#endif
}
if (eod < d4reccount(dbdata[handle]))
{
rt=d4zap(dbdata[handle],++eod,d4reccount(dbdata[handle]));
} else
rt=d4pack(dbdata[handle]);
if (vis)
{
#ifndef FOXPRO
progind_set_status((long)10);
progind_destroy();
#endif
}
DB_close(handle);
}
else
rt=code_base.error_code;
code_base.auto_open = 1;
return rt;
}
/*-------------------------------------------------------------------------
Compatta gli indici
--------------------------------------------------------------------------*/
int DB_packindex(short vis, const char * filename, RecDes *r, long *peod)
{
int rt=0,handle;
TAG4INFO tags[MaxKeys+1];
char s[82];
strcpy(s,"Ricostruzione indici file : ");
strcat(s,filename);
/* codebase.auto_open = 0 cosi' non apre gli indici */
code_base.auto_open=0 ;
handle=DB_open(filename,1); /* Exclusive mode open */
if (handle > -1)
{
int i;
char *ff = find_slash_backslash((char *)filename);
if (vis)
{
#ifndef FOXPRO
progind_create((long)r->NKeys,s,1,1,1);
#endif
}
if (ff == NULL || *ff == NULL)
ff = filename;
else
ff++;
do_key(ff,r,tags);
if (u4switch() &2 || u4switch() & 8) /* Clipper and DBIII */
{
rt = (int)i4create(dbdata[handle],(char*)filename,tags);
#ifndef FOXPRO
progind_set_status((long)r->NKeys);
#endif
if (rt!=0 && code_base.error_code==0)
{
FILE *fp;
char cgp[81];
strcpy(cgp,filename);
strcat(cgp,".CGP");
if ((fp=fopen(cgp,"w"))!=NULL)
{
int j;
for (j=0; j<r->NKeys;j++)
fprintf(fp,"%s\n",tags[j].name);
fclose(fp);
}
}
}
if (u4switch() & 1 || u4switch() & 4) /* FOXPRO and DBIV */
{
rt = (int)i4create(dbdata[handle],NULL,tags);
#ifndef FOXPRO
progind_set_status((long)r->NKeys);
#endif
}
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
{
u4free(tags[i].name);
u4free(tags[i].expression);
u4free(tags[i].filter);
}
if (vis)
{
#ifndef FOXPRO
progind_destroy();
#endif
}
*peod=DB_reccount(handle);
DB_close(handle);
}
code_base.auto_open = 1;
return(code_base.error_code);
}
/*-------------------------------------------------------------------------
costruisce il file filename
--------------------------------------------------------------------------*/
int DB_build(const char * filename, RecDes *r)
{
FIELD4INFO field_info[MaxFields+1]; /* Numero di campi in un record */
TAG4INFO tag_info[MaxKeys+1]; /* Numero di chiavi in un file */
DATA4 *dbuilded;
int rt=0,i;
char *ff = find_slash_backslash((char *)filename);
for (i=0; ((i<r->NFields) && (i<MaxFields)); i++) /* Construct field_info */
{
field_info[i].name = (char*)u4alloc(12);
strcpy(field_info[i].name,r->Fd[i].Name);
field_info[i].len = r->Fd[i].Len;
field_info[i].dec = r->Fd[i].Dec;
switch (r->Fd[i].TypeF)
{
case _intfld:
case _longfld:
case _realfld: /* It's a non sense to keep this in key! */
case _wordfld:
case _intzerofld:
case _longzerofld:
field_info[i].type=r4num;
break;
case _boolfld:
field_info[i].type=r4log;
break;
case _datefld:
field_info[i].type=r4date;
break;
case _charfld:
default:
field_info[i].type=r4str;
break;
}
}
field_info[i].name=NULL;
field_info[i].type=0;
field_info[i].len=0;
field_info[i].dec=0;
if (ff == NULL || *ff == NULL)
ff = (char *) filename;
else
ff++;
do_key(ff,r,tag_info);
if ((dbuilded=d4create(&code_base, (char *)filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */
rt=code_base.error_code;
else
rt=d4close(dbuilded);
if (u4switch() & 2 || u4switch() & 8) /* Rebuild filename.cgp for CLIPPER AND DBIII only */
{
FILE* fp;
char xx[81];
strcpy(xx,(char*)filename);
strcat(xx,".cgp");
if ((fp=fopen(xx,"w"))!=NULL)
{
int j;
for (j=0; tag_info[j].name ; j++)
fprintf(fp,"%s\n",tag_info[j].name);
fclose(fp);
}
}
if (rt!=0)
rt=code_base.error_code;
for (i=0; ((i < MaxFields) && (i < r->NFields)); i++)
u4free(field_info[i].name);
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
{
u4free(tag_info[i].name);
u4free(tag_info[i].expression);
u4free(tag_info[i].filter);
}
return(rt) ;
}
/*-------------------------------------------------------------------------
ritorna l'ultimo errore
--------------------------------------------------------------------------*/
int DB_get_error(void)
{
int rt = code_base.error_code;
code_base.error_code=0;
return (rt);
}
/*-------------------------------------------------------------------------
Azzera la viarabile globale d'errore
--------------------------------------------------------------------------*/
void DB_zero_error(void)
{
code_base.error_code=0;
}
/*-------------------------------------------------------------------------
Si posiziona sull'indice attivo alla chiave indicata, restituisce
la prima chiave che trova >= a from. (TCusrsor)
--------------------------------------------------------------------------*/
int DB_index_seek(int handle, char* from)
{
TAG4 *t;
if(dbdata[handle]==0) return(-1);
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
if (t4seek(t,from,strlen(from)) < 0) return(DB_get_error());
return(0);
}
/*-------------------------------------------------------------------------
Ritorna il numero di record corrispondente alla chiave corrente
--------------------------------------------------------------------------*/
long DB_index_recno(int handle)
{
TAG4 *t;
if(dbdata[handle]==0) return(-1);
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
return(t4recno(t));
}
/*-------------------------------------------------------------------------
Si posiziona sulla chiave successiva dell'indice corrente
--------------------------------------------------------------------------*/
long DB_index_next(int handle)
{
TAG4 *t;
if(dbdata[handle]==0) return(-1);
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
return(t4skip(t,1L));
}
/*-------------------------------------------------------------------------
Restituisce la chiave corrente
--------------------------------------------------------------------------*/
char* DB_index_getkey(int handle)
{
TAG4 *t;
static char key[MAXLEN];
int klen;
if(dbdata[handle]==0) return(NULL);
if ((t=d4tag_default(dbdata[handle]))==NULL) return(NULL);
klen=expr4key_len(t->expr);
if (klen > (MAXLEN-1)) klen=MAXLEN-1;
memcpy(key,t4key(t),klen); /* t4key non restituisce una null terminated string */
key[klen]='\0';
return(key);
}
/*-------------------------------------------------------------------------
Restituisce vero se l'indice e' alla fine
--------------------------------------------------------------------------*/
int DB_index_eof(int handle)
{
TAG4 *t;
if(dbdata[handle]==0) return(-1);
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
return(t4eof(t));
}
/*-------------------------------------------------------------------------
Blocca il record indicato
--------------------------------------------------------------------------*/
int DB_lock_rec(int handle,long nrec)
{
if(dbdata[handle]==0) return(-1);
if(d4lock(dbdata[handle],nrec)==r4locked) return(-1);
else return(0);
}
/*-------------------------------------------------------------------------
Ritorna vero se il file e' bloccato in modo exclusive
--------------------------------------------------------------------------*/
int DB_file_locked(int handle)
{
if(dbdata[handle]==0) return(-1);
return(d4lock_test_file(dbdata[handle]));
}
/*-------------------------------------------------------------------------
Ritorna vero se il record nrec e' bloccato
--------------------------------------------------------------------------*/
int DB_rec_locked(int handle,long nrec)
{
if(dbdata[handle]==0) return(-1);
return(d4lock_test(dbdata[handle],nrec));
}
/*-------------------------------------------------------------------------
restituisce la configurazione della libreria
--------------------------------------------------------------------------*/
long DB_getconf()
{
return(u4switch());
}
/*-------------------------------------------------------------------------
Restituisce il numero di versione scritto sull'header dell'indice
--------------------------------------------------------------------------*/
long DB_changed(int handle)
{
INDEX4 *i;
char fn[64];
if(dbdata[handle]==0) return(-1);
if (u4switch() & 2 || u4switch() & 8) /* Clipper & DBIII */
u4name_piece(fn,64,dbdata[handle]->file.name,0,0);
else
strcpy(fn,dbdata[handle]->file.name);
i=d4index(dbdata[handle],fn);
if (i == NULL) return(-1);
return(i4changed(i));
}