// FARB_TABELLE_256 is 6 bit

#include <stdio.h>
#include <stdlib.h>  // abs
#include <malloc.h>
#include <conio.h>

#include "error.h"
#include "vesa.h"       /* zeile */
#include "file.h"
#include "pcx.h"

/* Module Defines */
#define LOAD_BUFFER_SIZE 5000
#define BIOS_INTERRUPT 0x10
#define PALETTEN_FUNKTIONEN 0x10
#define MEHRERE_DACS_SETZEN 0x12

/* Module globale Variablen */
FILE *pcx_akt_handle=NULL;
T_BYTE *pcx_load_buffer=NULL;
T_INT pcx_header_read=T_FALSE;
T_INT pcx_muss_gelesen_werden=T_FALSE;
T_INT pcx_buffer_counter=0;

/* globale Variablen initialisieren */
T_WORD pcx_error=T_OK;
PCX_HEADER pcx_header;
ZEILE_EINES_BILDES pcx_zeile_eines_bildes256={0,NULL};
FARB_TABELLE_256 pcx_256_farb_tabelle;
FARB_TABELLE_16 pcx_16_farb_tabelle;
T_INT pcx_bild_art=BILD_UNBEKANNT;
T_INT pcx_color16_default=0;
T_INT pcx_set_file_color_flag=T_TRUE;

/* Modul globale Funktion */
T_INT pcx_load_bild_buffer(T_VOID);
T_INT pcx_test_farben_aender16(T_VOID);
T_INT pcx_test_farben_aender256(T_VOID);

