/*--------------------------------------------------------------------
 * FICHERO:  ConfWSET_c
 * OBJETIVO: Configurar la extensin del SB WSET
 * ENTRADAS: Se puede leer un fichero e introducir datos por teclado
 * SALIDAS:  Se puede generar un fichero
 * AUTOR:    Pedro Reina
 * FECHA:    M.28.7.1998
 *------------------------------------------------------------------*/

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

#include <Olimpo.h>          /*  Versin 2.0  */

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

#define TAMANO 272    /* Tamao del fichero WSET_ext */

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

#define LimpiaZonaTrabajo()  Pan_Borra(NEGRO,1,0,21,79)
#define LimpiaZonaPequena()  Pan_Borra(NEGRO,15,9,19,70)

/*--------------------------------------------------------------------
 * MACRO:    Palabra()
 * OBJETIVO: Devolver el valor de una palabra (2 octetos) en Memoria
 * ENTRADAS: La direccin
 * SALIDAS:  Un entero entre 0 y 2^16-1
 *------------------------------------------------------------------*/
#define Palabra(d)  (256*Memoria[d-1]+Memoria[d])

/*--------------------------------------------------------------------
 * MACRO:    PonPalabra()
 * OBJETIVO: Escribir un valor de palabra (2 octetos) en Memoria
 * ENTRADAS: El valor y la direccin
 * SALIDAS:  La zona de memoria queda modificada
 *------------------------------------------------------------------*/
#define PonPalabra(v,d)  (Memoria[d-1]=v/256,Memoria[d]=v%256)

/*--------------------------------------------------------------------
 * MACRO:    Octeto()
 * OBJETIVO: Devolver el valor de un octeto en Memoria
 * ENTRADAS: La direccin
 * SALIDAS:  Un entero entre 0 y 2^8-1
 *------------------------------------------------------------------*/
#define Octeto(d)  (Memoria[d-1])

/*--------------------------------------------------------------------
 * MACRO:    PonOcteto()
 * OBJETIVO: Escribir el valor de un octeto en Memoria
 * ENTRADAS: El valor y la direccin
 * SALIDAS:  La zona de memoria queda modificada
 *------------------------------------------------------------------*/
#define PonOcteto(v,d)  (Memoria[d-1]=v)

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

int Ancho[3];
int Alto[3];
int PosX[3];
int PosY[3];
int Papel[3];
int Tinta[3];
int AnchoBorde[3];
int ColorBorde[3];

caracter Nombre[37];
octeto   Memoria[TAMANO];

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

void Lee();
void Configura();
void Escribe();
void Explica();
void EscribeMarco();
void EscribeDatos();
void EscribeDato();
void EditaDato();
void TablaEntero();

/*--------------------------------------------------------------------
 * Programa principal
 *------------------------------------------------------------------*/
main()
  {
  enum { SALIDA_ESC, SALIDA, EXPLICA, SONIDO, LEE, CONFIGURA, ESCRIBE };
  static cadena Principal[] = { ">Salida", "E>xplica", "So>nido",
                                ">Lee", ">Configura", ">Escribe", NIL};
  entero Opcion = LEE;
  logico Sigue = SI, Leido = NO;

  Pan_Define (PAN_TEXTO);

  Prg_Presenta ( "Configurador de WSET", "1.1",
                 "Pedro Reina", "Julio 1998" );

  Cad_Copia (Nombre, "WSET_ext");

  while ( Sigue )
    {
    Cdr_Caja (CDR_SIMPLE,1,0,3,79,NEGRO,BLANCO);
    Opcion = Men_Horizontal (2,1,78,Principal,Opcion);
    switch ( Opcion )
      {
      case SALIDA_ESC:
      case SALIDA:
        if ( Usr_Consulta ("Quieres salir del programa?") )
          { Sigue = NO; }
        Opcion = SALIDA;
        break;

      case SONIDO:
        if ( Usr_Consulta ("Quieres tener sonido en el programa?") )
          { Son_Enciende(); }
        else
          { Son_Apaga(); }
        break;

      case EXPLICA:
        Explica();
        break;

      case LEE:
        Lee();   
        Leido = Tec_Ultima() != TEC_ESC;
        break;
        
      case CONFIGURA:    
        if ( !Leido )  { Usr_Avisa ("Todava no has leido"); }
        else           { Configura(); }
        break;
        
      case ESCRIBE:      
        if ( !Leido )  { Usr_Avisa ("Todava no has leido"); }
        else           { Escribe(); }
        break;
      }
    LimpiaZonaTrabajo();
    }

  Pan_Cierra();
  return ( 0 );
  }

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

