/*  Grafx2 - The Ultimate 256-color bitmap paint program
    Copyright 2008 Peter Gordon
    Copyright 2008 Yves Rizoud
    Copyright 2008 Adrien Destugues
    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
    Grafx2 is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; version 2
    of the License.
    Grafx2 is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with Grafx2; if not, see  or
    write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
//C
#include 
#include 
#include 
//POSIX
#include 
//SDL
#include 
#include 
#include 
//#include 
//mine
#include "SFont.h"
// Modificateurs pour Touche
#define MOD_SHIFT 0x1000
#define MOD_CTRL  0x2000
#define MOD_ALT   0x4000
#include "struct.h"
#include "clavier.h"
#include "const.h"
#include "io.h"
#include "hotkeys.h"
/*** Constants ***/
#define NB_MAX_TOUCHES 134
#define HAUTEUR_DEBUT_SETUP 7
#define HAUTEUR_FIN_SETUP 44
#define Header_size sizeof(struct Config_Header)
#define Chunk_size sizeof(struct Config_Chunk)
/* Colors */
#define COULEUR_SETUP 1
#define COULEUR_SELECT 8
/*** Global variables ***/
SFont_Font* MyFont;
SDL_Surface* Ecran;
bool Erreur[NB_MAX_TOUCHES];
uint8_t Choix_enreg;
uint16_t Decalage_curseur=0;
uint16_t Position_curseur=0;
byte * FichierConfig = NULL;
byte * ChunkData[CHUNK_MAX];
struct Config_Chunk Chunk[CHUNK_MAX];
uint8_t Fenetre_choix(int Largeur, int Hauteur, const char* Titre, const char* Choix, uint8_t Choix_debut,
	uint8_t Couleur,uint8_t Couleur_choix);
