Aggiunto Codebase 5.1, per supporto files.

- sheet.cpp : modificata gesione doppio click del mouse.


git-svn-id: svn://10.65.10.50/trunk@1533 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
angelo 1995-07-03 07:49:30 +00:00
parent 9775ccaaac
commit 76a217510a
14 changed files with 1937 additions and 454 deletions

914
include/codeb.c Executable file
View File

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

74
include/codeb.h Executable file
View File

@ -0,0 +1,74 @@
/*--------------------------------------------------------------------------
CODEBASE.H
data : 23.01.95
scopo: interfaccia verso CodeBase 5.0
--------------------------------------------------------------------------*/
#ifndef __CODEBASE_H
#define __CODEBASE_H
#ifndef __EXTCTYPE_H
#include <extctype.h>
#endif
/*--------------------------------------------------------------------------
numero massimo di database aperti contemporaneamente
--------------------------------------------------------------------------*/
#define CB4FILES 50
/*--------------------------------------------------------------------------
prototipi funzioni
--------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
void DB_init(void);
void DB_exit(void);
int DB_open(const char *filename,int mode);
int DB_close(int handle);
char *DB_getrecord(int handle);
int DB_reclen(int handle);
int DB_keylen(int handle);
long int DB_recno(int handle);
long int DB_reccount(int handle);
int DB_tagselect(int handle,int index_no);
int DB_tagget(int handle);
int DB_first(int handle);
int DB_last(int handle);
int DB_next(int handle);
int DB_prev(int handle);
int DB_skip(int handle,long int recno);
int DB_lock(int handle);
int DB_lockrec(int handle, long recno); // Per sbloccare il record basta la DB_unlock()
int DB_unlock(int handle);
int DB_seek(int handle,char *key);
int DB_eof(int handle);
int DB_bof(int handle);
int DB_go(int handle,long int recno);
int DB_delete(int handle);
int DB_recall(int handle);
int DB_delkey(int handle, char* key, long recno);
int DB_rewrite(int handle);
int DB_add(int handle);
int DB_lockfile(int handle); // Per sbloccare il file basta la DB_unlock()
int DB_packfile(short vis, const char * filename, long eod);
int DB_packindex(short vis, const char * filename, RecDes *r, long *peod );
int DB_build(const char * filename, RecDes *r);
int DB_get_error(void);
void DB_zero_error(void);
int DB_index_seek(int handle, char* from);
long DB_index_recno(int handle);
long DB_index_next(int handle);
char* DB_index_getkey(int handle);
int DB_index_eof(int handle);
int DB_lock_rec(int handle,long nrec);
int DB_file_locked(int handle);
int DB_rec_locked(int handle,long nrec);
long DB_getconf();
long DB_changed(int handle); // returns true if the index of the key is changed
#ifdef __cplusplus
};
#endif
#endif

View File

@ -199,13 +199,13 @@ typedef struct
typedef struct
{
SecDef f;
FilCtrl i;
int fhnd;
FileDes *d;
RecDes *r;
RecNoType RecNo;
RecNoType RecNo;
INT16 ln;
INT16 ft;
INT16 ft;
int knum;
} isdef ;

View File

@ -136,7 +136,7 @@ const char *TDir::name () const
}
const char *TDir::des () const
{
{
return _dir->Des;
}
@ -146,9 +146,11 @@ const char* TDir::tab_des(const char* tab)
TString256 tmp;
tmp << DESCDIR << "/d" << t << ".des";
#ifndef FOXPRO
TConfig cnf(tmp, DESCTAB);
t = cnf.get("Description", NULL, -1, tab);
#endif
return strcpy(__tmp_string, t);
}

File diff suppressed because it is too large Load Diff

View File

@ -80,9 +80,9 @@ public:
void settab(const char *tab);
char* string() const { return _rec;} // Ritorna il puntatore all'inizio. NON dovrebbe essere usata!
void discard() { *_rec = char(_deleted);} // Setta il flag di cancellazione
void recall() { *_rec = char(_valid);} // Ripristina il flag di cancellazione
bool isdeleted() const { return *_rec == _deleted;} // Chiede se e' cancellato
void discard() { *_rec = '*';} // Setta il flag di cancellazione
void recall() { *_rec = ' ';} // Ripristina il flag di cancellazione
bool isdeleted() const { return *_rec == '*';} // Chiede se e' cancellato
int len() const { return _length;} // Ritorna la lunghezza
TFieldtypes type(const char* fieldname) const; // Ritorna il tipo del campo
int length(const char* fieldname) const; // Ritorna lunghezza campo
@ -135,7 +135,7 @@ public:
// const isdef* filehnd() const { return _i; } // Ritorna il file isam associato
int num() const { return _logicnum;} // Ritorna il numero logico
bool empty() const {return _isempty;} // Ritorna se e' vuoto
bool valid() const {return _rec[0] == 0;} // Ritorna se il record non e'cancellato
bool valid() const {return _rec[0] == ' ';} // Ritorna se il record non e'cancellato
const char* key(int numkey = 1) const; // Ritorna l'espressione della chiave numero numkey
bool ok() const { return _rec != NULL; }
@ -238,7 +238,7 @@ public:
bool empty(); // Vero se il file e' vuoto
int num() const { return _logicnum;} // Ritorna il numero logico del record corrente
const char* description() const;
TRecnotype eod() const { return filehnd()->d->EOD;}
TRecnotype eod() const ;
isdef* filehnd() const { return (isdef*) _isamfile;} // Ritorna l'handle del file isam nella tabella
@ -341,8 +341,9 @@ public:
int extend(TRecnotype eox); // Estende un file preesistente
long size(TRecnotype eox); // Calcola lo spazio che il file occuperebbe se venisse esteso a eox
int update(TTrec& newrec, bool vis = TRUE);
int packfile(bool vis = TRUE); // Rimuove fisicamente i record cancellati
int pack(bool vis = TRUE); // Esegue packfile e packindex
int packfile(bool vis = TRUE); // Rimuove fisicamente i record cancellati
int packindex(bool vis = TRUE); // La stessa cosa sugli indici
// @DES Importa un file ascii. from e' il nome del file da importare
@ -495,6 +496,7 @@ public:
// @DPUB
extern TTransaction transaction;
extern TRectype** openrec;
extern void get_idx_names(int logicnum, TToken_string& i_names);
// @END
#undef extern

View File

@ -1,2 +1,2 @@
#define VERSION "1.4"
#define INTERNAL_VERSION "0"
#define INTERNAL_VERSION "1"

View File

@ -14,6 +14,11 @@
#include <scanner.h>
#include <utility.h>
#include <lffiles.h>
#include <codeb.h>
extern int get_error(int);
///////////////////////////////////////////////////////////
// extern variables are NO-NO!
@ -96,9 +101,10 @@ HIDDEN int closeall(bool changestudy, TBit_array& excl, TBit_array& toclose)
d.get(i + 1, _nolock, _nordir, _sysdirop);
if (toclose[i + 1] || changestudy || d.name()[0] != '%')
{
excl.set(i, isfd->f.LockMode == _excllock);
CClose(&isfd->f);
CBCloseFile(&isfd->i, &err);
excl.set(i, DB_file_locked(isfd->fhnd) == _excllock);
err=DB_close(isfd->fhnd);
if (err != NOERR) err=get_error(err);
if (err != NOERR) fatal_box("Can't close file %d. Error n. %d",isfd->ln,err);
exclunlock(CInsPref((char*) glockname, _nordir), FALSE);
}
}
@ -140,9 +146,10 @@ HIDDEN void openall(bool changestudy, TBit_array& excl, int oldmax, TBit_array&
*isfd->r = *r.rec();
if (excllock(CInsPref((char*) glockname, NORDIR), FALSE) == -1 && errno == EACCES)
fatal_box("Can't reopen file n. %d : file in use", i + 1);
COpen(&isfd->f, isfd->d->SysName, isfd->d->LenR, 0, excl[i]);
if ((err = isfd->f.IOR) == NOERR)
CBOpenFile (&isfd->i, CGetIdxName(isfd->d->SysName), excl[i], &err);
err=DB_open(isfd->d->SysName,excl[i]==_excllock);
if (err<0) err=get_error(err);
if (err == _islocked)
fatal_box("Can't reopen file n. %d : file in use", i + 1);
if (err != NOERR)
fatal_box("Can't reopen file n. %d : error n. %d", i + 1, err);
}

View File

@ -13,9 +13,8 @@ enum TFilelock { _excllock = 0x100, _autolock = 0x200,
_manulock = 0x400};
enum TReclock { _unlock = 0x1000, _nolock = 0x2000, _lock = 0x4000,
_testandlock = (int)0x8000} ;
enum TRecstates { _valid, _deleted};
enum TDirtype { _nordir, _comdir } ;
enum TDirop { _nordirop, _sysdirop };
enum TDirtype { _nordir, _comdir } ;
enum TDirop { _nordirop, _sysdirop };
enum TFieldtypes { _nullfld, _alfafld, _intfld, _longfld, _realfld,
_datefld, _wordfld, _charfld, _boolfld , _intzerofld, _longzerofld,
_memofld} ;

View File

@ -1,4 +1,4 @@
// $Id: relation.cpp,v 1.49 1995-06-28 16:35:26 guy Exp $
// $Id: relation.cpp,v 1.50 1995-07-03 07:49:22 angelo Exp $
// relation.cpp
// fv 12/8/93
// relation class for isam files
@ -17,14 +17,19 @@
#include <utility.h>
#include <xvtility.h>
#include <codeb.h>
// *** check if not already defined
#define NOTFOUND (-1)
// *** maximum number of elements in a cursor working page
#define CMAXELPAGE 8000
#define print_name(out, f) out << (f.num() == LF_TABCOM ? "%" : "") << f.name()
extern int get_error(int);
HIDDEN const char* field_type_str(TFieldtypes f)
{
const char* c = "";
@ -735,14 +740,15 @@ int TRelation::remove(TDate& atdate)
///////////////////////////////////////////////////////////
HIDDEN bool __evalcondition(const TRectype& r,TExpression* cond)
HIDDEN bool __evalcondition(const TRelation* r,TExpression* cond)
{
for (int i = 0; i < cond->numvar(); i++)
{
const char* s = cond->varname(i);
cond->setvar(i, r.get(s));
TFieldref f(s,0);
cond->setvar(i, f.read(r));
}
return (bool) *cond;
}
@ -768,17 +774,14 @@ FILE* TCursor::open_index(bool create)
TRecnotype TCursor::buildcursor(TRecnotype rp)
{
TRecnotype ap = 0, junkl;
char s[82];
int junk, l, pagecnt = 0;
Page p;
int pos;
const int kl = file().filehnd()->i.Base[file().filehnd()->i.PN].KeyLen;
TRecnotype oldrecno=0,pos,ap = 0;
int junk, l, pagecnt = 0;
const bool filtered = has_filter();
FILE* _f = open_index(TRUE);
if (file().filehnd()->i.Base[file().filehnd()->i.PN].PEOD == 0)
if (DB_reccount(file().filehnd()->fhnd) == 0)
{
fclose(_f);
return 0;
@ -787,62 +790,56 @@ TRecnotype TCursor::buildcursor(TRecnotype rp)
fseek(_f, 0L, SEEK_SET);
l = strlen(to());
BTrRead(&file().filehnd()->i, (char*)(const char*) from(), s, &junkl, &junk);
junk=DB_index_seek(file().filehnd()->fhnd, (char*)(const char*) from());
if (junk < 0) junk=get_error(junk);
if (junk == _iseof) return 0;
TRecnotype* page = new TRecnotype [CMAXELPAGE];
if (GetAPage(&file().filehnd()->i, &p, file().filehnd()->i.CurPag, &junk) != NOERR)
fatal_box("Can't read index n. %d - file n. %d", file().filehnd()->i.PN + 1, file().filehnd()->ln);
pos = file().filehnd()->i.Pos - 1;
_pos = -1;
TRecnotype* page = new TRecnotype [CMAXELPAGE];
pos = DB_index_recno(file().filehnd()->fhnd);
_pos=-1;
while (TRUE)
{
if (pos >= p.PA.PageHeader.NKey)
{
if (p.PA.PageHeader.Next == -1L) break;
file().filehnd()->i.CurPag = p.PA.PageHeader.Next;
if (GetAPage(&file().filehnd()->i, &p, file().filehnd()->i.CurPag, &junk) != NOERR)
fatal_box("Can't read index n. %d - file n. %d", file().filehnd()->i.PN + 1, file().filehnd()->ln);
pos = 0;
}
const char* s0 = p.PA.AreaForKey + pos++ * (kl + 4);
{
if (DB_index_eof(file().filehnd()->fhnd)) break;
const char* s0 = DB_index_getkey(file().filehnd()->fhnd);
const TRecnotype recno = DB_index_recno(file().filehnd()->fhnd);
if (l && (strncmp(to(), s0, l) < 0)) break;
if (recno == oldrecno) break; // means that no more keys are available
oldrecno=recno;
if (pagecnt == CMAXELPAGE)
{
if (filtered) pagecnt = filtercursor(pagecnt, page);
fwrite(page, sizeof(junkl), pagecnt, _f);
if (pos == -1)
for (int i = 0; i < pagecnt; i++)
if (page[i] == rp)
{
_pos = ap + i;
break;
}
ap += pagecnt;
pagecnt = 0;
}
page[pagecnt++] = *((long *)(s0 + kl));
}
if (pagecnt)
{
if (filtered) pagecnt = filtercursor(pagecnt, page);
fwrite(page, sizeof(junkl), pagecnt, _f);
if (pos == -1)
for (int i = 0; i < pagecnt; i++)
{
if (filtered) pagecnt = filtercursor(pagecnt,page);
fwrite(page,sizeof(TRecnotype),pagecnt,_f);
for (int i= 0; i< pagecnt; i++)
if (page[i] == rp)
{
_pos = ap + i;
break;
break;
}
ap += pagecnt;
pagecnt = 0;
}
page[pagecnt++] = recno;
DB_index_next(file().filehnd()->fhnd);
int rt=get_error(-1);
if (rt != NOERR)
fatal_box("Can't read index n. %d - file n. %d",DB_tagget(file().filehnd()->fhnd),file().filehnd()->ln);
} // while
if (pagecnt)
{
if (filtered) pagecnt = filtercursor(pagecnt, page);
fwrite(page, sizeof(TRecnotype), pagecnt, _f);
for (int i = 0; i < pagecnt; i++)
if (page[i] == rp)
{
_pos = ap + i;
break;
}
ap += pagecnt;
}
if (_pos == -1 ) pos = 0;
if (_pos == -1) pos=0;
delete page;
fclose(_f);
fclose (_f);
return ap;
}
@ -850,18 +847,19 @@ TRecnotype TCursor::buildcursor(TRecnotype rp)
int TCursor::filtercursor(int pagecnt, TRecnotype* page)
{
int np = 0;
TRectype& rec = file().curr();
for (int i = 0; i < pagecnt; i++)
int np=0, handle=file().filehnd()->fhnd;
TRectype& rec=file().curr();
for (int i=0; i< pagecnt; i++)
{
CRead(&file().filehnd()->f, rec.string(), page[i], _nolock);
file().readat(rec,page[i]);
if (update_relation()) _if->update();
if ((_filterfunction ? _filterfunction(_if) : TRUE ) &&
(_fexpr ? __evalcondition(rec, _fexpr) : TRUE))
(_fexpr ? __evalcondition(_if, _fexpr) : TRUE))
{
if (np < i) page[np] = page[i];
np++;
}
}
}
return np;
}
@ -881,34 +879,30 @@ bool TCursor::ok() const
}
if (key < kf || (kt.not_empty() && kt < key.left(kt.len())))
return FALSE;
return FALSE;
if (_filter_update || _filterfunction_update) _if->update();
if ((_filterfunction ? _filterfunction(_if) : TRUE ) &&
(_fexpr ? __evalcondition(rec, _fexpr) : TRUE))
(_fexpr ? __evalcondition(_if, _fexpr) : TRUE))
return TRUE;
return FALSE;
}
}
bool TCursor::changed()
{
isdef* fh = file().filehnd();
if (_frozen && _lastrec != 0L) return _filename != fh->f.name;
if (_frozen && _lastrec > 0L) return _filename != fh->d->SysName;
#if XVT_OS==XVT_OS_SCOUNIX
const TRecnotype eod = file().eod();
#else
int junk = 0;
const TRecnotype eod = cisgeteod(fh, &junk);
#endif
const TRecnotype eod = DB_reccount(fh->fhnd);
if (_lastrec != eod ||
(_lastkrec != fh->i.Base[_nkey -1].PEOD) ||
(_filename != fh->f.name))
(_lastkrec != DB_changed(fh->fhnd)) ||
(_filename != fh->d->SysName))
{
// _lastrec = eod;
// _lastkrec = fh->i.Base[_nkey -1].PEOD;
// _filename = fh->f.name;
// _filename = fh->d->SysName;
// _lastkrec = DB_changed(fh->fhnd);
return TRUE;
}
else return FALSE;
@ -924,19 +918,13 @@ TRecnotype TCursor::update()
const TRecnotype totrec = buildcursor(file().recno());
main_app().end_wait();
isdef* fh = file().filehnd();
#if XVT_OS==XVT_OS_SCOUNIX
const TRecnotype eod = file().eod();
#else
int junk = 0;
const TRecnotype eod = cisgeteod(fh, &junk);
#endif
isdef* fh = file().filehnd();
const TRecnotype eod = DB_reccount(fh->fhnd);
_lastrec = eod;
_lastkrec = fh->i.Base[_nkey -1].PEOD;
_filename = fh->f.name;
_filename = fh->d->SysName;
_lastkrec = DB_changed(fh->fhnd);
return totrec;
}
@ -1066,7 +1054,7 @@ TRecnotype TCursor::read(TIsamop op, TReclock lockop, TDate& atdate)
TCursor::TCursor(TRelation* r, const char* fil, int nkey,
const TRectype *from, const TRectype* to)
: _if(r), _nkey(nkey), _frozen(FALSE), _filterfunction(NULL), _fexpr(NULL)
: _if(r), _nkey(nkey), _frozen(FALSE), _filterfunction(NULL), _fexpr(NULL), _filter_update(FALSE), _filterfunction_update(FALSE)
{
file().setkey(_nkey);
_pos = 0;
@ -1111,16 +1099,27 @@ TRecnotype TCursor::readrec()
fclose(_f);
curr().setdirty();
CRead(&file().filehnd()->f, curr().string(), nrec, _nolock);
file().readat(nrec);
repos();
return nrec;
}
int TCursor::lock(TReclock l)
{
SecDef* sd = &file().filehnd()->f;
CLockRec(sd, _pos, l);
return sd->IOR;
int rt=NOERR;
switch(l)
{
case _lock:
rt=DB_lock_rec(file().filehnd()->fhnd,_pos);
break;
case _unlock:
rt=DB_unlock(file().filehnd()->fhnd);
break;
default:
break;
}
if (rt < NOERR) rt=get_error(rt);
return(rt);
}
TRecnotype TCursor::operator =(const TRecnotype pos)

View File

@ -1,4 +1,4 @@
/* $Id: relation.h,v 1.21 1995-06-28 16:35:30 guy Exp $ */
/* $Id: relation.h,v 1.22 1995-07-03 07:49:25 angelo Exp $ */
// join.h
// fv 12/8/93
// join class for isam files
@ -106,7 +106,7 @@ public:
void save_status () ;
void restore_status () ;
// positioning operators. return status
TRecnotype operator +=(const TRecnotype npos) { return skip(npos); }
TRecnotype operator -=(const TRecnotype npos) { return skip(-npos); }
@ -164,6 +164,7 @@ public:
// Classe TCursor : public TObject
class TExpression;
typedef bool (*FILTERFUNCTION)(const TRelation* r);
@ -172,31 +173,33 @@ class TCursor : public TObject
{
TRelation* _if;
int _nkey;
TRecnotype _pos; // Posizione corrente
TRecnotype _pos; // Posizione corrente
TRecnotype _totrec;
TRecnotype _lastrec;
TRecnotype _lastkrec;
TRecnotype _lastkrec;
TFilename _filename;
TString _filter; // Filtro
TString _keyfrom; // chiave iniziale
TString _keyto; // chiave finale
TExpression* _fexpr; // Espressione relativo filtro
TString _filter; // Filtro
TString _keyfrom; // chiave iniziale
TString _keyto; // chiave finale
TExpression* _fexpr; // Espressione relativo filtro
bool _frozen;
bool _filter_update; // Flag che permette l'update della relazione per l'espressione-filtro
bool _filterfunction_update;// Flag che permette l'update della relazione per la funzione-filtro
FILTERFUNCTION _filterfunction;
TFilename _indexname;
virtual TRecnotype buildcursor(TRecnotype rp);
int filtercursor(int pagecnt, TRecnotype* page);
bool changed();
FILE* open_index(bool create = FALSE);
TRecnotype update();
protected:
FILE* open_index(bool create = FALSE);
virtual bool changed();
virtual TRecnotype buildcursor(TRecnotype rp);
virtual int filtercursor(int pagecnt, TRecnotype* page);
TRecnotype readrec();
void filter(const char* filter, const TRectype* from = NULL,
const TRectype* to = NULL);
bool update_relation() {return (_filter_update || _filterfunction_update);}
public:
// @FPUB
@ -205,7 +208,7 @@ public:
TRecnotype operator -=(const TRecnotype npos) { return operator +=(-npos); }
TRecnotype operator ++() { return operator +=(1); }
TRecnotype operator --() { return operator -=(1); }
TRecnotype pos() const { return _pos; }
TRecnotype& pos() { return _pos; }
TRecnotype items();
TRecnotype size() const { return file().eod(); }
@ -223,7 +226,7 @@ public:
const char* filter() const { return _filter; }
void freeze(bool on = TRUE) { _frozen = on; }
bool frozen() const { return _frozen; }
void setfilter(const char* filter_expr) { filter(filter_expr); }
void setfilter(const char* filter_expr, bool update=FALSE) { filter(filter_expr); _filter_update = update; }
void setregion(const TRectype& from, const TRectype& to)
{ filter(NULL,&from, &to); }
@ -232,6 +235,9 @@ public:
TLocalisamfile& file(const char* name) const { return _if->lfile(name); }
int repos() { return _if->position_rels(); }
TExpression* expression() const { return _fexpr; }
FILTERFUNCTION filterfunction() const { return _filterfunction; }
void setkey() { file().setkey(_nkey); }
void setkey(int nkey);
int key() const { return _nkey; }
@ -239,7 +245,7 @@ public:
bool next_match(int lognum, const char* fl = NULL, int nk = 0);
bool is_first_match(int ln);
void set_filterfunction(FILTERFUNCTION ff) { _filterfunction = ff; _lastrec = 0L;}
void set_filterfunction(FILTERFUNCTION ff, bool update=FALSE) { _filterfunction = ff; _lastrec = 0L; _filterfunction_update = update;}
bool has_filter() const { return _filter.not_empty() || _filterfunction; }
void save_status () { _if->save_status(); }
@ -277,7 +283,7 @@ public:
void set_name(const char* n) { _name = n; }
void set_from(int f) { if (f > 0) f--; else f = 0; _from = f; }
void set_to(int t) { _to = t; }
int from() const { return _from; }
int to() const { return _to; }
int len(TRectype &rec) const;

View File

@ -209,10 +209,9 @@ void TSheet::handler(WINDOW win, EVENT* ep)
select(nuo);
if (ep->type == E_MOUSE_DBL)
dispatch_e_char(win, K_ENTER);
else if (_checkable && _check_enabled && !_disabled[nuo] && vec == nuo)
else if (vec == nuo)
{
_checked.not(nuo);
force_update();
dispatch_e_char(win, K_SPACE);
}
}
else

View File

@ -15,10 +15,12 @@
#include <checks.h>
#include <isam.h>
#include <prefix.h>
#include <codeb.h>
#define REFKEY "CAMPOKEY"
#define VERKEY "ìpÙˆ¬cê<"
extern isfdptr *openf;
HIDDEN long _stdlevel = 0;
long get_std_level()
@ -66,6 +68,7 @@ void init_global_vars()
if (SerNo && !muflag)
fatal_box("Abnormal termination: check protection or serial number\n");
#endif
DB_init();
}
void free_global_vars()
@ -79,6 +82,7 @@ void free_global_vars()
delete openrec;
prefix_destroy();
}
DB_exit();
}

View File

@ -56,8 +56,10 @@ long get_std_level();
void init_global_vars();
void free_global_vars();
#ifdef __cplusplus
extern void* operator new(unsigned);
extern void operator delete(void*);
#endif
// @END