/*--------------------------------------------------------------------
 * FICHERO:  TrzCrea.c
 * OBJETIVO: Definir las funciones Trz_Crea() y Trz_Destruye()
 * AUTOR:    Pedro Reina
 * FECHA:    L.17.7.1995
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Funciones privadas
 *
 *   Trz_CalculaTamano()
 *
 * Funciones privadas PC
 *
 *   Trz_LeeVGA()
 *
 * Funciones privadas QL
 *
 *   Trz_LeeQL()
 *------------------------------------------------------------------*/

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

#include "Trozo.h"

#ifdef OLIMPO_PC
#include <conio.h>          /*  gettext()   */
#include <mem.h>            /*  movedata()  */
#include <dos.h>            /*  FP_SEG() FP_OFF  */
#endif

/*--------------------------------------------------------------------
 * Declaracin de funciones
 *------------------------------------------------------------------*/

static entero Trz_CalculaTamano();

#ifdef OLIMPO_PC
static int Trz_LeeVGA();
#endif

#ifdef OLIMPO_QL
static int Trz_LeeQL();
#endif

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

/*--------------------------------------------------------------Olimpo
 * FUNCION:  Trz_Crea()
 * OBJETIVO: Crear un trozo
 * ENTRADAS: La fila superior, la columna izquierda, la fila
 *           inferior y la columna derecha, todo en caracteres
 * SALIDAS:  Un trozo o NIL si no se puede crear
 * EJEMPLO:  Trz_Crea (3,4,14,70)
 * ALGORITMO:
 *      Anotar los datos bsicos del trozo
 *      Pedir memoria para los datos de la pantalla
 *      Salvar los datos de pantalla en la zona reservada
 *------------------------------------------------------------------*/
trozo Trz_Crea (F1,C1,F2,C2)
octeto F1, C1, F2, C2;
  {
  trozo   Nuevo = NIL;
  entero  Tamano;
  memoria Memoria;
  int     Correcto;

  if ( Nuevo = (trozo) Mem_Crea ((sizeof(Trz_st))) )
    {
    Trz_PonModo  (Nuevo, Pan_Modo());
    Trz_PonAncho (Nuevo, C2-C1+1);
    Trz_PonAlto  (Nuevo, F2-F1+1);

#ifdef OLIMPO_QL
    {
    contador PrimerPixel, UltimoPixel;
    octeto   PrimeraColumna, UltimaColumna;

    PrimerPixel = Pan_MargenIzquierdo() + Pan_AnchoCar() * C1;
    UltimoPixel = PrimerPixel + Pan_AnchoCar() * Trz_Ancho(Nuevo) - 1;
    PrimeraColumna = PrimerPixel / 8;
    UltimaColumna  = UltimoPixel / 8;

    Trz_PonColumna (Nuevo, UltimaColumna - PrimeraColumna + 1);
    Trz_PonBitsIzquierda (Nuevo, PrimerPixel - 8 * PrimeraColumna);
    Trz_PonBitsDerecha (Nuevo, 8 * (UltimaColumna+1) - UltimoPixel - 1);
    }
#endif

    Tamano = Trz_CalculaTamano (Nuevo);
    if ( Memoria = Mem_Crea (Tamano) )
      { Trz_PonDato (Nuevo, Memoria); }
    else
      {
      Trz_Destruye (Nuevo);
      Nuevo = NIL;
      }

    if ( Nuevo )
      {
#ifdef OLIMPO_PC
      if ( Trz_Modo (Nuevo) == PAN_TEXTO )
        { Correcto = gettext (C1+1,F1+1,C2+1,F2+1,Memoria); }
      else
        {
        Correcto = Trz_LeeVGA (F1*Pan_AltoCar()+Pan_MargenSuperior(),C1,
                               Trz_Alto(Nuevo)*Pan_AltoCar(),
                               Trz_Ancho(Nuevo), Memoria);
        }
#endif
#ifdef OLIMPO_QL
        Correcto = Trz_LeeQL (F1*Pan_AltoCar()+Pan_MargenSuperior(),
                              (Pan_MargenIzquierdo()+Pan_AnchoCar()*C1)/8,
                              Trz_Alto(Nuevo)*Pan_AltoCar(),
                              Trz_Columna(Nuevo), Memoria);
#endif
      if ( !Correcto )
        {
        Trz_Destruye (Nuevo);
        Nuevo = NIL;
        }
      }
    }

  return ( Nuevo );
  }

