#include <io.h>
#include <alloc.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <graphics.h>

#include "c:\program\src_dos\libs\make_bot\make_bot.h"
#include "c:\program\src_dos\libs\bdatos\bdatos.hh"
#include "tpv_def.h"

#define NLINEAS_CMP 15
#define NLINEAS_PROVcmp   9

#define NORMAL     0
#define BARRAS     1

BDatos  BCmp;                  // Base de datos de Compras
COMPRAS SCmp;                  // Estructura de referencias

/*
BDatos   BVentProv;            // Compras por proveedor
CMP_PROV SVentProv;            // Ventas de proveedores
*/
                               // Dia y mes actual para la gestion
char DiaActual, MesActual;
long RegCompras[31 + 2];       // Indice para cado uno de los dias del mes + 2

extern char EmpresaActual[9];  // Empresa a la que se le realizan las gestiones

char AjusteCalendario;         // Ajuste para los dias del calendario
char DiasMes;                  // Dias que tiene el mes actual

extern BDatos BRef;            // Base de datos de Referencias
extern INFO_PRODUCTOS SRef;    // Estructura de referencias
                               // Para guardar las posiciones de los c�digos
BUSQUEDA_REF far *BusquedaRef;

extern BDatos BProv;           // Base de datos de Proveedores
extern INFO_PROVEEDORES SProv; // Estructura de Proveedores

char BusquedaDirecta;          // Tipo de busqueda en Referencias

char NomProveedor[80];         // Nombre del proveedor ( Datos Temporales )

 /*************************************\
|                                       |
|      Parte Principal del M�dulo       |
|                                       |
 \*************************************/
long PosicionDia( char Dia );
void MuestraDatosCmp( long RowStart );
void MuestraAyudaCmp( char columna );
void CmpNuevoRegistro( COMPRAS *MSCmp );
void EditItemCmp( char columna, int linea );
void SeleccionaMesCompras( int NivelAcceso );
void ManipulaIndiceDia( char Dia, char Accion );
void MuestraCmp( char columna, int linea, char como );
void ObtenCoordenadasCmp( char columna, char linea, int *X0, int *Y0, int *X1, int *Y1 );

extern long ActualizaStock( int Cantidad, int VentaCompra, char ComprasVentas );

 /*************************************\
|                                       |
|     Parte Secundaria del M�dulo       |
|                                       |
|    Secci�n de busqueda de compras     |
|                                       |
 \*************************************/
int  Match_Cmp( COMPRAS A, COMPRAS B );
int  ObtenMatchCmp( COMPRAS *MCmp, int *MesDia );
void EditMatchCmp( char Row, COMPRAS * MCmp, int *MesDia );
void MatchDrawCmp( char Row, COMPRAS MCmp, char como, int MesDia );
void BuscaCmp( char TipoBusqueda, char *CurrRow, long *CurrCmp, int NivelAcceso );
void ObtenCoordenadasMatchCmp( char Row, int *X0, int *Y0, int *X1, int *Y1 );

 /*************************************\
|                                       |
|       Parte Tercera del M�dulo        |
|                                       |
|   Secci�n para cargar los elementos   |
|                                       |
 \*************************************/
void ImprimeCompras( char como );
void MuestraImpresionesCmp( void );
void ImprimeCabeceraCmp( char como, FILE *file_out );

 /*************************************\
|                                       |
|        Parte Cuarta del M�dulo        |
|                                       |
|   Secci�n para cargar los elementos   |
|                                       |
 \*************************************/
int  CargaProductos( void );
void CargaProveedores( void );
/*
void ActualizaProv( long CodigoProv );
*/
int  MatchProveedor( long NProveedor );
int  MatchRef( unsigned long Codigo, char NormalBarras );

 /*************************************\
|                                       |
|        Parte Quinta del M�dulo        |
|                                       |
|      Utilidades para el calendario    |
|                                       |
 \*************************************/
void RellenaCalendario( int IncX, int IncY );
void MarcaDiaActual( int Sec, int Boton, char como );
extern int  P_Sec(int numero);

 /*************************************\
|                                       |
|         Parte Sexta del M�dulo        |
|                                       |
|    Edicion a�rea de los proveedores   |
|                                       |
 \*************************************/
void DespliegaProveedoresCmp( int Row );
void ProvNuevoRegistro( INFO_PROVEEDORES *NSProv );
void DuplicaBaseProveedores(void);

 /*************************************\
|                                       |
|        Parte Setima del M�dulo        |
|                                       |
|     Despliegue de los proveedores     |
|                                       |
 \*************************************/
void PreparaDespliege( int NuevaY1 );
void DespliegaProveedoresCmp( int Row );
void MuestraDatosProvCmp( long RowStart, int RowCmp );
void MuestraProvCmp( int linea, char como, int RowCmp );
void ObtenCoordenadasProvCmp( int RowCmp, char linea, int *X0, int *Y0, int *X1, int *Y1 );



