#include <dos.h>
#include <math.h>
#include <time.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"
#include "tpv_num.h"

#define NLINEAS_VENT 15

#define NORMAL     0
#define BARRAS     1

BDatos BVentas;                  // Base de datos de Ventaserencias
VENTAS SVentas[101];             // 100 productos ( distintos ) maximo por ticket
INFORMACION_VENTAS S_IVentas;    // Datos sobre la venta del dia
                                 // Empresa a la que se le realizan las gestiones
extern char EmpresaActual[9];
extern struct date FechaGestionActual;

extern BDatos BEmpl;           // Base de Datos de empleados
extern INFO_EMPLEADOS SEmpl;   // Estructura de Empleados

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

extern BDatos   BProtector;    // Base de datos para el protector
extern MENSAJES SProtector;    // Para guardar los mensajes del protector

extern BDatos           BClt1;  // Base de datos de Clientes1: FICHAS
extern INFO_CLIENTES1   SClt1;  // Estructura de Clientes

extern BDatos           BClt2;  // Base de datos de Clientes2: COMPRAS
extern INFO_CLIENTES2   SClt2;  // Estructura de Clientes


S_CobroCompleto SCc;            // Estructura para el cobro completo


extern char BufferM[6][65 + 1];// Buffer para los mensajes...


  char CurrRow;                // Linea sobre la que estamos
  int  CurrVentas;             // Producto sobre el que estamos posicionados a golpes



 /*************************************\
|                                       |
|      Parte Principal del M�dulo       |
|                                       |
 \*************************************/
void MuestraTotal( void );
long ObtenPrecioVenta( void );
char ProcesaCobroCompleto( char AsignarComprasCliente );
void InicializaDatosVentas( void );
void RedibujaPantallaVentas( void );
void MuestraDatosVentas( int RowStart );
void MuestraAyudaVentas( char columna );
void VentasNuevoRegistro( VENTAS *MSVentas );
void EditItemVentas( char columna, int linea );
void ManipulaVentas( int Registro, char operacion );
long ActualizaStock( int Cantidad, int VentaCompra, char ComprasVentas );
void MuestraVentas( char columna, int linea, char como );
void InsertarLinea( char *CurrRow, int *CurrVentas, char *CurrCol );
void ObtenCoordenadasVentas( char columna, char linea, int *X0, int *Y0, int *X1, int *Y1 );


 /*************************************\
|                                       |
|       Parte Segunda del M�dulo        |
|                                       |
|     Secci�n para el cobro completo    |
|                                       |
 \*************************************/
void MuestraDatosCCVentas( void );
void MuestraCCVentas( char columna, char como );
void MuestraAyudaCCVentas( char columna );
void EditItemCCVentas( char columna );
extern void BuscaClt( char TipoBusqueda, char *CurrRow, long *CurrClt );
extern void EmplNuevoRegistro( INFO_EMPLEADOS *MSEmpl );
extern int MatchVendedor( long CodigoVendedor );
extern int MatchCliente( long CodigoCliente );
extern int MatchCCliente( long CodigoEnlace );
extern void CltNuevoRegistro( INFO_CLIENTES1 *NSClt1 );
void CopiaDatosClnt(void);
extern void CltNuevoEnlace( INFO_CLIENTES1 *TmpClt );

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

 /*************************************\
|                                       |
|        Parte Cuarta del M�dulo        |
|                                       |
|   Secci�n para cargar los elementos   |
|                                       |
|       Enlaces, a TPV_VENT.CPP         |
|                                       |
 \*************************************/
extern int  CargaProductos( void );
extern int  MatchRef( unsigned long Codigo, char NormalBarras );

extern void GeneraBalanceDiario( void );

extern void CargaDatosProtector( void );

int  far RatonVentas(void);
int  ProtectorPantalla( void );
void CargaDatosProtector( void );

p_graphics TotalVenta = { 15, 15, 6, 3, 3, Config.NumFg, Config.NumBg, Config.NumLn };
p_Ampliada MensajesLn = { 17,  92, 13, 2, 2, Config.DigBg, Config.DigFg, 0 };

extern char DiaActual, MesActual;

long TotalVendido = 0;    // Cuanto se lleva vendido hasta ahora ??
char NProductos   = 0;    // # de productos en el ticket actual
char OldNProductos   ;    // # de productos del ticket anterior.

char Buffer[80];
char Transaccion;


extern int ScrollUpProtectorPantalla(void);
extern double Protector;              // Variable temporal para que salte el protector

