guy 4f99172ae0 Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
archives.cpp  Aggiunto flag inutile ancora specificato dai vecchi programmi
*.c           Eliminato uso di CUpString
controls.cpp  Corretta resize_rect per tener conto della status bar
currency.cpp  Supporto cambio contro EURO
date.cpp      Migliorato operator=(long) in modo da accettare TODAY
dongle.cpp    Corretta gestione del prawin.ini
expr.cpp      Sostituiti alcuni "" con EMPTY_STRING
form.cpp      Supporto currency
isam.cpp      Aggiunte () per evitare warning di compilazione
os_win*.cpp   Migliorato supporto per minimizzazioe e massimizzazione
prefix.cpp    Aggiunta class TFirm coi dati della ditta
printapp.cpp  Supporto currency
printwin.cpp  Aggiunte () per evitare warning di compilazione
relapp.cpp    Migliorato delete_mode
text.cpp      Sostituiti CHECK inutili con NFCHECK
tree.cpp      Tolti ; errati da statement if
viswin.cpp    Supporto zoom
window.cpp    Aggiunta char2pixel per calcolare bene la dimensione dei caratteri
xvtility.cpp  Corretta resize rect per tener conto della status bar


git-svn-id: svn://10.65.10.50/trunk@7664 c028cbd2-c16b-5b4b-a496-9718f37d4682
1999-01-19 09:15:17 +00:00

