/*--------------------------------------------------------------------
 * FICHERO:  Mondrian.c
 * OBJETIVO: Crear cuadros para imprimir o guardar en ficheros
 * AUTOR:    Pedro Reina
 * FECHA:    S.7.3.1998
 *------------------------------------------------------------------*/

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

#include <Olimpo.h>         /*  Versin 2.0  */
#include <string.h>         /*  strtok()     */

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

contador PideNumero();
contador PideEstilo();
cadena   PideDestino();
void     Imprime();
void     LeeConfig();

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

#define MAX_ORDEN 40
#define LONG_DEST 12

#ifdef OLIMPO_QL
#define IMPRESORA  "ser1"
#endif

#ifdef OLIMPO_PC
#define IMPRESORA  "PRN"
#endif

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

#define LimpiaZonaTrabajo()  Pan_Borra(NEGRO,9,46,18,75)

/*--------------------------------------------------------------------
 * Programa principal
 *------------------------------------------------------------------*/
void main (Narg, Arg)
int   Narg;
char *Arg[];
  {
  enum { SALIDA_ESC, SUPERIOR, IZQUIERDO, NUMLINEA, ALTURA, NUMCOLUMNA,
         ANCHURA, FUERA, DENTRO, DESTINO, IMPRIME };

  static cadena Principal[] = {"Margen >superior", "Margen i>zquierdo",
         "Nmero de >lneas", ">Altura de lnea", "Nmero de >columnas",
         "Anc>hura de columna", "Lneas e>xternas", "Lneas in>ternas",
         ">Destino", ">Imprime ahora", NIL };

  static cadena Explicacion[] = {
    "Este programa permite crear cuadros usando los caracteres semigrficos",
    "que se encuentran en casi todas las impresoras. Las lneas internas y ",
    "externas del cuadro pueden ser dobles o sencillas. El cuadro creado se",
    "puede enviar a la impresora o almacenar en un fichero de texto.       ",
    NIL };

  entero   Opcion;
  contador i;
  logico   Sigue;
  octeto   Preambulo[MAX_ORDEN+1];
  octeto   Postambulo[MAX_ORDEN+1];
  cadena   Nombre;

  contador Superior   = 0;
  contador Izquierdo  = 0;
  contador NumLinea   = 4;
  contador Altura     = 1;
  contador NumColumna = 5;
  contador Anchura    = 5;
  contador Fuera      = CDR_DOBLE;
  contador Dentro     = CDR_SIMPLE;
  cadena   Destino;

  Pan_Define (PAN_TEXTO);

  Prg_Presenta ( "Mondrian", "1.1", "Pedro Reina", "Marzo 1998" );

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

  Cdr_Caja (CDR_DOBLE,8,3,19,40,NEGRO,VERDE);
  Cdr_Caja (CDR_SIMPLE,8,45,19,76,NEGRO,VERDE);

  Preambulo[0] = NIL;
  Postambulo[0] = NIL;

  Destino = Cad_Crea(LONG_DEST);
  Cad_Copia (Destino,IMPRESORA);

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

  if ( Narg == 1 )
    {
    Nombre = Fch_Nombre ( "Mondrian","cnf");
    if ( Fch_Existe (Nombre) )
      {
      LeeConfig (Nombre, Preambulo, Postambulo, Destino,
                 &Superior, &Izquierdo, &NumLinea, &Altura,
                 &NumColumna, &Anchura, &Fuera, &Dentro);
      }
    }
  else
    {
    Nombre = Cad_Duplica ( Arg[1] );
    LeeConfig (Nombre, Preambulo, Postambulo, Destino,
               &Superior, &Izquierdo, &NumLinea, &Altura,
               &NumColumna, &Anchura, &Fuera, &Dentro);
    }
  Cad_Destruye (Nombre);

  Opcion = SUPERIOR;
  Sigue = SI;
  while ( Sigue )
    {
    Pan_Color (NEGRO,VERDE);
    Pan_PonEntero ( 9,28,Superior,3);
    Pan_PonEntero (10,28,Izquierdo,3);
    Pan_PonEntero (11,28,NumLinea,3);
    Pan_PonEntero (12,28,Altura,3);
    Pan_PonEntero (13,28,NumColumna,3);
    Pan_PonEntero (14,28,Anchura,3);
    Pan_PonTexto  (15,28,Fuera  == CDR_DOBLE ? "Doble " : "Simple");
    Pan_PonTexto  (16,28,Dentro == CDR_DOBLE ? "Doble " : "Simple");
    Pan_PonTexto  (17,28,"            ");
    Pan_PonTexto  (17,28,Destino);

    Pan_Color (NEGRO,ROJO);
    Pan_PonTexto (10,50,"Ejemplo de las lneas");
    Cdr_Dibuja (Fuera,Dentro,3,1,5,3,12,50,NEGRO,ROJO);

    Opcion = Men_Vertical (9,6,18,25,Principal,Opcion);
    LimpiaZonaTrabajo();
    switch ( Opcion )
      {
      case SALIDA_ESC:
           Sigue = ! Usr_Consulta ("Quieres terminar el programa?");
           break;
      case SUPERIOR:   Superior   = PideNumero (Superior,0,40);    break;
      case IZQUIERDO:  Izquierdo  = PideNumero (Izquierdo,0,80);   break;
      case NUMLINEA:   NumLinea   = PideNumero (NumLinea,1,200);   break;
      case ALTURA:     Altura     = PideNumero (Altura,1,80);      break;
      case NUMCOLUMNA: NumColumna = PideNumero (NumColumna,1,200); break;
      case ANCHURA:    Anchura    = PideNumero (Anchura,1,80);     break;
      case FUERA:      Fuera      = PideEstilo (Fuera);            break;
      case DENTRO:     Dentro     = PideEstilo (Dentro);           break;
      case DESTINO:    PideDestino (Destino);                      break;
      case IMPRIME:    Imprime (Destino, Superior, Izquierdo,
                                NumLinea, Altura,
                                NumColumna, Anchura,
                                Fuera, Dentro,
                                Preambulo, Postambulo);
                       break;
      }
    LimpiaZonaTrabajo();
    Opcion = Min (Opcion+1,IMPRIME);
    }

  Cad_Destruye (Destino);

  Pan_Cierra();
  }

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