/*** Fonctions de gestion des évènements SDL ***/
/* Attend qu'une touche soit pressée. Retourne le code touche. */
word Lire_Touche(void)
{
    SDL_Event Event;
    do{
        SDL_WaitEvent(&Event);
        if(Event.type==SDL_KEYDOWN)
        {
          word Touche = Conversion_Touche(Event.key.keysym);
          if (Touche != 0)
            return Touche;
        }
    }while(1);
}
/*** Drawing functions ***/
/* Draws a filled rectanble */
void Cadre(int x,int y,int w,int h,uint8_t color)
{
    SDL_Rect rct;
    rct.x=x;
    rct.y=y;
    rct.w=w;
    rct.h=h;
    SDL_FillRect(Ecran, &rct, color);
}
/* Draws the main screen and welcome message */
void Dessiner_ecran_principal()
{
    Cadre(3,3,630,40,2);
    SFont_Write(Ecran, MyFont, 8,6,"Setup program for Grafx2 (c) 1996-98 Sunset Design and 2008 PulkoMandy");
    SFont_Write(Ecran, MyFont, 8,18,"Use Up/Down arrows & Page-Up/Page-Down to scroll, Enter to modify, Delete to remove a hot-key, and Escape to validate or cancel.");
    SFont_Write(Ecran, MyFont, 8,30,"DO NOT USE Print-screen, Pause, and other special keys!");
//    Cadre(3,46,630,400,COULEUR_SETUP);
    SFont_Write(Ecran,MyFont,8,48,"Option");
    SFont_Write(Ecran,MyFont,8*38,48,"Hot-Key");
    SFont_Write(Ecran,MyFont,8*75,48,"Err");
    SDL_UpdateRect(Ecran,0,0,640,480);
}
/* Displays informations about an option */
void Ecrire(uint8_t Ligne, uint16_t Num_option, uint8_t Couleur)
{
    Cadre(3,Ligne*9,630,9,Couleur);
    SFont_Write(Ecran,MyFont,8,Ligne*9,ConfigTouche[Num_option].Libelle);
    SFont_Write(Ecran,MyFont,40*8,Ligne*9,Nom_touche(ConfigTouche[Num_option].Touche));
    if(Erreur[Num_option])
        SFont_Write(Ecran,MyFont,77*8,Ligne*9,"X");
    Cadre(36*8,Ligne*9,1,9,255);
    Cadre(74*8,Ligne*9,1,9,255);
    SDL_UpdateRect(Ecran,3,Ligne*9,630,9);
}
/* Displays comment about an option */
void Ecrire_commentaire(uint16_t Num_option)
{
    Cadre(8,50*9,630,18,0);
    SFont_Write(Ecran,MyFont,8,50*9,ConfigTouche[Num_option].Explic1);
    SFont_Write(Ecran,MyFont,8,51*9,ConfigTouche[Num_option].Explic2);
    SDL_UpdateRect(Ecran,8,50*9,631,19);
}
/* Display the options list */
void Tout_ecrire()
{
    uint8_t i = HAUTEUR_DEBUT_SETUP;
    Cadre(3,46,630,400,COULEUR_SETUP);
    while(i<=HAUTEUR_FIN_SETUP && i < NB_MAX_TOUCHES + HAUTEUR_DEBUT_SETUP)
    {
        Ecrire(i,Decalage_curseur+i-HAUTEUR_DEBUT_SETUP,
                (i==HAUTEUR_DEBUT_SETUP+Position_curseur)?COULEUR_SELECT:COULEUR_SETUP);
        i++;
    }
    Cadre(36*8,46,1,400,255);
    Cadre(74*8,46,1,400,255);
    SDL_UpdateRect(Ecran,0,0,640,480);
    Ecrire_commentaire(Decalage_curseur+Position_curseur);
}
/*** Configuration handling functions ***/
/* Reads the config file */
/* returns an error message, or NULL if everything OK */
char * Interpretation_du_fichier_config()
{
  FILE* Fichier;
  long int Taille_fichier;
  byte Numero_chunk;
  word Taille_chunk;
  byte * Ptr;
  int i;
  Fichier = fopen("gfx2.cfg","rb");
  if (!Fichier)
  {
    return "gfx2.cfg is missing! Please run the\nmain program to generate it.";
  }
  fseek(Fichier,0,SEEK_END); // Positionnement à la fin
  Taille_fichier = ftell(Fichier);
  if (!Taille_fichier)
  {
    fclose(Fichier);
    return "gfx2.cfg is empty. Please run the main\nprogram to generate it.";
  }
  FichierConfig = malloc(Taille_fichier);
  if (!Fichier)
  {
    fclose(Fichier);
    return "Out of memory when reading gfx2.cfg.";
  }
  fseek(Fichier,0,SEEK_SET); // Positionnement au début
  if (! read_bytes(Fichier, FichierConfig, Taille_fichier))
  {
    fclose(Fichier);
    return "Error while reading gfx2.cfg.";
  }
  fclose(Fichier);
  
  // Initialisation des "index"
  for (i=0; i= CHUNK_MAX)
      return "File gfx2.cfg invalid.";
    ChunkData[Numero_chunk] = Ptr;
    Chunk[Numero_chunk].Taille = Taille_chunk;
//    printf("%d %6X %d\n", Numero_chunk, Ptr - FichierConfig, Taille_chunk);
    Ptr+=Taille_chunk;
  }
  // Si la config contenait des touches, on les initialise:
  if (Chunk[CHUNK_TOUCHES].Taille)
  {
    unsigned int Indice_config;
    Ptr = ChunkData[CHUNK_TOUCHES];
    for (Indice_config=0; Indice_config 0)
    {
	if(Position_curseur <= HAUTEUR_FIN_SETUP - HAUTEUR_DEBUT_SETUP && Position_curseur > 0)
	{
	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur),Position_curseur + Decalage_curseur,
		    COULEUR_SETUP);
	    (Position_curseur) -- ;
	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur),Position_curseur + Decalage_curseur,
		    COULEUR_SELECT);
	}
	else if(Decalage_curseur>0)
	{
	    (Decalage_curseur) -- ;
	    Tout_ecrire();
	}
	Ecrire_commentaire(Position_curseur + Decalage_curseur);
    }
}
/* Moves one line down */
void Scroll_bas()
{
  if(Position_curseur + Decalage_curseur < (NB_MAX_TOUCHES-1))
  {
  	if(Position_curseur < HAUTEUR_FIN_SETUP - HAUTEUR_DEBUT_SETUP)
  	{
  	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur) ,Position_curseur + Decalage_curseur,
  		    COULEUR_SETUP);
  	    (Position_curseur) ++ ;
  	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur) ,Position_curseur + Decalage_curseur,
  		    COULEUR_SELECT);
  	}
  	else if(Decalage_curseur < (NB_MAX_TOUCHES-1))
  	{
  	    (Decalage_curseur) ++ ;
  	    Tout_ecrire();
  	}
  	Ecrire_commentaire(Position_curseur + Decalage_curseur );
  }
}
/* Moves one screen up */
void Page_up()
{
    if(Position_curseur+Decalage_curseur>0)
    {
	if(Position_curseur>0)
	{
	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur),Position_curseur + Decalage_curseur,
		    COULEUR_SETUP);
	    Position_curseur = 0 ;
	    Ecrire(HAUTEUR_DEBUT_SETUP + (Position_curseur),Position_curseur + Decalage_curseur,
		    COULEUR_SELECT);
	}
	else if(Decalage_curseur>0)
	{
	    if(Decalage_curseur > HAUTEUR_FIN_SETUP-HAUTEUR_DEBUT_SETUP)
		Decalage_curseur-=HAUTEUR_FIN_SETUP-HAUTEUR_DEBUT_SETUP;
	    else Decalage_curseur=0;
	    Tout_ecrire();
	}
	Ecrire_commentaire(Position_curseur+Decalage_curseur);
    }
}
/* Moves one screen down */
void Page_down()
{
  if(Position_curseur+Decalage_curseur<(NB_MAX_TOUCHES-1))
  {
  	if(Position_curseur