//  ���������������������������������������������������������������������
// �                     Parte principal del m�dulo                       �
//  ���������������������������������������������������������������������


 /**************************************************************************\
|*                                                                          *|
|*  ComprasDiarias                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Gestiona las compras diarias que se realizan                *|
|*              ( Solo se muestran rio...                                   *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void ComprasDiarias( int NivelAcceso )
{
 char ok = 0;
 int BPush, key;

 char oldCol = -1;
 char CurrRow;         // Linea sobre la que estamos
 char CurrCol;         // Columna sobre la que estamos
 long CurrCmp;         // Producto sobre el que estamos posicionados a golpes

 // Actualizasmos el mes y dia actual en curso
 DiaActual = FechaGestionActual.da_day;
 MesActual = FechaGestionActual.da_mon;

 // Rellenamos la pantalla con un fondo atractivo...
 setfillstyle( Config.FillBgS, Config.FillBgC ); bar( 0, 0, 640, 480 );
 Imprime_Estaticos( 40, "systm\\Tpv.img");     // Imprime botones estaticos 'Seccion 40'

 // Inicializa el tratamiento de proveedores para las compras
 CargaProveedores();

/*
 // Inicializa las compras por proveedor
 sprintf( buffer, "datos\\%s\\cmp_prv.%03d", NEmpresa, ( FechaGestionActual.da_year - (FechaGestionActual.da_year/1000)*1000 );
 if ( BVentProv.AbrirReg( buffer, sizeof( CMP_PROV ) ) == ERROR )
                                                             Error(0x01, BVentProv.cError );
*/

 // Inicializa un indice r�pido para encontrar a los productos por su c�digo
 if ( CargaProductos() != OK )
 {
  Optar( 0, "Error de Gestion", "No se pueden realizar compras", "sin que existan productos", "que puedan ser comprados", NULL );
  return;
 }

 // Abre el archivo coreccto y se posiciona en el dia
 // actual de gestion...
 SeleccionaMesCompras( NivelAcceso );

 // Nos posicionamos en el ultimo registro del dia actual
 CurrRow = 5;                         CurrCmp = RegCompras[ DiaActual ] - 5;
 if ( CurrCmp < 0 ) CurrCmp = 0; else
 while ( CurrCmp > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrCmp--;
 while ( CurrRow > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrRow--;

 // Mostramos datos hasta que se nos acabe la pantalla
 MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );

 // Leemos el registro sobre el que estamos posicionados
 if ( BCmp.LeeReg( (void *)&SCmp, CurrRow + CurrCmp + PosicionDia( DiaActual ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
 CurrCol = 0;

 do {
      if ( CurrCol != oldCol )
      {
       oldCol = CurrCol;       MuestraAyudaCmp( CurrCol );
      }

      MuestraCmp( CurrCol, CurrRow, INTENSO );
      BPush = Comprueba_Secuencia( 2, NULL );
      MuestraCmp( CurrCol, CurrRow, NORMAL  );

      switch ( BPush )
      {
       case  0:				  // No se pulso ningun BOTON
	       while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
               // Si se esta echando un vistazo general har� falta el calendario
               if ( NivelAcceso == TOTAL )
               {
                switch ( BPush = ReComprueba_Secuencia( 4 ) )
                {
                 case  0:
                 case -2:
                 case -1:
                         while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
                         break;
                 // Retrocede un mes
                 case 43:
                         if ( MesActual > 1 )
                         {
                          MarcaDiaActual( 4, DiaActual + AjusteCalendario, NORMAL );
                          MesActual--; DiaActual = 1;
                          SeleccionaMesCompras( NivelAcceso );

                          // Nos posicionamos en el ultimo registro del dia actual
                          CurrRow = 5;                         CurrCmp = RegCompras[ DiaActual ] - 5;
                          if ( CurrCmp < 0 ) CurrCmp = 0; else
                          while ( CurrCmp > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrCmp--;
                          while ( CurrRow > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrRow--;

                          // Mostramos datos hasta que se nos acabe la pantalla
                          MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                          if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                         }
                         break;
                 // Avanza un mes
                 case 44:
                         if ( MesActual < 12 )
                         {
                          MarcaDiaActual( 4, DiaActual + AjusteCalendario, NORMAL );
                          MesActual++; DiaActual = 1;
                          SeleccionaMesCompras( NivelAcceso );

                          // Nos posicionamos en el ultimo registro del dia actual
                          CurrRow = 5;                         CurrCmp = RegCompras[ DiaActual ] - 5;
                          if ( CurrCmp < 0 ) CurrCmp = 0; else
                          while ( CurrCmp > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrCmp--;
                          while ( CurrRow > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrRow--;

                          // Mostramos datos hasta que se nos acabe la pantalla
                          MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                          if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                         }
                         break;
                 default:
                         if ( ( BPush - AjusteCalendario ) > 0 && ( BPush - AjusteCalendario ) <= DiasMes )
                         {
                           MarcaDiaActual( 4, DiaActual + AjusteCalendario, NORMAL );

                           DiaActual = BPush - AjusteCalendario;

                           MarcaDiaActual( 4, DiaActual + AjusteCalendario, INTENSO );

                           // Marcamos el dia y reconfiguramos todos los par�metros
                           // para dicho dia...

                           // Mostramos datos hasta que se nos acabe la pantalla
                           // para el dia dado.

                           // Nos posicionamos en el ultimo registro del dia actual
                           CurrRow = 5;                         CurrCmp = RegCompras[ DiaActual ] - 5;
                           if ( CurrCmp < 0 ) CurrCmp = 0; else
                            while ( CurrCmp > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrCmp--;
                            while ( CurrRow > 0 && ( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] ) ) CurrRow--;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                           if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                         }
                         Anclar_Raton();
                         break;
                }
               }
	       break;
       case -2:				  // Hay una tecla normal en BUFFER
            if ( VisualMode == OK )
            {
             while( kbhit() ) getch();
            } else {

               if ( ( key = getch() ) != 13 && key != 27 )
                                                     ungetch( key );

               // Descontamos del Stock ( Compra incorrecta )
               if ( ( CurrCol == 0 || CurrCol == 2 ) )
               {

                if ( MatchRef( SCmp.CodigoR, NORMAL ) == OK )
                {
                 ActualizaStock( SCmp.Cantidad*SRef.CantUnitaria, -1, COMPRA );
                } else {
                 SCmp.PrecioCosto = SCmp.PrecioCosto /*/ SCmp.Cantidad*/;
                }
               }
/*
               // Le descontamos al proveedor esa, compra...
               if ( ActualizaProv( SCmp.CodigoProveedor ) == OK )
               {
                 SVenProv.Compras[MesActual-1][DiaActual-1] -= SCmp.Cantidad*SCmp.PrecioCosto;
                 if ( BVenProv.EscribeReg( (void *)&SVenProv, BVenProv.RegActual() ) == ERROR )
                                                                                 Error(0x01, BVenProv.cError );
               }
*/

               if ( MatchProveedor( SCmp.CodigoProveedor ) == OK )
               {
                   SProv.Compras[MesActual-1][0/*DiaActual-1*/] -= SCmp.PrecioCosto/**SCmp.Cantidad*SRef.CantUnitaria*/;
                   if ( BProv.EscribeReg( (void *)&SProv, BProv.RegActual() ) == ERROR )
                                                                                 Error(0x01, BProv.cError );
               }

               EditItemCmp( CurrCol, CurrRow );
/*
               // Le a�adimos las compras a ese proveedor
               if ( ActualizaProv( SCmp.CodigoProveedor ) == OK )
               {

                 SVentProv.Compras[MesActual-1][DiaActual-1] += SCmp.Cantidad*SCmp.PrecioCosto;
                 if ( BVentProv.EscribeReg( (void *)&SVentProv, BVentProv.RegActual() ) == ERROR )
                                                                                 Error(0x01, BVentProv.cError );
               }
*/

               // Miramos si existe ese producto, en caso de haber editado
               // la columna 0 || 2, ( columna del c�digo, cantidad )
               if ( ( CurrCol == 0 || CurrCol == 2 ) )
               {
                 if ( SCmp.CodigoR != 0 && MatchRef( SCmp.CodigoR, NORMAL ) == OK )
                 {
                   // Ya se debe haber cargado la referencia, asi que podemos
                   // copiar los datos importantes y actualizar el stock
                   strcpy ( SCmp.Descripcion, SRef.Descripcion );

                   // Como estamos sobre la estrcutura, sumamos nuevo stock.
                   SCmp.PrecioCosto = ActualizaStock( SCmp.Cantidad*SRef.CantUnitaria, +1, COMPRA );

                   MuestraCmp( 1, CurrRow, NORMAL );
                   MuestraCmp( 4, CurrRow, NORMAL );

                 } else {
                   SCmp.CodigoR = 0;   SCmp.Descripcion[0] = '\0';
                   if ( SCmp.Cantidad <= 0 ) SCmp.Cantidad = 1;
                   SCmp.PrecioCosto = SCmp.PrecioCosto /** SCmp.Cantidad*/;
                   MuestraCmp( 1, CurrRow, NORMAL );
                   MuestraCmp( 4, CurrRow, NORMAL );
                 }


               }
               if ( BCmp.EscribeReg( (void *)&SCmp, (CurrRow + CurrCmp + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );

               // Esto solo se puede hacer cuando ya tenemos el PrecioCosto
               if ( MatchProveedor( SCmp.CodigoProveedor ) == OK )
               {
                 SProv.Compras[MesActual-1][0/*DiaActual-1*/] += SCmp.PrecioCosto/**SCmp.Cantidad*SRef.CantUnitaria*/;
                 if ( BProv.EscribeReg( (void *)&SProv, BProv.RegActual() ) == ERROR )
                                                                                 Error(0x01, BProv.cError );
               }

               // Avanzamos a la siguiente columna
               // Solo se permite acceder a Todo cuando el Codigo es 0
               MuestraCmp( CurrCol, CurrRow, NORMAL  );
               if ( ( SCmp.CodigoR == 0 && CurrCol != 0 ) || SCmp.CodigoR != 0 )
               {
                CurrCol++;
                if ( SCmp.CodigoR == 0 )
                {
                  if ( CurrCol > 4 ) CurrCol =  4;
                } else {
                  if ( CurrCol == 1 ) CurrCol = 2;
                  else
                  if ( CurrCol == 4 ) CurrCol = 0;
                }
               }
            }
               break;
       case -1:				  // Hay una tecla especial en BUFFER
               switch( getch() )
               {
                 // Flecha Izquierda
                 case  75:
                 case  15:
                       // Solo se permite acceder a Todo cuando el Codigo es 0
                       CurrCol--;
                       if ( SCmp.CodigoR == 0 )
                       {
                                              if ( CurrCol <  0 ) CurrCol = 4;

                       } else {
                           if ( CurrCol < 0 ) CurrCol = 3;
                           else
                           if ( CurrCol < 2 ) CurrCol = 0;
                       }
                       break;
                 // Flecha Derecha
                 case  77:
                 case   9:
                       // Solo se permite acceder a Todo cuando el Codigo es 0
                       CurrCol++;
                       if ( SCmp.CodigoR == 0 )
                       {
                                              if ( CurrCol > 4 ) CurrCol =  0;
                       } else {
                           if ( CurrCol == 1 ) CurrCol = 2;
                           else
                           if ( CurrCol == 4 ) CurrCol = 0;
                       }
                       break;
                 // Flecha Arriba
                 case  72:
                        if ( (CurrRow + CurrCmp) > 0 )
                        {
                         if ( ( CurrRow ) <= 0 )
                         {
                          CurrRow = NLINEAS_CMP - 1;          CurrCmp -= NLINEAS_CMP;
                          if ( CurrCmp < 0 ) CurrCmp = 0;

                          while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrRow > 0 ) CurrRow--;
                          while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrCmp > 0 ) CurrCmp++;

                          // Mostramos datos hasta que se nos acabe la pantalla
                          MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                         } else {
                          CurrRow --; if ( CurrRow < 0 ) CurrRow = 0;
                         }


                         if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
                        if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                        }
                       break;
                // Flecha Abajo
                case  80:
                       if ( CurrCol >= 6 && CurrCol < 20 )
                       {
                        CurrCol++; if ( CurrCol > 19 ) CurrCol = 19;
                       } else {
                        if ( ( CurrRow + CurrCmp ) < ( RegCompras[DiaActual] - 1 )  )
                        {

                         if ( ( CurrRow ) >= NLINEAS_CMP - 1 )
                         {
                           CurrRow = 0;		CurrCmp += NLINEAS_CMP;

                           while ( (CurrCmp + CurrRow) >= RegCompras[DiaActual] ) CurrCmp--;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                         } else
                         	CurrRow++;
                        }
                        if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
                        if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                       }
                       break;
                // Inicio
                case  71:
                       CurrRow = 0;
                       if ( CurrCmp != 0 )
                       {
                        CurrCmp = 0;

                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                       }

                       if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
                       if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                       break;
                // Fin
                case  79:
                       CurrRow = 0;
                       if ( CurrCmp != RegCompras[DiaActual] - NLINEAS_CMP )
                       {
                        CurrCmp = RegCompras[DiaActual] - NLINEAS_CMP;
                        if ( CurrCmp < 0 )
                        {
                         CurrCmp = 0;
                         CurrRow = RegCompras[DiaActual]-1;
                        }
                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                       }

                       if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
                       if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
                       break;

               }
	       break;
       // Imprimir Compras
       case  1:
               MuestraImpresionesCmp();
	       break;
       // Menu Principal
       case  2:
               ok = 1;
               break;
       // Eliminar
       case  3:
            if ( VisualMode == OK )
            {
             while( kbhit() ) getch();
            } else {
               if ( Optar( 1, "ATENCION", "Seguro que desea eliminar", "la compra actual", "confirme la eliminaci�n", NULL ) )
               {

                if ( MatchRef( SCmp.CodigoR, NORMAL ) == OK )
                {
                 // Como estamos sobre la estrcutura, sumamos nuevo stock.
                 SCmp.PrecioCosto = ActualizaStock( SCmp.Cantidad*SRef.CantUnitaria, -1, COMPRA );
                }

                if ( BCmp.DelReg( BCmp.RegActual()/*CurrCmp + CurrRow + PosicionDia( DiaActual )*/ ) == ERROR )
                                                              Error(0x01, BCmp.cError );
                ManipulaIndiceDia( DiaActual, ELIMINAR );

                if ( RegCompras[DiaActual] == 0 )
                {
                  CmpNuevoRegistro( &SCmp );
                  if ( BCmp.InsReg( (void *)&SCmp, PosicionDia( DiaActual ), ARRIBA ) == ERROR )
                                                                               Error(0x01, BCmp.cError );
                  ManipulaIndiceDia( DiaActual, INSERTAR );
                  CurrRow = 0;
                } else

                // Si he borrado el �ltimo registro subo una linea
                if ( (CurrCmp+CurrRow) >= ( RegCompras[DiaActual] - 2 ) )
                {
                         if ( (CurrRow + CurrCmp) > 0 )
                         {
                          if ( ( CurrRow ) <= 0 )
                          {
#ifndef DEMOSTRACION
                           CurrRow = NLINEAS_CMP - 1;          CurrCmp -= NLINEAS_CMP;
                           if ( CurrCmp < 0 ) CurrCmp = 0;

                           while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrRow > 0 ) CurrRow--;
                           while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrCmp > 0 ) CurrCmp++;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
#endif
                          } else {
                           CurrRow --; if ( CurrRow < 0 ) CurrRow = 0;
                          }
                         }

                         if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                              Error(0x01, BCmp.cError );
                }

                // Mostramos datos hasta que se nos acabe la pantalla
                MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                              Error(0x01, BCmp.cError );
                if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
               }
	       break;
            }
       // Insertar
       case  4:
            if ( VisualMode == OK )
            {
             while( kbhit() ) getch();
            } else {
               CmpNuevoRegistro( &SCmp );

#ifdef DEMOSTRACION
               if ( RegCompras[DiaActual] >= 4 )
               {
                              Optar( 0, "VERSION DEMOSTRACION", "En esta versi�n no se",  "permiten mas de 3 compras", "por dia, en el mes.", NULL );
                              break;
               }
#endif

               if ( BCmp.InsReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ), ARRIBA ) == ERROR )
                                                             Error(0x01, BCmp.cError );
               ManipulaIndiceDia( DiaActual, INSERTAR );
               if ( ( CurrRow + CurrCmp ) < RegCompras[DiaActual] - 1 )
               {

                if ( ( CurrRow ) >= NLINEAS_CMP - 1 )
                {
#ifndef DEMOSTRACION
                   CurrRow = 0;		CurrCmp += NLINEAS_CMP;

                   while ( (CurrCmp + CurrRow) >= RegCompras[DiaActual] ) CurrCmp--;
#endif
                 } else
                   CurrRow++;
                 }

                 // Mostramos datos hasta que se nos acabe la pantalla
                 MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
                 if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
                 if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
            }
               break;
       // Retroceso R�pido
       case  5:
#ifndef DEMOSTRACION
               CurrRow = NLINEAS_CMP - 1;          CurrCmp -= NLINEAS_CMP;
               if ( CurrCmp < 0 ) CurrCmp = 0;

               while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrRow > 0 ) CurrRow--;
               while( ( CurrRow + CurrCmp ) >= RegCompras[DiaActual] && CurrCmp > 0 ) CurrCmp++;

               // Mostramos datos hasta que se nos acabe la pantalla
               MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
               if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
               if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
#endif
               break;
       // Busqueda Atras
       case  6:
               BuscaCmp( ATRAS, &CurrRow, &CurrCmp, NivelAcceso );
               if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
	       break;
       // Buscar
       case  7:
               BuscaCmp( NUEVA_BUSQUEDA, &CurrRow, &CurrCmp, NivelAcceso );
               if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
	       break;
       // Busqueda Adelante
       case  8:
               BuscaCmp( ADELANTE, &CurrRow, &CurrCmp, NivelAcceso );
               if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
	       break;
       // AvanceR�pido
       case  9:
#ifndef DEMOSTRACION
	       CurrRow = 0;		CurrCmp += NLINEAS_CMP;

               while ( (CurrCmp + CurrRow) >= RegCompras[DiaActual] ) CurrCmp--;

               // Mostramos datos hasta que se nos acabe la pantalla
               MuestraDatosCmp( CurrCmp + PosicionDia( DiaActual ) );
               if ( BCmp.LeeReg( (void *)&SCmp, (CurrCmp + CurrRow + PosicionDia( DiaActual ) ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
               if ( SCmp.CodigoR != 0 && ( CurrCol == 1 || CurrCol == 4 ) ) CurrCol = 0;
#endif
	       break;
       default:
	       break;
      }

 } while( !ok );

 farfree( BusquedaRef );
 BCmp.CerrarReg();
 BRef.CerrarReg();
 BProv.CerrarReg();
/*
 BVentProv.CerrarReg();
*/
}


 /**************************************************************************\
|*                                                                          *|
|*  SeleccionaMesCompras                                                    *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Abre el archivo adecuado al mes de compras requerido.       *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void SeleccionaMesCompras( int NivelAcceso )
{
 static char ArchivoAbierto = ERROR;
 char buffer[80]; char i;

 if ( ArchivoAbierto == OK )
 {
                         BCmp.CerrarReg();
                         ArchivoAbierto = ERROR;
 }

 // � Que archivo hay que abrir ?
 sprintf( buffer, "datos\\%s\\Cmp-%04d.M%02d", NEmpresa, FechaGestionActual.da_year, MesActual );

 // Abrimos el archivo
 if ( BCmp.AbrirReg( buffer, sizeof( COMPRAS ) ) == ERROR )
                                                             Error(0x01, BCmp.cError );
 else
                                                             ArchivoAbierto = OK;

 // Si no hay nada, habr� que inicializar el mes
 if ( BCmp.Registros() == 0 )
 {
  // Una estructura limpia
  CmpNuevoRegistro( &SCmp );

  // Tenemos que crear, almenos una compra por dia ( 31 dias )
  // e inicializamos el indice.

  for ( i = 0; i < 31; i++ )
  {
      BCmp.InsReg( (void *)&SCmp, i, ARRIBA );
      RegCompras[i] = 1;
  }
      RegCompras[     0] = 0;   // El dia 0 no tiene ningun registro

      RegCompras[31 + 0] = 1;   // Dia 31, solo 1 registro
      RegCompras[31 + 1] = 1;   // Por si las moscas, otro dia, D32

  BCmp.SalvaDatosUsuario( (void *)RegCompras );

 } else {
  // Recuperamos los datos de usuario
  BCmp.CargaDatosUsuario( (void *)RegCompras, sizeof(long)*32 );
 }

 if ( NivelAcceso == TOTAL )
 {
                  RellenaCalendario( 0, 0 );
                  MarcaDiaActual( 4, DiaActual + AjusteCalendario, INTENSO );
 }

}

 /**************************************************************************\
|*                                                                          *|
|*  ManipulaIndiceDia                                                       *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              A�ade o elimina un registro ( resta o suma al n� regs. )    *|
|*                                                                          *|
|*  Entradas: Dia que estamos tratando                                      *|
|*            ELIMINAR / INSERTAR                                           *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void ManipulaIndiceDia( char Dia, char Accion )
{

 if ( Accion == INSERTAR )
 {
  // Recorro todos los dia desde Dia hasta el 31 aumentando en 1 el n� de registros
      RegCompras[ Dia ] ++;
 } else {
  // Recorro todos los dia desde Dia hasta el 31 aumentando en 1 el n� de registros
      RegCompras[ Dia ] --;
 }

 // Salvamos estos datos
 BCmp.SalvaDatosUsuario( RegCompras );

}

 /**************************************************************************\
|*                                                                          *|
|*  PosicionDia                                                             *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Da el inicio f�sico del dia rrequerido en el archivo.       *|
|*                                                                          *|
|*  Entradas: Dia a obtener su inicio                                       *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
long PosicionDia( char Dia )
{
 long InicioDia, i;

 InicioDia = 0;

 // Recorro todos los dias hasta Dia - 1 para obtener el principio f�sico
 for ( i = 1; i < Dia; i++ )
     InicioDia += RegCompras[i];

 return InicioDia;
}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraDatosCmp                                                         *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Dado un registro, se muestran sucesivamente este y todos    *|
|*              los que hay por debajo de �l, hasta que se agote la base    *|
|*              o no quepan mas en la pantalla.                             *|
|*                                                                          *|
|*  Entradas: Registro por el que comenzar                                  *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraDatosCmp( long RowStart )
{
 int linea, campo;
 char dev;
 int X0, Y0, X1, Y1;

 // Imprimo la NLINEAS_CMP que caben en la pantalla
 dev = OK;
 for ( linea=0; linea < NLINEAS_CMP && dev == OK && (linea + RowStart) < PosicionDia( DiaActual + 1 ); linea++ )
 {
   dev = BCmp.LeeReg( (void *)&SCmp, RowStart + linea );
   if ( dev == OK )
   {
   // Por cada linea hay 5 campos, ehhh!!!
      for  ( campo=0; campo < 5; campo++ )
                                  MuestraCmp( campo, linea, NORMAL );
   }
 }

 // Ahora limpio los restantes huecos si los hay

  if ( linea < NLINEAS_CMP )
 {
   setfillstyle( SOLID_FILL, Config.TxtBgN );
   for ( ; linea < NLINEAS_CMP; linea++ )
     for  ( campo=0; campo < 5; campo++ )
     {
        ObtenCoordenadasCmp( campo, linea, &X0, &Y0, &X1, &Y1 );
        bar( X0, Y0, X1, Y1 );
     }
 }
}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraCmp                                                              *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Reescribe el campo dado, seg�n la fila, y la intensidad     *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha mostar                                    *|
|*            linea      linea en la que nos encontramos                    *|
|*            como       intensidad del texto (NORMAL/INTENSO)              *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraCmp( char columna, int linea, char como )
{
 char buffer[80];
 char buffer1[80];

 int X0, Y0, X1, Y1;

 ObtenCoordenadasCmp( columna, linea, &X0, &Y0, &X1, &Y1 );

 switch( columna )
 {
  // Codigo Real de la compra
  case  0:
       sprintf ( buffer, " %09lu", SCmp.CodigoR  );
       break;
  // Nombre del producto
  case  1:
       sprintf ( buffer, "%30s",  SCmp.Descripcion  );
       break;
  // Cantidad
  case  2:
       formatea_u_long( (unsigned long)SCmp.Cantidad, buffer1 );
       sprintf ( buffer, "%5s", buffer1 );
       break;
  // Proveedor
  case  3:
       MatchProveedor( SCmp.CodigoProveedor );
       sprintf ( buffer, "%19s", NomProveedor );
       break;
  // Precio de costo Total
  case  4:
       formatea_u_long( (unsigned long)(SCmp.PrecioCosto), buffer1 );
       sprintf ( buffer, " %8s", buffer1 );
       break;
 }

 setfillstyle( SOLID_FILL, ( como == NORMAL ) ? Config.TxtBgN : Config.TxtBgI );
 bar( X0, Y0, X1, Y1 );
 setcolor ( ( como == NORMAL ) ? Config.TxtFgN : Config.TxtFgI );

 if ( columna == 3 )      settextstyle( SMALL_FONT, HORIZ_DIR, 4 );

 outtextxy( X0+2, Y0, buffer );

 if ( columna == 3 )      settextstyle( SMALL_FONT, HORIZ_DIR, 5 );

}


 /**************************************************************************\
|*                                                                          *|
|*  MuestraAyudaCmp                                                         *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Muestra una peque�a descripcion del contenido para el campo *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha mostar su ayuda                           *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraAyudaCmp( char columna )
{
 char buffer1[80];

 switch( columna )
 {
  // Codigo Real del producto
  case  0:
       sprintf ( buffer1, "C�digo del producto. ( 0 si no tiene c�digo )" );
       break;
  // Nombre del producto
  case  1:
       sprintf ( buffer1, "Nombre ( para el producto sin catalogar )" );
       break;
  // Cantidades
  case  2:
       sprintf ( buffer1, "Unidades de compra. (Por paquetes)" );
       break;
  // Proveedores
  case  3:
       sprintf ( buffer1, "Nombre del proveedor del producto" );
       break;
  // Precio de costo
  case  4:
       sprintf ( buffer1, "Precio de costo total ( Producto sin catalogar )" );
       break;
 }

 // Ayuda reducida
 setfillstyle( SOLID_FILL, EGA_BLACK );  bar( 7, 457, 498, 473 );
 // Imprime la ayudita
 setcolor( EGA_WHITE ); outtextxy( 7, 457, buffer1 );

}

 /**************************************************************************\
|*                                                                          *|
|*  EditItemCmp                                                             *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Se encarga de editar y validar el campo.                    *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha editar                                    *|
|*            linea      linea en la que nos encontramos                    *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void EditItemCmp( char columna, int linea )
{
 char buffer[80];

 int X0, Y0, X1, Y1;

 ObtenCoordenadasCmp( columna, linea, &X0, &Y0, &X1, &Y1 );

 switch( columna )
 {
  // Codigo Real
  case  0:
       sprintf ( buffer, "%lu", SCmp.CodigoR  );
       if ( !( InputCadenaG( buffer, 1,  9, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
       SCmp.CodigoR = atol( buffer );
       MuestraCmp( 4, linea, NORMAL );
       break;
  // Nombre del producto ( Solo si el codigo es el 0 )
  case  1:
       if ( SCmp.CodigoR == 0 )
       {
        strcpy ( buffer, SCmp.Descripcion   );
        if ( !( InputCadenaG( buffer, 0, 30, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
        strcpy ( SCmp.Descripcion, buffer   );
       }
       break;
  // Cantidad
  case  2:
       sprintf ( buffer, "%u", SCmp.Cantidad );
       if ( !( InputCadenaG( buffer, 1, 4, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
       SCmp.Cantidad = atoi( buffer );
       MuestraCmp( 4, linea, NORMAL );
       break;
  // Proveedor
  case  3:
        // El tratamiento del proveedor es especial
        DespliegaProveedoresCmp( linea );
       break;
  // Precio de costo ( Solo Accesible con Codigo 0 )
  case  4:
       if ( SCmp.CodigoR == 0 )
       {
        sprintf ( buffer, "%ld", SCmp.PrecioCosto );
        if ( !( InputCadenaG( buffer, 1, 8, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
        SCmp.PrecioCosto = atol( buffer );
       }
       break;
 }

}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenCoordenadasCmp                                                     *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Obtiene las coordenadas de acotacion para el campo pedido   *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo del que obtener las coordenadas              *|
|*            linea      linea en la que nos encontramos                    *|
|*            X0 Y0 X1 Y1  Punteros para devolver las coordenadas           *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void ObtenCoordenadasCmp( char columna, char linea, int *X0, int *Y0, int *X1, int *Y1 )
{

 // Calculamos la Y0, Y1 para la linea dada ( SOLO columna < 6 )
 *Y0 = 164 + 19*linea;
 *Y1 = *Y0 + 17;

 switch( columna )
 {
  case 0:
       *X0 =   7;       *X1 =  98;
       break;
  case 1:
       *X0 = 107;       *X1 = 358;
       break;
  case 2:
       *X0 = 367;       *X1 = 413;
       break;
  case 3:
       *X0 = 422;       *X1 = 543;
       break;
  case 4:
       *X0 = 552;       *X1 = 633;
       break;
 }

 *X0 += 2;
 *X1 -= 2;

}

 /**************************************************************************\
|*                                                                          *|
|*  CmpNuevoRegistro                                                        *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Limpia el buffer, para un nuevo registro.                   *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void CmpNuevoRegistro( COMPRAS *NSCmp )
{

 NSCmp -> CodigoR = 0;     // Codigo real del producto

 NSCmp -> Descripcion[0] = '\0';    // Nombre del Producto

 NSCmp -> Cantidad = 1;             // # de productos por unidad

 NSCmp -> PrecioCosto = 0;          // Precio de costo

 NSCmp -> CodigoProveedor = 0;      // Codigo del proveedor del producto

 NSCmp -> PrecioCosto = 0;          // # de productos actualmente

                                   // Codigos asociados a este producto ( COMBINADOS )
}


//  ���������������������������������������������������������������������
// �                     Parte secundaria del m�dulo                      �
// �                                                                      �
// �                  Secci�n de Busqueda de refecencias                  �
//  ���������������������������������������������������������������������

 /**************************************************************************\
|*                                                                          *|
|*  BuscaCmp                                                                *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Busca una referencia por su n� o descripcion                *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           ATRAS             Busca otra coincidencia hacia atras          *|
|*           NUEVA_BUSQUEDA    Inicia una nueva busqueda                    *|
|*           ADELANTE          Busca otra coincidencia hacia delante        *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void BuscaCmp( char TipoBusqueda, char *CurrRow, long *CurrCmp, int NivelAcceso )
{
 static COMPRAS MCmp;
 static int MesDia = 0;
 char enc;
 long i;
 int OldDiaActual = DiaActual;

 switch ( TipoBusqueda )
 {
    case NUEVA_BUSQUEDA:
         MesDia = 0;
         if ( ObtenMatchCmp( &MCmp, &MesDia ) != OK )
                                           return;
         // Si el acceso es total, podemos buscar en toda la base
         if ( NivelAcceso == TOTAL && MesDia >> 8 )
         {
           // Toda la base:
           DiaActual = 1;
         }
         i = 0;
         break;
    case ATRAS:
    case ADELANTE:
         i = ( *CurrRow + *CurrCmp ) + TipoBusqueda;
         break;
 }

 Optar( ENCUADRE, "Comando: Buscar", "Ahora se inica", "la busqueda elegida", NULL );

 enc = 0;

 if ( MesDia >> 8 )
  if ( NivelAcceso == TOTAL )
  {
     // Busca a travez de todos los dias del mes
     for ( ; DiaActual < DiasMes && !enc; DiaActual++, i = 0 )
     while ( i < RegCompras[DiaActual] && !enc )
     {
      if ( BCmp.LeeReg( (void *)&SCmp, i + PosicionDia( DiaActual ) ) == ERROR )
                                                     Error( 0x01, BCmp.cError );
      if ( Match_Cmp( SCmp, MCmp ) )
                                    enc = 1;
      else
                                    i++;
     }
  } else {
     // Busca solo en el dia actual
     while ( i < RegCompras[DiaActual] && !enc )
     {
      if ( BCmp.LeeReg( (void *)&SCmp, i /*+ PosicionDia( DiaActual )*/ ) == ERROR )
                                                     Error( 0x01, BCmp.cError );
      if ( Match_Cmp( SCmp, MCmp ) )
                                    enc = 1;
      else
                                    i++;
     }
  }

     Optar( ENCUADRE, NULL );

     if ( enc )
     {
       *CurrRow = 0; *CurrCmp = i;
       // Mostramos datos hasta que se nos acabe la pantalla
       MuestraDatosCmp( *CurrRow + *CurrCmp + PosicionDia( DiaActual ) );
     } else {
       DiaActual = OldDiaActual;
       // Mostramos datos hasta que se nos acabe la pantalla
       MuestraDatosCmp( /**CurrRow + */*CurrCmp + PosicionDia( DiaActual ) );
       if ( BCmp.LeeReg( (void *)&SCmp, ( *CurrRow + *CurrCmp + PosicionDia( DiaActual ) ) ) == ERROR )
                                                                 Error(0x01, BCmp.cError );
       switch( TipoBusqueda )
       {
        case NUEVA_BUSQUEDA:
         Optar( 0, "Comando: Buscar", "No se encontr�", "ninguna coincidencia", NULL );
         break;
       case ATRAS:
       case ADELANTE:
         Optar( 0, "Comando: Buscar", "No se encontr�", "ninguna coincidencia", NULL );
         break;
       }
     }

     if ( BCmp.LeeReg( (void *)&SCmp, (*CurrRow + *CurrCmp + PosicionDia( DiaActual ) ) ) == ERROR )
                                                                 Error( 0x01, BCmp.cError );
}

 /**************************************************************************\
|*                                                                          *|
|*  Match_Cmp                                                               *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Compara dos registros y devuelve la posible coincidencia    *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Registros a comparar                                           *|
|*                                                                          *|
|*  Salidas:                                                                *|
|*           Resultado de la comparaci�n                                    *|
|*                                                                          *|
 \**************************************************************************/
