#include <bios.h>
#include <io.h>
#include <dos.h>
#include <dir.h>
#include <time.h>
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
#include <string.h>
#include <stdlib.h>
#include <graphics.h>

#include "..\..\libs\make_bot\make_bot.h"		// Fuciones de MAKE_BOTON
#include "c:\program\src_dos\libs\bdatos\bdatos.hh"
#include "alum_def.h"

#define SEC_MENU    1

#define OFF     0
#define ON      1

#ifdef __cplusplus
    #define __CPPARGS ...
#else
    #define __CPPARGS
#endif

#define INTR                           0X1C /* The clock tick interrupt */

extern unsigned _stklen = 18432U;


char far *VGARam = (char far *)MK_FP( 0xA000, 0);
typedef unsigned char DacPalette256[256][3];
DacPalette256 Palette256;

void Creditos(void);
int MuestraImagen( char *file );
int CargaPaleta(char *file );
void setvgapalette256(DacPalette256 *PalBuf);


void ImprimeEtiquetas(void);
void ImprimeNombrees( char como );
void OptenPaginasIniFin( int *Inicio, int *Fin, int NRegistros );

 /*********************************\
|*                                 *|
|* Informe general sobre el estado *|
|*   de la empresa selecionada.    *|
|*                                 *|
 \*********************************/
DatosInformativos DatosInf;
extern BDatos          BAlum;            // Base Datos Antig.Alumnos
extern AntiguosAlumnos SAlum;            // Struct Antig.Alumnos

void MuestraDatos( void );
void RecopilaDatos( void );


 /*********************************\
|*                                 *|
|* Gestion para la                 *|
|*                    CFG inicial  *|
|*                                 *|
 \*********************************/
extern BDatos BConfig;                // Base con la configuracion del programa
extern CONFIG Config;                 // Configuracion global del programa

struct date FechaGestionActual;// Fecha de gestion actual
char BufferM[6][65 + 1];       // Buffer para los mensajes...

char Buffer[180];              //
p_Ampliada MensajesLn;         // Definiciones del letrero digital (NOMB.EMPR)
extern char *ptr_char;         // Puntero a la fuentes de caracteres propia

			       // Control de EDICION / VISUALIZACION
char VisualMode = ERROR;       // ERROR: los datos pueden ser modificados
                               // OK:    solo se permite editar NO TOCAR

 /*********************************\
|*                                 *|
|* Vectores de interrupci�n para   *|
|* provocar que parpadeen las led's*|
|*                                 *|
 \*********************************/
void AnulaInterrupcion(void);
void ActivaInterrupcion(void);

void interrupt handler(__CPPARGS);
void interrupt ( *oldhandler)(__CPPARGS);
char count = 0, intvect = OFF, IntVect = OFF;


 /*********************************\
|*                                 *|
|* Funciones para el manejo del    *|
|* Men� Principal, y ejecuciones.  *|
|*                                 *|
 \*********************************/

void MenuPrincipal(void);
void DibujaMenuPrincipal( void );
int  SubItem( int Sec, int NItem );
void DibujaLogotipo( char * File, int X, int Y );
void EjecutaModulo( void (*FuncionModulo)(void) );
void MarcaItemSeleccionado( int Columna, char como  );
void PantallaGrafica( int X0, int Y0, int X1, int Y1 );
void MarcaSubItemSeleccionado( int Sec, int Columna, char como );
char TIPO_ORDENACION;

int Ordenar( const void *A, const void *B )
{
 char dev;

 switch( TIPO_ORDENACION )
 {
  case 0:
         if ( (dev = strcmp( (( AntiguosAlumnos *)A)->Nombre, (( AntiguosAlumnos *)B)->Nombre ) ) == 0)
          dev = strcmp( (( AntiguosAlumnos *)A)->Apellidos, (( AntiguosAlumnos *)B)->Apellidos );
         return dev;
         break;
  case 1:
         if ( (dev = strcmp( (( AntiguosAlumnos *)A)->Apellidos, (( AntiguosAlumnos *)B)->Apellidos ) ) == 0)
          dev = strcmp( (( AntiguosAlumnos *)A)->Nombre, (( AntiguosAlumnos *)B)->Nombre );
         return dev;
         break;
  case 2:
         return ( strcmp( (( AntiguosAlumnos *)A)->Direccion, (( AntiguosAlumnos *)B)->Direccion ) );
         return 0;
         break;
  case 3:
         return ( strcmp( (( AntiguosAlumnos *)A)->Direccion, (( AntiguosAlumnos *)B)->Direccion ) );
         return 0;
  case 4:
         if ( (( AntiguosAlumnos *)A)->CC.Oficina == (( AntiguosAlumnos *)B)->CC.Oficina )
         {
          if ( (( AntiguosAlumnos *)A)->CC.Sucursal == (( AntiguosAlumnos *)B)->CC.Sucursal )
          {
           if ( (( AntiguosAlumnos *)A)->CC.DigControl == (( AntiguosAlumnos *)B)->CC.DigControl )
           {
            if ( (( AntiguosAlumnos *)A)->CC.NumCuenta > (( AntiguosAlumnos *)B)->CC.NumCuenta ) return  1;
            if ( (( AntiguosAlumnos *)A)->CC.NumCuenta < (( AntiguosAlumnos *)B)->CC.NumCuenta ) return -1;
           }
           if ( (( AntiguosAlumnos *)A)->CC.DigControl > (( AntiguosAlumnos *)B)->CC.DigControl ) return  1;
           if ( (( AntiguosAlumnos *)A)->CC.DigControl < (( AntiguosAlumnos *)B)->CC.DigControl ) return -1;
          }
          if ( (( AntiguosAlumnos *)A)->CC.Sucursal > (( AntiguosAlumnos *)B)->CC.Sucursal ) return  1;
          if ( (( AntiguosAlumnos *)A)->CC.Sucursal < (( AntiguosAlumnos *)B)->CC.Sucursal ) return -1;
         }
         if ( (( AntiguosAlumnos *)A)->CC.Oficina > (( AntiguosAlumnos *)B)->CC.Oficina ) return  1;
         if ( (( AntiguosAlumnos *)A)->CC.Oficina < (( AntiguosAlumnos *)B)->CC.Oficina ) return -1;
         break;

 }
 return 0;
};



 /**************************************************************************\
|*                                                                          *|
|*  main                                                                    *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*            �Sabes lo que es tener el control?, bien pues esta funci�n     *|
|*            tiene el control de todo, inicializa y desinicializa todo:    *|
|*              - vectores de interrupci�n                                  *|
|*              - sistema gr�fico             - m�dulo de botones MK_Boton  *|
|*                                                                          *|
|*  Entradas: Par�metros de inicializaci�n para el programa.                *|
|*                                                                          *|
|*  Salidas:  0    Todo ha ido bien                                         *|
|*            #    C�digo de error ( descritos en la funci�n _Error  )      *|
|*                                                                          *|
|*                                                                          *|
 \**************************************************************************/