/*--------------------------------------------------------------------
 * FUNCION: Explica()
 *------------------------------------------------------------------*/
void Explica()
  {
  contador i = 6, Col = 7;

  Pan_Color ( NEGRO, BLANCO );

  Pan_PonTexto (i++,Col,
  "Este programa permite configurar la extensin del SuperBASIC");
  Pan_PonTexto (i++,Col,
  "llamada WSET, que se encarga de redefinir las ventanas 0, 1 y 2");
  i++;
  Pan_PonTexto (i++,Col,
  "Primero se usa la opcin Lee para cargar en memoria el contenido");
  Pan_PonTexto (i++,Col,
  "del fichero donde est el cdigo que define WSET");
  i++;
  Pan_PonTexto (i++,Col,
  "A continuacin se usa la opcin Configura para cambiar a voluntad");
  Pan_PonTexto (i++,Col,
  "los parmetros de cada una de las ventanas. El programa no");
  Pan_PonTexto (i++,Col,
  "comprueba que las definiciones tengan sentido");
  i++;
  Pan_PonTexto (i++,Col,
  "Por ltimo con la opcin Escribe se almacena en disco un fichero");
  Pan_PonTexto (i++,Col,
  "con la nueva configuracin");
  i++;
  Pan_PonTexto (i++,Col,
  "Con la opcin Salida concluye el programa");

  Usr_PulsaUnaTecla ("");
  }

/*--------------------------------------------------------------------
 * FUNCION: Lee()
 *------------------------------------------------------------------*/
void Lee()
  {
  fichero F;
  cadena  Aux;

  Cdr_Caja (CDR_SIMPLE,7,15,16,65,NEGRO,VERDE);
  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (10,20,"Nombre completo del fichero:");
  Aux = Usr_Texto (Nombre,36,13,21,NEGRO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( F = Fch_AbreLeer (Aux) )
      {
      Fch_LeeOcteto (F,Memoria,TAMANO);
      Fch_Cierra (F);

      Ancho[0] = Palabra (249), Alto[0] = Palabra (251);
      PosX[0]  = Palabra (253), PosY[0] = Palabra (255);
      Papel[0] = Octeto (58)  , Tinta[0] = Octeto (86) ;
      ColorBorde[0] = Octeto (70), AnchoBorde[0] = Palabra (73);

      Ancho[1] = Palabra (257), Alto[1] = Palabra (259);
      PosX[1]  = Palabra (261), PosY[1] = Palabra (263);
      Papel[1] = Octeto (142)  , Tinta[1] = Octeto (150) ;
      ColorBorde[1] = Octeto (126), AnchoBorde[1] = Palabra (129);

      Ancho[2] = Palabra (265), Alto[2] = Palabra (267);
      PosX[2]  = Palabra (269), PosY[2] = Palabra (271);
      Papel[2] = Octeto (206)  , Tinta[2] = Octeto (214) ;
      ColorBorde[2] = Octeto (190), AnchoBorde[2] = Palabra (193);

      Usr_PulsaUnaTecla ("Fichero ledo");
      }
    }
  Cad_Destruye (Aux);
  }

/*--------------------------------------------------------------------
 * FUNCION:  Configura()
 * OBJETIVO: Permitir al usuario variar los datos que se presentan
 *------------------------------------------------------------------*/