char SALIDA_TOTAL;
extern char *ptr_char;         // Puntero a la fuentes de caracteres propia
extern BDatos BConfig;         // Base con la configuracion del programa



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

 /**************************************************************************\
|*                                                                          *|
|*  RedibujaPantallasVentas                                                 *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Redibuja la pantalla de ventas, cuando se entra por primera *|
|*              vez, o se ha salido para realizar alguna gestion.           *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void RedibujaPantallaVentas(void)
{

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

 LeeFuentes(Config.Vent_msg);

 Imprime_Estaticos( 10, "systm\\Tpv.img");     // Imprime botones estaticos 'Seccion 1'

 MuestraDatosVentas( 0 );

 Numero_Digital(           -1,  &TotalVenta );

 MuestraTotal();

               // Luces de informaci�n
               if ( Config.OpcionesCaja.ImprimirTickets )
                                                      ponicono( 460+7,  5+7, led_on, 1 );
               else
                                                      ponicono( 460+7,  5+7, led_off, 1 );
               if ( Config.OpcionesCaja.CobroCompleto )
                                                      ponicono( 460+7, 50+7, led_on, 1 );
               else
                                                      ponicono( 460+7, 50+7, led_off, 1 );
               if ( SVentas[0].BarraMesa )
                                                      ponicono( 460+7, 95+7, led_on, 1 );
               else
                                                      ponicono( 460+7, 95+7, led_off, 1 );

}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraTotal                                                            *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Muestra el total con IVA ( servicio en mesa ) en los nos.   *|
|*              grandes y el total simple en los n�s peque�os.              *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraTotal( void )
{
 char buffer[80];
 char buffer1[80];

 // Dibujamos el total vendido incluyendo el IVA del servicio en mesa
 Numero_Digital( TotalVendido + ( SVentas[0].BarraMesa ? ( TotalVendido * Config.OpcionesCaja.PorcentajeMesa ) / 100 : 0 ),  &TotalVenta );

 formatea_u_long( (unsigned long)( TotalVendido ), buffer1 );
 sprintf( buffer, "%12s", buffer1 );

 setfillstyle( SOLID_FILL, Config.TxtBgN );
 bar( 507, 457, 633, 473 );
 setcolor ( Config.TxtFgN );
 outtextxy( 507, 457, buffer );

}

void AbreCajon(void)
{
 clock_t start;

  start = clock();
  while ( ( clock() - start ) / ( CLK_TCK / 16 ) <= 1 )
  {
   outportb( 0x2f8, 0x00 );
  }

}


 /**************************************************************************\
|*                                                                          *|
|*  VentasDiarias                                                           *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Gestiona las ventas diarias que se realizan                 *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
char UltimaPalabra;
void VentasDiarias( void )
{
 char buffer[100], ok = 0;
 int BPush, key;
 unsigned long PrecioC;
 long i;

#ifdef DEMOSTRACION
      char NumeroProductosVendidos = 0;
#endif

 SALIDA_TOTAL = !OK;


 char oldCol = -1;
 char CurrCol;         // Columna sobre la que estamos

 struct time HoraGestion, reloj;

 if ( VisualMode == OK )
 {
    Optar( 0, "Modo de Visualizaci�n", "No se permite la alteraci�n", "de datos en a�os pasados.", "- Consulte el manual -", NULL );
    return;
 }

 sprintf( Buffer, "1996 (c) JD. " );
 MensajesLn.x          = 15;              MensajesLn.y    = 92;
 MensajesLn.ndigitos   = 13;
 MensajesLn.AX         =  2;              MensajesLn.AY   =  2;
 MensajesLn.C1         =  Config.DigBg;   MensajesLn.C2   =  Config.DigFg;

 getdate( &FechaGestionActual );
 MesActual = FechaGestionActual.da_mon;
 DiaActual = FechaGestionActual.da_day;
 gettime( &reloj );
 sprintf( Buffer, "Hoy es %02d-%02d-%02d y son las %02d:%02d   ", FechaGestionActual.da_day, FechaGestionActual.da_mon, FechaGestionActual.da_year, (int)reloj.ti_hour, (int)reloj.ti_min );
 UltimaPalabra = strlen( Buffer ) - 3;

 char ClaveSalida[15];
 sprintf( ClaveSalida, "%02d%02d", FechaGestionActual.da_mon, FechaGestionActual.da_day );

 CargaDatosProtector();

 // Inicializamos los datos de ventas ( Nuevo ticket );
 InicializaDatosVentas();

 // Redibujamos la pantalla ( Esto se puede hacer ahora, por que los datos
 //                           se guardan en memoria )
 RedibujaPantallaVentas();

 // 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 ventas", "sin que existan productos", "que puedan ser vendidos", NULL );
  return;
 }

 // Abre un archivo temporal para agilizar la salvaguardia de datos
 // en bruto. ( Al abandonar este m�dulo, los datos del archivo temporal
 // se guardar�n en el archivo final, de una manera mas comoda y est�tica )

 sprintf( buffer, "datos\\%s\\Ventas.TMP", NEmpresa );
 if ( BVentas.AbrirReg( buffer, sizeof( VENTAS ) ) == ERROR )
                                                             Error( 1, BVentas.cError);
 if ( BVentas.Registros() == 0 )
 {
  gettime( &HoraGestion );

  S_IVentas.AperturaCaja.hora = HoraGestion.ti_hour;
  S_IVentas.AperturaCaja.min  = HoraGestion.ti_min;

  S_IVentas.Dia  = FechaGestionActual.da_day;
  S_IVentas.Mes  = FechaGestionActual.da_mon;
  S_IVentas.Anyo = FechaGestionActual.da_year;

  // Solo para el rango de cambio ;-)
  if ( HoraGestion.ti_hour >= 0 && HoraGestion.ti_hour < Config.VProductos.CambioHorario )
  {
   S_IVentas.Dia --;
   if ( S_IVentas.Dia <= 0 )
   {
    S_IVentas.Mes --;
    if ( S_IVentas.Mes <= 0 )
    {
     S_IVentas.Mes = 12;
     S_IVentas.Anyo--;
    }
    {
     // Dias de los meses si el a�o no es bisiesto
     auto char DiasMeses[12] = { 31, 00, 31, 30, 31, 30,
                           31, 31, 30, 31, 30, 31 };

     // Ajusta febrero si es bisiesto el a�o
     DiasMeses[1] = (S_IVentas.Anyo%4 == 0) ? 29 : 28;
     S_IVentas.Dia = DiasMeses[S_IVentas.Mes];
    }
   }


  }

  S_IVentas.Tickets = 0;
  S_IVentas.Cambio  = 0;

  BVentas.SalvaDatosUsuario( (void *)&S_IVentas );

 } else {

  BVentas.CargaDatosUsuario( (void *)&S_IVentas, sizeof( INFORMACION_VENTAS ) );

 }


 // Nos posicionamos en la primera venta
 CurrRow = CurrVentas = CurrCol = 0;
 Transaccion = ON;

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

      if ( Transaccion == ON )
            MuestraVentas( CurrCol, CurrRow+CurrVentas, INTENSO );

            BPush = Comprueba_Secuencia( 1, RatonVentas );

      if ( Transaccion == OFF )
      {
           Optar( ENCUADRE, NULL );
           SVentas[100] = SVentas[0];
           // Inicializamos los datos de ventas ( Nuevo ticket );
           InicializaDatosVentas();
           MuestraDatosVentas( 0 ); CurrRow = CurrVentas = CurrCol = 0;
           Transaccion = ON;
      } else
           MuestraVentas( CurrCol, CurrRow+CurrVentas, NORMAL  );

      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
#ifdef DEMOSTRACION
 if ( NumeroProductosVendidos > 5 )
 {
    while( kbhit() ) getch();
    Optar( 0, "VERSION DEMO", "El n�mero m�ximo de", "tickets por sesi�n", "es de CINCO!!!", NULL );
    break;
 }
#endif

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


               if ( CurrCol == 0 || CurrCol == 2 )
               {
                TotalVendido -= SVentas[CurrRow+CurrVentas].PrecioV * SVentas[CurrRow+CurrVentas].Cantidad;

                if ( MatchRef( SVentas[CurrRow+CurrVentas].CodigoR, NORMAL ) == OK )
                {
                 ActualizaStock( SVentas[CurrRow+CurrVentas].Cantidad, 1, VENTA );
                }
               }

               // Si la tecla que pulsamos fue intro y estamos en el campo
               // de cantidad, seguramente era para validar la cantidad...
               if ( ( CurrCol == 2 && key != 13 ) || CurrCol != 2 )
                EditItemVentas( CurrCol, CurrRow );
               while( kbhit() ) getch();

               // 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 ( MatchRef( SVentas[CurrRow+CurrVentas].CodigoR, NORMAL ) == OK )
                 {
                   // Ya se debe haber cargado la referencia, asi que podemos
                   // copiar los datos importantes y actualizar el stock

                   PrecioC = ActualizaStock( SVentas[CurrRow+CurrVentas].Cantidad, -1, VENTA );
                   SVentas[CurrRow+CurrVentas].PrecioC = PrecioC;

                   SVentas[CurrRow+CurrVentas].PrecioV = ObtenPrecioVenta();

                 } else {
                   SVentas[CurrRow+CurrVentas].CodigoR = 0;
                 }
               }
                   TotalVendido += SVentas[CurrRow+CurrVentas].PrecioV * SVentas[CurrRow+CurrVentas].Cantidad;

                   MuestraVentas( 1, CurrRow+CurrVentas, NORMAL );
                   MuestraVentas( 3, CurrRow+CurrVentas, NORMAL );

                   MuestraTotal();

                   // Esto que sigue es para que el cursor avance solo y
                   // a�ada el producto autom�ticamente...

                   MuestraVentas( CurrCol, CurrRow+CurrVentas, NORMAL  );
                   switch ( CurrCol )
                   {
                    case 0:
                           if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
                                CurrCol = 3;
                           else
                                CurrCol = 2;
                           break;
                    case 1:
                    case 2:
                           if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
                           {
                                                                    CurrCol = 3;
                           } else {
                            // de lo contrario, insertamos una nueva venta.
                            InsertarLinea( &CurrRow, &CurrVentas, &CurrCol );
                          }
                          break;
                    case 3:
                          if ( SVentas[CurrRow+CurrVentas].PrecioV != 0 )
                                                    InsertarLinea( &CurrRow, &CurrVentas, &CurrCol );
                          break;
                   }
               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--;
                       switch ( CurrCol )
                       {
                        case 0:
                               if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
                                                                           CurrCol = 3;
                               else
                                                                           CurrCol = 2;
                               break;
                        case 1:
                        case 2:
                               CurrCol = 0;
                               break;
                        case 3:
                               CurrCol = 2;
                               break;
                       }
                       break;
                 // Flecha Derecha
                 case  77:
                 case   9:
                       // Solo se permite acceder a Todo cuando el Codigo es 0
                       //CurrCol++;
                       switch ( CurrCol )
                       {
                        case 0:
                        case 1:
                               CurrCol = 2;
                               break;
                        case 2:
                               if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
                                                                           CurrCol = 3;
                               else
                                                                           CurrCol = 0;
                               break;
                        case 3:
                               CurrCol = 0;
                               break;
                       }
                       break;
                 // Flecha Arriba
                 case  72:
                        if ( (CurrRow + CurrVentas) > 0 )
                        {
                         if ( ( CurrRow ) <= 0 )
                         {
                          CurrRow = NLINEAS_VENT - 1;          CurrVentas -= NLINEAS_VENT;
                          if ( CurrVentas < 0 ) CurrVentas = 0;

                          while( ( CurrRow + CurrVentas ) >= NProductos && CurrRow > 0 ) CurrRow--;
                          while( ( CurrRow + CurrVentas ) >= NProductos && CurrVentas > 0 ) CurrVentas++;

                          // Mostramos datos hasta que se nos acabe la pantalla
                          MuestraDatosVentas( CurrVentas );
                         } else {
                          CurrRow --; if ( CurrRow < 0 ) CurrRow = 0;
                         }

                        if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                        }
                       break;
                // Flecha Abajo
                case  80:
                        if ( ( CurrRow + CurrVentas ) < ( NProductos - 1 )  )
                        {

                         if ( ( CurrRow ) >= NLINEAS_VENT - 1 )
                         {
                           CurrRow = 0;		CurrVentas += NLINEAS_VENT;

                           while ( (CurrVentas + CurrRow) >= NProductos ) CurrVentas--;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosVentas( CurrVentas );
                         } else
                         	CurrRow++;
                        }
                        if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                       break;
                // Inicio
                case  71:
                       CurrRow = 0;
                       if ( CurrVentas != 0 )
                       {
                        CurrVentas = 0;

                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosVentas( CurrVentas );
                       }

                       if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                       break;
                // Fin
                case  79:
                       CurrRow = 0;
                       if ( CurrVentas != NProductos - NLINEAS_VENT )
                       {
                        CurrVentas = NProductos - NLINEAS_VENT;
                        if ( CurrVentas < 0 )
                        {
                         CurrVentas = 0;
                         CurrRow = NProductos-1;
                        }
                        // Mostramos datos hasta que se nos acabe la pantalla
                        MuestraDatosVentas( CurrVentas );
                       }

                       if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                       break;
                // Eliminar
                case 83:
                        TotalVendido -= SVentas[CurrRow+CurrVentas].PrecioV * SVentas[CurrRow+CurrVentas].Cantidad;
                        MuestraTotal();

                        if ( MatchRef( SVentas[CurrRow+CurrVentas].CodigoR, NORMAL ) == OK )
                        {
                          ActualizaStock( SVentas[CurrRow+CurrVentas].Cantidad,  1, VENTA );
                        }

                       ManipulaVentas( CurrVentas + CurrRow, ELIMINAR );

                       if ( NProductos == 0 )
                       {
                         ManipulaVentas( 0, INSERTAR );
                         VentasNuevoRegistro( &SVentas[0] );
                         CurrRow = 0;
                       } else

                         // Si he borrado el �ltimo registro subo una linea
                       if ( (CurrVentas+CurrRow) >= ( NProductos - 2 ) )
                       {
                         if ( (CurrRow + CurrVentas) > 0 )
                         {
                          if ( ( CurrRow ) <= 0 )
                          {
                           CurrRow = NLINEAS_VENT - 1;          CurrVentas -= NLINEAS_VENT;
                           if ( CurrVentas < 0 ) CurrVentas = 0;

                           while( ( CurrRow + CurrVentas ) >= NProductos && CurrRow > 0 ) CurrRow--;
                           while( ( CurrRow + CurrVentas ) >= NProductos && CurrVentas > 0 ) CurrVentas++;

                           // Mostramos datos hasta que se nos acabe la pantalla
                           MuestraDatosVentas( CurrVentas );
                          } else {
                           CurrRow --; if ( CurrRow < 0 ) CurrRow = 0;
                          }
                         }
                       }

                       // Mostramos datos hasta que se nos acabe la pantalla
                       MuestraDatosVentas( CurrVentas );
                       if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
        	       break;
                // Insertar
                case 82:
                         InsertarLinea( &CurrRow, &CurrVentas, &CurrCol );
                         break;
                // Retroceso R�pido
                case 73:
                         CurrRow = NLINEAS_VENT - 1;          CurrVentas -= NLINEAS_VENT;
                         if ( CurrVentas < 0 ) CurrVentas = 0;

                         while( ( CurrRow + CurrVentas ) >= NProductos && CurrRow > 0 ) CurrRow--;
                         while( ( CurrRow + CurrVentas ) >= NProductos && CurrVentas > 0 ) CurrVentas++;

                         // Mostramos datos hasta que se nos acabe la pantalla
                         MuestraDatosVentas( CurrVentas );

                         if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                         break;
                // AvanceR�pido
                case 81:
                         CurrRow = 0;		CurrVentas += NLINEAS_VENT;

                         while ( (CurrVentas + CurrRow) >= NProductos ) CurrVentas--;

                         // Mostramos datos hasta que se nos acabe la pantalla
                         MuestraDatosVentas( CurrVentas );

                         if ( SVentas[CurrRow+CurrVentas].CodigoR != 0 && ( CurrCol == 1 || CurrCol == 3 ) ) CurrCol = 0;
                         break;
               }
	       break;
       // Imprimir �ltimo ticket
       case  1:
               // Solo si hay solo un producto ( y es no valido )
               if ( NProductos == 1 && SVentas[0].CodigoR == 0 && SVentas[0].PrecioV == 0 )
               {
                NProductos    = OldNProductos;
                SVentas[0]    = SVentas[100];

                if ( ProcesaCobroCompleto( !Config.OpcionesCaja.CobroCompleto ) == OK )
                {
                 // Tengo que modificar la compra del cliente: � Quien se la vendio ?
                 // ...pero solo lo hago si no esta activado el C.Completo
                 if ( !Config.OpcionesCaja.CobroCompleto )
                  for ( i = BVentas.Registros()-NProductos; i < BVentas.Registros(); i++ )
                  {
                     BVentas.LeeReg( (void *)&SVentas[1], i );
                     SVentas[1].CodigoVendedor = SVentas[0].CodigoVendedor;
                     BVentas.EscribeReg( (void *)&SVentas[1], i );
                  }
                }
                VentasNuevoRegistro( &SVentas[0] );

                OldNProductos = NProductos;
                NProductos    =          1;
                CurrRow = CurrVentas = CurrCol = 0; oldCol = -1;
               } else {
                Optar( 0, " �� No mas facturas !! ", "Solo se permite una factura", "pulsando el boton C.Completo", NULL );
               }
	       break;
       // Imprimir Tickets
       case  2:
               Config.OpcionesCaja.ImprimirTickets = !Config.OpcionesCaja.ImprimirTickets;
               if ( Config.OpcionesCaja.ImprimirTickets )
                                                      ponicono( 460+7, 5+7, led_on, 1 );
               else
                                                      ponicono( 460+7, 5+7, led_off, 1 );
               break;
       // Cobro Completo
       case  3:
               Config.OpcionesCaja.CobroCompleto = !Config.OpcionesCaja.CobroCompleto;
               if ( Config.OpcionesCaja.CobroCompleto )
                                                      ponicono( 460+7, 50+7, led_on, 1 );
               else
                                                      ponicono( 460+7, 50+7, led_off, 1 );
               break;
       // Servicio en mesa
       case  4:
               SVentas[0].BarraMesa = !SVentas[0].BarraMesa;
               if ( SVentas[0].BarraMesa )
                                                      ponicono( 460+7, 95+7, led_on, 1 );
               else
                                                      ponicono( 460+7, 95+7, led_off, 1 );
               MuestraTotal();
               break;
       // Enlace a la seccion de gastos / compras
       case  5:
               // Cerramos los archivos abiertos que necesita el m�dulo
               farfree( BusquedaRef );
               BRef.CerrarReg();

               // Ejecutamos el m�dulo de compras ( con acceso limitado )
               ComprasDiarias( NINGUNO );

               // Vuelvo a abrir los ficheros necesarios
               CargaProductos();

               // Al volver de esta secci�n habr� que redibujar la pantalla
               RedibujaPantallaVentas();

               oldCol = -1;
               break;
       // Men� Pricipal
       case  6:
               if ( strcmp( PideClave( "Clave de Salida", ">>> registrando..." ), ClaveSalida ) == 0 )
               //if ( PideClaveUsuario() == OK  )
               {
                S_IVentas.SalidasExito ++;
                ok = 1;
               } else {
                S_IVentas.IntentosSalir ++;
                SALIDA_TOTAL = OK;
                ok = 1;
               }
               break;
       // Fichar ticket
       case  7:
#ifdef DEMOSTRACION
NumeroProductosVendidos++;
#endif
               // Apertura de la caja para cambio
               if ( NProductos == 1 && SVentas[0].CodigoR == 0 && SVentas[0].PrecioV == 0 )
               {
                // Solo un producto, y su codigo y precio venta == 0 ( CAMBIO )
                S_IVentas.Cambio++;


                // Abrimos la caja
                AbreCajon();


                // Indicamos que la transacci�n ha finalizado
                Optar( ENCUADRE, "Transacci�n finalizada", "Cajon abierto para cambio", "Registrando tiempo de apertura", "��� Sistema preparado !!!", NULL );
               } else {

               // Si se entra, es un ticket completo
               if ( Config.OpcionesCaja.CobroCompleto )
                      if ( ProcesaCobroCompleto( Config.OpcionesCaja.CobroCompleto ) == ERROR )
                                                        break;

               // Esto es un ticket normal

                // Guardamos la info del ticket
                for ( i = 0; i < NProductos; i++ )
                {
                    SVentas[i].CodigoVendedor = SVentas[0].CodigoVendedor;
                    SVentas[i].BarraMesa = SVentas[0].BarraMesa;
                   // Solo insertamos el registro si: CodigoR != 0
                   //                   o: CodigoR == 0 && PrecioV != 0
                   if ( SVentas[i].CodigoR != 0 || SVentas[i].PrecioV != 0 )
                     BVentas.InsReg( (void *)&SVentas[i], BVentas.Registros(), ARRIBA );
                }

                S_IVentas.Tickets++;

                // Abrimos la caja
                AbreCajon();

                // Imprimimos el ticket's si corresponde
                if ( Config.OpcionesCaja.ImprimirTickets )
                                                        ImprimeVentas( 4 );

                // Indicamos que la transacci�n ha finalizado
                Optar( ENCUADRE, "Transacci�n finalizada", "La transacci�n ha finalizado", "sistema preparado para", "una nueva transacci�n.", NULL );
               }
               // Salvamos los datos estadisticos...
               BVentas.SalvaDatosUsuario( (void *)&S_IVentas );
               Transaccion = OFF;
               CurrRow = CurrVentas = CurrCol = 0; oldCol = -1;
               break;
       // Anular Ticket
       case  8:
               // ReActualizamos el stock
               for ( i = 0; i < NProductos; i++ )
               {
                 if ( MatchRef( SVentas[i].CodigoR, NORMAL ) == OK )
                                  ActualizaStock( SVentas[i].Cantidad, 1, VENTA );
               }

               // Inicializamos los datos de ventas ( Nuevo ticket );
               InicializaDatosVentas();
               // Redibujamos la pantalla ( Esto se puede hacer ahora, por que los datos
               //                           se guardan en memoria )
               MuestraDatosVentas( 0 ); CurrRow = CurrVentas = CurrCol = 0; oldCol = -1;
               Numero_Digital(           -1,  &TotalVenta );
               MuestraTotal();
               Transaccion = ON;
               break;
       default:
	       break;
      }

 } while( !ok );

 if ( Transaccion == ON )
   // ReActualizamos el stock
   for ( i = 0; i < NProductos; i++ )
   {
    if ( MatchRef( SVentas[i].CodigoR, NORMAL ) == OK )
                        ActualizaStock( SVentas[i].Cantidad, 1, VENTA );
   }


 gettime( &HoraGestion );
 S_IVentas.CierreCaja.hora   = HoraGestion.ti_hour;
 S_IVentas.CierreCaja.min    = HoraGestion.ti_min;
 BVentas.SalvaDatosUsuario( (void *)&S_IVentas );


 // Generamos el balance del dia y cerramos el archivo de ventas
 GeneraBalanceDiario();
 // El indice de referencias ya no nos hace falta
 farfree( BusquedaRef );
 BVentas.CerrarReg();
 BRef.CerrarReg();

 // Eliminamos el archivo temporal de ventas
 sprintf( buffer, "datos\\%s\\Ventas.TMP", NEmpresa );
 if ( unlink( buffer ) != 0 )
 {
    sprintf( buffer, "archivo: datos\\%s\\Ventas.TMP", NEmpresa );
    Optar( 0, "Error de eliminacion!", "Alguien impide eliminar el", buffer, "Eliminel� MANUALMENTE!!!", NULL );
 }


 if ( SALIDA_TOTAL == OK )
 {
  /*****************************\
 |* DesInicializamos todo y     *|                               ���ܲ��
 |* mostramos el mensaje final. *|                               ���߲��
  \*****************************/
 BConfig.CerrarReg();
 farfree( ptr_char );
 AnulaInterrupcion();
 closegraph();


 printf( "\nLa salida ILEGAL, acaba de ser registrada.\n��Queda un intento menos, para bloquear el programa!!\n" );
   exit( -1 );
 }

}


 /**************************************************************************\
|*                                                                          *|
|*  InsertatLinea                                                           *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Me he visto obligado a sacar esta parte del c�digo de la    *|
|*              funci�n principal, ya que se usa en distintas partes.       *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Linea en la que se inserta y posici�n f�sica, y columna        *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
 \**************************************************************************/
