#include <dos.h>
#include <mem.h>
#include <math.h>
#include <conio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <graphics.h>

//#include "alum_def.h"
//extern void Error( int code, char *MensajeError );


char *ptr_char;

char *VidRam = (char *)MK_FP( 0xA000, 0);
void far PutPixel(unsigned int x, unsigned int y, int c_elec );

typedef struct
 {
  int x, y;
  char ndigitos;
  char AX, AY;
  char C1, C2, C3;
 } p_graphics;

typedef struct
 {
  int x, y;             // Coordenadas iniciales de muestreo
  char ndigitos;        // n£mero de digitos a mostrar
  char AX, AY;          // factor de espaciado
  char C1, C2, C3;      // colores de fondo, texto, borde

  // Datos privados y uso interno exclusivamente
  unsigned int  Flen;   // longitud de la frase actual
  char BitByte;         // bit del byte por el que va en el recorrido
  char currByte;        // byte actual dentro de la frase

 } p_Ampliada;

int Numero_Digital( long numero,  p_graphics *ND );
void Fuente_Amplia( char *Frase, p_graphics *FA );


 /**************************************************************************\
|*                                                                          *|
|* Numero_Digital                                                           *|
|*                                                                          *|
|* Descripcion:                                                             *|
|*             Muestra un numero, con forma digital en pantalla,            *|
|*             escalandolo seg£n los factores indicados en p_graphics       *|
|*             ( 9 digitos como m ximo )                                    *|
|*                                                                          *|
|* Entradas:                                                                *|
|*             N£mero y estructura de muestreo                              *|
|*                                                                          *|
|* Salidas:    (ninguna)                                                    *|
|*                                                                          *|
 \**************************************************************************/
