                    #####
                    #   #  #    ###  ##   ##  ###   ####
                    #   #  #     #   # # # #  #  #  #  #
                    #   #  #     #   #  #  #  ###   #  #
                    #####  ###  ###  #     #  #     ####

       ----------------------------------------------------------------
       Sistema de programacin en C multiplataforma orientado al objeto
       ----------------------------------------------------------------
       Versin 2.0               Pedro Reina                L.28.8.1995
       ----------------------------------------------------------------


Indice
======

 1. Presentacin
 2. Distribucin
 3. Garanta
 4. Reconocimiento legal
 5. Requerimientos
 6. Ficheros del disquete
 7. Instalacin
 8. Uso del sistema
 9. Descripcin del sistema
10. Relacin alfabtica de funciones
11. Descripcin interna
12. El programa de ayuda
13. El programa Zeus
14. Cmo hacer cambios
15. Normas de codificacin
16. Historia de las versiones
17. Errores
18. Futuras mejoras
19. Agradecimientos y bibliografa
20. Comentarios personales
21. Programa de demostracin




Presentacin
============

Cuando un programador en C va a desarrollar un programa de tamao medio se
enfrenta con el problema de usar slo funciones de la librera estndar C (y
conseguir que el programa sea porttil) o usar todas las posibilidades de su
compilador (y que su programa slo se pueda recompilar con ese compilador).
Olimpo proporciona un punto medio entre esas dos posibilidades, ya que ofrece
un conjunto de funciones mucho ms amplio que el de la librera estndar, pero
es fcilmente transportable a diferentes compiladores.

Si el programador desea que su programa funcione en varias plataformas
distintas puede optar por comprar una herramienta multiplataforma.  Existen
muchas en el mercado. La mayor parte de ellas son para programar en C o en C++.
Las ms baratas permiten compilar para MS-DOS, Microsoft Windows y Macintosh;
las ms caras tambin generan ejecutables para UNIX, en sus distintas
versiones, OS/2 y VMS. Normalmente necesitan un potente equipo para funcionar
con comodidad.

Olimpo tambin es una herramienta de desarrollo multiplataforma, que se puede
utilizar en QL y en PC, tanto en modo texto como en modo grfico. Permite
desarrollar cdigo en C, es orientada al objeto, pero funciona perfectamente en
equipos ms modestos.

Al contrario de la herramientas comerciales, que suelen ser de elevado precio,
Olimpo es de Dominio Pblico y se recomienda que los programas escritos con l
sean puestos tambin en este modo de distribucin.

Ha sido desarrollada ntegramente en espaol, tanto la documentacin como los
fuentes y los mensajes en pantalla.

El sistema se ha implementado orientado a objetos por ser un mtodo de
programacin muy flexible, potente y fcil de usar. Pero para programar usando
Olimpo no es necesario conocer programacin orientada a objetos, ya que se ha
usado de un modo muy sencillo. Es ms, un nefito despus de usar Olimpo
probablemente empiece a usar esta metodologa de un modo muy natural.

Una idea bsica en el desarrollo de Olimpo es la claridad del cdigo. La
prioridad principal es que todo el sistema sea simple, fcil de entender,
mantener y modificar.

El sistema Olimpo pretende, por tanto, facilitar la tarea de los programadores
en C que utilizan el espaol como lengua corriente. Las reas en las que su
utilizacin puede ser ms provechosa son:

* Aumentar la legibilidad del cdigo.
* Acortar el tiempo de desarrollo de aplicaciones.
* Reutilizar cdigo.
* Transportar programas entre plataformas.

Olimpo est disponible para el QL usando el compilador C68 y para PC usando
Turbo C++ como compilador de C. Pretendo escribir una versin sobre Linux.

El sistema es muy sencillo de usar, ya que consta tan slo de un fichero de
cabecera y un fichero de librera. Se entrega con documentacin, programa de
demostracin y fuentes.

Cualquier sugerencia, comentario o pregunta ser bien recibido. Estos son mis
datos:

Pedro Reina
c/ Marquesa de Argeso, 4
28019 Madrid
Espaa

Telfono: 565 17 59




Distribucin
============

Mi objetivo como autor de Olimpo es ayudar a todos los programadores que deseen
usarlo y conseguir que su distribucin sea lo ms amplia posible. Por tanto, he
decidido ponerlo en el Dominio Pblico. Naturalmente, eso no quiere decir que
renuncie a la propiedad intelectual de su autora. Es claro que el creador de
algo siempre tiene derechos sobre lo que hace. Simplemente, deseo que Olimpo se
pueda copiar con total libertad, sin necesidad de pagar ninguna cantidad ms
all de la estrictamente razonable para cubrir los gastos de copia, soporte y
envo.

Como con cualquier programa, es muy importante que en su distribucin no se
pierdan partes. Pido a todos los que copiis Olimpo que no os dejis ningun
fichero ni cambiis el orden de los mismos. Lo mejor es hacer una copia
idntica del disquete que hayis recibido, conservando incluso la etiqueta del
mismo, en la que va anotado el nmero de versin.

Si algn desarrollador desea entregar los fuentes de un programa que ha escrito
usando Olimpo, est claro que no puede cargar el disquete con todo el sistema,
ya que ocupara demasiado. En ese caso, creo que lo mejor es incluir el fichero
de cabecera y el de librera (con los que ya es posible compilar el programa)
y, opcionalmente, el de documentacin (con el que se puede entender la notacin
de Olimpo). Yo agradecera enormente que se comente que que se ha usado Olimpo
y cmo se puede obtener en su versin completa, ya que as se podra aumentar
su difusin.

Si escribs algn programa con Olimpo, est claro que es vuestro y podis hacer
con l lo que queris (faltara ms!), pero os sugiero que pensis la
posibilidad de ponerlo en el Dominio Pblico. Yo pienso que es conveniente que
las ideas se muevan libremente por todo el mundo, sin limitaciones. Cuando
recibo un programa que me gusta, me resulta agradable ver los fuentes y poderlo
usar sin limitaciones, de modo que procuro hacer lo mismo con los mos. Os he
convencido?

Si os ha llegado Olimpo y os ha gustado o, mejor an, lo habis llegado a usar,
me encantara que me lo hicirais saber. Si queris, mandadme una tarjeta
postal, preferiblemente con una vista de vuestra localidad, en la que figure
vuestro nombre y todo lo que queris comentarme. No puedo garantizar la
contestacin, pero lo intentar. Puedo entender cartas en espaol, ingls y
francs.




Garanta
========

Lo habitual en los creadores de programas es que no se hagan responsables de
los posibles daos que pudieran derivarse del uso de sus productos. Quiere
esto decir que no se fan de lo que han hecho? Desde luego que no, lo que pasa
es que la ingeniera de software es una de las ms complejas y es
extremadamente difcil demostrar que un programa est libre de errores.
Normalmente los programas comerciales tienen errores que no resultan vitales, y
desde luego no producen efectos desastrosos. Sera de primera pgina de un
peridico que usando un procesador de textos el monitor estallara o el disco
duro saliera volando.

Yo tambin me voy a curar en salud. Aunque no creo que tu ordenador se rompa
por culpa de usar Olimpo, no me hago responsable de lo que pueda ocurrir.
Olimpo se entrega tal cual y su utilizacin depende exclusivamente de las
personas que lo usen.

Naturalmente, si tienes algn problema con l, bien porque no est claro cmo
usarlo o porque descubras algn error, puedes ponerte en contacto conmigo y, en
la medida de mis posibilidades, intentar ayudarte.




Reconocimiento legal
====================

A lo largo de la documentacin de Olimpo se citan varios productos comerciales.
Algunos de ellos se citan en el apartado "Agradecimientos y bibliografa". Los
que no aparecen ah tambin son reconocidos por este autor, naturalmente. A
cada uno lo suyo, y especialmente a las marcas registradas. Si alguien opina
que su trabajo no ha sido reconocido, que me lo comunique, y en las siguientes
versiones de Olimpo aparecer la referencia.




Requerimientos
==============

Hay tres tipos distintos de requerimientos, y cada uno de ellos tiene que ser
explicado para QL y para PC.


Compilar con Olimpo en el QL
----------------------------

Necesitas tener en funcionamiento el compilador C68, para lo que es suficiente
algo de memoria extra, una disquetera de doble densidad y Toolkit II, aunque
siempre ser mejor tener ms memoria (640K o ms) y disqueteras ED o disco
duro. A partir de una configuracin de un QL con Gold Card y disqueteras HD te
sentirs cmodo trabajando con Olimpo.

Esta versin de Olimpo se ha compilado con C68 versin 4.03, pero probablemente
se pueda usar con versiones superiores.


Compilar con Olimpo en el PC
----------------------------

Necesitas tener en funcionamiento el compilador Turbo C++, para lo que basta un
PC basado en 8086 y un pequeo disco duro. A partir de un 386sx se trabaja
bastante bien con Olimpo. Para crear programas que utilicen el modo grfico es
necesario tener una tarjeta VGA.

Esta versin de Olimpo se ha compilado con Turbo C++ versin 1.01, pero
probablemente se pueda usar con versiones superiores.


Ejecutar programas en el QL
---------------------------

Los programas creados con Olimpo funcionan perfectamente en un QL bsico, sin
ningn tipo de ampliacin. Normalmente se recomienda tener disqueteras, algo de
memoria extra y Toolkit II. Si se utiliza el objeto Pantalla o cualquier otro
que lo use (que es lo ms habitual) la pantalla debe estar en modo de alta
resolucin (MODE 4). En principio, los programas escritos con Olimpo no pueden
operar en multitarea, pero el programador puede conseguirlo si es cuidadoso.


Ejecutar programas en el PC
---------------------------

Los programas creados con Olimpo funcionan perfectamente en un PC bsico con un
8086 y una sola disquetera. Para ejecutar programas que utilicen el modo
grfico es necesario tener una tarjeta VGA.


Recompilar Olimpo en el QL
--------------------------

Si quieres recompilar Olimpo para hacer alguna adaptacin que te interese
necesitas un QL con un procesador rpido, por lo menos una Gold Card, y un
disco duro, ya que los fuentes y los ficheros objeto que se usar para formar la
librera exceden de la capacidad de un disquete ED.


Recompilar Olimpo en el PC
--------------------------

Para recompilar Olimpo en un PC necesitas un procesador rpido, para no
aburrirte esperando. Con un 486 a 33MHz se va bastante bien, aunque puedes
tener un procesador ms lento si, a cambio, tienes ms paciencia.




Ficheros del disquete
=====================

Estn disponibles dos disquetes: uno para QL y otro para PC. La relacin de
ficheros es muy similar en los dos casos:

Disquete PC     Disquete QL

Leeme.txt       Leeme_txt
Lha213.exe      UnZip_exe
Sistema.lhz     Sistema_zip
Demo.lzh        Demo_zip
Fuente.lzh      Fuente_zip

Leeme.txt y Leeme_txt contienen unas pequeas instrucciones para poder
descomprimir los ficheros comprimidos y as acceder a la informacin.

Lha213.exe y UnZip_exe son los programas descompresores.

Sistema.lzh y Sistema_zip contienen los ficheros imprescindibles para usar
Olimpo. Se explican en el captulo "Instalacin".

Demo.lzh y Demo_zip contienen los ficheros de una demostracin prctica de uso
de Olimpo para escribir un programa. Se explican en el captulo "Programa de
demostracin".

Fuente.lzh y Fuente_zip contienen todos los fuentes de Olimpo, los ficheros que
sirven para validar el desarrollo y algunas utilidades para reconstruir los
ficheros del sistema. Se explican en los captulos "Descripcin interna", "El
programa de ayuda", "El programa Zeus" y "Cmo hacer cambios".


Los programas descompresores
----------------------------

El programa UnZip_exe viene con C68, con el nombre UNZIP2, de modo que quiz ya
lo tengas instalado. Si no es as, puedes ponerlo en algn directorio
fcilmente accesible o simplemente invocarlo desde el disquete.

El programa Lha213.exe viene en formato comprimido, y por lo tanto antes de
poder usarlo lo debes descomprimir. Para ello, coloca el fichero Lha213.exe en
el lugar donde desees tenerlo (por ejemplo, en el directorio C:\Uti\Lha) y
ejectalo tecleando

LHA213

Preguntar si quieres seguir adelante: contesta "Y". Obtendrs varios ficheros:
el ejecutable Lha.exe y tres ficheros de documentacin.

Los dos programas explican claramente cmo se usan, pero a continuacin puedes
ver la idea bsica para descomprimir un fichero.


Descomprimir en el QL
---------------------

Para descomprimir un fichero que se llame Ejemplo_zip en un disquete en FLP2_,
pon el disquete con Olimpo en FLP1_, un disquete formateado en FLP2_ y teclea

EW FLP1_UnZip_exe ; "-DFLP2_ FLP1_Ejemplo"


Descomprimir en el PC
---------------------

Para descomprimir un fichero que se llame Ejemplo.lzh, cpialo al al directorio
donde quieras colocarlo y, colocado en l, teclea

C:\UTI\LHA\LHA e Ejemplo


Observacin

En UNIX y MS-DOS se utiliza como separador entre el nombre de un fichero y su
extensin el carcter '.'. En QDOS y SMSQ el que se utiliza es '_'. A lo largo
de la documentacin se va a utilizar de modo general el '.', incluso para
nombrar ficheros QDOS, salvo en algunos casos en que se respetar el nombre
correcto.




Instalacin
===========

Descomprime el fichero Sistema_zip o el Sistema.lzh siguiendo las intrucciones
del captulo "Ficheros del disquete".

Obtendrs tres ficheros:

Olimpo.txt -> Documentacin de Olimpo.
Olimpo.h -> Fichero de cabecera.
Olimpo.lib (en el QL, libOlimpo_a) -> Fichero de librera.

Copia el fichero Olimpo.txt en algn directorio de fcil localizacin, porque
te vendr bien para consultarlo cuando lo necesites.

Copia el fichero Olimpo.h en el directorio donde estn los ficheros de cabecera
del compilador. Consulta la documentacin si no sabes cul es. Podra ser algo
as como C:\TC\INCLUDE en el PC y Win1_C68_Include en el QL.

Copia el fichero Olimpo.lib (en el QL, libOlimpo_a) en el directorio donde
estn los ficheros de librera del compilador. Consulta la documentacin si no
sabes cul es. Podra ser algo as como C:\TC\LIB en el PC y Win1_C68_Lib en el
QL.



Uso del sistema
===============

Para poder usar Olimpo slo hay que respetar dos cosas: incluir el fichero de
cabecera Olimpo.h en los fuentes y al montar usar el fichero de librera
Olimpo.lib. Eso es todo; por lo dems, hay que recordar que si escribes usando
Olimpo ests escribiendo cdigo en C, slo que dispones de muchas funciones que
simplifican la mayor parte de tu trabajo de programador.

Vamos a ver paso a paso el proceso necesario para compilar un programa usando
Olimpo:

1. Escribir antes del cdigo:

#include <Olimpo.h>

2. Si se utiliza el objeto Pantalla o cualquier otro que lo use (que es la
situacin ms habitual), hay que empezar por usar la funcin Pan_Define() y
terminar con Pan_Cierra(); ste es el esquema general:

   /* Tu cdigo */
Pan_Define (PAN_TEXTO);
   /* Tu cdigo */
Pan_Cierra();
   /* Tu cdigo */

3. Al montar, aadir Olimpo.lib.

Con Turbo C++, se puede usar esta orden:

TCC Programa Olimpo.lib

Con C68, sta:

EX CC; "Programa_c -lOlimpo"

La librera suministrada en la versin PC corresponde al modelo de memoria
"Small"; si se desea utilizar otro modelo, hay que volver a compilar la
librera. En la seccin "Cmo hacer cambios" se explica el mtodo.

He comprobado Olimpo con los modelos de memoria "Small" y "Large", pero el
modelo "Huge" me ha dado problemas insolubles por el momento. Es de suponer que
con el resto de modelos Olimpo funcione perfectamente.

Siguiendo estas instrucciones, el programa "Hola, mundo" se escribira as en
el sistema Olimpo:

#include <Olimpo.h>
main()
  {
  Pan_Define (PAN_TEXTO);
  Pan_PonTexto (10,30,"Hola, mundo");
  Usr_PulsaUnaTecla ("Programa concluido");
  Pan_Cierra ();
  return (0);
  }




Descripcin del sistema
=======================

El sistema est distribuido por objetos. Cada uno se ocupa de una parte de la
programacin, lo que facilita su uso. Los usuarios de Olimpo se pueden
acostumbrar fcilmente a ver agrupadas en un objeto un conjunto de funciones
relacionadas entre s.

No es necesario tener conocimientos de programacin orientada al objeto para
usar Olimpo, ya que los usuarios no usan ninguna de las caractersticas
especficas de la programacin orientada al objeto, como la herencia, el
polimorfismo, el sistema de mensajes. Sin embargo, s se benefician de la
encapsulacin (aunque no lo sepan), ya que Olimpo se encarga de aislar los
distintos aspectos de la programacin.

Cada objeto tiene un identificador de tres letras y todas las funciones, macros
y variables globales de ese objeto comienzan con el identificador. Hay muy
pocas excepciones: en el objeto General no se sigue esta regla y en los macros
del objeto Pantalla que sirven para designar los colores tampoco se usa el
identificador de tres letras.

Ya que los objetos son independientes entre s, la mejor manera de describir el
sistema es describir cada uno de los objetos que lo constituyen.


Nombres e identificadores
-------------------------

Nombre     Identificador

General        Gen
Memoria        Mem
Pantalla       Pan
Azar           Azr
Tiempo         Tim
Sonido         Son
Carcter       Car
Lista          Lis
Trozo          Trz
Zona           Zon
Cadena         Cad
Programa       Prg
Fecha          Fec
Tecla          Tec
Cuadro         Cdr
Regin         Reg
Usuario        Usr
Fichero        Fch
Men           Men
Configuracin  Cnf
BaseDato       Bdt
Memo           Mmo
Indice         Ind
Diblane        Dbn
Tiff           Tif


General
-------

La especificacin del ordenador objetivo se hace mediante la definicin del
macro OLIMPO_PC o del OLIMPO_QL. Se pueden utilizar para escribir distintas
versiones del cdigo que lo exija y, mediante compilacin condicional, mantener
un nico fuente.

Por ejemplo, deseamos que la variable Ancho tenga un valor distinto segn
estemos en el QL o en el PC. Se puede hacer as:

#ifdef OLIMPO_QL
  Ancho = 17;
#endif

#ifdef OLIMPO_PC
  Ancho = 23;
#endif

Se define el tipo de datos "logico", con sus valores SI y NO.

Se definen varios tipos para manejar los distintos valores numricos enteros
disponibles. Se pueden ver en esta tabla:

Tipo    Signo  Bits  Valor mnimo   Valor mximo

menudo    s     8   -128           127
octeto    no     8   0              255
contador  s    16   -32768         32767
contpos   no    16   0              65535
entero    s    32   -2147483648    2147483647
entpos    no    32   0              4294967295

Se define el tipo de datos "real", que es simplemente un alias de float, y
puede tener distinta precisin en distinto ordenador.

Se define la constante NULO, que es un alias de NULL (carcter nulo).

Se define la constante NIL, que es el 0 (se utiliza en LISP como fin de lista).
En Olimpo se usa a menudo para marcar el fin de una relacin de varios items.

Se definen las funciones Abs(), Max(), Min(), Signo() y DivEx().


Memoria
-------

El manejo de memoria RAM es vital para muchas aplicaciones. Este objeto se
encarga de manipular la memoria RAM del ordenador.

Se puede reservar una parte de la memoria con la funcin Mem_Crea(), ajustar la
parte reservada con Mem_Ajusta() y devolverla con Mem_Destruye(). Se puede
asignar un valor a todos los octetos reservados con Mem_Asigna(), copiar una
parte de memoria en otra usando Mem_Copia() y realizar intercambios de
contenidos con Mem_Intercambia() y Mem_IntercambiaLarga().

Existe una serie de funciones que permiten leer y escribir datos en memoria
vindolos como valores de tipo menudo, octeto, contador, contpos, entero y
entpos. Los valores que ocupan ms de 8 bits se pueden leer y escribir usando
formato Motorola o Intel; para indicar este aspecto se dispone de los macros
MEM_MOTOROLA y MEM_INTEL.


Pantalla
--------

Este objeto permite controlar la apariencia completa de la pantalla. La funcin
Pan_Define() permite iniciar los valores por defecto necesarios. Se utiliza un
parmetro, que puede ser PAN_TEXTO o PAN_GRAFICO, para indicar al PC si se
desea tener la pantalla en modo texto o en modo grfico. Esto permite incluir
grficos en el PC. ste debe tener tarjeta VGA. Si no se dispone de ella, el
sistema arranca en modo texto. El parmetro se debe incluir tambin cuando se
trabaja en el QL, y por compatibilidad, el comportamiento del programa ser
distinto segn se est utilizando el modo de texto o el modo grfico, incluso
en el QL, en el que en principio no hay diferencia alguna entre ambos modos.

La funcin Pan_Cierra() se utiliza normalmente al final de la aplicacin para
restaurar todo y volver al sistema operativo.

Es perfectamente posible usar en una parte central del programa Pan_Cierra() y
luego otra vez Pan_Define() para cambiar de modo, aunque el contenido de la
pantalla se perder.

En cualquier  momento se puede consultar el modo en que se encuentra la
pantalla mediante la funcin Pan_Modo().

La pantalla es de 24 filas numeradas de 0 a 23 comenzando por arriba y 80
columnas numeradas de 0 a 79 empezando por la izquierda.

Se dispone de 4 colores, definidos con los macros BLANCO, NEGRO, ROJO y VERDE.
Se manejan con las funciones Pan_Papel(), Pan_Tinta() y Pan_Color(). Estas
funciones conviene utilizarlas antes de escribir algo, ya que los colores de
papel y de tinta se cambian muy a menudo al llamar a otros objetos, de modo que
no hay ninguna garanta de que permanezcan como los determine el programador.

La funcin Pan_Cursor() controla la posicin del cursor.

La funcin Pan_CursorVisible() determina si el cursor se ve en la pantalla o
no. En el PC en modo grfico no est disponible el cursor.

Las funciones Pan_Texto(), Pan_Entero(), Pan_Caracter() y Pan_Real() permiten
escribir en la pantalla texto (cadenas), enteros de cualquier tipo (ya sea
logico, menudo, octeto, contador, contpos, entero o entpos), caracteres y
nmeros reales. Si en el QL se usa Pan_Real(), hay que montar tambin la
librera matemtica.

Las funciones Pan_PonTexto(), Pan_PonEntero(), Pan_PonCar() y Pan_PonReal()
colocan el cursor en la posicin indicada y luego escriben el texto, entero,
carcter o real. Si en el QL se usa Pan_PonReal(), hay que montar tambin la
librera matemtica.

Las funciones Pan_TextoControlado() y Pan_PonTextoContolado() permiten escribir
texto en la pantalla de modo que no se rebase cierta longitud.

Se puede activar o desactivar el modo de escritura resaltada con la funcin
Pan_Resalta(). La situacin normal es la de escritura resaltada desactivada,
as que es importante conectarla cuando se desee usar e, inmediatamente,
desconectarla.

La funcin Pan_Limpia() borra la pantalla completa del color actual del papel.

La funcin Pan_BorraLinea() borra una lnea con el color actual del papel.

La funcin Pan_Borra() borra una zona rectangular con el color indicado.

La funcin Pan_Mueve() permite mover el contenido de una zona rectangular hacia
arriba o hacia abajo.


Azar
----

Se pueden obtener nmeros enteros aleatorios en el margen que se desee. Basta
iniciar el generador al principio con Azr_Inicia() y luego ir pidiendo enteros
con Azr_Entero().


Tiempo
------

La funcin Tim_Crono() devuelve una referencia temporal de precisin de tipo
real. Si se restan dos valores devueltos por Tim_Crono(), se obtiene el tiempo
real transcurrido entre las dos llamadas.

La funcin Tim_Espera() obliga al programa a suspender su ejecucin un periodo
de tiempo determinado.

Se puede consultar el reloj del sistema, viendo el ao, mes, da, hora, minuto
y segundo en curso.


Sonido
------

Este objeto se encarga de las seales acsticas. Se pueden conectar con
Son_Enciende(), desconectar con Son_Apaga() y cambiar de estado con
Son_Cambia().

Para saber si el sonido est o no conectado se usa Son_Estado().

Las llamadas a las funciones de este objeto no provocan inmediatamente la
generacin del sonido, eso depender de si en ese momento est conectado o no.

Hay tres funciones con distintos sonidos: Son_Bien(), Son_Error() y
Son_MalaTecla(); cada una de ellas devuelve el estado en ese momento del
sonido.


Carcter
--------

Olimpo funciona sobre ordenadores que usan distintos juegos de caracteres, por
lo que no coinciden los valores de muchos caracteres y ni siquiera cules son.

Por otra parte, las normas lingsticas del espaol no son contempladas por el
orden de caracteres ASCII.

El objeto Carcter tiene en cuenta estos problemas y adems permite transformar
los caracteres de los juegos del PC, del QL y el ANSI.

Para que funcione bien, debe usarse el juego PC-8 en el PC, correspondiente a
la tabla 437.

Se define el tipo "caracter" para uniformizar el tratamiento de los "char" en
los dos ordenadores. Es importante usarlo, ya que la suposicin "carcter =
char" no tiene por qu ser cierta en el futuro. En el sistema UNICODE, cada
carcter ocupa 16 bits, no 8.

Las funciones Car_EsMayus() y Car_EsMinus() permiten saber si un determinado
carcter es una letra mayscula o minscula.

Las funciones Car_Mayus() y Car_Minus() convierten un carcter en su letra
mayscula o minscula correspondiente.

La funcin Car_Compara() realiza una comparacin por orden alfabtico de dos
caracteres usando las normas del espaol. Incidentalmente: he intentado
respetar las normas de otros idiomas, aunque no puedo garantizar que funcione
para todos.

Las funciones Car_ConvierteQLaPC() y Car_ConviertePCaQL() comunican los dos
juegos de caracteres, permitiendo hacer traducciones de un juego a otro.

Existen macros para manejar aquellos caracteres que tienen distinta
representacin interna en un juego que en otro. Son stos:

Vocales minsculas acentuadas (    ):
CAR_A_AGUDO CAR_E_AGUDO CAR_I_AGUDO CAR_O_AGUDO CAR_U_AGUDO

