#define __CFILES_C /* fv */

#include <xvt.h>

#include "cfiles.h"

int  dirfl[2] = {0, 0}, recfl[2] = {0, 0} ;
PathSt __ptprf = "";        // Nome della directory con lo studio corrente

/*
   @(#) COpenDir  FILES

   @(ID)
   Apre il file directory di una ditta.
   @(FD)

   @(ISV)
   name  = percorso per il file di direttorio.

   Versione WIN32 e LINUX.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegare dettagliatamente il motivo.
   @(FN)
   */

void COpenDir(lockmode, dirflg)
  int     lockmode; /* modo di apertura */
  int     dirflg; /* flag per file comuni */

{
  PathSt          name;

  if (dirfl[dirflg]++) return;
  strcpy(name, CInsPref(directory, dirflg)) ;
  COpen(&fdir[dirflg], name, sizeof(FileDes), 0, lockmode) ;
  if (fdir[dirflg].IOR != NoErr)
  {
    char msg[256];
    sprintf(msg, "Can't open Directory. Error number : %d (%s)", fdir[dirflg].IOR,name);
    xvt_dm_post_fatal_exit(msg);
  }
}

/*
   @(#) CCloseDir  FILES

   @(ID)
   Chiude il file di direttorio di una ditta.
   @(FD)

   @(ISV)
   Versione WIN32 e LINUX.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void CCloseDir(int dirflg) /* flag per file comuni */
{
#ifdef LINUX
  exclunlock(CInsPref(glockname, dirflg), (fdir[dirflg].LockMode == ExclLock));
#endif
  if (dirfl[dirflg]) dirfl[dirflg]--;
  if (!dirfl[dirflg]) CClose(&fdir[dirflg]) ;
}

/*
   @(#) COpenFile  FILES

   @(ID)
   Legge i dati di un archivio dal Direttorio.
   @(FD)

   @(ISV)
   junk  = variabile spazzatura per la chiamata della funzione "sleep".

   s = stringa contenente messaggio di attesa.

   w     = descrittore finestra di attesa.

   Versione WIN32 e LINUX.
   @(FSV)

   @(IN)
   Sostituisce l'eventuale simbolo "$" con il prefisso corrente.

   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void COpenFile(logicname,filed,lockmode,dirflg)
  int                   logicname; /* numero logico file                        */
  FileDes *filed;    /* puntatore alla struttura che contiene i dati letti dal direttorio */
  int                     lockmode;  /* tipo di lock effettuato sul record */
  int                     dirflg; /* flag per file comuni */

{
  do 
  {
    CRead(&fdir[dirflg],(RecType) filed,(long) logicname, lockmode);
    
    if (TESTLOCK(fdir[dirflg].IOR)) 
    {
      char msg[256];
      sprintf(msg, "Sono in attesa della directory n.ro %d", logicname);
      xvt_dm_post_message(msg); 
    }
  } while TESTLOCK(fdir[dirflg].IOR) ;
  strcpy(filed->SysName, CAddPref(filed->SysName)) ;
}

/*
   @(#) CCloseFile  FILES

   @(ID)
   Chiude e Riscrive i dati di un file sul direttorio.
   @(FD)

   @(ISV)
   wd     = descrittore di una riga di direttorio.

   junk   = variabile spazzatura per la chiamata della funzione "sleep".

   s = messaggio di attesa.

   w      = descrittore della finestra di attesa.
   @(FSV)

   @(IN)
   ATTENZIONE : questa funzione aggiorna esclusivamente i campi EOD e Flags .

   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void CCloseFile(logicname,filed,dirflg)
  int                   logicname;  /* numero logico file                             */
  FileDes *filed;     /* puntatore al descrittore di un archivio */
  int     dirflg; /* flag per file comuni */

{
  FileDes   wd;

  CRead(&fdir[dirflg],(RecType) &wd,(long) logicname, NoLock);
  wd.EOD = filed->EOD;
  wd.Flags = filed->Flags;
  CWrite(&fdir[dirflg],(RecType) &wd,(long) logicname, UnLock);
}
/*
   @($) CGetFile  FILES

   @(ID)
   Legge i dati relativi ad un archivio nel direttorio.
   Non sostituisce con il prefisso l'eventuale carattere "$".
   @(FD)

   @(ISV)
   junk   = variabile spazzatura per la chiamata della funzione "sleep".

   s = messaggio di attesa.

   w      = descrittore finestra di attesa.

   Versione WIN32 e LINUX.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void CGetFile(logicname,filed,lockmode,dirflg)
  int                   logicname; /* numero logico file                               */
  FileDes *filed;    /* puntatore al descrittore archivio nel direttorio */
  int                     lockmode;  /* tipo di lock sul record                          */
  int                     dirflg; /* flag per file comuni */
{

  do
  {
    CRead(&fdir[dirflg],(RecType)    filed,(long) logicname, lockmode);
    if (TESTLOCK(fdir[dirflg].IOR)) 
    {
      char msg[256];
      sprintf(msg, "Sono in attesa della directory n.ro %d", logicname);
      xvt_dm_post_message(msg); 

    }
  }
  while TESTLOCK(fdir[dirflg].IOR) ;
}