T_INT pcx_read_header(T_PCHAR filename)
{
 FILE  *handle;
 T_DEBUG_ENTRY("pcx_read_header",30)
 if ((handle=fopen(filename,"rb"))==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return pcx_error=FILE_OPEN_ERROR;
 }
 fread(&pcx_header, sizeof(PCX_HEADER), 1, handle);
 pcx_header_read=T_TRUE;
 fclose(handle);
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/

T_INT pcx_print_header_daten(T_VOID)
{
 T_DEBUG_ENTRY("pcx_print_header_daten",30)
 if (pcx_header_read==T_TRUE)
 {
  printf("\nHersteller             : %i",pcx_header.hersteller);
  printf("\nVersion                : ");
  switch (pcx_header.version)
  {
   case 0:
   {
    printf("2.5");
    break;
   }
   case 2:
   {
    printf("2.8");
    break;
   }
   case 5:
   {
    printf("3.0");
    break;
   }
   default:
   {
    printf("unbekannte Version (%i)",pcx_header.version);
     break;
   }
  }
  printf("\nKodierungsart          : %i",pcx_header.kodierungsart);
  printf("\nBits/Pixel             : %i",pcx_header.bits_pro_pixel);
  printf("\nBildgroesse (x,y,X,Y)  : %i,%i,%i,%i",pcx_header.xmin,pcx_header.ymin,pcx_header.xmax,pcx_header.ymax);
  printf("\nAufl”sung X            : %u",pcx_header.aufloesung_x);
  printf("\nAufl”sung Y            : %u",pcx_header.aufloesung_y);
  printf("\nFarbebenen             : %u",pcx_header.anzahl_farbebenen);
  printf("\nBytes/Zeile            : %u",pcx_header.bytes_pro_zeile);
  printf("\nFarbart                : %i",pcx_header.farb_art);
  pcx_bild_art=BILD_UNBEKANNT;
  if ((pcx_header.bits_pro_pixel==8)&&(pcx_header.anzahl_farbebenen==1))
   pcx_bild_art=BILD_IST_256_FARBE_BILD;
  if ((pcx_header.bits_pro_pixel==1)&&(pcx_header.anzahl_farbebenen==4))
   pcx_bild_art=BILD_IST_16_FARBE_BILD;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return pcx_error=T_OK;
 }
 T_DEBUG_SET_THIS_FUNCTION_ERROR(NO_PCX_HEADER_READ)
 T_DEBUG_LEAVE
 return pcx_error=NO_PCX_HEADER_READ;
}

/*************************************************************************/

T_INT pcx_open_file(T_PCHAR filename)
{
 T_DEBUG_ENTRY("pcx_open_file",30)
 pcx_bild_art=BILD_UNBEKANNT;
 pcx_close_file();
 if ((pcx_akt_handle=fopen(filename,"rb"))==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return pcx_error=FILE_OPEN_ERROR;
 }
 fread(&pcx_header, sizeof(PCX_HEADER), 1, pcx_akt_handle);
 if ((pcx_load_buffer=(T_BYTE  *)malloc(LOAD_BUFFER_SIZE+1))==NULL )
 {
  pcx_close_file();
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(GENERIC_MEMORY_NOT_AVAILABLE)
  T_DEBUG_LEAVE
  return pcx_error=GENERIC_MEMORY_NOT_AVAILABLE;
 }
 if ((pcx_header.bits_pro_pixel==8)&&(pcx_header.anzahl_farbebenen==1))
 {
  if (pcx_header.xmax-pcx_header.xmin+1>(MAX_ZEILEN_LEN-3))
  {
   pcx_close_file();
   T_DEBUG_FUNCTION_POSITION(3)
   T_DEBUG_SET_THIS_FUNCTION_ERROR(PCX_LINE_TO_LONG)
   T_DEBUG_LEAVE
   return pcx_error=PCX_LINE_TO_LONG;
  }
  pcx_bild_art=BILD_IST_256_FARBE_BILD;
  pcx_zeile_eines_bildes256.zeile=zeile;
  if (pcx_set_file_color_flag==T_TRUE)
  {
   pcx_get_color256();
   pcx_set_color256();
  }
 }
 if ((pcx_header.bits_pro_pixel==1)&&(pcx_header.anzahl_farbebenen==4))
 {
  if (pcx_header.xmax-pcx_header.xmin+1>(MAX_ZEILEN_LEN-3))
  {
   pcx_close_file();
   T_DEBUG_FUNCTION_POSITION(4)
   T_DEBUG_SET_THIS_FUNCTION_ERROR(PCX_LINE_TO_LONG)
   T_DEBUG_LEAVE
   return pcx_error=PCX_LINE_TO_LONG;
  }
  pcx_bild_art=BILD_IST_16_FARBE_BILD;
  pcx_zeile_eines_bildes256.zeile=zeile;
  if (pcx_set_file_color_flag==T_TRUE)
  {
   pcx_get_color16();
   pcx_set_color16(pcx_color16_default);
  }
 }
 if (pcx_bild_art==BILD_UNBEKANNT)
 {
  pcx_close_file();
  T_DEBUG_FUNCTION_POSITION(5)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(BILD_UNBEKANNT)
  T_DEBUG_LEAVE
  return pcx_error=BILD_UNBEKANNT;
 }
 pcx_header_read=T_TRUE;
 pcx_muss_gelesen_werden=T_TRUE;
 pcx_zeile_eines_bildes256.zeilen_laenge=pcx_header.xmax-pcx_header.xmin+1;
 fseek(pcx_akt_handle,128,FROM_FILE_START);
 pcx_load_bild_buffer();
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/

T_INT pcx_close_file(T_VOID)
{
 T_INT fehler=FILE_NOT_CLOSED;
 T_DEBUG_ENTRY("pcx_close_file",30)
 pcx_zeile_eines_bildes256.zeile=NULL;
 if (pcx_load_buffer)
 {
  free(pcx_load_buffer);
  pcx_load_buffer=NULL;
 }
 if (pcx_akt_handle)
 {
  fclose(pcx_akt_handle);
  pcx_akt_handle=NULL;
  fehler=T_OK;
 }
 pcx_muss_gelesen_werden=T_FALSE;
 T_DEBUG_LEAVE
 return pcx_error=fehler;
}

/*************************************************************************/

T_INT pcx_load_bild_buffer(T_VOID)
{
 T_INT fehler=PCX_FILE_END;
 T_INT bytes_read=0;
 T_DEBUG_ENTRY("pcx_load_bild_buffer",30)
 if (pcx_muss_gelesen_werden==T_TRUE)
 {
  bytes_read=fread(pcx_load_buffer, 1, LOAD_BUFFER_SIZE,pcx_akt_handle);
  if (bytes_read!=LOAD_BUFFER_SIZE)
  pcx_muss_gelesen_werden=T_FALSE;
  pcx_buffer_counter=0;
  fehler=T_OK;
 }
 T_DEBUG_LEAVE
 return pcx_error=fehler;
}

/*************************************************************************/

T_INT pcx_get_zeile256(T_VOID)
{
 T_INT crunched_wert;
 T_INT zeilen_counter=0;
 T_INT anzahl_der_bytes;
 T_INT zeilen_laenge=pcx_header.bytes_pro_zeile;
 T_PBYTE zeilen_pointer=pcx_zeile_eines_bildes256.zeile;
 T_INT i;
 T_DEBUG_ENTRY("pcx_get_zeile256",30)
 while (zeilen_counter!=zeilen_laenge)
 {
  crunched_wert=pcx_load_buffer[pcx_buffer_counter++];
  if (pcx_buffer_counter==LOAD_BUFFER_SIZE)
   pcx_load_bild_buffer();
  if (crunched_wert<192)
   zeilen_pointer[zeilen_counter++]=crunched_wert;
  else
  {
   anzahl_der_bytes=crunched_wert&63;
   crunched_wert=pcx_load_buffer[pcx_buffer_counter++];
   if (pcx_buffer_counter==LOAD_BUFFER_SIZE)
    pcx_load_bild_buffer();
   for (i=0;i<anzahl_der_bytes;i++)
    zeilen_pointer[zeilen_counter++]=crunched_wert;
  }
 }
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/

T_VOID pcx_get_color256(T_VOID)
{
 T_INT i;
 T_DEBUG_ENTRY("pcx_get_color256",30)
 fseek(pcx_akt_handle,-768,FROM_FILE_END);
 fread(&pcx_256_farb_tabelle,3,256,pcx_akt_handle);
 if (pcx_test_farben_aender256()==T_TRUE)
 {
  for (i=0;i<256;i++)
  {
   pcx_256_farb_tabelle.rgb_farben[i].red>>=2;
   pcx_256_farb_tabelle.rgb_farben[i].green>>=2;
   pcx_256_farb_tabelle.rgb_farben[i].blue>>=2;
  }
 }
 T_DEBUG_LEAVE
}

/*************************************************************************/

T_INT pcx_test_farben_aender256(T_VOID)
{
 T_INT fehler=T_FALSE;
 T_INT i;
 T_DEBUG_ENTRY("pcx_test_farben_aender256",30)
 for (i=0;i<256;i++)
 {
  if ((pcx_256_farb_tabelle.rgb_farben[i].red>192)  ||
      (pcx_256_farb_tabelle.rgb_farben[i].green>192)||
      (pcx_256_farb_tabelle.rgb_farben[i].blue>192)   )
  {
   fehler=T_TRUE;
   break;
  }
 }
 T_DEBUG_LEAVE
 return pcx_error=fehler;
}

/*************************************************************************/

T_INT pcx_get_zeile16(T_INT farb_offset)
{
 T_INT anzahl_der_bytes;
 T_INT i;
 register T_INT bit_innen;
 register T_INT crunched_wert;
 T_INT bit_or=1;
 T_PBYTE zeilen_pointer;
 T_PBYTE z;
 T_PBYTE z_e;
 T_DEBUG_ENTRY("pcx_get_zeile16",30)
 zeilen_pointer=z=z_e=pcx_zeile_eines_bildes256.zeile;
 z_e+=pcx_header.bytes_pro_zeile*8;
 for (i=0;i<pcx_zeile_eines_bildes256.zeilen_laenge;i++)
  zeilen_pointer[i]=farb_offset;
 while (bit_or<9)
 {
  crunched_wert=pcx_load_buffer[pcx_buffer_counter++];
  if (pcx_buffer_counter==LOAD_BUFFER_SIZE)
   pcx_load_bild_buffer();
  if (crunched_wert<192)
  {
   bit_innen=128;
   while (bit_innen)
   {
    if (crunched_wert & bit_innen)
     *zeilen_pointer+=bit_or;
    zeilen_pointer++;
    bit_innen>>=1;
   }
   if (zeilen_pointer>=z_e)
   {
    bit_or<<=1;
    zeilen_pointer=z;
   }
  }
  else
  {
   anzahl_der_bytes=crunched_wert&63;
   crunched_wert=pcx_load_buffer[pcx_buffer_counter++];
   if (pcx_buffer_counter==LOAD_BUFFER_SIZE)
    pcx_load_bild_buffer();
   for (i=0;i<anzahl_der_bytes;i++)
   {
    bit_innen=128;
    while (bit_innen)
    {
     if (crunched_wert & bit_innen)
      *zeilen_pointer+=bit_or;
     zeilen_pointer++;
     bit_innen>>=1;
    }
    if (zeilen_pointer>=z_e)
    {
     bit_or<<=1;
     zeilen_pointer=z;
    }
   }
  }
 }
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/

T_VOID pcx_get_color16(T_VOID)
{
 T_INT i;
 T_DEBUG_ENTRY("pcx_get_color16",30)
 fseek(pcx_akt_handle,16,FROM_FILE_START);
 fread(&pcx_16_farb_tabelle,3,16,pcx_akt_handle);
 if (pcx_test_farben_aender16()==T_TRUE)
 {
  for (i=0;i<16;i++)
  {
   pcx_16_farb_tabelle.rgb_farben[i].red>>=2;
   pcx_16_farb_tabelle.rgb_farben[i].green>>=2;
   pcx_16_farb_tabelle.rgb_farben[i].blue>>=2;
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].red=pcx_16_farb_tabelle.rgb_farben[i].red;
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].green=pcx_16_farb_tabelle.rgb_farben[i].green;
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].blue=pcx_16_farb_tabelle.rgb_farben[i].blue;
  }
 }
 else
 {
  for (i=0;i<16;i++)
  {
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].red=pcx_16_farb_tabelle.rgb_farben[i].red;
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].green=pcx_16_farb_tabelle.rgb_farben[i].green;
   pcx_256_farb_tabelle.rgb_farben[i+pcx_color16_default].blue=pcx_16_farb_tabelle.rgb_farben[i].blue;
  }
 }
 T_DEBUG_LEAVE
}

