/*--------------------------------------------------------------------
 * FICHERO:       Indice.h
 * OBJETIVO:      Definir el objeto "Indice"
 * IDENTIFICADOR: Ind
 * AUTOR:         Pedro Reina
 * FECHA:         V.4.8.1995
 * OBJETOS UTILIZADOS: Memoria, Carcter, Cadena, Usuario, Fichero
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones pblicas
 *
 *   Ind_LongitudClave()     Indice.h
 *   Ind_Abre()              IndAbre.c
 *   Ind_Cierra()            Indice.h
 *   Ind_Primero()           IndPrime.c
 *   Ind_Clave()             IndClave.c
 *   Ind_Ultimo()            IndUltim.c
 *   Ind_Siguiente()         IndSigte.c
 *   Ind_Anterior()          IndAnter.c
 *   Ind_Busca()             IndBusca.c
 *   Ind_Crea()              IndCrea.c
 *   Ind_Inserta()           IndInser.c
 *------------------------------------------------------------------*/

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

/*--------------------------------------------------------------------
 * Funciones privadas
 *
 *   Ind_Fichero()           Indice.h
 *   Ind_PonFichero()        Indice.h
 *   Ind_ModoApertura()      Indice.h
 *   Ind_PonModoApertura()   Indice.h
 *   Ind_LongitudClave()     Indice.h
 *   Ind_PonLongitudClave()  Indice.h
 *   Ind_Pagina()            Indice.h
 *   Ind_Nivel()             Indice.h
 *   Ind_PonNivel()          Indice.h
 *   Ind_LeePagina()         IndLeePa.c
 *   Ind_EscribePagina()     IndEscPa.c
 *   Ind_NuevaPagina()       IndNuePa.c
 *   Ind_MaxNivel()          Indice.h
 *   Ind_PonMaxNivel()       Indice.h
 *   Ind_DirItem()           Indice.h
 *   Ind_PonDirItem()        Indice.h
 *   Ind_DirPosicion()       Indice.h
 *   Ind_PonDirPosicion()    Indice.h
 *   Ind_MaxItem()           Indice.h
 *   Ind_PonMaxItem()        Indice.h
 *   Ind_Desplazamiento      Indice.h
 *   Ind_PonDesplazamiento   Indice.h
 *   Ind_Item()              Indice.h
 *   Ind_PonItem()           Indice.h
 *   Ind_Posicion()          Indice.h
 *   Ind_PonPosicion()       Indice.h
 *   Ind_Registro()          IndRegis.c
 *   Ind_PonRegistro()       IndPonRe.c
 *   Ind_PaginaApuntada()    IndPagAp.c
 *   Ind_PonPaginaApuntada() IndPonPA.c
 *   Ind_Clave()             IndClave.c
 *   Ind_PonClave()          IndPonCl.c
 *   Ind_CreaObjeto()        IndCreOb.c
 *   Ind_Destruye()          IndCreOb.c
 *   Ind_IncrementaNivel()   IndIncNi.c
 *   Ind_DecrementaNivel()   IndDecNi.c
 *   Ind_IncrementaItem()    Indice.h
 *   Ind_DecrementaItem()    Indice.h
 *   Ind_ClavesPagina()      Indice.h
 *   Ind_PonClavesPagina()   Indice.h
 *   Ind_AlmacenaClave()     IndAlmCl.c
 *-----------------------------------------------------------------*/

#ifndef _INDICE_
#define _INDICE_

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

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

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

#define IND_LECTURA       (octeto)0
#define IND_ACTUALIZACION (octeto)1

#define IND_PAGINA        1024        /* Octetos de una pgina      */
#define IND_MINNIVEL      10          /* Mnima cantidad de niveles */
#define IND_FUERA         (-1)        /* Fuera del rbol            */

#define IND_MAXCLAVE      100         /* Por qu tan  pequeo?     */

/*--------------------------------------------------------------------
 * Definicin del tipo "indice"
 *------------------------------------------------------------------*/