/*
int Numero_Digital( long numero,  p_graphics *ND )
{
// Son 9 digitos VARIABLES
//        0
//    _________     _________   _________   _________   _________   _________   _________
//   |\______ /|   |\______ /| |\______ /| |\______ /| |\______ /| |\______ /| |\______ /|
//   | |     | |   | |     | | | |     | | | |     | | | |     | | | |     | | | |     | |
//3  | |  1  | | 5 | |     | | | |     | | | |     | | | |     | | | |     | | | |     | |
//   | /-----\ |   | /-----\ | | /-----\ | | /-----\ | | /-----\ | | /-----\ | | /-----\ |
//   | \-----/ |   | \-----/ | | \-----/ | | \-----/ | | \-----/ | | \-----/ | | \-----/ |
//4  | |     | | 6 | |     | | | |     | | | |     | | | |     | | | |     | | | |     | |
//   | |_____| |   | |_____| | | |_____| | | |_____| | | |_____| | | |_____| | | |_____| |
//   |/_______\|   |/_______\| |/_______\| |/_______\| |/_______\| |/_______\| |/_______\|
//        2

 static char dnumero[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
 static char Dn[9]      =   {  0, 0, 0, 0, 0, 0, 0, 0, 0 };

 static char vez = 0;
 static p_graphics ND1;

 char dnum=0, i, j, digital;
 int punto[10];
 int CONST = 0;
 char DnTmp[2];
 char signo = 0;
 static old_signo = 0;


 // Si ha cambiado la posicion, el n§ de digitos, o el factor de escala
 // habr  que recalcularlo todo.
 if (
      ND1.x        != ND -> x          ||    ND1.y != ND -> y   ||
      ND1.ndigitos != ND -> ndigitos   ||
      ND1.AX       != ND -> AX         ||    ND1.AY != ND -> AY
    )
 {
   dnumero[0] = -1; dnumero[1] = -1; dnumero[2] = -1;
   dnumero[3] = -1; dnumero[4] = -1; dnumero[5] = -1;
   dnumero[6] = -1; dnumero[7] = -1; dnumero[8] = -1;

   Dn[0] = 0; Dn[1] = 0; Dn[2] = 0;
   Dn[3] = 0; Dn[4] = 0; Dn[5] = 0;
   Dn[6] = 0; Dn[7] = 0; Dn[8] = 0;

   //ndigitos1 = ndigitos;
   ND1 = *ND;
   vez = 0;
 }

 // Miramos el signo del n£mero
 if ( numero < 0 )
 {
  numero *= -1;
  signo = 1;
 }

 if ( signo != old_signo ) vez = 0;

 setcolor(ND -> C3);

 // Miro todas las cifras que componen el n£mero
 for( i=0; i < ND -> ndigitos; i++ )
  {
   dnum = numero % 10;
   digital = numero;
   numero /= 10;

   // Si el n£mero pintado con anterioridad es distinto al actual, lo dibujamos
   if ( dnumero[ ND -> ndigitos - 1 - i] != dnum || digital == 0 || vez == 0 )
    {
     // digital = dnumero[5 - i];
     dnumero[ND -> ndigitos - 1  - i] = dnum;
     //////// Esta parte del c¢digo imprime el digito en pantalla
     CONST = 12*ND -> AX*(ND -> ndigitos - 1  - i);
     DnTmp[1] = Dn[ND -> ndigitos - 1 -i];

     //  Antes de nada, eliminamos los cero a la izquierda
     if ( digital == 0 && i != 0  ) { Dn[ND -> ndigitos - 1 -i] = 0; dnumero[ND -> ndigitos - 1  - i] = -1; } else
     switch( dnum )
      {
       case 0:
              Dn[ND -> ndigitos - 1 -i] = 0x7D;      // 0111 1101
          break;
       case 1:
              Dn[ND -> ndigitos - 1 -i] = 0x60;      // 0110 0000
          break;
       case 2:
              Dn[ND -> ndigitos - 1 -i] = 0x37;      // 0011 0111
          break;
       case 3:
              Dn[ND -> ndigitos - 1 -i] = 0x67;      // 0110 0111
          break;
       case 4:
              Dn[ND -> ndigitos - 1 -i] = 0x6A;      // 0110 1010
          break;
       case 5:
              Dn[ND -> ndigitos - 1 -i] = 0x4F;      // 0100 1111
          break;
       case 6:
	      Dn[ND -> ndigitos - 1 -i] = 0x5F;      // 0101 1111
          break;
       case 7:
              Dn[ND -> ndigitos - 1 -i] = 0x61;      // 0110 0001
          break;
       case 8:
              Dn[ND -> ndigitos - 1 -i] = 0x7F;      // 0111 1111
          break;
       case 9:
              Dn[ND -> ndigitos - 1 -i] = 0x6F;      // 0110 1111
          break;
      }

      DnTmp[0] = Dn[ND -> ndigitos - 1 -i];
     for( j=0; j<7; j++ )
      {
       if ( DnTmp[1]%2 != DnTmp[0]%2 || vez == 0 )
       {
        if ( DnTmp[0]%2 )
         setfillstyle(SOLID_FILL, ND -> C1);
	else
	 setfillstyle(SOLID_FILL, ND -> C2);

	switch( j )
	 {
	  case 0:
                 punto[0] =  0*ND -> AX + CONST + ND -> x;   punto[1] =  0*ND -> AY + ND -> y;
                 punto[2] = 10*ND -> AX + CONST + ND -> x;   punto[3] =  0*ND -> AY + ND -> y;
                 punto[4] =  8*ND -> AX + CONST + ND -> x;   punto[5] =  2*ND -> AY + ND -> y;
                 punto[6] =  2*ND -> AX + CONST + ND -> x;   punto[7] =  2*ND -> AY + ND -> y;
                 punto[8] =  0*ND -> AX + CONST + ND -> x;   punto[9] =  0*ND -> AY + ND -> y;
                 fillpoly( 5, punto );
               break;
          case 3:
                 punto[0] =  0*ND -> AX + CONST + ND -> x;   punto[1] =  0*ND -> AY + ND -> y;
                 punto[2] =  2*ND -> AX + CONST + ND -> x;   punto[3] =  2*ND -> AY + ND -> y;
		 punto[4] =  2*ND -> AX + CONST + ND -> x;   punto[5] =  9*ND -> AY + ND -> y;
                 punto[6] =  1*ND -> AX + CONST + ND -> x;   punto[7] = 10*ND -> AY + ND -> y;
                 punto[8] =  0*ND -> AX + CONST + ND -> x;   punto[9] =  9*ND -> AY + ND -> y;
                 fillpoly( 5, punto );
	      break;
          case 5:
                 punto[0] = 10*ND -> AX + CONST + ND -> x;   punto[1] =  0*ND -> AY + ND -> y;
                 punto[2] = 10*ND -> AX + CONST + ND -> x;   punto[3] =  9*ND -> AY + ND -> y;
                 punto[4] =  9*ND -> AX + CONST + ND -> x;   punto[5] = 10*ND -> AY + ND -> y;
		 punto[6] =  8*ND -> AX + CONST + ND -> x;   punto[7] =  9*ND -> AY + ND -> y;
                 punto[8] =  8*ND -> AX + CONST + ND -> x;   punto[9] =  2*ND -> AY + ND -> y;
                 fillpoly( 5, punto );
               break;
          case 1:
                 int punto1[12];
                 punto1[0] =  1*ND -> AX + CONST + ND -> x;   punto1[1] = 10*ND -> AY + ND -> y;
                 punto1[2] =  2*ND -> AX + CONST + ND -> x;   punto1[3] =  9*ND -> AY + ND -> y;
                 punto1[4] =  8*ND -> AX + CONST + ND -> x;   punto1[5] =  9*ND -> AY + ND -> y;
                 punto1[6] =  9*ND -> AX + CONST + ND -> x;   punto1[7] = 10*ND -> AY + ND -> y;
                 punto1[8] =  8*ND -> AX + CONST + ND -> x;   punto1[9] = 11*ND -> AY + ND -> y;
		 punto1[10] = 2*ND -> AX + CONST + ND -> x;   punto1[11] = 11*ND -> AY +ND -> y;
                 fillpoly( 6, punto1 );
               break;
          case 4:
		 punto[0] =  1*ND -> AX + CONST + ND -> x;   punto[1] = 10*ND -> AY + ND -> y;
                 punto[2] =  2*ND -> AX + CONST + ND -> x;   punto[3] = 11*ND -> AY + ND -> y;
                 punto[4] =  2*ND -> AX + CONST + ND -> x;   punto[5] = 18*ND -> AY + ND -> y;
                 punto[6] =  0*ND -> AX + CONST + ND -> x;   punto[7] = 20*ND -> AY + ND -> y;
                 punto[8] =  0*ND -> AX + CONST + ND -> x;   punto[9] = 11*ND -> AY + ND -> y;
		 fillpoly( 5, punto );
               break;
          case 6:
                 punto[0] =  9*ND -> AX + CONST + ND -> x;   punto[1] = 10*ND -> AY + ND -> y;
                 punto[2] = 10*ND -> AX + CONST + ND -> x;   punto[3] = 11*ND -> AY + ND -> y;
                 punto[4] = 10*ND -> AX + CONST + ND -> x;   punto[5] = 20*ND -> AY + ND -> y;
                 punto[6] =  8*ND -> AX + CONST + ND -> x;   punto[7] = 18*ND -> AY + ND -> y;
                 punto[8] =  8*ND -> AX + CONST + ND -> x;   punto[9] = 11*ND -> AY + ND -> y;
                 fillpoly( 5, punto );
               break;
          case 2:
		 punto[0] =  2*ND -> AX + CONST + ND -> x;   punto[1] = 18*ND -> AY + ND -> y;
                 punto[2] =  8*ND -> AX + CONST + ND -> x;   punto[3] = 18*ND -> AY + ND -> y;
                 punto[4] = 10*ND -> AX + CONST + ND -> x;   punto[5] = 20*ND -> AY + ND -> y;
		 punto[6] =  0*ND -> AX + CONST + ND -> x;   punto[7] = 20*ND -> AY + ND -> y;
		 punto[8] =  2*ND -> AX + CONST + ND -> x;   punto[9] = 18*ND -> AY + ND -> y;
                 fillpoly( 5, punto );
               break;
          default:
               break;
	 }
       }
        DnTmp[0] /= 2;
        DnTmp[1] /= 2;
      }
    }
  }

 if ( signo != old_signo )
  {

       if ( (old_signo = signo) == 1 )
       {
        setfillstyle(SOLID_FILL, ND -> C1);

        int punto1[12];
        punto1[0] =  1*ND -> AX + ND -> x;   punto1[1] = 10*ND -> AY + ND -> y;
        punto1[2] =  2*ND -> AX + ND -> x;   punto1[3] =  9*ND -> AY + ND -> y;
        punto1[4] =  8*ND -> AX + ND -> x;   punto1[5] =  9*ND -> AY + ND -> y;
        punto1[6] =  9*ND -> AX + ND -> x;   punto1[7] = 10*ND -> AY + ND -> y;
        punto1[8] =  8*ND -> AX + ND -> x;   punto1[9] = 11*ND -> AY + ND -> y;
	punto1[10] = 2*ND -> AX + ND -> x;   punto1[11] = 11*ND -> AY +ND -> y;
        fillpoly( 6, punto1 );
       }
  }

 vez = 1;
 return 0;
}
*/


