/*--------------------------------------------------------------------
 * FICHERO:       BaseDato.h
 * OBJETIVO:      Definir el objeto "BaseDato"
 * IDENTIFICADOR: Bdt
 * AUTOR:         Pedro Reina
 * FECHA:         V.14.7.1995
 * OBJETOS UTILIZADOS: Memoria, Tiempo, Cadena, Usuario, Fichero
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones pblicas
 *
 *   Bdt_Actual()            BaseDato.h
 *   Bdt_TotalCampo()        BaseDato.h
 *   Bdt_TotalRegistro()     BaseDato.h
 *   Bdt_Crea()              BdtCrea.c
 *   Bdt_Abre()              BdtAbre.c
 *   Bdt_Cierra()            BdtCreOb.c
 *   Bdt_AnoUltimo()         BaseDato.h
 *   Bdt_MesUltimo()         BaseDato.h
 *   Bdt_DiaUltimo()         BaseDato.h
 *   Bdt_NombreDeCampo()     BdtNomCa.c
 *   Bdt_TipoDeCampo()       BdtTipCa.c
 *   Bdt_LongitudDeCampo()   BdtLonCa.c
 *   Bdt_DecimalDeCampo()    BdtDecCa.c
 *   Bdt_NumeroDeCampo()     BdtNumCa.c
 *   Bdt_LeeRegistro()       BdtLeeRe.c
 *   Bdt_ActivoRegistro()    BaseDato.h
 *   Bdt_LimpiaRegistro()    BaseDato.h
 *   Bdt_BorraRegistro()     BaseDato.h
 *   Bdt_RecuperaRegistro()  BaseDato.h
 *   Bdt_AgregaRegistro()    BdtAgrRe.c
 *   Bdt_CampoNumero()       BdtCamNu.c
 *   Bdt_CampoNombre()       BdtCamNo.c
 *   Bdt_PonCampoNumero()    BdtPCaNu.c
 *   Bdt_PonCampoNombre()    BdtPCaNo.c
 *   Bdt_EscribeRegistro()   BdtEscRe.c
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones conocidas
 *
 *   Ninguna
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones privadas
 *
 *   Bdt_Fichero()              BaseDato.h
 *   Bdt_PonFichero()           BaseDato.h
 *   Bdt_DescriptorFichero()    BaseDato.h
 *   Bdt_DescriptoresCampo()    BaseDato.h
 *   Bdt_PonDescriptoresCampo() BaseDato.h
 *   Bdt_InfoActual()           BaseDato.h
 *   Bdt_PonInfoActual()        BaseDato.h
 *   Bdt_PonActual()            BaseDato.h
 *   Bdt_PonTotalCampo()        BaseDato.h
 *   Bdt_PonTotalRegistro()     BaseDato.h
 *   Bdt_Modificado()           BaseDato.h
 *   Bdt_PonModificado()        BaseDato.h
 *   Bdt_ModoApertura()         BaseDato.h
 *   Bdt_PonModoApertura()      BaseDato.h
 *   Bdt_ComienzoRegistro()     BaseDato.h
 *   Bdt_PonComienzoRegistro()  BaseDato.h
 *   Bdt_CreaObjeto()           BdtCreOb.c
 *   Bdt_LongitudRegistro()     BaseDato.h
 *   Bdt_PonLongitudRegistro()  BaseDato.h
 *   Bdt_PonAnoUltimo()         BaseDato.h
 *   Bdt_PonMesUltimo()         BaseDato.h
 *   Bdt_PonDiaUltimo()         BaseDato.h
 *   Bdt_Destruye()             BdtCreOb.c
 *   Bdt_MarcaRegistro()        BdtMarRe.c
 *------------------------------------------------------------------*/

#ifndef _BASEDATO_
#define _BASEDATO_

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

#include "Memoria.h"
#include "Tiempo.h"
#include "Cadena.h"
#include "Usuario.h"
#include "Fichero.h"

/*--------------------------------------------------------------------
 * Definicin de macros constantes
 *------------------------------------------------------------------*/

#define BDT_LECTURA       (octeto)0
#define BDT_ACTUALIZACION (octeto)1

