/*--------------------------------------------------------------------
 * FICHERO:  MenEjeVe.c
 * OBJETIVO: Definir las funciones privadas Men_EjecutaVerticalFijo()
 *           y Men_EjecutaVerticalMovil()
 * AUTOR:    Pedro Reina
 * FECHA:    L.7.8.1995
 *------------------------------------------------------------------*/

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

#include "Menu.h"

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

/*--------------------------------------------------------------------
 * FUNCION:  Men_EjecutaVerticalFijo()
 * OBJETIVO: Mostrar al usuario las opciones de un men de tipo vertical
 *           en el que todas las opciones quepan en la zona de pantalla,
 *           manejar las pulsaciones y devolver el nmero de opcin elegida
 * ENTRADAS: El men, la opcin que debe resaltarse al comenzar y el texto
 *           de la primera lnea de ayuda
 * SALIDAS:  El nmero de opcin o cero si no se elige ninguna
 * EJEMPLO:  Men_EjecutaVerticalFijo ( MenuPrincipal, 7 , "Elige la opcion" )
 *------------------------------------------------------------------*/
entero Men_EjecutaVerticalFijo (Menu, Opcion, Texto)
menu   Menu;
entero Opcion;
cadena Texto;
  {
  static tecla TeclaMover[] = { TEC_ARRIBA, TEC_ABAJO, NIL };
  octeto   Estado;
  entero   i;
  logico   Decidido=NO, Visto;
  tecla   *TeclaTrata;
  caracter TextoOpcion[MEN_MAXLONG];

  if ( Men_Tipo(Menu) == MEN_VECTOR )
    { TeclaTrata = Men_AgregaAtajo (Menu, TeclaMover); }
  else
    { TeclaTrata = TeclaMover; }

  Usr_Indica (Texto, "ENTER: acepta. ESC: anula. ARRIBA, ABAJO: mueve");
  Men_EscribeVerticalFijo (Menu, Opcion, SI);
  Pan_CursorVisible (NO);
  Men_Texto (Menu, Opcion, TextoOpcion);

  while ( !Decidido )
    {
    Estado = Men_Tecla (Menu, TeclaTrata);

    if ( Estado == MEN_SI )
      {
      if ( Men_Tipo(Menu) != MEN_VECTOR ||
           Men_Tipo(Menu) == MEN_VECTOR && Men_DiDisponible (Menu,Opcion) )
        { Decidido = SI; }
      else
        { Son_MalaTecla(); }
      }

    else if ( Estado == MEN_NO )
      {
      Decidido = SI;
      Opcion = 0;
      }

    else
      {
      Men_EscribeNormal (Menu, Opcion, Men_FilSup(Menu)+(octeto)Opcion-1,
                         Men_ColIzq (Menu), TextoOpcion);

      switch ( Tec_Ultima() )
        {
        case TEC_ARRIBA:
          Opcion--;
          if ( Opcion == 0 )  { Opcion = Men_Total(Menu); }
          break;

        case TEC_ABAJO:
          Opcion++;
          if ( Opcion == Men_Total(Menu)+1 )  { Opcion = 1; }
          break;

        default:   /* La tecla es un atajo */
          Visto = NO;
          for ( i=0 ; !Visto ; i++ )
            {
            if ( Tec_Mayus((tecla)
                     ((Men_TextoVector(Menu,i)[Men_Lugar(Menu,i)])))
                 == Tec_Mayus(Tec_Ultima()) )
              {
              Opcion = i;
              Visto = SI;
              }
            }
          if ( Men_Tipo(Menu) != MEN_VECTOR ||
               Men_Tipo(Menu) == MEN_VECTOR && Men_DiDisponible (Menu,Opcion) )
            { Decidido = SI; }
          else
            { Son_MalaTecla(); }
          break;
          }
      Men_Texto (Menu, Opcion, TextoOpcion);
      Men_EscribeResaltado (Menu, Opcion, Men_FilSup(Menu)+(octeto)Opcion-1,
                            Men_ColIzq (Menu), TextoOpcion);
      }  /* Fin Estado == MEN_TRATA */
    } /* Fin while (!Decidido) */

  if ( Men_Tipo(Menu) == MEN_VECTOR )
    { Mem_Destruye (TeclaTrata); }

  Usr_BorraZona (NEGRO);

  return ( Opcion );
  }