////////////////////////////////////////////////////////////////////////////////////
void far PutPixel(unsigned int x, unsigned int y, int c_elec )
{
  if ( x < 320 && y < 200 )
             *(VidRam + (x + y*320) ) = c_elec;
}


void LeeFuentes(char *file)
{
FILE *fich;
	/* Reservamos 4 Kb. para cargar la fuente en memoria */

	/* Abrimos el fichero de la fuente */

        if ((fich=fopen(file,"rb"))==NULL) {
                printf("\a\nArchivo %s no encontrado.\n",file);
//		Error(0, "No se encuentra el archivo de fuentes");
	}

	fseek(fich, SEEK_SET, 0);	/* Nos colocamos al principio del fichero     */
        fread(ptr_char,1,4096,fich);      /* Cargamos en memoria 4096 bytes del fichero */
	fclose(fich);					/* Cerramos el fichero 								 */
}





  /*


#define TAMx 8
#define TAMy 8
void Fuente_Amplia( char *Frase, p_Ampliada far *FA )
{
 int  i, j, k;           // Variables de avance
 int  c_elec;            // Color en el momento de imprimir
 int  PosX, PosY;        // Posicion fisica final
 char LCaract;           // Caracter de linea a tratar

 if ( FA->Flen != _fstrlen( Frase ) ) // Reseteamos las variables de control interno
 {
  // Obtenemos la longitud de la frase. ( En d¡gitos )
  FA -> Flen = _fstrlen( Frase );
  // Contador de digito actual a cero
  FA -> BitByte  = 0;
  // Posicion dentro de la frase
  FA -> currByte = 0;
 }

 // Avance horizontal de bit's ( avance de digitos )
 for ( i = 0; i < ( TAMx * (FA -> ndigitos) ); i++ )
 {
  k = ( (unsigned char)Frase[ ( (i+FA->BitByte)/TAMx + FA -> currByte ) % FA->Flen ] ) << 4;
  LCaract = ( (char)0x01 << (7 - (i+FA->BitByte)%TAMx) );
  PosX = FA -> x + FA->AX   * i;         // Posicion f¡sica horizontal
  // Avance vertical de bit's
  for ( j = 0; j < TAMy; j ++ )
  {
    PosY = FA -> y + FA->AY * j;         // Posicion f¡sica vertical

    if ( ptr_char[ k + j ] & LCaract )
      c_elec = FA->C2;
    else
      c_elec = FA->C1;

    putpixel ( PosX, PosY, c_elec );
  }
 }
 // Tenemos en cuenta el avance dentro de la frase
 if ( ( FA -> BitByte ++ ) >= 7 )
 {
  FA -> BitByte = 0; FA -> currByte ++;
  if ( FA -> currByte >= FA -> Flen )
     FA -> currByte = 0;
 }

}

#undef TAMy
#undef TAMx
*/