#define BDT_LONGDESCRIPTOR 32

/*--------------------------------------------------------------------
 * Definicin del tipo "basedato"
 *------------------------------------------------------------------*/
typedef struct {
               fichero  Fichero;
               octeto   DescriptorFichero[BDT_LONGDESCRIPTOR];
               memoria  DescriptoresCampo;
               memoria  InfoActual;
               entero   Actual;
               contador TotalCampo;
               entero   TotalRegistro;
               logico   Modificado;
               octeto   ModoApertura;
               entero   ComienzoRegistro;
               contador LongitudRegistro;
               } Bdt_st, *basedato;

/*--------------------------------------------------------------------
 * Variables globales
 *------------------------------------------------------------------*/

   /* Ninguna */

/*--------------------------------------------------------------------
 * Declaracin de funciones
 *------------------------------------------------------------------*/

basedato Bdt_CreaObjeto();
basedato Bdt_Abre();
void     Bdt_Cierra();
basedato Bdt_Crea();
void     Bdt_Destruye();
logico   Bdt_NombreDeCampo();
logico   Bdt_NumeroDeCampo();
logico   Bdt_LeeRegistro();
logico   Bdt_EscribeRegistro();
logico   Bdt_MarcaRegistro();
logico   Bdt_AgregaRegistro();
logico   Bdt_CampoNumero();
logico   Bdt_CampoNombre();
logico   Bdt_PonCampoNumero();
logico   Bdt_PonCampoNombre();
char     Bdt_TipoDeCampo();
contador Bdt_LongitudDeCampo();
contador Bdt_DecimalDeCampo();

/*--------------------------------------------------------------------
 * Estructura de los ficheros .DBF
 *
 * Un fichero .DBF se compone de una cabecera y los registros,
 * que son de longitud fija. Entre la cabecera y los registros puede
 * haber ms octetos, pero eso se sabe viendo la "longitud de cabecera",
 * informacin que ya viene reflejada en la cabecera.
 *
 * La cabecera se compone de un descriptor de fichero de 32 octetos
 * seguido de tantos descriptores de campo, de 32 octetos, como campos
 * tenga la base.
 *
 * En los datos que ocupan ms de un octeto, el menos significativo
 * se coloca primero. La interrogacin (?) significa que no conozco
 * la misin de ese dato.
 *
 * Esta es la estructura del descriptor de fichero:
 *
 * Despla-     Signo y
 * zamiento    Longitud     Significado
 *
 *    0        +   1        Versin de la base de datos:
 *                          0x03 -> Fichero sin memo
 *                          0x83 -> Fichero memo normal
 *                          0xF5 -> Fichero memo de FoxPro
 *                          0x8B -> Fichero memo de dBase IV
 *    1        +-  1        Ao de la ltima actualizacin, calculado como
 *                          Almacenado = 1900 - Real
 *    2        +-  1        Mes de la ltima actualizacin
 *    3        +-  1        Da de la ltima actualizacin
 *    4        +-  4        Nmero de registros
 *    8        +-  2        Longitud de la cabecera
 *   10        +-  2        Longitud de cada registro
 *   12        +-  2        Reservado
 *   14        +-  1        Indicador de transaccin comenzada (dBase IV)
 *   15        +-  1        Indicador de datos encriptados (dBase IV)
 *   16        +- 12        Reservado para LAN
 *   28        +-  1        Indicador MDX
 *   29        +-  3        Reservado
 *
 * Esta es la estructura del descriptor de campo:
 *
 * Despla-     Signo y
 * zamiento    Longitud     Significado
 *
 *    0        +- 11        Nombre del campo usado por dBase, incluye
 *                          espacio para el carcter NULO
 *   11        +-  1        Tipo de campo de dBase
 *   12        +-  2        Direccin del dato (?)
 *   14        +-  2        Ancho del campo (?)
 *   16        +   1        Ancho del campo en dBase
 *   17        +   1        Nmero de decimales en dBase
 *   18        +-  2        Reservado
 *   20        +-  8        Mximo valor del campo 'N'/'F' (?)
 *   28        +-  4        Reservado
 *
 * En cada registro el primer octeto se usa para indicar si el registro
 * est marcado como borrado. En ese caso, el octeto es '*'
 *------------------------------------------------------------------*/

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