int main( int argc, char *argv[] )
{

 int i;
 char buffer[4][80] = { "Jos� David Guill�n || _-�FuTuRe ViSiOn�-_ || 1997 (c)",
                        "        e-mail: Jose-David.Guillen@cs.us.es          ",
                        "        http://www.arrakis.es/~infomundo/JD          ",
                        "                                                     " };

  /*****************************\                                �������
 |* Obtenemos la fecha en curso *|
  \*****************************/
 getdate( &FechaGestionActual );

  /*****************************\
 |* Inicializaci�n del rat�n    *|                               ���ܲ��
 |* modo gr�fico y nueva paleta *|                               ���߲��
  \*****************************/
 Initialize( 9, 2 );                    // Inicializa el Modo Gr�fico

 setrgbpalette(EGA_WHITE,     56, 58, 59 );
 setrgbpalette(EGA_LIGHTGRAY, 30, 37, 43 );
 setrgbpalette(EGA_DARKGRAY,   24, 27, 30 );

 True_Push = ON;                        PunteroRaton = 1;
 inicializa_raton_grafico( 0, 0, 639, 479 );


  /*****************************\
 |* Colocamos el vector de int. *|                               �������
  \*****************************/
 intvect = ON;
 for ( i=1; i < argc; i++ )
   if ( strcmpi( argv[i], "/BLINK" ) == 0 )
    intvect = OFF;
 if ( intvect == OFF  || atexit( AnulaInterrupcion ) != 0 )
 {
   intvect = OFF;
 } else {
   intvect = ON;
   /* save the old interrupt vector */
   oldhandler = getvect(INTR);
   /* install the new interrupt handler */
   setvect(INTR, handler);

   IntVect = ON;
 }

  /*****************************\
 |*   Cargamos las fuentes de   *|                               ���ܲ��
 |* usuario para el letrero dig.*|                               ���߲��
  \*****************************/
 if ( ( ptr_char = ( char *)malloc( sizeof(char)*4096 ) ) == NULL )
                     Error( 0x06, "Error inicializando Memoria, fuentes" );
 LeeFuentes(Config.Vent_msg);


  /*****************************\
 |* Leemos la configuraci�n glb *|                               ���ܲ��
 |* y  desactivamos  el bloqueo *|                               ���۲��
 |* si   procede.               *|                               ���߲��
  \*****************************/
 if ( BConfig.AbrirReg( "datos\\config.cfg", sizeof( CONFIG ) ) != OK )
                                                 Error( 0x01, BConfig.cError );
 if ( BConfig.Registros() == 0 )
    BConfig.InsReg( (void *)&Config, BConfig.Registros(), ARRIBA );
 else
    BConfig.LeeReg( (void *)&Config, 0 );


//������������������������������������������������������������������������
//������������������������������������������������������������������������
//������������������������������������������������������������������������
// AnulaInterrupcion();
//������������������������������������������������������������������������
//������������������������������������������������������������������������
//������������������������������������������������������������������������

    MenuPrincipal();

  /*****************************\
 |* DesInicializamos todo y     *|                               ���ܲ��
 |* mostramos el mensaje final. *|                               ���߲��
  \*****************************/
 BConfig.CerrarReg();
 free( ptr_char );
 AnulaInterrupcion();

 closegraph();


 printf( "\n%s", buffer[0] );
 printf( "\n%s", buffer[1] );
 printf( "\n%s", buffer[2] );
 printf( "\n%s", buffer[3] );

return 0;

}

void AnulaInterrupcion(void)
{
/* reset the old interrupt handler */
if ( intvect == ON )
                setvect(INTR, oldhandler);
intvect = OFF;
}