#define TAMx  8
#define TAMy 16
void Fuente_Amplia3( char *Frase, p_Ampliada far *FA )
{
 int  i, j, k;           // Variables de avance
 int  c_elec;            // Color en el momento de imprimir
 int  PosX, PosY;        // Posicion fisica final
 char LCaract;           // Caracter de linea a tratar

 if ( FA->Flen != _fstrlen( Frase ) ) // Reseteamos las variables de control interno
 {
  // Obtenemos la longitud de la frase. ( En d¡gitos )
  FA -> Flen = _fstrlen( Frase );
  // Contador de digito actual a cero
  FA -> BitByte  = 0;
  // Posicion dentro de la frase
  FA -> currByte = 0;
 }

 // Avance horizontal de bit's ( avance de digitos )
 for ( i = 0; i < ( TAMx * (FA -> ndigitos) ); i++ )
 {
  k = ( (unsigned char)Frase[ ( (i+FA->BitByte)/TAMx + FA -> currByte ) % FA->Flen ] ) << 4;
  LCaract = ( (char)0x01 << (7 - (i+FA->BitByte)%TAMx) );
  PosX = FA -> x + FA->AX   * i;         // Posicion f¡sica horizontal
  // Avance vertical de bit's
  for ( j = 0; j < TAMy; j ++ )
  {
    PosY = FA -> y + FA->AY * j;         // Posicion f¡sica vertical

    if ( ptr_char[ k + j ] & LCaract )
      c_elec = FA->C2;
    else
      c_elec = FA->C1;

    PutPixel ( PosX, PosY, c_elec );
  }
 }
 // Tenemos en cuenta el avance dentro de la frase
 if ( ( FA -> BitByte ++ ) >= 7 )
 {
  FA -> BitByte = 0; FA -> currByte ++;
  if ( FA -> currByte >= FA -> Flen )
     FA -> currByte = 0;
 }

}
#undef TAMy
#undef TAMx

