guy eba1707224 Milgiorato supporto per progress dialog nativa
git-svn-id: svn://10.65.10.50/branches/R_10_00@23122 c028cbd2-c16b-5b4b-a496-9718f37d4682
2015-07-10 14:52:21 +00:00

1199 lines
34 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.
*/
#define XVT_INCL_NATIVE
#include <xvt.h>
#define S4OFF_REPORT
//#define S4DLL
//#define S4WIN32
#include <d4all.h>
#include <codeb.h>
#include <rectypes.h>
/*--------------------------------------------------------------------------
numero massimo di database aperti contemporaneamente
--------------------------------------------------------------------------*/
#define CB4FILES 64
#define MAXLEN 137 /* Lunghezza massima chiave */
static CODE4 code_base;
static DATA4* dbdata[CB4FILES];
static bool dbfast[CB4FILES];
#define HANDLE2DATA(handle, data) DATA4* data = dbdata[handle]; if (handle < 0 || handle >= CB4FILES || data == NULL || data->clientId < 0) return -1
#define HANDLE2DATASTR(handle, data) DATA4* data = dbdata[handle]; if (handle < 0 || handle >= CB4FILES || data == NULL || data->clientId < 0) return NULL
static const char* find_slash_backslash(const char* s)
{
const char* slash = NULL;
for ( ; *s; s++)
{
if (*s == '\\' || *s == '/')
slash = s;
}
return slash;
}
/*--------------------------------------------------------------------------
inizializzazione di CodeBase e delle variabili necessarie
questa funzione deve essere chiamata SOLO una volta all'interno
di ciascun eseguibile
--------------------------------------------------------------------------*/
void DB_init(void)
{
memset(dbdata, 0, sizeof(dbdata));
code4init(&code_base);
// Nella 3.0 il default LOCK4DATA e' stato messo nella DLL per non ridistribuire tutto.
// Nelle versioni succesive la DLL e' "intonsa" ed ha un default diverso deciso da Codebase.
// Per cui ora forziano LOCK4DATA (anche se considerato deprecated)
// in quanto non funziona bene LOCK4RECORD (che sarebbe quello giusto)
code4unlockAutoSet(&code_base, LOCK4DATA);
code_base.readLock=0;
code_base.errDefaultUnique=e4unique;
code_base.safety=0;
code_base.lockAttempts=1;
code4dateFormatSet(&code_base, "CCYYMMDD");
code_base.optimize = OPT4EXCLUSIVE; // Is the default?
code_base.optimizeWrite = OPT4EXCLUSIVE; // Is the default?
}
/*--------------------------------------------------------------------------
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)
{
int i;
for (i = 0; i < CB4FILES; i++)
{
if (dbdata[i] != NULL)
DB_close(i);
}
code4initUndo(&code_base);
}
/*-------------------------------------------------------------------------
apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura
esclusiva. Il parametro index consente se == 0 l'apertura senza indici
--------------------------------------------------------------------------*/
int DB_open(const char *filename,int mode,int index)
{
int i,found;
/* cerca il primo posto libero nel vettore dbdata */
found=-1;
for(i=0;i<CB4FILES;i++)
{
if(dbdata[i]==(DATA4*)NULL)
{
found=i;
break;
}
}
if (found >= 0)
{
if (mode)
code_base.accessMode=1; // Exclusive mode
code_base.errorCode=0;
if (!index)
{
code_base.autoOpen = 0; // Se e' stata richiesta l'apertura senza indici, resetta il flag autoOpen
dbdata[found]=d4open(&code_base, filename);
code_base.autoOpen = 1;
}
else
dbdata[found]=d4open(&code_base, filename);
if (mode)
code_base.accessMode=0; // Not-Exclusive mode
if(dbdata[found]!=NULL)
{
HANDLE2DATA(found, data);
// Guy: Non capisco bene perche' seleziono comunque un indice
d4tagSelect(data, d4tagDefault(data));
if (d4recCount(data) > 0)
d4top(data);
dbfast[found] = mode!=0; // Ottimizabile se esclusivo
}
else
return code_base.errorCode;
}
return found;
}
/*-------------------------------------------------------------------------
chiusura del database inviduato da handle
torna -1 se il database non puo essere chiuso
--------------------------------------------------------------------------*/
int DB_close(int handle)
{
HANDLE2DATA(handle, data);
d4close(data);
dbdata[handle] = NULL;
dbfast[handle] = FALSE;
code_base.errorCode=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)
{
HANDLE2DATASTR(handle, data);
return d4record(data);
}
/*-------------------------------------------------------------------------
torna la lunghezza del record
--------------------------------------------------------------------------*/
int DB_reclen(int handle)
{
HANDLE2DATA(handle, data);
return (int)d4recWidth(data);
}
/*-------------------------------------------------------------------------
torna la lunghezza della chiave corrente
--------------------------------------------------------------------------*/
int DB_keylen(int handle)
{
HANDLE2DATA(handle, data);
return a4tagKeyLen(data);
}
/*-------------------------------------------------------------------------
torna il numero del record attuale
--------------------------------------------------------------------------*/
long int DB_recno(int handle)
{
HANDLE2DATA(handle, data);
return d4recNo(data);
}
/*-------------------------------------------------------------------------
torna il numero complessivo dei records presenti nell'archivio
--------------------------------------------------------------------------*/
long int DB_reccount(int handle)
{
HANDLE2DATA(handle, data);
return d4recCount(data);
}
/*-------------------------------------------------------------------------
seleziona un indice sul database specificato
torna -1 se errore, altrimenti 0
--------------------------------------------------------------------------*/
int DB_tagselect(int handle,int index_no)
{
TAG4 *tt;
int i;
HANDLE2DATA(handle, data);
/* si posiziona sul primo indice */
tt=d4tagNext(data, NULL);
if (tt==NULL)
return -1;
for(i=1; i<index_no; i++)
{
tt=d4tagNext(data, tt);
if(tt==NULL)
return(-1);
}
d4tagSelect(data, tt);
return 0;
}
/*-------------------------------------------------------------------------
torna il numero dell'indice selezionato
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_tagget(int handle)
{
TAG4 *tt,*tt1;
int i;
HANDLE2DATA(handle, data);
/* si posiziona sul primo indice */
tt=d4tagDefault(data);
if(tt==NULL)
return(-1);
tt1=d4tagNext(data,NULL);
i=1;
while(tt!=tt1 && tt1!=NULL)
{
tt1=d4tagNext(data,tt1);
i++;
}
return(i);
}
/*-------------------------------------------------------------------------
si posiziona sul primo record
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_first(int handle)
{
HANDLE2DATA(handle, data);
return d4top(data);
}
/*-------------------------------------------------------------------------
si posiziona sull'ultimorecord
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_last(int handle)
{
HANDLE2DATA(handle, data);
return d4bottom(data);
}
/*-------------------------------------------------------------------------
skip avanti di un record
--------------------------------------------------------------------------*/
int DB_next(int handle)
{
return DB_skip(handle, +1);
}
/*-------------------------------------------------------------------------
skip indietro di un record
--------------------------------------------------------------------------*/
int DB_prev(int handle)
{
return DB_skip(handle, -1);
}
/*-------------------------------------------------------------------------
skip di n records
--------------------------------------------------------------------------*/
int DB_skip(int handle, long recno)
{
HANDLE2DATA(handle, data);
return d4skip(data, recno);
}
/*-------------------------------------------------------------------------
locka il record attuale
--------------------------------------------------------------------------*/
int DB_lock(int handle)
{
HANDLE2DATA(handle, data);
return d4lock(data, d4recNo(data));
}
/*-------------------------------------------------------------------------
slocka il record attuale
--------------------------------------------------------------------------*/
int DB_unlock(int handle)
{
HANDLE2DATA(handle, data);
return d4unlock(data);
}
/*-------------------------------------------------------------------------
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;
const char * k;
HANDLE2DATA(handle, data);
rc = d4seek(data,key);
if (rc)
return rc;
len = a4tagKeyLen(data);
k = a4tagKey(data);
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)
{
HANDLE2DATA(handle, data);
return d4eof(data);
}
/*-------------------------------------------------------------------------
torna 1 se bof, 0 altrimenti
--------------------------------------------------------------------------*/
int DB_bof(int handle)
{
HANDLE2DATA(handle, data);
return d4bof(data);
}
/*-------------------------------------------------------------------------
legge un record per numero record
--------------------------------------------------------------------------*/
int DB_go(int handle,long recno)
{
HANDLE2DATA(handle, data);
return d4go(data,recno);
}
/*-------------------------------------------------------------------------
cancella il record attuale. Non cancella le chiavi.
--------------------------------------------------------------------------*/
int DB_delete(int handle)
{
HANDLE2DATA(handle, data);
d4delete(data);
return 0;
}
/*-------------------------------------------------------------------------
ripristina il record attuale
--------------------------------------------------------------------------*/
int DB_recall(int handle)
{
HANDLE2DATA(handle, data);
d4recall(data);
return 0;
}
/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
int DB_flush(int handle)
{
int rt = 0;
HANDLE2DATA(handle, data);
if (dbfast[handle])
{
if (data->dataFile->nFieldsMemo > 0)
rt = d4write(data, -1);
}
else
{
while ((rt = d4flush(data)) == r4locked)
u4delaySec();
}
return rt;
}
/*-------------------------------------------------------------------------
riscrive il record attuale
--------------------------------------------------------------------------*/
int DB_rewrite(int handle)
{
int rt = -1;
HANDLE2DATA(handle, data);
while ((rt=d4write(data,d4recNo(data))) == r4locked)
u4delaySec();
if (rt == e4unique)
{
char msg[256];
DB_get_error();
sprintf(msg, "Errore in DB_rewrite(): chiave duplicata nel record %ld, file %s",
d4recNo(data) + 1, d4fileName(data));
xvt_dm_post_fatal_exit(msg);
}
if (rt == 0)
rt = DB_flush(handle);
rt = DB_unlock(handle);
return (rt);
}
/*-------------------------------------------------------------------------
appende il record attuale
--------------------------------------------------------------------------*/
int DB_add(int handle)
{
int rt = -1;
HANDLE2DATA(handle, data);
while ((rt = d4appendStart(data,0)) == r4locked)
u4delaySec();
if (rt == 0)
{
d4recall(data);
while ((rt = d4append(data)) == r4locked)
u4delaySec();
if (rt == e4unique)
{
const long rec_num = d4recNo(data);
DB_get_error();
if (rec_num > 0)
{
char msg[256];
sprintf(msg, "Errore in DB_add(): chiave duplicata nell' indice %ld, file %s",
rec_num + 1, d4fileName(data));
xvt_dm_post_fatal_exit(msg);
}
else
rt = _isreinsert;
}
else
{
if (rt == 0)
rt = DB_flush(handle);
}
}
return rt;
}
/*-------------------------------------------------------------------------
Blocca in modo esclusivo il file dati ed indice
--------------------------------------------------------------------------*/
int DB_lockfile(int handle)
{
int rt = -1;
HANDLE2DATA(handle, data);
rt = d4lockFile(data);
if (rt==0)
rt = d4lockIndex(data);
return rt;
}
HIDDEN void do_key(const char* fname, const RecDes* r, TAG4INFO* tag_info, int ntags)
{
const int nkeys = min(r->NKeys, ntags);
int i,j;
char tiname[_MAX_FNAME]; /* Tag name */
xvt_fsys_parse_pathname(fname, NULL, NULL, tiname, NULL, NULL);
xvt_str_make_upper(tiname);
for (i=0; i < nkeys; i++)
{
tag_info[i].name=(char *)u4alloc(_MAX_FNAME);
tag_info[i].expression=(char *)u4alloc(256);
tag_info[i].filter=(char*)u4alloc(32);
tag_info[i].descending=0;
if (r->Ky[i].DupKeys)
tag_info[i].unique=0;
else
tag_info[i].unique= i == 0 ? e4unique : r4unique_continue;
strcpy((char *)tag_info[i].filter,".NOT. DELETED()"); /* Not available for DBIII and CLIPPER */
strcpy((char *)tag_info[i].name,tiname) ;
strcat((char *)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((char *) tag_info[i].expression,"UPPER(");
}
if (r->Ky[i].FromCh[j] != 255) /* When partial field is specified */
strcat((char *)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((char *)tag_info[i].expression,"STR(");
break;
case _datefld:
strcat((char *)tag_info[i].expression,"DTOS(");
break;
case _boolfld:
strcat((char *)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((char *)tag_info[i].expression,r->Fd[nf].Name); /* Append field name */
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];
sprintf(ts,"%d",r->Fd[nf].Len);
strcat((char *)tag_info[i].expression,",");
strcat((char *)tag_info[i].expression,ts);
strcat((char *)tag_info[i].expression,",0)");
}
break;
case _boolfld:
strcat((char *)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((char *)tag_info[i].expression,")");
if (r->Ky[i].FromCh[j] != 255) /* If partial field was specified */
{ /* add parameters to SUBSTR */
char ts[8];
strcat((char *)tag_info[i].expression,",");
sprintf(ts,"%d",r->Ky[i].FromCh[j] + 1);
strcat((char *)tag_info[i].expression,ts);
strcat((char *)tag_info[i].expression,",");
sprintf(ts,"%d",r->Ky[i].ToCh[j] - r->Ky[i].FromCh[j] + 1);
strcat((char *)tag_info[i].expression,ts);
strcat((char *)tag_info[i].expression,")");
}
/* If there's another field in key adds "+" operator: */
if ((j < (r->Ky[i].NkFields-1)) && (strlen(r->Fd[nf].Name) > 0))
strcat((char *)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;
code_base.autoOpen = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open! */
if (handle >= 0)
{
WINDOW pi = NULL_WIN;
long rc = 0L;
if (vis)
{
char s[_MAX_PATH+32];
strcpy(s, "Compattamento ");
strcat(s, filename);
pi = xvt_dm_progress_create(NULL_WIN, s, 1, FALSE);
}
rc = d4recCount(dbdata[handle]);
if (eod < rc)
rt=d4zap(dbdata[handle],++eod,rc);
else
rt=d4pack(dbdata[handle]);
if (pi)
xvt_dm_progress_destroy(pi);
DB_close(handle);
}
else
rt=code_base.errorCode;
code_base.autoOpen = 1;
return rt;
}
/*-------------------------------------------------------------------------
Compatta il file dati
--------------------------------------------------------------------------*/
int DB_packmemo(short vis, const char * filename)
{
int rt=0,handle=0;
code_base.autoOpen = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open! */
if (handle > -1)
{
WINDOW pi = NULL_WIN;
if (vis)
{
char s[_MAX_PATH+32];
strcpy(s, "Compattamento memo : ");
strcat(s, filename);
pi = xvt_dm_progress_create(NULL_WIN, s, 1, FALSE);
}
rt=d4memoCompress(dbdata[handle]);
if (pi)
xvt_dm_progress_destroy(pi);
DB_close(handle);
}
else
rt=code_base.errorCode;
code_base.autoOpen = 1;
return rt;
}
/*-------------------------------------------------------------------------
Elimina i record duplicati
--------------------------------------------------------------------------*/
static int DB_clean_file(int handle, const char* filename,
const char* tagname, const RecDes* r, short vis)
{
TAG4INFO tags[2];
TAG4 * t;
char s[256], s0[256];
int l = 0, lt = 0, rt = 0;
long cnt = 0;
INDEX4 *w = NULL;
long items = DB_reccount(handle);
WINDOW pi = NULL_WIN;
if (items == 0)
return 0;
s[0] = '\0';
memset(tags, 0, sizeof(tags));
do_key(tagname, r, tags, 1);
strcat((char *) tags[0].expression, "+STR(RECNO(),9)");
w = i4create(dbdata[handle],(char*)filename,tags); // non "production" index ???
u4free((char *) tags[0].name);
u4free((char *) tags[0].expression);
u4free((char *) tags[0].filter);
if (w == NULL)
return code_base.errorCode;
t = d4tagDefault(dbdata[handle]);
lt = expr4len(t->tagFile->expr);
l = lt - 9;
if (vis)
pi = xvt_dm_progress_create(NULL_WIN,"Ricerca record duplicati",items,FALSE);
rt = tfile4bottom(t->tagFile);
while (code_base.errorCode == 0)
{
strncpy(s0, a4tagKey(dbdata[handle]), lt);
if (pi)
xvt_dm_progress_set_status(pi, ++cnt, items);
if (!strncmp(s, s0, l))
{
d4go(dbdata[handle],tfile4recNo(t->tagFile));
d4delete(dbdata[handle]);
tfile4seek(t->tagFile, s0, lt);
}
strncpy(s, s0, lt);
if (tfile4skip(t->tagFile, -1L) >= 0)
break;
} // while
rt = code_base.errorCode;
if (pi)
xvt_dm_progress_destroy(pi);
i4close(w);
return rt;
}
/*-------------------------------------------------------------------------
Compatta gli indici
--------------------------------------------------------------------------*/
static int DB_yesnobox(const char* msg)
{
return xvt_dm_post_ask("Si", "No", NULL, msg) == RESP_DEFAULT;
}
int DB_packindex(short vis, const char* filename, const RecDes *r, long *peod, bool ask)
{
int handle = 0, rt = 0;
code_base.autoOpen = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open */
if (handle >= 0)
{
TAG4INFO tags[MaxKeys+1];
INDEX4 * w = NULL;
WINDOW pi = NULL_WIN;
int i = 0;
const char *ff = find_slash_backslash(filename);
if (ff == NULL || *ff == '\0')
ff = (const char*)filename;
else
ff++;
memset(tags, 0, sizeof(tags));
do_key(ff, r, tags, r->NKeys);
if (vis)
{
char s[_MAX_PATH+32]; sprintf(s,"Creazione di %d indici su %s", (int)r->NKeys, ff);
pi = xvt_dm_progress_create(NULL_WIN, s, 1, FALSE); // No bar
}
w = i4create(dbdata[handle],NULL,tags); // NULL filename -> "production" index
if (w == NULL)
rt = code_base.errorCode;
if (pi)
{
xvt_dm_progress_destroy(pi);
pi = NULL_WIN;
}
if (rt == e4unique || rt == r4unique)
{
rt = 0;
if (!ask || DB_yesnobox("Sono stati rilevati alcuni records duplicati:\nsi desidera eliminarli?"))
{
if (vis)
{
char s[_MAX_PATH+32]; strcpy(s,"Rimozione duplicati "); strcat(s, ff);
pi = xvt_dm_progress_create(NULL_WIN, s, 1, FALSE); // No bar
}
rt = DB_clean_file(handle, filename, ff, r, vis);
if (pi)
{
xvt_dm_progress_destroy(pi);
pi = NULL_WIN;
}
}
else
tags[0].unique = r4unique_continue;
if (rt == 0)
{
if (vis)
{
char s[_MAX_PATH+32]; sprintf(s,"Creazione di %d indici su %s", (int)r->NKeys, ff);
pi = xvt_dm_progress_create(NULL_WIN, s, 1, FALSE); // No bar
}
// w = i4create(dbdata[handle],filename,tags);
w = i4create(dbdata[handle], NULL ,tags); // NULL filename -> "production" index 6/8/2014
if (w == NULL)
rt = code_base.errorCode;
if (pi)
{
xvt_dm_progress_destroy(pi);
pi = NULL_WIN;
}
}
}
for (i=0; i < r->NKeys && tags[i].name; i++)
{
u4free((char *) tags[i].name);
u4free((char *) tags[i].expression);
u4free((char *) tags[i].filter);
}
*peod=DB_reccount(handle);
DB_close(handle);
}
code_base.autoOpen = 1;
#ifdef DBG
{
char s[_MAX_PATH+20];
strcpy(s, filename);
strcat(s, ".cdx");
if (xvt_fsys_file_attr(s, XVT_FILE_ATTR_SIZE) == 0)
{
strcat(s, " e' stato compromesso!");
xvt_dm_post_error(s);
}
}
#endif
return(rt);
}
/*-------------------------------------------------------------------------
costruisce il file filename
--------------------------------------------------------------------------*/
int DB_build(const char* filename, const 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 = NULL;
int rt=0,i;
const char *ff = find_slash_backslash(filename);
memset(field_info, 0, sizeof(field_info));
memset(tag_info, 0, sizeof(tag_info));
for (i=0; ((i<r->NFields) && (i<MaxFields)); i++) /* Construct field_info */
{
field_info[i].name = (char*)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 _memofld:
field_info[i].type=r4memo;
field_info[i].len = 10;
field_info[i].dec = 0;
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 == '\0')
ff = filename;
else
ff++;
do_key(ff,r,tag_info, MaxKeys);
if ((dbuilded=d4create(&code_base, filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */
rt=code_base.errorCode;
else
rt=d4close(dbuilded);
if (rt!=0)
rt=code_base.errorCode;
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
{
u4free((char *) tag_info[i].name);
u4free((char *) tag_info[i].expression);
u4free((char *) tag_info[i].filter);
}
return(rt) ;
}
/*-------------------------------------------------------------------------
reperisce il tracciato record e la stringa di definizione delle chiavi
Stringa di definizione chiavi:
expression1|unique1$expression2|unique2$expression3|unique3
--------------------------------------------------------------------------*/
int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys)
{
/* filename must not have extension since it's used to search index name too*/
FIELD4INFO *field_info; /* Definizione del tracciato record */
TAG4INFO *tag_info; /* Definizione delle chiavi */
INDEX4 *index_file;
DATA4 *data_file;
int rt=0,num_fields,i;
data_file = d4open(&code_base, (char*)filename);
if (data_file != NULL)
{
field_info = d4fieldInfo(data_file);
index_file = d4index(data_file,"");
if (index_file == NULL)
{
char msg[256];
sprintf(msg, "Il file %s e' senza indici.",filename);
xvt_dm_post_fatal_exit(msg);
}
tag_info = i4tagInfo(index_file);
d->EOD = d->EOX = d4recCount(data_file);
d->LenR = (word)d4recWidth(data_file);
d->Flags = 0L;
strcpy(d->Des,"File esterno");
strcpy(d->FCalc,"");
strcpy(d->GenPrompt,"");
if (field_info != NULL && tag_info != NULL)
{
/* Compile field information */
num_fields = d4numFields(data_file);
r->NFields = num_fields;
for (i=0; ((i<num_fields) && (i<MaxFields)); i++)
{
strcpy(r->Fd[i].Name,field_info[i].name);
xvt_str_make_upper(r->Fd[i].Name);
r->Fd[i].Len = (unsigned char)field_info[i].len;
r->Fd[i].Dec = (unsigned char)field_info[i].dec;
switch(field_info[i].type)
{
case r4str : r->Fd[i].TypeF = r->Fd[i].Len > 1 ? _alfafld : _charfld; break;
case r4log : r->Fd[i].TypeF = _boolfld; break;
case r4date: r->Fd[i].TypeF = _datefld; break;
case r4memo: r->Fd[i].TypeF = _memofld; break;
case r4num :
if (r->Fd[i].Dec > 0)
r->Fd[i].TypeF = _realfld;
else
r->Fd[i].TypeF = r->Fd[i].Len < 6 ? _intfld : _longfld;
break;
default: r->Fd[i].TypeF = _alfafld; break; // Considero stringhe tutte le cose sconosciute
}
}
strcpy(keys,"");
/* Compile key definition */
for (i=0; i < MaxKeys; i++) /* Browse all tags */
{
if (tag_info[i].name == NULL)
break;
strcat(keys,tag_info[i].expression);
/* Tell me if you're unique my Boy... */
strcat(keys,"|");
strcat(keys,tag_info[i].unique == 0 ? "X" : " ");
strcat(keys,"$");
}
r->NKeys = i;
u4free(field_info);
u4free(tag_info);
}
else
rt = code_base.errorCode;
d4close(data_file);
}
else
rt = code_base.errorCode;
return (rt);
}
/*-------------------------------------------------------------------------
ritorna l'ultimo errore
--------------------------------------------------------------------------*/
int DB_get_error(void)
{
int rt = code_base.errorCode;
code_base.errorCode=0;
return (rt);
}
/*-------------------------------------------------------------------------
Azzera la viarabile globale d'errore
--------------------------------------------------------------------------*/
void DB_zero_error(void)
{
code_base.errorCode=0;
}
/*-------------------------------------------------------------------------
Si posiziona sull'indice attivo alla chiave indicata, restituisce
la prima chiave che trova >= a from. (TCusrsor)
--------------------------------------------------------------------------*/
int DB_index_seek(int handle, const char* from)
{
TAG4* t = NULL;
HANDLE2DATA(handle, data);
t = d4tagDefault(data);
if (t==NULL)
return -1;
if (tfile4seek(t->tagFile, 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;
HANDLE2DATA(handle, data);
t=d4tagDefault(data);
if (t==NULL)
return(-1);
return tfile4recNo(t->tagFile);
}
/*-------------------------------------------------------------------------
Si posiziona sulla chiave successiva dell'indice corrente
--------------------------------------------------------------------------*/
long DB_index_next(int handle)
{
TAG4 *t;
HANDLE2DATA(handle, data);
t = d4tagDefault(data);
if (t==NULL)
return -1;
return tfile4skip(t->tagFile,1L);
}
/*-------------------------------------------------------------------------
Restituisce la chiave corrente
--------------------------------------------------------------------------*/
char* DB_index_getkey(int handle)
{
static char key[MAXLEN];
TAG4 *t;
int klen;
const char* src;
HANDLE2DATASTR(handle, data);
if ((t=d4tagDefault(data))==NULL)
return(NULL);
klen=a4tagKeyLen(data);
if (klen > (MAXLEN-1)) klen=MAXLEN-1;
src = a4tagKey(data);
if (src != NULL)
{
memcpy(key,src,klen); /* tfile4key non restituisce una null terminated string */
key[klen]='\0';
}
else
key[0] = '\0';
return key;
}
/*-------------------------------------------------------------------------
Si posiziona sulla chiave ed il record indicati
--------------------------------------------------------------------------*/
int DB_index_go(int handle, const char* key, long recno)
{
TAG4* t = NULL;
HANDLE2DATA(handle, data);
t = d4tagDefault(data);
if (t==NULL)
return -1;
return tfile4go(t->tagFile, key, recno, FALSE);
}
/*-------------------------------------------------------------------------
Restituisce vero se l'indice e' alla fine
--------------------------------------------------------------------------*/
int DB_index_eof(int handle)
{
TAG4* t = NULL;
HANDLE2DATA(handle, data);
t = d4tagDefault(data);
if (t==NULL)
return -1;
return tfile4eof(t->tagFile);
}
/*-------------------------------------------------------------------------
Blocca il record indicato
--------------------------------------------------------------------------*/
int DB_lock_rec(int handle, long nrec)
{
HANDLE2DATA(handle, data);
return d4lock(data, nrec)==r4locked ? -1 : 0;
}
/*-------------------------------------------------------------------------
Ritorna vero(non zero) se il file dati od indice sono stati bloccati
in modo esclusivo dalla presente applicazione, non da altri programmi!!!
--------------------------------------------------------------------------*/
int DB_file_locked(int handle)
{
HANDLE2DATA(handle, data);
return a4lockTest(data);
}
/*-------------------------------------------------------------------------
Ritorna vero se il record nrec e' bloccato dalla presente applicazione,
non da altri programmi!!!
--------------------------------------------------------------------------*/
int DB_rec_locked(int handle, long nrec)
{
HANDLE2DATA(handle, data);
return d4lockTest(data,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)
{
HANDLE2DATA(handle, data);
return a4indexVersion(data);
}
char* DB_memoptr( const int handle, const char * fieldname )
{
FIELD4* f = NULL;
HANDLE2DATASTR(handle, data);
f = d4field(data, fieldname);
return f4memoPtr(f);
}
int DB_memowrite( const int handle, const char* fieldname, const char* memo )
{
FIELD4* f = NULL;
HANDLE2DATA(handle, data);
f = d4field(data, fieldname);
return f4memoAssign(f, memo);
}
long DB_version(char* str, int maxstr)
{
if (str != NULL && maxstr >= 16)
sprintf(str, "Codebase %d.%03d", S4VERSION/1000, S4VERSION%1000);
return S4VERSION;
}