void MenuPrincipal(void)
{
 int ok, CurrCol, BPush, PulsoIntro;
 int i;
 char buffer[80];


 ok = 0; CurrCol = 0;
 PulsoIntro = 0;

// if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

 RecopilaDatos();
 DibujaMenuPrincipal();

 // Recargamos los botones del men�
 if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

 do {
      if ( PulsoIntro == 0 )
      {
       MarcaItemSeleccionado( CurrCol, INTENSO  );
       BPush = Comprueba_Secuencia( SEC_MENU, RatonVentas );
       MarcaItemSeleccionado( CurrCol, NORMAL   );
       if ( BPush > 0 && BPush != 11 )
       {
        CurrCol = BPush - 1;
        MarcaItemSeleccionado( CurrCol, INTENSO  );
       }
      } else {
       while( kbhit() ) getch();
       PulsoIntro = 0;
       BPush = CurrCol + 1;
      }

       switch( BPush )
       {
       case  0:				  // No se pulso ningun BOTON
	       while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
               break;
       case -2:				  // Hay una tecla normal en BUFFER
               // Intro
               if ( getch() == 13 )
                                   PulsoIntro = 1;
	       while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
               break;
       case -1:				  // Hay una tecla especial en BUFFER
               switch( getch() )
               {
                // Flecha Izquierda
                case  75:
                case  15:
                       CurrCol--; if ( CurrCol <  0 ) CurrCol =  9;
                       break;
                // Flecha Arriba
                case  72:
                       CurrCol--; if ( CurrCol <  0 ) CurrCol =  7;
                       break;
                // Flecha Derecha
                case  77:
                case   9:
                       CurrCol++; if ( CurrCol > 9 ) CurrCol =  0;
                       break;
                // Flecha Abajo
                case  80:
                       CurrCol++; if ( CurrCol > 7 ) CurrCol =  0;
                       break;
                // Inicio
                case  71:
                       CurrCol = 0;
                       break;
                // Fin
                case  79:
                       CurrCol = 9;
                       break;
               }
            break;
       // Gestion de Antiguos Alumnos
       case  1:
            EjecutaModulo( GstAlumnos );
            break;
       // Ordenaciones
       case  2:
            PantallaGrafica( 215,  50, 415, 230 );
            Imprime_Estaticos( 92, "systm\\alumMP.img" );
            BPush = SubItem( 3, 5 );
            PantallaGrafica( 215,  50, 415, 230 );
            switch ( BPush )
            {
             case 1:
             case 2:
             case 3:
             case 4:
             case 5:
                    TIPO_ORDENACION = BPush - 1;
                    Optar( ENCUADRE, "Comando Ordenar", "Ordenando la base de", "datos. Esto puede tardar unos", "minutos. Por favor, espere...", NULL );
                    sprintf( buffer, "datos\\alum.dbf" );
                    if ( !access( buffer, 0 ) )
                    {
                     if ( BAlum.AbrirReg( buffer, sizeof( AntiguosAlumnos ) ) == ERROR )
                                                             Error(0x01, BAlum.cError);
                     BAlum.SortReg( Ordenar );
                     BAlum.CerrarReg();
                    }
                    Optar( ENCUADRE, "Comando Ordenar", "Ordenando la base de", "datos. Esto puede tardar unos", "minutos. Por favor, espere...", NULL );
                  break;
            }
            break;
       // --
       case  3:
/*
            PantallaGrafica( 215, 160, 415, 270 );
            Imprime_Estaticos( 95, "systm\\Tpv_MP.img" );
            BPush = SubItem( 6, 3 );
            PantallaGrafica( 215, 160, 415, 270 );
            switch ( BPush )
            {
             case 1:
                    EjecutaModulo( InfoEmpleados );
                  break;
             case 2:
                    EjecutaModulo( PassEmpleados );
                  break;
             case 3:
                    EjecutaModulo( GraficaVentaEmpleados );
                  break;
            }
*/
            break;
       // Listados
       case  4:
            PantallaGrafica( 215, 200, 415, 310 );
            Imprime_Estaticos( 93, "systm\\alumMP.img" );
            BPush = SubItem( 4, 3 );
            PantallaGrafica( 215, 200, 415, 310 );
            switch ( BPush )
            {
             case 1:
                    sprintf( buffer, "datos\\alum.dbf" );
                    if ( !access( buffer, 0 ) )
                    {
                     // Cargamos los botones del programa
                     if ( carga_botones( "systm\\alum.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

                     if ( BAlum.AbrirReg( buffer, sizeof( AntiguosAlumnos ) ) == ERROR )
                                                             Error(0x01, BAlum.cError);
                     ImprimeNombrees( 1 );
                     BAlum.CerrarReg();

                     // Cargamos los botones del programa
                     if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );
                    }
                  break;
             case 2:
                  EjecutaModulo( ImprimeEtiquetas );
                  break;
             case 3:
                    sprintf( buffer, "datos\\alum.dbf" );
                    if ( !access( buffer, 0 ) )
                    {
                     // Cargamos los botones del programa
                     if ( carga_botones( "systm\\alum.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

                     if ( BAlum.AbrirReg( buffer, sizeof( AntiguosAlumnos ) ) == ERROR )
                                                             Error(0x01, BAlum.cError);
                     if ( Optar( 1, "Escoja formato salida:", "Presione aceptar para imprimir", "los datos de salida, o canclar", "para grabarlos en soporte A:\\", NULL ) )
                      ImprimeNombrees( 3 );
                     else
                      Optar( 0, "ATENCION!!!", "Funci�n no implementada.", NULL );

                     BAlum.CerrarReg();

                    // Cargamos los botones del programa
                    if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );
                    }
                  break;
            }
            break;
       // --
       case  5:
/*
            PantallaGrafica( 215, 205, 415, 350 );
            Imprime_Estaticos( 94, "systm\\alumMP.img" );
            BPush  = SubItem( 5, 4 );
            PantallaGrafica( 215, 205, 415, 350 );
            switch ( BPush )
            {
             case 1:
//                  EjecutaModulo( VentasDiarias );
                  break;
             case 2:
                  break;
            }
*/
            break;
       // Ayuda
       case  6:
 // Cargamos los botones del programa
 if ( carga_botones( "systm\\alum.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

            Optar( 0, "� Ayuda !", "Para cualquier consulta", "dirijase a:","---","www.arrakis.es/~infomundo/JD", NULL );

 // Cargamos los botones del programa
 if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

            break;
       // Miscelanea
       case  7:
            PantallaGrafica( 215, 215, 415, 430 );
            Imprime_Estaticos( 96, "systm\\alumMP.img" );
            BPush = SubItem( 7, 6 );
            PantallaGrafica( 215, 215, 415, 430 );
            switch ( BPush )
            {
             case 1:
                  break;
             case 2:
                  break;
             case 3:
                  break;
             case 4:
                  break;
             case 5:
                  break;
             case 6:
                  EjecutaModulo( ConfigurarEntorno );
                  break;
            }
            break;
       // Salir
       case  8:
            ok = 1;
            break;
       // Marcador interior del letrero que se desplaza
       case  9:
            break;
       // Marcador exterior del letrero que se desplaza
       // Creditos...
       case 10:
            Creditos();
            DibujaMenuPrincipal();
            break;
       // Ventana infierior izquierda
       case 11:
            break;

       }

 } while ( !ok );

}


void EjecutaModulo( void (*FuncionModulo)(void) )
{
 // Cargamos los botones del programa
 if ( carga_botones( "systm\\alum.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

 // Ejecutamos la funcion Pedida
 FuncionModulo();

 // Recargamos los botones del men�
 if ( carga_botones( "systm\\alumMP.img" ) != OK ) Error( 0x03, "Make Boton, no pudo cargar los botones" );

 DibujaMenuPrincipal();

}


void MarcaItemSeleccionado( int Columna, char como  )
{

 Imprime_Bordes( SEC_MENU, ( Columna + 1 ), ( como == NORMAL ) ? -1 : 11 );

}

void MarcaSubItemSeleccionado( int Sec, int Columna, char como )
{

 Imprime_Bordes( Sec, ( Columna + 1 ), ( como == NORMAL ) ? -1 : 11 );

}

void DibujaMenuPrincipal(void)
{
 int i, Center;
 char buffer[80];
 char NombreMenu[8][80] = { "Gesti�n Ant. Alumnos", "Ordenar por...", "---",
                            "Listados", "---", "Ayuda",
                            "Miscelanea", "Salir" };

 // Rellenamos la pantalla con un fondo atractivo...
 setfillstyle( Config.FillBgS, Config.FillBgC ); bar( 0, 0, 640, 480 );

 Imprime_Estaticos( 90, "systm\\alumMP.img" );

 settextstyle( SMALL_FONT, HORIZ_DIR, 6 );

 for ( i = 0; i < 8; i++ )
 {
  Center = (200 - textwidth( NombreMenu[i] ) ) / 2;
  setcolor( EGA_BLACK );  outtextxy( 422 + Center, 164 + 40*i, NombreMenu[i] );
  setcolor( EGA_WHITE );  outtextxy( 423 + Center, 165 + 40*i, NombreMenu[i] );
 }

 if ( access( buffer, 0 ) != 0 )
    strcpy( buffer, "systm\\alum.pcx" );
 DibujaLogotipo( buffer, 25, 5 );

 sprintf( Buffer, "Dirija cualquier consulta a: e-mail: Jose-David.Guillen@cs.us.es o visiteme en http://www.arrakis.es/~infomundo/JD  " );

 MensajesLn.x          = 117;             MensajesLn.y    = 291;
 MensajesLn.ndigitos   =  11;
 MensajesLn.AX         =   2;             MensajesLn.AY   =   2;
 MensajesLn.C1         =  Config.DigBg;   MensajesLn.C2   =  Config.DigFg;

 MuestraDatos();
}



/***************************************************************************\
|*                                                                         *|
|* INT CLK                                                                 *|
|*                                                                         *|
|* Descripci�n:                                                            *|
|*              interrupci�n para el parpadeo de los led's                 *|
|*                                                                         *|
|* Entradas: (indeterminadas)                                              *|
|*                                                                         *|
|*                                                                         *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void interrupt handler(__CPPARGS)
{
/* increase the global counter */
 if ( IntVect == ON )
 {
   count = (count++)%16;
   if ( count == 1 )
   {
         setpalette( 11,  EGA_GREEN      );
         setpalette( 13,  EGA_LIGHTGREEN );
   }
   else if ( count == 8 )
   {
         setpalette( 11, EGA_RED        );
         setpalette( 13, EGA_LIGHTRED   );

   }
 }

/* call the old routine */
   oldhandler();
}


void DibujaLogotipo( char * File, int X, int Y )
{
 FILE *fp;
 int alto, ancho; unsigned char byte;
 int contador;
 char color[17] = { 0, EGA_RED, EGA_GREEN, EGA_LIGHTGRAY,
                    EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED,
                    EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED,
                    EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED, EGA_LIGHTRED };

                                    
 if ( ( fp = fopen ( File, "rb" ) ) != NULL )
 {

  // Saltamos la cabecera
  fseek( fp, 128, SEEK_SET );

  for(alto=0; alto<279; alto++)
  {
    for(ancho=0; ancho<240; )
    {
      byte=getc(fp);
      if(byte<=0xC0)
      {
        if  ( byte != 255 )
//               VGARam[ ancho+X + (alto+Y)*320 ] = color[byte%16];
                putpixel( ancho+X, alto+Y, color[byte%16] );
	ancho++;
      }
      else
      {
	contador=byte&0x3F; byte=getc(fp);
        if  ( byte != 255 )
	  for(; contador>0; contador--)
	  {
//                VGARam[ ancho+X + (alto+Y)*320 ] = color[byte%16];

                putpixel( ancho+X, alto+Y, color[byte%16] );
          ancho++;
	  }
        else
          ancho += contador;
      }
    }
  }



  fclose( fp );
 }

}


void PantallaGrafica( int X0, int Y0, int X1, int Y1 )
{
 static void far *ImagenFondo;
 static Memoria = 0;


 if ( Memoria == 1 )
 {
    putimage( X0, Y0, ImagenFondo, COPY_PUT );
    farfree( ImagenFondo );
    Memoria = 0;
 } else

 if ( ( ImagenFondo = farmalloc( JD_imagesize( X0, Y0, X1, Y1 ) ) ) != NULL )
 {
   Memoria = 1;
   getimage( X0, Y0, X1, Y1, ImagenFondo );

 } else {

  Error( 0x04, "Memoria insuficiente" );

 }

}

int SubItem( int Sec, int NItem )
{
int ok, PulsoIntro, CurrSubCol, BPush;
int dev = -1;
            ok = 0; PulsoIntro = 0; CurrSubCol = 0;
            do {

                  if ( PulsoIntro == 0 )
                  {
                     MarcaSubItemSeleccionado( Sec, CurrSubCol, INTENSO  );
                     BPush = Comprueba_Secuencia( Sec, NULL );//RatonVentas );
                     MarcaSubItemSeleccionado( Sec, CurrSubCol, NORMAL   );
                  } else {
                     PulsoIntro = 0;
                     BPush = CurrSubCol + 1;
                  }

                  switch( BPush )
                  {
                    case  0:				  // No se pulso ningun BOTON
	                 while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
                         ok = 1; dev = -1;
                         break;
                    case -2:				  // Hay una tecla normal en BUFFER
                         // Intro
                          if ( (BPush = getch()) == 13 )
                                   PulsoIntro = 1;
                          else if ( BPush == 27 ) { ok = 1; dev = -1; }
	                  while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
                         break;
                    case -1:				  // Hay una tecla especial en BUFFER
                         switch( getch() )
                         {
                            // Flecha Izquierda
                            case  75:
                            case  15:
                            // Flecha Arriba
                            case  72:
                                     CurrSubCol--; if ( CurrSubCol <  0 ) CurrSubCol =  NItem-1;
                                     break;
                            // Flecha Derecha
                            case  77:
                            case   9:
                                     ok = 1;
                                     dev = -1;
                                     break;
                            // Flecha Abajo
                            case  80:
                                     CurrSubCol++; if ( CurrSubCol > (NItem-1) ) CurrSubCol =  0;
                                     break;
                            // Inicio
                            case  71:
                                     CurrSubCol = 0;
                                     break;
                            // Fin
                            case  79:
                                     CurrSubCol = 9;
                                     break;
                            default:
                                     while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
                         }
                         break;
                    //
                    default:
                         if ( BPush <= NItem && BPush > 0 )
                         {
                          ok = 1;
                          dev = BPush;
                         }
                         break;
                  }
 } while ( !ok );

 return dev;
}






void Error( int code, char *MensajeError )
{
 free( ptr_char );
 AnulaInterrupcion();
 restorecrtmode();
 BConfig.CerrarReg();

 printf( "\nSe produjo un codigo de error %d, subcodigo no disponible ", code );
 switch( code )
 {
  case 0:
       printf( "\n Error Desconocido " );
       break;
  case 1:
       printf( "\n BDatos gener� el error de salida. |ERROR DE ACCESO| " );
       break;
  case 2:
       printf( "\n Make Boton gener� el error de salida " );
       break;
  case 3:
       printf( "\n Fall� en alg�n punto del men� principal" );
       break;

 };

 printf( "\n> %s_", MensajeError );
 exit(code);
}






 /**************************************************************************\
|*                                                                          *|
|*  RecopilaDatos                                                            *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Recopila todos los datos utilies, de la empresa seleccionada*|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void RecopilaDatos( void )
{
 char buffer[80];
 long RegComp[31 + 2];
 int  scl, ctot, clib;
 long bcl;

 struct ffblk ffblk;
 union REGS r;
 int done, i;

 int MesActual = FechaGestionActual.da_mon;

 // Recopilaci�n de datos sobre: Empresas
 sprintf( buffer, "datos\\alum.dbf" );
 if ( access( buffer, 0 ) == 0 && BAlum.AbrirReg( buffer, sizeof( AntiguosAlumnos ) ) != ERROR )
 {
  DatosInf.NumAlum = (int)BAlum.Registros();
  BAlum.CerrarReg();
 } else
  DatosInf.NumAlum = 0;

 // Datos de interes vario: Espacio Libre en disco
 char unidad = bdos(0x19,0,0);
 r.h.ah = 0x36;
 r.h.dl = unidad+1;
 intdos(&r,&r);
 scl = r.x.ax;                           /*sectores por cluster*/
 bcl = (long)scl*r.x.cx;                 /*bytes por cluster*/
 ctot = r.x.dx;                          /*clusters total*/
 clib = r.x.bx;                          /*clusters libres*/
 DatosInf.EspacioLib = (clib*bcl);

 // Datos de interes vario:
 //        Espacio consumido por las bases de datos ( del la EMPRESA ACTUAL )
 DatosInf.EspacioCon = 0;
 sprintf( buffer, "datos\\*.*" );
 done = findfirst( buffer, &ffblk, 0);
 while (!done)
 {
    DatosInf.EspacioCon += ffblk.ff_fsize;
    done = findnext(&ffblk);
 }
}


 /**************************************************************************\
|*                                                                          *|
|*  MuestraDatos                                                             *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Muestra los datos previamente recopilados.                  *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
#define NUM_LINEAS  3
void MuestraDatos( void )
{
 static char LineaActual = 0;

 p_Ampliada InfoDatos;
 char buffer[120];
 int i;

 LineaActual = 0;

 InfoDatos.x          =  30;
 InfoDatos.ndigitos   =  32;
 InfoDatos.AX         =   1;             InfoDatos.AY   =   1;
 InfoDatos.C1         =   0;             InfoDatos.C2   =  Config.TxtFgI;
 InfoDatos.C3         =   0;

 for ( i = 0; i < NUM_LINEAS; i++ )
 {
  switch( ( LineaActual + i ) % NUM_LINEAS )
  {
   case  0:
         sprintf( buffer, "Existen %d antiguos alumnos      ", DatosInf.NumAlum );
         break;
   case  1:
         buffer[0] =  ' ';
         buffer[1] = '\0';
         break;
   case  2:
         sprintf( buffer, "Espacio ocup: %ld Kb de %d Mb     ", DatosInf.EspacioCon / 1024, DatosInf.EspacioLib / 1048576L );
         break;
   default:
         buffer[0] =  ' ';
         buffer[1] = '\0';
         break;
   };
  InfoDatos.y       = 330 + 8*i;
  // No tenemos mas remedio que acceder a los datos privados:
  InfoDatos.BitByte = 0;             InfoDatos.currByte = 0;

  Fuente_Amplia( buffer, &InfoDatos );
 }
 LineaActual = ( LineaActual++ ) % NUM_LINEAS;
}


 /**************************************************************************\
|*                                                                          *|
|*  RatonVentas                                                             *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Funci�n soporte para el control del raton, que ademas se    *|
|*              encarga de mostrar el letrero digital y el protector de     *|
|*              pantalla.                                                   *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Linea en la que se inserta y posici�n f�sica, y columna        *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
int far RatonVentas(void)
{
 char Que;

 clock_t start, end, start2;

 struct time first;
 struct time old;

 start2 = start = clock();

  activa_raton();

  union REGS io;
  io.x.ax = 3;

  do{
      end = clock();

      if ( ( (end - start2) / (CLK_TCK /*/ 4*/) ) >= 0.001 )
      {
        start2 = end;
        old = first;
        gettime( &first );
        if ( ( old.ti_min != first.ti_min || old.ti_hour != first.ti_hour ) )
          sprintf( Buffer, "Hoy es %02d-%02d-%02d y son las %02d:%02d   (Cualquier consulta en: http://www.arrakis.es/~infomundo/JD ;-)", FechaGestionActual.da_day, FechaGestionActual.da_mon, FechaGestionActual.da_year, (int)first.ti_hour, (int)first.ti_min );

        Fuente_Amplia( Buffer, &MensajesLn );
      }

      int86(0x33, &io, &io);    // lee posici�n y estados del bot�n
//      boton_izq = io.x.bx & 1;
//      boton_der = (io.x.bx >> 1) & 1;
      x_raton = io.x.cx;
      y_raton = io.x.dx;

  }while( (io.x.bx & 1) == 0 && ((io.x.bx >> 1) & 1) == 0 && !kbhit() );


  /////////////////////////////////////////
  //     RETURN    Derecho   Izquierdo   //
  //                                     //
  //       0         0           0       //
  //       1         1           0       //
  //       2         0           1       //
  //       3         1           1       //
  //                                     //
  /////////////////////////////////////////


  if ( ((io.x.bx >> 1) & 1)==0 && (io.x.bx & 1)==0 ) Que = 0;
  if ( ((io.x.bx >> 1) & 1)==1 && (io.x.bx & 1)==0 ) Que = 1;
  if ( ((io.x.bx >> 1) & 1)==0 && (io.x.bx & 1)==1 ) Que = 2;
  if ( ((io.x.bx >> 1) & 1)==1 && (io.x.bx & 1)==1 ) Que = 3;

  desactiva_raton();
  return Que;
}