void InsertarLinea( char *CurrRow, int *CurrVentas, char *CurrCol )
{
 char campo;
                       ManipulaVentas( (*CurrVentas + *CurrRow), INSERTAR );
                       VentasNuevoRegistro( &SVentas[*CurrVentas+*CurrRow+1] );

                       if ( ( *CurrRow + *CurrVentas ) < NProductos - 1 )
                       {

                         if ( ( *CurrRow ) >= NLINEAS_VENT - 1 )
                         {
                          *CurrRow = 0;		*CurrVentas = *CurrVentas + NLINEAS_VENT;

                          while ( (*CurrVentas + *CurrRow) >= NProductos ) *CurrVentas = *CurrVentas - 1;

//                          MuestraDatosVentas( *CurrVentas );

                         } else
                          *CurrRow = *CurrRow + 1;
                          for  ( campo=0; campo < 4; campo++ )
                                  MuestraVentas( campo, *CurrRow + *CurrVentas, NORMAL );
                         }

                         *CurrCol = 0;
                         MuestraDatosVentas( *CurrVentas );
}

 /**************************************************************************\
|*                                                                          *|
|*  ManipulaVentas                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Inserta o elimina una venta                                 *|
|*                                                                          *|
|*  Entradas: Registro a manipular                                          *|
|*            Tipo de manipulacion INSERTAR / ELIMINAR                      *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void ManipulaVentas( int Registro, char operacion )
{
 int avance;

 if ( operacion == INSERTAR )
 {
  // Solo se permiten 100 compras por ticket
  if ( Registro > 99 )
                  return;

  NProductos++;

  avance = NProductos - 1;

  while( avance > (
  Registro+1) )
  {
   SVentas[ avance ] = SVentas[ avance - 1 ];
   avance--;
  }

 } else {

  NProductos --;

  if ( NProductos >= 0 )
  {
   avance = Registro;

   while( avance < NProductos )
   {
    SVentas[ avance ] = SVentas[ avance + 1 ];
    avance++;
   }
  }
 }

}


 /**************************************************************************\
|*                                                                          *|
|*  InicializaDatosVentas                                                      *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Inicializa los datos necesarios para un nuevo ticket        *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void InicializaDatosVentas(void)
{
 // Llevamos 0 ptas. vendidas
 TotalVendido = 0;

 OldNProductos = NProductos;
 // Hay solo 1 venta ( nada por defecto )
 NProductos = 1;
 VentasNuevoRegistro( &SVentas[0] );

}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenPrecioVenta                                                           *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Obtiene el precio de venta, dependiendo de la hora actual   *|
|*              ( se supone que la estructura SRef es sobre la que debemos  *|
|*               obtener el precio, y que esta actualizada )                *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  Precio de venta                                               *|
|*                                                                          *|
 \**************************************************************************/
