/*--------------------------------------------------------------------
 * FICHERO:  Demo.c
 * OBJETIVO: Servir de ejemplo de las posibilidades de Olimpo
 * AUTOR:    Pedro Reina
 * FECHA:    L.28.8.1995
 *------------------------------------------------------------------*/

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

#include "Olimpo.h"

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

void Logo();
void PreparaPantalla();

void Explica();
void ExplicaSistema();
void ExplicaObjetos();
void ExplicaNombre();
void ExplicaAutor();
void ExplicaTeclas();

void DemoGeneral();
void DemoMemoria();
void DemoPantalla();
void DemoAzar();
void DemoTiempo();
void DemoSonido();
void DemoCaracter();

void DemoLista();
int  ComparaCadena();

void DemoTrozo();

void DemoZona();
void DemoZonaAbsoluto();
void DemoZonaRelativo();

void DemoCadena();
void DemoPrograma();
void DemoFecha();
void DemoTecla();
void DemoCuadro();
void DemoRegion();

void DemoUsuario();
void Pulsa();

void DemoFichero();
void DemoFchExistencia();
void DemoFchLectura();
void DemoFchBorrado();
void DemoFchListado();

void   DemoMenu();
void   DemoMenuSencillo();
void   DemoMenuMostrar();
void   DemoMenuColor();
void   DemoMenuTecla();
logico FuncionDemoMenu();

void DemoConfig();

void DemoBaseDato();
void MuestraGeneral();
void MuestraEstructura();
void MuestraRegistros();
void MarcoRegistro();
void EscribeRegistro();

void DemoMemo();

void DemoIndice();
void MuestraRegistrosAlfa();
void MuestraRegistrosInv();

void DemoDiblane();
void DemoDbnManipula();
void DemoDbnEdita();

void DemoTiff();

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

   /* Ninguno */

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

logico ModoCambiado;

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

#define LimpiaZonaTrabajo()  Pan_Borra(NEGRO,2,14,20,78)

#define LimpiaZonaDemoUsr()  (Pan_Borra(NEGRO,6,28,19,77),\
                              Pan_Borra(NEGRO,18,17,19,25))

#define LimpiaZonaDemoFch()  (Pan_Borra(NEGRO,6,30,20,77),\
                              Pan_Borra(NEGRO,12,16,20,77))

/*--------------------------------------------------------------------
 * Programa principal
 *------------------------------------------------------------------*/
void main()
  {
  enum { SALIDA_ESC, SALIDA, EXPLICA, GENERAL, MEMORIA, PANTALLA,
         AZAR, TIEMPO, SONIDO, CARACTER, LISTA, TROZO, ZONA, CADENA,
         PROGRAMA, FECHA, TECLA, CUADRO, REGION, USUARIO, FICHERO,
         MENU, CONFIGURACION, BASEDATO, MEMO, INDICE, DIBLANE, TIFF };

  static cadena Principal[] = {"Salida", "Explica", "General", "Memoria",
         "Pantalla", "Azar", "Tiempo", "Sonido", "Carcter", "Lista",
         "Trozo", "Zona", "Cadena",  "Programa", "Fecha", "Tecla", "Cuadro",
         "Regin", "Usuario", "Fichero", "Men", "Config.", "BaseDato",
         "Memo", "Indice", "Diblane", "Tiff", NIL };

  entero Opcion=EXPLICA;
  logico Sigue=SI;

  Pan_Define (PAN_TEXTO);
  Azr_Inicia();
  PreparaPantalla();
  Logo();
  Usr_PulsaUnaTecla ("Bienvenido a la demostracin de Olimpo");

  while ( Sigue )
    {
    Logo();
    Opcion = Men_Vertical (2,1,20,10,Principal,Opcion);
    LimpiaZonaTrabajo();
    switch ( Opcion )
      {
      case SALIDA_ESC:
      case SALIDA:
           if ( Usr_Consulta ("Quieres terminar la demostracin?") )
             { Sigue = NO; }
           Opcion = SALIDA;
           break;
      case EXPLICA:       Explica();       break;
      case GENERAL:       DemoGeneral();   break;
      case MEMORIA:       DemoMemoria();   break;
      case PANTALLA:      DemoPantalla();
                          if ( ModoCambiado )
                            { PreparaPantalla(); }
                          break;
      case AZAR:          DemoAzar();      break;
      case TIEMPO:        DemoTiempo();    break;
      case SONIDO:        DemoSonido();    break;
      case CARACTER:      DemoCaracter();  break;
      case LISTA:         DemoLista();     break;
      case TROZO:         DemoTrozo();     break;
      case ZONA:          DemoZona();      break;
      case CADENA:        DemoCadena();    break;
      case PROGRAMA:      DemoPrograma();  break;
      case FECHA:         DemoFecha();     break;
      case TECLA:         DemoTecla();     break;
      case CUADRO:        DemoCuadro();    break;
      case REGION:        DemoRegion();    break;
      case USUARIO:       DemoUsuario();   break;
      case FICHERO:       DemoFichero();   break;
      case MENU:          DemoMenu();      break;
      case CONFIGURACION: DemoConfig();    break;
      case BASEDATO:      DemoBaseDato();  break;
      case MEMO:          DemoMemo();      break;
      case INDICE:        DemoIndice();    break;
      case DIBLANE:       DemoDiblane();   break;
      case TIFF:          DemoTiff();      break;
      }
    }

  Pan_Cierra();
  }

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

/*--------------------------------------------------------------------
 * FUNCION:  PreparaPantalla()
 * OBJETIVO: Preparar la pantalla para la demostracin
 *------------------------------------------------------------------*/
void PreparaPantalla()
  {
  Prg_Presenta ( "Demostracin de Olimpo", "2.0",
                 "Pedro Reina", "Agosto 1995" );

  Cdr_Caja (CDR_SIMPLE, 1, 0, 21, 11, NEGRO, BLANCO);
  Cdr_Caja (CDR_SIMPLE, 1,13, 21, 79, NEGRO, BLANCO);

  ModoCambiado = NO;
  }

/*--------------------------------------------------------------------
 * FUNCION:  Logo()
 * OBJETIVO: Mostrar la palabra Olimpo en grande
 *------------------------------------------------------------------*/