int Match_Cmp( COMPRAS A, COMPRAS B )
{
  if ( B.CodigoR != 0 )
                 return (A.CodigoR == B.CodigoR);
  if ( B.Descripcion[0] != '\0' )
                 return ( strncmpi( A.Descripcion, B.Descripcion, strlen( B.Descripcion ) ) == 0 );
  if ( B.CodigoProveedor != 0 )
                 return (A.CodigoProveedor == B.CodigoProveedor );
  return -1;
}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenMatchCmp                                                           *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Obtine los patrones de busqueda necesarios                  *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Estructura donde guardar el patron de busqueda                 *|
|*                                                                          *|
|*  Salidas:                                                                *|
|*           OK     La entrada es correcta                                  *|
|*           ERROR  El usuario interrumpio la busqueda                      *|
|*                                                                          *|
 \**************************************************************************/
int ObtenMatchCmp( COMPRAS *MCmp, int *MesDia )
{
 char Row, ok, i;
 int BPush, key, DEV;
 struct textsettingstype texttypeinfo;

 gettextsettings( &texttypeinfo );

 Optar( ENCUADRE, "Comando: Buscar", NULL );
 Imprime_Estaticos( 41, "systm\\tpv.img" );

 ok = 0; Row = 0;

 CmpNuevoRegistro( MCmp );

 do
 {
  MatchDrawCmp(Row, *MCmp, INTENSO, *MesDia);
  BPush = Comprueba_Secuencia( SEC_OPTAR, NULL );
  MatchDrawCmp(Row, *MCmp, NORMAL, *MesDia);

  switch ( BPush )
  {
       case  0:				  // No se pulso ningun BOTON
	       while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
       case -2:
               if ( ( key = getch() ) != 13 && key != 27 )
                                      ungetch( key );
               EditMatchCmp( Row, MCmp, MesDia );
               for ( i=0; i < 6; i++ )
                     MatchDrawCmp(i, *MCmp, NORMAL, *MesDia );
	       while( kbhit() ) getch();  // Limpiamos posibles teclas en BUFFER
	       break;
       case -1:
	       switch ( getch() )
               {
                // Flecha Izquierda
                case  75:
                case  15:
                // Flecha Arriba
                case  72:
                       Row--; if ( Row < 0 ) Row = 5;
                       break;
                // Flecha Derecha
                case  77:
                case   9:
                // Flecha Abajo
                case  80:
                       Row++; if ( Row > 5 ) Row = 0;
                       break;
               }
	       break;
       case  1:
               DEV = OK; ok = 1;
               // Chequeo por si los parametros de busqueda son incorrectos
               if ( Match_Cmp( *MCmp, *MCmp ) == -1 ) DEV = ERROR;
               break;
       case  2:
               DEV = ERROR; ok = 1;
               break;
  }

 } while ( !ok );

 Optar( ENCUADRE, NULL );

 settextstyle( texttypeinfo.font, texttypeinfo.direction, texttypeinfo.charsize );

 return DEV;

}

 /**************************************************************************\
|*                                                                          *|
|*  EditMatchCmp                                                            *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Edita el patron de busqueda                                 *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Campo a editar, y lugar donde almacenarlo                      *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void EditMatchCmp( char Row, COMPRAS * MCmp, int *MesDia )
{
 int X0, Y0, X1, Y1;
 char buffer[80];

 ObtenCoordenadasMatchCmp( Row, &X0, &Y0, &X1, &Y1 );

 switch( Row )
 {
  case 0:
         sprintf( buffer, "%lu", MCmp -> CodigoR );
         if ( !( InputCadenaG( buffer, 1,  9, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
         {
          CmpNuevoRegistro( MCmp );
          if ( MatchRef ( atol(buffer), NORMAL ) == OK )
                         MCmp -> CodigoR = atol(buffer);
         }
         break;
  case 1:
         buffer[0] = '\0';
         if ( !( InputCadenaG( buffer, 1,  9, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
         {
          CmpNuevoRegistro( MCmp );
          if ( MatchRef ( atol(buffer), BARRAS ) == OK )
                    MCmp -> CodigoR = SRef.CodigoR;
         }
         break;
  case 2:
         strcpy( buffer, MCmp -> Descripcion );
         if ( !( InputCadenaG( buffer, 0, 25, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
         {
          CmpNuevoRegistro( MCmp );
          strcpy ( MCmp -> Descripcion, buffer );
         }
         break;
  case 3:
         buffer[0] = '\0';
         if ( !( InputCadenaG( buffer, 1,  6, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
         {
          CmpNuevoRegistro( MCmp );
          if ( MatchProveedor ( atol(buffer) ) )
                    MCmp -> CodigoProveedor = SProv.CodigoR;
         }
  case 4:
         *MesDia = ( *MesDia & 0xFF00 ) | ! ( *MesDia & 0x00FF );
         break;
  case 5:
         *MesDia = ( *MesDia & 0x00FF ) | ( ! ( *MesDia >> 8 ) << 8 );
         break;
 }



}

 /**************************************************************************\
|*                                                                          *|
|*  MatchDrawCmp                                                            *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Escribe los distintos campos seg�n se le indique            *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Campo a mostrar, lugar donde se encuentra, y como mostrarlo    *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void MatchDrawCmp( char Row, COMPRAS MCmp,  char como, int MesDia )
{
 int X0, Y0, X1, Y1;
 char buffer[80];

 ObtenCoordenadasMatchCmp( Row, &X0, &Y0, &X1, &Y1 );

 switch( Row )
 {
  case 0:
         sprintf( buffer, " %9lu", MCmp.CodigoR );
         break;
  case 1:
         buffer[0] = '\0';
         break;
  case 2:
         strncpy( buffer, MCmp.Descripcion, 25 );
         buffer[26] = '\0';
         break;
  case 3:
         sprintf( buffer, "%6ld", MCmp.CodigoProveedor );
         break;
  case 4:
         sprintf( buffer, "%s", ( MesDia & 0x00FF ) ? "����" : "    " );
         break;
  case 5:
         sprintf( buffer, "%s", ( MesDia >> 8 ) ? "����" : "    " );
         break;
 }

 setfillstyle( SOLID_FILL, ( como == NORMAL ) ? Config.TxtBgN : Config.TxtBgI );
 bar( X0, Y0, X1, Y1 );
 setcolor ( ( como == NORMAL ) ? Config.TxtFgN : Config.TxtFgI );
 outtextxy( X0+2, Y0, buffer );

}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenCoordenadasMatchCmp                                                *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Obtiene las coordenadas relativas al campo dado.            *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Campo a obtener las coordenadas, y coordenadas de salida       *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void ObtenCoordenadasMatchCmp( char Row, int *X0, int *Y0, int *X1, int *Y1 )
{

 switch( Row )
 {
  case 0:
         *X0 = 260;  *X1 = 360;
         *Y0 = 200;  *Y1 = 220;
         break;
  case 1:
         *X0 = 365;  *X1 = 465;
         *Y0 = 200;  *Y1 = 220;
         break;
  case 2:
         *X0 = 260;  *X1 = 465;
         *Y0 = 225;  *Y1 = 245;
         break;
  case 3:
         *X0 = 260;  *X1 = 325;
         *Y0 = 250;  *Y1 = 275;
         break;
  case 4:
         *X0 = 435;  *X1 = 465;
         *Y0 = 252;  *Y1 = 273;
         break;
  case 5:
         *X0 = 435;  *X1 = 465;
         *Y0 = 277;  *Y1 = 300;
         break;
 }

 (*X0) ++;  (*Y0) ++;
 (*X1) --;  (*Y1) --;

}


//  ���������������������������������������������������������������������
// �                     Parte terciaria del m�dulo                       �
// �                                                                      �
// �                  Secci�n de Impresion de compras                     �
//  ���������������������������������������������������������������������

 /**************************************************************************\
|*                                                                          *|
|*  MuestraImpresionesCmp                                                   *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Muestra un cuadro con las distintas opciones de impresi�n   *|
|*                                                                          *|
|*  Entradas:(ninguna)                                                      *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void MuestraImpresionesCmp(void)
{
 void far *fondo;
 struct textsettingstype texttypeinfo;
 char ok, dev;

 if ( ( fondo = farmalloc ( JD_imagesize( 170, 165, 470, 315 ) ) ) != NULL )
 {

  gettextsettings( &texttypeinfo );
  getimage( 170, 165, 470, 315, fondo );

  Imprime_Estaticos( 42, "systm\\tpv.img" );

  settextstyle( texttypeinfo.font, texttypeinfo.direction, texttypeinfo.charsize );

  ok = 0;
  do {
    switch( Comprueba_Secuencia( 3, NULL ) )
    {
     case  0:
     case -1:
     case -2:
          while( kbhit() ) getch();
          break;
     // Cancelar
     case  1:
           dev = 0;
           ok  = 1;
           break;
     // Listado del dia
     case  2:
           dev = 1;
           ok  = 1;
           break;
     // Listado mesual
     case 3:
           dev = 2;
           ok  = 1;
           break;
    }
  } while( !ok );

  putimage( 170, 165, fondo, COPY_PUT );
  farfree( fondo );
  if ( dev != 0 )
       ImprimeCompras( dev );

 }

}

 /**************************************************************************\
|*                                                                          *|
|*  ImprimeCompras                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Imprime todas las referencias seg�n se le indique           *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Como imprimir las referencias                                  *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void ImprimeCompras( char como )
{
 long i, old_reg;
 char buffer[80];
 long buffTMP;
 unsigned long TotalCompras;
 FILE *file_out;

 old_reg = BCmp.RegActual();

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

 ImprimeCabeceraCmp( como, file_out );

 buffTMP = 0; TotalCompras = 0;
 for ( ( como==2 ? i=0 : i = PosicionDia(DiaActual) ); i < ( como==2 ? BCmp.Registros() : RegCompras[DiaActual] + 1 ) ; i++ )
 {
  BCmp.LeeReg( (void *)&SCmp, i );

  switch( como )
  {
   // Listado del dia      //
   case 1:                 //  Ambos listados son iguales
   // Mensual              //
   case 2:
        formatea_u_long( (unsigned long)SCmp.Cantidad, buffer );
        fprintf( file_out, " � %8lu � %-30s � %6s �", SCmp.CodigoR, SCmp.Descripcion, buffer );
        formatea_u_long( (unsigned long)SCmp.PrecioCosto/SCmp.Cantidad, buffer );
        fprintf( file_out, " %8s ", buffer );
        formatea_u_long( (unsigned long)SCmp.PrecioCosto, buffer );
        fprintf( file_out, "�%10s �\n\r", buffer );
        buffTMP += SCmp.Cantidad;
        TotalCompras += SCmp.PrecioCosto;
        break;
   case 3:
        break;
   case 4:
        break;
  }
 }

 if ( como == 1 || como == 2 )
 {
   fprintf( file_out, " �����������������������������������������������������������������������������\n\r" );
   fprintf( file_out, "\n\r" );
   fprintf( file_out, " �����������������������������������Ŀ\n\r" );
   formatea_u_long( TotalCompras, buffer );
   fprintf( file_out, " � %05ld Productos, %10s ptas. �\n\r", buffTMP, buffer );
   fprintf( file_out, " �������������������������������������\n\r" );
 }


 if ( !Config.Impresora.Printer )
                      fclose( file_out );

 BCmp.LeeReg( (void *)&SCmp, old_reg );

}

void ImprimeCabeceraCmp( char como, FILE *file_out )
{
  switch( como )
  {
    case 1:
    case 2:
        fprintf( file_out, " ���������������������������������������������������������������������������Ŀ\n\r" );
        fprintf( file_out, " �  C�digo  � Articulo                       �  Cant. � P.Costo  � P.Total   �\n\r" );
        fprintf( file_out, " ���������������������������������������������������������������������������Ĵ\n\r" );
         break;
    case 3:
         break;
    case 4:
        break;
  }
}

//  ���������������������������������������������������������������������
// �                       Parte Cuarta del m�dulo                        �
// �                                                                      �
// �                 Secci�n de Carga de elementos en Memoria             �
//  ���������������������������������������������������������������������


 /**************************************************************************\
|*                                                                          *|
|*  CargaProductos                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Carga las direcciones de hasta 5000 c�digos.                *|
|*                                                                          *|
|*  Entradas:(ninguna)                                                      *|
|*                                                                          *|
|*  Salidas:                                                                *|
|*           OK                                                             *|
|*           ERROR                                                          *|
|*                                                                          *|
 \**************************************************************************/
