/*
@(SH) Utility per la gestione dei file ISAM
-------------------------------------------------------------------------------
*/

#include        <ccommon.h>
#include        <genconst.h>
#include        <ccustio.h>
#include        <cfiles.h>
#include        <cbpltree.h>
#include        <cbplcre.h>
#include        <cisam.h>
#ifdef __WATCOMC__
#include <malloc.h>
#else
#include        <memory.h>
#endif
#include        <progind.h>

/*
@(#) creorgfile  ISAM

@(ID)
Compatta il file dati eliminando fisicamente i record cancellati logicamente.
Ritorna il codice di errore.
@(FD)

@(ISV)
wisfd    = puntatore al descrittore del file.

rec      = buffer per contenere un record.

i        = contatore.

k        = contatore.

oldeod   = variabile che contiene il vecchio valore di End of Data.


junk     = variabile spazzatura per la chiamata di varie funzioni.

w        = finestra di visualizzazione.

s    = stringa messaggio.

- Versione DOS e XENIX
@(FSV)
*/

int creorgfile(logicname,vis,err)
int           logicname; /* numero logico del file                           */
BOOLEAN       vis;       /* se true visualizza le operazioni che sta facendo */
int           *err;      /* codice errore                                    */

  {
    isfdptr   wisfd;
    RecType   rec;
    RecNoType i = 0L,k = 0L,oldeod;
    int       junk;
    char      s[80];

    *err = NoErr;
    if (cisopen(&wisfd, logicname, &rec, ExclLock, err)) return(*err);
    oldeod = wisfd->d->EOD;
    if (vis && (oldeod > 0))
    {
      sprintf(s,"Compatta - %s", wisfd->d->Des);
      progind_create(wisfd->d->EOD, s, FALSE, TRUE, 70);
    }
    while (i < wisfd->d->EOD)
    {
      i++;
      CRead(&wisfd->f, rec, i, NoLock);
      if ((*err = wisfd->f.IOR)) break ;
      if (!IRecIsDeleted(rec))
      {
        k++;
        if (k < i) CWrite(&wisfd->f, rec, k, NoLock);
      }
      if (vis && (oldeod > 0) && (!(i % 10)))
        progind_set_status(i);
    }
    if (vis && (oldeod > 0))
      progind_set_status(i);
    if (!*err)
    {
      wisfd->d->EOD = k;
#ifndef DOS
      writelog(FNREORG, NULL, (RecType) &oldeod);
#endif
      junk  = cisupdflags(wisfd, &junk, TRUE);
    }
    junk = cisclose(&wisfd, &rec, &junk);
    if (vis && oldeod > 0)
      progind_destroy();
    return(*err);
  }

/*
@(#) creorgindex  ISAM

@(ID)
Ricostruisce l'indice di un file.
Ritorna il codice di errore.
@(FD)

@(ISV)
wisfd    = puntatore al descrittore del file.

rec      = buffer per contenere un record.

j        = contatore.

junk     = variabile spazzatura per la chiamata di varie funzioni.

w        = finestra di visualizzazione.

s    = stringa messaggio.
@(FSV)

@(IN)
Deve essere usata in coppia con la "creorgfile".
@(FN)
*/

int creorgindex(logicname,vis,err)
int           logicname; /* numero logico del file                   */
BOOLEAN       vis;       /* se  true visualizza cio' che sta facendo */
int           *err;      /* codice errore                            */

  {
    isfdptr   wisfd;
    RecType   rec;
    int       junk, j;
    char      s[80];
    int werr = NoErr;

    *err = NoErr;
    getisfd(&wisfd, logicname);
    CBInitFile(&wisfd->i);
    for (j = 1; j <= wisfd->r->NKeys;j++)
    {
      CBInitPath(j,CCalcLenKey(wisfd->r,j),wisfd->d->EOX,
                 wisfd->r->Ky[j-1].DupKeys,&(wisfd->i),err);
      if (*err)
      {
        relisfd(&wisfd);
        return (*err);
      }
    }
    junk = unlink(CGetIdxName(wisfd->d->SysName));
    CBCreate(&wisfd->i, CGetIdxName(wisfd->d->SysName),err);
    relisfd(&wisfd);
    if (*err) return (*err);
    if (cisopen(&wisfd, logicname, &rec, ExclLock, err)) return(*err);
    wisfd->RecNo = 0L;
    if (vis && (wisfd->d->EOD > 0))
    {
      sprintf(s,"Crea indice - %s", wisfd->d->Des);
      progind_create(wisfd->d->EOD, s, FALSE, TRUE, 70);
    }
    while (wisfd->RecNo < wisfd->d->EOD)
    {
      wisfd->RecNo++;
      CRead(&wisfd->f, rec, wisfd->RecNo, NoLock);
      werr = wisfd->f.IOR;
      if (!IRecIsDeleted(rec))
        addkeys(wisfd,rec,1,&werr);
      if (vis && (wisfd->d->EOD > 0) && (!(wisfd->RecNo % 10)))
        progind_set_status(wisfd->RecNo);
      if (werr != NoErr && *err == NoErr)
        *err = werr;
    }
    if (vis && (wisfd->d->EOD > 0))
      progind_set_status(wisfd->RecNo);
    junk = cisclose(&wisfd, &rec, &junk);
    if (vis)
      progind_destroy();
    if (*err != NoErr)
      error_box("Si e' verificato almeno un errore n. %d\nVerificare l'archivio e ripetere il compattamento", *err);
    return(*err);
  }