2528 lines
69 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.
*/
#define XVT_INCL_NATIVE
#include <xvt.h>
#define S4OFF_REPORT
#ifdef CB6
#if XVT_OS == XVT_OS_WIN
#define S4DLL
#define S4WIN16
#endif
#if XVT_OS == XVT_OS_WIN32
#define S4DLL
#define S4WIN32
#endif
#ifdef FOXPRO
#define S4DLL
#define S4WIN16
#endif
//#pragma pack(1)
#include <d4all.h>
//#pragma pack()
#include <codeb.h>
#include <rectypes.h>
#include <progind.h>
#include <checks.h>
#define MAXLEN 137 /* Lunghezza massima chiave */
static CODE4 code_base;
static DATA4 *dbdata[CB4FILES];
bool handle_ok(int handle)
{
return handle >= 0 && handle < CB4FILES && dbdata[handle] !=0;
}
static char* find_slash_backslash(const char* s)
{
/*
const int l = strlen(str);
const char* xstr = str + l;
while (xstr-- && l--)
if (*xstr == '\\' || *xstr == '/' || l <= 0)
break;
if (l <= 0)
return NULL;
else
return xstr;
*/
const char* slash = NULL;
for ( ; *s; s++)
{
if (*s == '\\' || *s == '/')
slash = s;
}
return (char*)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)
{
int i;
for(i=0;i<CB4FILES;i++)
{
dbdata[i]=(DATA4 *) 0;
}
code4init(&code_base);
code_base.readLock=0;
code_base.errDefaultUnique=e4unique;
code_base.safety=0;
code_base.lockAttempts=1;
// code_base.optimize_write = 0;
code4dateFormatSet(&code_base, "CCYYMMDD");
}
/*--------------------------------------------------------------------------
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)
{
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;
if (mode) code_base.accessMode=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.errorCode=0;
if (index == 0) /* Se e' stata richiesta l'apertura senza indici, setta il flag */
code_base.autoOpen = 0;
dbdata[found]=d4open(&code_base,(char*)filename);
if (index == 0) /* Restore the configuration of opening indexes*/
code_base.autoOpen = 1;
if(dbdata[found]==0)
return code_base.errorCode;
code_base.accessMode=0;
d4tagSelect(dbdata[found],d4tagDefault(dbdata[found]));
if (d4recCount(dbdata[found]) > 0)
d4top(dbdata[found]);
return(found);
}
/*-------------------------------------------------------------------------
chiusura del database inviduato da handle
torna -1 se il database non puo essere chiuso
--------------------------------------------------------------------------*/
int DB_close(int handle)
{
if(!handle_ok(handle)) return(-1);
d4close(dbdata[handle]);
dbdata[handle]=(DATA4 *) 0;
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)
{
if(!handle_ok(handle)) return((char *) 0);
return(d4record(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza del record
--------------------------------------------------------------------------*/
int DB_reclen(int handle)
{
if(!handle_ok(handle)) return(-1);
return((int) d4recWidth(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza della chiave corrente
--------------------------------------------------------------------------*/
int DB_keylen(int handle)
{
return a4tagKeyLen(dbdata[handle]);
}
/*-------------------------------------------------------------------------
torna il numero del record attuale
--------------------------------------------------------------------------*/
long int DB_recno(int handle)
{
if(!handle_ok(handle)) return(-1L);
return(d4recNo(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna il numero complessivo dei records presenti nell'archivio
--------------------------------------------------------------------------*/
long int DB_reccount(int handle)
{
if(!handle_ok(handle)) 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(!handle_ok(handle)) return(-1);
/* si posiziona sul primo indice */
tt=d4tagNext(dbdata[handle],NULL);
if(tt==NULL) return(-1);
for(i=1;i<index_no;i++) {
tt=d4tagNext(dbdata[handle],tt);
if(tt==NULL) return(-1);
}
d4tagSelect(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(!handle_ok(handle)) return(-1);
/* si posiziona sul primo indice */
tt=d4tagDefault(dbdata[handle]);
if(tt==NULL) return(-1);
tt1=d4tagNext(dbdata[handle],NULL);
i=1;
while(tt!=tt1 && tt1!=NULL) {
tt1=d4tagNext(dbdata[handle],tt1);
i++;
}
return(i);
}
/*-------------------------------------------------------------------------
si posiziona sul primo record
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_first(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4top(dbdata[handle]));
}
/*-------------------------------------------------------------------------
si posiziona sull'ultimorecord
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_last(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4bottom(dbdata[handle]));
}
/*-------------------------------------------------------------------------
skip avanti di un record
--------------------------------------------------------------------------*/
int DB_next(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],1L));
}
/*-------------------------------------------------------------------------
skip indietro di un record
--------------------------------------------------------------------------*/
int DB_prev(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],-1L));
}
/*-------------------------------------------------------------------------
skip di n records
--------------------------------------------------------------------------*/
int DB_skip(int handle,long int recno)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],recno));
}
/*-------------------------------------------------------------------------
locka il record attuale
--------------------------------------------------------------------------*/
int DB_lock(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4lock(dbdata[handle],d4recNo(dbdata[handle])));
}
/*-------------------------------------------------------------------------
slocka il record attuale
--------------------------------------------------------------------------*/
int DB_unlock(int handle)
{
if(!handle_ok(handle)) 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;
const char * k;
if(!handle_ok(handle)) return(-1);
rc = d4seek(dbdata[handle],key);
if (rc)
return rc;
len = a4tagKeyLen(dbdata[handle]);
k = a4tagKey(dbdata[handle]);
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(!handle_ok(handle)) return(-1);
return(d4eof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna 1 se tof, 0 altrimenti
--------------------------------------------------------------------------*/
int DB_bof(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4bof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
legge un record per numero record
--------------------------------------------------------------------------*/
int DB_go(int handle,long recno)
{
if(!handle_ok(handle)) return(-1);
return(d4go(dbdata[handle],recno));
}
/*-------------------------------------------------------------------------
cancella il record attuale. Non cancella le chiavi.
--------------------------------------------------------------------------*/
int DB_delete(int handle)
{
if(!handle_ok(handle)) return(-1);
d4delete(dbdata[handle]);
return(0);
}
/*-------------------------------------------------------------------------
ripristina il record attuale
--------------------------------------------------------------------------*/
int DB_recall(int handle)
{
if(!handle_ok(handle)) return(-1);
d4recall(dbdata[handle]);
return(0);
}
/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
int DB_flush(int handle)
{
int rt;
while ((rt = d4flush(dbdata[handle])) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_flush");
#else
u4delay_sec();
#endif
return rt;
}
/*-------------------------------------------------------------------------
riscrive il record attuale
--------------------------------------------------------------------------*/
int DB_rewrite(int handle)
{
int rt;
if(!handle_ok(handle)) return(-1);
while ((rt=d4write(dbdata[handle],d4recNo(dbdata[handle]))) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_rewrite");
#else
u4delaySec();
#endif
if (rt == 0)
{
while ((rt = d4flush(dbdata[handle])) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_rewrite (d4flush)");
#else
u4delaySec();
#endif
}
if (rt == e4unique)
{
DB_get_error();
fatal_box("Errore in DB_rewrite(): chiave duplicata nel record %ld, file %s",
d4recNo(dbdata[handle]) + 1, d4fileName(dbdata[handle]));
}
rt=DB_unlock(handle);
return (rt);
}
/*-------------------------------------------------------------------------
appende il record attuale
--------------------------------------------------------------------------*/
int DB_add(int handle)
{
int rt;
int is_locked = 0;
DATA4 * data = dbdata[handle];
if (data==0) return(-1);
is_locked = DB_file_locked(handle);
if (is_locked == 0) /* Se non e' stato gia' bloccato in modo esclusivo */
{
while (d4lockAll(data) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add");
#else
u4delaySec();
#endif
}
while ((rt = d4appendStart(data,0)) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add (d4append_start)");
#else
u4delaySec();
#endif
if (rt == 0)
{
d4recall(data);
while ((rt = d4append(data)) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add (d4append)");
#else
u4delaySec();
#endif
if (rt == e4unique)
{
long rec_num = d4recNo(data);
DB_get_error();
if (rec_num > 0)
fatal_box("Errore in DB_add(): chiave duplicata nell' indice %ld, file %s",
rec_num + 1, d4fileName(data));
else
rt = _isreinsert;
}
else
if (rt == 0)
{
while ((rt = d4flush(data)) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add (d4flush)");
#else
u4delaySec();
#endif
}
}
DB_unlock(handle);
if (is_locked == 0)
d4unlock(data);
return(rt);
}
/*-------------------------------------------------------------------------
Blocca in modo esclusivo il file dati ed indice
--------------------------------------------------------------------------*/
int DB_lockfile(int handle)
{
int rt;
if(!handle_ok(handle)) return(-1);
rt = d4lockFile(dbdata[handle]);
if (rt==0) rt=d4lockIndex(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 n_keys)
{
int i,j;
char tiname[9]; /* Tag name, max 8 characters long! */
char* dot;
strcpy(tiname,fname);
dot = strchr(tiname, '.');
if (dot) *dot = '\0';
_strupr(tiname);
for (i=0; ((i < MaxKeys) && (i < n_keys)); i++)
{
tag_info[i].name=(char *)u4alloc(9);
tag_info[i].expression=(char *)u4alloc(256);
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= i == 0 ? e4unique : r4unique_continue;
/* tag_info[i].unique=e4unique; */
strcpy((char *)tag_info[i].filter,".NOT. DELETED()"); /* Not available for DBIII and CLIPPER */
strcpy((char *)tag_info[i].name,tiname) ;
if (strlen(tiname) < 8)
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];
strcat((char *)tag_info[i].expression,",");
sprintf(ts,"%d",r->Fd[nf].Len);
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 > -1)
{
char s[81];
if (vis)
{
strcpy(s,"Compattamento dati file : ");
strcat(s,(char*)filename);
#ifndef FOXPRO
progind_create(100L,s,0,0,60);
#endif
}
if (eod < d4recCount(dbdata[handle]))
{
rt=d4zap(dbdata[handle],++eod,d4recCount(dbdata[handle]));
} else
rt=d4pack(dbdata[handle]);
if (vis)
{
#ifndef FOXPRO
progind_destroy();
#endif
}
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;
code_base.autoOpen = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open! */
if (handle > -1)
{
char s[81];
if (vis)
{
strcpy(s,"Compattamento memo file : ");
strcat(s,(char*)filename);
#ifndef FOXPRO
progind_create(100L,s,0,0,60);
#endif
}
rt=d4memoCompress(dbdata[handle]);
if (vis)
{
#ifndef FOXPRO
progind_destroy();
#endif
}
DB_close(handle);
}
else
rt=code_base.errorCode;
code_base.autoOpen = 1;
return rt;
}
/*-------------------------------------------------------------------------
Elimina i record duplicati
--------------------------------------------------------------------------*/
int DB_clean_file(int handle, char * filename, char * ff, 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);
if (items == 0)
return 0;
s[0] = '\0';
do_key(ff, r, tags, 1);
strcat((char *) tags[0].expression, "+STR(RECNO(),9)");
w = i4create(dbdata[handle],(char*)filename,tags);
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;
#ifndef FOXPRO
if (vis)
progind_create(items,"Ricerca record duplicati",0,1,60);
#endif
rt = tfile4bottom(t->tagFile);
while (code_base.errorCode == 0)
{
strncpy(s0, a4tagKey(dbdata[handle]), lt);
#ifndef FOXPRO
if (vis)
progind_set_status(++cnt);
#endif
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;
#ifndef FOXPRO
if (vis)
progind_destroy();
#endif
i4close(w);
return rt;
}
/*-------------------------------------------------------------------------
Compatta gli indici
--------------------------------------------------------------------------*/
int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask)
{
int rt=0,handle;
TAG4INFO tags[MaxKeys+1];
char s[82];
INDEX4 * w = NULL;
strcpy(s,"Ricostruzione indici file : ");
strcat(s,filename);
code_base.autoOpen=0 ;
handle=DB_open(filename,1,0); /* Exclusive mode open */
if (handle > -1)
{
int i;
char *ff = find_slash_backslash((char *)filename);
#ifndef FOXPRO
if (vis)
progind_create((long)r->NKeys,s,0,1,60);
#endif
if ((ff == NULL) || *ff == '\0')
ff = (char *)filename;
else
ff++;
do_key(ff,r,tags, r->NKeys);
w = i4create(dbdata[handle],NULL,tags);
#ifndef FOXPRO
if (vis)
{
progind_set_status((long)r->NKeys);
progind_destroy();
}
#endif
if (w == NULL) rt = code_base.errorCode;
if (rt == e4unique || rt == r4unique)
{
rt = 0;
if (!ask || yesno_box("Sono stati rilevati alcuni records duplicati nel file %s. Devo eliminarli ?",filename))
rt = DB_clean_file(handle, (char*) filename, ff, r, vis);
else
tags[0].unique = r4unique_continue;
if (rt == 0)
{
#ifndef FOXPRO
if (vis)
progind_create((long)r->NKeys,s,0,1,60);
#endif
w = i4create(dbdata[handle],(char*)filename,tags);
if (w == NULL) rt = code_base.errorCode;
#ifndef FOXPRO
if (vis)
{
progind_set_status((long)r->NKeys);
progind_destroy();
}
#endif
}
}
if (rt == 0)
{
if (u4switch() & 2 || u4switch() & 8) /* Clipper and DBIII */
{
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);
}
}
}
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); 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;
return(rt);
}
/*-------------------------------------------------------------------------
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 _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 = (char *) filename;
else
ff++;
do_key(ff,r,tag_info, r->NKeys);
if ((dbuilded=d4create(&code_base, (char *)filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */
rt=code_base.errorCode;
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.errorCode;
for (i=0; ((i < MaxFields) && (i < r->NFields)); i++)
u4free(field_info[i].name);
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,"" /*(char*)filename */);
if (index_file == NULL)
fatal_box("Il file %s e' senza indici.",filename);
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);
_strupr(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:
if (r->Fd[i].Len > 1)
r->Fd[i].TypeF = _alfafld;
else
r->Fd[i].TypeF = _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:
break;
}
}
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, char* from)
{
TAG4 *t;
if(!handle_ok(handle)) return(-1);
if ((t=d4tagDefault(dbdata[handle]))==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;
if(!handle_ok(handle)) return(-1);
if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1);
return(tfile4recNo(t->tagFile));
}
/*-------------------------------------------------------------------------
Si posiziona sulla chiave successiva dell'indice corrente
--------------------------------------------------------------------------*/
long DB_index_next(int handle)
{
TAG4 *t;
if(!handle_ok(handle)) return(-1);
if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1);
return(tfile4skip(t->tagFile,1L));
}
/*-------------------------------------------------------------------------
Restituisce la chiave corrente
--------------------------------------------------------------------------*/
char* DB_index_getkey(int handle)
{
static char* key = NULL;
TAG4 *t;
int klen;
if (key == NULL)
key = malloc(MAXLEN);
if(!handle_ok(handle))
return(NULL);
if ((t=d4tagDefault(dbdata[handle]))==NULL) return(NULL);
klen=a4tagKeyLen(dbdata[handle]);
if (klen > (MAXLEN-1)) klen=MAXLEN-1;
memcpy(key,a4tagKey(dbdata[handle]),klen); /* tfile4key 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(!handle_ok(handle)) return(-1);
if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1);
return(tfile4eof(t->tagFile));
}
/*-------------------------------------------------------------------------
Blocca il record indicato
--------------------------------------------------------------------------*/
int DB_lock_rec(int handle,long nrec)
{
if(!handle_ok(handle)) return(-1);
if(d4lock(dbdata[handle],nrec)==r4locked) return(-1);
else return(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)
{
if(!handle_ok(handle)) return(-1);
return a4lockTest(dbdata[handle]);
}
/*-------------------------------------------------------------------------
Ritorna vero se il record nrec e' bloccato dalla presente applicazione,
non da altri programmi!!!
--------------------------------------------------------------------------*/
int DB_rec_locked(int handle,long nrec)
{
if(!handle_ok(handle)) return(-1);
return(d4lockTest(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)
{
return(a4indexVersion(dbdata[handle]));
}
char* DB_memoptr( const int handle, const char * fieldname )
{
FIELD4 * f;
f = d4field( dbdata[ handle ], ( char *)fieldname );
return f4memoPtr( f );
}
int DB_memowrite( const int handle, const char * fieldname, const char * data )
{
int ret;
FIELD4 * f;
f = d4field(dbdata[handle], fieldname );
ret = f4memoAssign( f, ( char * )data );
d4flush(dbdata[handle]);
return ret;
}
#else // CB6
#if XVT_OS == XVT_OS_WIN
#define S4DLL
#define S4WIN16
#else
#if XVT_OS == XVT_OS_WIN32
#define S4DLL
#define S4WIN32
#else
#define S4UNIX
#endif
#endif
#ifdef FOXPRO
#undef S4UNIX
#define S4DLL
#endif
#include <d4all.h>
#include <codeb.h>
#include <rectypes.h>
#include <progind.h>
#include <checks.h>
#define MAXLEN 137 /* Lunghezza massima chiave */
static CODE4 code_base;
static DATA4 *dbdata[CB4FILES];
bool handle_ok(int handle)
{
return handle >=0 && handle < CB4FILES && dbdata[handle] !=0;
}
static char * find_slash_backslash(char * str)
{
static char* xstr = NULL;
int l=strlen(str);
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. Il parametro index consente se == 0 l'apertura senza indici
--------------------------------------------------------------------------*/
int DB_open(const char *filename,int mode, int index)
{
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;
if (index == 0) /* Se e' stata richiesta l'apertura senza indici, setta il flag */
code_base.auto_open = 0;
dbdata[found]=d4open(&code_base,(char*)filename);
if (index == 0) /* Restore the configuration of opening indexes*/
code_base.auto_open = 1;
if(dbdata[found]==0) return(-1);
// d4init(&codebase);
code_base.exclusive=0;
d4tag_select(dbdata[found],d4tag_default(dbdata[found]));
if (d4reccount(dbdata[found]) > 0)
d4top(dbdata[found]);
return(found);
}
/*-------------------------------------------------------------------------
chiusura del database inviduato da handle
torna -1 se il database non puo essere chiuso
--------------------------------------------------------------------------*/
int DB_close(int handle)
{
if(!handle_ok(handle)) 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(!handle_ok(handle)) return((char *) 0);
return(d4record(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza del record
--------------------------------------------------------------------------*/
int DB_reclen(int handle)
{
if(!handle_ok(handle)) return(-1);
return((int) d4record_width(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna la lunghezza della chiave corrente
--------------------------------------------------------------------------*/
int DB_keylen(int handle)
{
TAG4 *t;
if (!handle_ok(handle)) 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(!handle_ok(handle)) return(-1L);
return(d4recno(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna il numero complessivo dei records presenti nell'archivio
--------------------------------------------------------------------------*/
long int DB_reccount(int handle)
{
if(!handle_ok(handle)) 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(!handle_ok(handle)) 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(!handle_ok(handle)) 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(!handle_ok(handle)) return(-1);
return(d4top(dbdata[handle]));
}
/*-------------------------------------------------------------------------
si posiziona sull'ultimorecord
torna -1 se errore
--------------------------------------------------------------------------*/
int DB_last(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4bottom(dbdata[handle]));
}
/*-------------------------------------------------------------------------
skip avanti di un record
--------------------------------------------------------------------------*/
int DB_next(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],1L));
}
/*-------------------------------------------------------------------------
skip indietro di un record
--------------------------------------------------------------------------*/
int DB_prev(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],-1L));
}
/*-------------------------------------------------------------------------
skip di n records
--------------------------------------------------------------------------*/
int DB_skip(int handle,long int recno)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],recno));
}
/*-------------------------------------------------------------------------
locka il record attuale
--------------------------------------------------------------------------*/
int DB_lock(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4lock(dbdata[handle],d4recno(dbdata[handle])));
}
/*-------------------------------------------------------------------------
slocka il record attuale
--------------------------------------------------------------------------*/
int DB_unlock(int handle)
{
if(!handle_ok(handle)) 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(!handle_ok(handle)) return(-1);
rc = d4seek(dbdata[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(!handle_ok(handle)) return(-1);
return(d4eof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
torna 1 se tof, 0 altrimenti
--------------------------------------------------------------------------*/
int DB_bof(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4bof(dbdata[handle]));
}
/*-------------------------------------------------------------------------
legge un record per numero record
--------------------------------------------------------------------------*/
int DB_go(int handle,long recno)
{
if(!handle_ok(handle)) return(-1);
// return(d4go(&xdb[handle],recno));
return(d4go(dbdata[handle],recno));
}
/*-------------------------------------------------------------------------
cancella il record attuale. Non cancella le chiavi.
--------------------------------------------------------------------------*/
int DB_delete(int handle)
{
if(!handle_ok(handle)) return(-1);
d4delete(dbdata[handle]);
return(0);
}
/*-------------------------------------------------------------------------
ripristina il record attuale
--------------------------------------------------------------------------*/
int DB_recall(int handle)
{
if(!handle_ok(handle)) 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;
int is_locked = 0; /* Diverso da 0 se il file e' bloccato in modo esclusivo */
/* (dati o indice) da me stesso*/
char fn[64];
if(!handle_ok(handle)) 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);
is_locked = DB_file_locked(handle);
if (is_locked == 0) /* Se non e' stato bloccato in modo esclusivo */
{
while ((rt=i4lock(i)) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_delkey");
#else
u4delay_sec();
#endif
}
if (rt == 0)
rt=t4remove_calc(t,recno);
if (is_locked == 0) /* Siccome ho fatto il lock dell'indice, devo anche sbloccarlo */
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
yesnofatal_box("Sono in attesa nella DB_flush");
#else
u4delay_sec();
#endif
return rt;
}
/*-------------------------------------------------------------------------
riscrive il record attuale
--------------------------------------------------------------------------*/
int DB_rewrite(int handle)
{
int rt;
if(!handle_ok(handle)) return(-1);
while ((rt=d4write(dbdata[handle],d4recno(dbdata[handle]))) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_rewrite");
#else
u4delay_sec();
#endif
if (rt == 0)
{
while ((rt = d4flush(dbdata[handle])) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_rewrite (d4flush)");
#else
u4delay_sec();
#endif
}
if (rt == e4unique)
{
DB_get_error();
fatal_box("Errore in DB_rewrite(): chiave duplicata nel record %ld, file %s",
dbdata[handle]->rec_num + 1, dbdata[handle]->file.name);
}
rt=DB_unlock(handle);
return (rt);
}
/*-------------------------------------------------------------------------
appende il record attuale
--------------------------------------------------------------------------*/
int DB_add(int handle)
{
int rt;
int is_locked = 0;
DATA4 * data = dbdata[handle];
if (data==0) return(-1);
is_locked = DB_file_locked(handle);
if (is_locked == 0) /* Se non e' stato gia' bloccato in modo esclusivo */
{
while (file4lock(&data->file, L4LOCK_POS_OLD, 1L) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add");
#else
u4delay_sec();
#endif
}
while ((rt = d4append_start(data,0)) == r4locked)
#ifdef DBG
yesnofatal_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
yesnofatal_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 in DB_add(): chiave duplicata nell' indice %ld, file %s",
data->rec_num + 1, data->file.name);
else
rt = _isreinsert;
}
else
if (rt == 0)
{
while ((rt = d4flush(data)) == r4locked)
#ifdef DBG
yesnofatal_box("Sono in attesa nella DB_add (d4flush)");
#else
u4delay_sec();
#endif
}
}
DB_unlock(handle);
if (is_locked == 0)
{
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(!handle_ok(handle)) 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 n_keys)
{
int i,j;
char tiname[9]; /* Tag name, max 8 characters long! */
char* dot;
strcpy(tiname,fname);
dot = strchr(tiname, '.');
if (dot) *dot = '\0';
_strupr(tiname);
for (i=0; ((i < MaxKeys) && (i < n_keys)); i++)
{
tag_info[i].name=(char *)u4alloc(9);
tag_info[i].expression=(char *)u4alloc(256);
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= i == 0 ? e4unique : r4unique_continue;
/* tag_info[i].unique=e4unique; */
strcpy(tag_info[i].filter,".NOT.DELETED()"); /* 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 partial field was specified */
/* add parameters to SUBSTR */
/*
if (r->Ky[i].FromCh[j] != 255)
{
char ts[8];
strcat(tag_info[i].expression,",");
sprintf(ts,"%d",r->Ky[i].FromCh[j] + 1);
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 (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] + 1);
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,")");
}
/* If there's another field in key adds "+" operator: */
if ((j < (r->Ky[i].NkFields-1)) && (strlen(r->Fd[nf].Name) > 0))
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(!handle_ok(handle)) return(-1);
codebase.auto_open = 0 cosi' non apre gli indici
*/
code_base.auto_open = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open! */
if (handle > -1)
{
char s[81];
if (vis)
{
strcpy(s, "Compattamento dati file : ");
strcat(s, filename);
#ifndef FOXPRO
progind_create(100L,s,0,0,60);
#endif
}
if (eod < d4reccount(dbdata[handle]))
{
rt=d4zap(dbdata[handle],++eod,d4reccount(dbdata[handle]));
} else
rt=d4pack(dbdata[handle]);
if (vis)
{
#ifndef FOXPRO
progind_destroy();
#endif
}
DB_close(handle);
}
else
rt=code_base.error_code;
code_base.auto_open = 1;
return rt;
}
/*-------------------------------------------------------------------------
Compatta il file dati
--------------------------------------------------------------------------*/
int DB_packmemo(short vis, const char * filename)
{
int rt=0,handle;
code_base.auto_open = 0;
handle=DB_open(filename,1,0); /* Exclusive mode open! */
if (handle > -1)
{
char s[81];
if (vis)
{
strcpy(s,"Compattamento memo file : ");
strcat(s,(char*)filename);
#ifndef FOXPRO
progind_create(100L,s,0,0,60);
#endif
}
rt=d4memo_compress(dbdata[handle]);
if (vis)
{
#ifndef FOXPRO
progind_destroy();
#endif
}
DB_close(handle);
}
else
rt=code_base.error_code;
code_base.auto_open = 1;
return rt;
}
/*-------------------------------------------------------------------------
Elimina i record duplicati
--------------------------------------------------------------------------*/
int DB_clean_file(int handle, char * filename, char * ff, 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);
if (items == 0)
return 0;
s[0] = '\0';
do_key(ff, r, tags, 1);
strcat(tags[0].expression, "+STR(RECNO(),9)");
w = i4create(dbdata[handle],(char*)filename,tags);
u4free(tags[0].name);
u4free(tags[0].expression);
u4free(tags[0].filter);
if (w == NULL) return code_base.error_code;
t = d4tag_default(dbdata[handle]);
lt = expr4key_len(t->expr);
l = lt - 9;
#ifndef FOXPRO
if (vis)
progind_create(items,"Ricerca record duplicati",0,1,60);
#endif
rt = t4bottom(t);
while (code_base.error_code == 0)
{
strncpy(s0, t4key(t), lt);
#ifndef FOXPRO
if (vis)
progind_set_status(++cnt);
#endif
if (!strncmp(s, s0, l))
{
d4go(dbdata[handle],t4recno(t));
d4delete(dbdata[handle]);
t4seek(t, s0, lt);
}
strncpy(s, s0, lt);
if (t4skip(t, -1L) >= 0)
break;
} // while
rt = code_base.error_code;
#ifndef FOXPRO
if (vis)
progind_destroy();
#endif
i4close(w);
return rt;
}
/*-------------------------------------------------------------------------
Compatta gli indici
--------------------------------------------------------------------------*/
int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask)
{
int rt=0,handle;
TAG4INFO tags[MaxKeys+1];
char s[82];
INDEX4 * w = NULL;
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,0); /* Exclusive mode open */
if (handle > -1)
{
int i;
char *ff = find_slash_backslash((char *)filename);
#ifndef FOXPRO
if (vis)
progind_create((long)r->NKeys,s,0,1,60);
#endif
if ((ff == NULL) || *ff == '\0')
ff = (char *)filename;
else
ff++;
do_key(ff,r,tags, r->NKeys);
w = i4create(dbdata[handle],NULL,tags);
#ifndef FOXPRO
if (vis)
{
progind_set_status((long)r->NKeys);
progind_destroy();
}
#endif
if (w == NULL) rt = code_base.error_code;
if (rt == e4unique || rt == r4unique)
{
rt = 0;
if (!ask || yesno_box("Sono stati rilevati alcuni records duplicati nel file %s. Devo eliminarli ?",filename))
rt = DB_clean_file(handle, (char*) filename, ff, r, vis);
else
tags[0].unique = r4unique_continue;
if (rt == 0)
{
#ifndef FOXPRO
if (vis)
progind_create((long)r->NKeys,s,0,1,60);
#endif
w = i4create(dbdata[handle],(char*)filename,tags);
if (w == NULL) rt = code_base.error_code;
#ifndef FOXPRO
if (vis)
{
progind_set_status((long)r->NKeys);
progind_destroy();
}
#endif
}
}
if (rt == 0)
{
if (u4switch() & 2 || u4switch() & 8) /* Clipper and DBIII */
{
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);
}
}
/*
else
if (u4switch() & 1 || u4switch() & 4) // FOXPRO and DBIV
{
}
*/
}
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
{
u4free(tags[i].name);
u4free(tags[i].expression);
u4free(tags[i].filter);
}
*peod=DB_reccount(handle);
DB_close(handle);
}
code_base.auto_open = 1;
return(rt);
}
/*-------------------------------------------------------------------------
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 _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 = (char *) filename;
else
ff++;
do_key(ff,r,tag_info, r->NKeys);
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) ;
}
/*-------------------------------------------------------------------------
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 = d4field_info(data_file);
index_file = d4index(data_file,(char*)filename);
if (index_file == NULL)
fatal_box("Il file %s e' senza indici.",filename);
tag_info = i4tag_info(index_file);
d->EOD = d->EOX = d4reccount(data_file);
d->LenR = (word)d4record_width(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 = d4num_fields(data_file);
r->NFields = num_fields;
for (i=0; ((i<num_fields) && (i<MaxFields)); i++)
{
strcpy(r->Fd[i].Name,field_info[i].name);
_strupr(r->Fd[i].Name);
r->Fd[i].Len = field_info[i].len;
r->Fd[i].Dec = field_info[i].dec;
switch(field_info[i].type)
{
case r4str:
if (r->Fd[i].Len > 1)
r->Fd[i].TypeF = _alfafld;
else
r->Fd[i].TypeF = _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:
break;
}
}
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.error_code;
d4close(data_file);
}
else
rt = code_base.error_code;
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(!handle_ok(handle)) 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(!handle_ok(handle)) 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(!handle_ok(handle)) 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)
{
static char* key = NULL;
TAG4 *t;
int klen;
if (key == NULL)
key = malloc(MAXLEN);
if(!handle_ok(handle))
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(!handle_ok(handle)) 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(!handle_ok(handle)) return(-1);
if(d4lock(dbdata[handle],nrec)==r4locked) return(-1);
else return(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)
{
if(!handle_ok(handle)) return(-1);
return(d4lock_test_file(dbdata[handle]) + d4lock_test_index(dbdata[handle]));
}
/*-------------------------------------------------------------------------
Ritorna vero se il record nrec e' bloccato dalla presente applicazione,
non da altri programmi!!!
--------------------------------------------------------------------------*/
int DB_rec_locked(int handle,long nrec)
{
if(!handle_ok(handle)) 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(!handle_ok(handle)) 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));
}
char* DB_memoptr( const int handle, const char * fieldname )
{
FIELD4 * f;
f = d4field( dbdata[ handle ], ( char *)fieldname );
return f4memo_ptr( f );
}
int DB_memowrite( const int handle, const char * fieldname, const char * data )
{
int ret;
FIELD4 * f;
f = d4field( dbdata[ handle ], (char *)fieldname );
ret = f4memo_assign( f, ( char * )data );
d4flush_data( dbdata[ handle ] );
return ret;
}
#endif // CB6