Vocales minsculas con acento grave (    ):
CAR_A_GRAVE CAR_E_GRAVE CAR_I_GRAVE CAR_O_GRAVE CAR_U_GRAVE

Vocales minsculas con acento circunflejo: (    )
CAR_A_CIRCUNFLEJO CAR_E_CIRCUNFLEJO CAR_I_CIRCUNFLEJO CAR_O_CIRCUNFLEJO
CAR_U_CIRCUNFLEJO

Vocales minsculas con diresis (    ):
CAR_A_DIERESIS CAR_E_DIERESIS CAR_I_DIERESIS CAR_O_DIERESIS CAR_U_DIERESIS

Vocales maysculas con diresis (  ):
CAR_MAY_A_DIERESIS CAR_MAY_O_DIERESIS CAR_MAY_U_DIERESIS

Vocales maysculas acentuadas ():
CAR_MAY_E_AGUDO

Las dos ees ( ):
CAR_N_TILDE CAR_MAY_N_TILDE

Las dos ces con cejilla ( ):
CAR_C_CEDILLA CAR_MAY_C_CEDILLA

Las aperturas de admiracin e interrogacin ( ):
CAR_ADMIRACION CAR_INTERROGACION

Contracciones latinas ( ):
CAR_AE CAR_MAY_AE

Letras griegas: (a b d f m p)
CAR_ALFA CAR_BETA CAR_DELTA CAR_FI CAR_MU CAR_PI

Smbolos matemticos ( ):
CAR_DIVISION CAR_ANGSTROM

Smbolos tipogrficos (  ):
CAR_COMILLA_ABRIR CAR_COMILLA_CERRAR CAR_FINPARRAFO