/*--------------------------------------------------------------------
 * FUNCION:  PideNumero()
 * OBJETIVO: Pedir un dato numrico
 *------------------------------------------------------------------*/
contador PideNumero (Original,Menor,Mayor)
contador Original, Menor, Mayor;
  {
  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (11,50,"Define el nuevo valor");

  return ( Usr_Entero (Original, 3, Menor, Mayor, 15, 59, ROJO, NEGRO) );
  }

/*--------------------------------------------------------------------
 * FUNCION:  PideEstilo()
 * OBJETIVO: Pedir un estilo de lnea
 *------------------------------------------------------------------*/
contador PideEstilo (Original)
contador Original;
  {
  static cadena Tipo[] = { ">Simple", ">Doble", NIL };
  entero   Opcion;
  contador Respuesta;

  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (11,51,"Elige el nuevo tipo");

  Opcion = Original == CDR_SIMPLE ? 2 : 1;

  Opcion = Men_Horizontal (15,52,68,Tipo,Opcion);

  switch ( Opcion )
    {
    case 0 : Respuesta = Original;   break;
    case 1 : Respuesta = CDR_SIMPLE; break;
    case 2 : Respuesta = CDR_DOBLE;  break;
    }

  return ( Respuesta );
  }

/*--------------------------------------------------------------------
 * FUNCION:  PideDestino()
 * OBJETIVO: Pedir el destino para los cuadros
 *------------------------------------------------------------------*/
cadena PideDestino (Original)
cadena Original;
  {
  cadena Aux;

  Pan_Color (NEGRO,VERDE);
  Pan_PonTexto (11,50,"Elige el nuevo destino");

  Aux = Usr_Texto (Original,LONG_DEST,15,53,ROJO,NEGRO);
  Cad_Copia (Original,Aux);

  Cad_Destruye (Aux);
  return ( Original );
  }

/*--------------------------------------------------------------------
 * FUNCION:  Imprime()
 * OBJETIVO: Imprir el cuadro
 *------------------------------------------------------------------*/
void Imprime (Destino, Superior, Izquierdo, NumLinea, Altura,
              NumColumna, Anchura, Fuera, Dentro, Preambulo, Postambulo)
cadena   Destino;
contador Superior, Izquierdo, NumLinea, Altura,
         NumColumna, Anchura, Fuera, Dentro;
