/*--------------------------------------------------------------------
 * FICHERO:  BdtAbre.c
 * OBJETIVO: Definir la funcin Bdt_Abre()
 * AUTOR:    Pedro Reina
 * FECHA:    V.14.7.1995
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Ficheros de cabecera
 *------------------------------------------------------------------*/

#include "BaseDato.h"

/*--------------------------------------------------------------------
 * Definicin de funciones
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------Olimpo
 * FUNCION:  Bdt_Abre()
 * OBJETIVO: Abrir un fichero de base de datos y obtener un
 *           objeto en memoria para manejarlo
 * ENTRADAS: El nombre completo del fichero que hay que abrir,
 *           y el modo de apertura
 * SALIDAS:  Una base de datos o NIL si no se puede crear
 * EJEMPLO:  Bdt_Abre ("Agenda.dbf", BDT_LECTURA)
 * ALGORITMO:
 *      Pedir un objeto base de datos
 *      Abrir el fichero
 *      Anotar fichero y modo de apertura
 *      Leer descriptor de fichero
 *      Calcular y anotar nmero, longitud y comienzo de registros
 *      Calcular y anotar el nmero de campos
 *      Reservar memoria para InfoActual y anotarlo
 *      Reservar memoria para DescriptoresCampo y anotarlo
 *      Leer DescriptoresCampo
 *------------------------------------------------------------------*/
basedato Bdt_Abre (NombreFichero, Modo)
cadena NombreFichero;
octeto Modo;
  {
  basedato Nuevo;
  logico   ErrorFormato = NO, ErrorMemoria = NO, ErrorFichero = NO;
  contador TotalCampo, LongRegistro, LongCabecera;
  entero   TotalRegistro;
  memoria  DireccionDescrCam, DireccionRegistro;
  fichero  Fichero;
  cadena   Mensaje;

  if ( Nuevo = Bdt_CreaObjeto() )
    {
    if ( Modo == BDT_LECTURA )
      { Fichero = Fch_AbreLeer (NombreFichero,FCH_BINARIO); }
    else
      { Fichero = Fch_AbreActualizar (NombreFichero,FCH_BINARIO); }

    if ( !Fichero )
      { ErrorFichero = SI; }
    else
      {
      Bdt_PonFichero (Nuevo, Fichero);
      Bdt_PonModoApertura (Nuevo, Modo);

      if ( ! Fch_LeeOcteto(Fichero,Bdt_DescriptorFichero(Nuevo),
           BDT_LONGDESCRIPTOR) )
        { ErrorFormato = SI; }
      else
        {
        if ( Bdt_DescriptorFichero(Nuevo)[0] != 0x03 &&
             Bdt_DescriptorFichero(Nuevo)[0] != 0x83 )
          { ErrorFormato = SI; }
        else
          {
          TotalRegistro = Mem_LeeEntero (Bdt_DescriptorFichero(Nuevo)+4,
                                         MEM_INTEL);
          Bdt_PonTotalRegistro (Nuevo, TotalRegistro);

          LongRegistro = Mem_LeeContador (Bdt_DescriptorFichero(Nuevo)+10,
                                          MEM_INTEL);
          Bdt_PonLongitudRegistro (Nuevo, LongRegistro);

          LongCabecera = Mem_LeeContador (Bdt_DescriptorFichero(Nuevo)+8,
                                          MEM_INTEL);
          Bdt_PonComienzoRegistro (Nuevo, LongCabecera);

          TotalCampo = LongCabecera / BDT_LONGDESCRIPTOR - 1;
          Bdt_PonTotalCampo (Nuevo,TotalCampo);

          DireccionRegistro = Mem_Crea (LongRegistro);
          if ( !DireccionRegistro ) { ErrorMemoria = SI; }
          else
            {
            Bdt_PonInfoActual (Nuevo, DireccionRegistro);

            DireccionDescrCam = Mem_Crea (TotalCampo * BDT_LONGDESCRIPTOR);
            if ( !DireccionDescrCam ) { ErrorMemoria = SI; }
            else
              {
              Bdt_PonDescriptoresCampo (Nuevo,DireccionDescrCam);

              if ( ! Fch_LeeOcteto (Fichero,DireccionDescrCam,
                                    TotalCampo * BDT_LONGDESCRIPTOR) )
                { ErrorFormato = SI; }
              }
            }
          }
        }
      }
    }

  if ( ErrorMemoria )
    { Usr_Avisa ("Falta memoria para crear una nueva base de datos"); }

  if ( ErrorFormato )
    {
    Mensaje = Cad_Une ("El fichero \"",NombreFichero,"\" no tiene formato ",
                       "correcto", CAD_FIN);
    Usr_Avisa (Mensaje);
    Cad_Destruye (Mensaje);
    }

  if ( ErrorMemoria || ErrorFormato || ErrorFichero )
    {
    Bdt_Destruye (Nuevo);
    Nuevo = NIL;
    }

  return ( Nuevo );
  }