void Configura()
  {
  static contador Fil[] = {  5,  5,  5,  5,  7,  7,  7,  7,
                            11, 11, 11, 11, 13, 13, 13, 13,
                            17, 17, 17, 17, 19, 19, 19, 19  };

  static contador Col[] = { 27, 42, 57, 73, 27, 42, 57, 73,
                            27, 42, 57, 73, 27, 42, 57, 73,
                            27, 42, 57, 73, 27, 42, 57, 73  };

  static contador Esp[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3  };

  static contador Minimo[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  };

  static contador Maximo[] = { 512, 511, 128, 40, 256, 255, 128, 128,
                               512, 511, 128, 40, 256, 255, 128, 128,
                               512, 511, 128, 40, 256, 255, 128, 128  };
  contador i, j;
  int *Numero[24];

  for ( i=0 , j=0 ; i<3 ; i++ )
    {
    Numero[j++] = &Ancho[i];
    Numero[j++] = &PosX[i];
    Numero[j++] = &Papel[i];
    Numero[j++] = &AnchoBorde[i];
    Numero[j++] = &Alto[i];
    Numero[j++] = &PosY[i];
    Numero[j++] = &Tinta[i];
    Numero[j++] = &ColorBorde[i];
    }

  EscribeMarco();
  TablaEntero (Numero, Fil, Col, Esp, Minimo, Maximo, 24, 4,
               NEGRO, VERDE, NEGRO, BLANCO, BLANCO, NEGRO);

  for ( i=0 , j=0 ; i<3 ; i++ )
    {
    Ancho[i]      = *Numero[j++];
    PosX[i]       = *Numero[j++];
    Papel[i]      = *Numero[j++];
    AnchoBorde[i] = *Numero[j++];
    Alto[i]       = *Numero[j++];
    PosY[i]       = *Numero[j++];
    Tinta[i]      = *Numero[j++];
    ColorBorde[i] = *Numero[j++];
    }

  PonPalabra (Ancho[0],249), PonPalabra (Alto[0],251);
  PonPalabra (PosX[0],253), PonPalabra (PosY[0],255);
  PonOcteto (Papel[0],58) , PonOcteto (Papel[0],94) ;
  PonOcteto (Tinta[0],86) ;
  PonOcteto (ColorBorde[0],70), PonPalabra (AnchoBorde[0],73);

  PonPalabra (Ancho[1],257), PonPalabra (Alto[1],259);
  PonPalabra (PosX[1],261), PonPalabra (PosY[1],263);
  PonOcteto (Papel[1],142) , PonOcteto (Papel[1],158);
  PonOcteto (Tinta[1],150) ;
  PonOcteto (ColorBorde[1],126), PonPalabra (AnchoBorde[1],129);

  PonPalabra (Ancho[2],265), PonPalabra (Alto[2],267);
  PonPalabra (PosX[2],269), PonPalabra (PosY[2],271);
  PonOcteto (Papel[2],206),  PonOcteto (Papel[2],222);
  PonOcteto (Tinta[2],214) ;
  PonOcteto (ColorBorde[2],190), PonPalabra (AnchoBorde[2],193);
  }

/*--------------------------------------------------------------------
 * FUNCION:  Escribe()
 *------------------------------------------------------------------*/