int CargaProductos(void)
{
 long i;
 char buffer[80];

 sprintf( buffer, "datos\\%s\\info_ref.dbf", NEmpresa );
 if ( BRef.AbrirReg( buffer, sizeof( INFO_PRODUCTOS ) ) == ERROR )
                                                             Error(0x01, BRef.cError );

 if ( BRef.Registros() > 0 )
 {
  // Solo almacenaremos 5000 registros
  if ( BRef.Registros() > 5000 )
                           i = 5000;
  else
                           i = BRef.Registros();

  if ( ( BusquedaRef = ( BUSQUEDA_REF far * ) farmalloc( sizeof( BUSQUEDA_REF ) * i ) ) == NULL )
                                                                                       BusquedaDirecta = ON;
  else
                                                                                       BusquedaDirecta = OFF;
  if ( BusquedaDirecta == OFF )
   for ( i = 0; i < BRef.Registros() && i < 5000; i++ )
   {
    BRef.LeeReg( (void *)&SRef, i );
    BusquedaRef[i].CodigoR  = SRef.CodigoR;
    BusquedaRef[i].CodigoB  = SRef.CodigoB;
    BusquedaRef[i].Posicion = (unsigned int)i;
   }

   return OK;
 }

 return ERROR;
}

 /**************************************************************************\
|*                                                                          *|
|*  MatchRef                                                                *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Busca el c�digo que se le pasa como parametro               *|
|*              teniendo en cuenta si es de barra o normal...               *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           C�digo a buscar y tipo de c�digo                               *|
|*                                                                          *|
|*  Salidas:                                                                *|
|*           OK      Si lo encuentra                                        *|
|*           ERROR                                                          *|
|*                                                                          *|
 \**************************************************************************/
