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

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

#include "BaseDato.h"

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

/*--------------------------------------------------------------Olimpo
 * FUNCION:  Bdt_Crea()
 * OBJETIVO: Crear un fichero de base de datos y obtener un
 *           objeto en memoria para manejarlo
 * ENTRADAS: El nombre completo del fichero que hay que crear,
 *           un vector con los nombres de los campos (terminado
 *           en NIL), un vector de caracteres con los tipos de
 *           los campos, un vector de nmeros con las longitudes
 *           de cada campo y un vector con la cantidad de 
 *           decimales de cada campo.
 * SALIDAS:  Una base de datos o NIL si no se puede crear
 * EJEMPLO:  Bdt_Crea ( "Agenda.dbf", {"NOMBRE", "EDAD", NIL},
 *                      {'C','N'}, {20, 3}, {0, 0} )
 * NOTAS:    1. Los nombres de los campos no pueden tener ms
 *              de 10 caracteres
 *           2. Es costumbre que los nombres de los campos se
 *              escriban en maysculas
 *           3. Los tipos de campo pueden ser:
 *              'C' -> carcter
 *              'D' -> fecha, debe tener longitud 8
 *              'L' -> lgico, debe tener longitud 1
 *              'M' -> memo, debe tener longitud 10
 *              'N' -> numrico
 * ALGORITMO:
 *      Pedir un objeto base de datos
 *      Calcular el nmero de campos y anotarlo
 *      Pedir memoria para DescriptoresCampo
 *      Para cada campo:
 *           Anotar sus datos en DescriptoresCampo
 *           Ir sumando su longitud a longitud de registro
 *           Comprobar si es un campo memo
 *      Anotar en DescriptorFichero versin, longitud de cabecera y
 *                                           longitud de registro
 *      Pedir memoria para InfoActual y anotarlo
 *      Anotar Modificado, ModoApertura, ComienzoRegistro y LongitudRegistro
 *      Abrir el nuevo fichero y anotarlo
 *      Grabar en el fichero DescriptorFichero, DescriptoresCampo y 2 octetos
 *          (uno lo grabo por decirlo as en la LongitudCabecera y el otro
 *           por evitar problemas al grabar registros en una base de datos
 *           con 0 registros)
 *------------------------------------------------------------------*/
basedato Bdt_Crea (NombreFichero, Nombre, Tipo, Longitud, Decimal)
cadena   NombreFichero, Nombre[];
char     Tipo[];
contador Longitud[], Decimal[];
  {
  static char Inutil[2] = { 13, 0 }; /* Por compatibilidad dBase III+ */
  basedato Nuevo;             
  logico   HayCampoMemo=NO, Error = NO;
  contador TotalCampo = 0, LongRegistro = 0, LongCabecera, i;
  memoria  DireccionDescrCam, DireccionRegistro;
  fichero  Fichero;

  if ( Nuevo = Bdt_CreaObjeto() )
    {
    for ( i=0 ; Nombre[i] ; i++ ) { TotalCampo++; }
    Bdt_PonTotalCampo (Nuevo,TotalCampo);
    DireccionDescrCam = Mem_Crea (TotalCampo * BDT_LONGDESCRIPTOR);
    if ( !DireccionDescrCam ) { Error = SI; }
    else
      {
      Mem_Asigna (DireccionDescrCam,0,TotalCampo * BDT_LONGDESCRIPTOR);
      Bdt_PonDescriptoresCampo (Nuevo,DireccionDescrCam);
      for ( i=0 ; i<TotalCampo ; i++ )
        {
        Cad_Copia (DireccionDescrCam+i*BDT_LONGDESCRIPTOR,Nombre[i]);
        DireccionDescrCam[i*BDT_LONGDESCRIPTOR+11] = Tipo[i];
        DireccionDescrCam[i*BDT_LONGDESCRIPTOR+16] =
                                        (unsigned char) Longitud[i];
        DireccionDescrCam[i*BDT_LONGDESCRIPTOR+17] =
                                        (unsigned char) Decimal[i];
        LongRegistro += Longitud[i];
        if ( Tipo[i] == 'M' )  { HayCampoMemo=SI; }
        }
      LongCabecera = BDT_LONGDESCRIPTOR * ( TotalCampo + 1 ) + 1;
      LongRegistro++;
      if ( HayCampoMemo )
        { Bdt_DescriptorFichero(Nuevo)[0] = 0x83; }
      else
        { Bdt_DescriptorFichero(Nuevo)[0] = 0x03; }
      Mem_EscribeContador (Bdt_DescriptorFichero(Nuevo)+8, MEM_INTEL,
                           LongCabecera);
      Mem_EscribeContador (Bdt_DescriptorFichero(Nuevo)+10, MEM_INTEL,
                           LongRegistro);

      DireccionRegistro = Mem_Crea (LongRegistro);
      if ( !DireccionRegistro ) { Error = SI; }
      else
        {
        Mem_Asigna (DireccionRegistro,0,LongRegistro);
        Bdt_PonInfoActual (Nuevo, DireccionRegistro);
        Bdt_PonModificado (Nuevo, SI);
        Bdt_PonModoApertura (Nuevo, BDT_ACTUALIZACION);
        Bdt_PonComienzoRegistro (Nuevo, LongCabecera);
        Bdt_PonLongitudRegistro (Nuevo, LongRegistro);
        if ( Fichero = Fch_AbreGrabar (NombreFichero,FCH_BINARIO) )
          {
          Bdt_PonFichero (Nuevo, Fichero);
          Fch_EscribeOcteto (Fichero,Bdt_DescriptorFichero(Nuevo),
                             BDT_LONGDESCRIPTOR);
          Fch_EscribeOcteto (Fichero,Bdt_DescriptoresCampo(Nuevo),
                             BDT_LONGDESCRIPTOR*TotalCampo);
          Fch_EscribeOcteto (Fichero,Inutil,2);
          }
        else
          {
          Bdt_Destruye (Nuevo);
          Nuevo = NIL;
          }
        }
      }
    }

  if ( Error )
    {
    Bdt_Destruye (Nuevo);
    Usr_Avisa ("Falta memoria para crear una nueva base de datos");
    Nuevo = NIL;
    }

  return ( Nuevo );
  }