void Creditos(void)
{

 desactiva_raton();

 // Cambiamos a 320x200
 IntVect = OFF;


 restorecrtmode();
 asm    mov al, 0x13
 asm    mov ah, 0x00
 asm    int 0x10

 //
 MuestraImagen( "SYSTM\\alumc.PCX" );
 while( !kbhit() );
 while(  kbhit() ) getch();

 // Cambiamos a 640x480
 asm    mov al, 0x03
 asm    mov ah, 0x00
 asm    int 0x10

 setgraphmode( 2 );
 inicializa_raton_grafico( 0, 0, 639, 479 );
 //////////
 setrgbpalette(EGA_WHITE,     56, 58, 59 );
 setrgbpalette(EGA_LIGHTGRAY, 30, 37, 43 );
 setrgbpalette(EGA_DARKGRAY,   24, 27, 30 );

 IntVect = ON;

}


#define RES_X  320
#define RES_Y  200
 /**************************************************************************\
|*                                                                          *|
|*  MuestraImagen                                                           *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Descomprime y copia a la pagina indicada un PCX             *|
|*                                                                          *|
|*  Entradas: nombre de la imagen                                           *|
|*                                                                          *|
|*                                                                          *|
|*  Salidas:  OK    Todo ha ido bien                                        *|
|*            ERROR Algo va mal                                             *|
|*                                                                          *|
 \**************************************************************************/