/*
   @($) CPutFile  FILES

   @(ID)
   Chiude il direttorio e Riscrive i dati relativi ad un archivo.
   Aggiorna tutti i campi.
   @(FD)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void CPutFile(logicname,filed,dirflg)
  int                   logicname; /* numero logico file                            */
  FileDes *filed;    /* puntatore al descrittore dell'archivio */
  int                     dirflg; /* flag per file comuni */

{
  CWrite(&fdir[dirflg],(RecType)filed,(long) logicname, UnLock);
}

/*
   @($) zerofdes  FILES

   @(ID)
   Azzera un descrittore di directory.
   @(FD)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */


void         zerofdes(d) 
  FileDes    *d; /* puntatore al descrittore di un archivio nella direttorio */

{ 
  strcpy(d->SysName, ""); 
  d->EOD = 0; 
  d->EOX = 0; 
  d->LenR = 0; 
  d->Flags = 0; 
  strcpy(d->Des, ""); 
  strcpy(d->FCalc, ""); 
  strcpy(d->GenPrompt, ""); 
} 

/*
   @(#) COpenRecDir  FILES

   @(ID)
   Apre l'Archivio dei Tracciati Record.
   @(FD)

   @(ISV)
   name = nome dell'archivio dei Tracciati Record.

   Versione WIN32 e LINUX.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void COpenRecDir(lockmode,dirflg)
  int             lockmode;  /* modo di apertura */
  int             dirflg; /* flag per file comuni */

{
  PathSt          name;

  if (recfl[dirflg]++) return;
  strcpy(name, CInsPref(ntrrec, dirflg)) ;
  COpen(&rdir[dirflg], name, sizeof(RecDes), 0, lockmode) ;
  if (rdir[dirflg].IOR != NoErr)
  {
    char msg[256];
    sprintf(msg, "Can't open record description file. Error number : %d (%s)", rdir[dirflg].IOR,name);
    xvt_dm_post_fatal_exit(msg);
  }

}

/*
   @(#) CCloseRecDir  FILES

   @(ID)
   Chiude l'Archivio dei Tracciati Record
   @(FD)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo
   @(FN)
   */

void CCloseRecDir(dirflg)
  int     dirflg; /* flag per file comuni */

{
  if (recfl[dirflg]) recfl[dirflg]--;
  if (!recfl[dirflg]) CClose(&rdir[dirflg]) ;
}

/*
   @(#) CGetRec  FILES

   @(ID)
   Legge il tracciato record del file "logicname" e lo mette in "recd".
   @(FD)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

void CGetRec(logicname,recd,dirflg)
  int             logicname; /* numero file               */
  RecDes  *recd;   /* descrittore record  */
  int     dirflg; /* flag per file comuni */

{
  CRead(&rdir[dirflg],(RecType)      recd,(long) logicname, NoLock);
}


/*
   @($) CPutRec  FILES

   @(ID)
   Aggiorna il file dei Tracciati Record.
   @(FD)

   */

void CPutRec(logicname,recd,dirflg)
  int             logicname; /* numero file                       */
  RecDes  *recd;   /* descrittore record  */
  int     dirflg; /* flag per file comuni */

{
  CWrite(&rdir[dirflg],(RecType)     recd,(long) logicname, NoLock);
}

/*
   @($) CGetCampoIni  FILES

   @(ID)
   Restituisce il nome del file che contiene il prefisso corrente.
   @(FD)

   @(ISV)
   s,s1 = stringhe di lavoro.

   Versione WIN32 e LINUX.
   @(FSV)
*/   
const char* CGetCampoIni(void)
{
  static char* prawin = NULL;
  if (prawin == NULL)
  {
    char exedir[_MAX_PATH], path[_MAX_PATH];
    DIRECTORY dir; 
    BOOLEAN bFound = FALSE;
    xvt_fsys_get_dir(&dir);
    xvt_fsys_convert_dir_to_str(&dir, exedir, sizeof(exedir));
#ifdef WIN32
    // Nelle installazioni sfigate con programmi in rete cerca di stabilire il percorso locale di Campo.ini
    if (xvt_fsys_is_network_drive(exedir))
    {
      int p;
      for (p = 1; ; p++)
      {
        int len = 0;
        char para[4]; sprintf(para, "%d", p);
        len = xvt_sys_get_profile_string("c:/campo.stp", para, "Program", "", path, sizeof(path));
        if (len <= 0)
          break;
        if (path[len-1] == '\\' || path[len-1] == '/')
        {
          len--;
          path[len] = '\0';
        }
        if (xvt_str_compare_ignoring_case(path, exedir) == 0)
        {
          xvt_sys_get_profile_string("c:/campo.stp", para, "CampoIni", "", path, sizeof(path));
          bFound = TRUE;
          break;
        }
      }
      if (!bFound)
      {
        const char* pp = getenv("PREFPATH");
        if (pp != NULL)
        {
          char dri[_MAX_DRIVE], dir[_MAX_PATH];
          xvt_fsys_parse_pathname(pp, dri, dir, NULL, NULL, NULL);
          xvt_fsys_build_pathname(path, dri, dir, "campo", "ini", NULL);
          bFound = TRUE;
        }
      }
    }
#endif
    if (!bFound)
    {
#ifdef LINUX
      char ininame[32];
      sprintf(ininame, "campo%u", getuid());
      xvt_fsys_build_pathname(path, NULL, exedir, ininame, "ini", NULL);
#else
      xvt_fsys_build_pathname(path, NULL, exedir, "campo", "ini", NULL);
#endif
    }
    prawin = xvt_str_duplicate(path);
  }
  return prawin;
}