/*************************************************************************/

T_INT pcx_test_farben_aender16(T_VOID)
{
 T_INT fehler=T_FALSE;
 T_INT i;
 T_DEBUG_ENTRY("pcx_test_farben_aender16",30)
 for (i=0;i<16;i++)
 {
   if ((pcx_16_farb_tabelle.rgb_farben[i].red>192)  ||
       (pcx_16_farb_tabelle.rgb_farben[i].green>192)||
       (pcx_16_farb_tabelle.rgb_farben[i].blue>192)   )
  {
   fehler=T_TRUE;
   break;
  }
 }
 T_DEBUG_LEAVE
 return pcx_error=fehler;
}

/*************************************************************************/

T_INT pcx_write_256pic(T_INT x,T_INT y, T_INT len_x, T_INT len_y, T_PCHAR filename)
{
 FILE *this_file=NULL;
 PCX_HEADER this_pcx_header;
 FARB_TABELLE_256 this_256_tabelle;
 T_PBYTE zeilen_pointer;
 T_PBYTE f1;
// T_PBYTE f2;
 T_INT p,i;
 T_BYTE this_byte,zaehler;
 T_DEBUG_ENTRY("pcx_write_256pic",30)
 this_pcx_header.hersteller=10;
 this_pcx_header.version=5;
 this_pcx_header.kodierungsart=1;
 this_pcx_header.bits_pro_pixel=8;
 this_pcx_header.xmin=0;
 this_pcx_header.ymin=0;
 this_pcx_header.xmax=len_x-1;
 this_pcx_header.ymax=len_y-1;
 this_pcx_header.aufloesung_x=len_x;
 this_pcx_header.aufloesung_y=len_y;
 this_pcx_header.anzahl_farbebenen=1;
 this_pcx_header.bytes_pro_zeile=len_x;
 this_pcx_header.farb_art=1;
 pcx_zeile_eines_bildes256.zeile=zeile;
 pcx_zeile_eines_bildes256.zeilen_laenge=len_x;
 this_file = fopen(filename, "w+b"); /* file wird ueberschrieben */
 if (this_file==NULL)
 {
  pcx_error=FILE_OPEN_ERROR;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return FILE_OPEN_ERROR;
 }
 fwrite(&this_pcx_header,sizeof(PCX_HEADER),1,this_file);
 pcx_zeile_eines_bildes256.zeile=zeile;
 pcx_zeile_eines_bildes256.zeilen_laenge=len_x;
 zeilen_pointer=pcx_zeile_eines_bildes256.zeile;
 for (p=0; p<len_y; p++)
 {
  vesa_get_zeile(x,y+p,len_x,zeilen_pointer);
  i=0;
  while (i<len_x)
  {
   this_byte=zeilen_pointer[i++];
   zaehler=1+64+128;
   if (this_byte>63)
   {
    while ((zeilen_pointer[i]==this_byte)&&(zaehler!=255)&&(i<len_x))
    {
     i++;
     zaehler++;
    }
    fwrite(&zaehler,1,1,this_file);
    fwrite(&this_byte,1,1,this_file);
   }
   else
   {
    if (zeilen_pointer[i]!=this_byte)
     fwrite(&this_byte,1,1,this_file);
    else
    {
     while ((zeilen_pointer[i])==this_byte&&(zaehler!=255)&&(i<len_x))
     {
      i++;
      zaehler++;
     }
     fwrite(&zaehler,1,1,this_file);
     fwrite(&this_byte,1,1,this_file);
    }
   }
  }
 }
 f1=(T_PBYTE ) &this_256_tabelle.rgb_farben[0].red;
 vesa_get_mehrere_dac(0,256, &(this_256_tabelle.rgb_farben[0].red));
// f2=(T_PBYTE ) &pcx_256_farb_tabelle.rgb_farben[0].red;
// neu neu 5.1.'98

 for (i=0;i<768;i++)
  f1[i]<<=2;
 zaehler=12;    /* einleitung zur 256 Farbpalette */
 fwrite(&zaehler,1,1,this_file);
 fwrite(&this_256_tabelle,768,1,this_file);
 fclose(this_file);
 T_DEBUG_LEAVE
 return T_OK;
}