int MuestraImagen( char *file )
{
  int alto, ancho, contador;
  unsigned char byte;
  FILE *fp;

  CargaPaleta( file );

  if ( (fp = fopen( file,"rb")) != NULL )
  {
          // Saltamos la cabecera
          fseek( fp, 128, SEEK_SET );

          for(alto=0; alto<RES_Y; alto++)
          {
            for(ancho=0; ancho<RES_X; )
            {
              byte=getc(fp);
              if(byte<=0xC0)
              {
//                putpixel (ancho, alto, byte);
                VGARam[ ancho + alto*320 ] = byte;
                ancho++;
              } else {
                contador=byte&0x3F; byte=getc(fp);
                for(; contador>0; contador--)
                {
//                  putpixel (ancho, alto, byte);
                VGARam[ ancho + alto*320 ] = byte;
                  ancho++;
                }
              }
            }
          }

          fclose(fp);

  } else return ERROR;



  return OK;
}



 /**************************************************************************\
|*                                                                          *|
|*  CargaPaleta                                                             *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Carga la paleta con los colores por defecto                 *|
|*                                                                          *|
|*                                                                          *|
|*  Entradas: achivo PCX de donde cargar la paleta                          *|
|*                                                                          *|
|*  Salidas:  OK    Todo ha ido bien                                        *|
|*            ERROR Algo va mal                                             *|
|*                                                                          *|
 \**************************************************************************/