typedef struct {
               fichero   Fichero;
               octeto    ModoApertura;
               contador  LongitudClave;
               octeto    Pagina[IND_PAGINA];   /* Pgina en memoria       */
               contador  Nivel;                /* Nivel en el rbol       */
               contador  MaxNivel;
               contador  ClavesPagina;
               contador *DirItem;     /* Item en cada pgina del rbol    */
               entero   *DirPosicion; /* Direccin relativa en el fichero */
               } Ind_st, *indice;

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

   /* Ninguna */

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

indice Ind_CreaObjeto();
indice Ind_Abre();
indice Ind_Crea();
void   Ind_Cierra();
void   Ind_Destruye();
entero Ind_Registro();
void   Ind_PonRegistro();
entero Ind_PaginaApuntada();
void   Ind_PonPaginaApuntada();
logico Ind_LeePagina();
logico Ind_EscribePagina();
entero Ind_NuevaPagina();
logico Ind_IncrementaNivel();
logico Ind_DecrementaNivel();
logico Ind_Primero();
logico Ind_Ultimo();
logico Ind_Siguiente();
logico Ind_Anterior();
logico Ind_Inserta();
cadena Ind_Clave();
void   Ind_PonClave();
void   Ind_AlmacenaClave();

/*--------------------------------------------------------------------
 * Estructura de los ficheros .NTX
 *
 * Un fichero .NTX est organizado por "pginas" de 1024 octetos
 *
 * La primera pgina es la cabecera, que slo tiene 280 octetos tiles
 *
 * El resto de las pginas tiene estructura de rbol.
 *
 * En cada pgina se almacenan varios "items", que se componen de la clave,
 * el nmero de registro a que pertenece y punteros a otras pginas, que
 * permiten ir recorriendo el rbol.
 *
 * En los datos que ocupan ms de un octeto, el menos significativo
 * se coloca primero (formato Intel).
 *
 * Esta es la estructura del descriptor de fichero:
 *
 * Despla-     Signo y
 * zamiento    Longitud     Significado
 *
 *    0        +-  2        Indicador:   0x06 -> dBase / Clipper
 *    2        +-  2        Indicador:   0x01 -> Clipper
 *    4        +-  4        Desplazamiento a la pgina raz
 *    8        +-  4        Cabecera de lista de pginas sin usar
 *   12        +-  2        Longitud de cada item
 *   14        +-  2        Longitud de la clave que mantiene el ndice
 *   16        +-  2        Nmero de decimales en las claves numricas
 *   18        +-  2        Mximo nmero de claves en cada pgina
 *   20        +-  2        Claves en media pgina
 *   22        +-  256      Cadena que expresa la clave
 *  278        +-  2        Indicador de clave nica: 1 -> S, 0 -> No
 *
 * Esta es la estructura de cada pgina:
 *
 * Despla-     Signo y
 * zamiento    Longitud     Significado
 *
 *    0        +-  2        Nmero de claves reales en la pgina
 *    2        Variable     Vector de desplazamientos a cada item en
 *                          la pgina. Hay uno ms, porque el ltimo
 *                          tiene un significado distinto
 *             Variable     Vector de items
 *             +-  4        Posicin de la pgina de ndices a la que
 *                          hay que desplazarse si la clave buscada es
 *                          mayor que la mayor de la pgina (o 0)
 *
 * Cada item se compone de:
 *
 * Despla-     Signo y
 * zamiento    Longitud     Significado
 *
 *    0        +-  4        Posicin de la pgina de ndices a la que
 *                          hay que desplazarse si la clave buscada es
 *                          menor que la del item (o 0)
 *    4        +-  4        Nmero del registro (se empiezan a contar en 1)
 *    8        Variable     Clave (no est terminada en NULO)
 *------------------------------------------------------------------*/

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

/*--------------------------------------------------------------------
 * MACRO:    Ind_Fichero()
 * OBJETIVO: Decir el fichero asociado con un ndice
 * ENTRADAS: Un ndice
 * SALIDAS:  El fichero asociado
 * EJEMPLO:  Ind_Fichero ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Fichero(i)  ((i)->Fichero)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonFichero()
 * OBJETIVO: Anotar el fichero asociado con un ndice
 * ENTRADAS: Un ndice y un fichero
 * SALIDAS:  El fichero asociado
 * EJEMPLO:  Ind_PonFichero ( Agenda, Fichero )
 *------------------------------------------------------------------*/