/*************************************************************************/

T_INT pcx_set_file_color(T_PCHAR filename)
{
 PCX_HEADER header;
 T_DEBUG_ENTRY("pcx_set_file_color",30)
 if (pcx_akt_handle!=NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_ALREADY_OPEN)
  T_DEBUG_LEAVE
  return pcx_error=FILE_ALREADY_OPEN;
 }
 if ((pcx_akt_handle=fopen(filename,"rb"))==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return pcx_error=FILE_OPEN_ERROR;
 }
 fread(&header, sizeof(PCX_HEADER), 1, pcx_akt_handle);
 if ((header.bits_pro_pixel==8)&&(header.anzahl_farbebenen==1))
 {
  pcx_get_color256();
 }
 if ((header.bits_pro_pixel==1)&&(header.anzahl_farbebenen==4))
 {
  pcx_get_color16();
 }
 fclose(pcx_akt_handle);
 pcx_akt_handle=NULL;
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/

T_INT pcx_get_256palette(FARB_TABELLE_256 *neue_farb_tabelle,T_PCHAR filename)
{
 FILE  *handle=NULL;
 /*static*/ PCX_HEADER header;
 T_INT bild_art=BILD_UNBEKANNT;
 T_INT fehler=T_FALSE;
 T_INT i;
 T_DEBUG_ENTRY("pcx_get_256palette",30)
 if ((neue_farb_tabelle==NULL)||(filename==NULL))
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return T_NOT_OK;
 }
 if ((handle=fopen(filename,"rb"))==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(FILE_OPEN_ERROR)
  T_DEBUG_LEAVE
  return pcx_error=FILE_OPEN_ERROR;
 }
 fread(&header, sizeof(PCX_HEADER), 1, handle);
 if ((pcx_header.bits_pro_pixel==8)&&(pcx_header.anzahl_farbebenen==1))
 {
  bild_art=BILD_IST_256_FARBE_BILD;
 }
 if ((pcx_header.bits_pro_pixel==1)&&(pcx_header.anzahl_farbebenen==4))
 {
  fclose(handle);
  T_DEBUG_FUNCTION_POSITION(3)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(BILD_IST_16_FARBE_BILD)
  T_DEBUG_LEAVE
  return bild_art=BILD_IST_16_FARBE_BILD;
 }
 if (bild_art==BILD_UNBEKANNT)
 {
  fclose(handle);
  T_DEBUG_FUNCTION_POSITION(4)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(BILD_UNBEKANNT)
  T_DEBUG_LEAVE
  return pcx_error=BILD_UNBEKANNT;
 }
 fseek(handle,-768,FROM_FILE_END);
 fread(neue_farb_tabelle,3,256,handle);
 for (i=0;i<256;i++)
 {
  if ((neue_farb_tabelle->rgb_farben[i].red>192)  ||
      (neue_farb_tabelle->rgb_farben[i].green>192)||
      (neue_farb_tabelle->rgb_farben[i].blue>192)   )
  {
   fehler=T_TRUE;
   break;
  }
 }
 if (fehler==T_TRUE)
 {
  for (i=0;i<256;i++)
  {
   neue_farb_tabelle->rgb_farben[i].red>>=2;
   neue_farb_tabelle->rgb_farben[i].green>>=2;
   neue_farb_tabelle->rgb_farben[i].blue>>=2;
  }
 }
 fclose(handle);
 T_DEBUG_LEAVE
 return pcx_error=T_OK;
}