long ObtenPrecioVenta( void )
{
 char i; long Precio;
 struct time t;

 gettime( &t );

 Precio = SRef.PrecioVenta[0];

 for ( i=1; i < 5; i++ )
      // 1� tienen que coincidir las horas
      if ( t.ti_hour >= Config.VProductos.HoraIni[i].hora && t.ti_hour <= Config.VProductos.HoraFin[i].hora &&
           t.ti_min  >= Config.VProductos.HoraIni[i].min  && t.ti_min  <= Config.VProductos.HoraFin[i].min     )
      {
                     Precio = SRef.PrecioVenta[i];
                     break;
      }

 return Precio;
}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraDatosVentas                                                         *|
|*                                                                          *|
|*  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 MuestraDatosVentas( int RowStart )
{
 int linea, campo;
 int X0, Y0, X1, Y1;

 linea = CurrRow;
 // Imprimo la NLINEAS_VENT que caben en la pantalla
 for ( CurrRow=0; CurrRow < NLINEAS_VENT && (CurrRow + RowStart) < NProductos; CurrRow++ )
 {
   // Por cada CurrRow hay 4 campos, ehhh!!!
      for  ( campo=0; campo < 4; campo++ )
                                  MuestraVentas( campo, CurrRow+RowStart, NORMAL );
 }

 // Ahora limpio los restantes huecos si los hay

  if ( CurrRow < NLINEAS_VENT )
 {
   setfillstyle( SOLID_FILL, Config.TxtBgN );
   for ( ; CurrRow < NLINEAS_VENT; CurrRow++ )
     for  ( campo=0; campo < 4; campo++ )
     {
        ObtenCoordenadasVentas( campo, CurrRow, &X0, &Y0, &X1, &Y1 );
        bar( X0, Y0, X1, Y1 );
     }
 }

 CurrRow = linea;

}

 /**************************************************************************\
|*                                                                          *|
|*  MuestraVentas                                                              *|
|*                                                                          *|
|*  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 MuestraVentas( char columna, int linea, char como )
{
 char buffer[80];
 char buffer1[80];

 int X0, Y0, X1, Y1;

 ObtenCoordenadasVentas( columna, CurrRow, &X0, &Y0, &X1, &Y1 );

 switch( columna )
 {
  // Codigo Real de la compra
  case  0:
       sprintf ( buffer, " %09lu", SVentas[linea].CodigoR  );
       break;
  // Nombre del producto
  case  1:
       if ( MatchRef( SVentas[linea].CodigoR, NORMAL ) == ERROR )
       {
         strcpy( buffer1, "Ticket Varios" );
         sprintf ( buffer, "  %30s", buffer1 );
       } else
       sprintf ( buffer, "  %30s",  SRef.Descripcion  );
       break;
  // Cantidad
  case  2:
       sprintf ( buffer, "%4d", SVentas[linea].Cantidad );
       break;
  // Total
  case  3:
       formatea_u_long( (unsigned long)( SVentas[linea].Cantidad * SVentas[linea].PrecioV ), 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 );
 outtextxy( X0+2, Y0, buffer );

 //������������������������������������������������������������������������
 //  �   �    �   �    �   �    �   �    �   �    �   �    �   �    �   �
 //������������������������������������������������������������������������
 //  �   �    �   �    �   �    �   �    �   �    �   �    �   �    �   �
 //������������������������������������������������������������������������
 /*
 setfillstyle( SOLID_FILL, Config.TxtFgN );
 bar( 507, 457, 633, 473 );
 formatea_long( (unsigned long)( SVentas[CurrRow+CurrVentas].PrecioC ), buffer );
 setcolor ( Config.TxtBgN );
 outtextxy( 507, 457, buffer );
*/
 //������������������������������������������������������������������������
 //  �   �    �   �    �   �    �   �    �   �    �   �    �   �    �   �
 //������������������������������������������������������������������������
 //  �   �    �   �    �   �    �   �    �   �    �   �    �   �    �   �
 //������������������������������������������������������������������������

}


 /**************************************************************************\
|*                                                                          *|
|*  MuestraAyudaVentas                                                      *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Muestra una peque�a descripcion del contenido para el campo *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha mostar su ayuda                           *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraAyudaVentas( 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;
  // Cantidad
  case  2:
       sprintf ( buffer1, "Unidades de venta" );
       break;
  // Total
  case  3:
       sprintf ( buffer1, "Total de la venta actual" );
       break;
 }

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

}

 /**************************************************************************\
|*                                                                          *|
|*  EditItemVentas                                                             *|
|*                                                                          *|
|*  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 EditItemVentas( char columna, int linea )
{
 char buffer[80];

 int X0, Y0, X1, Y1;

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

 switch( columna )
 {
  // Codigo Real
  case  0:
       buffer[0] = '\0';  // Creo que lo mejor es que teclee el c�digo desde cero
       if ( !( InputCadenaG( buffer, 1,  9, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
       SVentas[CurrRow+CurrVentas].CodigoR = atol( buffer );
       break;
  // Nombre del producto ( Solo si el codigo es el 0 )
  case  1:
/*
       if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
       {
// �����������������������������������������������������������������������������
          strcpy ( buffer, SVentas[CurrRow+CurrVentas].Descripcion   );
          if ( !( InputCadenaG( buffer, 0, 30, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
          strcpy ( SVentas[CurrRow+CurrVentas].Descripcion, buffer   );
// �����������������������������������������������������������������������������
       }
*/
       while( kbhit() ) getch();
       break;
  // Cantidad
  case  2:
       buffer[0] = '\0';
       if ( !( InputCadenaG( buffer, 1, 4, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
       SVentas[CurrRow+CurrVentas].Cantidad = atoi( buffer );

       if ( SVentas[CurrRow+CurrVentas].Cantidad == 0 )
          SVentas[CurrRow+CurrVentas].Cantidad = 1;
       break;
  // Total ( Solo Accesible con Codigo 0 )
  case  3:
       if ( SVentas[CurrRow+CurrVentas].CodigoR == 0 )
       {
        buffer[0] = '\0';
        if ( !( InputCadenaG( buffer, 1, 8, Config.TxtBgN, Config.TxtFgN, X0, Y0, X1, Y1) >> 8 ) )
        SVentas[CurrRow+CurrVentas].PrecioV = atol( buffer ) / SVentas[CurrRow+CurrVentas].Cantidad;
       }
       while( kbhit() ) getch();
       break;
  default:
       while( kbhit() ) getch();
       break;

 }

}

 /**************************************************************************\
|*                                                                          *|
|*  ObtenCoordenadasVentas                                                     *|
|*                                                                          *|
|*  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 ObtenCoordenadasVentas( 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 =  123;
       break;
  case 1:
       *X0 = 137;       *X1 = 468;
       break;
  case 2:
       *X0 = 482;       *X1 = 528;
       break;
  case 3:
       *X0 = 542;       *X1 = 632;
       break;
 }

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

}

 /**************************************************************************\
|*                                                                          *|
|*  VentasNuevoRegistro                                                        *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Limpia el buffer, para un nuevo registro.                   *|
|*                                                                          *|
|*  Entradas: (ninguna)                                                     *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void VentasNuevoRegistro( VENTAS *NSVentas )
{
 struct time t;

 gettime( &t );

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

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

 NSVentas -> PrecioV   = 0;         // Precio de venta

 NSVentas -> BarraMesa = 0;         // Servicio en barra o en mesa

 NSVentas -> PrecioC   = 0;         // Precio de Costo del Producto

 NSVentas -> CodigoVendedor = 0;    // C�digo del vendedor ( 0 gen�ricos )

                                    // Hora exacta de venta del producto
 NSVentas -> HoraV.hora = t.ti_hour;
 NSVentas -> HoraV.min  = t.ti_min;

}

 /**************************************************************************\
|*                                                                          *|
|*  ActualizaStock                                                          *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Actualiza el Stock teniendo en cuenta si es un combinado    *|
|*              Se supone que la referencia origen esta cargada en SRef.    *|
|*                                                                          *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*           Referencia Origen, Cantidad, VentaCompra ( -1, 1 )             *|
|*                                                                          *|
|*  Salidas: (ninguna)                                                      *|
|*                                                                          *|
|* ��� Nota: !!!                                                            *|
|*                                                                          *|
|*   COMBINADO PADRE:     producto que se llama a si mismo                  *|
|*   COMBINADO HIJO:      alguien llamo a un combinado padre (x partes util)*|
|*   COMBINADO NORMAL:    resto de casos                                    *|
|*                                                                          *|
 \**************************************************************************/
#define COMBINADO_NORMAL      1
#define COMBINADO_PADRE       2
#define COMBINADO_HIJO        3
#define COMBINADO_COMBINADO   0

long ActualizaStock( int Cantidad, int VentaCompra, char ComprasVentas )
{
  long CodigoR[10], BRef_pos, BRef_und, BRef_cod;
  unsigned long PrecioCosto;
  char i, j;
  char TipoCombinado = NORMAL;

  // Si no es un combinado, simplemente actualizamos en su Stock la cantidad
  if ( SRef.Combinado == 0 )
  {
      SRef.Stock += ( (long)Cantidad * VentaCompra );
      if ( BRef.EscribeReg( (void *)&SRef, BRef.RegActual() ) == ERROR )
                                                    Error(0x01, BRef.cError );
      PrecioCosto = SRef.PrecioCosto * Cantidad;
  } else {

      // Como es un combinado, tenemos que realizar un rastreo para actualizar
      // las referencias de cada combinado

      BRef_pos = BRef.RegActual();  // Guardamos la posici�n para saber de donde venimos
      BRef_und = SRef.CantUnitaria; // Unidades que hay que quitar a los subcodigos
      BRef_cod = SRef.CodigoR;

      // Guardamos los c�digos combinados
      for ( i = 0; i < 10; i++ )
        CodigoR[i] = SRef.CodigosAsociados[i];

      PrecioCosto = 0;

      // Ahora recorremos cada c�digo para actualizar el combinado
      for ( i = 0; i < 10; i++ )
        if ( CodigoR[i] )
        {
          if ( MatchRef( CodigoR[i], NORMAL ) == OK )
          {
            // Comprobamos si la sub-ref. es o no un combinado
            TipoCombinado = COMBINADO_COMBINADO;
            for ( j = 0; j < 10 && TipoCombinado == COMBINADO_COMBINADO; j++ )
            {
              if ( SRef.CodigoR == SRef.CodigosAsociados[j] )
              {
                if ( SRef.CodigoR == BRef_cod )
                  TipoCombinado = COMBINADO_PADRE;
                else
                  TipoCombinado = COMBINADO_HIJO;
              } else {
                TipoCombinado = COMBINADO_NORMAL;
              }
            }

            if ( SRef.Combinado == 0 || TipoCombinado != COMBINADO_COMBINADO )
            {
                switch( TipoCombinado )
                {
                  // C�digo padre ( lo estoy vendiendo entero )
                  case COMBINADO_HIJO:
                    // Solo vendo parte del c�digo padre
                    if ( ComprasVentas == COMPRA )
                      SRef.Stock  += ( (long)Cantidad *         /*SRef.CantUnitaria*/   VentaCompra );
                    else
                      SRef.Stock  += ( (long)Cantidad * BRef_und/*SRef.CantUnitaria*/ * VentaCompra );
                    PrecioCosto += SRef.CantUnitaria == 0 ? 1 : (long)( ( (double)(SRef.PrecioCosto / SRef.CantUnitaria ) * Cantidad ) );
                    break;
                  case COMBINADO_PADRE:
                    if ( ComprasVentas == COMPRA )
                      SRef.Stock  += ( (long)Cantidad *                     VentaCompra );
                    else
                      SRef.Stock  += ( (long)Cantidad * SRef.CantUnitaria * VentaCompra );
                    Cantidad = Cantidad / SRef.CantUnitaria;
                    PrecioCosto +=   SRef.PrecioCosto    * Cantidad;
                    break;
                  case COMBINADO_NORMAL:
                  default:
                    SRef.Stock  += ( (long)Cantidad /** SRef.CantUnitaria*/ * VentaCompra );
                    PrecioCosto +=   SRef.PrecioCosto    * Cantidad;
                    break;
                }

              if ( BRef.EscribeReg( (void *)&SRef, BRef.RegActual() ) == ERROR )
                Error(0x01, BRef.cError );

            } else {
              PrecioCosto += ActualizaStock( ( Cantidad * SRef.CantUnitaria ), VentaCompra, ComprasVentas );
            } // Fin sub-ref. es combinado / no combinado
        }
      }

   BRef.LeeReg( (void *)&SRef, BRef_pos );

  } // Fin no combinado / combinado

  return PrecioCosto;

}



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

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


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

 printf( "\n\r" );
 ImprimeCabeceraVentas( como, file_out );

 for ( i=0; i < NProductos; i++ )
 {

  switch( como )
  {
   case 1:
        break;
   case 2:
        break;
   case 3:
        break;
   case 4:
        if ( SVentas[i].PrecioV != 0 || SVentas[i].CodigoR != 0 )
        {
         formatea_u_long( (unsigned long)SVentas[i].PrecioV*SVentas[i].Cantidad, buffer );
         if ( MatchRef( SVentas[i].CodigoR, NORMAL ) == OK )
           fprintf( file_out, "%9lu  %-30s %4ld %6s\n\r", (unsigned long)SVentas[i].CodigoR, SRef.Descripcion, (long)SVentas[i].Cantidad, buffer );
         else
           fprintf( file_out, "%9lu  Tickets varios                 %4ld %6s\n\r",(unsigned long) SVentas[i].CodigoR, (long)SVentas[i].Cantidad, buffer );

         Suma_Total += SVentas[i].PrecioV*SVentas[i].Cantidad;
        }
        break;
  }
 }

 if ( como == 4 )
 {
   formatea_long( Suma_Total, buffer );
   fprintf ( file_out, "\n\r Suma total                               %11s\n\r", buffer );
   for ( i=0; i < 4; i++ )
     fprintf( file_out, "\n\r%s", &Config.Impresora.FinTickets[i][0] );
 }

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

}