void Logo()
  {
  static cadena CadenaLogo[] = { "#####",
                                 "#   #  #    ###  ##   ##  ###   ####",
                                 "#   #  #     #   # # # #  #  #  #  #",
                                 "#   #  #     #   #  #  #  ###   #  #",
                                 "#####  ###  ###  #     #  #     ####",
                                 NIL };
  octeto i, T;

  switch ( Azr_Entero(0,2) )
    {
    case 0: T = BLANCO; break;
    case 1: T = ROJO  ; break;
    case 2: T = VERDE ; break;
    }

  LimpiaZonaTrabajo();
  Pan_Color (NEGRO,T);

  for ( i=0 ; CadenaLogo[i] ; i++ )
    { Pan_PonTexto (8+i, 28, CadenaLogo[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  Explica()
 * OBJETIVO: Dirigir las explicaciones
 *------------------------------------------------------------------*/
void Explica()
  {
  enum { SALIDA_ESC, SISTEMA, OBJETOS, NOMBRE, AUTOR, TECLAS };
  static octeto MaxOpcion = 5;
  static cadena Menu[] = {"En qu consiste el sistema",
                          "Los distintos objetos",
                          "Lo que significa el nombre",
                          "Contactar con el autor",
                          "Teclas PC y teclas QL",
                          NIL };
  static cadena Presentacion[] = {
    "Desde aqu puedes pedir explicacin sobre diferentes",
    "aspectos de Olimpo y de este programa de demostracin.",
    "Elige el que desees y pulsa ESC cuando hayas terminado.",
    NIL };

  logico Sigue = SI;
  entero Opcion = 1;
  octeto i;

  while ( Sigue )
    {
    LimpiaZonaTrabajo();
    Pan_Color (NEGRO,BLANCO);
    for ( i=0 ; Presentacion[i] ; i++ )
      { Pan_PonTexto (3+i,18,Presentacion[i]); }

    Opcion = Men_Vertical (9,32,13,60,Menu,Opcion);
    LimpiaZonaTrabajo();
    switch ( Opcion )
      {
      case SALIDA_ESC:  Sigue = NO;         break;
      case SISTEMA:     ExplicaSistema();   break;
      case OBJETOS:     ExplicaObjetos();   break;
      case NOMBRE:      ExplicaNombre();    break;
      case AUTOR:       ExplicaAutor();     break;
      case TECLAS:      ExplicaTeclas();    break;
      }
    if ( Opcion )  { Usr_PulsaUnaTecla(""); }
    Opcion++;
    if ( Opcion > MaxOpcion )  { Opcion = 1; }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  ExplicaSistema()
 * OBJETIVO: Explicar el objetivo del sistema
 *------------------------------------------------------------------*/
void ExplicaSistema()
  {
  static cadena Mensaje[] = {
      "Olimpo es un sistema de programacin en C multiplataforma",
      "orientado al objeto. Esto quiere decir que permite escribir",
      "cdigo en C de una manera ms sencilla y potente que usando",
      "exclusivamente las funciones de la librera estndar de C.",
      "",
      "Al ser multiplataforma, permite que el cdigo se pueda",
      "compilar, sin ninguna modificacin, en distintos sistemas",
      "operativos. En esta versin se dispone de Olimpo para el QL",
      "usando C68 y para PC, bajo MS-DOS, usando Turbo C.",
      "",
      "Como es orientado al objeto, permite un tipo de programacin",
      "sencillo, fcil de usar y modificar, moderno y que facilita",
      "la reutilizacin del cdigo.",
      "",
      "Olimpo es de dominio pblico, incluyendo los fuentes, aunque",
      "el autor valora que se le mande una postal si alguien utiliza",
      "el sistema para algo.",
       NIL };

  octeto i;

  Pan_Color (NEGRO,BLANCO);
  for ( i=0 ; Mensaje[i] ; i++ )
    { Pan_PonTexto (3+i,16,Mensaje[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  ExplicaObjetos()
 * OBJETIVO: Explicar en qu consisten los objetos
 *------------------------------------------------------------------*/
void ExplicaObjetos()
  {
  static cadena Mensaje[] = {
      "Olimpo ofrece al programador 25 objetos, que se ocupan de",
      "muchas de las diferentes necesidades que se presentan al",
      "escribir una aplicacin.",
      "",
      "En esta demostracin se pueden ver, no exhaustivamente,",
      "las posibilidades que ofrece cada uno de los objetos.",
      "",
      "",
      "                Relacin de objetos",
      "                -------------------",
      "",
      "General    Sonido     Cadena     Regin         BaseDato",
      "Memoria    Carcter   Programa   Usuario        Memo",
      "Pantalla   Lista      Fecha      Fichero        Indice",
      "Azar       Trozo      Tecla      Men           Diblane",
      "Tiempo     Zona       Cuadro     Configuracin  Tiff",
       NIL };

  octeto i;

  Pan_Color (NEGRO,BLANCO);
  for ( i=0 ; Mensaje[i] ; i++ )
    { Pan_PonTexto (3+i,18,Mensaje[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  ExplicaNombre()
 * OBJETIVO: Explicar lo que significa el nombre Olimpo
 *------------------------------------------------------------------*/
void ExplicaNombre()
  {
  static cadena Mensaje[] = {
      "En el mundo griego existan numerosos montes llamados",
      "Olimpo: uno, en Misia; otro, en Cilicia; un tercero, en",
      "lide; otro, en Arcadia, y, finalmente, el mas clebre de",
      "todos, que se alzaba en los confines de Macedonia y Tesalia.",
      "Desde los poemas homricos, el Olimpo es considerado como la",
      "mansin de los dioses, en particular como la morada de Zeus.",
      "En l, por ejemplo, el dios pesa los destinos de Aquiles y",
      "Hctor, y desde su altura precipita a Hefesto cuando ste",
      "quiere intervenir en favor de Hera, etc. Sin embargo, poco a",
      "poco la residencia de los dioses se va diferenciando de la",
      "montaa tesalia, y el trmino Olimpo se aplica, de manera",
      "general, a las moradas celestes donde reside la divinidad.",
      "",
      "Diccionario de mitologa griega y romana",
      "Pierre Grimal, Editorial Paidos",
       NIL };

  octeto i;

  Pan_Color (NEGRO,BLANCO);
  for ( i=0 ; Mensaje[i] ; i++ )
    { Pan_PonTexto (3+i,16,Mensaje[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  ExplicaAutor()
 * OBJETIVO: Explicar quin es el autor y cmo contactar con l
 *------------------------------------------------------------------*/
void ExplicaAutor()
  {
  static cadena Mensaje[] = {
      "Olimpo es un sistema abierto, cualquiera puede trabajar con",
      "l y modificarlo para su uso de la manera que desee.",
      "",
      "Te agradecer cualquier comentario, indicacin o consulta",
      "que quieras hacerme.",
      "",
      "Si usas Olimpo para algo, me gustara que me enviaras una",
      "tarjeta postal, quiz con una vista de tu poblacin y",
      "algn comentario.",
      "",
      "Mis datos:",
      "                 Pedro Reina",
      "                 c/ Marquesa de Argeso, 4",
      "                 28019 Madrid",
      "                 Espaa",
      "",
      "                 Telfono 565 17 59",
      NIL };

  octeto i;

  Pan_Color (NEGRO,BLANCO);
  for ( i=0 ; Mensaje[i] ; i++ )
    { Pan_PonTexto (3+i,18,Mensaje[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  ExplicaTeclas()
 * OBJETIVO: Explicar las teclas que son distintas en QL y en PC
 *------------------------------------------------------------------*/
void ExplicaTeclas()
  {
  static cadena Mensaje[] = {
      "El QL y el PC tienen distintos teclados y algunas teclas",
      "no tienen correspondiente directo.",
      "",
      "Olimpo asigna a ciertas combinaciones de teclas del QL la",
      "funcin de algunas teclas del PC. sta es la relacin:",
      "",
      "         Tecla PC        Equivalente QL",
      "         --------        --------------",
      "",
      "         Inicio          Alt-Izquierda",
      "         Fin             Alt-Derecha",
      "         RePag           Alt-Arriba",
      "         AvPag           Alt-Abajo",
      "         Insert          Maysculas-Fijamaysculas",
      "         Supr            Ctrl-Derecha",
      "         Retroceso       Ctrl-Izquierda",
       NIL };

  octeto i;

  Pan_Color (NEGRO,BLANCO);
  for ( i=0 ; Mensaje[i] ; i++ )
    { Pan_PonTexto (3+i,18,Mensaje[i]); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoGeneral()
 * OBJETIVO: Demostrar las posibilidades del objeto General
 *------------------------------------------------------------------*/
void DemoGeneral()
  {
  contador Primero, Segundo;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Este es un objeto atpico, que rene definiciones de");
  Pan_PonTexto (4,16,"tipos y funciones de uso general.");

  Pan_Tinta (VERDE);
  Pan_PonTexto (6,16,"Programa compilado en un ");
  Pan_Tinta (BLANCO);

#ifdef OLIMPO_QL
  Pan_Texto ("QL");
#endif

#ifdef OLIMPO_PC
  Pan_Texto ("PC");
#endif

  Pan_PonTexto (8,16,"Tipo \"menudo\"  : enteros con signo de  8 bits");
  Pan_PonTexto (9,16,"Tipo \"octeto\"  : enteros sin signo de  8 bits");
  Pan_PonTexto (10,16,"Tipo \"contador\": enteros con signo de 16 bits");
  Pan_PonTexto (11,16,"Tipo \"contpos\" : enteros sin signo de 16 bits");
  Pan_PonTexto (12,16,"Tipo \"entero\"  : enteros con signo de 32 bits");
  Pan_PonTexto (13,16,"Tipo \"entpos\"  : enteros sin signo de 32 bits");

  Pan_Tinta (VERDE);
  Pan_PonTexto (15,16,"Dame dos nmeros: ");
  Primero = Usr_Entero (101,3,0,200,15,34,NEGRO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    Pan_Color (NEGRO,VERDE);
    Pan_PonCar (15,39,'y');
    Segundo = Usr_Entero (17,3,1,200,15,41,NEGRO,BLANCO);
    if ( Tec_Ultima() != TEC_ESC )
      {
      Pan_Tinta (BLANCO);
      Pan_PonTexto (17,16,"El mximo de los dos: ");
      Pan_Tinta (VERDE);
      Pan_Entero (Max(Primero,Segundo),1);
      Pan_Tinta (BLANCO);
      Pan_PonTexto (18,16,"El minimo de los dos: ");
      Pan_Tinta (VERDE);
      Pan_Entero (Min(Primero,Segundo),1);
      Pan_Tinta (BLANCO);
      Pan_PonTexto (19,16,"Su divisin por exceso: ");
      Pan_Tinta (VERDE);
      Pan_Entero (DivEx(Primero,Segundo),1);
      Usr_PulsaUnaTecla ("");
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMemoria()
 * OBJETIVO: Demostrar las posibilidades del objeto Memoria
 *------------------------------------------------------------------*/
void DemoMemoria()
  {
  octeto Aux[2];

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"El manejo de memoria RAM es esencial programando en C.");
  Pan_PonTexto (4,16,"Olimpo encapsula las funciones para reservar y liberar");
  Pan_PonTexto (5,16,"memoria RAM.");
  Pan_PonTexto (7,16,"Los valores que ocupan ms de un octeto se pueden");
  Pan_PonTexto (8,16,"almacenar en memoria de dos formas:");
  Pan_PonTexto (9,16,"Formato Motorola: el ms significativo primero.");
  Pan_PonTexto (10,16,"Formato Intel: el menos significativo primero.");
  Pan_PonTexto (11,16,"Con Olimpo se pueden leer y escribir datos en memoria");
  Pan_PonTexto (12,16,"en cualquiera de los formatos");

  Pan_Tinta (VERDE);
  Pan_PonTexto (14,16,"Usamos dos octetos: ");
  Aux[0] = Usr_Entero (2,3,0,255,14,36,NEGRO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    Pan_Color (NEGRO,VERDE);
    Pan_PonCar (14,41,'y');
    Aux[1] = Usr_Entero (10,3,0,255,14,43,NEGRO,BLANCO);
    if ( Tec_Ultima() != TEC_ESC )
      {
      Pan_Tinta (BLANCO);
      Pan_PonTexto (16,16,"Si consideramos los dos octetos como un valor");
      Pan_PonTexto (17,16,"de 16 bits sin signo, tomar estos valores:");
      Pan_PonTexto (19,16,"En formato Motorola: ");
      Pan_Tinta (VERDE);
      Pan_Entero (Mem_LeeContpos(Aux,MEM_MOTOROLA),1);
      Pan_Tinta (BLANCO);
      Pan_PonTexto (20,16,"En formato Intel: ");
      Pan_Tinta (VERDE);
      Pan_Entero (Mem_LeeContpos(Aux,MEM_INTEL),1);
      Usr_PulsaUnaTecla ("");
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoPantalla()
 * OBJETIVO: Demostrar las posibilidades del objeto Pantalla
 *------------------------------------------------------------------*/
void DemoPantalla()
  {
  octeto ModoAnterior;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Se dispone de varias funciones bsicas para manejar");
  Pan_PonTexto (4,16,"colores, cursor, texto, nmeros enteros y reales");

  Pan_Borra (VERDE,6,16,15,72);
  Pan_Borra (ROJO,8,20,13,48);
  Pan_Borra (BLANCO,8,52,13,68);
  Pan_Borra (NEGRO,10,24,11,64);

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (17,16,"La pantalla puede estar en modo texto o grfico.");
  Pan_PonTexto (19,16,"Ahora est en modo ");
  Pan_Tinta (VERDE);
  if ( Pan_Modo() == PAN_TEXTO )   { Pan_Texto ("Texto"); }
  if ( Pan_Modo() == PAN_GRAFICO ) { Pan_Texto ("Grfico"); }

  if ( Usr_Consulta ("Quieres cambiar de modo?") )
    {
    ModoAnterior = Pan_Modo();
    Pan_Cierra();
    if ( ModoAnterior == PAN_TEXTO )   { Pan_Define (PAN_GRAFICO); }
    if ( ModoAnterior == PAN_GRAFICO ) { Pan_Define (PAN_TEXTO);   }
    ModoCambiado = SI;
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoAzar()
 * OBJETIVO: Demostrar las posibilidades del objeto Azar
 *------------------------------------------------------------------*/
void DemoAzar()
  {
  contador Minimo, Maximo, i, j;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Hay un generador de nmeros aleatorios.");
  Pan_PonTexto (5,16,"Vamos a generar 72 enteros entre");
  Minimo = Usr_Entero (0,3,-99,100,5,50,NEGRO,VERDE);
  if ( Tec_Ultima() != TEC_ESC )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonCar (5,55,'y');
    Maximo = Usr_Entero (200,3,Minimo,999,5,57,NEGRO,VERDE);
    if ( Tec_Ultima() != TEC_ESC )
      {
      Usr_Informa ("Generando enteros aleatorios");
      Pan_Color (NEGRO,ROJO);
      /* La funcin Azr_Inicia() est puesta al comienzo del programa */
      for ( i=0 ; i<7 ; i++ )
        {
        for ( j=0 ; j<13; j++ )
          { Pan_PonEntero (8+2*i,15+5*j,Azr_Entero(Minimo,Maximo),3); }
        }
      Usr_PulsaUnaTecla ("Generacin concluida");
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoTiempo()
 * OBJETIVO: Demostrar las posibilidades del objeto Tiempo
 *------------------------------------------------------------------*/
void DemoTiempo()
  {
  real   Comienzo, Transcurrido;
  logico Sigue = SI;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,
      "Se puede consultar la fecha y la hora del sistema operativo:");
  Pan_PonTexto (5,26,"Ao:");
  Pan_PonTexto (6,26,"Mes:");
  Pan_PonTexto (7,26,"Da:");
  Pan_PonTexto (5,45,"Hora:");
  Pan_PonTexto (6,45,"Minuto:");
  Pan_PonTexto (7,45,"Segundo:");
  Pan_Tinta (VERDE);
  Pan_PonEntero (5,31,Tim_Ano(),4);
  Pan_PonEntero (6,33,Tim_Mes(),2);
  Pan_PonEntero (7,33,Tim_Dia(),2);
  Pan_PonEntero (5,54,Tim_Hora(),2);
  Pan_PonEntero (6,54,Tim_Minuto(),2);
  Pan_PonEntero (7,54,Tim_Segundo(),2);

  Pan_Tinta (BLANCO);
  Pan_PonTexto (10,16,"Es posible representar un reloj en tiempo real");
  Cdr_Caja (CDR_SIMPLE,12,35,18,50,NEGRO,ROJO);
  Pan_Color (NEGRO,ROJO);
  Pan_PonTexto (14,40,"Tiempo");
  Usr_Indica ( "Pulsa cualquier tecla para parar",
               "El reloj se para automticamente a los 60 segundos" );
  Comienzo = Tim_Crono();
  while ( !Tec_Disponible() && Sigue )
    {
    Pan_CursorVisible (NO);
    Pan_Color (NEGRO,VERDE);
    Transcurrido = Tim_Crono() - Comienzo;
    if ( Transcurrido > 60.0 )
      { Sigue = NO; }
    else
      { Pan_PonReal (16,41,Transcurrido,4,1); }
    }
  if ( Sigue ) { Tec_Pulsada(); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoSonido()
 * OBJETIVO: Demostrar las posibilidades del objeto Sonido
 *------------------------------------------------------------------*/
void DemoSonido()
  {
  enum { SALIDA_ESC, CAMBIO, BIEN, MALATECLA, ERROR };
  static cadena MenuSonido[] = { ">Cambio", ">Bien", ">MalaTecla",
                                 ">Error", NIL };
  entero Opcion=1;
  logico Sigue=SI;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"El sonido puede estar conectado o apagado.");
  Pan_PonTexto (5,16,"Se dispone de varios sonidos. Prubalos:");
  Pan_PonTexto (18,16,"Si dejas  el sonido encendido, podrs comprobar");
  Pan_PonTexto (19,16,"su efecto en los dems objetos.");

  Pan_Tinta (VERDE);
  Pan_PonTexto (8,16,"Estado:");

  Cdr_Caja (CDR_SIMPLE,10,16,15,28,NEGRO,VERDE);
  while ( Sigue )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_Cursor (8,24);
    if ( Son_Estado() ) { Pan_Texto ("Encendido"); }
    else                { Pan_Texto ("Apagado  "); }

    Opcion = Men_Vertical (11,17,14,27,MenuSonido,Opcion);
    switch ( Opcion )
      {
      case SALIDA_ESC:  Sigue = NO;       break;
      case CAMBIO:      Son_Cambia();     break;
      case BIEN:        Son_Bien();       break;
      case MALATECLA:   Son_MalaTecla();  break;
      case ERROR:       Son_Error();      break;
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoCaracter()
 * OBJETIVO: Demostrar las posibilidades del objeto Carcter
 *------------------------------------------------------------------*/
void DemoCaracter()
  {
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Olimpo maneja el juego PC-8 en el PC y el MGE en el QL.");
  Pan_PonTexto (4,16,"En cualquier caso se tratan adecuadamente las maysculas");
  Pan_PonTexto (5,16,"y minsculas, as como el paso de un juego a otro.");
  Pan_PonTexto (7,16,"Los caracteres se pueden comparar segn las reglas");
  Pan_PonTexto (8,16,"del castellano. Es decir: 'a' y '' son iguales, etc.");
  Pan_PonTexto (10,16,"Tambin hay macros para representar caracteres con");
  Pan_PonTexto (11,16,"distinto cdigo en cada ordenador. Por ejemplo:");

  Pan_PonTexto (13,16,"Mayscula de ");
  Pan_Caracter (CAR_E_AGUDO);
  Pan_Texto (": ");
  Pan_Caracter (Car_Mayus(CAR_E_AGUDO));

  Pan_PonTexto (14,16,"Carcter PI: ");
  Pan_Caracter (CAR_PI);

  Pan_PonTexto (16,16,"Olimpo permite traducir caracteres entre los juegos");
  Pan_PonTexto (17,16,"del QL, del PC y el ANSI.");

  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoLista()
 * OBJETIVO: Demostrar las posibilidades del objeto Lista
 *------------------------------------------------------------------*/
void DemoLista()
  {
  static cadena Primera[] = {"Pro", "Te",  "A",  "Cle", "Je",  "Tre", "Chu"};
  static cadena Segunda[] = {"zu",  "mi",  "ro", "xa",  "li",  "pu",  "no" };
  static cadena Tercera[] = {"er",  "dor", "da", "bo",  "mal", "za",  "fo" };

  lista  Lista1, Lista2, Lista3, L1, L2, L3;
  cadena Palabra1, Palabra2, Palabra3;
  octeto Tope = 11, M = 6, i;

  Lista1 = Lis_Crea();
  Lista2 = Lis_Crea();
  Lista3 = Lis_Crea();

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Se pueden crear y destruir listas encadenadas.");
  Pan_PonTexto (4,16,"Los nodos se pueden agregar por el principio, que");
  Pan_PonTexto (5,16,"es ms rpido, o por el final, ms natural.");
  Pan_PonTexto (6,16,"Las listas se pueden ordenar usando una funcin");
  Pan_PonTexto (7,16,"proporcionada por el programador.");

  Pan_Tinta (VERDE);
  Pan_PonTexto (9,27,"Principio");
  Pan_PonTexto (9,41,"Final");
  Pan_PonTexto (9,55,"Ordenada");

  for ( i=0 ; i<Tope ; i++ )
    {
    Palabra1 = Cad_Une (Primera[Azr_Entero(0,M)], Segunda[Azr_Entero(0,M)],
                        Tercera[Azr_Entero(0,M)], CAD_FIN);
    Palabra2 = Cad_Duplica(Palabra1);
    Palabra3 = Cad_Duplica(Palabra1);
    /*
     * Las cadenas se destruyen al destruir
     * las listas, al final de la funcin
     */
    Lista1 = Lis_Anota    (Lista1,Palabra1);
    Lista2 = Lis_AnotaFin (Lista2,Palabra2);
    Lista3 = Lis_Anota    (Lista3,Palabra3);
    }

  Lista3 = Lis_Ordena (Lista3, ComparaCadena);

  Pan_Color (NEGRO,BLANCO);
  for ( L1 = Lista1 , L2 = Lista2 , L3 = Lista3 , i = 0 ;
        L1 || L2 || L3 ;
        L1 = Lis_Siguiente (L1) , L2 = Lis_Siguiente (L2) ,
        L3 = Lis_Siguiente (L3) , i++ )
    {
    Pan_PonTexto (10+i,27,Lis_Contenido(L1));
    Pan_PonTexto (10+i,41,Lis_Contenido(L2));
    Pan_PonTexto (10+i,55,Lis_Contenido(L3));
    }

  Lis_Destruye (Lista1);
  Lis_Destruye (Lista2);
  Lis_Destruye (Lista3);

  Usr_PulsaUnaTecla("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  ComparaCadena()
 * OBJETIVO: Comparar dos cadenas
 * ENTRADAS: Los punteros a las dos cadenas
 * SALIDAS:  Un int que indica qu cadena es menor
 *------------------------------------------------------------------*/
int ComparaCadena (Cad1,Cad2)
cadena *Cad1, *Cad2;
  {
  return ( Cad_Compara (*Cad1,*Cad2) );
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoTrozo()
 * OBJETIVO: Demostrar las posibilidades del objeto Trozo
 *------------------------------------------------------------------*/
void DemoTrozo()
  {
  trozo Trozo;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Se puede almacenar en memoria un \"trozo\" de");
  Pan_PonTexto (4,16,"pantalla y luego escribirlo en la posicin deseada");

  Cdr_Caja (CDR_DOBLE,  6, 16, 10, 27, BLANCO, ROJO);
  Cdr_Caja (CDR_SIMPLE, 7, 18,  9, 25, BLANCO, VERDE);
  Pan_Color (BLANCO, NEGRO);
  Pan_PonTexto (8, 19, "Olimpo");

  Pan_Color (NEGRO, VERDE);
  Pan_PonTexto (8, 30, "<- ste es el contenido original");
  Usr_PulsaUnaTecla ("Ahora el original se reproducir.");

  if ( Trozo = Trz_Crea(6,16,10,27) )
    {
    Pan_Color (NEGRO, VERDE);
    Pan_PonTexto (12, 16, "stas son reproducciones:");
    Trz_Restituye (Trozo, 14, 20);
    Trz_Restituye (Trozo, 15, 40);
    Trz_Restituye (Trozo, 13, 60);
    Trz_Destruye (Trozo);
    Usr_PulsaUnaTecla("");
    }
  else  { Usr_Avisa("No se ha podido crear el trozo"); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoZona()
 * OBJETIVO: Demostrar las posibilidades del objeto Zona
 *------------------------------------------------------------------*/
void DemoZona()
  {
  enum { SALIDA_ESC, ABSOLUTO, RELATIVO };
  static cadena MenuZona[] = { "Demostracin del modo absoluto",
                               "Demostracin del modo relativo", NIL };
  entero Opcion=1;
  logico Sigue=SI;

  while ( Sigue )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (3,16,"Una zona es una parte de la pantalla en la que se");
    Pan_PonTexto (4,16,"pueden representar grficos. Slo estn disponibles,");
    Pan_PonTexto (5,16,"lgicamente, con la pantalla en modo grfico.");
    Pan_PonTexto (6,16,"En un PC es necesaria tarjeta VGA.");
    Pan_PonTexto (8,16,"Se puede acceder a una zona de dos formas distintas:");
    Pan_PonTexto (9,16,"en modo absoluto y en modo relativo.");

    if ( Pan_Modo() == PAN_TEXTO )
      {
      Pan_PonTexto (11,18,"Ahora ests en modo Texto, de modo que no estn");
      Pan_PonTexto (12,18,"disponibles las zonas. Cambia de modo con la opcin");
      Pan_PonTexto (13,18,"\"Pantalla\" del men principal y vuelve aqu.");
      Usr_PulsaUnaTecla ("");
      Sigue = NO;
      }

    else  /* Pan_Modo() == PAN_GRAFICO */
      {
      Pan_PonTexto (10,16,"Elige lo que quieres ver:");
      Opcion = Men_Vertical (12,18,13,50,MenuZona,Opcion);
      LimpiaZonaTrabajo();
      switch ( Opcion )
        {
        case SALIDA_ESC:  Sigue = NO;                            break;
        case ABSOLUTO:    DemoZonaAbsoluto(); Opcion = RELATIVO; break;
        case RELATIVO:    DemoZonaRelativo(); Opcion = ABSOLUTO; break;
        }
      LimpiaZonaTrabajo();
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoZonaAbsoluto()
 * OBJETIVO: Demostrar las posibilidades del objeto Zona manejado
 *           en modo absoluto
 *------------------------------------------------------------------*/
void DemoZonaAbsoluto()
  {
  zona     Asterix, Obelix;
  contador X, Y, MaxX, MaxY, AlturaObelix, i=0;
  contador Tercio, DosTercios, Repite;
  entero   Cuenta=0, Tope;
  octeto   Color, Banda=BLANCO, Mascara = 1;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"En modo absoluto se puede acceder a cada pixel y a");
  Pan_PonTexto (4,16,"cada oxel de una zona.");
  Pan_PonTexto (5,16,"Un oxel es un grupo de 8 pixels que se maneja de forma");
  Pan_PonTexto (6,16,"unitaria, tanto por el hardware como por Olimpo");

  if ( Asterix = Zon_Crea (9,18,18,64) )
    {
    if ( Obelix = Zon_Crea (9,72,18,74) )
      {
      MaxX = Zon_AnchoFisico (Asterix) - 1;
      MaxY = Zon_AltoFisico (Asterix) - 1;
      AlturaObelix = Zon_AltoFisico (Obelix);
      Tercio = MaxX / 3;
      DosTercios = 2 * MaxX / 3;
      Tope = (entero) MaxX * MaxY;
      Usr_Indica ("A la izquierda ves pixels y a la derecha oxels",
                  "Pulsa cualquier tecla para parar");
      while ( !Tec_Disponible() )
        {
        for ( Repite = 0 ; Repite < 50 ; Repite++ )
          {
          X = Azr_Entero (0,MaxX);
          Y = Azr_Entero (0,MaxY);
          if      ( X < Tercio )     { Color = BLANCO; }
          else if ( X > DosTercios ) { Color = ROJO;   }
          else                       { Color = VERDE;  }
          Zon_PixelSeguro (Asterix,X,Y,Color);
          }
        Cuenta += 50;
        if ( Cuenta > Tope )
          {
          Cuenta = 0;
          Zon_Borra (Asterix,NEGRO);
          }

        Zon_OxelSeguro (Obelix,0,i,Mascara,Banda);
        Mascara++;
        i++;
        if ( i == AlturaObelix )
          {
          i=0;
          if      ( Banda == BLANCO ) { Banda = VERDE;  }
          else if ( Banda == VERDE  ) { Banda = ROJO;   }
          else                        { Banda = BLANCO; }
          }
        }
      Tec_Pulsada();
      Zon_Destruye (Obelix);
      }
    Zon_Destruye (Asterix);
    }

  else
    {
    Pan_PonTexto (8,16,"Aunque ests en modo Grfico, no hay suficiente");
    Pan_PonTexto (9,16,"memoria para abrir zonas.");
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoZonaRelativo()
 * OBJETIVO: Demostrar las posibilidades del objeto Zona manejado
 *           en modo relativo
 *------------------------------------------------------------------*/
void DemoZonaRelativo()
  {
  zona   Asterix, Obelix;
  octeto Color, Cuenta;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"En modo relativo una zona se maneja mediante una");
  Pan_PonTexto (4,16,"escala especificada por el programador.");
  Pan_PonTexto (5,16,"Mediante esa escala, se pueden dibujar puntos, lneas");
  Pan_PonTexto (6,16,"y bloques.");

  if ( Asterix = Zon_Crea (9,18,18,64) )
    {
    if ( Obelix = Zon_Crea (9,72,18,74) )
      {
      Usr_Indica ("A la izquierda ves lneas y a la derecha bloques",
                  "Pulsa cualquier tecla para parar");
      while ( !Tec_Disponible() )
        {
        Zon_Borra (Asterix, NEGRO);
        Zon_Borra (Obelix, NEGRO);
        for ( Cuenta = 0 ; Cuenta <= 100 ; Cuenta++ )
          {
          switch ( Azr_Entero(0,2) )
            {
            case 0: Color = BLANCO; break;
            case 1: Color = VERDE;  break;
            case 2: Color = ROJO;   break;
            }
          Zon_Linea (Asterix, (real) Azr_Entero(2,12), (real) Azr_Entero(1,99),
                     (real) Azr_Entero(88,98), (real) Azr_Entero(1,99), Color);
          Zon_Bloque (Obelix,0.0,0.0,100.0,(real)Cuenta,VERDE);
          }
        }
      Tec_Pulsada();
      Zon_Destruye (Obelix);
      }
    Zon_Destruye (Asterix);
    }

  else
    {
    Pan_PonTexto (8,16,"Aunque ests en modo Grfico, no hay suficiente");
    Pan_PonTexto (9,16,"memoria para abrir zonas.");
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoCadena()
 * OBJETIVO: Demostrar las posibilidades del objeto Cadena
 *------------------------------------------------------------------*/
void DemoCadena()
  {
  cadena   Cadena1, Cadena2, Aux;
  contador Comparacion;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Hay muchas funciones para manejar con comodidad");
  Pan_PonTexto (4,16,"cadenas. Slo vemos unos ejemplos.");
  Pan_PonTexto (5,16,"Se utiliza asignacin dinmica.");

  Pan_PonTexto (7,16,"Introduce dos cadenas:");
  Pan_Borra (ROJO,7,39,7,55); Pan_Borra (ROJO,7,58,7,73);
  Cadena1 = Usr_Texto ("",16,7,39,ROJO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    Cadena2 = Usr_Texto ("",16,7,58,ROJO,BLANCO);
    if ( Tec_Ultima() != TEC_ESC )
      {
      Pan_Color (NEGRO,BLANCO);
      Pan_PonTexto (9,16,"Sus longitudes: ");
      Pan_Entero ( Cad_Longitud(Cadena1), 2 );
      Pan_Texto (" y ");
      Pan_Entero ( Cad_Longitud(Cadena2), 2 );

      Pan_PonTexto (10,16,"Las cadenas concatenadas: ");
      Aux = Cad_Une (Cadena1,Cadena2,CAD_FIN);
      Pan_Texto (Aux);
      Cad_Destruye (Aux);

      Pan_PonTexto (11,16,"Posicin de 'a' en la primera: ");
      Pan_Entero ( Cad_CarPertenece(Cadena1,'a'), 2 );
      Pan_PonTexto (12,16,"Posicin de 'x' en la primera: ");
      Pan_Entero ( Cad_CarPertenece(Cadena1,'x'), 2 );

      Pan_PonTexto (13,16,"El trozo de 2 a 5 de la primera: ");
      if ( Cad_Longitud (Cadena1) >= 2 )
        {
        Aux = Cad_Trozo (Cadena1,2,5);
        Pan_Texto ( Aux );
        Cad_Destruye ( Aux );
        }

      Pan_PonTexto (14,16,"Posicin de la primera en la segunda: ");
      Pan_Entero ( Cad_Subcadena (Cadena2,Cadena1), 2 );

      Pan_PonTexto (15,16,"La primera cadena en maysculas: ");
      Aux = Cad_Mayus (Cad_Duplica(Cadena1));
      Pan_Texto (Aux);
      Cad_Destruye (Aux);

      Pan_PonTexto (16,16,"La primera cadena en minsculas: ");
      Aux = Cad_Minus (Cad_Duplica(Cadena1));
      Pan_Texto (Aux);
      Cad_Destruye (Aux);

      Pan_PonTexto (17,16,"Por orden alfabtico la primera va ");
      Comparacion = Cad_Compara (Cadena1,Cadena2);
      Pan_Resalta ( SI );
      if      ( Comparacion < 0 ) { Pan_Texto ("antes");   }
      else if ( Comparacion > 0 ) { Pan_Texto ("despus"); }
      else                        { Pan_Texto ("igual"); }
      Pan_Resalta ( NO );
      Pan_Texto ( " que la segunda");
      Usr_PulsaUnaTecla ("");
      }
    Cad_Destruye (Cadena2);
    }
  Cad_Destruye (Cadena1);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoPrograma()
 * OBJETIVO: Demostrar las posibilidades del objeto Programa
 *------------------------------------------------------------------*/
void DemoPrograma()
  {
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"La lnea de arriba de la pantalla est reservada");
  Pan_PonTexto (4,16,"para presentar el programa.");
  Pan_PonTexto (6,16,"Se puede indicar el nombre del programa, la versin,");
  Pan_PonTexto (7,16,"el autor y la fecha.");
  Pan_PonTexto (9,16,"Todos estos datos se colocan automticamente.");
  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFecha()
 * OBJETIVO: Demostrar las posibilidades del objeto Fecha
 *------------------------------------------------------------------*/
void DemoFecha()
  {
  static cadena NombreDia[] = {"Domingo", "Lunes", "Martes", "Mircoles",
                               "Jueves", "Viernes", "Sbado" };
  static cadena NombreMes[] = {"Enero", "Febrero", "Marzo", "Abril", "Mayo",
                               "Junio", "Julio", "Agosto", "Septiembre",
                               "Octubre", "Noviembre", "Diciembre"};
  fecha  Fecha, Hoy;
  cadena Cadena;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Se pueden hacer algunos clculos con fechas, como");
  Pan_PonTexto (4,16,"encontrar el da de la semana y el nmero de das");
  Pan_PonTexto (5,16,"transcurridos entre dos fechas.");
  Pan_PonTexto (6,16,"No se puede (an) comprobar la validez de una fecha.");
  Pan_Tinta (VERDE);
  Pan_PonTexto (8,61,"AAAAMMDD");
  Pan_Tinta (BLANCO);
  Pan_PonTexto (9,16,"Introduce una fecha con el formato indicado:");
  Cadena = Usr_Texto ("",8,9,61,ROJO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    Fecha = Fec_LeeCadena(Cadena);
    Hoy = Fec_Hoy();

    if ( Fec_Mes(Fecha)>0 && Fec_Mes(Fecha)<13 &&
         Fec_Dia(Fecha)>0 && Fec_Dia(Fecha)<32 )
      {
      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (11,16,"La fecha: ");
      Pan_Tinta (BLANCO);
      Pan_Texto ( NombreDia [Fec_DiaSemana(Fecha)] );
      Pan_Caracter ( ' ' );
      Pan_Entero ( Fec_Dia(Fecha), 1 );
      Pan_Texto ( " de " );
      Pan_Texto ( NombreMes [Fec_Mes(Fecha)-1] );
      Pan_Texto ( " de " );
      Pan_Entero ( Fec_Ano(Fecha), 1 );

      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (13,16,"Hoy: ");
      Pan_Tinta (BLANCO);
      Pan_Texto ( NombreDia [Fec_DiaSemana(Hoy)] );
      Pan_Caracter ( ' ' );
      Pan_Entero ( Fec_Dia(Hoy), 1 );
      Pan_Texto ( " de " );
      Pan_Texto ( NombreMes [Fec_Mes(Hoy)-1] );
      Pan_Texto ( " de " );
      Pan_Entero ( Fec_Ano(Hoy), 1);

      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (15,16,"Han transcurrido ");
      Pan_Tinta (BLANCO);
      Pan_Entero ( Fec_Diferencia(Fecha,Hoy), 1 );
      Pan_Texto ( " das" );
      }
    else
      { Pan_PonTexto (11,16,"Esa fecha no existe."); }

    Fec_Destruye (Fecha);
    Fec_Destruye (Hoy);
    Usr_PulsaUnaTecla("");
    }
  Cad_Destruye (Cadena);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoTecla()
 * OBJETIVO: Demostrar las posibilidades del objeto Tecla
 *------------------------------------------------------------------*/
void DemoTecla()
  {
  static tecla Lista[] = { TEC_F1, TEC_F2, TEC_F3, TEC_F4,
                           TEC_F5, TEC_ESC, NIL };
  static cadena Efe[] = { "F1", "F2", "F3", "F4", "F5" };
  tecla  Tecla;
  octeto i, EfeAntes=0, EfeAhora=0, Pos=0;
  logico Sigue=SI;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Es posible comprobar que se pulsa una tecla entre");
  Pan_PonTexto (4,16,"un conjunto predeterminado y mientras tanto hacer");
  Pan_PonTexto (5,16,"otras operaciones.");

  Cdr_Dibuja (CDR_SIMPLE,CDR_SIMPLE,1,1,5,4,9,33,NEGRO,VERDE);
  Usr_Indica ("Pulsa las teclas F1, F2, F3, F4 o F5 a tu gusto",
              "Cuando quieras terminar, pulsa ESC");
  Pan_Color (NEGRO,ROJO);
  for ( i=0 ; i<5 ; i++ )
    { Pan_PonTexto (10,35+5*i,Efe[i]); }
  Pan_Color (NEGRO,VERDE);
  for ( i=0 ; i<48 ; i++ )
    { Pan_PonCar (16,22+i,'.'); }

  while ( Sigue )
    {
    if ( Tecla = Tec_ValidadaRapido (Lista) )
      {
      switch ( Tecla )
        {
        case TEC_F1:   EfeAhora = 0;  break;
        case TEC_F2:   EfeAhora = 1;  break;
        case TEC_F3:   EfeAhora = 2;  break;
        case TEC_F4:   EfeAhora = 3;  break;
        case TEC_F5:   EfeAhora = 4;  break;
        case TEC_ESC:  Sigue = NO;    break;
        }
      Pan_Tinta (ROJO);
      Pan_PonTexto (10,35+5*EfeAntes,Efe[EfeAntes]);
      Pan_Tinta (BLANCO);
      Pan_PonTexto (10,35+5*EfeAhora,Efe[EfeAhora]);
      EfeAntes = EfeAhora;
      }
    else
      {
      Tim_Espera (0.1);
      Pan_Tinta (VERDE);
      Pan_PonCar (16,22+Pos,'.');
      Pos++; if ( Pos==48 )  { Pos = 0; }
      Pan_PonCar (16,22+Pos,'*');
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoCuadro()
 * OBJETIVO: Demostrar las posibilidades del objeto Cuadro
 *------------------------------------------------------------------*/
void DemoCuadro()
  {
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Se pueden dibujar en la pantalla lneas, cajas");
  Pan_PonTexto (4,16,"y cuadros con los colores disponibles.");
  Pan_PonTexto (5,16,"Hay dos grosores posibles.");
  Cdr_Linea (CDR_SIMPLE,7,16,7,76,ROJO,BLANCO);
  Cdr_Linea (CDR_DOBLE,19,16,19,76,VERDE,NEGRO);
  Cdr_Dibuja (CDR_DOBLE,CDR_SIMPLE,4,1,5,4,9,18,BLANCO,ROJO);
  Cdr_Dibuja (CDR_DOBLE,CDR_SIMPLE,4,1,5,4,9,49,NEGRO,VERDE);
  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoRegion()
 * OBJETIVO: Demostrar las posibilidades del objeto Region
 *------------------------------------------------------------------*/
void DemoRegion()
  {
  region Region;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Las regiones son partes rectangulares de la pantalla");
  Pan_PonTexto (4,16,"en las que se puede escribir de la misma forma que");
  Pan_PonTexto (5,16,"a la pantalla, pero usando coordenadas relativas a");
  Pan_PonTexto (6,16,"la esquina superior derecha, no coordenadas absolutas");
  Pan_PonTexto (7,16,"de la pantalla. Cada regin mantiene los colores con");
  Pan_PonTexto (8,16,"los que escribe.");

  if ( Region = Reg_Crea(11,18,18,74) )
    {
    Reg_Borde (Region, CDR_DOBLE, BLANCO, ROJO);
    Reg_Color (Region, BLANCO, NEGRO);
    Reg_TextoCentrado (Region, "Es fcil poner bordes", 2);
    Reg_TextoCentrado (Region, "Es fcil centrar texto", 4);
    Reg_Destruye (Region);
    }
  else  { Usr_Avisa("No se ha podido crear la regin"); }

  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoUsuario()
 * OBJETIVO: Demostrar las posibilidades del objeto Usuario
 *------------------------------------------------------------------*/
void DemoUsuario()
  {
  enum { SALIDA_ESC, CONSULTA, INFORMA, AVISA, ESPERA, INDICA,
         ENTERO, TEXTO, EDITA };
  static cadena MenuUsuario[] = { ">Consulta", ">Informa", ">Avisa",
         ">Espera", "I>ndica", "En>tero", "Te>xto", "E>dita", NIL };
  entero   Opcion=1;
  contador Entero;
  logico   Sigue=SI, Respuesta;
  cadena   Cadena;
  region   Region;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Las dos ltimas lneas de la pantalla estn reservadas");
  Pan_PonTexto (4,16,"para interactuar con el usuario. Hay varias opciones:");

  Cdr_Caja (CDR_SIMPLE,6,16,15,27,NEGRO,VERDE);
  while ( Sigue )
    {
    Opcion = Men_Vertical (7,17,14,26,MenuUsuario,Opcion);
    Pan_Color (NEGRO,BLANCO);
    switch ( Opcion )
      {
      case SALIDA_ESC:  Sigue = NO;    break;

      case CONSULTA:
           Pan_PonTexto (8,40,"Contesta esta pregunta");
           Respuesta = Usr_Consulta ("Quieres contestar esta pregunta?");
           Pan_Color (NEGRO,BLANCO);
           Pan_PonTexto (12,40,"Respuesta: ");
           if ( Respuesta ) { Pan_Texto ("S"); }
           else             { Pan_Texto ("No"); }
           Pulsa();
           break;

      case INFORMA:
           Pan_PonTexto (9,40,"Mientras se calcula algo");
           Pan_PonTexto (10,40,"se puede informar al usuario");
           Usr_Informa ("Estoy haciendo una operacin");
           Pulsa();
           break;

      case AVISA:
           Pan_PonTexto (10,40,"As se muestran los errores");
           Usr_Avisa ("No te preocupes, esto es un falso error");
           break;

      case ESPERA:
           Usr_PulsaUnaTecla ("Entrate de este mensaje");
           break;

      case INDICA:
           Pan_PonTexto (12,40,"Observa las indicaciones");
           Usr_Indica ("Fjate qu bien te estoy informando.",
                       "Dispones de dos lneas.");
           Pulsa();
           break;

      case ENTERO:
           Pan_PonTexto (7,35,"Se puede dar un entero para editar");
           Entero = 100;
           Pan_PonTexto (10,35,"Entero antes de editar: ");
           Pan_Entero (Entero,3);
           Entero = Usr_Entero (Entero,3,-99,999,12,45,ROJO,BLANCO);
           Pan_Color (NEGRO,BLANCO);
           Pan_PonTexto (14,35,"Entero despus de editar: ");
           Pan_Entero (Entero,3);
           Pulsa();
           break;

      case TEXTO:
           Pan_PonTexto (7,35,"Se puede dar un texto para editar");
           Cadena = "Texto inicial";
           Pan_PonTexto (10,35,"Texto antes de editar: ");
           Pan_Texto (Cadena);
           Cadena = Usr_Texto (Cadena,20,12,41,ROJO,BLANCO);
           Pan_Color (NEGRO,BLANCO);
           Pan_PonTexto (14,35,"Texto despus: ");
           Pan_Texto (Cadena);
           Cad_Destruye (Cadena);
           Pulsa();
           break;

      case EDITA:
           Pan_PonTexto (7,35,"Se dispone de un pequeo editor.");
           Pan_PonTexto (8,35,"Prubalo escribiendo algo:");
           Cdr_Caja (CDR_SIMPLE,10,35,18,74,NEGRO,ROJO);
           Region = Reg_Crea(11,36,17,73);
           Cadena = Usr_Edita (Region,"");
           Cad_Destruye (Cadena);
           Reg_Destruye (Region);
           Pulsa();
           break;
      }
    LimpiaZonaDemoUsr();
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  Pulsa()
 * OBJETIVO: Esperar que el usuario pulse una tecla
 *------------------------------------------------------------------*/
void Pulsa()
  {
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (18,17,"Pulsa una");
  Pan_PonTexto (19,17,"tecla: ");
  Pan_CursorVisible(SI);
  Tec_Pulsada();
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFichero()
 * OBJETIVO: Demostrar las posibilidades del objeto Fichero
 *------------------------------------------------------------------*/
void DemoFichero()
  {
  enum { SALIDA_ESC, EXISTENCIA, LECTURA, BORRADO, LISTADO };
  static cadena MenuFichero[] = { ">Existencia", ">Lectura", ">Borrado",
                                  "Li>stado", NIL };
  entero Opcion=1;
  logico Sigue=SI;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Olimpo maneja de modo automtico varias operaciones con");
  Pan_PonTexto (4,16,"ficheros, liberando al programador de muchas ");
  Pan_Texto ("comprobaciones");

  Cdr_Caja (CDR_SIMPLE,6,16,11,29,NEGRO,VERDE);
  while ( Sigue )
    {
    Opcion = Men_Vertical (7,17,10,28,MenuFichero,Opcion);
    Pan_Color (NEGRO,BLANCO);
    switch ( Opcion )
      {
      case SALIDA_ESC:  Sigue = NO;           break;
      case EXISTENCIA:  DemoFchExistencia();  break;
      case LECTURA:     DemoFchLectura();     break;
      case BORRADO:     DemoFchBorrado();     break;
      case LISTADO:     DemoFchListado();     break;
      }
    LimpiaZonaDemoFch();
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFchExistencia()
 * OBJETIVO: Demostrar las posibilidades de la funcin Fch_Existe()
 *------------------------------------------------------------------*/
void DemoFchExistencia()
  {
  cadena  Nombre;
  fichero Fichero;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (7,33,"Se puede comprobar si existe un fichero");

  Pan_PonTexto (9,33,"Escribe el nombre de un fichero:");
  Nombre = Usr_Texto ("",20,11,33,BLANCO,NEGRO);
  Pan_Color (NEGRO,BLANCO);

  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( Fch_Existe (Nombre) ) { Pan_PonTexto (13,33,"S existe"); }
    else                       { Pan_PonTexto (13,33,"No existe"); }
    Usr_PulsaUnaTecla ("");
    }

  Cad_Destruye (Nombre);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFchLectura()
 * OBJETIVO: Demostrar las posibilidades de lectura de ficheros
 *------------------------------------------------------------------*/
void DemoFchLectura()
  {
  cadena   Nombre, Linea;
  fichero  Fichero;
  contador i;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (7,33,"Se pueden leer y grabar ficheros de texto");
  Pan_PonTexto (8,33,"y binarios.");

  Nombre = Fch_Nombre ("Demo","cnf");
  Pan_PonTexto (10,33,"Primeras 6 lneas de ");
  Pan_Texto (Nombre);
  Fichero = Fch_AbreLeer (Nombre,FCH_TEXTO);
  if ( Fichero )
    {
    Pan_Tinta (VERDE);
    for ( i=0 ; i<6 && (Linea = Fch_LeeLinea(Fichero)) ; i++ )
      {
      Pan_PonTexto (12+i,16,Linea);
      Cad_Destruye (Linea);
      }
    Fch_Cierra (Fichero);
    Cad_Destruye (Nombre);

    Pan_Tinta (BLANCO);
    Pan_PonTexto (19,16,"Si se intenta abrir un fichero inexistente...");
    Nombre = Fch_Nombre ("Vacuum","txt");
    Fichero = Fch_AbreLeer (Nombre,FCH_TEXTO);
    if (Fichero)
      {
      Fch_Cierra(Fichero);
      Usr_PulsaUnaTecla ("Bueno, pues s exista");
      }
    }
  Cad_Destruye (Nombre);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFchBorrado()
 * OBJETIVO: Demostrar las posibilidades de la funcin Fch_Borra()
 *------------------------------------------------------------------*/
void DemoFchBorrado()
  {
  cadena   Nombre;
  fichero  Fichero;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (7,33,"Puedes borrar un fichero. Para probarlo, creo");
  Pan_PonTexto (8,33,"un fichero de nombre extrao: ");
  Nombre = Fch_Nombre ("Inutil","xyz");
  Pan_Texto (Nombre);

  if ( Fichero = Fch_AbreGrabar (Nombre,FCH_TEXTO) )
    {
    Fch_EscribeLinea (Fichero,"Este fichero no sirve para nada");
    Fch_Cierra (Fichero);
    }

  Pan_PonTexto (10,33,"Y ahora llamo a la funcin que borra: ");
  Fch_Borra (Nombre);

  Cad_Destruye (Nombre);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoFchListado()
 * OBJETIVO: Demostrar las posibilidades de la funcin Fch_ListaNombre()
 *------------------------------------------------------------------*/
void DemoFchListado()
  {
  cadena   Mascara, Propuesta, Mensaje;
  lista    Posible, L;
  entero   Elegido;
  menu     MenuPosible;
  caracter Aux[21];

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (6,33,"Puedes ver los ficheros que encajan");
  Pan_PonTexto (7,33,"con una mscara determinada:");

  Propuesta = Fch_Nombre ("*","?");
  Mascara = Usr_Texto (Propuesta,12,9,33,BLANCO,NEGRO);
  Cad_Destruye (Propuesta);

  if ( Tec_Ultima() != TEC_ESC )
    {
    Usr_Informa ("Buscando ficheros");
    Posible = Fch_ListaNombre (Mascara);
    if ( Posible )
      {
      MenuPosible = Men_Crea (MEN_VERTICAL,9,53,20,70,Lis_Total(Posible),
                              MEN_LISTA,(memoria)Posible);
      Elegido = Men_Ejecuta (MenuPosible,(entero)1,
                             "Elige uno de los ficheros");
      Pan_Color (NEGRO,VERDE);

      Pan_PonTexto (13,20,"Fichero elegido:");
      Pan_Cursor (15,20);
      Pan_Tinta (BLANCO);
      if ( Elegido )
        {
        Men_Texto (MenuPosible, Elegido, Aux);
        Pan_TextoControlado (Aux, 20);
        }
      else
        { Pan_Texto ("[Ninguno]"); }

      Men_Destruye (MenuPosible);
      Lis_Destruye (Posible);
      }

    else
      {
      Mensaje = Cad_Une ("No se encontrado ningn fichero ","\"",Mascara,
                         "\"", CAD_FIN);
      Usr_PulsaUnaTecla (Mensaje);
      Cad_Destruye (Mensaje);
      }
    }
  Cad_Destruye (Mascara);

  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMenu()
 * OBJETIVO: Demostrar las posibilidades del objeto Men
 *------------------------------------------------------------------*/
void DemoMenu()
  {
  static cadena MenuMenu[] = { "Mens >sencillos", ">Mostrar opciones",
                               ">Configurar colores", ">Teclas de control",
                               NIL };
  logico Sigue = SI;
  entero Opcion = 1;

  while ( Sigue )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (3,18,"Se pueden usar dos tipos de mens: los sencillos,");
    Pan_PonTexto (4,18,"que no se pueden configurar pero se crean fcilmente");
    Pan_PonTexto (5,18,"y los completos, que admiten muchas variantes, como");
    Pan_PonTexto (6,18,"usarlos slo para mostrar las opciones disponibles,");
    Pan_PonTexto (7,18,"cambiar los colores, usar ms teclas de control,");
    Pan_PonTexto (8,18,"especificar opciones no disponibles, etc.");

    Opcion = Men_Vertical (11,30,15,50,MenuMenu,Opcion);
    LimpiaZonaTrabajo();
    switch ( Opcion )
      {
      case 0:  Sigue = NO;                      break;
      case 1:  DemoMenuSencillo();  Opcion++;   break;
      case 2:  DemoMenuMostrar();   Opcion++;   break;
      case 3:  DemoMenuColor();     Opcion++;   break;
      case 4:  DemoMenuTecla();     Opcion=1;   break;
      }
    LimpiaZonaTrabajo();
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMenuSencillo()
 * OBJETIVO: Demostrar las posibilidades del objeto Men con mens sencillos
 *------------------------------------------------------------------*/
void DemoMenuSencillo()
  {
  static cadena MenuH[] = {">Primero", ">Segundo", ">Tercero", ">Cuarto", NIL};

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,18,"Los mens sencillos pueden ser horizontales o ");
  Pan_Texto ("verticales.");
  Pan_PonTexto (5,18,"Ambos se adaptan automticamente al espacio disponible");

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (8,16,"Un men horizontal:");
  Cdr_Caja (CDR_SIMPLE,10,16,12,76,NEGRO,VERDE);
  Men_Horizontal (11,17,75,MenuH,(entero)1);

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (15,16,"El mismo men con menos espacio:");
  Cdr_Caja (CDR_SIMPLE,17,16,19,55,NEGRO,VERDE);
  Men_Horizontal (18,17,54,MenuH,(entero)1);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMenuMostrar()
 * OBJETIVO: Demostrar las posibilidades del objeto Men para mostar opciones
 *------------------------------------------------------------------*/
void DemoMenuMostrar()
  {
  menu Menu;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Cuando se crea un men configurable, se puede optar");
  Pan_PonTexto (4,16,"por slo mostrar las opciones, sin obligar a elegir");
  Pan_PonTexto (5,16,"entre ellas.");

  Menu = Men_Crea (MEN_VERTICAL,8,31,19,57,(entero)75,
                   MEN_PROPIO,(memoria)FuncionDemoMenu);
  Men_Muestra (Menu, (entero)15, "Estudia los 75 primeros cuadrados");
  Men_Destruye (Menu);
  }

/*--------------------------------------------------------------------
 * FUNCION:  FuncionDemoMenu()
 * OBJETIVO: Apoyar la funcin DemoMenuMostrar()
 *------------------------------------------------------------------*/
logico FuncionDemoMenu (Num, Texto)
entero Num;
cadena Texto;
  {
  sprintf ( Texto, " El cuadrado de %ld es %ld ", Num, Num*Num );
  return ( SI );
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMenuColor()
 * OBJETIVO: Demostrar las posibilidades del objeto Men para cambiar colores
 *------------------------------------------------------------------*/
void DemoMenuColor()
  {
  static cadena MenuColor[] = {
    ">Primero", ">Segundo", ">Tercero", ">Cuarto", ">Quinto", "Se>xto",
    "Sptimo", "Octavo", "Noveno", "Dcimo", "Undcimo", "Duodcimo" };
  menu Menu;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Cuando se crea un men configurable, se pueden cambiar");
  Pan_PonTexto (4,16,"los colores de cada elemento del men.");
  Pan_PonTexto (6,16,"Observa el mismo men con distintos colores:");

  Menu = Men_Crea (MEN_VERTICAL,10,34,17,44,(entero)12,
                   MEN_VECTOR,(memoria)MenuColor);
  Men_Disponible (Menu, (entero)7, NO);
  Men_Disponible (Menu, (entero)10, NO);
  Men_Ejecuta (Menu, (entero)1,
      "Aunque no tenga importancia, elige una de las opciones");
  Men_Color (Menu, ROJO, BLANCO, BLANCO, VERDE, VERDE, ROJO, NEGRO, VERDE);
  Men_Ejecuta (Menu, (entero)1,
      "Aunque no tenga importancia, elige una de las opciones");
  Men_Destruye (Menu);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMenuTecla()
 * OBJETIVO: Demostrar las posibilidades del objeto Men para aadir
 *           teclas de control
 *------------------------------------------------------------------*/
void DemoMenuTecla()
  {
  static cadena TextoH[] = { ">Archivo", ">Edicin", "A>yuda" };
  static cadena TextoV1[] = { ">Abrir...            ^A",
                              ">Guardar             ^G",
                              "Guar>dar como...     ^D",
                              ">Cerrar          Alt-F3",
                              ">Salir            Alt-X" };
  static cadena TextoV2[] = { ">Copiar   ^C",
                              "Cor>tar   ^T",
                              ">Pegar    ^P" };
  static cadena TextoV3[] = { ">General      F1",
                              ">Contenidos  ^F1",
                              "Acerca de...   " };

  static tecla TeclaV1[] = { TEC_DERECHA, NIL };
  static tecla TeclaV2[] = { TEC_IZQUIERDA, TEC_DERECHA, NIL };
  static tecla TeclaV3[] = { TEC_IZQUIERDA, NIL };

  menu   MenuH, MenuV1, MenuV2, MenuV3;
  logico Sigue=SI, Desplegado=NO;
  entero OpcionH=1, OpcionV=1;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Cuando se crea un men configurable, se pueden cambiar");
  Pan_PonTexto (4,16,"las teclas que permiten salir de un men. Permite crear");
  Pan_PonTexto (5,16,"fcilmente mens encadenados:");

  MenuH = Men_Crea (MEN_HORIZONTAL,8,17,8,70,(entero)3,
                    MEN_VECTOR,(memoria)TextoH);
  MenuV1 = Men_Crea (MEN_VERTICAL,10,17,14,40,(entero)5,
                     MEN_VECTOR,(memoria)TextoV1);
  MenuV2 = Men_Crea (MEN_VERTICAL,10,38,12,51,(entero)3,
                     MEN_VECTOR,(memoria)TextoV2);
  MenuV3 = Men_Crea (MEN_VERTICAL,10,53,12,69,(entero)3,
                     MEN_VECTOR,(memoria)TextoV3);
  Men_TeclaSi (MenuV1, TeclaV1);
  Men_TeclaSi (MenuV2, TeclaV2);
  Men_TeclaSi (MenuV3, TeclaV3);

  while ( Sigue )
    {
    if ( !Desplegado )
      {
      OpcionH = Men_Ejecuta (MenuH, OpcionH,
                             "Ests en el men principal");
      Desplegado = SI;
      }
    switch ( OpcionH )
      {
      case 0: Sigue = NO; break;
      case 1: OpcionV = Men_Ejecuta (MenuV1, (entero)1,
                            "Ests en el men Archivo");
              break;
      case 2: OpcionV = Men_Ejecuta (MenuV2, (entero)1,
                            "Ests en el men Edicin");
              break;
      case 3: OpcionV = Men_Ejecuta (MenuV3, (entero)1,
                            "Ests en el men Ayuda");
              break;
      }
    Pan_Borra (NEGRO,10,17,14,78);
    if ( !OpcionV )  { Desplegado = NO; }
    else
      {
      switch ( Tec_Ultima() )
        {
        case TEC_ENTER:     Sigue = NO; break;
        case TEC_DERECHA:   OpcionH++;
                            Men_Escribe (MenuH, OpcionH, SI);
                            break;
        case TEC_IZQUIERDA: OpcionH--;
                            Men_Escribe (MenuH, OpcionH, SI);
                            break;
        }
      }
    }

  Men_Destruye (MenuH);
  Men_Destruye (MenuV1);
  Men_Destruye (MenuV2);
  Men_Destruye (MenuV3);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoConfig()
 * OBJETIVO: Demostrar las posibilidades del objeto Configuracin
 *------------------------------------------------------------------*/
void DemoConfig()
  {
  cadena   NombreConfig, Linea;
  fichero  Fichero;
  config   Configuracion;
  contador i;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Este objeto lee un fichero entregando slo las");
  Pan_PonTexto (4,16,"lneas que no son comentarios. Veamos un ejemplo:");

  NombreConfig = Fch_Nombre ("Demo","cnf");
  Pan_Tinta (ROJO);
  Pan_PonTexto (6,16,"Este el el fichero ");
  Pan_Texto (NombreConfig);
  Fichero = Fch_AbreLeer (NombreConfig,FCH_TEXTO);
  if ( Fichero )
    {
    Pan_Tinta (VERDE);
    i=0;
    while ( Linea = Fch_LeeLinea (Fichero) )
      {
      Pan_PonTexto (7+i++,16,Linea);
      Cad_Destruye (Linea);
      }
    Fch_Cierra ( Fichero );

    Pan_Tinta (ROJO);
    Pan_PonTexto (18,16,"Y esto es lo que se lee mediante este objeto");
    Configuracion = Cnf_Abre (NombreConfig);
    if ( Configuracion )
      {
      for ( i=0 ; Linea = Cnf_Lee (Configuracion) ; i++ )
        {
        Pan_Tinta (VERDE);
        Pan_PonTexto (19+i,16,Linea);
        Pan_Tinta (BLANCO);
        Pan_PonTexto (19+i,35,"[Nmero ");
        Pan_Entero (Cnf_Linea(Configuracion),1);
        Pan_Caracter (']');
        Cad_Destruye (Linea);
        }
      Cnf_Cierra ( Configuracion );
      }
    }

  Cad_Destruye (NombreConfig);
  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoBaseDato()
 * OBJETIVO: Demostrar las posibilidades del objeto Base de datos
 *------------------------------------------------------------------*/
void DemoBaseDato()
  {
  static cadena MenuBase[] = { ">Datos generales", ">Estructura",
                               ">Registros", NIL };
  logico Sigue = SI;
  entero Opcion = 1;

  while ( Sigue )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (3,16,"Es posible crear, leer y modificar ficheros de base de");
    Pan_PonTexto (4,16,"datos en formato dBase (DBF).");
    Pan_PonTexto (6,16,"De cualquier base de datos se puede ver:");

    switch ( Opcion = Men_Vertical (8,20,10,40,MenuBase,Opcion) )
      {
      case 0:  Sigue = NO;                      break;
      case 1:  MuestraGeneral();    Opcion++;   break;
      case 2:  MuestraEstructura(); Opcion++;   break;
      case 3:  MuestraRegistros();  Opcion = 1; break;
      }
    LimpiaZonaTrabajo();
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  MuestraGeneral()
 * OBJETIVO: Mostrar datos generales de una base de datos
 *------------------------------------------------------------------*/
void MuestraGeneral()
  {
  cadena   Propuesta, NombreFich;
  basedato Base;

  Pan_Borra (NEGRO,6,16,15,78);
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (6,16,"Datos generales del fichero:");
  Propuesta = Fch_Nombre ("Demo","dbf");
  NombreFich = Usr_Texto (Propuesta,30,6,45,BLANCO,NEGRO);
  Usr_BorraZona (NEGRO);
  Cad_Destruye (Propuesta);

  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( Base = Bdt_Abre (NombreFich, BDT_LECTURA) )
      {
      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (8,16,"Fecha de la ltima modificacin: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Bdt_DiaUltimo(Base),1);
      Pan_Caracter ('.');
      Pan_Entero (Bdt_MesUltimo(Base),1);
      Pan_Caracter ('.');
      Pan_Entero (Bdt_AnoUltimo(Base),1);

      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (10,16,"Nmero de registros: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Bdt_TotalRegistro(Base),1);

      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (12,16,"Nmero de campos: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Bdt_TotalCampo(Base),1);

      Bdt_Cierra (Base);
      Usr_PulsaUnaTecla ("");
      }
    }

  Cad_Destruye (NombreFich);
  }

/*--------------------------------------------------------------------
 * FUNCION:  MuestraEstructura()
 * OBJETIVO: Mostrar la estructura de una base de datos
 *------------------------------------------------------------------*/
void MuestraEstructura()
  {
  cadena   Propuesta, NombreFich;
  basedato Base;
  contador Tope=13, i;
  caracter Aux[11];

  LimpiaZonaTrabajo();
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Estructura del fichero:");
  Propuesta = Fch_Nombre ("Demo","dbf");
  NombreFich = Usr_Texto (Propuesta,30,3,40,BLANCO,NEGRO);
  Usr_BorraZona (NEGRO);
  Cad_Destruye (Propuesta);

  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( Base = Bdt_Abre (NombreFich, BDT_LECTURA) )
      {
      Cdr_Caja (CDR_SIMPLE,5,16,7+Tope,72,NEGRO,VERDE);
      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (6,18,"Nmero");
      Pan_PonTexto (6,27,"Nombre");
      Pan_PonTexto (6,40,"Tipo");
      Pan_PonTexto (6,49,"Longitud");
      Pan_PonTexto (6,60,"Decimales");

      Pan_Color (NEGRO,BLANCO);
      for ( i = 0 ; i < Min(Tope,Bdt_TotalCampo(Base)) ; i++ )
        {
        Pan_PonEntero (7+i,20,i,2);
        Bdt_NombreDeCampo (Base,i,Aux);
        Pan_PonTexto (7+i,27,Aux);
        Pan_PonCar (7+i,42,Bdt_TipoDeCampo(Base,i));
        Pan_PonEntero (7+i,52,Bdt_LongitudDeCampo(Base,i),3);
        Pan_PonEntero (7+i,63,Bdt_DecimalDeCampo(Base,i),2);
        }
      if ( Bdt_TotalCampo(Base) > Tope )
        { Pan_PonCar(7+Tope,74,'+'); }
      Bdt_Cierra (Base);
      Usr_PulsaUnaTecla ("");
      }
    }

  Cad_Destruye (NombreFich);
  }

/*--------------------------------------------------------------------
 * FUNCION:  MuestraRegistros()
 * OBJETIVO: Mostrar registros de Demo.dbf en el orden en que estn
 *------------------------------------------------------------------*/
void MuestraRegistros()
  {
  cadena   Contenido, NombreFich;
  basedato Base;
  entero   i;
  logico   Sigue = SI;
  menudo   Fil;

  LimpiaZonaTrabajo();
  Pan_Color (NEGRO,BLANCO);

  NombreFich = Fch_Nombre ("Demo","dbf");
  if ( Base = Bdt_Abre (NombreFich, BDT_LECTURA) )
    {
    Contenido = Cad_Crea (Bdt_LongitudRegistro(Base));
    MarcoRegistro();

    for ( i = 0 , Fil = 0 ;
          i < Bdt_TotalRegistro(Base) && Sigue ; i++ , Fil++ )
      {
      EscribeRegistro (Base,i,Contenido,Fil);
      if ( Fil == 15 )
        {
        Sigue = Usr_Consulta ("Hay ms registros. Quieres verlos?");
        Fil = -1;
        Pan_Borra (NEGRO,5,16,20,76);
        }
      }

    Cad_Destruye (Contenido);
    Bdt_Cierra (Base);
    if ( Sigue )  { Usr_PulsaUnaTecla (""); }
    }

  Cad_Destruye (NombreFich);
  }

/*--------------------------------------------------------------------
 * FUNCION:  MarcoRegistro()
 * OBJETIVO: Dibujar en la pantalla el marco para mostrar registros
 *------------------------------------------------------------------*/
void MarcoRegistro()
  {
  cadena NombreFich;

  Pan_Color (NEGRO,BLANCO);
  NombreFich = Fch_Nombre ("Demo","dbf");
  Pan_PonTexto (2,16,"Registros del fichero ");
  Pan_Texto (NombreFich);
  Cad_Destruye (NombreFich);

  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (4,16,"Nombre");
  Pan_PonTexto (4,29,"Apellido");
  Pan_PonTexto (4,41,"Altura");
  Pan_PonTexto (4,49,"Peso");
  Pan_PonTexto (4,55,"Deporte");
  Pan_PonTexto (4,67,"Pais");
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeRegistro()
 * OBJETIVO: Escribir el registro i de Demo.dbf en la fila Fil
 *------------------------------------------------------------------*/
void EscribeRegistro (Base,i,Contenido,Fil)
basedato Base;
entero   i;
cadena   Contenido;
contador Fil;
  {
  static contador Col[] = {16,29,42,50,55,67};
  contador k;

  Bdt_LeeRegistro (Base,i);
  Pan_Color (NEGRO,BLANCO);

  for ( k = 0 ; k < Bdt_TotalCampo(Base) ; k++ )
    {
    Bdt_CampoNumero (Base,k,Contenido);
    Pan_PonTexto (5+Fil,Col[k],Contenido);
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoMemo()
 * OBJETIVO: Demostrar las posibilidades del objeto Memo
 *------------------------------------------------------------------*/
void DemoMemo()
  {
  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Este objeto permite acceder a los registros de los");
  Pan_PonTexto (4,16,"ficheros memo (DBT) que tienen algunas bases de");
  Pan_PonTexto (5,16,"datos dBase.");
  Pan_PonTexto (7,16,"Es posible crear, abrir y modificar registros memo.");
  Usr_PulsaUnaTecla("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoIndice()
 * OBJETIVO: Demostrar las posibilidades del objeto Indice
 *------------------------------------------------------------------*/
void DemoIndice()
  {
  static cadena MenuIndice[] = { "Orden >alfabtico", "Orden >inverso", NIL };

  logico Sigue = SI;
  entero Opcion = 1;

  while ( Sigue )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (3,16,"Es posible crear, leer y modificar ficheros de ndice");
    Pan_PonTexto (4,16,"en formato Clipper (NTX).");

    Pan_PonTexto (6,16,"Podemos ver los registros en cualquier orden:");
    switch ( Opcion = Men_Vertical (8,20,9,40,MenuIndice,Opcion) )
      {
      case 0:  Sigue = NO;                         break;
      case 1:  MuestraRegistrosAlfa(); Opcion++;   break;
      case 2:  MuestraRegistrosInv();  Opcion = 1; break;
      }
    LimpiaZonaTrabajo();
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  MuestraRegistrosAlfa()
 * OBJETIVO: Mostrar registros de Demo.dbf en orden alfabtico
 *------------------------------------------------------------------*/
void MuestraRegistrosAlfa()
  {
  cadena   Contenido, NombreFich, NombreIndice, Clave;
  basedato Base;
  indice   Indice;
  entero   i, Numero;
  logico   Sigue = SI, HayOtro;
  menudo   Fil;

  LimpiaZonaTrabajo();
  Pan_Color (NEGRO,BLANCO);

  NombreFich = Fch_Nombre ("Demo","dbf");
  NombreIndice = Fch_Nombre ("Demo","ntx");

  if ( Base = Bdt_Abre (NombreFich, BDT_LECTURA) )
    {
    Contenido = Cad_Crea (Bdt_LongitudRegistro(Base));
    if ( Indice = Ind_Abre (NombreIndice, IND_LECTURA) )
      {
      Clave = Cad_Crea (Ind_LongitudClave(Indice));
      MarcoRegistro();

      for ( i = 0 , Fil = 0 , HayOtro = Ind_Primero (Indice,&Numero,Clave) ;
            i < Bdt_TotalRegistro(Base) && Sigue && HayOtro ;
            i++ , Fil++, HayOtro = Ind_Siguiente (Indice,&Numero,Clave) )
        {
        EscribeRegistro (Base,Numero,Contenido,Fil);
        if ( Fil == 15 )
          {
          Sigue = Usr_Consulta ("Hay ms registros. Quieres verlos?");
          Fil = -1;
          Pan_Borra (NEGRO,5,16,20,76);
          }
        }
      Ind_Cierra (Indice);
      Cad_Destruye (Clave);
      }
    Bdt_Cierra (Base);
    Cad_Destruye (Contenido);
    }

  if ( Sigue ) { Usr_PulsaUnaTecla (""); }

  Cad_Destruye (NombreFich);
  Cad_Destruye (NombreIndice);
  }

/*--------------------------------------------------------------------
 * FUNCION:  MuestraRegistrosInv()
 * OBJETIVO: Mostrar registros de Demo.dbf en orden alfabtico inverso
 *------------------------------------------------------------------*/
void MuestraRegistrosInv()
  {
  cadena   Contenido, NombreFich, NombreIndice, Clave;
  basedato Base;
  indice   Indice;
  entero   i, Numero;
  logico   Sigue = SI, HayOtro;
  menudo   Fil;

  LimpiaZonaTrabajo();
  Pan_Color (NEGRO,BLANCO);

  NombreFich = Fch_Nombre ("Demo","dbf");
  NombreIndice = Fch_Nombre ("Demo","ntx");

  if ( Base = Bdt_Abre (NombreFich, BDT_LECTURA) )
    {
    Contenido = Cad_Crea (Bdt_LongitudRegistro(Base));
    if ( Indice = Ind_Abre (NombreIndice, IND_LECTURA) )
      {
      Clave = Cad_Crea (Ind_LongitudClave(Indice));
      MarcoRegistro();

      for ( i = 0 , Fil = 0 , HayOtro = Ind_Ultimo (Indice,&Numero,Clave) ;
            i < Bdt_TotalRegistro(Base) && Sigue && HayOtro ;
            i++ , Fil++, HayOtro = Ind_Anterior (Indice,&Numero,Clave) )
        {
        EscribeRegistro (Base,Numero,Contenido,Fil);
        if ( Fil == 15 )
          {
          Sigue = Usr_Consulta ("Hay ms registros. Quieres verlos?");
          Fil = -1;
          Pan_Borra (NEGRO,5,16,20,76);
          }
        }
      Ind_Cierra (Indice);
      Cad_Destruye (Clave);
      }
    Bdt_Cierra (Base);
    Cad_Destruye (Contenido);
    }

  if ( Sigue ) { Usr_PulsaUnaTecla (""); }

  Cad_Destruye (NombreFich);
  Cad_Destruye (NombreIndice);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoDiblane()
 * OBJETIVO: Demostrar las posibilidades del objeto Diblane
 *------------------------------------------------------------------*/
void DemoDiblane()
  {
  static cadena MenuDiblane[] = { "Manipulacin", "Edicin", NIL };
  logico Sigue = SI;
  entero Opcion = 1;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,16,"Diblane quiere decir \"DIbujo en BLAnco y NEgro\".");
  Pan_PonTexto (4,16,"Por medio de este objeto se pueden manipular y editar");
  Pan_PonTexto (5,16,"imgenes que slo tengan dos colores.");

  if ( Pan_Modo() == PAN_TEXTO )
    {
    Pan_PonTexto (11,18,"Ahora ests en modo Texto, de modo que no puedes");
    Pan_PonTexto (12,18,"visualizar los dibujos. Cambia de modo con la opcin");
    Pan_PonTexto (13,18,"\"Pantalla\" del men principal y vuelve aqu.");
    Usr_PulsaUnaTecla ("");
    }

  else  /* Pan_Modo() == PAN_GRAFICO */
    {
    while ( Sigue )
      {
      Opcion = Men_Horizontal (7,28,55,MenuDiblane,Opcion);
      switch ( Opcion )
        {
        case 0:  Sigue = NO;                    break;
        case 1:  DemoDbnManipula(); Opcion = 2; break;
        case 2:  DemoDbnEdita();    Opcion = 1; break;
        }
      Pan_Borra (NEGRO,6,16,20,78);
      }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoDbnManipula()
 * OBJETIVO: Demostrar las posibilidades de manipulacin del objeto Diblane
 *------------------------------------------------------------------*/
void DemoDbnManipula()
  {
  static cadena MenuDbnManipula[] = { ">Figura", "Fon>do", ">Invertir",
                                      ">Horizontal", ">Vertical", NIL };
  zona     Zona;
  diblane  Dibujo;
  tiff     Tiff;
  cadena   NombreTiff;
  logico   Sigue = SI;
  entero   Opcion = 1;
  octeto   Fondo=NEGRO, Figura=BLANCO;
  contador PosX, PosY;

  Zona = Zon_Crea (9,14,20,78);
  NombreTiff = Fch_Nombre ("Demo","tif");
  if ( Tiff = Tif_Abre (NombreTiff) )
    {
    Dibujo = Dbn_Crea (Tif_Ancho(Tiff), Tif_Alto(Tiff));
    Tif_LeeImagenBN (Tiff, Dbn_Dato(Dibujo));
    Tif_Cierra (Tiff);

    PosX = Max (0, (Zon_AnchoEnOxel(Zona)-Dbn_AnchoEnOxel(Dibujo))/2);
    PosY = Max (0, (Zon_AltoFisico(Zona)-Dbn_Alto(Dibujo))/2);

    while ( Sigue )
      {
      Dbn_Coloca (Dibujo, Zona, PosX, PosY, Fondo, Figura);
      Opcion = Men_Horizontal (7,18,76,MenuDbnManipula,Opcion);
      Usr_Informa ("Estoy calculando");
      switch ( Opcion )
        {
        case 0:  Sigue = NO;                    break;
        case 1:  switch ( Figura )
                   {
                   case BLANCO: Figura = VERDE;  break;
                   case VERDE:  Figura = ROJO;   break;
                   case ROJO:   Figura = NEGRO;  break;
                   case NEGRO:  Figura = BLANCO; break;
                   }
                 break;
        case 2:  switch ( Fondo )
                   {
                   case BLANCO: Fondo = VERDE;  break;
                   case VERDE:  Fondo = ROJO;   break;
                   case ROJO:   Fondo = NEGRO;  break;
                   case NEGRO:  Fondo = BLANCO; break;
                   }
                 break;
        case 3:  Dbn_Invierte(Dibujo);          break;
        case 4:  Dbn_ReflejaHorizontal(Dibujo); break;
        case 5:  Dbn_ReflejaVertical(Dibujo);   break;
        }
      } /* Fin while Sigue */
    Dbn_Destruye (Dibujo);
    } /* Fin if Tiff */
  Cad_Destruye (NombreTiff);
  Zon_Destruye (Zona);
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoDbnEdita()
 * OBJETIVO: Demostrar las posibilidades de edicin del objeto Diblane
 *------------------------------------------------------------------*/
void DemoDbnEdita()
  {
  zona     ZonaEdicion, ZonaMuestra;
  diblane  Dibujo;
  contador PosX, PosY;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (9,16,"Edita un dibujo ->");

  ZonaEdicion = Zon_Crea (9,40,19,74);
  ZonaMuestra = Zon_Crea (13,16,18,30);
  if ( Dibujo = Dbn_Crea ((entero)18,(entero)10) )
    {
    Dbn_Invierte (Dibujo);
    Dbn_Edita (Dibujo, ZonaEdicion);
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (11,16,"As queda:");
    PosX = Max (0, (Zon_AnchoEnOxel(ZonaMuestra)-Dbn_AnchoEnOxel(Dibujo))/2);
    PosY = Max (0, (Zon_AltoFisico(ZonaMuestra)-Dbn_Alto(Dibujo))/2);
    Dbn_Coloca (Dibujo, ZonaMuestra, PosX, PosY, NEGRO, BLANCO);
    Dbn_Destruye (Dibujo);
    }
  Zon_Destruye (ZonaEdicion);
  Zon_Destruye (ZonaMuestra);
  Usr_PulsaUnaTecla("");
  }

/*--------------------------------------------------------------------
 * FUNCION:  DemoTiff()
 * OBJETIVO: Demostrar las posibilidades del objeto Tiff
 *------------------------------------------------------------------*/
void DemoTiff()
  {
  tiff   Tiff;
  cadena NombreFich, Propuesta;

  Pan_Color (NEGRO,BLANCO);
  Pan_PonTexto (3,18,"Por medio de este objeto se pueden crear y leer");
  Pan_PonTexto (4,18,"ficheros TIFF. Deben ser en blanco y negro sin");
  Pan_PonTexto (5,18,"comprimir.");
  Pan_PonTexto (6,18,"Se pueden manipular completos o por bandas.");

  Pan_PonTexto (8,18,"Datos del fichero:");
  Propuesta = Fch_Nombre ("Demo","tif");
  NombreFich = Usr_Texto (Propuesta,30,8,37,BLANCO,NEGRO);

  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( Tiff = Tif_Abre (NombreFich) )
      {
      Pan_Color (NEGRO,VERDE);
      Pan_PonTexto (10,18,"Anchura: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_Ancho(Tiff),1);
      Pan_Texto (" pixels");

      Pan_Tinta (VERDE);
      Pan_PonTexto (11,18,"Altura: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_Alto(Tiff),1);
      Pan_Texto (" pixels");

      Pan_Tinta (VERDE);
      Pan_PonTexto (12,18,"Tamao: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_Tamano(Tiff),1);
      Pan_Texto (" octetos");

      Pan_Tinta (VERDE);
      Pan_PonTexto (13,18,"Mtodo de compresin: ");
      Pan_Tinta (BLANCO);
      switch ( Tif_Compresion(Tiff) )
        {
        case TIF_SIN_COMPRESION: Pan_Texto ("(Ninguno)");     break;
        case TIF_CCITT1D:        Pan_Texto ("CCITT 1D");      break;
        case TIF_FAX3:           Pan_Texto ("FAX 3");         break;
        case TIF_FAX4:           Pan_Texto ("FAX 4");         break;
        case TIF_LZW:            Pan_Texto ("LZW");           break;
        case TIF_JPEG:           Pan_Texto ("JPEG");          break;
        case TIF_PACKBITS:       Pan_Texto ("PackBits");      break;
        default:                 Pan_Texto ("(Desconocido)"); break;
        }

      Pan_Tinta (VERDE);
      Pan_PonTexto (14,18,"Bits por pixel: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_BitsPorPixel(Tiff),1);

      Pan_Tinta (VERDE);
      Pan_PonTexto (15,18,"Interpretacin fotomtrica: ");
      Pan_Tinta (BLANCO);
      switch ( Tif_Interpretacion(Tiff) )
        {
        case TIF_BLANCO_CERO: Pan_Texto ("Cero es blanco");    break;
        case TIF_NEGRO_CERO:  Pan_Texto ("Cero es negro");     break;
        case TIF_RGB:         Pan_Texto ("Color real");        break;
        case TIF_PALETA:      Pan_Texto ("Paleta de colores"); break;
        case TIF_MASCARA:     Pan_Texto ("Mscara");           break;
        default:              Pan_Texto ("(Desconocida)");     break;
        }

      Pan_Tinta (VERDE);
      Pan_PonTexto (16,18,"Filas por banda: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_FilasPorBanda(Tiff),1);

      Pan_Tinta (VERDE);
      Pan_PonTexto (17,18,"Muestras por pixel: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_MuestrasPorPixel(Tiff),1);

      Pan_Tinta (VERDE);
      Pan_PonTexto (18,18,"Nmero de bandas: ");
      Pan_Tinta (BLANCO);
      Pan_Entero (Tif_TotalBanda(Tiff),1);

      Tif_Cierra (Tiff);
      }
    Usr_PulsaUnaTecla ("");
    }

  Cad_Destruye (Propuesta);
  Cad_Destruye (NombreFich);
  }