int MatchRef( unsigned long Codigo, char NormalBarras )
{
 long i;  char enc;
 static char flag = 0;

 if ( Codigo == 0 ) return ERROR;

 if ( flag != 0 )
 {
  // Antes de realizar la busqueda, vemos si el registro actual
  // concuerda con nuestros requisitos...
  if ( NormalBarras == NORMAL )
  {
       if ( SRef.CodigoR == Codigo ) return OK;
  } else {
       if ( SRef.CodigoB == Codigo )
       {
        Codigo = SRef.CodigoR;
        return OK;
       }
  }
 } else flag = 1;


 enc = ERROR; i = 0;
 if ( BusquedaDirecta == OFF )
  for ( i=0; i < BRef.Registros() && enc != OK; )
   if ( NormalBarras == NORMAL )
   {
        if ( BusquedaRef[i].CodigoR == Codigo ) enc = OK; else i++;
   } else {
        if ( BusquedaRef[i].CodigoB == Codigo )
        {
         Codigo = BusquedaRef[i].CodigoR;
         enc = OK;
        } else i++;
   }

 // Si lo hemos encontrado, cargamos su estructura.
 if ( enc == OK )
     if ( BRef.LeeReg( (void *)&SRef, BusquedaRef[i].Posicion ) == ERROR )
                                                              Error( 0x01, BRef.cError );
 else
 if ( BusquedaDirecta == ON || i >= 5000 )
  // Comenzamos una busqueda directa
  for ( ; i < BRef.Registros() && enc != OK; i++ )
  {
   BRef.LeeReg( (void *)&SRef, i );
   if ( NormalBarras == NORMAL )
   {
       if ( SRef.CodigoR == Codigo ) enc = OK;
   } else {
       if ( SRef.CodigoB == Codigo )
       {
        Codigo = SRef.CodigoR;
        enc = OK;
       }
   }
  }

 return enc;
}


 /**************************************************************************\
|*                                                                          *|
|*  CargaProveedores                                                        *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Abre y carga los datos necesarios para visualizar a los     *|
|*              proveedores                                                 *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void CargaProveedores(void)
{
 char buffer[80];

 sprintf( buffer, "datos\\%s\\info_prv.%03d", NEmpresa, ( FechaGestionActual.da_year - (FechaGestionActual.da_year/1000)*1000 ) );

 // Este a�o no existe la base de datos, pero quizas exista el a�o anterior
 if  ( access( buffer, 0 ) != 0 )
 {
   sprintf( buffer, "datos\\%s\\info_prv.%03d", NEmpresa, ( (FechaGestionActual.da_year-1) - ((FechaGestionActual.da_year-1)/1000)*1000 ) );
   if  ( access( buffer, 0 ) == 0 )
   {
     Optar( ENCUADRE, "Generando clon de Proveedores", "Atenci�n se detecto un nuevo", "a�o y se esta generando un", "clon de la base anterior.", NULL );
     DuplicaBaseProveedores();
     Optar( ENCUADRE, "Generando clon de Proveedores", "Atenci�n se detecto un nuevo", "a�o y se esta generando un", "clon de la base anterior.", NULL );
   }
 }

 sprintf( buffer, "datos\\%s\\info_prv.%03d", NEmpresa, ( FechaGestionActual.da_year - (FechaGestionActual.da_year/1000)*1000 ) );
 if ( BProv.AbrirReg( buffer, sizeof( INFO_PROVEEDORES ) ) == ERROR )
                                                             Error(0x01, BProv.cError );
 if ( BProv.LeeReg( (void *)&SProv, 0 ) == ERROR )
                                                             Error(0x01, BProv.cError );
}


 /**************************************************************************\
|*                                                                          *|
|*  MatchProveedor                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              He decidido, que para la busqueda no utilizar� ninguna      *|
|*              estructura de datos en memoria, y ser� directa...           *|
|*                                                                          *|
|*  Entradas: N� de proveedor a buscar                                      *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
int MatchProveedor( long NProveedor )
{
 static char vez = 0;
 int i, enc;

/*
 if ( NProveedor == 0 )
 {
   strcpy ( SProv.Proveedor, "Prov. Varios" );
   return OK;
 }
*/

 // Antes de realizar la busqueda, veo si el proveedor actual es el que
 // estamos buscado.
 if ( NProveedor != SProv.CodigoR || vez == 0 )
 {
   vez = 1;   enc = ERROR;
   for ( i = 0; i < BProv.Registros() && enc != OK; i++ )
   {
    BProv.LeeReg( (void *)&SProv, i );
    if ( SProv.CodigoR == NProveedor )
                                     enc = OK;
   }
   if ( enc != OK )
   {
    if ( SProv.CodigoR == 0 )
    {
            ProvNuevoRegistro( &SProv );

            SProv.CodigoR = 0;
            strcpy ( SProv.Proveedor,          "Prov. Varios" );
            strcpy ( SProv.ActividadProveedor, "Prov. Varios" );

            BProv.InsReg( (void *)&SProv, BProv.Registros(), ARRIBA );
     } else
            enc = ERROR;
   }

   strcpy( NomProveedor, SProv.ActividadProveedor );
   NomProveedor[20]='\0';

 } else enc = OK;

 return enc;
}



