/*--------------------------------------------------------------------
 * FICHERO:  MenCrea.c
 * OBJETIVO: Definir la funcin Men_Crea()
 * AUTOR:    Pedro Reina
 * FECHA:    V.14.7.1995
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones privadas
 *
 *   Men_Examina()
 *   Men_CalculaColumna()
 *------------------------------------------------------------------*/

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

#include "Menu.h"

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

#define MEN_INDICADOR  '>'   /* Indicador de tecla caliente (atajo) */

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

static void Men_Examina();
static void Men_CalculaColumna();

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

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

  if ( Nuevo = Men_CreaObjeto() )
    {
    /* Los colores los pone Men_CreaObjeto() */
    Men_PonModo   (Nuevo, Modo);
    Men_PonFilSup (Nuevo, Fil1);
    Men_PonColIzq (Nuevo, Col1);
    Men_PonAncho  (Nuevo, Col2-Col1+1);
    Men_PonAlto   (Nuevo, Fil2-Fil1+1);
    Men_PonTotal  (Nuevo, Total);
    Men_PonTipo   (Nuevo, Tipo);

    if ( Tipo == MEN_LISTA || Tipo == MEN_PROPIO )
      { Men_PonDatoOpcion (Nuevo, Dato); }
    else  /* Tipo == MEN_VECTOR */
      {
      if ( ( TextoOpcion = (cadena *) Mem_Crea (Total*sizeof(cadena)) ) &&
           ( LugarOpcion = (octeto *) Mem_Crea (Total*sizeof(octeto)) ) &&
           ( VectorDisponible = (logico *) Mem_Crea (Total*sizeof(logico)) ) )
        {
        Mem_Asigna (TextoOpcion, 0, Total*sizeof(cadena));
        Mem_Asigna (LugarOpcion, 0, Total*sizeof(octeto));
        Mem_Asigna (VectorDisponible, 0, Total*sizeof(logico));
        Men_PonDatoOpcion (Nuevo, (memoria)TextoOpcion);
        Men_PonDirLugar (Nuevo, LugarOpcion);
        Men_PonDirDisponible (Nuevo, VectorDisponible);
        for ( i=0 ; i<Total && !Error ; i++ )
          {
          Men_Disponible (Nuevo, i+1, SI);
          Lugar = Cad_CarPertenece (((cadena *)Dato)[i], MEN_INDICADOR);
          Texto = Cad_Crea (Cad_Longitud(((cadena *)Dato)[i])+2-(Lugar>0));
          if ( Texto )
            {
            Men_PonLugar (Nuevo, i+1, Lugar);
            Men_Examina (((cadena *)Dato)[i], Texto);
            Men_PonTextoVector (Nuevo, i+1, Texto);
            }
          else  { Error = SI; }
          }
        }
      } /* Fin de manejo segn Tipo */

    if ( Modo == MEN_HORIZONTAL && !Error )
      {
      if ( DirColumna = (octeto *) Mem_Crea (Total*sizeof(octeto)) )
        {
        Men_PonDirColumna (Nuevo, DirColumna);
        Men_CalculaColumna (Nuevo);
        }
      else  { Error = SI; }
      }
    } /* Fin if Nuevo */

  if ( Error )
    {
    Men_Destruye (Nuevo);
    Nuevo = NIL;
    }

  return ( Nuevo );
  }

/*--------------------------------------------------------------------
 * FUNCION:  Men_Examina()
 * OBJETIVO: Examinar una opcin, poniendo un espacio por delante y
 *           otro por detrs y quitando el indicador de atajo
 * ENTRADAS: La cadena con la opcin y una cadena donde dejar el resultado
 * SALIDAS:  Ninguna
 * EJEMPLO:  Men_Examina ( "A>yuda", Aux )
 * ALGORITMO:
 *     Carcter 0 de Aux es ESPACIO
 *     Recorrer la cadena de la opcin
 *       Se copia cada carcter en Aux, salvo el indicador de atajo
 *     Aadir ESPACIO y NULO a Aux
 *------------------------------------------------------------------*/
static void Men_Examina ( Opcion, Aux )
cadena Opcion, Aux;
  {
  contador i, j=0;

  Aux[j++] = ' ';

  for ( i=0 ; Opcion[i] ; i++ )
    {
    if ( Opcion[i] != MEN_INDICADOR )
      { Aux[j++] = Opcion[i]; }
    }

  Aux[j++] = ' ';
  Aux[j] = NULO;
  }

/*--------------------------------------------------------------------
 * FUNCION:  Men_CalculaColumna()
 * OBJETIVO: En un men de modo MEN_HORIZONTAL, calcular en qu columna
 *           hay que empezar a escribir cada opcin
 * ENTRADAS: El men
 * SALIDAS:  Ninguna
 * EJEMPLO:  Men_CalculaColumna ( MenuPrincipal )
 * NOTA:     Esta funcin slo se debe usar con mens MEN_HORIZONTAL
 * ALGORITMO:
 *      Calcular cuntos caracteres se necesitan para mostrar el men
 *      Calcular el espacio restante
 *      Calcular el hueco que hay que dejar entre cada dos opciones
 *        y lo que queda al comienzo de la primera
 *      Calcular la columna de comienzo de cada opcin y anotarla
 *------------------------------------------------------------------*/
static void Men_CalculaColumna (Menu)
menu Menu;
  {
  contador Necesario, Restante, Hueco, Sobra, Comienzo, i;

  Necesario = 0;
  for ( i=0 ; i<Men_Total(Menu) ; i++ )
    { Necesario += Cad_Longitud (Men_TextoVector(Menu,i+1)); }

  Restante = Men_Ancho (Menu) - Necesario;
  Hueco = Restante / (Men_Total(Menu) - 1);
  Sobra = Restante - Hueco * (Men_Total(Menu) - 1);
  Comienzo = Sobra / 2;

  Men_PonColumna (Menu, 1, Men_ColIzq(Menu) + Comienzo);
  for ( i=2 ; i<=Men_Total(Menu) ; i++ )
    {
    Men_PonColumna (Menu, i, Men_Columna(Menu,i-1) +
                    Cad_Longitud (Men_TextoVector(Menu,i-1)) + Hueco);
    }
  }
