Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
codeb.c     Migliorata la funzione static find_slash_backslash
config.cpp  Tolto messaggio di creazione config, in quanto blocca il
            programma se viene mostrato durante la create!
expr.h      Trasformate in TString80 alcune TString
form.*      Aggiunto metodo per accedere ai campi per numero
git-svn-id: svn://10.65.10.50/trunk@6947 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
	
			
		
			
				
	
	
		
			2517 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2517 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  */
 | 
						|
 | 
						|
//extern char* CUpString(char *);
 | 
						|
#define CUpString(str) _strupr(str)
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
/*-------------------------------------------------------------------------
 | 
						|
  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';
 | 
						|
  CUpString(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);
 | 
						|
        CUpString(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  */
 | 
						|
 | 
						|
extern char* CUpString(char *);
 | 
						|
 | 
						|
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_delkeys");
 | 
						|
#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';
 | 
						|
  CUpString(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);
 | 
						|
        CUpString(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
 |