#define Ind_PonFichero(i,f)  (((i)->Fichero)=(f))

/*--------------------------------------------------------------------
 * MACRO:    Ind_ModoApertura()
 * OBJETIVO: Decir el modo con que ha sido abierto un ndice
 * ENTRADAS: El ndice
 * SALIDAS:  El modo de apertura
 * EJEMPLO:  Ind_ModoApertura ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_ModoApertura(i)  ((i)->ModoApertura)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonModoApertura()
 * OBJETIVO: Anotar el modo con que ha sido abierto un ndice
 * ENTRADAS: El ndice y el modo
 * SALIDAS:  El modo
 * EJEMPLO:  Ind_PonModoApertura ( Agenda, IND_LECTURA )
 *------------------------------------------------------------------*/
#define Ind_PonModoApertura(i,m)  (((i)->ModoApertura)=(m))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Ind_LongitudClave()
 * OBJETIVO: Decir la longitud de la clave mantenida por
 *           el ndice
 * ENTRADAS: El ndice
 * SALIDAS:  La longitud de la clave
 * NOTA:     En la longitud no se incluye el NULO
 * EJEMPLO:  Ind_LongitudClave ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_LongitudClave(i)  ((i)->LongitudClave)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonLongitudClave()
 * OBJETIVO: Anotar la longitud de la clave mantenida por el ndice
 * ENTRADAS: El ndice y la longitud
 * SALIDAS:  La longitud
 * EJEMPLO:  Ind_PonLongitudClave ( Agenda, 40 )
 *------------------------------------------------------------------*/
#define Ind_PonLongitudClave(i,l)  (((i)->LongitudClave)=(l))

/*--------------------------------------------------------------------
 * MACRO:    Ind_Pagina()
 * OBJETIVO: Decir la direccin de la pgina que est en memoria
 * ENTRADAS: El ndice
 * SALIDAS:  La direccin
 * EJEMPLO:  Ind_Pagina ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Pagina(i)  ((i)->Pagina)

/*--------------------------------------------------------------------
 * MACRO:    Ind_Nivel()
 * OBJETIVO: Decir el nivel del rbol en que nos encontramos
 * ENTRADAS: El ndice
 * SALIDAS:  El nivel
 * NOTAS:    1. El nivel 0 es el de la raz del rbol
 *           2. Si no estamos en el rbol, el nivel es IND_FUERA
 * EJEMPLO:  Ind_Nivel ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Nivel(i)  ((i)->Nivel)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonNivel()
 * OBJETIVO: Anotar el nivel del rbol en que nos encontramos
 * ENTRADAS: El ndice y el nivel
 * SALIDAS:  El nivel
 * EJEMPLO:  Ind_PonNivel ( Agenda, 2 )
 *------------------------------------------------------------------*/
#define Ind_PonNivel(i,n)  (((i)->Nivel)=(n))

/*--------------------------------------------------------------------
 * MACRO:    Ind_ClavesPagina()
 * OBJETIVO: Decir cuntas claves caben en una pgina de un ndice
 * ENTRADAS: El ndice
 * SALIDAS:  El nmero de claves que caben en una pgina
 * EJEMPLO:  Ind_ClavesPagina ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_ClavesPagina(i)  ((i)->ClavesPagina)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonClavesPagina()
 * OBJETIVO: Poner el nmero de claves que caben en una pgina de un ndice
 * ENTRADAS: El ndice y el nmero de claves que caben en una pgina
 * SALIDAS:  El nmero de claves que caben en una pgina
 * EJEMPLO:  Ind_PonClavesPagina ( Agenda, 20 )
 *------------------------------------------------------------------*/
#define Ind_PonClavesPagina(i,c)  (((i)->ClavesPagina)=(c))