/////ÜÜ/////////////////////////////////////////////////////////////////////////////
////Û/////////////////////////////////////////////////////////////////////////////////
/////ßÜ/////Ü///////////////////////////////////////////////////////////////////////
//////ß///Ü////ß/Ü//////////////////////////////////////////////////////////////////
///////ß/Ü///Ü//////////////////////////////////////////////////////////////////////
////////Ü//ß////ß///////////////////////////////////////////////////////////////////
/////////ß////Ü/////////////////////////////////////////////////////////////////////
///////////ß////////////////////////////////////////////////////////////////////////
#define TAMx  8
#define TAMy  7//16
void FuenteAmplia( char *Frase, p_Ampliada far *FA )
{
 int  i, j, k;           // Variables de avance
 int  c_elec;            // Color en el momento de imprimir
 int  PosX, PosY;        // Posicion fisica final
 int  LCaract;           // Caracter de linea a tratar

 if ( FA->C3 == -1 || FA->Flen != _fstrlen( Frase ) )              // Reseteamos las variables de control interno
 {
  // Obtenemos la longitud de la frase. ( En d¡gitos )
  FA -> Flen = _fstrlen( Frase );
  // Contador de digito actual a cero
  FA -> BitByte  = 0;
  // Posicion dentro de la frase
  FA -> currByte = 0;
 }

 // Avance horizontal de bit's ( avance de digitos )
 for ( i = 0; i < ( TAMx * (FA -> ndigitos) ); i++ )
 {
  k = ( (unsigned char)Frase[ ( (i+FA->BitByte)/TAMx + FA -> currByte ) % FA->Flen ] ) << 4;
  LCaract = ( (char)0x01 << (7 - (i+FA->BitByte)%TAMx) );
  PosX = FA -> x + FA->AX   * i;         // Posicion f¡sica horizontal
  // Avance vertical de bit's
  for ( j = 0; j < TAMy; j ++ )
  {
    PosY = FA -> y + FA->AY * j;         // Posicion f¡sica vertical

    if ( ptr_char[ k + j ] & LCaract )
      c_elec = FA->C2;
    else
      c_elec = FA->C1;

    PutPixel ( PosX, PosY, c_elec );
  }
 }
 // Tenemos en cuenta el avance dentro de la frase
 if ( ( FA -> BitByte ++ ) >= 7 )
 {
  FA -> BitByte = 0; FA -> currByte ++;
  if ( FA -> currByte >= FA -> Flen )
     FA -> currByte = 0;
 }

}
#undef TAMy
#undef TAMx



void main(void)
{
  p_Ampliada P;
  int ok = 0;
  unsigned delayT;

  P.x = P.y = 0;
  P.ndigitos = 1;
  P.AX = P.AY = 1;
  P.C1 = EGA_DARKGRAY;
  P.C2 = EGA_RED;

  if ( ( ptr_char = new char [4096] ) == NULL )
   return;

  // Cambiamos a 320x200
  asm    mov al, 0x13
  asm    mov ah, 0x00
  asm    int 0x10


 LeeFuentes("leds.fnt");

 ok = 0;
 delayT = 1;
 while( !ok )
 {
   if ( kbhit() )
   {
    switch( getch() )
    {
     case 0:
      switch( getch() )
      {
       case 75:
               P.AX--; if ( P.AX < 1 ) P.AX = 1;
               break;
       case 77:
               P.AX++; if ( P.AX > 40 ) P.AX = 40;
               break;
       case 72:
               P.AY--; if ( P.AY < 1 ) P.AY = 1;
               break;
       case 80:
               P.AY++; if ( P.AY > 40 ) P.AY = 40;
               break;
      }
      break;
     case '1':
              P.ndigitos--; if ( P.ndigitos < 1 ) P.ndigitos = 1;
              break;
     case '2':
              P.ndigitos++; if ( P.ndigitos > 40 ) P.ndigitos = 40;
              break;
     case '3':
              delayT--; if ( delayT < 1 ) delayT = 1;
              break;
     case '4':
              delayT++; if ( delayT > 40 ) delayT = 40;
              break;
     case  27:
              ok = 1;
              break;
    }
    memset( VidRam, 0, 64000 );
   }
   FuenteAmplia( "Esto es una prueba para ver la relaci¢n del texto y el tama¤o de la muestra", &P );
   delay(delayT);
 };

 // Volvemos al modo texto
 asm    mov al, 0x03
 asm    mov ah, 0x00
 asm    int 0x10

 delete [] ptr_char;

}