/*************************************************************************/
/* eigene benutzte farben */
/* werden aus den pcx_256_farb_tabelle (oder so aehnlich) farben genommen */
/***************************************************************/

T_BYTE get_nearest_color(T_BYTE r1,T_BYTE g1,T_BYTE b1, FARB_TABELLE_256 farb_tabelle,T_INT start_farbe,T_INT end_farbe,T_INT equal)
{
 T_BYTE farbnummer=0;
 T_LONG help=100000000;
 T_PLONG distance;
 T_INT i;
 FARB_TABELLE farb_tab;
 T_DEBUG_ENTRY("get_nearest_color",30)
 farb_tab.anzahl=256;
 farb_tab.rgb_farben=farb_tabelle.rgb_farben;
 farb_tab.punkte=farb_tabelle.punkte;
 distance=get_distances_of_colors(r1,g1,b1,farb_tab,start_farbe,end_farbe,equal);
 if (distance==NULL)
 {
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return 0;
 }
 for (i=start_farbe;i<=end_farbe;i++)
 {
  if (distance[i]<help)
  {
   help=distance[i];
   farbnummer=i;
  }
 }
 free(distance);
 T_DEBUG_LEAVE
 return farbnummer;
}

/* eigene benutzte farben */
/* werden aus den pcx_256_farb_tabelle (oder so aehnlich) farben genommen */
/***************************************************************/