void ImprimeCabeceraVentas( char como, FILE *file_out )
{
  int i;

  switch( como )
  {
    case 1:
         break;
    case 2:
         break;
    case 3:
         break;
    case 4:
        for ( i=0; i < 4; i++ )
           fprintf( file_out, "%s\n\r", &Config.Impresora.PrincipioTickets[i][0] );
        fprintf( file_out, "\n\rC�digo     Articulo                       Cant  P.Total \n\r" );
        break;
  }
}




//���������������������������������������������������������������������������
// �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �

int ProtectorPantalla( void )
{

  p_Ampliada far *LetraG[6];
  int Pasadas = 20*8 - 1;
  time_t first;
  char Paso;

  int i;

  for ( i = 0; i < 6; i++ )
      if ( ( LetraG[i] = ( p_Ampliada far * )farmalloc( sizeof( p_Ampliada ) ) ) == NULL )
      {
       for ( i=0; i < 6; i++ )
                farfree( LetraG[i] );
       ungetch( 255 );
       return 0;
      }



  LetraG[0] -> x        =  0;      LetraG[0] -> y  = 0;
  LetraG[0] -> ndigitos = 20;
  LetraG[0] -> AX       =  2;      LetraG[0] -> AY = 2;
  LetraG[0] -> C1       =  0;      LetraG[0] -> C2 = Config.DigFg+5;
  LetraG[0] -> C3       =  0;

  *LetraG[5] = *LetraG[4] = *LetraG[3] = *LetraG[2] = *LetraG[1] = *LetraG[0];

  LetraG[1] -> y =  32;
  LetraG[2] -> y =  64;
  LetraG[3] -> y =  96;
  LetraG[4] -> y = 128;
  LetraG[5] -> y = 160;

  for ( i = 0; i < 6; i++ )
  {
   LetraG[i] -> C1 = SProtector.CBg[i];
   LetraG[i] -> C2 = SProtector.CFg[i];
//   LetraG[i] -> Frase1[0] = '\0';
  }

  for ( i = 0; i < 6; i++ )
    sprintf( BufferM[i], "%-20s%-20s%-20s", SProtector.Mensaje1[i], SProtector.Mensaje2[i], SProtector.Mensaje3[i] );

  desactiva_raton();

  // Cambiamos a 320x200
  IntVect = OFF;

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

  LeeFuentes(Config.Prot_fnt);
  time( &first );


  Paso = 0;
  do {
      if ( Pasadas == -1 && difftime( time(NULL), first ) >= SProtector.TEspera )
      {
        Pasadas = 0;
        if ( Paso == 4 ) Paso = 1;
      }

      if ( Pasadas >= 0 )
      {
          Pasadas ++;
          if ( Pasadas > (Paso != 3 ? 20*8 : 20*8 ) )
          {
              time( &first );
              Pasadas = -1;
              Paso++;
          }
       }

       for ( i = 0; i < 6; i++ )
       {
           if ( SProtector.Desplaz[i] || Pasadas != -1 )
                   FuenteAmplia( BufferM[i], LetraG[i] );
       }


  } while( !kbhit() );


 while ( kbhit() ) getch();


 for ( i=0; i < 6; i++ )
           farfree( LetraG[i] );

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

 setgraphmode( 2 );
 inicializa_raton_grafico( 0, 0, 639, 479 );

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


 IntVect = ON;

 ungetch( 255 );

 return 0;
}


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

 clock_t start, end, start2;

 struct time first;
 struct time old;

 start2 = start = clock();

  activa_raton();

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

  do{
      end = clock();
      if ( Protector == 1 && ( ( end - start ) / CLK_TCK ) >= Config.Protector )
      {
        if ( Transaccion == OFF )
        {
           Optar( ENCUADRE, NULL );
           // Inicializamos los datos de ventas ( Nuevo ticket );
           InicializaDatosVentas();
           MuestraDatosVentas( 0 );
           Transaccion = ON;
        }
//��������������������������������������������������������������������������������������������������
//��������������������������������������������������������������������������������������������������
//           ProtectorPantalla();
 if ( ScrollUpProtectorPantalla() == 1 )
                                     ProtectorPantalla();
//��������������������������������������������������������������������������������������������������
//��������������������������������������������������������������������������������������������������

           RedibujaPantallaVentas();
           return 0;

      }
/*
      if ( (m++) >= Config.TiempoDezplazamiento )
      {
                            m = 0;
*/
      if ( ( (end - start2) / (CLK_TCK /*/ 4*/) ) >= 0.001 )
      {
        start2 = end;
        old = first;
        gettime( &first );
        if ( Protector == 1 && ( old.ti_min != first.ti_min || old.ti_hour != first.ti_hour ) )
          sprintf( Buffer, "Hoy es %02d-%02d-%02d y son las %02d:%02d   ", FechaGestionActual.da_day, FechaGestionActual.da_mon, FechaGestionActual.da_year, (int)first.ti_hour, (int)first.ti_min );

        Fuente_Amplia( Buffer, &MensajesLn );
      }

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

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


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


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

  desactiva_raton();
  return Que;
}