/*--------------------------------------------------------------------
 * MACRO:    Bdt_Fichero()
 * OBJETIVO: Decir el fichero asociado con una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El fichero asociado
 * EJEMPLO:  Bdt_Fichero ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_Fichero(b)  ((b)->Fichero)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonFichero()
 * OBJETIVO: Poner el fichero asociado a una base de datos
 * ENTRADAS: La base de datos y el fichero
 * SALIDAS:  El fichero asociado
 * EJEMPLO:  Bdt_PonFichero ( Agenda,FicheroAgenda )
 *------------------------------------------------------------------*/
#define Bdt_PonFichero(b,f)  (((b)->Fichero)=(f))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_DescriptorFichero()
 * OBJETIVO: Decir la direccin de comienzo del descriptor de fichero
 *           de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  La direccin de memoria donde se almacena el descriptor
 * EJEMPLO:  Bdt_DescriptorFichero ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_DescriptorFichero(b)  ((b)->DescriptorFichero)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_DescriptoresCampo()
 * OBJETIVO: Decir la direccin de comienzo de los descriptores de campo
 *           de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  La direccin de memoria donde se almacenan los descriptores
 * EJEMPLO:  Bdt_DescriptoresCampo ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_DescriptoresCampo(b)  ((b)->DescriptoresCampo)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonDescriptoresCampo()
 * OBJETIVO: Poner la direccin de comienzo de los descriptores de campo
 *           de una base de datos
 * ENTRADAS: La base de datos y la direccin
 * SALIDAS:  La direccin de memoria donde se almacenan los descriptores
 * EJEMPLO:  Bdt_PonDescriptoresCampo ( Agenda, InfoCampos )
 *------------------------------------------------------------------*/
#define Bdt_PonDescriptoresCampo(b,d)  (((b)->DescriptoresCampo)=(d))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_InfoActual()
 * OBJETIVO: Decir la direccin de comienzo de la informacin del registro
 *           actual de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  La direccin de memoria donde se almacena el registro
 * EJEMPLO:  Bdt_InfoActual ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_InfoActual(b)  ((b)->InfoActual)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonInfoActual()
 * OBJETIVO: Poner la direccin de comienzo de la informacin del registro
 *           actual de una base de datos
 * ENTRADAS: La base de datos y la direccin
 * SALIDAS:  La direccin de memoria donde se almacena el registro
 * EJEMPLO:  Bdt_PonInfoActual ( Agenda, InfoRegistro )
 *------------------------------------------------------------------*/
#define Bdt_PonInfoActual(b,d)  (((b)->InfoActual)=(d))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_Actual()
 * OBJETIVO: Decir el nmero de registro del registro actual de
 *           una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El entero que indica el nmero del registro actual
 * EJEMPLO:  Bdt_Actual ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_Actual(b)  ((b)->Actual)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonActual()
 * OBJETIVO: Poner el nmero de registro del registro actual de una
 *           base de datos
 * ENTRADAS: La base de datos y el entero
 * SALIDAS:  El entero que indica el nmero del registro actual
 * EJEMPLO:  Bdt_PonActual ( Agenda, Numero )
 *------------------------------------------------------------------*/
#define Bdt_PonActual(b,n)  (((b)->Actual)=(n))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_TotalCampo()
 * OBJETIVO: Decir el nmero de campos de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El contador que indica el nmero de campos
 * EJEMPLO:  Bdt_TotalCampo ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_TotalCampo(b)  ((b)->TotalCampo)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonTotalCampo()
 * OBJETIVO: Poner el nmero de campos de una base de datos
 * ENTRADAS: La base de datos y el contador
 * SALIDAS:  El contador que indica el nmero de campos
 * EJEMPLO:  Bdt_PonTotalCampo ( Agenda, Numero )
 *------------------------------------------------------------------*/