/*--------------------------------------------------------------------
 * MACRO:    Ind_MaxNivel()
 * OBJETIVO: Decir el mximo nivel del rbol al que se puede bajar
 * ENTRADAS: El ndice
 * SALIDAS:  El nivel mximo
 * EJEMPLO:  Ind_MaxNivel ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_MaxNivel(i)  ((i)->MaxNivel)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonMaxNivel()
 * OBJETIVO: Anotar el mximo nivel del rbol al que se puede bajar
 * ENTRADAS: El ndice y el mximo nivel
 * SALIDAS:  El mximo nivel
 * EJEMPLO:  Ind_PonMaxNivel ( Agenda, 2 )
 *------------------------------------------------------------------*/
#define Ind_PonMaxNivel(i,n)  (((i)->MaxNivel)=(n))

/*--------------------------------------------------------------------
 * MACRO:    Ind_DirItem()
 * OBJETIVO: Decir la direccin del vector donde se anotan los item en que
 *           nos encontramos en cada nivel
 * ENTRADAS: El ndice
 * SALIDAS:  La direccin
 * EJEMPLO:  Ind_DirItem ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_DirItem(i)  ((i)->DirItem)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonDirItem()
 * OBJETIVO: Anotar la direccin del vector donde se anotan los item en que
 *           nos encontramos en cada nivel
 * ENTRADAS: El ndice y la direccin
 * SALIDAS:  La direccin
 * EJEMPLO:  Ind_PonDirItem ( Agenda, NuevaDireccion )
 *------------------------------------------------------------------*/
#define Ind_PonDirItem(i,d)  (((i)->DirItem)=(d))

/*--------------------------------------------------------------------
 * MACRO:    Ind_DirPosicion()
 * OBJETIVO: Decir la direccin del vector donde se anotan las posiciones
 *           de las pginas que han sido leidas al navegar por el rbol
 * ENTRADAS: El ndice
 * SALIDAS:  La direccin
 * EJEMPLO:  Ind_DirPosicion ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_DirPosicion(i)  ((i)->DirPosicion)

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonDirPosicion()
 * OBJETIVO: Anotar la direccin del vector donde se anotan las posiciones
 *           de las pginas que han sido leidas al navegar por el rbol
 * ENTRADAS: El ndice y la direccin
 * SALIDAS:  La direccin
 * EJEMPLO:  Ind_PonDirPosicion ( Agenda, NuevaDireccion )
 *------------------------------------------------------------------*/
#define Ind_PonDirPosicion(i,d)  (((i)->DirPosicion)=(d))

/*--------------------------------------------------------------Olimpo
 * MACRO:    Ind_Cierra ()
 * OBJETIVO: Cerrar un ndice
 * ENTRADAS: El ndice
 * SALIDAS:  Ninguna
 * EJEMPLO:  Ind_Cierra ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Cierra(i)  (Fch_Cierra(Ind_Fichero(i)),Ind_Destruye(i))

/*--------------------------------------------------------------------
 * MACRO:    Ind_MaxItem()
 * OBJETIVO: Decir cul es la cantidad de items efectivos de la pgina
 *           que est en memoria
 * ENTRADAS: El ndice
 * SALIDAS:  La cantidad de items efectivos
 * EJEMPLO:  Ind_MaxItem ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_MaxItem(i)  (Mem_LeeContador(Ind_Pagina(i),MEM_INTEL))

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonMaxItem()
 * OBJETIVO: Poner la cantidad de items efectivos de la pgina
 *           que est en memoria
 * ENTRADAS: El ndice y la cantidad de items
 * SALIDAS:  La cantidad de items efectivos
 * EJEMPLO:  Ind_PonMaxItem ( Agenda, 15 )
 *------------------------------------------------------------------*/
#define Ind_PonMaxItem(i,c)  (Mem_EscribeContador(Ind_Pagina(i),MEM_INTEL,(c)))