void Escribe()
  {
  fichero F;
  cadena  Aux;

  Cdr_Caja (CDR_SIMPLE,7,15,16,65,NEGRO,VERDE);
  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (10,20,"Nombre completo del fichero:");
  Aux = Usr_Texto (Nombre,36,13,21,NEGRO,BLANCO);
  if ( Tec_Ultima() != TEC_ESC )
    {
    if ( F = Fch_AbreGrabar (Aux) )
      {
      Fch_EscribeOcteto (F,Memoria,TAMANO);
      Fch_Cierra (F);
      Usr_PulsaUnaTecla ("Fichero escrito");
      }
    }
  Cad_Destruye (Aux);
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeMarco()
 *------------------------------------------------------------------*/
void EscribeMarco()
  {
  contador i;
  LimpiaZonaTrabajo();
  Cdr_Dibuja (CDR_DOBLE,CDR_SIMPLE,3,5,5,14,2,2,NEGRO,ROJO);
  for ( i=0 ; i<3 ; i++ )
    {
    Pan_Color (NEGRO,BLANCO);
    Pan_PonTexto (5+6*i,5,"Ventana ");
    Pan_Entero (i,1);
    Pan_Tinta (VERDE);
    Pan_PonTexto (3+6*i,19,"Dimensiones");
    Pan_PonTexto (5+6*i,19,"Ancho");
    Pan_PonTexto (7+6*i,19,"Alto");
    Pan_PonTexto (3+6*i,36,"Posicin");
    Pan_PonTexto (5+6*i,34,"X");
    Pan_PonTexto (7+6*i,34,"Y");
    Pan_PonTexto (3+6*i,51,"Colores");
    Pan_PonTexto (5+6*i,49,"Papel");
    Pan_PonTexto (7+6*i,49,"Tinta");
    Pan_PonTexto (3+6*i,67,"Borde");
    Pan_PonTexto (5+6*i,64,"Ancho");
    Pan_PonTexto (7+6*i,64,"Color");
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  TablaEntero()
 * OBJETIVO: Editar una agrupacin rectangular de enteros
 * ENTRADAS: Un vector de enteros, los parmetros para editar cada uno
 *           y los colores para cada posibilidad
 * SALIDAS:  El vector de enteros puede quedar modificado
 *------------------------------------------------------------------*/
void TablaEntero (Num, Fil, Col, Ancho, Mn, Mx, Total, Avance,
                  PapelNormal, TintaNormal, PapelResaltado, TintaResaltado,
                  PapelEdicion, TintaEdicion)
int     *Num[];
contador Fil[], Col[], Ancho[], Mn[], Mx[], Total, Avance,
         PapelNormal, TintaNormal, PapelResaltado, TintaResaltado,
         PapelEdicion, TintaEdicion;
  {
  static tecla Lista[] = { TEC_IZQUIERDA, TEC_DERECHA, TEC_ARRIBA, TEC_ABAJO,
                           TEC_ENTER, TEC_ESC, TEC_ESPACIO, NIL };
  contador i;
  logico   Sigue;
  tecla    Tecla;
  int     *Aux;

  Aux = (int *) Mem_Crea ( Total * sizeof (int) );

  for ( i=0 ; i<Total ; i++ )
    { Aux[i] = *Num[i]; }

  Pan_Color (PapelNormal, TintaNormal);
  for ( i=0 ; i<Total ; i++ )
    { Pan_PonEntero (Fil[i],Col[i],Aux[i],Ancho[i]); }

  Usr_Indica (
      "Utiliza IZQUIERDA, DERECHA, ARRIBA y ABAJO para elegir el dato",
      "Pulsa ENTER editar, ESC para anular y ESPACIO para terminar");

  i=0, Sigue = SI;
  while ( Sigue )
    {
    Pan_Color (PapelResaltado, TintaResaltado);
    Pan_Resalta (SI);
    Pan_PonEntero (Fil[i],Col[i],Aux[i],Ancho[i]);
    Pan_Resalta (NO);

    Tecla = Tec_Validada (Lista);
    if ( Tecla == TEC_IZQUIERDA || Tecla == TEC_DERECHA ||
         Tecla == TEC_ARRIBA    || Tecla == TEC_ABAJO    )
       {
       Pan_Color (PapelNormal, TintaNormal);
       Pan_PonEntero (Fil[i],Col[i],Aux[i],Ancho[i]);
       }
    switch ( Tecla )
      {
      case TEC_IZQUIERDA:
               i = (i%Avance==0) ? i+Avance-1 : i-1;                    break;
      case TEC_DERECHA:
               i = (i%Avance==Avance-1) ? i-Avance+1 : i+1;             break;
      case TEC_ARRIBA:
               i = (i<Avance) ? (Total/Avance-1)*Avance+i : i-Avance;   break;
      case TEC_ABAJO:
               i = (i>=Total-Avance) ? i%Avance : i+Avance;             break;
      case TEC_ENTER:
               Aux[i] = Usr_Entero (Aux[i], Ancho[i], Mn[i], Mx[i],
                            Fil[i], Col[i], PapelEdicion, TintaEdicion);
               Pan_Color (PapelNormal, TintaNormal);
               Pan_PonEntero (Fil[i],Col[i],Aux[i],Ancho[i]);
               i = (i==Total-1) ? 0 : i+1;
               Usr_Indica (
               "Utiliza IZQUIERDA, DERECHA, ARRIBA y ABAJO para elegir el dato",
               "Pulsa ENTER editar, ESC para anular y ESPACIO para terminar");
               break;
      case TEC_ESC:          Sigue = NO;        break;
      case TEC_ESPACIO:      Sigue = NO;
                             for ( i=0 ; i<Total ; i++ )
                               { *Num[i] = Aux[i]; }
                             break;
      }
    } /* Fin while (Sigue) */

  Mem_Destruye ((memoria)Aux);
  }