// �۲۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�������
// ���۲������۱�����۱����۲�����۲������۱�������۰�����۰۲۲۰���۲�����۲
// ���۲�۰��۲�۰���۱۰���۱۰���۱۰���۱����۲���۲۲�۰����۰۱��۱����۲
// ���۲�۰��۲�۰���۱۰���۱۰���۱۰���۱����۲���۲۲�۰۲۲۰۱��۱����۲
// ���۲�۰��۲�۰���۱����۲�۰��۲�۰���۱����۲���۲۲�۰۲۲۰���۲�����۲
// ���۲�۰��۲�۰���۱۰���۱�۱�۲�۰���۱����۲���۲۲�۰۲۲۰۱�۲�����۲
// ���۲�۰��۲�۰���۱۰���۱۰��۲�۰���۱����۲���۲۲�۰۲۲۰۱�۲�����۲
// ���۲������۱�����۱����۲�۰���۱�����۱�������۰�����۰۲۲۰۱�۲�����۲
// ���۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲
// �۲۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�����۲�������

 /**************************************************************************\
|*                                                                          *|
|*  ProcesaCobroCompleto                                                    *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Procesa un cobro completo, gestionando tanto al vendedor    *|
|*              como al cliente, para obtener datos posteriores sobre ellos *|
|*                                                                          *|
|*  Entradas: Si se desea o no asignar las compras al cliente (1�,2� vez)   *|
|*                                                                          *|
|*  Salidas:  Transacci�n aceptada o no!!!                                  *|
|*                                                                          *|
 \**************************************************************************/