#define Bdt_PonTotalCampo(b,n)  (((b)->TotalCampo)=(n))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_TotalRegistro()
 * OBJETIVO: Decir el nmero de registros de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El entero que indica el nmero de registros
 * EJEMPLO:  Bdt_TotalRegistro ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_TotalRegistro(b)  ((b)->TotalRegistro)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonTotalRegistro()
 * OBJETIVO: Poner el nmero de registros de una base de datos
 * ENTRADAS: La base de datos y el entero
 * SALIDAS:  El entero que indica el nmero de registros
 * EJEMPLO:  Bdt_PonTotalRegistro ( Agenda, Numero )
 *------------------------------------------------------------------*/
#define Bdt_PonTotalRegistro(b,n)  (((b)->TotalRegistro)=(n))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_Modificado()
 * OBJETIVO: Decir si una base de datos ha sido modificada desde la ltima
 *           vez que se puso al da
 * ENTRADAS: La base de datos
 * SALIDAS:  Lgica
 * EJEMPLO:  Bdt_Modificado ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_Modificado(b)  ((b)->Modificado)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonModificado()
 * OBJETIVO: Anotar si la base de datos ha sido modificada o no
 * ENTRADAS: La base de datos y el valor lgico
 * SALIDAS:  El valor lgico
 * EJEMPLO:  Bdt_PonModificado ( Agenda, NO )
 *------------------------------------------------------------------*/
#define Bdt_PonModificado(b,v)  (((b)->Modificado)=(v))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_ModoApertura()
 * OBJETIVO: Decir el modo con que ha sido abierta una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El modo de apertura
 * EJEMPLO:  Bdt_ModoApertura ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_ModoApertura(b)  ((b)->ModoApertura)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonModoApertura()
 * OBJETIVO: Anotar el modo con que ha sido abierta una base de datos
 * ENTRADAS: La base de datos y el modo
 * SALIDAS:  El modo
 * EJEMPLO:  Bdt_PonModoApertura ( Agenda, BDT_LECTURA )
 *------------------------------------------------------------------*/
#define Bdt_PonModoApertura(b,m)  (((b)->ModoApertura)=(m))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_ComienzoRegistro()
 * OBJETIVO: Decir la posicin de comienzo de los registros de una base de
 *           datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El entero que indica la posicin
 * EJEMPLO:  Bdt_ComienzoRegistro ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_ComienzoRegistro(b)  ((b)->ComienzoRegistro)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonComienzoRegistro()
 * OBJETIVO: Anotar la posicin donde comienzan los registros de una base
 *           de datos
 * ENTRADAS: La base de datos y el entero
 * SALIDAS:  El entero que indica la posicin
 * EJEMPLO:  Bdt_PonComienzoRegistro ( Agenda, Comienzo )
 *------------------------------------------------------------------*/
#define Bdt_PonComienzoRegistro(b,n)  (((b)->ComienzoRegistro)=(n))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_LongitudRegistro()
 * OBJETIVO: Decir la longitud de cada registro de una base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El contador que indica la longitud
 * EJEMPLO:  Bdt_LongitudRegistro ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_LongitudRegistro(b)  ((b)->LongitudRegistro)

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonLongitudRegistro()
 * OBJETIVO: Anotar la longitud de cada registro de una base de datos
 * ENTRADAS: La base de datos y el contador
 * SALIDAS:  El contador que indica la longitud
 * EJEMPLO:  Bdt_PonLongitudRegistro ( Agenda, Longitud )
 *------------------------------------------------------------------*/
#define Bdt_PonLongitudRegistro(b,l)  (((b)->LongitudRegistro)=(l))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_AnoUltimo()
 * OBJETIVO: Decir el ao de la ltima modificacin de una
 *           base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El contador que indica el ao
 * EJEMPLO:  Bdt_AnoUltimo ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_AnoUltimo(b)  ((contador) (1900+Bdt_DescriptorFichero(b)[1]))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonAnoUltimo()
 * OBJETIVO: Poner el ao de la ltima modificacin de una base de datos
 * ENTRADAS: La base de datos y el ao
 * SALIDAS:  El ao - 1900
 * EJEMPLO:  Bdt_PonAnoUltimo ( Agenda, 1994 )
 *------------------------------------------------------------------*/