//  ���������������������������������������������������������������������
// �                       Parte Quinta del m�dulo                        �
// ��                                                                    ��
// �                 Secci�n de Utilidades para el calendario             �
//  ���������������������������������������������������������������������


 /**************************************************************************\
|*                                                                          *|
|*  RellenaCalendario                                                       *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Rellena el calendario en pantalla y rellena el factor de    *|
|*              correccion para los dias.                                   *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void RellenaCalendario( int IncX, int IncY  )
{
 struct textsettingstype Tcfg;
 char i;
 char buffer[80];

 char Mes[12][80] = { "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio",
                      "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };


 // Obtenemos la configuraci�n actual del texto
 gettextsettings( &Tcfg );

 // Ponemos en blanco el calendario
/*
 Imprime_Estaticos( 45, "systm\\Tpv.img"); // Imprime botones estaticos 'Seccion 45'
*/
 Imprime_Secuencia( 4 );

 // Imprimimos el mes ( centrado claro )
 settextstyle( SMALL_FONT, VERT_DIR, 5 );
 setcolor( EGA_BLACK ); outtextxy( 122+IncX,   5+IncY + ( (120 - textwidth( Mes[MesActual-1] ) ) / 2 ), Mes[MesActual-1] );
                        outtextxy( 147+IncX,   5+IncY, "---> " );
                        outtextxy( 147+IncX,  62+IncY, "<---  " );

 setcolor( EGA_WHITE ); outtextxy( 123+IncX,   6+IncY + ( (120 - textwidth( Mes[MesActual-1] ) ) / 2 ), Mes[MesActual-1] );
                        outtextxy( 148+IncX,   6+IncY, "---> " );
                        outtextxy( 148+IncX,  63+IncY, "<---  " );


 // Calculamos los dias que tiene el mes y el ajuste necesario
 CalculaAjusteDias( &AjusteCalendario, &DiasMes, MesActual, FechaGestionActual.da_year );

 // Ahora empiezo a imprimir los dias
 settextstyle( SMALL_FONT, HORIZ_DIR, 5 );
 for ( i = AjusteCalendario; i < DiasMes+AjusteCalendario; i++ )
 {
     sprintf( buffer, " %2d", (int)(i - AjusteCalendario + 1) );
     setcolor( EGA_WHITE );     outtextxy ( 170+IncX + 30*(i%7), 7+IncY + 20*(i/7), buffer );
     setcolor( EGA_BLACK );     outtextxy ( 171+IncX + 30*(i%7), 8+IncY + 20*(i/7), buffer );
 }

 // Restauramos la configuraci�n anterior
 settextstyle( Tcfg.font, Tcfg.direction, Tcfg.charsize );

}




 /**************************************************************************\
|*                                                                          *|
|*  MarcaDiaActual                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Marca el dia actual, en el calendario de forma que parpadee *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MarcaDiaActual( int Sec, int Boton, char como )
{

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

}



//  ���������������������������������������������������������������������
// �                        Parte Sexta del m�dulo                        �
// ��                                                                    ��
// �                 Secci�n de Muesteo de Proveedores                    �
//  ���������������������������������������������������������������������

 /**************************************************************************\
|*                                                                          *|
|*  DespliegaProveedoresCmp                                                 *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Dada la linea donde se iniciar� el despliegue, se encarga   *|
|*              de gestionar todo el depliegue y permitir seleccionar el    *|
|*              proveedor elegido por el usuario...                         *|
|*                                                                          *|
|*  Entradas: Linea en la que comenzar el despliegue                        *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void DespliegaProveedoresCmp( int Row )
{
 void far *FondoImagen;
 char buffer[80], ok, BPush;
 int X0, Y0, X1, Y1;
 int CurrRow, key;
 long CurrProv;

 // Si no hay proveedores no podemos editar nada
 if ( BProv.Registros() == 0 ) return;

 ObtenCoordenadasCmp( 3, Row, &X0, &Y0, &X1, &Y1 );

 // � Tenemos memoria para realizar el tratamiento completo ?
 if ( ( FondoImagen = farmalloc( JD_imagesize( 415, Y0-159, 570, Y1 + 5 ) ) ) != NULL )
 {
  // Recalculamos las coordenadas ( Almenos mostramos 15 Proveedores a la vez )
  X0 = 415;  X1 = 570;
  Y0 -= 159; Y1 +=   5;

  getimage( X0, Y0, X1, Y1, FondoImagen );

  PreparaDespliege( Y0 );

  CurrProv = CurrRow = 0;

  MuestraDatosProvCmp( CurrRow + CurrProv, Row );

  if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                              Error(0x01, BProv.cError);

  ok = 0;
  do {

    MuestraProvCmp( CurrRow, INTENSO, Row );
    BPush = Comprueba_Secuencia( 5, NULL );
    MuestraProvCmp( CurrRow, NORMAL, Row  );

    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
               if ( (key = getch() ) != 27 )
               {
                  if ( key == 13 )
                  {
                    SCmp.CodigoProveedor = SProv.CodigoR;
                    strcpy( NomProveedor, SProv.ActividadProveedor );
                    NomProveedor[20]='\0';
                    ok = 1;
                  } else {
                    ungetch( key );

                    buffer[0] = '\0';
                    ObtenCoordenadasCmp( 3, Row, &X0, &Y0, &X1, &Y1 );
                    if ( !( InputCadenaG( buffer, 1, 5, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
                    SCmp.CodigoProveedor = atol( buffer );

                    // Si el c�digo introducido es correcto, salimos fuera...
                    if ( MatchProveedor( SCmp.CodigoProveedor ) == OK )
                    {
                       SCmp.CodigoProveedor = SProv.CodigoR;
                       ok = 1;
                    } else {
                      X0 = 415;  X1 = 570;
                      Y1 +=   5; Y0 -= 159;
                    }
                    BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) );
                  }
               } else {
                SCmp.CodigoProveedor = SProv.CodigoR;
                ok = 1;
               }
               break;
       case -1:				  // Hay una tecla especial en BUFFER
               switch( ( key = getch() ) )
               {
                // Inicio
                case  71:
                       CurrRow = 0;
                       if ( CurrProv != 0 )
                       {
                        CurrProv = 0;

                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosProvCmp( CurrProv, Row );
                       }

                       if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                             Error(0x01, BProv.cError);
                       break;
                // Fin
                case  79:
                       CurrRow = 0;
                       if ( CurrProv != BProv.Registros() - NLINEAS_PROVcmp )
                       {
                        CurrProv = BProv.Registros() - NLINEAS_PROVcmp;
                        if ( CurrProv < 0 )
                        {
                         CurrProv = 0;
                         CurrRow = BProv.Registros()-1;
                        }
                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosProvCmp( CurrProv, Row );
                       }

                       if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                             Error(0x01, BProv.cError);
                       break;
                }
               while( kbhit() ) getch();
               break;
       // Flecha Arriba
       case  2:
                         if ( ( CurrRow + CurrProv ) < ( BProv.Registros() - 1 ) )
                         {

                          if ( ( CurrRow ) >= NLINEAS_PROVcmp - 1 )
                          {
                            CurrRow = 0;		CurrProv += NLINEAS_PROVcmp;

                            while ( (CurrProv + CurrRow) >= BProv.Registros() ) CurrProv--;

                            // Mostramos datos hasta que se nos acabe la pantalla
                            MuestraDatosProvCmp( CurrProv, Row );
                          } else
                          	CurrRow++;
                         }
                         if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                              Error(0x01, BProv.cError);
	       break;
       // Retroceso R�pido
       case  3:
               CurrRow = NLINEAS_PROVcmp - 1;          CurrProv -= NLINEAS_PROVcmp;
               if ( CurrProv < 0 ) CurrProv = 0;

               while( ( CurrRow + CurrProv ) >= BProv.Registros() && CurrRow > 0 ) CurrRow--;
               while( ( CurrRow + CurrProv ) >= BProv.Registros() && CurrProv > 0 ) CurrProv++;

               // Mostramos datos hasta que se nos acabe la pantalla
               MuestraDatosProvCmp( CurrProv, Row );
               if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                             Error(0x01, BProv.cError);
	       break;
       // Salir
       case  4:
               ok = 1;
	       break;
       // AvanceR�pido
       case  5:
	       CurrRow = 0;		CurrProv += NLINEAS_PROVcmp;

               while ( (CurrProv + CurrRow) >= BProv.Registros() ) CurrProv--;

               // Mostramos datos hasta que se nos acabe la pantalla
               MuestraDatosProvCmp( CurrProv, Row );
               if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                             Error(0x01, BProv.cError);
	       break;
       // Flecha Abajo
       case  6:
                         if ( (CurrRow + CurrProv) > 0 )
                         {
                          if ( ( CurrRow ) <= 0 )
                          {
                           CurrRow = NLINEAS_PROVcmp - 1;          CurrProv -= NLINEAS_PROVcmp;
                           if ( CurrProv < 0 ) CurrProv = 0;

                           while( ( CurrRow + CurrProv ) >= BProv.Registros() && CurrRow > 0 ) CurrRow--;
                           while( ( CurrRow + CurrProv ) >= BProv.Registros() && CurrProv > 0 ) CurrProv++;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosProvCmp( CurrProv, Row );
                          } else {
                           CurrRow --; if ( CurrRow < 0 ) CurrRow = 0;
                          }
                         }

                         if ( BProv.LeeReg( (void *)&SProv, (CurrProv + CurrRow) ) == ERROR )
                                                              Error(0x01, BProv.cError);
               break;
       default:
/*
               if ( BProv.LeeReg( (void *)&SProv, (CurrProv + ( BPush - 6 ) ) ) == ERROR )
                                                              Error(0x01, BProv.cError);
               SCmp.CodigoProveedor = SProv.CodigoR;
*/
	       break;
      }

  } while ( !ok );

  ObtenCoordenadasCmp( 3, Row, &X0, &Y0, &X1, &Y1 );
  // Recalculamos las coordenadas ( Almenos mostramos 10 Proveedores a la vez )
  X0 = 415;  X1 = 570;
  Y1 +=   5; Y0 -= 159;
  putimage( X0, Y0, FondoImagen, COPY_PUT );
  farfree( FondoImagen );
  settextstyle( SMALL_FONT, HORIZ_DIR, 5 );

 } else {
 // Como no hay memoria, al menos, dejaremos que introduzca el c�digo de
 // proveedor...
   sprintf ( buffer, "%ld", SCmp.CodigoProveedor );
   if ( !( InputCadenaG( buffer, 1, 5, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
   {
    SCmp.CodigoProveedor = atol( buffer );
    strcpy( NomProveedor, SProv.ActividadProveedor );
    NomProveedor[20]='\0';
   }
 }

}


 /**************************************************************************\
|*                                                                          *|
|*  PreparaDespliegue                                                       *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Dada la linea donde se iniciar� el despliegue, prepara      *|
|*              todos los registros de botones para realizarlo...           *|
|*                                                                          *|
|*  Entradas: Linea en la que comenzar el despliegue                        *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void PreparaDespliege( int NuevaY0 )
{
  struct Make_Boton {
	       int Up,  Left, Down, Right;
		unsigned char Cdf, Cb1,  Cb2;
		unsigned char Ab,  Pb;
		unsigned char Isc, Sc;
	};

  extern struct Make_Boton far *Botones;
  int i, IniSec, Incremento;

  int Up_Base[]   = {   5,  5,  41,  72, 123, 159 };
  int Down_Base[] = { 186, 31,  67, 118, 149, 185 };

  IniSec = P_Sec( 5 - 1 );

     for ( i = 0; i < 7; i ++ )
     {
        Botones[ i + IniSec ].Up   = Up_Base[i];
        Botones[ i + IniSec ].Down = Down_Base[i];
     }



  Incremento = NuevaY0 - Botones[ 0 ]. Up;


  for ( i = 0; i < 7; i ++ )
  {
        Botones[ i + IniSec ].Up   += Incremento;
        Botones[ i + IniSec ].Down += Incremento;
  }

  Imprime_Secuencia( 5 );

  settextstyle( SMALL_FONT, VERT_DIR, 4 );

  setcolor( EGA_BLACK );
  outtextxy( 556,   3 + Incremento, " --> " );
  outtextxy( 556,  41 + Incremento, " >> " );
  outtextxy( 556,  72 + Incremento, " Salir " );
  outtextxy( 556, 123 + Incremento, " << " );
  outtextxy( 556, 157 + Incremento, " <-- " );

  setcolor( EGA_WHITE );
  outtextxy( 557,   4 + Incremento, " --> " );
  outtextxy( 557,  42 + Incremento, " >> " );
  outtextxy( 557,  73 + Incremento, " Salir " );
  outtextxy( 557, 124 + Incremento, " << " );
  outtextxy( 557, 158 + Incremento, " <-- " );

  settextstyle( SMALL_FONT, HORIZ_DIR, 4 );

}


 /**************************************************************************\
|*                                                                          *|
|*  MuestraDatosProvCmp                                                     *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Dado un registro, se muestran sucesivamente este y todos    *|
|*              los que hay por debajo de �l, hasta que se agote la base    *|
|*              o no quepan mas en la pantalla.                             *|
|*                                                                          *|
|*  Entradas: Registro por el que comenzar                                  *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraDatosProvCmp( long RowStart, int RowCmp )
{
 int linea;
 char dev;
 int X0, Y0, X1, Y1;

 // Imprimo la NLINEAS_CMP que caben en la pantalla
 dev = OK;
 for ( linea=0; linea < NLINEAS_PROVcmp && dev == OK; linea++ )
 {
   dev = BProv.LeeReg( (void *)&SProv, RowStart + linea );
   if ( dev == OK )
              MuestraProvCmp( linea, NORMAL, RowCmp );
 }

  // Ahora limpio los restantes huecos si los hay
  if ( linea <= NLINEAS_PROVcmp )
  {
   if ( dev != OK ) linea--;
   setfillstyle( SOLID_FILL, Config.TxtBgN );
   for ( ; linea < NLINEAS_PROVcmp; linea++ )
   {
        ObtenCoordenadasProvCmp( RowCmp, linea, &X0, &Y0, &X1, &Y1 );
        bar( X0, Y0, X1, Y1 );
   }
  }
}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenCoordenadasProvCmp                                                 *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Obtiene las coordenadas de acotacion para el campo pedido   *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo del que obtener las coordenadas              *|
|*            linea      linea en la que nos encontramos                    *|
|*            X0 Y0 X1 Y1  Punteros para devolver las coordenadas           *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void ObtenCoordenadasProvCmp( int RowCmp, char linea, int *X0, int *Y0, int *X1, int *Y1 )
{

 // Calculamos la Y0, Y1 para la linea dada ( SOLO columna < 6 )
 ObtenCoordenadasCmp( 3, RowCmp, X0, Y0, X1, Y1 );

 *Y1 = *Y1 - 40 - 15*linea  ;
 *Y0 = *Y1 + 13             ;

 *X0 = 418;
 *X1 = 546;

}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraProvCmp                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Reescribe el campo dado, seg�n la fila, y la intensidad     *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha mostar                                    *|
|*            linea      linea en la que nos encontramos                    *|
|*            como       intensidad del texto (NORMAL/INTENSO)              *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraProvCmp( int linea, char como, int RowCmp )
{
 char buffer[80];

 int X0, Y0, X1, Y1;

 ObtenCoordenadasProvCmp( RowCmp, linea, &X0, &Y0, &X1, &Y1 );

 SProv.ActividadProveedor[20] = '\0';
 sprintf ( buffer, "%21s", SProv.ActividadProveedor );

 setfillstyle( SOLID_FILL, ( como == NORMAL ) ? Config.TxtBgN : Config.TxtBgI );
 bar( X0, Y0, X1, Y1 );
 setcolor ( ( como == NORMAL ) ? Config.TxtFgN : Config.TxtFgI );
 outtextxy( X0+2, Y1, buffer );

 if ( como == INTENSO )
 {
  ObtenCoordenadasCmp( 3, RowCmp, &X0, &Y0, &X1, &Y1 );
  setfillstyle( SOLID_FILL, ( como == NORMAL ) ? Config.TxtBgN : Config.TxtBgI );
  bar( X0, Y0, X1, Y1 );
  setcolor ( ( como == NORMAL ) ? Config.TxtFgN : Config.TxtFgI );
  sprintf ( buffer, "Codigo: %11ld", SProv.CodigoR );
  outtextxy( X0+2, Y0, buffer );
 }

}




 /*************************************************************************\
|*                                                                         *|
|*  ActualizaProv                                                          *|
|*                                                                         *|
|*  Descripci�n:                                                           *|
|*              Busca y actualiza al proveedor,en el dia que corresponda,  *|
|*              en caso de no encontrarlo, lo a�ade.                       *|
|*  Entradas:                                                              *|
|*           Mes a actualizar                                              *|
|*           Dia a actualizar                                              *|
|*                                                                         *|
|*  Salidas: (ninguna)                                                     *|
|*                                                                         *|
 \*************************************************************************/
/*
void ActualizaProv( long CodigoProv )
{
 char enc;
 long i;



   // Quizas estamos situados sobre ella
   if ( SVentProv.CodigoR == CodigoProv )
   {
      // Asi que ya lo hemos encontrado
      enc = OK;
   } else {
      enc = ERROR;
      BVentProv.LeeReg( (void *)&SVentProv, 0 );
      // No estabamos sobre ella. Buscamos la referencia del producto
      for ( i = 0; i < BVentProv.Registros() && enc == ERROR; i ++ )
      {
       if ( SVentProv.CodigoR == CodigoR )
       {
        enc = OK;
       } else {
        BVentProv.LeeReg( (void *)&SVentProv, i );
       }
      }
   }

   // Llegado a este punto, ya se si se encuentra en el fichero o no,
   // asi que si no se encuentra en el fichero, lo inserto.
   if ( enc == ERROR )
   {

    NuevoRegistroInforme2( SVentProv );
    SVentProv.CodigoR = CodigoR;
    // 1� Obtenemos el nombre del producto ( si el Cod. 0 -> Tickets Varios )
    if ( MatchProveedor( CodigoR ) == OK )
    {
      strcpy ( SVentProv -> Nombre, SProv.Proveedor );
    } else {
      strcpy ( SVentProv -> Nombre, "Proveedor Varios" );
    }

    BVentProv.InsReg( (void *)SVentProv, BVentProv.Registros(), ARRIBA );
   }

}
*/