HIDDEN BOOLEAN CGetFirmDir()
{           
  const char* prawin = CGetCampoIni();
  BOOLEAN good = _access(prawin, 0x00) == 0;
  if (good)  
  {
    const int len = xvt_sys_get_profile_string(prawin, "Main", "Study", "", __ptprf, sizeof(__ptprf));
    good = len > 0;
    if (good)
    {
      char firm[8];
      long ditta;
    
      if (__ptprf[len-1] != '\\' && __ptprf[len-1] != '/')
      {
        __ptprf[len] = DIRSEP;
        __ptprf[len+1] = '\0';
      }
      
      xvt_sys_get_profile_string(prawin, "Main", "Firm", "COM", firm, sizeof(firm));
      ditta = atol(firm);
      if (ditta > 0) sprintf(firm, "%05ldA", ditta);
      _makepath(cprefix, NULL, __ptprf, firm, NULL);
    }   
  }  
  
  return good;
}

BOOLEAN CPutFirmDir(const char* pref)
{           
  const char* prawin = CGetCampoIni();
  BOOLEAN good = xvt_sys_set_profile_string(prawin, "Main", "Firm", pref);
  xvt_sys_set_profile_string(prawin, "Main", "Study", __ptprf);
  return good;
}

/*
   @(#) CGetPref  FILES

   @(ID)
   Legge dal file prefisso il prefisso dati corrente.
   @(FD)

   @(ISV)
   f = puntatore al file.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

const char* CGetPref()
{                    
  if (!CGetFirmDir()) 
  {          
		strcpy(cprefix, "COM");
    CPutFirmDir(cprefix);
  }  
  return cprefix;
}

/*
   @($) CPutPref  FILES

   @(ID)
   Aggiorna sul file prefisso il prefisso dati corrente.
   @(FD)

   @(ISV)
   f = puntatore a file.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */


void CPutPref(const char* pref)  /* stringa contenente il nuovo prefisso */
{
  CPutFirmDir(pref);
}

/*
   @($) CAddPref  FILES

   @(ID)
   Cerca il carattere "$" nel nome file e lo sostituisce con il prefisso corrente.
   @(FD)

   @(ISV)
   s = stringa che contiene il nome.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

char *CAddPref(name)
  char *name; /* nome file */

{
  static char* s = NULL;

  if (*name == '$')
  {
    name++;
    return(CInsPref(name, NORDIR)) ;
  }
  else
  {
    if (*name == '%')
    {
      name++;
      return(CInsPref(name, COMDIR)) ;
    }
    else
    {      
      if (s == NULL)
         s = malloc(_MAX_PATH);
      if (strncmp(__ptprf, name, strlen(__ptprf)) != 0)
        sprintf(s, "%s%s", __ptprf, name);
      else 
        strcpy(s, name);
      return s;
    }
  }  
}

/*
   @($) CInsPref  FILES

   @(ID)
   Aggiunge (a sinistra) il prefisso corrente.
   @(FD)

   @(ISV)
   s = stringa di lavoro.
   @(FSV)

   @(IN)
   NON UTILIZZARE !!.

   Se si utilizza spiegarne dettagliatamente il motivo.
   @(FN)
   */

char    *CInsPref(name,dirflg)
  char    *name; /* nome del file  cui aggiungere il prefisso */
  int     dirflg; /* flag per file comuni */

{
  static char* s = NULL;
  if (s == NULL)
    s = malloc(_MAX_PATH);

  if (dirflg == NORDIR)
  {
    if (*cprefix == '\0') 
      strcpy(s, name);
    else 
      _makepath(s, NULL, cprefix, name, NULL);
  }
  else 
    sprintf(s,"%scom%c%s", __ptprf, DIRSEP, name);
  return s;
}