T_PLONG get_distances_of_colors(T_BYTE r1,T_BYTE g1,T_BYTE b1, FARB_TABELLE farb_tabelle,T_INT start_farbe,T_INT end_farbe,T_INT equal)
{
 T_PLONG distance=NULL;
 T_LONG max_med=0;
 T_LONG max_min=0;
 T_LONG med_min=0;
 T_LONG max_med1=0;
 T_LONG max_min1=0;
 T_LONG med_min1=0;
 T_LONG max_med2=0;
 T_LONG max_min2=0;
 T_LONG med_min2=0;
 T_INT i=0;
 T_INT RGB1[3]={0,0,0};
 T_INT color_max1=-1;
 T_INT color_med1=-1;
 T_INT color_min1=-1;
 T_INT equal_all_flag1=0;
 T_INT equal_first_two1=0;
 T_INT equal_second_two1=0;
 T_INT e_q_f=0;
 T_INT e_q_s=0;
 T_INT e_q_a=0;
 T_INT r2=0,g2=0,b2=0;
 T_INT RGB2[3]={0,0,0};
 T_INT color_max2=-1;
 T_INT color_med2=-1;
 T_INT color_min2=-1;
 T_INT equal_all_flag2=0;
 T_INT equal_first_two2=0;
 T_INT equal_second_two2=0;
 T_DEBUG_ENTRY("get_distances_of_colors",30)
 if ((start_farbe<0)||(end_farbe>farb_tabelle.anzahl-1)||(start_farbe>end_farbe))
 {
  printf("startwert fehler!");
  printf("\nget_distances_of_colors(..)");
  pcx_error=T_NOT_OK;
  T_DEBUG_FUNCTION_POSITION(1)
  T_DEBUG_LEAVE
  return NULL;
 }
 distance=(T_PLONG)malloc(sizeof(T_LONG)*(1+end_farbe)); /* dann zwar zuviel, aber man kann einfacher darauf zugreifen */
 if (distance==NULL)
 {
  printf("\nspeicher fehler!");
  printf("\nget_distances_of_colors(..)");
  pcx_error=GENERIC_MEMORY_NOT_AVAILABLE;
  T_DEBUG_FUNCTION_POSITION(2)
  T_DEBUG_SET_THIS_FUNCTION_ERROR(GENERIC_MEMORY_NOT_AVAILABLE)
  T_DEBUG_LEAVE
  return NULL;
 }
 RGB1[T_RED]=r1;
 RGB1[T_GREEN]=g1;
 RGB1[T_BLUE]=b1;
 if ((r1>b1)&&(r1>g1))
  color_max1=T_RED;
 if ((g1>r1)&&(g1>b1))
  color_max1=T_GREEN;
 if ((b1>r1)&&(b1>g1))
  color_max1=T_BLUE;
 if ((r1<b1)&&(r1<g1))
  color_min1=T_RED;
 if ((g1<r1)&&(g1<b1))
  color_min1=T_GREEN;
 if ((b1<r1)&&(b1<g1))
  color_min1=T_BLUE;
 if (((r1<b1)&&(r1>g1))||((r1>b1)&&(r1<g1)))
  color_med1=T_RED;
 if (((g1<r1)&&(g1>b1))||((g1>r1)&&(g1<b1)))
  color_med1=T_GREEN;
 if (((b1<r1)&&(b1>g1))||((b1>r1)&&(b1<g1)))
  color_med1=T_BLUE;
 if ((color_max1==-1)&&(color_min1==-1))
 {
  e_q_a=1;
  color_max1=T_RED;
  color_med1=T_GREEN;
  color_min1=T_BLUE;
 }
 if ((color_max1==-1)&&(color_med1==-1))
 {
  e_q_f=1;
  if (color_min1==T_RED)
  {
   color_max1=T_GREEN;
   color_med1=T_BLUE;
  }
  if (color_min1==T_GREEN)
  {
   color_max1=T_RED;
   color_med1=T_BLUE;
  }
  if (color_min1==T_BLUE)
  {
   color_max1=T_RED;
   color_med1=T_GREEN;
  }
 }
 if ((color_med1==-1)&&(color_min1==-1))
 {
  e_q_s=1;
  if (color_max1==T_RED)
  {
   color_med1=T_GREEN;
   color_min1=T_BLUE;
  }
  if (color_max1==T_GREEN)
  {
   color_med1=T_RED;
   color_min1=T_BLUE;
  }
  if (color_max1==T_BLUE)
  {
   color_med1=T_RED;
   color_min1=T_GREEN;
  }
 }
 if ((color_max1==-1)||(color_med1==-1)||(color_min1==-1))
 {
  printf("distanz -1 wert fehler!\n");
  printf("color_max1: %i\n",color_max1);
  printf("color_med1: %i\n",color_med1);
  printf("color_min1: %i\n",color_min1);
  free(distance);
  pcx_error=T_NOT_OK;
  T_DEBUG_FUNCTION_POSITION(3)
  T_DEBUG_LEAVE
  return NULL;
 }
 if (abs(RGB1[color_max1]-RGB1[color_min1])<equal)
 {
  equal_all_flag1=1;
  equal_second_two1=0;
  equal_first_two1=0;
 }
 if (equal_all_flag1==0)
 {
  if (abs(RGB1[color_med1]-RGB1[color_min1])<equal)
   equal_second_two1=1;
  if (abs(RGB1[color_max1]-RGB1[color_med1])<equal)
   equal_first_two1=1;
 }
 for (i=start_farbe;i<=end_farbe;i++)
 {
  color_max2=-1;
  color_med2=-1;
  color_min2=-1;
  equal_all_flag2=0;
  equal_first_two2=0;
  equal_second_two2=0;
  r2=farb_tabelle.rgb_farben[i].red;
  g2=farb_tabelle.rgb_farben[i].green;
  b2=farb_tabelle.rgb_farben[i].blue;
  RGB2[T_RED]=r2;
  RGB2[T_GREEN]=g2;
  RGB2[T_BLUE]=b2;
  if ((r2>b2)&&(r2>g2))
   color_max2=T_RED;
  if ((g2>r2)&&(g2>b2))
   color_max2=T_GREEN;
  if ((b2>r2)&&(b2>g2))
   color_max2=T_BLUE;
  if ((r2<b2)&&(r2<g2))
   color_min2=T_RED;
  if ((g2<r2)&&(g2<b2))
   color_min2=T_GREEN;
  if ((b2<r2)&&(b2<g2))
   color_min2=T_BLUE;
  if (((r2<b2)&&(r2>g2))||((r2>b2)&&(r2<g2)))
   color_med2=T_RED;
  if (((g2<r2)&&(g2>b2))||((g2>r2)&&(g2<b2)))
   color_med2=T_GREEN;
  if (((b2<r2)&&(b2>g2))||((b2>r2)&&(b2<g2)))
   color_med2=T_BLUE;
  if ((color_max2==-1)&&(color_min2==-1))
  {
   equal_all_flag2=1;
   color_max2=T_RED;
   color_med2=T_GREEN;
   color_min2=T_BLUE;
   if ((e_q_a==1)&&(color_max1==T_RED))
   {
    color_max2=T_GREEN;
    color_med2=T_RED;
    color_min2=T_BLUE;
   }
  }
  if ((color_max2==-1)&&(color_med2==-1))
  {
   equal_first_two2=1;
   if ((e_q_f==1)&&(color_min1==color_min2))
   {
    if (color_min2==T_RED)
    {
     color_med2=T_GREEN;
     color_max2=T_BLUE;
    }
    if (color_min2==T_GREEN)
    {
     color_med2=T_RED;
     color_max2=T_BLUE;
    }
    if (color_min2==T_BLUE)
    {
     color_med2=T_RED;
     color_max2=T_GREEN;
    }
   }
   else
   {
    if (color_min2==T_RED)
    {
     color_med2=T_BLUE;
     color_max2=T_GREEN;
    }
    if (color_min2==T_GREEN)
    {
     color_max2=T_RED;
     color_med2=T_BLUE;
    }
    if (color_min2==T_BLUE)
    {
     color_max2=T_RED;
     color_med2=T_GREEN;
    }
   }
  }
  if ((color_med2==-1)&&(color_min2==-1))
  {
   equal_second_two2=1;
   if ((e_q_s==1)&&(color_max1==color_max2))
   {
    if (color_max2==T_RED)
    {
     color_med2=T_BLUE;
     color_min2=T_GREEN;
    }
    if (color_max2==T_GREEN)
    {
     color_med2=T_BLUE;
     color_min2=T_RED;
    }
    if (color_max2==T_BLUE)
    {
     color_med2=T_GREEN;
     color_min2=T_RED;
    }
   }
   else
   {
    if (color_max2==T_RED)
    {
     color_med2=T_GREEN;
     color_min2=T_BLUE;
    }
    if (color_max2==T_GREEN)
    {
     color_med2=T_RED;
     color_min2=T_BLUE;
    }
    if (color_max2==T_BLUE)
    {
     color_med2=T_RED;
     color_min2=T_GREEN;
    }
   }
  }
  if ((color_max2==-1)||(color_med2==-1)||(color_min2==-1)  )
  {
   printf("distanz -1 wert fehler!\n");
   printf("color_max2: %i\n",color_max2);
   printf("color_med2: %i\n",color_med2);
   printf("color_min2: %i\n",color_min2);
   free(distance);
   pcx_error=T_NOT_OK;
   T_DEBUG_FUNCTION_POSITION(4)
   T_DEBUG_LEAVE
   return NULL;
  }
  if (abs(RGB2[color_max2]-RGB2[color_min2])<equal)
  {
   equal_all_flag2=1;
   equal_second_two2=0;
   equal_first_two2=0;
  }
  if (equal_all_flag2==0)
  {
   if (abs(RGB2[color_med2]-RGB2[color_min2])<equal)
    equal_second_two2=1;
   if (abs(RGB2[color_max2]-RGB2[color_med2])<equal)
    equal_first_two2=1;
  }
  distance[i] =MAX_OFF(abs(RGB1[color_max1]-RGB2[color_max1]));
  distance[i]+=MED_OFF(abs(RGB1[color_med1]-RGB2[color_med1]));
  distance[i]+=MIN_OFF(abs(RGB1[color_min1]-RGB2[color_min1]));
  max_med1=(T_LONG)abs(RGB1[color_max1]-RGB1[color_med1]);
  max_med2=(T_LONG)abs(RGB2[color_max2]-RGB2[color_med2]);
  max_med=(T_LONG)abs(max_med1-max_med2);
  max_min1=(T_LONG)abs(RGB1[color_max1]-RGB1[color_min1]);
  max_min2=(T_LONG)abs(RGB2[color_max2]-RGB2[color_min2]);
  max_min=(T_LONG)abs(max_min1-max_min2);
  med_min1=(T_LONG)abs(RGB1[color_med1]-RGB1[color_min1]);
  med_min2=(T_LONG)abs(RGB2[color_med2]-RGB2[color_min2]);
  med_min=(T_LONG)abs(med_min1-med_min2);
  distance[i]+=WERT_DIF_MAX_MED(max_med);
  distance[i]+=WERT_DIF_MAX_MIN(max_min);
  distance[i]+=WERT_DIF_MED_MIN(med_min);
  distance[i]+=(T_LONG)HELLIGKEIT_DIF((T_LONG)abs((T_LONG)((T_LONG)(r1+g1+b1)-(T_LONG)(r2+g2+b2))));
/* ungleichheiten der farbenpositionen berücksichtigen */
  if ((color_max1!=color_max2)&&(!((equal_all_flag1)&&(equal_all_flag2)))&&(!((equal_first_two1)&&(equal_first_two2)&&((color_max1==color_med2)||(color_max1==color_max2)))))
   distance[i]+=MAX_GRENZE;
  if ((color_med1!=color_med2)&&(!((equal_all_flag1)&&(equal_all_flag2)))&&(!((equal_first_two1)&&(equal_first_two2)&&((color_med1==color_med2)||(color_med1==color_max2))))
       &&(!((equal_second_two1)&&(equal_second_two2)&&((color_med1==color_min2)||(color_med1==color_med2)))))
   distance[i]+=MED_GRENZE;
  if ((color_min1!=color_min2)&&(!((equal_all_flag1)&&(equal_all_flag2)))&&(!((equal_second_two1)&&(equal_second_two2)&&((color_min1==color_min2)||(color_min1==color_med2)))))
   distance[i]+=MIN_GRENZE;
/* ganz hell beruecksichtigen */
  if (((H2(63-r1)+H2(63-g1)+H2(63-b1))<64*3)&&((H2(63-r2)+H2(63-g2)+H2(63-b2))<64*3)&&(equal_all_flag1)&&(equal_all_flag2))
  {
   if (((H2(63-r1)+H2(63-g1)+H2(63-b1))<25*3)&&((H2(63-r2)+H2(63-g2)+H2(63-b2))<25*3))
   {
    if (((H2(63-r1)+H2(63-g1)+H2(63-b1))<25)&&((H2(63-r2)+H2(63-g2)+H2(63-b2))<25))
    {
     if (distance[i]>4*(63*3-r1-g1-b1)+13)
      distance[i]=4*(63*3-r1-g1-b1)+13;
    }
    else
     if (distance[i]>5*(63*3-r1-g1-b1)+13)
      distance[i]=5*(63*3-r1-g1-b1)+13;
   }
   else
   if (distance[i]>6*(63*3-r1-g1-b1)+13)
    distance[i]=6*(63*3-r1-g1-b1)+13;
  }
  else
  {
   /* alles dunkel beuecksichtigen */
   if ( ((H2(r1)+H2(g1)+H2(b1))<64*3)&&((H2(r2)+H2(g2)+H2(b2))<64*3))
   {
    if ( ((H2(r1)+H2(g1)+H2(b1))<25*3)&&((H2(r2)+H2(g2)+H2(b2))<25*3))
    {
     if ( ((H2(r1)+H2(g1)+H2(b1))<25)&&((H2(r2)+H2(g2)+H2(b2))<25))
     {
      if (distance[i]>5*(r1+g1+b1)+13)
       distance[i]=4*(r1+g1+b1)+13;
     }
     else
      if (distance[i]>5*(r1+g1+b1)+13)
       distance[i]=5*(r1+g1+b1)+13;
    }
    else
     if (distance[i]>6*(r1+g1+b1)+13)
      distance[i]=6*(r1+g1+b1)+13;
   }
  }
 }
 T_DEBUG_LEAVE
 return distance;
}

/***************************************************************/

T_VOID pcx_set_color256(T_VOID)
{
 T_DEBUG_ENTRY("pcx_set_color256",30)
 vesa_set_mehrere_dac(0,256, (T_PBYTE )(&pcx_256_farb_tabelle.rgb_farben[0].red));
 T_DEBUG_LEAVE
}

/*************************************************************************/

T_VOID pcx_set_color16(T_INT dac_farb_offset)
{
 T_DEBUG_ENTRY("pcx_set_color16",30)
 vesa_set_mehrere_dac(dac_farb_offset,16,(T_PBYTE )(&pcx_16_farb_tabelle.rgb_farben[0].red));
 T_DEBUG_LEAVE
}

/*************************************************************************/