int CargaPaleta(char *file )
{
 int index;
 FILE *fp;

 if ( (fp=fopen( file, "rb" ) ) == NULL )
                                                  return ERROR;

 if ( fseek( fp, -768L, SEEK_END ) == 0 )
 {
    for (index=0; index<256; index++)
    {
    // get the red component
    // get the green component
    // get the blue component
    // set components
    Palette256[index][0] = (getc(fp) >> 2);//*64 / 256;
    Palette256[index][1] = (getc(fp) >> 2);//*64 / 256;
    Palette256[index][2] = (getc(fp) >> 2);//*64 / 256;
    } // end for index

 }
 setvgapalette256( &Palette256 );


 fclose( fp );
 return OK;
}

/* Setvgapalette256 sets the entire 256 color palette */
/* PalBuf contains RGB values for all 256 colors      */
/* R,G,B values range from 0 to 63	              */
/* Usage:					      */
/*  DacPalette256 dac256;			      */
/*						      */
/* setvgapalette256(&dac256);			      */
void setvgapalette256(DacPalette256 *PalBuf)
{
  struct REGPACK reg;

  reg.r_ax = 0x1012;
  reg.r_bx = 0;
  reg.r_cx = 256;
  reg.r_es = FP_SEG(PalBuf);
  reg.r_dx = FP_OFF(PalBuf);
  intr(0x10,&reg);
}