/*--------------------------------------------------------------------
 * MACRO:    Ind_Desplazamiento()
 * OBJETIVO: Calcular el desplazamiento al ensimo item de la pgina en
 *           memoria
 * ENTRADAS: El ndice y el nmero de item
 * SALIDAS:  El desplazamiento
 * NOTAS:    1. Los items se cuentan a partir de 0
 *           2. No se comprueba que el item sea vlido
 * EJEMPLO:  Ind_Desplazamiento ( Agenda, 3 )
 *------------------------------------------------------------------*/
#define Ind_Desplazamiento(i,n)  (Mem_LeeContador(Ind_Pagina(i)+2+2*(n), \
                                  MEM_INTEL))

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonDesplazamiento()
 * OBJETIVO: Anotar el desplazamiento al ensimo item de la pgina en
 *           memoria
 * ENTRADAS: El ndice, el nmero de item y el desplazamiento
 * SALIDAS:  El desplazamiento
 * NOTAS:    1. Los items se cuentan a partir de 0
 *           2. No se comprueba que el item sea vlido
 * EJEMPLO:  Ind_PonDesplazamiento ( Agenda, 3, 500 )
 *------------------------------------------------------------------*/
#define Ind_PonDesplazamiento(i,n,d)  (Mem_EscribeContador(Ind_Pagina(i) \
                                       +2+2*(n), MEM_INTEL, d))
                                                   
/*--------------------------------------------------------------------
 * MACRO:    Ind_Item()
 * OBJETIVO: Decir cul es el item en que estamos situados en la pgina
 *           que est en memoria
 * ENTRADAS: El ndice
 * SALIDAS:  El item
 * EJEMPLO:  Ind_Item ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Item(i)  (Ind_DirItem(i)[Ind_Nivel(i)])

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonItem ()
 * OBJETIVO: Anotar el item en que estamos situados en la pgina
 *           que est en memoria
 * ENTRADAS: El ndice y el nmero de item
 * SALIDAS:  El item
 * EJEMPLO:  Ind_PonItem ( Agenda, 0 )
 *------------------------------------------------------------------*/
#define Ind_PonItem(i,n)  ((Ind_DirItem(i)[Ind_Nivel(i)])=(n))

/*--------------------------------------------------------------------
 * MACRO:    Ind_Posicion ()
 * OBJETIVO: Decir cul es la posicin relativa al comienzo del fichero
 *           de la pgina del nivel actual
 * ENTRADAS: El ndice
 * SALIDAS:  La posicin
 * EJEMPLO:  Ind_Posicion ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_Posicion(i)  (Ind_DirPosicion(i)[Ind_Nivel(i)])

/*--------------------------------------------------------------------
 * MACRO:    Ind_PonPosicion ()
 * OBJETIVO: Anotar la posicin relativa al comienzo del fichero
 *           de la pgina del nivel actual
 * ENTRADAS: El ndice y la posicin
 * SALIDAS:  La posicin
 * EJEMPLO:  Ind_PonPosicion ( Agenda, 2048 )
 *------------------------------------------------------------------*/
#define Ind_PonPosicion(i,d)  ((Ind_DirPosicion(i)[Ind_Nivel(i)])=(d))

/*--------------------------------------------------------------------
 * MACRO:    Ind_IncrementaItem ()
 * OBJETIVO: Aumentar en una unidad el item en que estamos situados en
 *           la pgina que est en memoria
 * ENTRADAS: El ndice
 * SALIDAS:  El nuevo valor del item
 * EJEMPLO:  Ind_IncrementaItem ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_IncrementaItem(i)  ((Ind_DirItem(i)[Ind_Nivel(i)])++)

/*--------------------------------------------------------------------
 * MACRO:    Ind_DecrementaItem ()
 * OBJETIVO: Disminuir en una unidad el item en que estamos situados en
 *           la pgina que est en memoria
 * ENTRADAS: El ndice
 * SALIDAS:  El nuevo valor del item
 * EJEMPLO:  Ind_DecrementaItem ( Agenda )
 *------------------------------------------------------------------*/
#define Ind_DecrementaItem(i)  ((Ind_DirItem(i)[Ind_Nivel(i)])--)

#endif /* _INDICE_ */