char ProcesaCobroCompleto( char AsignarComprasCliente )
{
 int Status, ok;
 int CurrCol, oldCol;
 char CurrRow, OCRow;
 long CurrClnt, OCClnt;
 int BPush, key, i;
 char buffer[80];

 CurrRow = CurrClnt  = -1;
 CurrCol = 0; oldCol = -1;
 ok = 0; Status = ERROR;

/*
 if ( ( SClt2 = (INFO_CLIENTES2 *)malloc( sizeof( INFO_CLIENTES2 ) * TOTAL_COMPRAS_ANUAL ) )  == NULL )
 {
  Optar( 0, "� Memoria insuficiente !", "Atenci�n, no hay suficiente memoria", "libre, por lo que no se", "asignar�n las compras al Clte.", NULL );
  return Status;
 }
*/

 sprintf( buffer, "datos\\%s\\info_clt1.dbf", NEmpresa );
 if ( BClt1.AbrirReg( buffer, sizeof( INFO_CLIENTES1 ) ) == ERROR )
                                                             Error(0x01, BClt1.cError);

 sprintf( buffer, "datos\\%s\\info_clt2.%03d", NEmpresa, ( FechaGestionActual.da_year - (FechaGestionActual.da_year/1000)*1000 ) );
 if ( BClt2.AbrirReg( buffer, sizeof( INFO_CLIENTES2 ) * TOTAL_COMPRAS_ANUAL ) == ERROR )
                                                             Error(0x01, BClt2.cError);

 Imprime_Estaticos( 11, "systm\\Tpv.img");     // Imprime botones estaticos 'Seccion 1'

 // Si no existe el empleado gen�rico, obtenemos el nombre del primer empleado
 EmplNuevoRegistro( &SEmpl );
 SEmpl.CodigoR = 0;
 if ( MatchVendedor( SEmpl.CodigoR ) == ERROR )
  BEmpl.LeeReg( (void *)&SEmpl, 0 );

 SCc.EntregadoCaja = 0;

 CopiaDatosClnt();
 MuestraDatosCCVentas();

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

      MuestraCCVentas( CurrCol, INTENSO );

      BPush = Comprueba_Secuencia( 12, RatonVentas );

      MuestraCCVentas( CurrCol, NORMAL  );

      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()) == 255 )
                                           break;
               if ( key != 13 && key != 27 )
                                                     ungetch( key );


               EditItemCCVentas( CurrCol );
               if ( CurrCol == 0 )
               {
                // Busca al cliente cuyo c�digo concuerde
                if ( MatchCliente( SCc.CodCliente ) == ERROR )
                {
                 CltNuevoRegistro( &SClt1 );
                 SCc.CodCliente = SClt1.Codigo;
                 strcpy( SCc.Nombre, "Cliente -NUEVO-" );
                } else {
                 CopiaDatosClnt();
                }
                MuestraDatosCCVentas();

               }
               while( kbhit() ) getch();

               break;
       case -1:				  // Hay una tecla especial en BUFFER
               switch( getch() )
               {
                 // Flecha Izquierda
                 case  75:
                 case  15:
                 // Flecha Arriba
                 case  72:
                       CurrCol--; if ( CurrCol < 0 ) CurrCol = 0;
                       break;
                 // Flecha Derecha
                 case  77:
                 case   9:
                // Flecha Abajo
                case  80:
                       CurrCol++; if ( CurrCol > 9 ) CurrCol = 9;
                       break;
                // Inicio
                case  71:
                       CurrCol = 0;
                // Fin
                case  79:
                       CurrCol = 9;
                       break;
               }
	       break;
       // Aceptar
       case  1:
               Status = OK;
               ok = 1;
	       break;
       // Cancelar
       case  2:
               Status = ERROR;
               ok = 1;
               break;

       // Busca a un cliente determinado, desplegando el cuadro de busqueda.
       // Buscar Anterior
       case  3:
               OCRow = CurrRow; OCClnt = CurrClnt;
               BuscaClt( ATRAS, &CurrRow, &CurrClnt );
               if ( OCRow != CurrRow || OCClnt != CurrClnt )
                 CopiaDatosClnt();
               MuestraDatosCCVentas();
               break;
       // Buscar
       case  4:
               OCRow = CurrRow; OCClnt = CurrClnt;
               BuscaClt( NUEVA_BUSQUEDA, &CurrRow, &CurrClnt );
               if ( OCRow != CurrRow || OCClnt != CurrClnt )
                 CopiaDatosClnt();
               MuestraDatosCCVentas();
               break;
       // Buscar Posterior
       case  5:
               OCRow = CurrRow; OCClnt = CurrClnt;
               BuscaClt( ADELANTE, &CurrRow, &CurrClnt );
               if ( OCRow != CurrRow || OCClnt != CurrClnt )
                 CopiaDatosClnt();
               MuestraDatosCCVentas();
               break;
       default:
	       break;
      }
 } while ( !ok );

 ok = OK;
 if ( Status == OK )
 {
   SVentas[0].CodigoVendedor = SEmpl.CodigoR;
   if ( AsignarComprasCliente )
   {
    // Localizamos la ficha de ventas del cliente y le a�adimos los productos
    // que ha comprado, (solo c�digo, cant. y total) el resto (nombre prod.)
    // lo pillamos del archivo de venta de productos.
    if ( MatchCliente( SCc.CodCliente ) == ERROR )
    {
     if ( Optar( 1, "-Cliente Nuevo-", "� Desea dar de alta,", "a este nuevo cliente?", NULL ) )
     {
      // Si el cliente en cuesti�n no existe, habr� que crearlo...
      CltNuevoRegistro( &SClt1 );
      SClt1.Codigo = SCc.CodCliente;
      strcpy( SClt1.Cif     , SCc.CifNif );
      strcpy( SClt1.Nombre     , SCc.Nombre );
      strcpy( SClt1.Direccion  , SCc.Direccion );
      strcpy( SClt1.Localidad  , SCc.Localidad );
      strcpy( SClt1.Provincia  , SCc.Provincia );
      SClt1.CodPostal    = SCc.CodPostal;
      // Habrimos la base de datos de clientes y lo insertamos
      CltNuevoEnlace( &SClt1 );

      BClt1.EscribeReg( (void *)&SClt1, BClt1.RegActual() );
     } else {
      ok = ERROR;
     }
    }
    // Solo si el cliente existe, o lo dio de alta, le a�adimos sus compras
    if ( ok != ERROR )
    {
/*
     if ( MatchCCliente( SClt1.CodEnlace ) == ERROR )
     {
      SClt2[0].MesDia = (int)(S_IVentas.Mes<<8) || S_IVentas.Dia;
      SClt2[0].CodigoR = SClt1.CodEnlace;
      SClt2[0].Unidades = 0;
      SClt2[0].Total = 0;
      BClt2.InsReg( (void *)SClt2, BClt2.Registros(), ARRIBA );
     }
     MatchCCliente( SClt1.CodEnlace );
     BClt2.LeeReg( (void *)SClt2, BClt2.RegActual() );

     long NRegInicio = SClt2[0].Total;

     SClt2[0].Total += NProductos;
*/
     // Escribimos los  productos que ha comprado
     for ( i = 0; i < NProductos; i++/*, NRegInicio++ */ )
     {
      SClt2.CodEnlace                    = SClt1.CodEnlace;
      SClt2/*[i+1+NRegInicio]*/.MesDia   = (int)(S_IVentas.Mes<<8) || S_IVentas.Dia;
      SClt2/*[i+1+NRegInicio]*/.CodigoR  = SVentas[i].CodigoR;
      SClt2/*[i+1+NRegInicio]*/.Unidades = SVentas[i].Cantidad;
      SClt2/*[i+1+NRegInicio]*/.Total    = SVentas[i].PrecioC;
      BClt2.InsReg( (void *)&SClt2, BClt2.Registros(), ARRIBA );
     }
//     BClt2.EscribeReg( (void *)SClt2, BClt2.RegActual() );
    }
   }
   // Ahora abrimos la base de datos -> Ventas a Clientes <- e insertamos la compra
 }

// free( SClt2 );

 BClt1.CerrarReg();
 BClt2.CerrarReg();

 #ifdef DEMOSTRACION
  Optar( 0, "VERSION DEMO", "Registre el programa", "si realmente desea", "usarlo. ���Gracias!!!", NULL );
 #endif

 // Terminada la transaccion ( correcta o no ), redibujamos toda la pantalla
 RedibujaPantallaVentas();

 return Status;
}

#ifndef DEMOSTRACION
void MuestraDatosCCVentas(void)
{
 int i;

 // ...y los mostramos.
 for ( i = 0; i < 11; i++ )
  MuestraCCVentas( i, NORMAL );
}
#endif


void CopiaDatosClnt(void)
{
 // Copiamos los datos del cliente a nuestra estructura...
 SCc.CodCliente = SClt1.Codigo;
 strcpy( SCc.CifNif     , SClt1.Cif );
 strcpy( SCc.Nombre     , SClt1.Nombre );
 strcpy( SCc.Direccion  , SClt1.Direccion );
 strcpy( SCc.Localidad  , SClt1.Localidad );
 strcpy( SCc.Provincia  , SClt1.Provincia );
 SCc.CodPostal    = SClt1.CodPostal;
}