int Comprueba_Impresora(void)
{
 return ( biosprint(2, 0, 0) & 0x80 );
}


void ImprimeEtiquetas(void)
{
 long i; char pag, buffer[80];
 int Center, lineas = 2, CMen;
 int PagInicio, PagFin;

 char Mensaje[][50] = { "Para interrumpir", "pulse una tecla" };

 OptenPaginasIniFin( &PagInicio, &PagFin, BAlum.Registros() );

 FILE *file_out;

 if ( !Config.Impresora.Printer )
 {
   if ( ( file_out = fopen( Config.Impresora.PrintTo, "w" ) ) == NULL )
                                                            return;
 } else {
      file_out = stdprn;

      if ( !Optar( 1, "� Prepare la impresora !", "Prepare y encienda la", "impresora, y pulse ACEPTAR", "cuando este lista...", NULL ) )
           return;

      while ( !Comprueba_Impresora() )
      {
       if ( !Optar( 1, "ERROR IMPRESORA", "Encienda la impresora", "y pulse ACEPTAR para continuar", NULL ) )
                                                                            return;
      }
 }

                    sprintf( buffer, "datos\\alum.dbf" );
                    if ( !access( buffer, 0 ) )
                     if ( BAlum.AbrirReg( buffer, sizeof( AntiguosAlumnos ) ) == ERROR )
                                                             Error(0x01, BAlum.cError);


//////////////////////////////////////////////////////////////

  Imprime_Estaticos( 100, "systm\\alum.img" );

  settextstyle( SMALL_FONT, HORIZ_DIR, 6 );

  setcolor( 63 );  outtextxy( 172, 165, "Imprimiendo Etiquetas" );
  setcolor( EGA_RED );

  for ( CMen = 0; CMen < lineas; CMen++ )
  {
   Center= (296 - textwidth( Mensaje[CMen] ) ) / 2;
   outtextxy( 172+Center, 200+20*CMen, Mensaje[CMen] );
  }
//////////////////////////////////////////////////////////////


  pag = 0;
  PagInicio--;
  for ( i=PagInicio; i < BAlum.Registros() && i < PagFin; i++, pag++ )
  {

   if ( pag >= 3*12 )
   {
    if ( !Optar( 1, "NUEVA PAGINA", "Por favor, realinee la pagina", "y pulse una tecla", NULL ) )
                 return;
    pag = 0;
   }

   BAlum.LeeReg( (void *)&SAlum, i );
//   do { BAlum.LeeReg( (void *)&SAlum, i ); i++; } while( !SAlum.Varios.Notific && i < BAlum.Registros() );
//   do { BAlum.LeeReg( (void *)&BHtmp,     i ); i++; } while( !BHtmp.Varios.Notific && i < BAlum.Registros() );
   fprintf( file_out, "\n\r" );
   fprintf( file_out, "N� Alumno:  %4ld", SAlum.CodigoR );
   fprintf( file_out, "\n\r" );
   fprintf( file_out, "\n\r" );
   sprintf( buffer, "%s %s", SAlum.Nombre, SAlum.Apellidos );
   buffer[32]='\0';
   fprintf( file_out, "%-32s   ", buffer );

   fprintf( file_out, "\n\r" );

   sprintf( buffer, "%s", SAlum.Direccion );
   fprintf( file_out, "%-32s   ", buffer );

   fprintf( file_out, "\n\r" );
   fprintf( file_out, "\n\r" );

   sprintf( buffer, "%s (%s)", SAlum.Localidad, SAlum.Provincia );
   fprintf( file_out, "%-32s   ", buffer );

   fprintf( file_out, "\n\r" );
   fprintf( file_out, "C.P. %5ld", SAlum.CodPostal );
   fprintf( file_out, "\n\r" );
   fprintf( file_out, "\n\r" );

/*
   fprintf( file_out, "\n\r" );
   fprintf( file_out, "N� Alumno:  %4ld  %s                    N� de Alumno:  %4ld  %s", SAlum.NHno, (SAlum.Varios.CuotaFam ? "F" :" " ), BHtmp.NHno, (BHtmp.Varios.CuotaFam ? "F" :" " ) );
   fprintf( file_out, "\n\r" );
   sprintf( buffer, "%s %s %s", SAlum.Nombre, SAlum.Apellido1, SAlum.Apellido2 );
   fprintf( file_out, "%-37s   ", buffer );
   sprintf( buffer, "%s %s %s", BHtmp.Nombre, BHtmp.Apellido1, BHtmp.Apellido2 );
   fprintf( file_out, "%-37s", buffer );

   fprintf( file_out, "\n\r" );

   sprintf( buffer, "%s%s%s%s%s", SAlum.Direccion, (SAlum.Num[0]=='\0')?"":",", SAlum.Num, (SAlum.Piso[0]=='\0')?"":",", SAlum.Piso );
   fprintf( file_out, "%-37s   ", buffer );
   sprintf( buffer, "%s%s%s%s%s", BHtmp.Direccion, (BHtmp.Num[0]=='\0')?"":",", BHtmp.Num, (BHtmp.Piso[0]=='\0')?"":",", BHtmp.Piso );
   fprintf( file_out, "%-37s", buffer );

   fprintf( file_out, "\n\r" );

   sprintf( buffer, "%s (%s)", SAlum.Localidad, SAlum.Provincia );
   fprintf( file_out, "%-37s   ", buffer );
   sprintf( buffer, "%s (%s)", BHtmp.Localidad, BHtmp.Provincia );
   fprintf( file_out, "%-37s", buffer );

   fprintf( file_out, "\n\r" );
   fprintf( file_out, "C.P. %5ld                              C.P. %5ld", SAlum.CodP, BHtmp.CodP );
   fprintf( file_out, "\n\r" );
*/

   if ( kbhit() )
   {
    getch();
    if ( Optar( 1, "CANCELAR IMPRESION ?", "Desea Cancelar la impresion", "el trabajo aun no ha concluido ?", NULL ) )
                                                                                  break ;
   }
  }

 BAlum.CerrarReg();
}

void OptenPaginasIniFin( int *Inicio, int *Fin, int NRegistros )
{
 void far *Imagen;
 char buffer[80];
 struct textsettingstype texttypeinfo;

 *Inicio = 1;
 *Fin    = NRegistros;


  Optar( ENCUADRE, "Rango de salida", NULL );

  settextstyle( SMALL_FONT, HORIZ_DIR, 6 );

  outtextxy( 175, 220,   "Ficha inicial:");
  outtextxy( 175, 260,   "Ficha final:");

  settextstyle( SMALL_FONT, HORIZ_DIR, 5 );
  sprintf( buffer, "%d", (*Inicio) );
  InputCadenaG(buffer, 0, 5, EGA_WHITE, EGA_BLUE, 320, 220, 460, 240 );
  (*Inicio) = atoi(buffer);
  if ( *Inicio < 0 ) *Inicio = 0;
  sprintf( buffer, "%d", (*Fin) );
  InputCadenaG(buffer, 0, 5, EGA_WHITE, EGA_BLUE, 320, 260, 460, 280 );
  (*Fin   ) = atoi(buffer);
  if ( *Fin > NRegistros ) *Fin = NRegistros;

  Optar( ENCUADRE, "Rango de salida", NULL );
}