Smbolos monetarios (`  ):
CAR_LIBRA CAR_CENTAVO CAR_YEN

Flechas en las cuatro direcciones:
CAR_FLECHA_ARRIBA CAR_FLECHA_ABAJO CAR_FLECHA_DERECHA CAR_FLECHA_IZQUIERDA

Existe una tabla de caracteres muy utilizada y til: la tabla ANSI. Por
ejemplo, es la utilizada por defecto en Miscrosoft Windows. Para poder usarla,
Olimpo proporciona funciones para pasar de los conjuntos de caracteres del QL y
del PC al ANSI y viceversa. Son las funciones Car_ConvierteQLaANSI(),
Car_ConvierteANSIaQL(), Car_ConviertePCaANSI() y Car_ConvierteANSIaPC().


Lista
-----

Las listas encadenadas son una de las estructuras ms importantes en
informtica. Olimpo proporciona una implementacin muy sencilla de las listas.

sta es la estructura general de una lista:

  -------------          -------------                 -------------
  | Contenido |          | Contenido |                 | Contenido |
  |-----------|    /-->  |-----------|    /--> ... --> |-----------|
  | Siguiente | --/      | Siguiente | --/             | Siguiente | --> NIL
  -------------          -------------                 -------------

El tipo "lista" corresponde a estructuras como la de arriba. Con Lis_Crea() se
obtiene una lista con un solo nodo que no tiene contenido y que tiene como
siguiente nodo NIL, es decir: ninguno (o "tierra", como se dice a veces).

El "contenido" puede ser cualquier cosa, ya que lo que realmente se almacena es
un puntero a una direccin de memoria que haya sido reservada mediante
Mem_Crea(); por ejemplo, se puede almacenar una cadena creada por Cad_Crea() o
un diblane creado con Dbn_Crea(). Para anotar en el nodo recin creado el
contenido que se desee est la funcin Lis_PonContenido().

A continuacin hay que ir aadiendo ms nodos a la lista. Esto es ms sencillo,
porque las funciones Lis_Agrega() y Lis_AgregaFin() slo necesitan recibir la
lista a la que hay que aadir el nodo y el contenido del nuevo nodo; ellas se
encargar de crear el nuevo nodo, poner el contenido, aadir el nuevo nodo y
devuelven la lista resultante.

An ms sencillas de usar son las funciones Lis_Anota() y Lis_AnotaFin(), que
aaden un nuevo contenido a cualquier lista, sabiendo dnde deben anotarlo.

Para usar la lista hay que ir viendo su contenido con Lis_Contenido() y navegar
por la lista usando Lis_Siguiente().

Una lista se puede ordenar por cualquier criterio, puesto que la funcin
Lis_Ordena() utiliza para realizar la ordenacin una funcin proporcionada por
el programador.

Cuando la lista no sea necesaria, se libera la memoria que utiliza con
Lis_Destruye(), a la que basta darle el primer nodo, ya que ella va recorriendo
toda la lista liberando la memoria reservada para todos los nodos.


Trozo
-----

Cuando se invoca la funcin Trz_Crea(), una zona rectangular de pantalla se
queda en memoria y se devuelve una variable de tipo "trozo". Entonces es
posible volcar los datos otra vez a la pantalla con la funcin Trz_Restituye().
La posicin de los datos no tiene por qu ser la misma que la original, y es
posible usar Trz_Restituye() varias veces y por tanto reproducir en varias
posiciones distintas un mismo contenido. Para poder realizar la restitucin es
imprescindible que el modo de pantalla sea el mismo al crear el trozo que al
restituirlo.

Cuando no se necesite ms el trozo, se debe usar Trz_Destruye() para liberar la
memoria utilizada.


Zona
----

Este objeto es el encargado de los grficos. Slo se puede utilizar cuando la
pantalla est en modo grfico. Por lo tanto, en un PC que no disponga de
tarjeta grfica VGA no se puede usar este objeto.

Hay un tipo de datos llamado "zona" que permite manejar las posibilidades del
objeto.

Lo primero que hay que hacer es crear una zona mediante la funcin Zon_Crea().
Si no se puede crear, por falta de memoria o porque la pantalla no est en modo
grfico, esta funcin devuelve NIL.

A partir de ese momento, podemos acceder a cada pixel de la zona. Las funciones
Zon_AltoFisico() y Zon_AnchoFisico() dan las dimensiones de una zona en pixels.
Obviamente, la misma zona no tendr las mismas dimensiones en ordenadores
distintos, de ah la importancia de disponer de estas funciones.

Los pixels de la zona se numeran empezando en 0 de arriba hacia abajo y de
izquierda a derecha, como es lo habitual.

Se puede dibujar cada pixel de la zona mediante dos funciones, Zon_Pixel() y
Zon_PixelSeguro(). La diferencia entre ambas es que la primera comprueba que el
pixel pedido realmente existe en esa zona (si no existe, no lo dibuja) y la
segunda no. Por tanto, la primera es ms lenta; pero para usar la segunda hay
que estar seguro de que el pixel pedido pertenece a la zona.

Manejar una pantalla pixel a pixel es bastante lento, de modo que he buscado
una manera ms rpida de manejar fsicamente las zonas. El resultado de la
bsqueda ha sido el manejo de cada "oxel" de la zona. Tanto la tarjeta VGA como
la memoria grfica del QL manejan los pixels agrupados de ocho en ocho. Pues
bien, cada grupo de 8 pixels manejado globalmente por el hardware es lo que he
denominado oxel. Siempre agrupa 8 pixels en lnea, nunca en columnas.

Se puede saber cuntos oxels de ancho tiene una zona se usa la funcin
Zon_AnchoEnOxel(). La altura de una zona no se puede medir en oxels.

Para manejar cada oxel de una zona se usan las funciones Zon_Oxel() y
Zon_OxelSeguro(). La diferencia entre ambas es la misma que para los pixels.
Estas dos funciones necesitan conocer no slo el color que hay que usar, sino
tambin cules de los pixels del oxel se desean poner de ese color. Esto se
indica mediante las "mscaras". Una mscara es simplemente un octeto, ocho
bits. Cuando el bit es un 1, el pixel correspondiente cambia al color pedido;
cuando es 0, no cambia. Por ejemplo, si deseamos cambiar de color el pixel ms
a la izquierda y el ms a la derecha de un oxel, la mscara debe ser 10000001,
que en decimal es 129, y en hexadecimal 0x81.

Tambin es posible dibujar en una zona usando modos de direccionamiento
relativos, mediante una escala que puede definir el programador. Con la funcin
Zon_Escala() se define qu dimensiones (relativas) se quiere dar a la zona y
dnde se desea que est situado el origen de coordenadas.

Las funciones Zon_Alto(), Zon_Ancho(), Zon_OrigenX() y Zon_OrigenY() devuelven
los valores vigentes en ese momento para la altura, anchura y posicin del
origen relativos de una zona.

Las funciones Zon_Punto() y Zon_PuntoSeguro() dibujan un punto del color
especificado, La funcin Zon_Linea() una lnea entre dos puntos y la
Zon_Bloque() un bloque rectangular relleno.

Cuando una zona ya no sea necesaria, hay que liberar la memoria que usa con la
funcin Zon_Destruye().


Cadena
------

El manejo de cadenas en C no es muy cmodo. He implementado este objeto usando
cadenas de asignacin dinmica, por ser una aproximacin ms flexible que las
cadenas de asignacin esttica.

He definido el tipo "cadena", que es simplemente un puntero a caracter; es
decir, si declaramos una variable como tipo cadena, no se reserva
automticamente memoria para ella, sino que hay que pedirla explcitamente y
luego liberarla. Muchas de las funciones definidas en este objeto y otros que
lo utilizan realizan la reserva de memoria sin que el programador se tenga que
ocupar; en estos casos, el programador debe ser quien disponga la destruccin
de estas cadenas cuando no sean necesarias.

Esto permite trabajar de dos formas distintas con las cadenas:

Por ser punteros, se pueden asignar a cadenas constantes. Por ejemplo, es
vlido:

cadena Cad;
Cad = "Esto es una cadena";
 /* Aqu tu cdigo */
Cad = "Y esto es otra cadena";

Y por otro lado, se pueden crear cadenas de la longitud precisa en cada
momento:

cadena Cad;
Cad = Cad_Crea (10);
Cad_Copia (Cad,"0123456789");
 /* Aqu tu cdigo */
Cad_Destruye (Cad);

Las funciones ms importantes son las que reservan memoria y la liberan.

Cad_Crea() reserva memoria para una cadena de la longitud indicada (reservando
un carcter ms para el carcter NULL, que en Olimpo se llama NULO), le da el
valor inicial de cadena vaca y devuelve la direccin de memoria reservada (que
es un puntero a caracter). La memoria as reservada no se libera
automticamente al salir de la funcin en la que se reserva, de modo que es
responsabilidad del programador destruirla cuando no sea necesaria.

Cad_Destruye() es la encargada de liberar la memoria reservada mediante
Cad_Crea(). Tambin se debe usar para liberar memoria reservada por otras
funciones.

El resto de las funciones son de uso directo y puedes consultar cmo se usan y
cules son en el captulo "Relacin alfabtica de funciones".


Programa
--------

Este objeto se ocupa simplemente de presentar informacin sobre el programa en
la lnea superior de la pantalla. Si no se utiliza, se dispone de una lnea ms
para el desarrollo del programa.

La funcin que presenta esta informacin es Prg_Presenta().


Fecha
-----

Se pueden crear objetos de tipo "fecha" de tres formas distintas:

1. Dndole el ao, el mes y el da a la funcin Fec_Crea().

2. Dndole una cadena con la fecha en formato AAAAMMDD a la funcin
Fec_LeeCadena().

3. Con la funcin Fec_Hoy().

Una vez creada una fecha se pueden consultar sus datos con Fec_Ano(), Fec_Mes()
y Fec_Dia(), se puede calcular el da de la semana con Fec_DiaSemana() y se
puede convertir en cadena con Fec_Cadena().

Se puede calcular el nmero de das que hay entre dos fechas con
Fec_Diferencia().

Cuando una fecha ya no sea necesaria, se debe destruir con Fec_Destruye().


Tecla
-----

He definido el tipo "tecla" y la funcin Tec_Pulsada() como bsicos para poder
olvidar las grandes diferencias en el tratamiento de las teclas en los diversos
sistemas operativos. En Olimpo slo hay que saber que Tec_Pulsada() devuelve la
tecla que haya pulsado el usuario, que pertenece al tipo "tecla". Junto con
eso, hay toda una coleccin de macros que definen cada tecla; por ejemplo, la
tecla F1 est definida con el macro TEC_F1, y el programador no necesita
conocer qu codigo (o cdigos) asigna el sistema operativo a F1 (cada uno lo
hace de una forma distinta).

Si la tecla corresponde con un carcter, se pueden utilizar los macros que
definen los caracteres para compararlos con la tecla pulsada. Por ejemplo, si
el programador quiere comprobar si el usuario ha pulsado la tecla '' puede
usar

if ( Tec_Pulsada() == (tecla) CAR_N_TILDE )
 { /* Cdigo */ }

Se puede consultar en cualquier momento cul fue la ltima tecla pulsada por el
usuario con Tec_Ultima(), lo que resulta muy cmodo para obtener informacin en
funciones muy alejadas de aquellas en las que el programa interacta con el
usuario.

Se puede pedir una tecla que pertenezca a un determinado rango con
Tec_Validada() e incluso hacerlo con vuelta inmediata, si no hay tecla correcta
disponible, con Tec_ValidadaRapido().

Las funciones Tec_Mayus() y Tec_Minus() convierten una tecla en su
correspondiente mayscula o minscula.

Se puede saber si una tecla est dentro de un conjunto predeterminado con
Tec_Pertenece().

Para saber si se puede procesar alguna tecla est la funcin Tec_Disponible().

La funcin Tec_FijadoMayus() permite saber si est activo la funcin de fijado
de maysculas del teclado.

No he definido macros para todas las teclas que son posibles en cada ordenador,
sino slo para aquellas que son perfectamente compatibles. En el PC existen
algunas teclas que no estn disponibles en el QL, pero con funciones que
normalmente en el QL se asignan a determinadas combinaciones de tecla.

sta es la lista de los macros que corresponden a distintas pulsaciones en PC y
en QL:

Macro           Tecla PC    Tecla QL

TEC_INICIO      Inicio      ALT/Cursor izquierda
TEC_FIN         Fin         ALT/Cursor derecha
TEC_AVPAG       AvPg       ALT/Cursor abajo
TEC_REPAG       RePg       ALT/Cursor arriba
TEC_CTRL_INICIO CTRL/Inicio CTRL/ALT/Cursor izquierda
TEC_CTRL_FIN    CTRL/Fin    CTRL/ALT/Cursor derecha
TEC_CTRL_AVPAG  CTRL/AvPg  CTRL/ALT/Cursor abajo
TEC_CTRL_REPAG  CTRL/RePg  CTRL/ALT/Cursor arriba
TEC_INSERTAR    Insert      MAY/FijaMaysculas
TEC_SUPRIMIR    Supr        CTRL/Cursor derecha
TEC_RETROCESO   Retroceso   CTRL/Cursor izquierda

Y sta es la de teclas comunes:

TEC_ESC  TEC_ENTER  TEC_ESPACIO
TEC_ARRIBA  TEC_ABAJO  TEC_IZQUIERDA  TEC_DERECHA
TEC_TAB  TEC_MAY_TAB
TEC_A ... TEC_Z
TEC_MAY_A ... TEC_MAY_Z
TEC_0  TEC_1 ... TEC_9
TEC_CTRL_A ... TEC_CTRL_Z
TEC_ALT_A ... TEC_ALT_Z
TEC_ALT_0  TEC_ALT_1 ... TEC_ALT_9
TEC_F1  TEC_F2  TEC_F3  TEC_F4  TEC_F5
TEC_MAY_F1 TEC_MAY_F2 EC_MAY_F3 EC_MAY_F4 EC_MAY_F5
TEC_CTRL_F1  TEC_CTRL_F2  TEC_CTRL_F3  TEC_CTRL_F4
TEC_ALT_F1 TEC_ALT_F2 TEC_ALT_F3 TEC_ALT_F4 TEC_ALT_F5


Cuadro
------

Se pueden representar cuadros, cajas y lneas de cualquier color disponible y
en dos grosores distintos con las funciones Cdr_Dibuja(), Cdr_Caja() y
Cdr_Linea().

Los grosores de las lneas se indican con los macros CDR_SIMPLE y CDR_DOBLE.

Es posible construir una lista de cadenas que forman un cuadro con la funcin
Cdr_Construye(). El cuadro se formar correctamente cuando se use el juego de
caracteres PC-8 (el normal en un PC). La mayora de las impresoras disponen de
este juego.


Regin
------

Este objeto permite manejar de una manera ms sencilla muchas de las funciones
ya disponibles en otros objetos. Tambin permite escribir cdigo respecto a
posiciones de pantalla relativas y no absolutas.

Primero hay que obtener una variable de tipo "region" usando la funcin
Reg_Crea(). Las posiciones absolutas donde se ha creado siempre son accesibles
mediante las funciones Reg_FilSup(), Reg_FilInf(), Reg_ColIzq() y Reg_ColDer().
Las dimensiones en caracteres de una regin se consultan con Reg_Ancho() y
Reg_Alto().

Los colores de papel y de tinta que se usarn para escribir en una regin se
fijan con Reg_Papel(), Reg_Tinta() y Reg_Color(). Una vez fijados los valores
de papel y tinta, siempre se usarn stos, hasta que se vuelvan a cambiar con
las mismas funciones, para escribir mediante las funciones de este objeto. Es
decir, aunque cambien los colores al escribir con funciones del objeto
Pantalla, se reinstauran al escribir mediante las funciones del objeto Regin.

Las funciones que efectivamente escriben en una regin son Reg_PonCar(),
Reg_PonTexto(), Reg_PonEntero() y Reg_PonReal(), que tienen las mismas
explicaciones que las del objeto pantalla salvo que las posiciones en las que
escriben son relativas a la esquina superior derecha de la regin y no de la
pantalla. Si se utiliza Reg_PonReal() en el QL, hay que montar la librera
matemtica.

Tambin se dispone de Reg_TextoCentrado(), que escribe un texto en una lnea de
la regin centrndolo respecto a las columnas izquerda y derecha. El cursor
tambin es posible situarlo en una regin con Reg_Cursor().

Se puede poner un borde a toda la regin con Reg_Borde(), limpiar toda la
regin o slo la parte interna con Reg_Limpia() y Reg_LimpiaInterior().

Se puede guardar en memoria el contenido completo de la regin con Reg_Lee() y
volverlo a escribir ms adelante con Reg_Escribe().

Por ltimo, cuando no se vaya a usar ms una regin , hay que destruirla con
Reg_Destruye().


Usuario
-------

Las dos ltimas filas de la pantalla estn reservadas para interactuar con el
usuario. Esas filas se pueden borrar de cualquier color con Usr_BorraZona().

Para mandar un mensaje y esperar que se pulse alguna tecla est la funcin
Usr_PulsaUnaTecla(). Para escribir dos lneas de explicaciones se usa
Usr_Indica(). Para informarle de algo que est sucediendo y que debe esperar se
usa Usr_Informa(). Cuando hay un error se puede usar Usr_Avisa(). Cuando debe
responder s o no a una pregunta se usa Usr_Consulta(). Si durante la ejecucin
del programa se produce un error irrecuperable, que obligar a abortar la
ejecucin, se puede usar la funcin Usr_ErrorFatal().

El usuario puede editar un nmero (de tipo contador) con Usr_Entero(), una
cadena simple con Usr_Texto() y una cadena ms compleja, formada por varias
lneas, con Usr_Edita().


Fichero
-------

El acceso a ficheros se realiza mediante este objeto. Primero hay que abrir un
fichero mediante las funciones Fch_Abre(), Fch_AbreLeer(), Fch_AbreGrabar() y
Fch_AbreActualizar(), que devuelven una variable de tipo "fichero". Con las
funciones Fch_Manejador() y Fch_NombreReal() simpre se puede acceder al puntero
a FILE que est usando C para acceder al fichero fsico y el nombre real con
que se abri el fichero.

Si se desea, se puede comprobar si existe un fichero antes de decidir si
abrirlo o crearlo, mediante Fch_Existe().

La funcin Fch_Abre() permite abrir un fichero con cualquier modo de los
admitidos por C, pero es ms recomendable usar alguna de las otras tres. La
funcin Fch_AbreLeer() permite abrir un fichero para leer datos de l, la
funcin Fch_AbreGrabar() crearlo para grabar datos y la Fch_AbreActualizar()
abrirlo para leer sus datos y modificarlos. Ambas cosas se pueden hacer en modo
texto y en modo binario, y para indicarlo estn los macros FCH_TEXTO y
FCH_BINARIO. Naturalmente, esta distincin es necesaria por culpa del MS-DOS;
de hecho, en el QL no hay ninguna diferencia entre los dos modos.

Una vez abierto un fichero, se pueden leer y escribir lneas con Fch_LeeLinea()
y Fch_EscribeLinea() y grupos de octetos con Fch_LeeOcteto() y
Fch_EscribeOcteto().

Se puede mover la posicin de lectura y escritura en el fichero con las
funciones Fch_Coloca() y Fch_ColocaFinal(). La posicin en la que se est
situado dentro de un fichero se puede conocer con Fch_Posicion().

Las funciones se encargan de gestionar los errores que se puedan producir. Por
ejemplo, al llamar a Fch_Borra(), primero se pide confirmacin al usuario,
luego se comprueba la existencia del fichero y por ltimo se emite un mensaje
indicando si ha sido posible el borrado o no.

La funcin Fch_ListaNombre() devuelve una lista con los nombres de los ficheros
de un directorio que corresponden a una determinada "mscara". He aqu unos
ejemplos:

"*.txt" -> Todos los ficheros del directorio actual que tienen extensin "txt".

"Cap?.c" -> Todos los ficheros del directorio actual que tienen extensin "c" y
cuyo nombre comienza con "Cap" y un carcter ms.

Cuando se ha terminado de trabajar con un fichero, hay que cerrarlo con
Fch_Cierra().

Existen dos funciones para manejar fcilmente el hecho de que el separador
entre un nombre de fichero y su extensin cambie entre sistemas operativos. La
funcin Fch_Separador() da el carcter empleado como separador y la funcin
Fch_Nombre() da el nombre completo que tendr un fichero a partir de su nombre
y su extensin.


Men
----

Olimpo puede manejar dos tipos de mens: unos muy sencillos de usar en los que
el sistema se ocupa de todo y otros ms potentes en los que se pueden
especificar muchas caractersticas.

Los mens sencillos pueden ser horizontales y verticales. Slo hay que
preocuparse de asignar la zona de la pantalla en la que se desea que aparezca
el men, el objeto se ocupa de la colocacin. Las opciones pueden llevar una
tecla caliente, un atajo o "hotkey", que permite elegir la opcin simplemente
pulsando esa tecla. Para indicar cul es, se utiliza el carcter '>' antes de
la letra en la llamada al objeto. Las funciones Men_Horizontal() y
Men_Vertical() son las que manejan estos mens.

La otra manera de manejar mens consiste en crearlos, otorgarles las
caractersticas deseadas, usarlos y por ltimo destruirlos.

Un men se crea con Men_Crea(). Esta es una funcin compleja, porque hay muchas
posibilidades distintas para un men: las opciones pueden leerse de un vector
de cadenas, de una lista de cadenas o generarse mediante una funcin definida
por el programador. En el caso de que las opciones se pasen con un vector de
cadenas, el men puede ser, adems, horizontal o vertical.

Cuando el men est creado se pueden cambiar los colores que debe usar con la
funcin Men_Color(), especificar qu teclas, adems de las habituales ENTER y
ESC, servirn para salir del men con Men_TeclaSi() y Men_TeclaNo(), consultar
el texto de una opcin con Men_Texto() y poner y quitar a una opcin la
categora de disponible con Men_Disponible().

Cuando el men est preparado se puede usar de tres formas distintas:
escribindolo con Men_Escribe(), que devuelve el control inmediatamente,
mostrando las distintas opciones con Men_Muestra() y pidiendo al usuario que
elija una opcin con Men_Ejecuta().

Por ltimo, cuando el men ya no sea necesario, se debe destruir con
Men_Destruye().


Configuracin
-------------

Este objeto permite leer informacin de un fichero filtrando todos los
comentarios que se hayan escrito en l. El programador debe decidir despus
cmo lee la informacin entregada por el objeto, que lo hace en forma de
cadena.

En los ficheros de configuracin se considera lnea de comentario toda aquella
que tenga un '*' (asterisco) como primer carcter, aunque haya caracteres en
blanco antes de l.

Tambin se pueden poner comentarios dentro de una lnea poniendo "//" (doble
barra). Todo lo que haya a continuacin, se considera comentario.

Las lneas en blanco se ignoran.

Para leer un fichero de configuracin hay que usar la funcin Cnf_Abre(), que
devuelve una variable de tipo "config". Entonces se puede ir leyendo lnea a
lnea con Cnf_Lee(); si es necesario, se puede consultar qu numero de lnea
del fichero se est procesando con la funcin Cnf_Linea(). Por fin se cierra
con Cnf_Cierra().


BaseDato
--------

Este objeto permite crear, leer y modificar bases de datos en formato
compatible "xBase", es decir, compatible con las distintas generaciones del
programa dBase y sus derivados: dBase III, dBase III+, dBase IV, Clipper,...

Una base de datos se puede crear con la funcin Bdt_Crea() y abrir con
Bdt_Abre(). Estas funciones devuelven un tipo "basedato", que es necesario usar
en las futuras referencias a la base de datos. La base de datos se puede abrir
de modo que slo admite lecturas si se usa el macro BDT_LECTURA o bien de modo
que admite modificaciones si se usa el macro BDT_MODIFICACION.

Una vez creada o abierta es posible acceder a sus registros. Las funciones
Bdt_LeeRegistro() y Bdt_EscribeRegistro() se encargan de leer y escribir cada
registro en una base de datos utilizando como referencia el nmero del
registro. Los registros se empiezan a numerar en 0, y el nmero total de ellos
se puede consultar con Bdt_TotalRegistro(). Es importante resaltar que el
nmero de orden de un registro se refiere exclusivamente al orden fsico en el
fichero, y nunca al orden relativo que puede tener cuando, mediante un fichero
externo de ndices, estn ordenados de alguna forma. Se puede aadir un nuevo
registro con Bdt_AgregaRegistro().

Siempre se mantiene en memoria un registro, de modo que el contenido de sus
campos se puede leer y modificar. La funcin Bdt_LimpiaRegistro() borra el
contenido del registro en memoria. Para saber cul es el nmero
el nmero del registro en memoria se usa la funcin Bdt_Actual().

Hay dos maneras de acceder al contenido de un campo: mediante su nmero y
mediante su nombre. Los campos estn numerados a partir de cero; su nmero
total se obtiene mediante la funcin Bdt_TotalCampo(). Es ms rpido usar los
campos por su nmero, con las funciones Bdt_CampoNumero() y
Bdt_PonCampoNumero(), aunque suele ser ms legible usar los campos por su
nombre, con las funciones Bdt_CampoNombre() y Bdt_PonCampoNombre(). Es posible
averiguar el nombre de cada uno de los campos a partir de su nmero, usando
Bdt_NombreDeCampo() y el nmero que tiene un campo a partir de su nmero con
Bdt_NumeroDeCampo().

Tambin se puede examinar la estructura de la base de datos, viendo las
caractersticas de cada campo: su tipo, longitud y cantidad de lugares para
cifras decimales. Las funciones Bdt_TipoDeCampo(), Bdt_LongitudDeCampo(),
Bdt_DecimalDeCampo() dan estos valores.

Las bases de datos mantienen la fecha de la ltima modificacin. Olimpo permite
acceder a esta fecha con las funciones Bdt_AnoUltimo(), Bdt_MesUltimo() y
Bdt_DiaUltimo().

Los registros de una base de datos pueden estar "marcados para borrar", que
quiere decir simplemente que tienen una marca especial que indica que son
susceptibles de ser borrados fsicamente del fichero cuando se realice la
operacin especfica correspondiente. Un registro se puede marcar para borrar
mediante la fucin Bdt_BorraRegistro() y es posible eliminar la marca con la
funcin Bdt_RecuperaRegistro(). La funcin Bdt_ActivoRegistro() permite
consultar si un registro est marcado para borrar.

Cuando se termine de usar una base de datos, se debe cerrar con Bdt_Cierra().
Esto es imprescindible ya que, si no se hace, algunos datos no quedarn
actualizados en el fichero correspondiente.


Memo
----

Este objeto permite acceder al contenido de los ficheros memo que tienen
algunas bases de datos xBase. Los ficheros memo del dBase IV no se pueden leer
con Olimpo, ya que tienen un formato distinto de los dems, pero dBase IV s
puede leer los ficheros memo creados con Olimpo.

Un fichero memo se lee con Mmo_Abre() y se crea con Mmo_Crea(), que devuelven
una variable de tipo "memo".

Los registros individuales se leen con Mmo_Lee() y se escriben con
Mmo_Escribe(). Se pueden aadir nuevos registros con Mmo_Agrega().

El fichero memo hay que cerrarlo cuando no se utilice con Mmo_Cierra().

El programador es responsable de leer y escribir en la base de datos dbf los
valores de los nmeros de registro del fichero dbt.


Indice
------

Este objeto es un complemento del objeto BaseDato. Con l se pueden crear y
mantener ficheros de ndice que permiten navegar por una base de datos usando
un determinado orden. El formato de los ndices es el "NTX", que es el que
utiliza el lenguaje "Clipper".

Para usar un ndice primero hay que abrirlo mediante Ind_Abre(), que devuelve
un tipo "indice" que hay que usar en las siguientes referencias al fichero
recin abierto. Se puede abrir de dos formas, diferenciadas por los macros
IND_LECTURA e IND_MODIFICACION. Si se abre de este ltimo modo, es posible
aadir nuevos datos.

Hay cuatro funciones que permiten navegar por los ndices: Ind_Primero(),
Ind_Ultimo(), Ind_Siguiente() e Ind_Anterior(). Todas ellas devuelven un valor
lgico que indica si se ha podido completar con xito la operacin requerida y
adems devuelven, modificando dos parmetros de entrada, el nmero de registro
y la clave de clasificacin correspondientes al ndice encontrado.

La longitud de la clave que devuelven las cuatro funciones se puede conocer de
antemano mediante la funcin Ind_LongitudClave().

Se puede buscar rpidamente una referencia mediante la funcin Ind_Busca().

Cuando no se necesite ms el ndice, se debe liberar la memoria utilizada
invocando la funcin Ind_Cierra().

Para crear los ndices hay que usar la funcin Ind_Crea(), ir aadiendo los
datos con Ind_Inserta() y al terminar usar Ind_Cierra().


Diblane
-------

La palabra diblane quiere decir "DIbujo en BLAnco y NEgro". Este objeto permite
crear, modificar y mostrar dibujos que estn formados por slo dos colores,
conocidos como el color de fondo y el color de figura.

Primero hay que crear un "diblane" usando la funcin Dbn_Crea(). Se puede
acceder a cada punto del dibujo usando Dbn_Punto() y cambiar el valor de un
punto con Dbn_PonPunto(). La direccin de memoria donde se encuentra el dibujo
es accesible mediante Dbn_Dato(), lo que permite, por ejemplo, leer dibujos
desde ficheros de grficos. El tamao en octetos ocupado por la imagen viene
dado por la funcin Dbn_Tamano(). Las dimensiones del dibujo siempre se pueden
consultar con las funciones Dbn_Ancho(), Dbn_Alto() y Dbn_AnchoEnOxel().

El dibujo completo se puede modificar con las funciones Dbn_Invierte(),
Dbn_ReflejaHorizontal() y Dbn_ReflejaVertical().

El dibujo se puede ver en una pantalla grfica con Dbn_Coloca() y
Dbn_Muestra().

La funcin Dbn_Edita() permite una edicin interactiva de un dibujo que no sea
grande en una pantalla grfica.

Cuando el diblane ya no sea necesario, hay que destruirlo usando la funcin
Dbn_Destruye().


Tiff
----

Los ficheros TIFF son uno de los formatos ms utilizados para manejar grficos
bitmaps. El objeto tiff permite crear y leer ficheros TIFF. Por el momento,
slo se pueden manejar imgenes en blanco y negro sin comprimir.

Un fichero TIFF puede contener ms de una imagen. Aunque habitualmente los
programas comerciales slo manejan la primera de ellas, Olimpo permite leer y
crear ficheros con varias imgenes.

Cada imagen puede estar formada por varias bandas, y este objeto permite
acceder a las imgenes y crearlas de forma global o banda a banda. Normalmente
hacerlo de una manera u otra depende de la cantidad de memoria disponible.

Existen dos modos completamente distintos de usar este objeto: leyendo ficheros
ya existentes o creando ficheros nuevos. Las funciones que se usan de un modo
no se pueden usar con el otro.

Cuando se quiere leer un fichero TIFF hay que empezar por abrirlo usando la
funcin Tif_Abre(), que devuelve una variable de tipo "tiff". En ese momento se
est en condiciones de manejar la primera de las imgenes del fichero, pero la
funcin Tif_Siguiente() hace que se pase a tratar la siguiente imagen del
fichero (si la hay). Cuando se est situado en una imagen, se pueden consultar
sus datos ms importantes usando las funciones Tif_TotalBanda(), Tif_Alto(),
Tif_Ancho(), Tif_BitsPorPixel(), Tif_Compresion(), Tif_Interpretacion(),
Tif_MuestrasPorPixel(), Tif_Tamano() y Tif_TamanoBanda(). Las funciones
Tif_LeeBandaBN() y Tif_LeeImagenBN() son las que se encargan de leer los datos
que forman las bandas o la imagen completa. Cuando se terminen las lecturas en
un fichero TIFF, hay que cerrarlo y destruir la variable "tiff" usando la
funcin Tif_Cierra().

Cuando se quieren almacenar una o ms imgenes en un fichero TIFF, hay que
empezar por crearlo con la funcin Tif_Crea(), que devuelve una variable de
tipo "tiff". Para almacenar cada una de las imgenes es posible usar dos
mtodos: a) usar la funcin Tif_EscribeImagenBN(); b) empezar por usar la
funcin Tif_EscribeDirectorioBN() y luego usar tantas veces como bandas se
quiera que tenga la imagen la funcin Tif_EscribeBandaBN(). Cuando se hayan
escrito todas las imgenes que se desee, hay que cerrar el fichero TIFF y
destruir la variable "tiff" usando Tif_Cierra().


Y ahora qu mas?

Para ampliar informacin sobre el uso de los objetos, consulta el captulo
"Relacin alfabtica de funciones" y mira el fichero de demostracin (Demo.c) y
los de validacin de funciones (V???.c)




Relacin alfabtica de funciones
================================


FUNCION:  Abs()
OBJETIVO: Calcular el valor absoluto de un nmero
ENTRADAS: Un nmero
SALIDAS:  El valor absoluto
NOTA:     El argumento se evala dos veces
EJEMPLO:  Abs(-3)

FUNCION:  Azr_Entero ()
OBJETIVO: Obtener un nmero entero aleatorio en un
          rango especificado
ENTRADAS: Los valores ms bajo y ms alto admitidos
SALIDAS:  Un nmero entero entre los extremos
          (ambos inclusive)
EJEMPLOS: Azr_Entero (0,100)
          Azr_Entero (-10,10)

FUNCION:  Azr_Inicia ()
OBJETIVO: Iniciar el generador con un nmero aleatorio
ENTRADAS: Ninguna, se lee el reloj del sistema
SALIDAS:  Ninguna
EJEMPLO:  Azr_Inicia ()

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)

FUNCION:  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)

FUNCION:  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 )

FUNCION:  Bdt_AgregaRegistro()
OBJETIVO: Agregar un registro desde memoria al fichero,
          ponindolo al final de ste
ENTRADAS: La base de datos y una variable donde dejar el
          nmero de registro
SALIDAS:  Lgica indicando si el registro se ha escrito. En
          la variable queda indicado el nmero de registro
NOTA:     Los registros se cuentan a partir de 0
EJEMPLO:  Bdt_AgregaRegistro (Agenda,&Numero)

FUNCION:  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 )

FUNCION:  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)

FUNCION:  Bdt_CampoNombre()
OBJETIVO: Dar el contenido de un campo a partir de su nombre
ENTRADAS: La base de datos, el nombre del campo y una cadena
          donde dejar el contenido
SALIDAS:  Lgica indicando si el campo existe. La cadena
          queda rellena
NOTA:     La funcin no comprueba la longitud de la cadena;
          el programador debe asegurarse de que es
          suficientemente larga para contener el contenido
          del campo
EJEMPLO:  Bdt_CampoNombre (Agenda,"EDAD",Aux)

FUNCION:  Bdt_CampoNumero()
OBJETIVO: Dar el contenido de un campo a partir de su nmero
ENTRADAS: La base de datos, el nmero del campo y una cadena
          donde dejar el contenido
SALIDAS:  Lgica indicando si el campo existe. La cadena
          queda rellena
NOTAS:    1. Los campos se numeran a partir de 0
          2. La funcin no comprueba la longitud de la
             cadena; el programador debe asegurarse de que
             es suficientemente larga para contener el
             contenido del campo
EJEMPLO:  Bdt_CampoNumero (Agenda,1,Aux)

FUNCION:  Bdt_Cierra()
OBJETIVO: Cerrar una base de datos
ENTRADAS: La base de datos
SALIDAS:  Ninguna
EJEMPLO:  Bdt_Cierra ( Agenda )

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

FUNCION:  Bdt_DecimalDeCampo()
OBJETIVO: Decir el nmero de decimales de un campo a partir
          de su nmero
ENTRADAS: La base de datos y el nmero de campo
SALIDAS:  Un nmero indicando el nmero de decimales del
          campo. Si el campo no existe, se devuelve 0
NOTA:     Los campos se numeran desde 0
EJEMPLO:  Bdt_DecimalDeCampo (Agenda,1)

FUNCION:  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 )

FUNCION:  Bdt_EscribeRegistro()
OBJETIVO: Escribir un registro desde memoria al fichero
ENTRADAS: La base de datos y el nmero de registro
SALIDAS:  Lgica indicando si el registro se ha escrito.
NOTA:     Los registros se cuentan a partir de 0
EJEMPLO:  Bdt_EscribeRegistro (Agenda,1)

FUNCION:  Bdt_LeeRegistro()
OBJETIVO: Leer un registro desde el fichero a memoria
ENTRADAS: La base de datos y el nmero de registro
SALIDAS:  Lgica, que indicando si el registro se ha ledo.
NOTA:     Los registros se cuentan a partir de 0
EJEMPLO:  Bdt_LeeRegistro (Agenda,1)

FUNCION:  Bdt_LimpiaRegistro()
OBJETIVO: Limpiar el registro en memoria
ENTRADAS: La base de datos
SALIDAS:  Ninguna
EJEMPLO:  Bdt_LimpiaRegistro (Agenda)

FUNCION:  Bdt_LongitudDeCampo()
OBJETIVO: Decir la longitud de un campo a partir de su nmero
ENTRADAS: La base de datos y el nmero de campo
SALIDAS:  Un nmero indicando la longitud del campo. Si el
          campo no existe, se devuelve 0
NOTA:     Los campos se numeran desde 0
EJEMPLO:  Bdt_LongitudDeCampo (Agenda,1)

FUNCION:  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 )

FUNCION:  Bdt_NombreDeCampo()
OBJETIVO: Decir el nombre de un campo a partir de su nmero
ENTRADAS: La base de datos, el nmero de campo y la cadena
          donde dejar el nombre
SALIDAS:  Lgica indicando si el campo existe. La cadena
          queda rellena
EJEMPLO:  Bdt_NombreDeCampo (Agenda,1,Aux)
NOTAS:    1. La cadena reservada debe tener 11 octetos
             (o ms)
          2. Los campos se numeran desde 0

FUNCION:  Bdt_NumeroDeCampo()
OBJETIVO: Hallar el nmero de un campo a partir de su nombre
ENTRADAS: La base de datos, una variable donde dejar el
          nmero y una cadena indicando el nombre
SALIDAS:  Lgica indicando si el campo existe. El nmero
          queda relleno
EJEMPLO:  Bdt_NumeroDeCampo (Agenda,&Numero,Nombre)

FUNCION:  Bdt_PonCampoNombre()
OBJETIVO: Poner el contenido de un campo dado su nombre
ENTRADAS: La base de datos, el nombre del campo y una cadena
          con el contenido
SALIDAS:  Lgica indicando si el campo existe.
NOTA:     La funcin no comprueba la longitud de la cadena;
          el programador debe asegurarse de que no es
          ms larga que la longitud del campo
EJEMPLO:  Bdt_PonCampoNombre (Agenda,"EDAD"," 35")

FUNCION:  Bdt_PonCampoNumero()
OBJETIVO: Poner el contenido de un campo dado su nmero
ENTRADAS: La base de datos, el nmero del campo y una cadena
          con el contenido
SALIDAS:  Lgica indicando si el campo existe.
NOTAS:    1. Los campos se numeran a partir de 0
          2. La funcin no comprueba la longitud de la
             cadena; el programador debe asegurarse de que
             no es ms larga que la longitud del campo
EJEMPLO:  Bdt_PonCampoNumero (Agenda,1,"Alberto")

FUNCION:  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)

FUNCION:  Bdt_TipoDeCampo()
OBJETIVO: Decir el tipo de un campo a partir de su nmero
ENTRADAS: La base de datos y el nmero de campo
SALIDAS:  Un carcter indicando el tipo de campo. Si el campo
          no existe, se devuelve NULO
NOTA:     Los campos se numeran desde 0
EJEMPLO:  Bdt_TipoDeCampo (Agenda,1)

FUNCION:  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 )

FUNCION:  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 )

FUNCION:  Cad_Cambia()
OBJETIVO: Cambiar en una cadena un carcter por otro
ENTRADAS: Cadena destino, carcter viejo, carcter nuevo
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_Cambia (Cadena,'a','b')

FUNCION:  Cad_CarPertenece ()
OBJETIVO: Averiguar si un caracter pertenece a una cadena
ENTRADAS: La cadena y el caracter
SALIDA:   La posicin que ocupa el carcter en la cadena, o 0
NOTA:     Se empieza a contar en 1
EJEMPLO:  Cad_CarPertenece (Nombre,'a')

FUNCION:  Cad_Compara()
OBJETIVO: Comparar dos cadenas alfabticamente segn el
          criterio del idioma espaol
ENTRADAS: El nmero
SALIDAS:  Un contador que expresa el resultado de
              la comparacin:
            Si es negativo, la primera cadena debe ir antes
              que la segunda
            Si es cero, las dos cadenas pueden ir en
              cualquier orden
            Si es positivo, la primera cadena debe ir despus
              que la segunda
EJEMPLO:  Cad_Compara ("Cao","Cazo")

FUNCION:  Cad_ConvierteANSIaPC()
OBJETIVO: Convertir una cadena del juego de caracteres
          ANSI al del PC
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConvierteANSIaPC (Cadena)

FUNCION:  Cad_ConvierteANSIaQL()
OBJETIVO: Convertir una cadena del juego de caracteres
          ANSI al del QL
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConvierteANSIaQL (Cadena)

FUNCION:  Cad_ConviertePCaANSI()
OBJETIVO: Convertir una cadena del juego de caracteres
          del PC al ANSI
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConviertePCaANSI (Cadena)

FUNCION:  Cad_ConviertePCaQL()
OBJETIVO: Convertir una cadena del juego de caracteres
          del PC al del QL
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConviertePCaQL (Cadena)

FUNCION:  Cad_ConvierteQLaANSI()
OBJETIVO: Convertir una cadena del juego de caracteres
          del QL al ANSI
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConvierteQLaANSI (Cadena)

FUNCION:  Cad_ConvierteQLaPC()
OBJETIVO: Convertir una cadena del juego de caracteres
          del QL al del PC
ENTRADAS: La cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_ConvierteQLaPC (Cadena)

FUNCION:  Cad_Copia()
OBJETIVO: Copiar una cadena en otra
ENTRADAS: La cadena destino y la cadena origen
SALIDAS:  La cadena destino
EJEMPLO:  Cad_Copia (Nombre,"Eustaquio")

FUNCION:  Cad_Crea()
OBJETIVO: Reservar memoria para almacenar una cadena
ENTRADAS: El nmero mximo de caracteres de la cadena
SALIDAS:  Una cadena
NOTAS:    1. Se reserva espacio automticamente para el NULO
          2. La cadena queda iniciada a cadena vaca
          3. La cadena devuelta hay que destruirla cuando no
             sea necesaria
EJEMPLO:  Cad_Crea (80)

FUNCION:  Cad_Destruye()
OBJETIVO: Liberar la memoria reservada para una cadena
ENTRADAS: La cadena
SALIDAS:  Ninguna
EJEMPLO:  Cad_Destruye (Cadena)

FUNCION:  Cad_Duplica()
OBJETIVO: Duplicar una cadena
ENTRADAS: Una cadena
SALIDAS:  Una nueva cadena con el mismo contenido que
          la entrada
NOTA:     La cadena devuelta hay que destruirla cuando no
          sea necesaria
EJEMPLO:  Cad_Duplica ("Artesonado")

FUNCION:  Cad_Entero()
OBJETIVO: Convertir un nmero en una cadena
ENTRADAS: El nmero
SALIDAS:  La cadena
NOTAS:    1. La cadena devuelta hay que destruirla cuando
             no sea necesaria
          2. El nmero se evala dos veces
EJEMPLO:  Cad_Entero (130)

FUNCION:  Cad_Igual()
OBJETIVO: Indicar si dos cadenas son iguales
ENTRADAS: Las dos cadenas
SALIDA:   Lgica
EJEMPLO:  Cad_Igual (Nombre,"Eustaquio")

FUNCION:  Cad_Longitud()
OBJETIVO: Calcular la longitud de una cadena
ENTRADAS: Una cadena
SALIDAS:  Su longitud
EJEMPLO:  Cad_Longitud (Nombre)

FUNCION:  Cad_Mayus()
OBJETIVO: Pasar a maysculas todos los caracteres de
          una cadena
ENTRADAS: Una cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_Mayus (Cadena)

FUNCION:  Cad_Minus()
OBJETIVO: Pasar a minsculas todos los caracteres de
          una cadena
ENTRADAS: Una cadena
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_Minus (Cadena)

FUNCION:  Cad_Mueve()
OBJETIVO: Mover hacia la derecha todos los caracteres de una
          cadena desde una posicin determinada, cuidando
          que la longitud no exceda un cierto mximo
ENTRADAS: La cadena, la posicin y el mximo
NOTA:     Las posiciones se cuentan a partir de cero
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_Mueve (Cadena,2,40)

FUNCION:  Cad_PrimerUtil()
OBJETIVO: Decir la posicin del primer carcter de una
          cadena que no sea ni blanco, ni tabulador, ni
          retorno de carro ni nueva lnea
ENTRADAS: La cadena
SALIDA:   La posicin que ocupa el primer carcter til, o 0
NOTA:     Se empieza a contar en 1
EJEMPLO:  Cad_PrimerUtil ( "   Ahora" )

FUNCION:  Cad_QuitaCar()
OBJETIVO: Quitar el caracter que ocupa una determinada
          posicin en una cadena
ENTRADAS: La cadena y la posicin que hay que suprimir
NOTA:     Las posiciones se cuentan a partir de cero
SALIDAS:  La cadena queda modificada y se devuelve
EJEMPLO:  Cad_QuitaCaracter (Cadena,2)

FUNCION:  Cad_RecortaFinal()
OBJETIVO: Quitar de una cadena el espacio en blanco final
ENTRADAS: Una cadena
SALIDAS:  La cadena se modifica y se devuelve
EJEMPLO:  Cad_RecortaFinal ("Esto es todo.     ")

FUNCION:  Cad_Subcadena()
OBJETIVO: Averiguar si la segunda cadena est contenida
          en la primera
ENTRADAS: Las dos cadenas
SALIDA:   La posicin que ocupa el primer carcter de la
          primera donde comienza la primera aparicin de
          la segunda, o 0
NOTA:     Se empieza a contar en 1
EJEMPLO:  Cad_Subcadena ( "Calamares","mar" )

FUNCION:  Cad_Trozo()
OBJETIVO: Extraer una cadena de otra
ENTRADAS: Cadena origen y puntos de comienzo y fin del corte
SALIDAS:  La cadena destino
NOTAS:    1. El primer carcter lleva el nmero 1
          2. La cadena devuelta hay que destruirla cuando no
             sea necesaria
EJEMPLO:  Cad_Trozo (Nombre,3,7)

FUNCION:  Cad_Une()
OBJETIVO: Unir varias cadenas
ENTRADAS: Las cadenas que hay que unir, terminadas
          por CAD_FIN
SALIDAS:  Una cadena conteniendo la unin
NOTA:     La cadena devuelta hay que destruirla cuando no
          sea necesaria
EJEMPLO:  Cad_Une ("Veinte de ", Mes, " de 1808",CAD_FIN)

FUNCION:  Car_Compara()
OBJETIVO: Comparar dos caracteres con el criterio castellano
ENTRADAS: Dos caracteres
SALIDAS:  Un contador que expresa el resultado de la
          comparacin:
            Si es negativo, el primer carcter debe ir antes
              que el segundo
            Si es cero, los dos caracteres pueden ir en
              cualquier orden
            Si es positivo, el primer carcter debe ir
              despus que el segundo
EJEMPLO:  Car_Convierte ('')

FUNCION:  Car_ConvierteANSIaPC()
OBJETIVO: Convertir un carcter del juego ANSI al PC
ENTRADAS: Un carcter considerado como del juego ANSI
SALIDAS:  El carcter correspondiente en el juego PC
EJEMPLO:  Car_ConvierteANSIaPC ('')

FUNCION:  Car_ConvierteANSIaQL()
OBJETIVO: Convertir un carcter del juego ANSI al QL
ENTRADAS: Un carcter considerado como del juego ANSI
SALIDAS:  El carcter correspondiente en el juego QL
EJEMPLO:  Car_ConvierteANSIaQL ('')

FUNCION:  Car_ConviertePCaANSI()
OBJETIVO: Convertir un carcter del juego PC al ANSI
ENTRADAS: Un carcter considerado como del juego PC
SALIDAS:  El carcter correspondiente en el juego ANSI
EJEMPLO:  Car_ConviertePCaANSI ('')

FUNCION:  Car_ConviertePCaQL()
OBJETIVO: Convertir un carcter del juego PC al QL
ENTRADAS: Un carcter considerado como del juego PC
SALIDAS:  El carcter correspondiente en el juego QL
EJEMPLO:  Car_ConviertePCaQL ('')

FUNCION:  Car_ConvierteQLaANSI()
OBJETIVO: Convertir un carcter del juego QL al ANSI
ENTRADAS: Un carcter considerado como del juego QL
SALIDAS:  El carcter correspondiente en el juego ANSI
EJEMPLO:  Car_ConvierteQLaANSI ('')

FUNCION:  Car_ConvierteQLaPC()
OBJETIVO: Convertir un carcter del juego QL al PC
ENTRADAS: Un carcter considerado como del juego QL
SALIDAS:  El carcter correspondiente en el juego PC
EJEMPLO:  Car_ConvierteQLaPC ('')

FUNCION:  Car_EsMayus()
OBJETIVO: Decir si un carcter es una letra mayscula
ENTRADAS: Un carcter
SALIDAS:  Lgica, que indica si el carcter es una
          letra mayscula
EJEMPLO:  Car_EsMayus ('')

FUNCION:  Car_EsMinus()
OBJETIVO: Decir si un carcter es una letra minscula
ENTRADAS: Un carcter
SALIDAS:  Lgica, que indica si el carcter es una
          letra minscula
EJEMPLO:  Car_EsMinus ('')

FUNCION:  Car_Mayus()
OBJETIVO: Transformar un carcter en su mayscula
ENTRADAS: Un carcter
SALIDAS:  El carcter en mayscula o el mismo carcter
          si no tiene mayscula
EJEMPLO:  Car_Mayus ('')

FUNCION:  Car_Minus()
OBJETIVO: Transformar un carcter en su minscula
ENTRADAS: Un carcter
SALIDAS:  El carcter en minscula o el mismo carcter
          si no tiene minscula
EJEMPLO:  Car_Minus ('')

FUNCION:  Cdr_Caja()
OBJETIVO: Dibujar una caja
ENTRADAS: Tipo de la caja, sus coordenadas y colores de
          papel y tinta
SALIDAS:  Ninguna
EJEMPLO:  Cdr_Caja (CDR_DOBLE,1,1,10,70,ROJO,BLANCO)

FUNCION:  Cdr_Construye()
OBJETIVO: Construye un cuadro: una lista de cadenas que
          forman un cuadro
ENTRADAS: El tipo de lnea que se dibuja en las lneas
          externas, el de las internas, el nmero de filas,
          el alto de cada una, el nmero de columnas y el
          ancho de cada una
SALIDAS:  Una lista de cadenas
NOTA:     La lista devuelta hay que destruirla cuando no
          sea necesaria
EJEMPLO:  Cdr_Construye (CDR_DOBLE,CDR_SIMPLE,2,3,4,1)

FUNCION:  Cdr_Dibuja()
OBJETIVO: Dibujar un cuadro
ENTRADAS: El tipo de lnea que se dibuja en las lneas
          externas, el de las internas, el nmero de filas,
          el alto de cada una, el nmero de columnas, el
          ancho de cada una, la fila y columna de la esquina
          superior izquierda y los colores de papel y tinta
SALIDAS:  Ninguna
EJEMPLO:  Cdr_Dibuja (CDR_DOBLE,CDR_SIMPLE,2,3,4,1,3,3,
                      ROJO,BLANCO)

FUNCION:  Cdr_Linea()
OBJETIVO: Dibujar una lnea
ENTRADAS: El tipo de lnea, las coordenadas y los colores
          de papel y tinta
SALIDAS:  Ninguna
EJEMPLO:  Cdr_Linea (CDR_DOBLE,2,3,2,71,BLANCO,NEGRO)

FUNCION:  Cnf_Abre()
OBJETIVO: Abrir un fichero de configuracin
ENTRADAS: El nombre del fichero
SALIDAS:  Un objeto config o NIL si ha habido algn error
EJEMPLO:  Cnf_Abre ( "Datos.dat" )

FUNCION:  Cnf_Cierra()
OBJETIVO: Cerrar una configuracin
ENTRADAS: El objeto config
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Cnf_Cierra ( DatoImpresora )

FUNCION:  Cnf_Lee()
OBJETIVO: Obtener la siguiente lnea de una configuracin
ENTRADAS: El objeto config
SALIDAS:  La cadena si no hay error, o NIL
NOTAS:    1. La cadena no contiene '\n'
          2. La cadena devuelta hay que destruirla cuando
             no sea necesaria
          3. La cadena devuelta no tiene espacio en blanco
             al final
EJEMPLO:  Cnf_Lee ( DatoImpresora )

FUNCION:  Cnf_Linea()
OBJETIVO: Decir el nmero de lnea actual de una
          configuracin
ENTRADAS: El objeto config
SALIDAS:  El nmero de lnea
EJEMPLO:  Cnf_Linea ( DatoImpresora )

FUNCION:  Dbn_Alto()
OBJETIVO: Decir el alto en pixels de un diblane
ENTRADAS: El diblane
SALIDAS:  El alto en pixels
EJEMPLO:  Dbn_Alto ( Dibujo )

FUNCION:  Dbn_Ancho()
OBJETIVO: Decir el ancho en pixels de un diblane
ENTRADAS: El diblane
SALIDAS:  El ancho en pixels
EJEMPLO:  Dbn_Ancho ( Dibujo )

FUNCION:  Dbn_AnchoEnOxel()
OBJETIVO: Decir el ancho en oxels de un diblane
ENTRADAS: El diblane
SALIDAS:  El ancho en oxels
EJEMPLO:  Dbn_AnchoEnOxel ( Dibujo )

FUNCION:  Dbn_Coloca()
OBJETIVO: Mostrar un objeto "diblane" en una posicin
          de una zona
ENTRADAS: Un diblane, una zona, el nmero de oxel y el nmero
          de fila de la posicin y los colores del fondo y
          la figura
SALIDAS:  Ninguna
EJEMPLO:  Dbn_Coloca (Dibujo, Zona, 5, 7, BLANCO, ROJO)

FUNCION:  Dbn_Crea()
OBJETIVO: Crear un objeto "diblane" y darle valores iniciales
ENTRADAS: El ancho y el alto requeridos
SALIDAS:  Un diblane o NIL si no se puede crear
EJEMPLO:  Dbn_Crea (80,30)

FUNCION:  Dbn_Dato()
OBJETIVO: Decir la direccin donde se encuentran los datos
          de un diblane
ENTRADAS: El diblane
SALIDAS:  La direccin en memoria de los datos
EJEMPLO:  Dbn_Dato ( Dibujo )

FUNCION:  Dbn_Destruye()
OBJETIVO: Destruir un objeto diblane, liberando su memoria
ENTRADAS: El diblane
SALIDAS:  Ninguna
EJEMPLO:  Dbn_Destruye ( Dibujo )

FUNCION:  Dbn_Edita()
OBJETIVO: Editar un objeto "diblane" en una zona
ENTRADAS: Un diblane y una zona
SALIDAS:  Lgica, que indica si el diblane ha sido modificado,
          entendiendo como modificado que el usuario termin
          pulsando ENTER
EJEMPLO:  Dbn_Edita (Dibujo, Zona)
NOTAS:    1. Esta funcin slo se debe usar con diblanes
             de pequeas dimensiones
          2. Esta funcin cambia la escala de la zona

FUNCION:  Dbn_Invierte()
OBJETIVO: Invertir los colores de un objeto diblane
ENTRADAS: Un diblane
SALIDAS:  Ninguna
EJEMPLO:  Dbn_Invierte (Dibujo)

FUNCION:  Dbn_Muestra()
OBJETIVO: Mostrar un objeto "diblane" en una zona
ENTRADAS: Un diblane y una zona
SALIDAS:  Ninguna
EJEMPLO:  Dbn_Muestra (Dibujo, Zona)

FUNCION:  Dbn_PonPunto()
OBJETIVO: Poner el valor de un punto de un diblane
ENTRADAS: El diblane, la fila y la columna del punto y el
          nuevo valor
SALIDAS:  El nuevo valor del punto, que es 0  1
NOTAS:    1. La fila 0 es la de arriba
          2. La columna 0 es la de la izquierda
          3. Se asume que el punto pertenece al diblane
EJEMPLO:  Dbn_PonPunto ( Dibujo, 4, 17, 1 )

FUNCION:  Dbn_Punto()
OBJETIVO: Decir el valor de un punto de un diblane
ENTRADAS: El diblane, la fila y la columna del punto
SALIDAS:  El valor del punto, que es 0  1
NOTAS:    1. La fila 0 es la de arriba
          2. La columna 0 es la de la izquierda
          3. Se asume que el punto pertenece al diblane
EJEMPLO:  Dbn_Punto ( Dibujo, 4, 17 )

FUNCION:  Dbn_ReflejaHorizontal()
OBJETIVO: Reflejar horizontalmente un objeto diblane
ENTRADAS: Un diblane
SALIDAS:  Ninguna
EJEMPLO:  Dbn_ReflejaHorizontal (Dibujo)

FUNCION:  Dbn_ReflejaVertical()
OBJETIVO: Reflejar verticamente un objeto diblane
ENTRADAS: Un diblane
SALIDAS:  Ninguna
EJEMPLO:  Dbn_ReflejaVertical (Dibujo)

FUNCION:  Dbn_Tamano()
OBJETIVO: Decir el tamao en octetos de un diblane
ENTRADAS: El diblane
SALIDAS:  El tamao en octetos
EJEMPLO:  Dbn_Tamano ( Dibujo )

FUNCION:  DivEx()
OBJETIVO: Calcular la divisin por exceso de dos nmeros
ENTRADAS: Los dos nmeros
SALIDAS:  La divisin por exceso del primer nmero entre
          el segundo
NOTA:     Los argumentos se evalan dos veces
EJEMPLO:  DivEx ( 8, 5 )

FUNCION:  Fch_Abre()
OBJETIVO: Abrir un fichero
ENTRADAS: El nombre del fichero y el tipo
SALIDAS:  El fichero abierto o NIL si ha habido algn error
EJEMPLO:  Fch_Abre ( "Datos.dat", "r" )

FUNCION:  Fch_AbreActualizar()
OBJETIVO: Abrir un fichero para actualizarlo
ENTRADAS: El nombre del fichero y el modo: texto o binario
SALIDAS:  El fichero abierto o NIL si ha habido algn error
NOTA:     El puntero del fichero queda en el comienzo
EJEMPLO:  Fch_AbreActualizar ( "Datos.dat", FCH_BINARIO )

FUNCION:  Fch_AbreGrabar()
OBJETIVO: Abrir un fichero para grabar en l
ENTRADAS: El nombre del fichero y el modo: texto o binario
SALIDAS:  El fichero abierto o NIL si ha habido algn error o
          el usuario se niega a sobreescribir un fichero ya
          existente
EJEMPLO:  Fch_AbreGrabar ( "Informe.txt", FCH_BINARIO )

FUNCION:  Fch_AbreLeer()
OBJETIVO: Abrir un fichero para leerlo
ENTRADAS: El nombre del fichero y el modo: texto o binario
SALIDAS:  El fichero abierto o NIL si ha habido algn error
EJEMPLO:  Fch_AbreLeer ( "Datos.dat", FCH_TEXTO )

FUNCION:  Fch_Borra()
OBJETIVO: Borrar un fichero
ENTRADAS: El nombre del fichero
SALIDAS:  Ninguna
EJEMPLO:  Fch_Borra ( "Viejo.txt" )

FUNCION:  Fch_Cierra()
OBJETIVO: Cerrar un fichero
ENTRADAS: El fichero
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_Cierra ( Salida )

FUNCION:  Fch_Coloca()
OBJETIVO: Colocar el puntero interno de un fichero en una
          determinada posicin
ENTRADAS: El fichero y la nueva posicin, contada desde
          el principio
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_Coloca ( Dato, 50 )

FUNCION:  Fch_ColocaFinal()
OBJETIVO: Colocar el puntero interno de un fichero al final
ENTRADAS: El fichero
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_ColocaFinal ( Dato )

FUNCION:  Fch_EscribeLinea()
OBJETIVO: Escribir una lnea en un fichero (es decir,
          se pone '\n')
ENTRADAS: El fichero y una cadena
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_EscribeLinea ( Salida, Linea )

FUNCION:  Fch_EscribeOcteto()
OBJETIVO: Escribir en un fichero cierta cantidad de octetos
ENTRADAS: El fichero, la zona de memoria de donde se toman
          los octetos y la cantidad de octetos
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_EscribeOcteto ( Salida, Item, 1024 )

FUNCION:  Fch_Existe()
OBJETIVO: Informar si un fichero existe
ENTRADAS: El nombre del fichero
SALIDAS:  Lgica
EJEMPLO:  Fch_Existe ( "Datos.dat" )

FUNCION:  Fch_LeeLinea()
OBJETIVO: Obtener la siguiente lnea de un fichero
ENTRADAS: El fichero
SALIDAS:  La cadena si no hay error, o NIL
NOTAS:    1. La cadena no contiene '\n'
          2. La cadena devuelta hay que destruirla cuando
             no sea necesaria
          3. Las lneas de ms de 512 caracteres quedan
             truncadas
EJEMPLO:  Fch_LeeLinea ( Entrada )

FUNCION:  Fch_LeeOcteto()
OBJETIVO: Leer de un fichero cierta cantidad de octetos
ENTRADAS: El fichero, la zona de memoria donde dejar lo
          leido y la cantidad de octetos
SALIDAS:  Lgica, que indica si todo ha ido bien
EJEMPLO:  Fch_LeeOcteto ( Datos, Info, 1024 )

FUNCION:  Fch_ListaNombre()
OBJETIVO: Dada una mscara, dar una lista con los nombres
          que encajen con esa mscara
ENTRADAS: Una mscara para los ficheros
SALIDAS:  Una lista con los nombres o NIL si no se
          encuentra ninguno
NOTAS:    1. La lista devuelta hay que destruirla cuando no
             sea necesaria
          2. Se pueden utilizar dos comodines: * y ?
EJEMPLO:  Fch_ListaNombre ("*.txt")

FUNCION:  Fch_Manejador()
OBJETIVO: Decir el puntero a FILE que est usando un fichero
ENTRADAS: El fichero
SALIDAS:  Un puntero a FILE
EJEMPLO:  Fch_Manejador ( Entrada )
NOTA:     Esta funcin permite acceder a cualquier funcin C
          que sirva para manejar ficheros, pero se recomienda
          usar las de Olimpo siempre que sea posible

FUNCION:  Fch_Nombre()
OBJETIVO: Formar el nombre completo de un fichero uniendo
          el nombre, el separador y la extensin
ENTRADAS: El nombre y la extensin
SALIDAS:  La cadena con el nombre completo
NOTA:     La cadena devuelta hay que destruirla cuando no
          sea necesaria
EJEMPLO:  Fch_Nombre ( "Datos", "txt" )

FUNCION:  Fch_NombreReal()
OBJETIVO: Decir el nombre que se us al abrir un fichero
ENTRADAS: El fichero
SALIDAS:  Una cadena con el nombre
EJEMPLO:  Fch_NombreReal ( Entrada )

FUNCION:  Fch_Posicion()
OBJETIVO: Decir la posicin del puntero interno de un fichero
ENTRADAS: El fichero
SALIDAS:  La posicin o -1 si hay error
EJEMPLO:  Fch_Posicion ( Dato )

FUNCION:  Fch_Separador()
OBJETIVO: Decir el carcter separador entre el nombre y la
          extensin usado por el sistema operativo
ENTRADAS: Ninguna
SALIDAS:  Un carcter
EJEMPLO:  Fch_Separador()

FUNCION:  Fec_Ano()
OBJETIVO: Decir el ao de una fecha
ENTRADAS: La fecha
SALIDAS:  El ao
EJEMPLO:  Fec_Ano ( Nacimiento )

FUNCION:  Fec_Cadena()
OBJETIVO: Convertir una fecha en una cadena con
          formato AAAAMMDD
ENTRADAS: La fecha
SALIDAS:  La cadena
NOTA:     La cadena devuelta hay que destruirla cuando no
          se necesite
EJEMPLO:  Fec_Cadena (Nacimiento)

FUNCION:  Fec_Crea()
OBJETIVO: Crear un objeto "fecha" con los datos dados
ENTRADAS: El ao, el mes y el da de la fecha
SALIDAS:  Una fecha o NIL si no se puede crear
NOTA:     No se comprueba que la fecha sea vlida
EJEMPLO:  Fec_Crea (1960,10,25)

FUNCION:  Fec_Destruye()
OBJETIVO: Destruir una fecha, liberando su memoria
ENTRADAS: La fecha
SALIDAS:  Ninguna
EJEMPLO:  Fec_Destruye ( Nacimiento )

FUNCION:  Fec_Dia()
OBJETIVO: Decir el da de una fecha
ENTRADAS: La fecha
SALIDAS:  El da
EJEMPLO:  Fec_Dia ( Nacimiento )

FUNCION:  Fec_DiaSemana()
OBJETIVO: Decir el da de la semana de una fecha
ENTRADAS: La fecha
SALIDAS:  Un nmero que indica el da de la semana, con
          este convenio:
          0 -> Domingo, 1 -> Lunes, ..., 6 -> Sbado
EJEMPLO:  Fec_DiaSemana (Nacimiento)

FUNCION:  Fec_Diferencia()
OBJETIVO: Calcular la diferencia en das entre dos fechas
ENTRADAS: Dos fechas
SALIDAS:  El nmero de das que hay desde la primera hasta
          la segunda
EJEMPLO:  Fec_Diferencia ( Nacimiento, Hoy )

FUNCION:  Fec_Hoy()
OBJETIVO: Devolver una fecha con el da del reloj
          del ordenador
ENTRADAS: Ninguna
SALIDAS:  Una fecha
NOTA:     La fecha hay que destruirla cuando no sea necesaria
EJEMPLO:  Fec_Hoy()

FUNCION:  Fec_LeeCadena()
OBJETIVO: Leer una fecha de una cadena con formato AAAAMMDD
ENTRADAS: La cadena
SALIDAS:  La fecha
NOTA:     La fecha devuelta hay que destruirla cuando no
          se necesite
EJEMPLO:  Fec_LeeCadena ("19601025")

FUNCION:  Fec_Mes()
OBJETIVO: Decir el mes de una fecha
ENTRADAS: La fecha
SALIDAS:  El mes
EJEMPLO:  Fec_Mes ( Nacimiento )

FUNCION:  Ind_Abre()
OBJETIVO: Abrir un fichero de ndices y obtener un objeto
          en memoria para manejarlo
ENTRADAS: El nombre completo del fichero que hay que abrir,
          y el modo de apertura
SALIDAS:  Un indice o NIL si no se puede crear
EJEMPLO:  Ind_Abre ("Agenda.ntx", IND_LECTURA)

FUNCION:  Ind_Anterior()
OBJETIVO: Dar el anterior ndice de un fichero de ndices
ENTRADAS: El ndice, una variable en la que dejar el nmero
          de registro del ndice encontrado y una cadena
          donde dejar la clave
SALIDAS:  Lgica, que indica si se ha podido encontrar;
          la variable y la cadena quedan modificadas
NOTAS:    1. Los registros se numeran a partir de 0
          2. La cadena debe ser suficientemente larga como
             para recibir la clave, sin olvidar el espacio
             para el NULO
          3. Si se llama a esta funcin inmediatamente
             despus de abrir el ndice, se devuelve
             Ind_Ultimo()
EJEMPLO:  Ind_Anterior ( Agenda, &NumeroRegistro, Clave )

FUNCION:  Ind_Busca()
OBJETIVO: Dar el mayor ndice que sea menor o igual que
          una clave dada
ENTRADAS: El ndice, una variable en la que dejar el nmero
          de registro del ndice encontrado, una cadena
          donde dejar la clave y que contiene la clave de
          referencia y la funcin que se usar para comparar
          claves (debe recibir dos cadenas y devolver un
          contador).
SALIDAS:  Lgica, que indica si se ha podido encontrar;
          la variable y la cadena quedan modificadas.
NOTAS:    1. Los registros se numeran a partir de 0
          2. La cadena debe ser suficientemente larga como
             para recibir la clave, sin olvidar el espacio
             para el NULO
EJEMPLO:  Ind_Busca ( Agenda, &NumeroRegistro, Clave,
                      FuncionComparacion )

FUNCION:  Ind_Cierra ()
OBJETIVO: Cerrar un ndice
ENTRADAS: El ndice
SALIDAS:  Ninguna
EJEMPLO:  Ind_Cierra ( Agenda )

FUNCION:  Ind_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,
          la expresin que usar para comparar claves,
          la longitud de las claves y el nmero de decimales
          de la clave (si es numrica)
SALIDAS:  Un objeto indice o NIL si no se puede crear
EJEMPLO:  Ind_Crea ( "Agenda.ntx", "Apellido+Nombre", 40, 0 )
NOTAS:    1. La expresin no suele llevar espacios
          2. La expresin debe permitir regenerar el ndice
             si es necesario.
          3. La longitud de una clave no puede ser mayor de 100
          4. La longitud de la expresin de una clave no puede
             ser mayor de 255

FUNCION:  Ind_Inserta()
OBJETIVO: Insertar una nueva clave en un ndice
ENTRADAS: El ndice, el nmero de registro de base de datos,
          la clave  y la funcin que se usar para comparar
          claves (debe recibir dos cadenas y devolver un
          contador).
SALIDAS:  Lgica, que indica si se ha podido insertar
EJEMPLO:  Ind_Inserta ( Agenda, NumeroRegistro, Clave,
                        FuncionComparacion )
NOTA:     Los registros se numeran a partir de 0

FUNCION:  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 )

FUNCION:  Ind_Primero()
OBJETIVO: Dar el primer ndice de un fichero de ndices
ENTRADAS: El ndice, una variable en la que dejar el nmero
          de registro del ndice encontrado y una cadena
          donde dejar la clave
SALIDAS:  Lgica, que indica si se ha podido encontrar;
          la variable y la cadena quedan modificadas
NOTAS:    1. Los registros se numeran a partir de 0
          2. La cadena debe ser suficientemente larga como
             para recibir la clave, sin olvidar el espacio
             para el NULO
EJEMPLO:  Ind_Primero ( Agenda, &NumeroRegistro, Clave )

FUNCION:  Ind_Siguiente()
OBJETIVO: Dar el siguiente ndice de un fichero de ndices
ENTRADAS: El ndice, una variable en la que dejar el nmero
          de registro del ndice encontrado y una cadena
          donde dejar la clave
SALIDAS:  Lgica, que indica si se ha podido encontrar;
          la variable y la cadena quedan modificadas
NOTAS:    1. Los registros se numeran a partir de 0
          2. La cadena debe ser suficientemente larga como
             para recibir la clave, sin olvidar el espacio
             para el NULO
          3. Si se llama a esta funcin inmediatamente
             despus de abrir el ndice, se devuelve
             Ind_Primero()
EJEMPLO:  Ind_Siguiente ( Agenda, &NumeroRegistro, Clave )

FUNCION:  Ind_Ultimo()
OBJETIVO: Dar el ltimo ndice de un fichero de ndices
ENTRADAS: El ndice, una variable en la que dejar el nmero
          de registro del ndice encontrado y una cadena
          donde dejar la clave
SALIDAS:  Lgica, que indica si se ha podido encontrar;
          la variable y la cadena quedan modificadas
NOTAS:    1. Los registros se numeran a partir de 0
          2. La cadena debe ser suficientemente larga
             como para recibir la clave, sin olvidar
             el espacio para el NULO
EJEMPLO:  Ind_Ultimo ( Agenda, &NumeroRegistro, Clave )

FUNCION:  Lis_Agrega()
OBJETIVO: Aadir un elemento a una lista
ENTRADAS: La lista y el contenido del nuevo elemento
SALIDAS:  Una lista nueva o la antigua si no ha sido
          posible realizar el agregado
EJEMPLO:  Lis_Agrega (Agenda,Nombre)
NOTA:     El elemento agregado se coloca el primero
          de la lista

FUNCION:  Lis_AgregaFin()
OBJETIVO: Aadir un elemento a una lista por el final
ENTRADAS: La lista y el contenido del nuevo elemento
SALIDAS:  La lista original
EJEMPLO:  Lis_AgregaFin (Agenda,Nombre)
NOTAS:    1. El elemento agregado se coloca el ltimo de
             la lista
          2. Si no hay memoria suficiente, no se agrega

FUNCION:  Lis_Anota()
OBJETIVO: Anotar un elemento en una lista: si la lista no
          tena contenido, el elemento se coloca como
          contenido; si la lista ya tena contenido, se crea
          un nodo nuevo, se pone el elemento como contenido
          y se aade a la lista, colocndose en primer lugar
ENTRADAS: La lista y el contenido del nuevo elemento
SALIDAS:  Una lista nueva o la antigua si no ha sido posible
          realizar la anotacin
EJEMPLO:  Lis_Anota (Agenda,Nombre)

FUNCION:  Lis_AnotaFin()
OBJETIVO: Anotar un elemento en una lista: si la lista no
          tena contenido, el elemento se coloca como
          contenido; si la lista ya tena contenido, se crea
          un nodo nuevo, se pone el elemento como contenido
          y se aade a la lista, colocndose en ltimo lugar
ENTRADAS: La lista y el contenido del nuevo elemento
SALIDAS:  Una lista nueva o la antigua si no ha sido
          posible realizar la anotacin
EJEMPLO:  Lis_AnotaFin (Agenda,Nombre)

FUNCION:  Lis_Contenido()
OBJETIVO: Dar el contenido de un elemento de una lista
ENTRADAS: Una lista
SALIDAS:  El contenido del primer elemento
EJEMPLO:  Lis_Contenido (Agenda)

FUNCION:  Lis_Crea()
OBJETIVO: Crear una lista y darle valores iniciales seguros
ENTRADAS: Ninguna
SALIDAS:  Una lista nueva o NIL si no hay memoria
          para crearla
EJEMPLO:  Lis_Crea()

FUNCION:  Lis_Destruye()
OBJETIVO: Destruir una lista completa, incluyendo
          los contenidos
ENTRADAS: Una lista
SALIDAS:  Ninguna
EJEMPLO:  Lis_Destruye (Agenda)

FUNCION:  Lis_Ordena()
OBJETIVO: Ordenar los nodos de una lista segn el
          criterio indicado
ENTRADAS: Una lista y la funcin de comparacin entre
          dos contenidos
SALIDAS:  La lista se modifica y se devuelve
EJEMPLO:  Lis_Ordena ( Lista, FuncionComparacion )

FUNCION:  Lis_PonContenido()
OBJETIVO: Poner el contenido de un elemento de una lista
ENTRADAS: Una lista y el contenido que se va a poner, que
          debe ser una direccin de memoria reservada
SALIDAS:  El contenido
EJEMPLO:  Lis_PonContenido (Agenda,Nombre)

FUNCION:  Lis_PonSiguiente()
OBJETIVO: Poner el siguiente elemento de una lista
ENTRADAS: Una lista y la lista que se va a poner
          como siguiente
SALIDAS:  La lista siguiente
EJEMPLO:  Lis_PonSiguiente (Agenda,Nuevo)

FUNCION:  Lis_Siguiente()
OBJETIVO: Dar el siguiente elemento de una lista
ENTRADAS: Una lista
SALIDAS:  Otra lista, que comienza en el siguiente
          elemento de la lista original
EJEMPLO:  Lis_Siguiente (Agenda)

FUNCION:  Lis_Total()
OBJETIVO: Calcular el nmero de elementos de una lista
ENTRADAS: Una lista
SALIDAS:  El nmero de elementos
EJEMPLO:  Lis_Total (Agenda)

FUNCION:  Max()
OBJETIVO: Calcular el mximo de dos nmeros
ENTRADAS: Los nmeros
SALIDAS:  El mayor de ellos
NOTA:     El argumento devuelto se evala dos veces
EJEMPLO:  Max (2,5)

FUNCION:  Mem_Ajusta()
OBJETIVO: Ajustar la reserva de memoria
ENTRADAS: La posicin de memoria reservada con anterioridad
          y el nuevo nmero de octetos que hay que reservar
SALIDAS:  La nueva memoria, ya ajustada o NULO si no se
          puede ajustar
EJEMPLO:  Mem_Ajusta (Auxiliar,2048)
NOTA:     En el PC, con esta funcin no se puede reservar un
          bloque mayor de 64K

FUNCION:  Mem_Asigna()
OBJETIVO: Dar un valor a un grupo de octetos
ENTRADAS: La posicin de memoria donde comenzar, el valor
          y la cantidad de octetos
SALIDAS:  La posicin de memoria
EJEMPLO:  Mem_Asigna (Memoria,32,1024)

FUNCION:  Mem_Copia()
OBJETIVO: Copiar los valores de una zona de memoria a otra
ENTRADAS: La posicin de memoria destino, la origen y la
          cantidad de octetos
SALIDAS:  La posicin de memoria destino
EJEMPLO:  Mem_Copia (MemoriaFinal,MemoriaInicial,1024)

FUNCION:  Mem_Crea()
OBJETIVO: Reservar cierta cantidad de memoria
ENTRADAS: El nmero de octetos que hay que reservar
SALIDAS:  La memoria reservada o NULO si no se puede reservar
EJEMPLO:  Mem_Crea (1024)
NOTA:     En el PC, con esta funcin no se puede reservar un
          bloque mayor de 64K

FUNCION:  Mem_Destruye()
OBJETIVO: Devolver memoria reservada con anterioridad
ENTRADAS: La memoria reservada
SALIDAS:  Si la memoria era NULO, NO; si la memoria era
          no NULO, SI
EJEMPLO:  Mem_Destruye (Memoria)

FUNCION:  Mem_EscribeContador()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como contador
ENTRADAS: La posicin de memoria, el modo de almacenamiento
          y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeContador (Memoria+10, MEM_INTEL, -20205)

FUNCION:  Mem_EscribeContpos()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como contpos
ENTRADAS: La posicin de memoria, el modo de almacenamiento
          y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeContpos (Memoria+10, MEM_INTEL, 40205)

FUNCION:  Mem_EscribeEntero()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como entero
ENTRADAS: La posicin de memoria, el modo de almacenamiento
          y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeEntero (Memoria+10, MEM_INTEL, -2000111222)

FUNCION:  Mem_EscribeEntpos()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como entpos
ENTRADAS: La posicin de memoria, el modo de almacenamiento
          y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeEntpos (Memoria+10, MEM_INTEL, 4000111222)

FUNCION:  Mem_EscribeMenudo()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como menudo
ENTRADAS: La posicin de memoria y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeMenudo (Memoria+10, -105)

FUNCION:  Mem_EscribeOcteto()
OBJETIVO: Poner en una posicin de memoria un valor dado
          como octeto
ENTRADAS: La posicin de memoria y el valor
SALIDAS:  El valor
EJEMPLO:  Mem_EscribeOcteto (Memoria+10, 205)

FUNCION:  Mem_Intercambia()
OBJETIVO: Intercambiar los valores de dos posiciones
          de memoria
ENTRADAS: Las posiciones
SALIDAS:  Ninguna
EJEMPLO:  Mem_Intercambia (Memoria+3, Memoria+5)

FUNCION:  Mem_IntercambiaLarga()
OBJETIVO: Intercambiar una zona de memoria con otra
ENTRADAS: Las dos zonas, una zona auxiliar y la cantidad
          de octetos que hay que intercambiar
SALIDAS:  Ninguna
EJEMPLO:  Mem_IntercambiaLarga (Zona1, Zona2, Aux, 80)

FUNCION:  Mem_LeeContador()
OBJETIVO: Dar el valor de una posicin de memoria como
          contador
ENTRADAS: La posicin de memoria y el modo de almacenamiento
SALIDAS:  El valor
EJEMPLO:  Mem_LeeContador (Memoria+10, MEM_MOTOROLA)

FUNCION:  Mem_LeeContpos()
OBJETIVO: Dar el valor de una posicin de memoria
          como contpos
ENTRADAS: La posicin de memoria y el modo de almacenamiento
SALIDAS:  El valor
EJEMPLO:  Mem_LeeContpos (Memoria+10, MEM_MOTOROLA)

FUNCION:  Mem_LeeEntero()
OBJETIVO: Dar el valor de una posicin de memoria como entero
ENTRADAS: La posicin de memoria y el modo de almacenamiento
SALIDAS:  El valor
EJEMPLO:  Mem_LeeEntero (Memoria+10, MEM_MOTOROLA)

FUNCION:  Mem_LeeEntpos()
OBJETIVO: Dar el valor de una posicin de memoria como entpos
ENTRADAS: La posicin de memoria y el modo de almacenamiento
SALIDAS:  El valor
EJEMPLO:  Mem_LeeEntpos (Memoria+10, MEM_MOTOROLA)

FUNCION:  Mem_LeeMenudo()
OBJETIVO: Dar el valor de una posicin de memoria como menudo
ENTRADAS: La posicin de memoria
SALIDAS:  El valor
EJEMPLO:  Mem_LeeMenudo (Memoria+10)

FUNCION:  Mem_LeeOcteto()
OBJETIVO: Dar el valor de una posicin de memoria como octeto
ENTRADAS: La posicin de memoria
SALIDAS:  El valor
EJEMPLO:  Mem_LeeOcteto (Memoria+10)

FUNCION:  Men_Color()
OBJETIVO: Asignar los colores que usar un men
ENTRADAS: El men y ocho colores con estos significados:
          Color 1 -> Color del papel para la zona del men
          Color 2 -> Color de la tinta para las opciones
          Color 3 -> Color del papel para la opcin resaltada
          Color 4 -> Color de la tinta para la opcin
                     resaltada
          Color 5 -> Color de los caracteres que marcan el
                     atajo, para las opciones no resaltadas
          Color 6 -> Color de los caracteres que marcan el
                     atajo, para la opcin resaltada
          Color 7 -> Color de la tinta para las opciones no
                     disponibles
          Color 8 -> Color de la tinta para las flechas
SALIDAS:  Ninguna
EJEMPLO:  Men_Color ( MenuPrincipal, NEGRO, BLANCO, BLANCO,
                      NEGRO, VERDE, VERDE, ROJO, ROJO);

FUNCION:  Men_Crea()
OBJETIVO: Crear un men
ENTRADAS: El modo del men (MEN_HORIZONTAL o MEN_VERTICAL),
          las coordenadas de la parte de pantalla destinada
          al men, el nmero total de opciones, el tipo de
          men (MEN_VECTOR, MEN_LISTA o MEN_PROPIO) y una
          direccin de memoria que debe contener:
            Si el tipo es MEN_VECTOR, un vector de cadenas
               con las opciones, que pueden llevar un
               indicador del carcter que seala la tecla
               de acceso rpido (atajos)
            Si el tipo es MEN_LISTA, una lista de cadenas
               con las opciones, sin teclas de acceso rpido
               (atajos)
            Si el tipo es MEN_PROPIO, una funcin que recibe
               un nmero de tipo entero entre 1 y Total y
               una cadena y rellena la cadena con el texto de
               la opcin correspondiente, sin teclas de
               acceso rpido (atajos); la funcin debe
               devolver un valor lgico
SALIDAS:  Un men o NIL si no se puede crear
EJEMPLOS: Men_Crea (MEN_HORIZONTAL, 1, 3, 1, 78, 3, MEN_VECTOR,
                    (memoria) {">Salida",">Ejecutar","A>yuda"})
          Men_Crea (MEN_VERTICAL, 1, 3, 21, 23, 120, MEN_LISTA,
                    (memoria) ListaOpciones)
          Men_Crea (MEN_VERTICAL, 1,3,21,23,12000, MEN_PROPIO,
                    (memoria) FuncionPropia)
NOTAS:    1. Los mens de tipo MEN_VECTOR slo pueden ser de
             modo MEN_HORIZONTAL
          2. En un men de tipo MEN_VECTOR a las opciones se
             les aade un espacio en blanco por delante y
             por detrs
          3. En un men de tipo MEN_VECTOR todas las opciones
             se encuentran disponibles al crear el men
          4. En un men de modo MEN_HORIZONTAL la fila
             superior de la parte de la pantalla dedicada al
             men debe ser la misma que la fila inferior.
          5. El men recibe estos colores por defecto:
                Color del papel para la zona del men: NEGRO
                Color de la tinta para las opciones: BLANCO
                Color del papel para la opcin resaltada:
                     BLANCO
                Color de la tinta para la opcin resaltada:
                     VERDE
                Color de los caracteres que marcan el atajo,
                     para las opciones no resaltadas: VERDE
                Color de los caracteres que marcan el atajo,
                     para la opcin resaltada: VERDE
                Color de la tinta para las opciones no
                     disponibles: ROJO
                Color de la tinta para las flechas: ROJO

FUNCION:  Men_Destruye()
OBJETIVO: Destruir un objeto men, liberando su memoria
ENTRADAS: El men
SALIDAS:  Ninguna
EJEMPLO:  Men_Destruye ( MenuPrincipal )

FUNCION:  Men_Disponible()
OBJETIVO: Especificar si una opcin de un men se encuentra
          disponible
ENTRADAS: El men, el nmero de opcin y el nuevo estado
SALIDAS:  Lgica, que indica si la opcin queda disponible
EJEMPLO:  Men_Disponible ( MenuPrincipal, 3, NO )
NOTAS:    1. Esta funcin slo se puede usar en mens de
             tipo MEN_VECTOR
          2. Las opciones se empiezan a numerar en 1

FUNCION:  Men_Ejecuta()
OBJETIVO: Mostrar al usuario las opciones de un men, manejar
          las pulsaciones y devolver el nmero de opcin
          elegida
ENTRADAS: El men, la opcin que debe resaltarse al comenzar y
          el texto de la primera lnea de ayuda
SALIDAS:  El nmero de opcin o cero si no se elige ninguna
EJEMPLO:  Men_Ejecuta ( MenuPrincipal, 7 , "Elige la opcion" )

FUNCION:  Men_Escribe()
OBJETIVO: Escribir las opciones de un men
ENTRADAS: El men, la opcin que debe aparecer seguro y si
          hay que resaltarla o no
SALIDAS:  Ninguna
EJEMPLO:  Men_Escribe ( MenuPrincipal, 7, SI )

FUNCION:  Men_Horizontal()
OBJETIVO: Presentar al usuario un men horizontal para que
          pueda elegir entre varias opciones, mediante las
          teclas del cursor o mediante un atajo (tecla
          caliente)
ENTRADAS: La fila en la que se muestra el men, las columnas
          entre las que se muestra, un vector de cadenas,
          terminado en NIL, en el que se sealan los atajos
          y la opcin que hay resaltar en primer lugar
SALIDAS:  Un nmero indicando la opcin elegida, empezando a
          contar en 1, o 0 si no se elige ninguna o no hay
          memoria suficiente
EJEMPLO:  Men_Horizontal (1,1,78,{">Fichero","A>yuda",NIL},2)

FUNCION:  Men_Muestra()
OBJETIVO: Mostrar las opciones de un men
ENTRADAS: El men, la opcin que debe aparecer seguro al
          comenzar y el texto que debe aparecer en la primera
          lnea de mensajes
SALIDAS:  Lgica, que indica cmo ha salido el usuario
EJEMPLO:  Men_Muestra ( MenuPrincipal, 7 , "Mira la relacin")

FUNCION:  Men_TeclaNo()
OBJETIVO: Anotar las teclas especiales que permiten al
          usuario salir del men sin aceptar ninguna opcin
ENTRADAS: El men y un vector de teclas terminado en NIL
SALIDAS:  La direccin de memoria
EJEMPLO:  Men_TeclaNo ( MenuPrincipal, {TEC_MAY_F3, NIL} )

FUNCION:  Men_TeclaSi()
OBJETIVO: Anotar las teclas especiales que permiten al
          usuario salir del men aceptando la opcin
          resaltada
ENTRADAS: El men y un vector de teclas terminado en NIL
SALIDAS:  La direccin de memoria donde comienza el vector
EJEMPLO:  Men_TeclaSi ( MenuPrincipal, {TEC_TAB, TEC_F3, NIL} )

FUNCION:  Men_Texto()
OBJETIVO: Decir cul es el texto de una opcin de un men
ENTRADAS: El men, el nmero de opcin y una cadena para
          dejar el texto de la opcin
SALIDAS:  Valor lgico SI
EJEMPLO:  Men_Texto ( MenuPrincipal, 7, Texto)
NOTA:     La cadena debe tener longitud suficiente para
          almacenar el texto

FUNCION:  Men_Vertical()
OBJETIVO: Presentar al usuario un men vertical para que
          pueda elegir entre varias opciones, mediante las
          teclas del cursor o mediante un atajo (tecla
          caliente)
ENTRADAS: Las coordenadas de la esquina superior izquierda e
          inferior derecha de la zona asignada al men, un
          vector de cadenas, terminado en NIL, en el que se
          sealan los atajos y la opcin que hay que resaltar
          en primer lugar
SALIDAS:  Un nmero indicando la opcin elegida, empezando a
          contar en 1, o 0 si no se elige ninguna o no hay
          memoria
EJEMPLO:  Men_Vertical (1,10,8,20,{">Fichero","A>yuda",NIL},2)

FUNCION:  Min()
OBJETIVO: Calcular el mnimo de dos nmeros
ENTRADAS: Los nmeros
SALIDAS:  El menor de ellos
NOTA:     El argumento devuelto se evala dos veces
EJEMPLO:  Min (2,5)

FUNCION:  Mmo_Abre()
OBJETIVO: Abrir un fichero memo y obtener un objeto en
          memoria para manejarlo
ENTRADAS: El nombre completo del fichero que hay que abrir,
          y el modo de apertura
SALIDAS:  Un objeto memo o NIL si no se puede crear
EJEMPLO:  Mmo_Abre ("Agenda.dbt", MMO_LECTURA)

FUNCION:  Mmo_Agrega()
OBJETIVO: Agregar un registro a un fichero memo
ENTRADAS: El objeto memo y la cadena que hay que almacenar
SALIDAS:  El nmero de bloque asignado al registro.
          Si no se ha podido realizar la operacin se
          devuelve 0
EJEMPLO:  Mmo_Agrega ( Dato, Anotacion )
NOTA:     Los fines de lnea en la cadena se deben indican
          con el carcter '\r'

FUNCION:  Mmo_Cierra()
OBJETIVO: Cerrar un fichero memo
ENTRADAS: El objeto memo
SALIDAS:  Ninguna
EJEMPLO:  Mmo_Cierra ( Nota )

FUNCION:  Mmo_Crea()
OBJETIVO: Crear un fichero memo y obtener un objeto en
          memoria para manejarlo
ENTRADAS: El nombre completo del fichero que hay que crear y
          el nombre interno
SALIDAS:  Un objeto memo o NIL si no se puede crear
EJEMPLO:  Mmo_Crea ("Agenda.dbt", "Agenda")
NOTA:     El nombre interno debe tener ocho caracteres
          como mximo

FUNCION:  Mmo_Escribe()
OBJETIVO: Escribir un registro de un fichero memo
ENTRADAS: El objeto memo, el nmero de bloque donde comienza
          el registro y la cadena que hay que almacenar
SALIDAS:  El nmero de bloque asignado al registro. Puede ser
          el mismo que tena u otro nuevo. Si no se ha podido
          realizar la operacin se devuelve 0
EJEMPLO:  Mmo_Escribe ( Dato, 17, Anotacion )
NOTAS:    1. Los fines de lnea en la cadena se deben indican
             con el carcter \r
          2. Si hay espacio suficiente en el fichero, se
             conserva el nmero de bloque; si no, se aade
             el registro al final del fichero y se devuelve
             un nmero de bloque nuevo

FUNCION:  Mmo_Lee()
OBJETIVO: Leer un registro de un fichero memo
ENTRADAS: El objeto memo y el nmero de bloque donde comienza
          el registro
SALIDAS:  Una cadena con el texto o NIL si hay algn problema
EJEMPLO:  Mmo_Lee ( Dato, 17 )
NOTA:     Los fines de lnea se indican con el carcter \r

FUNCION:  Pan_Borra()
OBJETIVO: Borrar una zona de la pantalla
ENTRADAS: El color y las coordenadas
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Borra ( ROJO,3,3,15,15 )

FUNCION:  Pan_BorraLinea()
OBJETIVO: Limpiar una lnea determinada
ENTRADAS: La lnea
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_BorraLinea ( 0 )

FUNCION:  Pan_Caracter()
OBJETIVO: Escribir un carcter en la pantalla
ENTRADAS: El carcter
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Caracter ('A')

FUNCION:  Pan_Cierra()
OBJETIVO: Dejar la pantalla preparada para volver
          al sistema operativo
ENTRADAS: Ninguna
EJEMPLO:  Pan_Cierra()

FUNCION:  Pan_Color()
OBJETIVO: Cambiar el color del papel y la tinta
ENTRADAS: El color del papel y de la tinta
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Color ( VERDE, NEGRO )

FUNCION:  Pan_Cursor()
OBJETIVO: Colocar el cursor en una posicin determinada
ENTRADAS: La fila y la columna
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Cursor ( 0,0 )

FUNCION:  Pan_CursorVisible()
OBJETIVO: Poner y quitar el cursor
ENTRADAS: Lgica
SALIDAS:  Ninguna
EJEMPLO:  Pan_CursorVisible ( SI )

FUNCION:  Pan_Define()
OBJETIVO: Definir la pantalla principal del programa
ENTRADAS: El modo que se va a usar: texto o grfico
NOTA:     Se usa una pantalla de 24 filas (de 0 a 23) y
          80 columnas (de 0 a 79)
EJEMPLO:  Pan_Define ( PAN_TEXTO )

FUNCION:  Pan_Entero()
OBJETIVO: Escribir un nmero entero en la pantalla en
          un ancho determinado
ENTRADAS: El nmero y el ancho
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Entero ( 12345,6 )
NOTA:     El nmero se evala dos veces

FUNCION:  Pan_Limpia()
OBJETIVO: Borrar la pantalla completa
ENTRADAS: Ninguna
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Limpia()
NOTA:     Se usa el color del papel en ese momento

FUNCION:  Pan_Modo()
OBJETIVO: Decir el modo en que est definida la pantalla
ENTRADAS: Ninguna
SALIDAS:  PAN_TEXTO o PAN_GRAFICO
EJEMPLO:  Pan_Modo()

FUNCION:  Pan_Mueve()
OBJETIVO: Mover hacia arriba o hacia abajo el contenido de un
          rectngulo de pantalla
ENTRADAS: La direccin de movimiento, el nmero de filas que
          hay que mover y las coordenadas del rectngulo
SALIDAS:  Ninguna
EJEMPLO:  Pan_Mueve ( PAN_ARRIBA, 2,3,4,8,15 )

FUNCION:  Pan_Papel()
OBJETIVO: Cambiar el color de la pantalla
ENTRADAS: El nuevo color
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Papel ( VERDE )

FUNCION:  Pan_PonCar()
OBJETIVO: Escribir un carcter en cierta posicin
ENTRADAS: La fila, la columna y el carcter
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_PonCar (3,5,'A')

FUNCION:  Pan_PonEntero()
OBJETIVO: Escribir un nmero entero en cierta posicin
ENTRADAS: La fila, la columna, el entero y el
          ancho disponible
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_PonEntero (3,5,12345,6)
NOTA:     El nmero se evala dos veces

FUNCION:  Pan_PonReal()
OBJETIVO: Escribir un nmero real en la pantalla en una
          posicin determinada
ENTRADAS: La fila, la columna, un nmero real, el ancho
          asignado y el nmero de decimales
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_PonReal (0, 0, 1.23455, 5, 2)

FUNCION:  Pan_PonTexto()
OBJETIVO: Escribir un texto en cierta posicin
ENTRADAS: La fila, la columna y el texto
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_PonTexto (3,5,"Hola")

FUNCION:  Pan_PonTextoControlado()
OBJETIVO: Escribir una cadena en la pantalla en una
          posicin determinada de modo que no exceda un
          determinado nmero de caracteres
ENTRADAS: La fila, la columna, la cadena y el nmero
          de caracteres
SALIDAS:  Ninguna
EJEMPLO:  Pan_PonTextoControlado ( 3, 6, "Hola, mundo", 4 )

FUNCION:  Pan_Real()
OBJETIVO: Escribir un nmero real en la pantalla
ENTRADAS: Un nmero real, el ancho asignado y el nmero
          de decimales
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Real (1.23455, 5, 2)

FUNCION:  Pan_Resalta()
OBJETIVO: Poner y quitar la situacin de resaltado
          de caracteres
ENTRADAS: Lgica
SALIDAS:  Ninguna
EJEMPLO:  Pan_Resalta ( SI )

FUNCION:  Pan_Texto()
OBJETIVO: Escribir un texto en la pantalla
ENTRADAS: Una cadena
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Texto ("Hola, usuario")

FUNCION:  Pan_TextoControlado()
OBJETIVO: Escribir una cadena en la pantalla de modo
          que no exceda un determinado nmero de caracteres
ENTRADAS: La cadena y el nmero de caracteres
SALIDAS:  Ninguna
EJEMPLO:  Pan_TextoControlado ( "Hola, mundo", 4 )

FUNCION:  Pan_Tinta()
OBJETIVO: Cambiar el color con el que se escribe en
          la pantalla
ENTRADAS: El nuevo color
SALIDAS:  El valor lgico SI
EJEMPLO:  Pan_Tinta ( ROJO )

FUNCION:  Prg_Presenta()
OBJETIVO: Presentar el programa
ENTRADAS: Nombre, versin, autor y fecha
SALIDAS:  Ninguna
EJEMPLO:  Prg_Presenta ( "Programa","0.0",
                         "Pedro Reina","1993" )

FUNCION:  Reg_Alto()
OBJETIVO: Decir la altura de una regin
ENTRADAS: La regin
SALIDAS:  La altura
EJEMPLO:  Reg_Alto ( CuadroInfo )

FUNCION:  Reg_Ancho()
OBJETIVO: Decir la anchura de una regin
ENTRADAS: La regin
SALIDAS:  La anchura
EJEMPLO:  Reg_Ancho ( CuadroInfo )

FUNCION:  Reg_Borde()
OBJETIVO: Poner borde en una regin
ENTRADAS: La regin, el tipo de lnea para el borde, el
          color de fondo del borde y el de la lnea
SALIDAS:  Ninguna
EJEMPLO:  Reg_Borde ( CuadroInfo, CDR_DOBLE, BLANCO, NEGRO )

FUNCION:  Reg_ColDer()
OBJETIVO: Decir la columna derecha de una regin
ENTRADAS: La regin
SALIDAS:  Un octeto que indica la columna derecha
EJEMPLO:  Reg_ColDer ( CuadroInfo )

FUNCION:  Reg_ColIzq()
OBJETIVO: Decir la columna izquierda de una regin
ENTRADAS: La regin
SALIDAS:  Un octeto que indica la columna izquierda
EJEMPLO:  Reg_ColIzq ( CuadroInfo )

FUNCION:  Reg_Color()
OBJETIVO: Poner el color del papel y la tinta de una regin
ENTRADAS: La regin y dos octetos que indiquen los colores
SALIDAS:  Un octeto que indica el color de tinta
EJEMPLO:  Reg_Color ( CuadroInfo, NEGRO, BLANCO )

FUNCION:  Reg_Crea()
OBJETIVO: Crear una regin
ENTRADAS: La fila superior, la columna izquierda, la fila
          inferior y la columna derecha, todo en caracteres
SALIDAS:  Una regin o NIL si no se puede crear
EJEMPLO:  Reg_Crea (3,4,14,70)

FUNCION:  Reg_Cursor()
OBJETIVO: Colocar el cursor de pantalla en una posicin
          relativa de una regin
ENTRADAS: La regin, la fila y la columna
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_Cursor ( CuadroInfo, 3, 4 )
NOTAS:    1. Las filas de una regin se numeran desde 0,
             la superior
          2. Las columnas de una regin se numeran desde 0,
             la izquierda

FUNCION:  Reg_Destruye()
OBJETIVO: Eliminar una regin, liberando memoria
ENTRADAS: La region
SALIDAS:  Ninguna
EJEMPLO:  Reg_Destruye ( CuadroInfo )

FUNCION:  Reg_Escribe()
OBJETIVO: Escribir el trozo almacenado en el trozo de
          una regin
ENTRADAS: La regin
SALIDAS:  Lgica, que indica que se ha podido realizar la
          escritura
EJEMPLO:  Reg_Escribe (CuadroInfo)

FUNCION:  Reg_FilInf()
OBJETIVO: Decir la fila inferior de una regin
ENTRADAS: La regin
SALIDAS:  Un octeto que indica la fila inferior
EJEMPLO:  Reg_FilInf ( CuadroInfo )

FUNCION:  Reg_FilSup()
OBJETIVO: Decir la fila superior de una regin
ENTRADAS: La regin
SALIDAS:  Un octeto que indica la fila superior
EJEMPLO:  Reg_FilSup ( CuadroInfo )

FUNCION:  Reg_Lee()
OBJETIVO: Almacenar el trozo tapado por una regin
ENTRADAS: La regin
SALIDAS:  Lgica, que indica que se ha podido realizar
          la lectura
EJEMPLO:  Reg_Lee (CuadroInfo)
NOTA:     Si ya se hubiera leido con anterioridad, se perder
          la lectura anterior

FUNCION:  Reg_Limpia()
OBJETIVO: Limpiar una regin con un color
ENTRADAS: La regin y un octeto que indica el color
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_Limpia ( CuadroInfo, NEGRO )

FUNCION:  Reg_LimpiaInterior()
OBJETIVO: Limpiar el interior de una regin con un color
          (toda la regin salvo las primera y ltima fila
          y columna)
ENTRADAS: La regin y un octeto que indica el color
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_LimpiaInterior ( CuadroInfo, NEGRO )

FUNCION:  Reg_Papel()
OBJETIVO: Poner el color de papel de una regin
ENTRADAS: La regin y un octeto que indica el color de papel
SALIDAS:  Un octeto que indica el color de papel
EJEMPLO:  Reg_Papel ( CuadroInfo, ROJO )

FUNCION:  Reg_PonCar()
OBJETIVO: Escribir un carcter en cierta posicin de
          una regin
ENTRADAS: La regin, la fila, la columna y el carcter
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_PonCar (CuadroInfo,3,5,'A')

FUNCION:  Reg_PonEntero()
OBJETIVO: Escribir un nmero entero en cierta posicin de
          una regin
ENTRADAS: La regin, la fila, la columna, el entero y el
          ancho disponible
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_PonEntero (CuadroInfo,3,5,12345,6)
NOTA:     El nmero se evala dos veces

FUNCION:  Reg_PonReal()
OBJETIVO: Escribir un nmero real en cierta posicin de
          una regin
ENTRADAS: La regin, la fila, la columna, un nmero real, el
          ancho asignado y el nmero de decimales
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_PonReal (CuadroInfo, 0, 0, 1.23455, 8, 2)

FUNCION:  Reg_PonTexto()
OBJETIVO: Escribir un texto en cierta posicin de una regin
ENTRADAS: La regin, la fila, la columna y el texto
SALIDAS:  El valor lgico SI
EJEMPLO:  Reg_PonTexto (CuadroInfo,3,5,"Hola")

FUNCION:  Reg_TextoCentrado()
OBJETIVO: Escribir un texto en una regin centrado en
          una fila
ENTRADAS: La regin, el texto y la fila
SALIDAS:  Ninguna
EJEMPLO:  Reg_TextoCentrado (CuadroInfo,"Informacin",2)

FUNCION:  Reg_Tinta()
OBJETIVO: Poner el color de tinta de una regin
ENTRADAS: La regin y un octeto que indica el color de tinta
SALIDAS:  Un octeto que indica el color de tinta
EJEMPLO:  Reg_Tinta ( CuadroInfo, BLANCO )

FUNCION:  Signo()
OBJETIVO: Calcular el signo de un nmero
ENTRADAS: El nmero
SALIDAS:  Un menudo con el signo del nmero
NOTA:     El argumento se evala dos veces
EJEMPLO:  Signo ( -1.3 )

FUNCION:  Son_Apaga()
OBJETIVO: Apagar el sonido
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Apaga()

FUNCION:  Son_Bien()
OBJETIVO: Sealar brevemente que algo es correcto
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Bien()

FUNCION:  Son_Cambia()
OBJETIVO: Cambiar el estado del sonido
          (Encendido / Apagado)
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Cambia()

FUNCION:  Son_Enciende()
OBJETIVO: Encender el sonido
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Enciende()

FUNCION:  Son_Error()
OBJETIVO: Sealar un error
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Error()

FUNCION:  Son_Estado()
OBJETIVO: Informar del estado del sonido
          (Encendido / Apagado)
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_Estado()

FUNCION:  Son_MalaTecla()
OBJETIVO: Sealar que la tecla pulsada no se admite
ENTRADAS: Ninguna
SALIDAS:  Lgica, que indica si el sonido est encendido
EJEMPLO:  Son_MalaTecla()

FUNCION:  Tec_Disponible()
OBJETIVO: Decir si est disponible alguna tecla
ENTRADAS: Ninguna
SALIDAS:  0 si no hay tecla disponible, 1 si la hay
EJEMPLO:  Tec_Disponible()

FUNCION:  Tec_FijadoMayus()
OBJETIVO: Decir si est activado el sujeta-maysculas
ENTRADAS: Ninguna, se lee del sistema
SALIDAS:  Lgica
EJEMPLO:  Tec_FijadoMayus()

FUNCION:  Tec_Mayus()
OBJETIVO: Convertir una tecla en mayscula
ENTRADAS: Una tecla
SALIDAS:  La tecla convertida en mayscula
EJEMPLO:  Tec_Mayus ( TEC_A )

FUNCION:  Tec_Minus()
OBJETIVO: Convertir una tecla en minscula
ENTRADAS: Una tecla
SALIDAS:  La tecla convertida en minscula
EJEMPLO:  Tec_Minus ( TEC_MAY_A )

FUNCION:  Tec_Pertenece()
OBJETIVO: Decidir si una tecla pertenece a cierto rango
ENTRADAS: Una tecla y un vector con las teclas admitidas,
          terminado en NIL
SALIDAS:  La tecla si pertenece o NIL si no pertenece
EJEMPLO:  Tec_Pertenece ( TEC_F1, {TEC_ESC,NIL} )

FUNCION:  Tec_Pulsada()
OBJETIVO: Esperar a que el usuario pulse una tecla y devolver
          su cdigo
ENTRADAS: Ninguna
SALIDAS:  El cdigo asignado a la tecla pulsada
          La variable global Tec_Ultima_ queda modificada
NOTA:     Deben usarse siempre los macros, puesto que los
          cdigos dependen del compilador
EJEMPLO:  Tec_Pulsada()

FUNCION:  Tec_Ultima()
OBJETIVO: Devolver la ltima tecla pulsada por el usuario
ENTRADAS: Ninguna
SALIDAS:  La ltima tecla pulsada por el usuario
EJEMPLO:  Tec_Ultima()

FUNCION:  Tec_Validada()
OBJETIVO: Devolver una tecla de un determinado rango
ENTRADAS: Un vector con las teclas admitidas, terminado
          en NIL
SALIDAS:  La tecla pulsada
EJEMPLO:  Tec_Validada ( {TEC_ESC,NIL} )

FUNCION:  Tec_ValidadaRapido()
OBJETIVO: Devolver una tecla de un determinado rango o NIL
          si no hay disponible ninguna tecla correcta
ENTRADAS: Un vector con las teclas admitidas, terminado
          en NIL
SALIDAS:  La tecla pulsada o NIL
EJEMPLO:  Tec_ValidadaRapido ( {TEC_ESC,NIL} )

FUNCION:  Tif_Abre()
OBJETIVO: Abrir un fichero TIFF y obtener un objeto
          en memoria para manejarlo
ENTRADAS: El nombre completo del fichero que hay que abrir
SALIDAS:  Un tiff o NIL si se produce algn error
EJEMPLO:  Tif_Abre ("Imagen.tif")

FUNCION:  Tif_Alto()
OBJETIVO: Decir la altura de la imagen que se est manejando
ENTRADAS: Un tiff
SALIDAS:  La altura de la imagen
EJEMPLO:  Tif_Alto ( Imagen )

FUNCION:  Tif_Ancho()
OBJETIVO: Decir la anchura de la imagen que se est manejando
ENTRADAS: Un tiff
SALIDAS:  La anchura de la imagen
EJEMPLO:  Tif_Ancho ( Imagen )

FUNCION:  Tif_BitsPorPixel()
OBJETIVO: Decir el nmero de bits necesarios para definir
          un pixel
ENTRADAS: Un tiff
SALIDAS:  El nmero de bits por pixel
EJEMPLO:  Tif_BitsPorPixel ( Imagen )

FUNCION:  Tif_Cierra()
OBJETIVO: Cerrar un fichero TIFF
ENTRADAS: El objeto Tiff que lo maneja
SALIDAS:  Ninguna
EJEMPLO:  Tif_Cierra ( Imagen )

FUNCION:  Tif_Compresion()
OBJETIVO: Decir el modo de compresin de la imagen que se
          est manejando
ENTRADAS: Un tiff
SALIDAS:  El modo de compresin de la imagen, que puede ser
            TIF_SIN_COMPRESION -> No se usa compresin
            TIF_CCITT1D
            TIF_FAX3
            TIF_FAX4
            TIF_LZW
            TIF_JPEG
            TIF_PACKBITS
EJEMPLO:  Tif_Compresion ( Imagen )

FUNCION:  Tif_Crea()
OBJETIVO: Crear un fichero TIFF
ENTRADAS: El nombre del fichero
SALIDAS:  Un objeto tiff o NIL si no se puede crear
EJEMPLO:  Tif_Crea ("Imagen.tif")
NOTA:     Slo se crea la cabecera del fichero, el resto hay
          que ponerlo despus

FUNCION:  Tif_EscribeBandaBN()
OBJETIVO: Escribir los datos que realmente expresan una banda
          de una imagen en blanco y negro
ENTRADAS: Un objeto tiff, el tamao en octetos de la banda,
          el nmero de la banda y la direccin en que se
          encuentran los datos
SALIDAS:  Lgica, que indica que todo ha ido bien
EJEMPLO:  Tif_EscribeBandaBN ( Imagen, 4096, 2, Aux )
NOTAS:    1. Se asume que la banda existe
          2. Las bandas se empiezan a numerar en 0
          3. Si la imagen slo tiene una banda, esta funcin
             escribe la nica banda, aunque se pida otra

FUNCION:  Tif_EscribeDirectorioBN()
OBJETIVO: Escribir el directorio de una imagen en blanco
          y negro en un fichero TIFF
ENTRADAS: Un objeto tiff, la anchura y altura de la imagen,
          el nmero de bandas en que se va a dividir la
          imagen, el mtodo de compresin y la interpretacin
          fotomtrica
SALIDAS:  Lgica, que indica que todo ha ido bien
EJEMPLO:  Tif_EscribeDirectorioBN ("Imagen.tif", 240, 100,
                    1, TIF_SIN_COMPRESION, TIF_NEGRO_CERO)
NOTAS:    1. El modo de compresin slo puede ser
             TIF_SIN_COMPRESION
          2. La interpretacin fotomtrica puede ser
             TIF_NEGRO_CERO o TIF_BLANCO_CERO
          3. Se asume que las bandas sern del mismo tamao,
             salvo quiz la ltima

FUNCION:  Tif_EscribeImagenBN()
OBJETIVO: Escribir los datos que realmente expresan una imagen
          en blanco y negro
ENTRADAS: Un objeto tiff, la anchura y altura de la imagen,
          el nmero de bandas en que se va a dividir la
          imagen, la direccin donde se encuentran los datos,
          el mtodo de compresin y la interpretacin
          fotomtrica
SALIDAS:  Lgica, que indica que todo ha ido bien
EJEMPLO:  Tif_EscribeImagenBN ( Imagen, 4096, 2, Aux )
NOTAS:    1. El modo de compresin slo puede ser
             TIF_SIN_COMPRESION
          2. La interpretacin fotomtrica puede ser
             TIF_NEGRO_CERO o TIF_BLANCO_CERO
          3. Si el nmero de bandas es 0, esta funcin
             calcula el nmero ms adecuado

FUNCION:  Tif_FilasPorBanda()
OBJETIVO: Decir cuntas filas tiene cada banda de la imagen
          que se est manejando (la ltima banda puede tener
          menos)
ENTRADAS: Un tiff
SALIDAS:  El nmero de filas por banda de la imagen o cero
          si no se encuentra este tag
EJEMPLO:  Tif_FilasPorBanda ( Imagen )

FUNCION:  Tif_Interpretacion()
OBJETIVO: Decir el la interpretacin fotomtrica de la imagen
          que se est manejando
ENTRADAS: Un tiff
SALIDAS:  La interpretacin fotomtrica de la imagen, que
          puede ser
            TIF_BLANCO_CERO
            TIF_NEGRO_CERO
            TIF_RGB
            TIF_PALETA
            TIF_MASCARA
EJEMPLO:  Tif_Interpretacion ( Imagen )

FUNCION:  Tif_LeeBandaBN()
OBJETIVO: Leer los datos que realmente expresan una banda de
          la imagen que se est manejando y est en blanco
          y negro sin comprimir
ENTRADAS: Un tiff, el nmero de banda y la direccin de
          memoria donde dejar los datos
SALIDAS:  Lgica, que indica que todo ha ido bien
EJEMPLO:  Tif_LeeBandaBN ( Imagen, 2, Aux )
NOTAS:    1. Se asume que la banda existe
          2. Las bandas se empiezan a numerar en 0
          3. Si la imagen slo tiene una banda, esta funcin
             lee la nica banda, aunque se pida otra

FUNCION:  Tif_LeeImagenBN()
OBJETIVO: Leer los datos que realmente expresan la imagen
          que se est manejando y est en blanco y negro
          sin comprimir
ENTRADAS: Un tiff y la direccin de memoria donde
          dejar los datos
SALIDAS:  Lgica, que indica que todo ha ido bien
EJEMPLO:  Tif_LeeImagenBN ( Imagen, Aux )

FUNCION:  Tif_MuestrasPorPixel()
OBJETIVO: Decir el modo de compresin de la imagen que se
          est manejando
ENTRADAS: Un tiff
SALIDAS:  El nmero de muestras de cada pixel (normalmente
          1  3)
EJEMPLO:  Tif_MuestrasPorPixel ( Imagen )

FUNCION:  Tif_Siguiente()
OBJETIVO: Cargar en memoria el siguiente directorio de imagen
ENTRADAS: Un tiff
SALIDAS:  Lgica, que indica si se ha cargado el directorio
EJEMPLO:  Tif_Siguiente ( Imagen )

FUNCION:  Tif_Tamano()
OBJETIVO: Decir el tamao en octetos de la imagen que
          se est manejando
ENTRADAS: Un tiff
SALIDAS:  El tamao en octetos que ocupa la imagen o cero si
          no se ha podido calcular
EJEMPLO:  Tif_Tamano ( Imagen )

FUNCION:  Tif_TamanoBanda()
OBJETIVO: Decir el tamao de una banda de la imagen que
          se est manejando
ENTRADAS: Un tiff y el nmero de banda
SALIDAS:  El tamao en octetos que ocupa la banda o cero si
          no se ha encontrado
EJEMPLO:  Tif_TamanoBanda ( Imagen, 2 )
NOTAS:    1. Se asume que la banda existe
          2. Las bandas se empiezan a numerar en 0
          3. Si la imagen slo tiene una banda, esta funcin
             da el tamao de la nica banda, aunque se pida otra

FUNCION:  Tif_TotalBanda()
OBJETIVO: Decir el nmero total de bandas de la
          imagen que se encuentre en memoria
ENTRADAS: Un tiff
SALIDAS:  El total de bandas
EJEMPLO:  Tif_TotalBanda ( Imagen )

FUNCION:  Tim_Ano()
OBJETIVO: Decir el ao en curso
ENTRADAS: Ninguna
SALIDAS:  El ao en curso
EJEMPLO:  Tim_Ano ()

FUNCION:  Tim_Crono()
OBJETIVO: Obtener una referencia temporal de precisin
ENTRADAS: Ninguna, se consulta el reloj del sistema
SALIDAS:  Un nmero real que indica el nmero de segundos
          desde la medianoche
NOTA:     Esta funcin no tiene la misma precisin en
          TurboC y en C68
EJEMPLO:  Tim_Crono()

FUNCION:  Tim_Dia()
OBJETIVO: Decir el da en curso
ENTRADAS: Ninguna
SALIDAS:  El da en curso
EJEMPLO:  Tim_Dia ()

FUNCION:  Tim_Espera()
OBJETIVO: Suspender la ejecucin del programa durante
          cierto tiempo
ENTRADAS: El tiempo en segundos
SALIDAS:  Ninguna
EJEMPLO:  Tim_Espera (0.5)

FUNCION:  Tim_Hora()
OBJETIVO: Decir la hora en curso
ENTRADAS: Ninguna
SALIDAS:  La hora en curso
EJEMPLO:  Tim_Hora()

FUNCION:  Tim_Mes()
OBJETIVO: Decir el mes en curso
ENTRADAS: Ninguna
SALIDAS:  El mes en curso
EJEMPLO:  Tim_Mes ()

FUNCION:  Tim_Minuto()
OBJETIVO: Decir el minuto en curso
ENTRADAS: Ninguna
SALIDAS:  El minuto en curso
EJEMPLO:  Tim_Minuto()

FUNCION:  Tim_Segundo()
OBJETIVO: Decir el segundo en curso
ENTRADAS: Ninguna
SALIDAS:  El segundo en curso
EJEMPLO:  Tim_Segundo()

FUNCION:  Trz_Crea()
OBJETIVO: Crear un trozo
ENTRADAS: La fila superior, la columna izquierda, la fila
          inferior y la columna derecha, todo en caracteres
SALIDAS:  Un trozo o NIL si no se puede crear
EJEMPLO:  Trz_Crea (3,4,14,70)

FUNCION:  Trz_Destruye()
OBJETIVO: Destruir un objeto trozo, liberando su memoria
ENTRADAS: El trozo
SALIDAS:  Ninguna
EJEMPLO:  Trz_Destruye ( Panel )

FUNCION:  Trz_Restituye()
OBJETIVO: Restituir un trozo a un lugar de la pantalla
ENTRADAS: El trozo, la fila superior y la columna izquierda
          en donde se desea hacer la restitucin
SALIDAS:  Lgica, que indica si se ha podido realizar
          la restitucin
EJEMPLO:  Trz_Restituye (Panel,3,4)

FUNCION:  Usr_Avisa()
OBJETIVO: Avisar al usuario de algo
ENTRADAS: El texto del aviso
SALIDAS:  Ninguna
EJEMPLO:  Usr_Avisa ( "Operacin incorrecta" )

FUNCION:  Usr_BorraZona()
OBJETIVO: Borrar la zona de interaccin con el usuario
ENTRADAS: El nuevo color de la zona
SALIDAS:  Ninguna
EJEMPLO:  Usr_BorraZona ( NEGRO )

FUNCION:  Usr_Consulta()
OBJETIVO: Preguntar algo al usuario
ENTRADAS: El texto de la pregunta
SALIDAS:  Lgica, segn la contestacin del usuario
EJEMPLO:  Usr_Consulta ( "Quieres seguir?" )

FUNCION:  Usr_Edita()
OBJETIVO: Implementar un pequeo editor de texto
ENTRADAS: Una regin donde realizar la edicin y el
          texto inicial
SALIDAS:  Una cadena con el texto editado
EJEMPLO:  Usr_Edita (RegionTexto,"")
NOTAS:    1. La cadena hay que destruirla cuando no
             sea necesaria
          2. El fin de lnea se marca con un solo carcter,
             el '\r'
          3. El usuario dispone de varias teclas para editar
             el texto que no aparecen en la ayuda de pantalla:
               Arriba, abajo, izquierda y derecha: mueven
                 el cursor
               Suprimir: borra el carcter del cursor
               Retroceso: borra el carcter a la izquierda
                 del cursor
               Inicio: comienzo de lnea
               Fin: fin de lnea
               RePag: retrasa una pantalla
               AvPag: avanza una pantalla
               Control-RePag: comienzo de texto
               Control-AvPag: fin de texto
           4. Las lneas slo se manejan hasta la anchura
              de la regin

FUNCION:  Usr_Entero()
OBJETIVO: Devolver un nmero determinado por el usuario
          despus de editar el que se le ofrece
ENTRADAS: El nmero que hay que editar, el ancho asignado,
          los valores mnimo y mximo admitidos, las
          coordenadas donde se edita y los colores
SALIDAS:  El entero editado
EJEMPLO:  Usr_Entero (100,4,-900,2000,1,1,BLANCO,NEGRO)

FUNCION:  Usr_ErrorFatal()
OBJETIVO: Informar al usuario de que se ha producido un
          error irrecuperable y abortar el programa
ENTRADAS: El texto del informe
SALIDAS:  Ninguna, el programa aborta
EJEMPLO:  Usr_ErrorFatal ( "Error: faltan recursos." )

FUNCION:  Usr_Indica()
OBJETIVO: Mandar un mensaje al usuario
ENTRADAS: Dos cadenas
SALIDAS:  Ninguna
EJEMPLO:  Usr_Indica ( "Elige una opcin", "Pulsa ENTER" )

FUNCION:  Usr_Informa()
OBJETIVO: Mandar un mensaje al usuario
ENTRADAS: El texto del mensaje
SALIDAS:  Ninguna
EJEMPLO:  Usr_Informa ( "Calculando" )

FUNCION:  Usr_PulsaUnaTecla()
OBJETIVO: Mandar un mensaje al usuario y esperar que pulse
          una tecla
ENTRADAS: El texto del aviso
SALIDAS:  Ninguna
EJEMPLO:  Usr_PulsaUnaTecla ( "Operacin terminada." )

FUNCION:  Usr_Texto()
OBJETIVO: Devolver una cadena determinada por el usuario
          despus de editar la que se le ofrece
ENTRADAS: La cadena que hay que editar, el ancho asignado,
          las coordenadas donde se edita y los colores
SALIDAS:  Una cadena
NOTA:     La cadena devuelta hay que destruirla cuando no
          sea necesaria
EJEMPLO:  Usr_Texto ("Artesonado",20,1,1,BLANCO,NEGRO)

FUNCION:  Zon_Alto()
OBJETIVO: Decir la altura en escala de una zona
ENTRADAS: La zona
SALIDAS:  Un nmero real que indica la altura en escala
EJEMPLO:  Zon_Alto ( Imagen )

FUNCION:  Zon_AltoFisico()
OBJETIVO: Decir la altura en pixels de una zona
ENTRADAS: La zona
SALIDAS:  Un contador que indica la altura fsica
EJEMPLO:  Zon_AltoFisico ( Imagen )

FUNCION:  Zon_Ancho()
OBJETIVO: Decir la anchura en escala de una zona
ENTRADAS: La zona
SALIDAS:  Un nmero real que indica la anchura en escala
EJEMPLO:  Zon_Ancho ( Imagen )

FUNCION:  Zon_AnchoEnOxel()
OBJETIVO: Decir la anchura en oxels de una zona
ENTRADAS: La zona
SALIDAS:  Un contador que indica la anchura en oxels
EJEMPLO:  Zon_AnchoEnOxel ( Imagen )

FUNCION:  Zon_AnchoFisico()
OBJETIVO: Decir la anchura en pixels de una zona
ENTRADAS: La zona
SALIDAS:  Un contador que indica la anchura fsica
EJEMPLO:  Zon_AnchoFisico ( Imagen )

FUNCION:  Zon_Bloque()
OBJETIVO: Dibujar un bloque rectangular
ENTRADAS: Una zona, las coordenadas de dos puntos
          diagonalmente opuestos del bloque y el color
SALIDAS:  La zona
EJEMPLO:  Zon_Bloque ( Imagen, 20.4, 15.8, 59.0, 12.7, ROJO )

FUNCION:  Zon_Borra()
OBJETIVO: Borrar una zona con un color
ENTRADAS: La zona y un octeto que indica el color
SALIDAS:  Ninguna
EJEMPLO:  Zon_Borra ( Imagen, NEGRO )

FUNCION:  Zon_Crea()
OBJETIVO: Crear una zona
ENTRADAS: La fila superior, la columna izquierda, la fila
          inferior y la columna derecha, todo en caracteres
SALIDAS:  Una zona o NIL si no se puede crear
NOTA:     La zona queda iniciada con una escala de 100
          unidades de altura y de anchura, con el origen
          situado en la esquina inferior izquierda
EJEMPLO:  Zon_Crea (3,4,14,70)

FUNCION:  Zon_Destruye()
OBJETIVO: Eliminar una zona, liberando memoria
ENTRADAS: La zona
SALIDAS:  Ninguna
EJEMPLO:  Zon_Destruye ( Imagen )

FUNCION:  Zon_Escala()
OBJETIVO: Establecer la escala que se usar al manejar
          una zona
ENTRADAS: La zona y nmeros reales que indican la anchura,
          la altura y el origen de coordenadas
SALIDAS:  La zona
NOTA:     El signo de la anchura y la altura indican la
          direccin que se va a considerar positiva. Un
          valor positivo indica respecto a la convencin
          (horizontal es positivo hacia la derecha, vertical
          es positivo hacia arriba), mientras que un valor
          negativo invierte la convencin. El origen tambin
          se cuenta en un extremo de la zona o en otro segn
          estos signos.
EJEMPLO:  Zon_Escala (Imagen, 4.5, 2.8, 2.3, 1.4)

FUNCION:  Zon_Linea()
OBJETIVO: Dibujar una lnea de un color
ENTRADAS: Una zona, las coordenadas de los extremos y
          el color
SALIDAS:  La zona
EJEMPLO:  Zon_Linea ( Imagen, 20.4, 15.8, 59.0, 12.7, ROJO )
NOTA:     El algoritmo usado es lento, hay que mejorarlo.
          (El "clipping" hay que hacerlo antes de dibujar
          la lnea, no cuando se dibuja cada punto)

FUNCION:  Zon_OrigenX()
OBJETIVO: Decir el origen de abscisas en escala de una zona
ENTRADAS: La zona
SALIDAS:  Un nmero real que indica el origen de abscisas
          en escala
EJEMPLO:  Zon_OrigenX ( Imagen )

FUNCION:  Zon_OrigenY()
OBJETIVO: Decir el origen de ordenadas en escala de una zona
ENTRADAS: La zona
SALIDAS:  Un nmero real que indica el origen de ordenadas
          en escala
EJEMPLO:  Zon_OrigenY ( Imagen )

FUNCION:  Zon_Oxel()
OBJETIVO: Dibujar un oxel de una zona de un color
ENTRADAS: La zona, los valores "x" e "y" del oxel, la
          mscara de dibujo y el color
SALIDAS:  Lgica, indicando si se ha podido dibujar
NOTAS:    1. Los valores "x" e "y" se cuentan a partir de 0
             desde la izquierda y desde arriba
             respectivamente
EJEMPLO:  Zon_Oxel ( Imagen, 6, 7, 0xFF, ROJO )

FUNCION:  Zon_OxelSeguro()
OBJETIVO: Dibujar un oxel que pertenezca a una zona
          de un color
ENTRADAS: La zona, los valores "x" e "y" del oxel, la
          mscara de dibujo y el color
SALIDAS:  SI, ya que debe poder ejecutarse
NOTAS:    1. Los valores "x" e "y" se cuentan a partir de
             0 desde la izquierda y desde arriba
             respectivamente
          2. Para ejecutar esta funcin el oxel debe
             pertenecer a la zona
EJEMPLO:  Zon_OxelSeguro ( Imagen, 0, 5, 0xFF, ROJO )

FUNCION:  Zon_Pixel()
OBJETIVO: Dibujar un pixel de una zona de un color
ENTRADAS: La zona, los valores "x" e "y" del pixel y el color
SALIDAS:  Lgica, indicando si se ha podido dibujar
NOTA:     Los valores "x" e "y" se cuentan a partir de 0
          desde la izquierda y desde arriba respectivamente
EJEMPLO:  Zon_Pixel ( Imagen, 3, 8, ROJO )

FUNCION:  Zon_PixelSeguro()
OBJETIVO: Dibujar un pixel que pertenezca a una zona
          de un color
ENTRADAS: La zona, los valores "x" e "y" del pixel y el color
SALIDAS:  SI, ya que debe poder ejecutarse
NOTAS:    1. Los valores "x" e "y" se cuentan a partir de 0
             desde la izquierda y desde arriba
             respectivamente
          2. Para ejecutar esta funcin el pixel debe
             pertenecer a la zona
EJEMPLO:  Zon_PixelSeguro ( Imagen, 3, 8, ROJO )

FUNCION:  Zon_Punto()
OBJETIVO: Dibujar un punto de una zona de un color
ENTRADAS: La zona, los valores "x" e "y" del punto (en
          escala) y el color
SALIDAS:  Lgica, indicando si se ha podido dibujar
EJEMPLO:  Zon_Punto ( Imagen, 21.3, 82.7, ROJO )

FUNCION:  Zon_PuntoSeguro()
OBJETIVO: Dibujar un punto de una zona de un color
ENTRADAS: La zona, los valores "x" e "y" del punto (en
          escala) y el color
SALIDAS:  SI, ya que debe poder ejecutarse
NOTA      Para ejecutar esta funcin el punto debe
          pertenecer a la zona
EJEMPLO:  Zon_PuntoSeguro ( Imagen, 21.3, 82.7, ROJO )




Descripcin interna
===================

En este captulo voy a explicar las caractersticas internas de Olimpo, cmo
est concebido y desarrollado. Para usar el sistema no es necesario leer este
captulo, pero para introducir cambios en Olimpo, s. De todos modos, aunque no
vayas a cambiar nada el Olimpo, te recomiendo que lo leas; normalmente se
maneja mejor una herramienta cuanto mejor se conoce.

Ya se vio en el captulo "Descripcin del sistema" que Olimpo est formado por
una serie de objetos que son independientes entre s. Al menos, se pretende que
lo sean tanto como sea posible.

Los objetos estn colocados en forma de pirmide, unos se apoyan en otros: se
comienza con objetos de bajo nivel, que se comunican directamente con el
hardware y hay que reescribir cuando se intenta llevar el sistema a una
plataforma distinta. Estos objetos permiten uniformizar el tratamiento de las
funciones de bajo nivel y sobre ellos se puede construir objetos ms abstractos
que dan servicios ms complejos. Los objetos de alto nivel pueden usar los de
bajo nivel, pero nunca al revs.


Componentes de un objeto
------------------------

En cada objeto se puede encontrar:

El identificador: tres letras que permiten referirse al objeto con toda
sencillez.

La abreviatura: algunos nombres de objetos tienen ms de ocho caracteres o
acentos. La abreviatura es una manera ms corta de referirse al objeto, de modo
que con un mximo de ocho caracteres sea posible referirse al objeto y aun as
sea fcilmente identificable.

El fichero de descripcin: un fichero .des en el que se describen los objetos
de los que depende y los ficheros de que se compone. Lo utiliza el programa
Zeus, por lo que se explican con detalle en el captulo "El programa Zeus".

El fichero de cabecera: un fichero .h en el que se encuentra una relacin de
todas los funciones que tiene el objeto, as como las definiciones de tipos,
variables globales, declaraciones de funciones y cualquier otra informacin
general sobre el objeto que pueda resultar de inters. El mejor modo de empezar
a estudiar un objeto es consultar este fichero. Tiene como nombre la
abreviatura del objeto.

El fichero def: un fichero con extensin .def en el que se encuentra la
definicin de algunas variables globales. Son pocos los objetos que tienen este
fichero y probablemente en prximas versiones de Olimpo desaparezcan. Tiene
como nombre la abreviatura del objeto.

Los ficheros de funciones: los ficheros .c donde se encuentran las definiciones
de aquellas funciones de Olimpo que no son simples macros. El cdigo est
dividido en la mayor cantidad posible de ficheros para facilitar la realizacin
de cambios. Los nombres de estos ficheros tienen como sus tres primeras letras
el identificador del objeto y las otras cinco pretenden reflejar la funcin ms
importante que definen.

El fichero de validacin: es un fichero .c que permite validar el objeto, es
decir, comprobar que todas las funciones son correctas. Se nombra con la
inicial V seguida de las tres letras del identificador del objeto. Se compila
para formar un ejecutable mediante un fichero makefile creado por el programa
Zeus.

Los ficheros auxiliares: algunos objetos necesitan ficheros para realizar la
validacin. La mayor parte de estos ficheros son generados por el propio
programa de validacin, pero hay otros que deben estar creados de antemano.


Tipos de funciones
------------------

En un objeto hay muchas funciones, y slo una parte de ellas son las que ve el
usuario que utiliza Olimpo. He clasificado las funciones en tres tipos
distintos:

Funciones pblicas: son aquellas que se documentan en el manual, las que ve el
usario que programa con Olimpo. Al ser las ms visibles, es muy importante
cambiarlas lo menos posible de una versin a otra.

Funciones conocidas: son funciones de un objeto que son usadas por otros
objetos. Lo ideal sera que no hubiera ninguna, pero ya que las hay, es
necesario tocarlas con cuidado, ya que sus cambios influyen en otros objetos.

Funciones privadas: son las funciones que necesita un objeto para su propio
funcionamiento. Por tanto, se pueden cambiar y retocar sin mayor problema que
adaptar el cdigo interno de ese objeto.

A continuacin voy a exponer para cada objeto algunas consideraciones sobre su
diseo.


General
-------

Aqu se encuentran todas aquellas definiciones absolutamente generales a todo
Olimpo, que son usadas por los dems objetos. Es el lugar idneo para colocar
macros que dirijan el comportamiento global de una aplicacin as como tipos
numricos.


Memoria
-------

Las funciones que reservan, liberan, ajustan y dan valores a la memoria son
simples alias de las funciones que proporciona la librera estndar C. Sera
interesante aadir la posibilidad de reservar ms de 64K en un PC.

Si se desea incorporar un gestor de memoria propio, ste es el lugar idneo.

Las funciones que leen y escriben datos en memoria en distintos formatos y
tipos son muy sencillas, ya que se basan simplemente en intercambiar octetos en
memoria.


Pantalla
--------

ste es el objeto ms importante del sistema. Todas las aplicaciones escritas
con Olimpo deberan usar Pan_Define() y Pan_Cierra() al principio y al final,
de modo que en esas dos funciones se puede poner todo el cdigo de preparacin
y cierre de la pantalla que sea necesario: carga de fuentes, preparacin de
colores, posible almacenamiento de la pantalla anterior, etc.

El cdigo del objeto Pantalla est triplicado, ya que hay que manejar de modo
completamente distinto el QL, el PC en modo texto y el PC en modo grfico.

Para el QL utilizo funciones especficas de C68, que llaman directamente a
funciones QDOS.

Para el PC en modo texto confo en las funciones suministradas por Turbo C, que
parecen ser perfectamente compatibles con cualquier PC.

Para manejar el PC en modo grfico utilizo mi propio cdigo. Necesito mantener
varias variables globales con la informacin de los colores, del resaltado y
alguna ms. La funcin ms importante es la que escribe un carcter en modo
grfico. Todas las dems funciones que escriben en la pantalla la utilizan. La
tabla de caracteres que se usa est en ROM, y la voy leyendo para ir
"dibujando" cada carcter en pantalla.

En el objeto Pantalla se encuentran bastantes funciones conocidas que se usan
en otros objetos. Esto hace que sea especialmente delicada la implementacin.
Los objetos Trozo, Zona y Cuadro utilizan profusamente estas funciones
conocidas.


Azar
----

Este objeto utiliza funciones ANSI C para la generacin de nmeros aleatorios y
efecta una llamada al reloj del sistema para tomar como semilla un nmero que
sea realmente aleatorio.

Si las rutinas suministradas no fueran lo suficientemente aleatorias, se podra
usar algn otro algoritmo de generacin de nmeros aleatorios.

El objeto Azar slo genera nmeros enteros, ya que lo considero suficiente. Es
fcil obtener nmeros decimales a partir de nmeros enteros.


Tiempo
------

Hay dos tipos de funciones en este objeto: las que simplemente leen el reloj
del sistema y las que necesitan una cierta precisin midiendo lapsos.

Las que leen el reloj del sistema no presentan ninguna dificultad, pero las
otras confan en la resolucin del reloj interno del ordenador y no pueden dar
la misma precisin en un QL, que slo actualiza su reloj 50 veces por segundo,
que en un PC, en el que se pueden medir lapsos de tiempo al milisegundo.


Sonido
------

Aunque la generacin de sonido es completamente distinta en QL y en el PC, la
implementacin de este objeto es muy sencilla, ya que lo nico que necesito es
generar pequeas seales indicadoras, y es suficiente que sean parecidas, no se
requiere que sean idnticas. Usando la funcin interna Son_Ejecuta(), es fcil
aadir ms sonidos.


Carcter
--------

Lo ms importante de este objeto es saber que slo maneja una de las posibles
tablas del PC, la ms usual, y si el ordenador donde se ejecute una aplicacin
no tiene cargada esa tabla, habr cosas que no funcionen correctamente.

La implementacin del objeto Carcter requiere mucha paciencia, ya que hay que
ir recorriendo las dos tablas (QL y PC) y anotando cada valor en una variable
interna de Olimpo.

No hay ningn problema de rendimiento cuando se usa este objeto, ya que toda la
informacin se encuentra en tablas de acceso directo.


Lista
-----

El objeto lista es muy cmodo de escribir y mantener, ya que nicamente es
necesario utilizar C de modo normal junto con algunas funciones sencillas de
Olimpo.

Las listas se mantienen en memoria, lo que permite manejar listas de gran
tamao muy rpidamente, siempre y cuando haya memoria suficiente.


Trozo
-----

La implementacin de este objeto, como el objeto Pantalla, necesita un esfuerzo
triple.

Para implementarlo en el PC en modo texto utilizo funciones especficas de
Turbo C.

Para hacerlo en el PC en modo grfico manejo directamente el contenido de la
memoria grfica de la pantalla VGA.

Para hacerlo en el QL he tenido que usar mis propias ideas, puesto que no he
encontrado ningn sitio en que se usara la tcnica necesaria. El cdigo es un
poco complicado, pero es rpido.


Zona
----

El manejo de grficos debe ser rpido para poder ser til, de modo que el
objeto Zona accede directamente a la memoria de vdeo de cada ordenador.

En el QL, estoy suponiendo que la pantalla comienza en 131072, lo que puede no
ser correcto en todos los sistemas QDOS, aunque suele funcionar.

En el PC, la nica posibilidad es que se disponga de tarjeta VGA, aunque creo
que sera sencillo aadir cdigo que manejara una EGA o una SVGA. En todo caso,
las funciones del objeto Zona se implementan de modo que no haya ningn
problema al cambiar de resolucin. Antes habra que retocar el objeto Pantalla
para que funcionara correctamente con todas las tarjetas que se desearan
aadir.

La idea que dirige el desarrollo de este objeto es usar lo ms que sea posible
funciones de alto nivel que dibujen figuras usando algoritmos generales y
usando las funciones de ms bajo nivel que acceden a los pixels fsicos.


Cadena
------

La implementacin de este objeto se basa en las funciones ANSI C que manejan
cadenas, con la ayuda del objeto Carcter en aquellos lugares a los que el ANSI
C no llega.

Casi todas las funciones de este objeto consideran que el primer carcter de la
cadena es el nmero 1. Esto no sigue la costumbre habitual del C, pero resulta
til. Las funciones que empiezan a contar el 0 son aquellas que realmente el
usuario no necesita muy a menudo, sino que utilizan otros objetos de Olimpo.


Programa
--------

La implementacin de este objeto es elemental y no merece mayor comentario.


Fecha
-----

De una fecha slo se mantiene en memoria su ao, mes y da; todo lo dems hay
que calcularlo en el momento. Es importante la funcin interna Fec_Factor().


Tecla
-----

Lo ms importante en la implementacin de este objeto es el modo en que se
tratan aquellas teclas que no generan un slo cdigo, sino dos. A las que
generan dos cdigos les doy valores obtenidos sumando 255 al cdigo principal.
Esto permite que cada tecla tenga asignada un nmero distinto. Por fin, la
coleccin de macros hace que todos los detalles queden ocultos.

Dado que el PC y el QL no tienen el mismo teclado ni la misma orientacin en la
manera de asignar cdigos, es posible realizar distintas asociaciones entre las
teclas de cada uno. Yo he elegido la que me parece ms usual, pero no hay
reglas fijas.

Parece lgico no contemplar aquellas combinaciones de teclas que no son
reproducibles en ambos ordenadores, pero Olimpo se puede extender de modo no
compatible asignando valores a teclas especficas.


Cuadro
------

Dado que el QL no dispone de caracteres semigrficos y el PC en modo texto no
tiene capacidad grfica, la implementacin de los cuadros es absolutamente
distinta en ambos ordenadores.

En el QL se realizan los cuadros dibujando lneas de distintos grosores y en el
PC se hace creando cadenas con caracteres semigrficos.


Regin
------

La implementacin de este objeto es muy simple, ya que se basa en llamar a
funciones que ya estaban definidas en otros objetos. Por tanto, es muy fcil
aadir ms funciones que puedan resultar tiles.


Usuario
-------

La implementacin de este objeto supone una de las ms importantes decisiones
de diseo de Olimpo, ya que muchos objetos lo van a utilizar.

El objeto Usuario se instala en las dos filas ms bajas de la pantalla por
decisin arbitraria y personal, pero mi idea es que todas las funciones puedan
seguir siendo utilizadas del mismo modo incluso si se decide implementar el
objeto de manera distinta.

Una posible implementacin alternativa del objeto Usuario es por medio de
ventanas que aparezcan en cualquier lugar de la pantalla y se oculten cuando no
sean necesarias.

La funcin Usr_Edita() es atpica; convendra mejorarla, darle ms
posibilidades y convertir el cdigo resultante en un objeto nuevo.


Fichero
-------

Este objeto utiliza las funciones normales del ANSI C para abrir, leer,
escribir y cerrar ficheros, pero atrapando los errores que se pueden producir
en el proceso. El objetivo es que el usuario programador no tenga que
preocuparse de eso. El objeto Fichero debe informar al usuario final de los
errores que se produzcan. El programador puede adems consultar el valor
devuelto por las funciones.

La funcin Fch_ListaNombre() es dependiente del compilador usado.


Men
----

En los mens horizontales no se comprueba la apariencia en que quedarn las
opciones en la pantalla; es responsabilidad del programador el que queden todas
las opciones correctamente presentadas.

Este objeto depende exclusivamente de objetos anteriores de Olimpo, por lo que
su recompilacin no debera dar ningn problema.


Configuracin
-------------

Este objeto depende exclusivamente de objetos anteriores de Olimpo, por lo que
su recompilacin no debera dar ningn problema.


BaseDato
--------

Aconsejo que se utilicen bases de datos generadas por distintas aplicaciones
para probar las funciones de este objeto.


Memo
----

Aconsejo que se usen ficheros memo generados por distintas aplicaciones para
probar este objeto.


Indice
------

Evidentemente, el funcionamiento de este objeto debe ser validado con ndices
generados por aplicaciones escritas en Clipper.


Diblane
-------

Este objeto utiliza exclusivamente objetos anteriores de Olimpo, pero para
poder ser til normalmente se utilizar leyendo los datos desde ficheros
grficos, por lo que habr que tener cuidado con las funciones que importen y
exporten datos.


Tiff
----

Existen muchos programas que manejan ficheros TIFF, de modo que es fcil
comprobar de distintas formas el funcionamiento de este objeto. Si algo no
funciona bien con algn programa comercial, no siempre hay que pensar que el
cdigo de Olimpo es lo que falla; varias veces he encontrado errores en
programas comerciales. En esos casos, es til hacer comprobaciones entre
ficheros creados por esas aplicaciones.




El programa de ayuda
====================

Cuando se desarrolla o retoca Olimpo hay que realizar varias tareas adems de
escribir cdigo. Para realizarlas ms fcilmente he escrito unas pequeas
rutinas que explicar brevemente en este captulo.

Las rutinas han sido implementadas como ficheros .BAT en el PC y como
procedimientos del programa Soporte_bas en el QL.

Para poder usarlas debes estar situado en el directorio donde has descomprimido
los fuentes; por ejemplo, Win1_Olimpo en el QL y C:\Olimpo en el PC.


Arranque de la ayuda
--------------------

En el PC, teclea

Ayuda

En el QL, teclea

LRUN Soporte_bas

Esto te dar una pantalla de ayuda con la lista de las utilidades disponibles y
el orden de los objetos de OLimpo.

Cuando quieras volver a ver la pantalla de ayuda basta que teclees

Ayuda


M
-

Con M se invoca make con un nombre de fichero makefile. Si tienes un fichero
makefile llamado Ejemplo.mak y quieres que make lo procese tienes que teclar

En el QL

M "Ejemplo"

En el PC

M Ejemplo


Zeus
----

Es un programa ejecutable; se explica en detalle en el captulo "El programa
Zeus"


CreaLib
-------

Cuando se compila un fichero .c se genera un fichero objeto (que no hay que
confundir con los objetos de la programacin orientada al objeto). Estos
ficheros objeto se renen en un fichero de librera mediante el programa TLIB
con Turbo C++ y con el programa slb con C68.

Con CreaLib se dirije este proceso automticamente, usando el fichero
Olimpo.lst, que se debe crear con Zeus.

En el QL hay que usar la utilidad Examina antes de usar CreaLib.


Mdemo
-----

Cuando se han creado los ficheros del sistema Olimpo.h y Olimpo.lib se puede
compilar el programa de demostracin. Con esta utilidad se ordena compilar y
montar adecuadamente este programa


PrepCop
-------

Cuando se tiene preparado el sistema completo, hay que copiarlo en un disquete
para su distribucin. Con esta ultilidad se crean los ficheros comprimidos que
se entregan con Olimpo.


Copia
-----

Una vez ejecutada la utilidad PrepCop, Copia realiza la copia de los ficheros
de distribucin de Olimpo a un disquete.


Salva
-----

Cuando se desarrolla un programa, incluso pequeo, es imprescincible realizar
copias de seguridad del trabajo. Con Copia se realiza una copia comprimida de
los ficheros imprescindibles de Olimpo.




El programa Zeus
================

Olimpo tiene tales dimensiones que resultara incmodo realizar manualmente
todas las tareas que requiere su desarrollo. Zeus permite generar
automticamente muchos ficheros que sufren cambios a menudo a partir de unos
ficheros de descripcin, que son mucho ms fciles de modificar.

Se necesita un fichero de descripcin general, llamado Olimpo.des, y un fichero
de descripcin para cada objeto.

Zeus permite generar:

* Los ficheros makefile que dirigen la creacin de los programas de validacin.

* El fichero Olimpo.h, uno de los esenciales del sistema.

* El fichero Olimpo.lst, usado por la utilidad CreaLib para generar Olimpo.lib.

* El fichero Olimpo.doc, que rene las cabeceras de todas las funciones
pblicas; se usa para crear el captulo "Relacin alfabtica de funciones" del
manual.


Compilacin de Zeus
-------------------

Para usar Zeus primero hay que compilarlo. Est escrito en C K&R, por lo que
debera funcionar con cualquier compilador de C.

Tiene un macro constante, que puede ser QL o PC, para indicar el ordenador en
que se est trabajando.

Hay un fichero makefile, Zeus.mak (distinto en el QL que en el PC), que dirige
la compilacin de Zeus. Por tanto, para crear Zeus.exe basta teclear en el QL

M "Zeus"

y en el PC

M Zeus


Los ficheros de descripcin
---------------------------

Son simples ficheros ASCII. Slo se lee la primera palabra de cada lnea, de
modo que se pueden insertar comentarios en cada lnea. Si una lnea comienza
con el carcter '*' se considera comentario la lnea completa. Se pueden
insertar lneas en blanco.

En el fichero de descripcin Olimpo.des se anotan las abreviaturas de todos los
objetos que constituyen Olimpo, en el orden en que deben ser comprobados.

Los dems ficheros de descripcin (uno por objeto) tienen como nombre la
abreviatura de cada objeto y como extensin des. Se componen de cuatro partes:

1. Nombre, identificador y abreviatura del objeto; deben estar en este orden y
deben estar los tres.

2. Requisitos. A partir de la palabra Requisito se deben escribir las
abreviaturas de los objetos necesarios para el desarrollo de ste.

3. Fuentes. A partir de la palabra Fuente se deben escribir los nombres de los
ficheros fuentes que constituyen el objeto. Los nombres se escriben sin
extensin.

4. Cabeceras. A partir de la palabra Cabecera se deben escribir las extensiones
de los ficheros de cabecera del objeto. El nombre de estos ficheros deber ser
la abreviatura del objeto.


Uso de Zeus
-----------

Una vez preparados los ficheros de descripcin y compilado Zeus, se puede
utilizar, lo que debe resultar muy sencillo, ya que se van presentando las
opciones disponibles en pantalla.

Por sencillez de implementacin, cuando Zeus encuentra un error aborta su
ejecucin con un mensaje indicativo del error.




Cmo hacer cambios
==================

Veo dos maneras distintas de efectuar cambios en Olimpo: una rpida y
arriesgada y otra ms lenta y segura.


Cambios rpidos
---------------

El mtodo sera:

1. Modificar los ficheros requeridos

2. Recompilar todos los ficheros. Esto se puede hacer con una sola orden.

En el QL

EX CC ; "-c *_c"

En el PC

TCC -c *.c

Si se desea crear Olimpo.lib con un modelo de memoria distinto del
suministrado, basta usar la opcin correspondiente al compilar todos los
ficheros. Por ejemplo, si se desea crear una versin de Olimpo.lib para el
modelo "Large", se usar esta orden:

TCC -c -ml *.c

3. Usando Zeus y las utilidades de ayuda, reconstruir los ficheros Olimpo.h y
Olimpo.lib.


Cambios seguros
---------------

Al ser un sistema orientado al objeto, los cambios deben efectuarse
internamente en cada objeto, procurando no mezclar las implementaciones de
distintos objetos y conservando la estructura de pirmide explicada en el
captulo "Descripcin interna".

Cuando se realiza un cambio en un objeto, hay que comprobar si ese cambio
afecta a otros objetos que dependan de l, por lo que es muy aconsejable seguir
el orden dado.

Una vez realizados cambios en un objeto, se debe usar el programa de validacin
correspondiente. Si es necesario, hay que modificar el fichero de descripcin
del objeto y volver a generar el fichero makefile usando el programa Zeus.

Si se aaden funciones nuevas, tambin habra que escribir cdigo para
comprobarlas.

Una vez terminados los cambios, basta reconstruir los fichero Olimpo.h y
Olimpo.lib usando el programa Zeus y las utilidades de ayuda.




Normas de codificacin
======================

Cuando un programa o sistema informtico alcanza un cierto tamao resulta de
mucha importancia que la codificacin sea lo ms uniforme posible. Eso favorece
la claridad del cdigo y la facilidad de hacer modificaciones.

El estilo de codificacin es algo bastante personal, sin que pueda decirse en
muchos casos que unas prcticas sean mejores o peores que otras. Lo importante
es que exista y se siga con fidelidad.


Estructura de los ficheros
--------------------------

Los ficheros .h y .c de Olimpo siguen una misma estructura. En el caso de los
.h, deben aparecer todos los apartados, aunque no tengan contenido. En el caso
de los .c, admito que los apartados que estn vacos desaparezcan, por
sencillez. sta es la estructura:

Cabecera de fichero. Donde se escriben los datos genricos del fichero.

Relacin de funciones. Especificando las funciones pblicas, conocidas y
privadas.

Ficheros de cabecera. Especificando las funciones y estructuras que se utilizan
de cada fichero, salvo las de Olimpo.

Definicin de macros constantes.

Definicin de tipos.

Declaracin de variables globales.

Declaracin de funciones.

Definicin de macros funciones.

En los ficheros .c aparece, adems, como ltimo apartado

Definicin de funciones.


Eleccin de nombres
-------------------

Los tipos se nombran con letras minsculas y un mximo de 8 caracteres, con la
excepcin de algunos tipos auxiliares.

Los macros constantes se nombran con letras maysculas y comienzan con el
identificador del objeto a que pertenecen seguido del carcter '_' (subrayado).

Las variables se nombran con letras maysculas y minsculas: Cuando estn
formadas por varias palabras, la inicial de cada palabra va en mayscula. No se
utiliza el carcter subrayado.

Las funciones, tanto las definidas como macros como las autnticas funciones,
se nombran como las variables, pero anteponiendo el identificador del objeto
seguido del carcter subrayado.




Historia de las versiones
=========================

La idea de realizar Olimpo proviene de intentar resolver varios problemas:

* Llevaba mucho tiempo programando y me encontraba que estaba escribiendo las
mismas rutinas una y otra vez. Haba que encontrar el mtodo para utilizar las
rutinas ya escritas en programas nuevos.

* Tengo tres sistemas operativos y me gustara que mis programas funcionaran,
sin cambiar el cdigo, en los tres. El lenguaje que me permite hacer esto es
el C.

* Me gustara escribir mtodos generales de resolucin de problemas para
estudiar inteligencia artificial, pero para poder presentar un programa debe
tener un mnimo interfaz; por tanto, hay que empezar por programar las cosas
bsicas y sobre ellas ir montando mtodos mas complejos.

Cuando se realiza cualquier sistema de programacin es muy aconsejable que las
nuevas versiones no cambien los protocolos de las funciones, para no tener que
retocar el cdigo de un programa escrito sobre el sistema al cambiar de
versin. Desafortunadamente, conforme se va profundizando en un sistema y
aadiendo nuevas posibilidades, se suele descubrir que para mejorar algunas
funciones hay que hacer cambios a veces significativos; por tanto, ser
inevitable que algunas funciones cambien de protocolo conforme aumente el
nmero de versin de Olimpo. Por supuesto, ir documentando los cambios.


Versin 0.0
-----------

Fecha de lanzamiento: V.12.2.1993

Es la versin en la que se comienzan a construir las bases del sistema.

Se dispone de un conjunto de definiciones generales y de 12 objetos:

General, Pantalla, Azar, Tiempo, Cadena, Sonido, Tecla, Usuario, Fichero, Men,
Programa, Cuadro y Configuracin.

El sistema funciona por medio del fichero Olimpo.h, cuyo nico cometido es
llamar a los distintos .h de los objetos. Por tanto, el tiempo de compilacin
es muy elevado.


Versin 0.1
-----------

Fecha de lanzamiento: J.18.2.1993

Reno todos los .h para formar el fichero Olimpo.h.

Retoco el objeto Fichero, aadiendo Fch_Borra() y un manejador de
interrupciones en el PC.


Versin 1.0
-----------

Fecha de lanzamiento: J.15.7.1993

Separo lo ms posible el cdigo en varios ficheros, que compilo por separado, y
creo un fichero de librera. Adems, escribo un programa que permite unir todos
los .h del sistema quitando todas las redundancias y formando Olimpo.h, nico
fichero de cabecera que debe utilizar el programador usuario del sistema.

Reescribo completamente el objeto Cadena, utilizando asignacin dinmica.

El objeto Pantalla en el PC ahora admite trabajar en modo grfico, lo que abre
las posibilidades de crear y aadir objetos grficos a Olimpo en un futuro.

Reescribo completamente los programas de validacin y creo mtodos para el
mantenimiento de los ficheros.

Todas estas funciones han sido retocadas de modo que hay que revisar el cdigo
que las utilice:

Pan_Define(), Pan_Entero(), Usr_Consulta(), Usr_Texto(), Fch_Abre(),
Fch_AbreLeer(), Fch_AbreGrabar(), Fch_LeeLinea(), Fch_EscribeLinea(),
Fch_Nombre() y todas las del objeto Cadena.


Versin 1.1
-----------

Fecha de lanzamiento: Enero 1994

Aado los objetos Zona, Lista y Base de datos.

Aado las funciones Pan_Modo(), Cad_Igual(), Tim_Ano, Tim_Mes(), Tim_Dia(),
Fch_Coloca(), Fch_ColocaFinal() y Fch_AbreActualizar().

Aado el tipo octeto.

Preparo makefiles para la versin QL. Mejoro el programa de soporte.


Versin 1.2
-----------

Fecha de lanzamiento: Abril 1994

Aado los objetos Carcter e Indice.

Aado los tipos entpos y real.

Elimino el tipo tiempo, que debe ser sustituido por el tipo real en todos los
puntos en que aparezca.

La funcin Pan_Resalta() ya tiene efecto en el PC en modo grfico.

Aado las funciones Pan_Real(), Pan_PonReal(), Tim_Hora(), Tim_Minuto(),
Tim_Segundo(), Son_Estado(), Cad_Duplica(), Cad_Compara(), Cad_Convierte(),
Cad_Mayus(), Cad_Minus(), Cdr_Construye() y Fch_ListaNombre().

El objeto Tecla ya maneja bien los caracteres acentuados y muchos ms.

El manejo de nmeros enteros ha sido mejorado en muchas funciones.

La funcin Cad_Une() ha cambiado en su protocolo. Antes el fin de las cadenas
se indicaba mediante NIL, ahora hay que usar CAD_FIN.

Amplo la pila del programa en el QL a 8000 octetos.


Versin 1.3
-----------

Fecha de lanzamiento: Junio 1994.

Esta versin no presenta cambios significativos. Simplemente se corrigen
algunos errores y se ampla la documentacin. Lo ms importante es la aparicin
de un fichero con explicaciones en ingls.

La funcin Bdt_EscribeRegistro() ahora est documentada.


Versin 2.0
-----------

Fecha de lanzamiento: Agosto 1995

Aado los objetos Memoria, Trozo, Regin, Fecha, Memo, Diblane y Tiff.

Aado numerosas funciones en los objetos ya existentes, as como nuevos tipos.

Mejoro numerosas funciones. Mejoro la documentacin en general.

Introduzco el programa Zeus, que permite eliminar los ficheros makefile y los
problemas que llevaban asociados.

El el objeto Tiempo cambian los tipos que devuelven las funciones
Tim_Segundo(), Tim_Minuto(), Tim_Hora(), Tim_Dia() y Tim_Mes().

En el objeto Carcter, elimino la funcin Car_Convierte() y los macros CAR_PC y
CAR_QL. En su lugar se dispone de las funciones Car_ConvierteQLaPC() y
Car_ComviertePCaQL().

En el objeto Cadena, elimino la funcin Cad_Convierte(). En su lugar se dispone
de las funciones Cad_ConvierteQLaPC() y Cad_ComviertePCaQL().

En el objeto Cuadro, elimino la funcin Cdr_Color() y cambio el protocolo de
las funciones que dibujan en pantalla, que ahora deben especificar ellas mismas
los colores que deben usar.

El objeto Fichero sufre cambios sustanciales; cambian el tipo que devuelven
muchas funciones y Fch_Coloca() y Fch_ColocaFinal() cambian incluso el
significado de su respuesta.

Las funciones del objeto Men cambian el tipo de sus parmetros.

En el objeto Configuracin se aade el tipo config, as que hay que retocar
todo el cdigo que utilice este objeto.

El objeto Base de Datos ahora se llama BaseDato.




Errores
=======

Todo el software que conozco tiene errores. Parece que es algo consustancial
con el ser humano: equivocarse. Lo primero que hay que hacer para arreglar un
error es conocerlo. Agredezco la ayuda de todos los usuarios de Olimpo que
encuentran errores en l.


Versin 0.0
-----------

Usr_Consulta() -> En la versin PC el cursor a veces aparece y a veces no. No
he encontrado el patrn del error; sospecho que es problema de la BIOS.

Cad_ConvierteEntero() -> tiene distinta implementacin en QL que en PC y no
estoy seguro de que funcione bien para enteros muy grandes. Arreglado en la
versin 1.2.

Objeto Fichero -> en la versin PC hay que aadir un manejo de interrupciones,
usando harderr(), ya que las interrupciones de hardware, como intentar escribir
un un disquete protegido de escritura, las trata el sistema y rompe el diseo
de la pantalla. Aadido en la versin 0.1.


Versin 1.0
-----------

Usr_Consulta() -> aun habiendo cambiado la funcin Pan_CursorVisible(), el
error presente en la versin 0.0 sigue apareciendo.

Usr_Texto() -> no funciona la tecla cursor derecha cuando el ancho asignado es
igual a la longitud de la cadena. Arreglado en la versin 1.1.

No se puede distribuir un programa en varios ficheros porque al incluir ms de
una vez Olimpo.h se producen errores. Arreglado en la versin 1.1.

Cnf_Lee() -> Deja memoria sin devolver. Arreglado en la versin 1.1.

Men_Horizontal(), Men_Vertical() -> producen errores cuando se mandan ms
opciones de las que pueden manejar. Arreglado en la versin 1.1.

Fch_LeeOcteto() -> no da error cuando no puede leer tantos octetos como se le
pide. Arreglado en la versin 1.1.

Pan_Define() -> una incorrecta implementacin hace que compilando en el PC bajo
el modelo de memoria "Large" se puedan producir errores de ejecucin sin razn
aparente. Arreglado en la versin 2.0.


Versin 1.1
-----------

Objeto Zona -> en el QL hay una pequea discrepancia entre cada zona y los
pixels ms a la derecha que se pueden representar de esa zona. La discrepancia
no se presenta en la QXL.

En la distribucin de los fuentes en el PC faltan los ficheros Zon*.c.
Arreglado en la versin 1.2.

Objeto Pantalla -> Compilando con Borland C++ se producen errores debido a que
muchas funciones retornan valores de tipo distinto segn el modo de pantalla
sea texto o grfico. Arreglado en la versin 1.2.

Cad_Une() -> Compilando bajo el modelo de memoria "Huge" la funcin tiene un
comportamiento incorrecto. Arreglado en la versin 1.2.

Tim_Mes() -> Da el resultado incorrecto casi siempre, en el QL. Arreglado en la
versin 1.2.

Men_Vertical() -> Provocaba comportamientos extraos en los programas, debido a
que escriba, a veces, en zonas de memoria no reservadas. Arreglado en la
versin 1.2.

Bdt_Abre() -> No estaba declarada en BaseDato.h, lo que provocaba que al
compilar en el PC con el modelo de memoria "Large" devolviera un valor
incorrecto, que impeda su ulterior utilizacin. Arreglado en la versin 1.2.

Bdt_LimpiaRegistro() -> Mal escrita, no permita la compilacin o provocaba
comportamientos incorrectos. Arreglado en la versin 1.2.

Bdt_LongitudCampo() -> Daba valores negativos cuando el valor real era mayor de
128. Arreglado en la versin 1.3.

Bdt_Abre() -> No calculaba bien el nmero de registros, y con bases de datos
grandes poda dar lugar a errores. Arreglado en la versin 1.3.


Versin 1.2
-----------

Pan_Caracter() -> En el PC en modo grfico, compilando con el modelo de memoria
"Huge", no funciona. Parece que no se lee correctamente la tabla que define los
caracteres.

Fch_ListaNombre() -> En el QL no siempre daba la lista correctamente, puesto
que no se tena en cuenta que el nombre de un directorio puede estar en
maysculas pero los ficheros en minsculas. Arreglado en la versin 1.3.

Car_Compara() -> En el PC haba asignado al carcter 'T' el mismo valor que al
carcter 'R'. Corregido en la 2.0.

Cad_Compara() -> Debido al error de Car_Compara(), en el PC daba algunos
resultados errneos. Corregido en la 2.0.


Versin 1.3
-----------

Azr_Inicio() -> Devuelve valores iguales cuando se llama sucesivas veces con
poca separacin. Mejorado en la versin 2.0.

Cad_Convierte() -> Mal escrita; se sustituye por las funciones
Cad_ConviertePCaQL() y Cad_ConvierteQLaPC() en la versin 2.0.

Objeto Men -> No se admite la  como tecla caliente. Arreglado para el PC en
la versin 2.0.




Futuras mejoras
===============

Olimpo est en constante desarrollo, ya que intento que lo que voy aprendiendo
y necesitando en informtica se vaya incorporando al sistema. Es el mejor
mtodo que conozco para aprovechar al mximo el tiempo: reutilizar cdigo.

A continuacin voy a exponer algunas de las ideas que pretendo ir incorporando
al sistema. Algunas estn muy prximas a su incorporacin, puesto que ya tengo
cdigo escrito, mientras que otras son proyectos a medio plazo. Tambin me
permito incluir algunas mejoras que deseara incorporar a ms largo plazo, pero
que de momento son slo entelequias (usando el trmino habitual: "vaporware").


General
-------

Olimpo en el QL asume una posicin de las variables del sistema que era la
normal en el primer QL, pero que puede cambiar en implementaciones ms
modernas. Aunque no suele dar problemas tal como est, sera conveniente una
funcin Gen_VarSis() que d la posicin de las variables del sistema.


Pantalla
--------

Mejorar la funcin Pan_Mueve(), para que admita mover el contenido de un
rectngulo de la pantalla tambin hacia la derecha y hacia la izquierda.


Trozo
-----

Deseo poder convertir un trozo extrado de una pantalla en modo grfico en un
fichero grfico. Para ello habr que escribir varias funciones que den las
dimensiones del trozo y los colores de sus puntos.


Zona
----

Deseo escribir funciones para dibujar distintas figuras, todas ellas usando la
escala relativa de la zona.


Fecha
-----

Es muy importante una funcin que compruebe la validez de una fecha.


Usuario
-------

La funcin Usr_Edita() es muy grande y quiz la saque del objeto Usuario para
formar el objeto Editor. Esto puede dar pie a otorgar mayores posibilidades,
tales como manejo de prrafos, variedades a las letras y estilos.


BaseDato
--------

Hay que escribir funciones que permitar leer y escribir campos en otros
formatos ms cmodos: lgico, nmero, etc., y no slo como cadenas, como ocurre
ahora.


Indice
------

Olimpo utiliza un sistema muy sencillo para mantener la estructura interna de
los ficheros de ndice, pero no demasiado eficiente. Pretendo estudiar el
problema y mejorar el mantenimiento de la estructura.


Tiff
----

Deseo ampliar el manejo de ficheros TIFF a imgenes en escala de grises, color
y con varios estilos de compresin.


Compresin
----------

Deseo poder manejar varios mtodos de compresin de datos, empezando por los
ms sencillos (PackBits) y llegando al menos hasta la codificacin de Huffman.

A modo de ejemplo, he incluido junto con los fuentes de Olimpo los ficheros
PackBits.h y PackBits.c, que implementan la compresin y descompresin
PackBits. Aunque los he usado ya en algn programa, y ha funcionado sin
problemas, creo que contienen algn error. Los us con la versin 1.3, de modo
que quiz necesiten algn retoque para funcionar con la 2.0.


Impresora
---------

Es un objeto nuevo, que deber encargarse de la gestin de impresoras. Mientras
que QDOS y UNIX gestionan muy bien la comunicacin con la impresora, MS-DOS es
bastante deficiente.


Rich Text Format
----------------

Los ficheros RTF son un mtodo muy cmodo de trasportar texto con informacin
de formato entre distintas plataformas y distintos programas. Son sencillos de
implementar, de modo que quiz introduzca un objeto que los maneje.


Guin
-----

Es conveniente dar a los usuarios finales de los programas la posibilidad de
que alteren de modo sencillo el comportamiento de stos. El objeto
Configuracin permite esas variaciones, pero es algo limitado.

Sera mucho mejor disponer, adems, de la posibilidad de ejecutar guiones
escritos en ficheros ASCII; es decir, pequeos programas interpretados y
ejecutados desde dentro de un programa.

Usara sintaxis C, pero en castellano y sin tantas posibilidades, porque no son
necesarias para tareas sencillas.


TrueType
--------

Las fuentes escalables TrueType son fciles de encontrar y dan muy buena
calidad tanto en pantalla como en impresora. Aunque no son sencillas de
manejar, lo intentar.




Agradecimientos y bibliografa
==============================

Los conceptos de la programacin orientada el objeto que constituyen la columna
vertebral de este sistema las aprend de la empresa "EQ, sistemas
inteligentes", que es una empresa especializada en inteligencia artificial,
software basado en el conocimiento y pedagoga de estos conceptos. Para ms
informacin:

EQ sistemas inteligentes
Av. General Pern 19, bajo C
28020 Madrid
Telfonos 556 53 09 y 555 10 19
Fax 556 53 09


No slo es importante programar; hay que hacerlo con buen estilo. El lenguaje C
es perverso: se puede escribir cdigo incomprensible o cdigo clarsimo. Adems
de los consejos de EQ sistemas inteligentes, me ha resultado clarificador el
libro:

Ttulo:    The Elements of C Programming Style
Autores:   Jay Ranade y Alan Nash
Editorial: McGraw-Hill


Tambin he leido a nuestros "viejos" maestros, los creadores del lenguaje:

Ttulo:    The C Programming Language
Autores:   Brian W. Kernighan y Dennis M. Ritchie
Editorial: Prentice-Hall


Para conocer las diferencias entre el C K&R y el ANSI consulto el libro:

Ttulo:    A C User's Guide to ANSI C
Autores:   Ken Arnold y John Peyton
Editorial: Addison-Wesley


Los manuales de los compiladores de C que utilizo para desarrollar Olimpo son
muy importantes; sin ellos no podra desarrollar nada. En el PC utilizo un
compilador de Borland. La delegacin espaola est en:

Borland Ibrica S.A.
Edificio Borland
c/ Azalea, 1
28100 Soto de la Moraleja
Madrid


Como libro de consulta para algunas funciones de bajo nivel en el PC uso:

Ttulo:    Micro Guas BIOS / DOS
Autor:     Rafael Nez Hervs
Editorial: ra-ma


Para el QL uso el que sin ninguna duda es el mejor compilador de C disponible,
C68. Este compilador es de dominio pblico y no sera posible contar con l sin
el esfuerzo desinteresado de muchas personas. C68 se puede conseguir en
cualquier distribuidor de software de dominio pblico para QL. El actual
coordinador del equipo de desarrollo es:

Dave Walker
22 Kimptons Mead Potters
Bar Herts, EN6 3HZ
United Kingdom


Como complemento al manual de C68 es muy conveniente usar algn libro sobre el
QDOS. El que suelo manejar es:

Ttulo:    QL Programacin Avanzada
Autor:     Adrian Dickens
Editorial: ra-ma


Casi la totalidad del cdigo de Olimpo es original. Aunque he recogido ideas en
varios sitios, algunas cruciales y muy bien expuestas, el cdigo final ha
salido de mis dedos, no de "cortar y pegar". En los casos en que uso cdigo de
otros autores, lo he adaptado a la notacin y estilo de Olimpo.


Las funciones de manejo de la tarjeta grfica VGA del PC y los algoritmos de
dibujo de figuras grficas las he aprendido en:

Ttulo:    Graphics Programming in C
Autor:     Roger T. Stevens
Editorial: Prentice Hall


En el objeto Trozo se necesita leer y escribir porciones de la pantalla VGA.
Las funciones para poder hacerlo las he aprendido en:

Ttulo:    Saving and restoring VGA screens
Autor:     Ben Myers
Revista:   Dr. Dobb's Journal, Julio de 1991
Editorial: Miller Freeman


El pequeo editor de texto de la funcin Usr_Texto() lo he adaptado de un
captulo del libro

Ttulo:    The Craft of C
Autor:     Herbert Schildt
Editorial: Osborne McGraw Hill


Para desarrollar los objetos Tecla y Men me ha sido de mucha utilidad el
conocimiento del lenguaje Clipper en su versin 5.01, que en aquel momento
perteneca a Nantucket. La versin actual es otra, y el producto es de Computer
Associates.


Asmismo me ha sido til en el desarrollo del objeto Men el libro:

Ttulo:    Designing Screen Interfaces in C
Autor:     James Pinson
Editorial: Yourdon Press


Para el desarrollo de los objetos BaseDato, Memo e Indice me he basado
exclusivamente en la documentacin que acompaa al producto "SoftC Database
Library", desarrollado por la empresa

SoftC Limited
16820 Third Street
Northeast Anoka, MN 55304-4703
U.S.A.

En el momento de escribir estas notas quien distribuye la librera es:

Greenleaf Software
16479 Dallas Parkway Suite
570 Dallas, TX 75248
U.S.A.


La especificacin de los ficheros TIFF se puede obtener de:

Aldus Developers Desk
Aldus Corporation
411 First Avenue South
Seattle, WA 98104-2871
U.S.A.


Sin embargo, yo he utilizado el material obtenido al pedir informacin sobre el
escner HP ScanJet II a Hewlett-Packard. Se obtienen explicaciones detalladas
de la programacin del escner, as como la especificacin TIFF y un tutorial
sobre la programacin de ficheros TIFF. Para ms informacin:

Hewlett-Packard
Int. Business Reply Service
C.C.R.I., Numro 353
1100 VC Amsterdam-Zuidoost
The Netherlands


Para la distribucin de los ficheros fuente en formato comprimido utilizo
programas compresores que han sido puestos a disposicin general por sus
amables autores.

En el QL utilizo el compresor-descompresor que viene con C68:

UnZip:  Zipfile Extract v5.0 of 21 August 1992;
(c) 1989 S.H.Smith and others Versions 3.0 and later by Info-ZIP.
Bug reports ONLY to zip-bugs@cs.ucla.edu
Ported to Qdos by Erik Slagter, Jan. 1993, release 2.00

En el PC uso el magnfico:

LHA versin 2.13, (c) Haruyasu Yoshizaki, 1988-91




Comentarios personales
======================

A lo largo de toda la documentacin procuro usar un estilo sencillo y riguroso.
En este apartado me dar alguna libertad ms para comentar desde un punto de
vista escrictamente personal algunos aspectos generales de la programacin y
particulares del desarrollo de Olimpo.

Si te aburres al leerlo, pasa inmediatamente al siguiente captulo o a otra
cosa, antes de que tu aprecio por Olimpo, si es que existe, se desvanezca.


Gestacin de Olimpo
-------------------

Durante el curso acadmico de 1991-92 curs en el CETICAM, perteneciente a la
Comunidad Autnoma de Madrid, un Curso de Sistemas Expertos, en el que pude
aprender tcnicas de Inteligencia Artificial y de programacin orientada al
objeto en C (entre otras cosas) gracias a la magnfica labor de mis profesores,
casi todos pertenecientes a EQ Sistemas Inteligentes.

Culminamos la asignatura de programacin en C orientada al objeto estudiando un
ejemplo de aplicacin de estudio de laberintos. Los profesores la implementaron
y la estudi con la intencin de compilarla en otro sistema operativo. Estaba
escrita en C para PC y yo quera que corriera en mi QL; por entonces yo slo
usaba el QL. Dado que estaba muy bien escrita, me result muy sencillo; slo
tuve que retocar unos pocos macros de acceso a la pantalla. Colocacin del
cursor, fundamentalmente.

La ltima asignatura del curso consisti en implementar un pequeo sistema
experto combinando varias herramientas: el interfaz de usuario se escriba en
Clipper, el ncleo del sistema se desarroll con una herramienta de
inteligencia artificial y un pequeo mdulo en C una el interfaz con el
ncleo. Como apliqu las tcnicas de programacin orientada al objeto a la
creacin del interfaz, obtuve una idea clara de en qu deberan consistir unos
objetos suficientes para manejar aplicaciones con interfaces sencillos.

Al poco tiempo de terminar el curso, me convert en profesor en la enseanza
pblica. Empec a tener ms tiempo libre y me anim a escribir con mtodo unas
cuantas funciones porttiles entre el QL y el PC. Quera tener lo mejor de cada
mundo.

No tard mucho en tener la versin 0.0 funcionando.

Tuve suerte: escrib un programa usando esa primera versin y lo vend. Desde
luego, Olimpo naca con buen pie.


Desarrollo de Olimpo
--------------------

Olimpo avanza por una va de doble direccin. Cuando escribo un programa, uso
Olimpo; como no siempre tiene todo lo que necesito, lo amplo. En las
siguientes versiones, aado lo que tengo nuevo. Es un proceso que espero que
contine mucho tiempo.

No me resulta fcil sacar una nueva versin o escribir cdigo que trabaje en
direcciones realmente nuevas. Normalmente esto lo hago en vacaciones;
afortunadamente, tengo bastantes das libres, y tres vacaciones largas al ao.

Si estoy en casa, uso un Dell 466/M con tarjeta QXL y si estoy fuera, uso un
porttil Altec 386sx


Sistemas de desarrollo
----------------------

Existen enormes entornos de desarrollo para programar, con montones de
dibujitos, que se dirigen desde el ratn. Normalmente, tambin son muy caras y
se beben los discos duros. Tengo la impresin de que para escribir interfaces
de usuario son buenas.

Y qu pasa con el cdigo? Los programas deberan tener algo ms que un bonito
interfaz, no? En mi opinin, ese cdigo ms profundo se escribe con un editor
y se compila con un compilador, as que para qu ms?

Tanto en el QL como en el PC, uso un editor independiente para escribir cdigo
y un compilador en lnea para compilar. Miro los errores en la pantalla, cargo
otra vez el editor, los arreglo y vuelvo a compilar.

Por tanto, ni siquiera uso depuradores. Pero tengo un remedio infalible para
no tener errores! No escribirlos. Es decir: si se escribe buen cdigo los
errores no suelen ser graves, y se arreglan en un momento.


Sistemas operativos
-------------------

Slo uso tres, y todos tienen sus pros y sus contras. Desde luego, es
sorprendente que uno de los peores sea el que ms xito ha conseguido; pero hay
que vivir con ello.

Afortunadamente, en una misma mquina se pueden poner varios sistemas
operativos, de modo que es posible usar lo mejor de cada uno y pasar de
puntillas por las cosas malas o incmodas que todos tienen.

Tengo muy poca experiencia en UNIX, pero espero aprender lo suficiente como
para tener una versin de Olimpo corriendo bajo Linux.


El rendimiento
--------------

Por definicin, los ordenadores son rpidos; los que los programamos, sin
embargo, sabemos que un mismo programa segn como se implemente puede variar
enormemente su rendimiento.

Cuando escribo Olimpo me ocupo fundamentalmente de que el cdigo sea claro y
limpio; en un primer acercamiento, el rendimiento es secundario. Tampoco
escribo cdigo en ensamblador porque no me manejo bien con l y porque eso
pondra en dificultades a quienes quisieran modificar o comprender el cdigo
fuente de Olimpo.

Sin embargo, s me interesa el rendimiento cuando tengo que elegir el algoritmo
apropiado para implementar una idea. Normalmente sta es la mejor manera de
conseguir que un programa vaya rpido: es mucho ms eficiente un buen algoritmo
en C que un mal algoritmo en ensamblador.


Fiabilidad
----------

Es vital que un sistema sea fiable, que un programa no se "cuelgue" ni aborte.
Tengo especial inters en que Olimpo sea muy seguro. Aunque el manejo de
errores no es exhaustivo, s es suficiente como para atrapar la mayor parte de
los errores que pueden surgir.

El cdigo pasa por varias fases de comprobacin:

La primera es que hay que compilar todo bajo varios  puntos de vista: el PC en
modo texto, el PC en modo grfico, el PC en modelo de memoria "Small", el PC en
modelo de memoria "Large" y QL. Es muy difcil que un error "tcnico" pase
desapercibido despus de que el cdigo se haya compilado tantas veces.

La segunda es la de los programas de validacin. Creo que todas las funciones
quedan comprobadas, y algunas desde distintas funcionalidades, ya que unos
objetos necesitan de otros. Ya me ha pasado encontrar un error en un objeto al
validar otro. Es difcil que los errores de diseo pasen por este punto vivos.

La tercera es el programa de demostracin. Como es un programa real, se ponen
en prctica muchas de las tcnicas necesarias para crear un programa completo.
Aqu suelo atrapar imperfecciones en el modo de manejar las funciones pblicas.

La cuarta, no hay que decirlo, es la real: los programas que se escriben con
Olimpo y que muchas veces hay que recompilar con las distintas versiones.


Prototipos ANSI
---------------

Olimpo declara y define las funciones usando el estilo K&R. Esto da lugar a
errores durante su desarrollo y a veces cuando se usa. Sin embargo, hay alguna
funcin que usa prototipos ANSI, de modo que Olimpo no compilara con un
compilador que no los admita.

Es evidente que debo pasar a usar los prototipos ANSI en cuanto pueda, e
incluir informacin sobre los tipos de entrada y salida de las funciones en la
documentacin. Conseguirlo supondr un buen esfuerzo, pero que merecer la pena
por los errores que evitar.


La versin 3.0
--------------

No s cuntas versiones 2.x habr, ni cuntas cosas incorporarn, pero tengo
previsto (a largo plazo) que la versin 3.0 tenga prototipos ANSI y corra sobre
Linux. Cundo llegar?




Programa de demostracin
========================

Cualquier sistema de ayuda a la programacin est pensado para desarrollar
programas, de modo que el mejor modo de comprender cmo se usa Olimpo es verlo
realizar algo concreto. Por ese motivo, he desarrollado un programa de
demostracin. No pretende ser exhaustivo, sino un punto de arranque para que el
usuario de Olimpo pueda empezar lo antes posible a desarrollar su propio
cdigo.

Para poder ver este programa debes descomprimir el fichero Demo.lzh o el
Demo_zip. Esto crea varios ficheros, entre ellos el ejecutable Demo.exe.
Ejectalo teniendo en cuenta que espera que los dems ficheros estn en el
mismo directorio.

Si ests leyendo la versin en disquete de esta documentacin, consulta el
fichero Demo.c; en el caso de que ests leyendo la versin en papel, ms
tradicional y creo que tambin ms cmoda, puedes ver el fichero impreso al
final de estas notas.

El programa de demostracin utiliza una base de datos de nombre Demo.dbf y un
fichero de ndices llamado Demo.ntx. El programa CreaBdDm.c, entregado junto
con los fuentes de Olimpo, permite crear la base de datos y el ndice con la
cantidad de registros que se desee. El programa va generando registros
aleatoriamente usando la informacin de los ficheros Nombre.txt, Apellido.txt,
Deporte.txt y Pais.txt.