/*--------------------------------------------------------------------
 * FUNCION:  Men_EjecutaVerticalMovil()
 * OBJETIVO: Mostrar al usuario las opciones de un men de tipo vertical
 *           en el que no todas las opciones quepan en la zona de pantalla,
 *           manejar las pulsaciones y devolver el nmero de opcin elegida
 * ENTRADAS: El men, la opcin que debe resaltarse al comenzar y el texto
 *           de la primera lnea de ayuda
 * SALIDAS:  El nmero de opcin o cero si no se elige ninguna
 * EJEMPLO:  Men_EjecutaVerticalMovil ( MenuPrincipal, 7 , "Elige la opcion" )
 * ALGORITMO:
 *------------------------------------------------------------------*/
entero Men_EjecutaVerticalMovil (Menu, Opcion, Texto)
menu   Menu;
entero Opcion;
cadena Texto;
  {
  static tecla TeclaMover[] = { TEC_ARRIBA, TEC_ABAJO, TEC_REPAG,
                                TEC_AVPAG, NIL };
  octeto   Estado;
  entero   Primero, Ultimo, i;
  logico   Decidido=NO, Visto;
  tecla   *TeclaTrata;
  caracter TextoOpcion[MEN_MAXLONG];

  if ( Men_Tipo(Menu) == MEN_VECTOR )
    { TeclaTrata = Men_AgregaAtajo (Menu, TeclaMover); }
  else
    { TeclaTrata = TeclaMover; }

  Usr_Indica (Texto,
    "ENTER: acepta. ESC: anula. ARRIBA, ABAJO, REPAG, AVPAG: mueve");
  Men_CalculaPrimeroUltimo (Menu, Opcion, &Primero, &Ultimo);
  Men_EscribeVerticalMovil (Menu, Opcion, SI);
  Pan_CursorVisible (NO);
  Men_Texto (Menu, Opcion, TextoOpcion);

  while ( !Decidido )
    {
    Estado = Men_Tecla (Menu, TeclaTrata);

    if ( Estado == MEN_SI )
      {
      if ( Men_Tipo(Menu) != MEN_VECTOR ||
           Men_Tipo(Menu) == MEN_VECTOR && Men_DiDisponible (Menu,Opcion) )
        { Decidido = SI; }
      else
        { Son_MalaTecla(); }
      }

    else if ( Estado == MEN_NO )
      {
      Decidido = SI;
      Opcion = 0;
      }

    else
      {
      Men_EscribeNormal (Menu, Opcion, Men_FilSup(Menu)+
          (octeto)(Opcion-Primero), Men_ColIzq (Menu), TextoOpcion);

      switch ( Tec_Ultima() )
        {
        case TEC_ARRIBA:
          if ( Opcion == 1 )  { Son_MalaTecla(); }
          else
            {
            Opcion--;
            if ( Primero != 1 &&
                 Ultimo-Opcion > Men_Alto(Menu)/2 )
              {
              Primero--;
              Ultimo--;
              Pan_Papel (Men_Papel(Menu));
              Pan_Mueve (PAN_ABAJO, 1, Men_FilSup(Menu)+1, Men_ColIzq(Menu),
                                       Men_FilInf(Menu)-1, Men_ColDer(Menu));
              if ( Ultimo == Men_Total(Menu)-1 )
                { Men_IndicaHayMas (Menu, Men_FilInf(Menu), CAR_FLECHA_ABAJO); }
              Men_Texto (Menu, Primero+1, TextoOpcion);
              Men_EscribeNormal (Menu, Primero+1, Men_FilSup(Menu)+1,
                                 Men_ColIzq(Menu), TextoOpcion);
              if ( Primero == 1 )
                {
                Men_Texto (Menu, (entero)1, TextoOpcion);
                Pan_Borra (Men_Papel(Menu), Men_FilSup(Menu), Men_ColIzq(Menu),
                                            Men_FilSup(Menu), Men_ColDer(Menu));
                Men_EscribeNormal (Menu, (entero)1, Men_FilSup(Menu),
                                   Men_ColIzq(Menu), TextoOpcion);
                }
              }
            }
          break;

        case TEC_ABAJO:
          if ( Opcion == Men_Total(Menu) )  { Son_MalaTecla(); }
          else
            {
            Opcion++;
            if ( Ultimo != Men_Total(Menu) && 
                 Opcion-Primero > Men_Alto(Menu)/2 )
              {
              Primero++;
              Ultimo++;
              Pan_Papel (Men_Papel(Menu));
              Pan_Mueve (PAN_ARRIBA, 1, Men_FilSup(Menu)+1, Men_ColIzq(Menu),
                                        Men_FilInf(Menu)-1, Men_ColDer(Menu));
              if ( Primero == 2 )
                { Men_IndicaHayMas (Menu, Men_FilSup(Menu), CAR_FLECHA_ARRIBA); }
              Men_Texto (Menu, Ultimo-1, TextoOpcion);
              Men_EscribeNormal (Menu, Ultimo-1, Men_FilInf(Menu)-1,
                                 Men_ColIzq(Menu), TextoOpcion);
              if ( Ultimo == Men_Total(Menu) )
                {
                Men_Texto (Menu, Ultimo, TextoOpcion);
                Pan_Borra (Men_Papel(Menu), Men_FilInf(Menu), Men_ColIzq(Menu),
                                            Men_FilInf(Menu), Men_ColDer(Menu));
                Men_EscribeNormal (Menu, Ultimo, Men_FilInf(Menu),
                                   Men_ColIzq(Menu), TextoOpcion);
                }
              }
            }
          break;
          
        case TEC_AVPAG:
          if ( Opcion == Men_Total(Menu) )  { Son_MalaTecla(); }
          else
            {
            Opcion = Min ( Opcion + Men_Alto(Menu) - 2, Men_Total(Menu) );
            Men_CalculaPrimeroUltimo (Menu, Opcion, &Primero, &Ultimo);
            Men_EscribeVerticalMovil (Menu, Opcion, SI);
            }
          break;

        case TEC_REPAG:
          if ( Opcion == 1 )  { Son_MalaTecla(); }
          else
            {
            Opcion = Max ( Opcion - Men_Alto(Menu) + 2, 1 );
            Men_CalculaPrimeroUltimo (Menu, Opcion, &Primero, &Ultimo);
            Men_EscribeVerticalMovil (Menu, Opcion, SI);
            }
          break;

        default:   /* La tecla es un atajo */
          Visto = NO;
          for ( i=0 ; !Visto ; i++ )
            {
            if ( Tec_Mayus((tecla)
                     ((Men_TextoVector(Menu,i)[Men_Lugar(Menu,i)])))
                 == Tec_Mayus(Tec_Ultima()) )
              {
              Opcion = i;
              Visto = SI;
              }
            }
          Men_CalculaPrimeroUltimo (Menu, Opcion, &Primero, &Ultimo);
          Men_EscribeVerticalMovil (Menu, Opcion, SI);
          if ( Men_Tipo(Menu) != MEN_VECTOR ||
               Men_Tipo(Menu) == MEN_VECTOR && Men_DiDisponible (Menu,Opcion) )
            { Decidido = SI; }
          else
            { Son_MalaTecla(); }
          break;
          }
          
      Men_Texto (Menu, Opcion, TextoOpcion);
      Men_EscribeResaltado (Menu, Opcion, Men_FilSup(Menu)+
          (octeto)(Opcion-Primero), Men_ColIzq (Menu), TextoOpcion);
      }  /* Fin Estado == MEN_TRATA */
    } /* Fin while (!Decidido) */

  if ( Men_Tipo(Menu) == MEN_VECTOR )
    { Mem_Destruye (TeclaTrata); }

  Usr_BorraZona (NEGRO);
                        
  return ( Opcion );
  }