octeto   Preambulo[], Postambulo[];
  {
  fichero  Fichero;
  lista    Cuadro, L;
  contador i;
  cadena   Blanco, Linea;

  Blanco = Cad_Crea (Izquierdo);
  for ( i=0 ; i<Izquierdo ; i++ )
    { Blanco[i] = ' '; }
  Blanco[i] = NULO;

  if ( Cuadro = Cdr_Construye (Fuera,Dentro,NumLinea,Altura,
                NumColumna,Anchura) )
    {
    Linea = Cad_Crea (Izquierdo+Cad_Longitud(Lis_Contenido(Cuadro)));

    if ( Fichero = Fch_AbreGrabar (Destino, FCH_TEXTO) )
      {
      Usr_Informa ("Imprimiendo cuadro");

      for ( i=0 ; Preambulo[i] ; i++ )
        { Fch_EscribeOcteto (Fichero, Preambulo+i, 1); }

      for ( i=0 ; i<Superior ; i++ )
        { Fch_EscribeLinea (Fichero,""); }

      for ( L=Cuadro ; L ; L=Lis_Siguiente(L) )
        {
        Cad_Copia (Linea,Blanco);
        strcat (Linea,Lis_Contenido(L));
        Fch_EscribeLinea (Fichero,Linea);
        }

      for ( i=0 ; Postambulo[i] ; i++ )
        { Fch_EscribeOcteto (Fichero, Postambulo+i, 1); }

      Fch_Cierra (Fichero);
      }

    Cad_Destruye (Linea);
    Lis_Destruye (Cuadro);
    }

  else { Usr_Avisa ("No hay memoria suficiente"); }

  Cad_Destruye (Blanco);
  }

/*--------------------------------------------------------------------
 * FUNCION:  LeeConfig()
 * OBJETIVO: Leer el fichero de comfiguracion
 *------------------------------------------------------------------*/
void LeeConfig (Nombre, Preambulo, Postambulo, Destino,
               Superior, Izquierdo, NumLinea, Altura,
               NumColumna, Anchura, Fuera, Dentro)
cadena   Nombre;
octeto   Preambulo[], Postambulo[];
cadena   Destino;
contador *Superior, *Izquierdo, *NumLinea, *Altura,
         *NumColumna, *Anchura, *Fuera, *Dentro;
  {
  config    Config;
  cadena    Linea;
  contador  Tipo, i;
  char     *Etiqueta, *Aux;

  Usr_Informa ("Leyendo configuracin");

  if ( Config = Cnf_Abre (Nombre) )
    {
    while ( Linea = Cnf_Lee (Config) )
      {
      if ( Etiqueta = strtok (Linea, " ") )
        {

        if ( Cad_Igual (Etiqueta,"Sonido") )
          {
          if ( Aux = strtok (NULL, " ") )
            {
            if ( toupper(Aux[0]) == 'S' ) { Son_Enciende(); }
            else                          { Son_Apaga(); }
            }
          }

        else if ( Cad_Igual (Etiqueta,"Superior") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *Superior = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"Izquierdo") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *Izquierdo = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"NumLnea") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *NumLinea = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"Altura") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *Altura = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"NumColumna") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *NumColumna = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"Anchura") )
          {
          if ( Aux = strtok (NULL, " ") )
            { *Anchura = atoi(Aux); }
          }

        else if ( Cad_Igual (Etiqueta,"Dentro") )
          {
          if ( Aux = strtok (NULL, " ") )
            {
            Tipo = atoi(Aux);
            if ( Tipo == 1 ) { *Dentro = CDR_SIMPLE; }
            if ( Tipo == 2 ) { *Dentro = CDR_DOBLE; }
            }
          }

        else if ( Cad_Igual (Etiqueta,"Fuera") )
          {
          if ( Aux = strtok (NULL, " ") )
            {
            Tipo = atoi(Aux);
            if ( Tipo == 1 ) { *Fuera = CDR_SIMPLE; }
            if ( Tipo == 2 ) { *Fuera = CDR_DOBLE; }
            }
          }

        else if ( Cad_Igual (Etiqueta,"Destino") )
          {
          if ( Aux = strtok (NULL, " ") )
            {
            if ( Cad_Longitud(Aux) > LONG_DEST )
              { Aux[LONG_DEST] = NULO; }
            Cad_Copia (Destino, Aux);
            }
          }

        else if ( Cad_Igual (Etiqueta,"Prembulo") )
          {
          i = 0;
          while ( (Aux = strtok (NULL, " ")) && i<MAX_ORDEN )
            { Preambulo[i++] = atoi(Aux); }
          Preambulo[i] = NIL;
          }

        else if ( Cad_Igual (Etiqueta,"Postmbulo") )
          {
          i = 0;
          while ( (Aux = strtok (NULL, " ")) && i<MAX_ORDEN )
            { Postambulo[i++] = atoi(Aux); }
          Postambulo[i] = NIL;
          }

        } /* Fin if Etiqueta */
      Cad_Destruye (Linea);
      } /* Fin while Linea */
    } /* Fin if Cnf_Abre() */
  }