/*--------------------------------------------------------------------
 * FUNCION:  Trz_CalculaTamano()
 * OBJETIVO: Calcular la cantidad de memoria necesaria para almacenar
 *           los datos de un trozo
 * ENTRADAS: El trozo
 * SALIDAS:  El tamao necesario
 * EJEMPLO:  Trz_CalculaTamano ( Panel )
 *------------------------------------------------------------------*/
static entero Trz_CalculaTamano (Trozo)
trozo Trozo;
  {
  entero Tamano;

#ifdef OLIMPO_PC
  if ( Trz_Modo(Trozo) == PAN_TEXTO )
    /* Cada carcter necesita dos octetos */
    { Tamano = 2 * Trz_Alto(Trozo) * Trz_Ancho(Trozo); }
  else
    /* Cada fila de cada carcter necesita 4 octetos, uno para cada plano */
    { Tamano = Pan_AltoCar() * 4 * Trz_Alto(Trozo) * Trz_Ancho(Trozo); }
#endif

#ifdef OLIMPO_QL
    Tamano = 2 * Trz_Columna (Trozo) * Pan_AltoCar() * Trz_Alto(Trozo);
#endif

  return ( Tamano );
  }

/*--------------------------------------------------------------Olimpo
 * FUNCION:  Trz_Destruye()
 * OBJETIVO: Destruir un objeto trozo, liberando su memoria
 * ENTRADAS: El trozo
 * SALIDAS:  Ninguna
 * EJEMPLO:  Trz_Destruye ( Panel )
 * ALGORITMO:
 *      Si se ha reservado memoria para datos, liberarla
 *      Liberar la memoria del objeto trozo
 *------------------------------------------------------------------*/
void Trz_Destruye (Trozo)
trozo Trozo;
  {
  if ( Trz_Dato(Trozo) )  { Mem_Destruye (Trz_Dato(Trozo)); }
  Mem_Destruye (Trozo);
  }

#ifdef OLIMPO_PC
/*--------------------------------------------------------------------
 * FUNCION:  Trz_LeeVGA()
 * OBJETIVO: Leer un fragmento de pantalla VGA y almacenarlo en memoria
 * ENTRADAS: La fila superior (medida en pixels), la columna izquierda
 *           (medida en octetos), la altura (en pixels), la anchura (en
 *           octetos) y la zona de memoria donde dejar el resultado.
 * SALIDAS:  1, que indica que ha ido bien
 * EJEMPLO:  Trz_LeeVGA (100,3,120,40,Aux)
 *------------------------------------------------------------------*/
static int Trz_LeeVGA (Fila, Columna, Alto, Ancho, Memoria)
contador Fila, Columna, Alto, Ancho;
memoria  Memoria;
  {
  contador Plano, i;
  unsigned Comienzo;

  Pan_MandaOrden (0x3CE, 5, 0);

  /*
   * Olimpo no usa el plano 4 (intensidad),
   * pero lo incluyo por claridad y por si
   * alguna aplicacin lo necesita
   */

  for ( Plano=0 ; Plano<4 ; Plano++ )
    {
    Pan_MandaOrden (0x3CE, 4, Plano);
    Comienzo = 80 * Fila + Columna;

    for ( i=0 ; i<Alto ; i++ )
      {
      movedata (0xA000, Comienzo, FP_SEG(Memoria), FP_OFF(Memoria), Ancho);
      Memoria += Ancho;
      Comienzo += 80;
      }
    }

  Pan_MandaOrden (0x3CE, 5,0x10);
  Pan_MandaOrden (0x3CE, 4, 0);

  return ( 1 );
  }
#endif

#ifdef OLIMPO_QL
/*--------------------------------------------------------------------
 * FUNCION:  Trz_LeeQL()
 * OBJETIVO: Leer un fragmento de pantalla QL y almacenarlo en memoria
 * ENTRADAS: La fila superior (medida en pixels), la columna izquierda
 *           (medida en octetos), la altura (en pixels), la anchura (en
 *           octetos) y la zona de memoria donde dejar el resultado.
 * SALIDAS:  1, que indica que ha ido bien
 * EJEMPLO:  Trz_LeeQL (100,3,120,40,Aux)
 *------------------------------------------------------------------*/
static int Trz_LeeQL (Fila, Columna, Alto, Ancho, Memoria)
contador Fila, Columna, Alto, Ancho;
memoria  Memoria;
  {
  contador i;
  memoria  Comienzo;

  Ancho *= 2;
  Comienzo = (memoria) (Pan_Comienzo() + 128 * Fila + 2 * Columna);

  for ( i=0 ; i<Alto ; i++ )
    {
    Mem_Copia (Memoria, Comienzo, Ancho);
    Memoria += Ancho;
    Comienzo += 128;
    }

  return ( 1 );
  }
#endif