#ifndef DEMOSTRACION
 /**************************************************************************\
|*                                                                          *|
|*  MuestraCCVentas                                                         *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Reescribe el campo dado, seg�n la fila, y la intensidad     *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha mostar                                    *|
|*            como       intensidad del texto (NORMAL/INTENSO)              *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void MuestraCCVentas( char columna, char como )
{
 char buffer[80];
 char buffer1[80];

 int X0[]={ 240, 460, 240, 240, 240, 500, 240, 240, 400, 290, 475 },
     Y0[]={ 171, 171, 191, 211, 231, 231, 251, 291, 291, 311, 311 },
     X1[]={ 350, 575, 575, 575, 420, 575, 420, 330, 575, 380, 575 },
     Y1[]={ 189, 189, 209, 229, 249, 249, 269, 309, 309, 329, 329 };

 switch( columna )
 {
  // C�digo del Cliente
  case  0:
       sprintf ( buffer, " %09lu", SCc.CodCliente  );
       break;
  // Cif/Nif
  case  1:
       sprintf ( buffer, "%10s", SCc.CifNif );
       break;
  // Nombre del cliente
  case  2:
       sprintf ( buffer, " %27s",  SCc.Nombre );
       break;
  // Direccion
  case  3:
       sprintf ( buffer, " %30s",  SCc.Direccion );
       break;
  // Localidad
  case  4:
       sprintf ( buffer, " %15s",  SCc.Localidad );
       break;
  // Cod. Post
  case  5:
       sprintf ( buffer, " %ld",  SCc.CodPostal );
       break;
  // Provincia
  case  6:
       sprintf ( buffer, " %15s",  SCc.Provincia );
       break;
  // Cod. Vendedor
  case  7:
       sprintf ( buffer, " %ld",  SEmpl.CodigoR );
       break;
  // Nombre Vendedor
  case  8:
       sprintf ( buffer, " %15s %15s",  SEmpl.Nombre, SEmpl.Apellido1 );
       break;
  // Entregado a caja
  case  9:
       formatea_u_long( (unsigned long)( SCc.EntregadoCaja ), buffer1 );
       sprintf ( buffer, "%9s", buffer1 );
       break;
  // Devolver
  case 10:
       formatea_long( (unsigned long)( SCc.EntregadoCaja - TotalVendido ), buffer1 );
       sprintf ( buffer, "%9s", buffer1 );
       break;
 }

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

}
#endif

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

 switch( columna )
 {
  // Codigo del cliente
  case  0:
       sprintf ( buffer1, "C�digo del cliente. (Si el cliente no existe se crear�)" );
       break;
  // Nif/Cif
  case  1:
       sprintf ( buffer1, "Nif/Cif o equivalente." );
       break;
  // Nombre del cliente
  case  2:
       sprintf ( buffer1, "Nombre ( para el cliente si este no existe )" );
       break;
  // Direcci�n
  case  3:
       sprintf ( buffer1, "Direcci�n del cliente" );
       break;
  // Localidad
  case  4:
       sprintf ( buffer1, "Localidad del Cliente" );
       break;
  // Cod. Post
  case  5:
       sprintf ( buffer1, "C�digo postal del Cliente" );
       break;
  // Provincia
  case  6:
       sprintf ( buffer1, "Provincia del Cliente" );
       break;

  // Codigo de vendedor
  case  7:
       sprintf ( buffer1, "C�digo del vendedor" );
       break;
  // Nombre del vendedor
  case  8:
       sprintf ( buffer1, "Nombre del vendedor (no modificable)" );
       break;

  // Entregado a caja
  case  9:
       sprintf ( buffer1, "Importe que el cliente entrega a caja." );
       break;
  // Devolver caja
  case 10:
       sprintf ( buffer1, "Devoluci�n al cliente seg�n cantidad entregada." );
       break;
 }

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

}

 /**************************************************************************\
|*                                                                          *|
|*  EditItemCCVentas                                                        *|
|*                                                                          *|
|*  Descripci�n:                                                            *|
|*              Se encarga de editar y validar el campo.                    *|
|*                                                                          *|
|*  Entradas:                                                               *|
|*            columna    campo ha editar                                    *|
|*                                                                          *|
|*  Salidas:  (ninguna)                                                     *|
|*                                                                          *|
 \**************************************************************************/
void EditItemCCVentas( char columna )
{
 char buffer[80];

 int X0[]={ 240, 460, 240, 240, 240, 500, 240, 240, 400, 290, 475 },
     Y0[]={ 171, 171, 191, 211, 231, 231, 251, 291, 291, 311, 311 },
     X1[]={ 350, 575, 575, 575, 420, 575, 420, 330, 575, 380, 575 },
     Y1[]={ 189, 189, 209, 229, 249, 249, 269, 309, 309, 329, 329 };

 switch( columna )
 {
  // Codigo Cliente
  case  0:
       sprintf( buffer, "%ld", SCc.CodCliente );
       if ( !( InputCadenaG( buffer, 1,  9, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       SCc.CodCliente = atol( buffer );
       break;
  // CIF/NIF Cliente
  case  1:
       strcpy( buffer, SCc.CifNif );
       if ( !( InputCadenaG( buffer, 0, 10, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       strcpy( SCc.CifNif, buffer );
       break;
  // Nombre del Cliente
  case  2:
       strcpy( buffer, SCc.Nombre );
       if ( !( InputCadenaG( buffer, 0, 25, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       strcpy( SCc.Nombre, buffer );
       break;
  // Direcci�n
  case  3:
       strcpy( buffer, SCc.Direccion );
       if ( !( InputCadenaG( buffer, 0, 30, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       strcpy( SCc.Direccion, buffer );
       break;
  // Localidad
  case  4:
       strcpy( buffer, SCc.Localidad );
       if ( !( InputCadenaG( buffer, 0, 15, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       strcpy( SCc.Localidad, buffer );
       break;
  // Cod.Postal
  case  5:
       sprintf( buffer, "%ld", SCc.CodPostal );
       if ( !( InputCadenaG( buffer, 1, 4, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       SCc.CodPostal = atol( buffer );
       break;
  // Provincia
  case  6:
       strcpy( buffer, SCc.Provincia );
       if ( !( InputCadenaG( buffer, 0, 15, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       strcpy( SCc.Provincia, buffer );
       break;

  // C�digo vendedor
  case  7:
        sprintf( buffer, "%ld", SEmpl.CodigoR );
        if ( !( InputCadenaG( buffer, 1, 8, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
        {
         SEmpl.CodigoR = atol( buffer );
         // si modifico el c�digo de vendedor
         if ( MatchVendedor( SEmpl.CodigoR ) == ERROR )
         {
          SEmpl.CodigoR = 0;
          if ( MatchVendedor( SEmpl.CodigoR ) == ERROR )
          BEmpl.LeeReg( (void *)&SEmpl, 0 );
         }
         MuestraCCVentas( 7, NORMAL );
         MuestraCCVentas( 8, NORMAL );
        }
       break;
  // Entregado a caja
  case  9:
       sprintf( buffer, "%ld", SCc.EntregadoCaja );
       if ( !( InputCadenaG( buffer, 1, 5, Config.TxtBgN, Config.TxtFgN, X0[columna], Y0[columna], X1[columna], Y1[columna]) >> 8 ) )
       SCc.EntregadoCaja = atol( buffer );
       MuestraCCVentas( 10, NORMAL );
       break;

  default:
       while( kbhit() ) getch();
       break;

 }

}

/*
& 110, 160, 580, 340,       7, 63, 56, 2, 2
| 120, 170,                 2,  6,  0, 63, C�d. Cliente:               Cif/Nif:,
| 121, 171,                 2,  6,  0,  0, C�d. Cliente:               Cif/Nif:,
& 240, 171, 350, 189,      63,  7, 56, 0, 2
& 460, 171, 575, 189,      63,  7, 56, 0, 2
| 120, 190,                 2,  6,  0, 63, Nombre:,
| 121, 191,                 2,  6,  0,  0, Nombre:,
& 240, 191, 575, 209,      63,  7, 56, 0, 2
| 120, 210,                 2,  6,  0, 63, Direcci�n:,
| 121, 211,                 2,  6,  0,  0, Direcci�n:,
& 240, 211, 575, 229,      63,  7, 56, 0, 2
| 120, 230,                 2,  6,  0, 63, Localidad:                     Cod Post,
| 121, 231,                 2,  6,  0,  0, Localidad:                     Cod Post,
& 240, 231, 420, 249,      63,  7, 56, 0, 2
& 500, 231, 575, 249,      63,  7, 56, 0, 2
| 120, 250,                 2,  6,  0, 63, Provincia:,
| 121, 251,                 2,  6,  0,  0, Provincia:,
& 240, 251, 420, 269,      63,  7, 56, 0, 2
| 120, 290,                 2,  6,  0, 63, Cod.Vendedor:         Nombre:,
| 121, 291,                 2,  6,  0,  0, Cod.Vendedor:         Nombre:,
& 240, 291, 330, 309,      63,  7, 56, 0, 2
& 400, 291, 575, 309,      63,  7, 56, 0, 2
| 120, 310,                 2,  6,  0, 63, Entregado a caja:          devolver:,
| 121, 311,                 2,  6,  0,  0, Entregado a caja:          devolver:,
& 290, 311, 380, 329,      63,  7, 56, 0, 2
& 475, 311, 575, 329,      63,  7, 56, 0, 2
*/