#define Bdt_PonAnoUltimo(b,a)  (Bdt_DescriptorFichero(b)[1]=(char)((a)-1900))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_MesUltimo()
 * OBJETIVO: Decir el mes de la ltima modificacin de una
 *           base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El octeto que indica el mes
 * EJEMPLO:  Bdt_MesUltimo ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_MesUltimo(b)  ((octeto) (Bdt_DescriptorFichero(b)[2]))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonMesUltimo()
 * OBJETIVO: Poner el mes de la ltima modificacin de una base de datos
 * ENTRADAS: La base de datos y el mes
 * SALIDAS:  El mes
 * EJEMPLO:  Bdt_PonMesUltimo ( Agenda, 12 )
 *------------------------------------------------------------------*/
#define Bdt_PonMesUltimo(b,m)  (Bdt_DescriptorFichero(b)[2]=(char)(m))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_DiaUltimo()
 * OBJETIVO: Decir el da de la ltima modificacin de una
 *           base de datos
 * ENTRADAS: La base de datos
 * SALIDAS:  El octeto que indica el da
 * EJEMPLO:  Bdt_DiaUltimo ( Agenda )
 *------------------------------------------------------------------*/
#define Bdt_DiaUltimo(b)  ((octeto) (Bdt_DescriptorFichero(b)[3]))

/*--------------------------------------------------------------------
 * MACRO:    Bdt_PonDiaUltimo()
 * OBJETIVO: Poner el da de la ltima modificacin de una base de datos
 * ENTRADAS: La base de datos y el da
 * SALIDAS:  El Dia
 * EJEMPLO:  Bdt_PonDiaUltimo ( Agenda, 31 )
 *------------------------------------------------------------------*/
#define Bdt_PonDiaUltimo(b,d)  (Bdt_DescriptorFichero(b)[3]=(char)(d))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_ActivoRegistro()
 * OBJETIVO: Decir si el registro en memoria est activo (es
 *           decir: no est marcado como borrado)
 * ENTRADAS: La base de datos
 * SALIDAS:  Lgica indicando si el registro est activo
 * EJEMPLO:  Bdt_ActivoRegistro (Agenda)
 *------------------------------------------------------------------*/
#define Bdt_ActivoRegistro(b)  (Bdt_InfoActual(b)[0]!='*')

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_LimpiaRegistro()
 * OBJETIVO: Limpiar el registro en memoria
 * ENTRADAS: La base de datos
 * SALIDAS:  Ninguna
 * EJEMPLO:  Bdt_LimpiaRegistro (Agenda)
 *------------------------------------------------------------------*/
#define Bdt_LimpiaRegistro(b)  (Mem_Asigna(Bdt_InfoActual(b),' ',  \
                                Bdt_LongitudRegistro(b)))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_BorraRegistro()
 * OBJETIVO: Marcar un registro como borrado
 * ENTRADAS: La base de datos y el nmero de registro
 * SALIDAS:  Lgica indicando si el registro se ha borrado
 * NOTAS:    1. Los registros se cuentan a partir de 0
 *           2. El registro no se borra fsicamente, slo
 *              se marca
 *           3. El registro actual en memoria queda ste
 * EJEMPLO:  Bdt_BorraRegistro (Agenda,1)
 *------------------------------------------------------------------*/
#define Bdt_BorraRegistro(b,n)  (Bdt_MarcaRegistro(b,n,'*'))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Bdt_RecuperaRegistro()
 * OBJETIVO: Recuperar un registro que estaba marcado como
 *           borrado
 * ENTRADAS: La base de datos y el nmero de registro
 * SALIDAS:  Lgica indicando si el registro se ha recuperado
 * NOTAS:    1. Los registros se cuentan a partir de 0
 *           2. El registro actual en memoria queda ste
 * EJEMPLO:  Bdt_RecuperaRegistro (Agenda,1)
 *------------------------------------------------------------------*/
#define Bdt_RecuperaRegistro(b,n)  (Bdt_MarcaRegistro(b,n,' '))

#endif /* _BASEDATO_ */