/*  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
#define TOUCHE_MOUSEMIDDLE     (SDLK_LAST+1)
#define TOUCHE_MOUSEWHEELUP    (SDLK_LAST+2)
#define TOUCHE_MOUSEWHEELDOWN  (SDLK_LAST+3)
#define TOUCHE_BUTTON          (SDLK_LAST+4)
#ifdef __gp2x__
  #define TOUCHE_ESC (TOUCHE_BUTTON+GP2X_BUTTON_X)
#else
  #define TOUCHE_ESC SDLK_ESCAPE
#endif
#include "struct.h"
#include "clavier.h"
#include "const.h"
#include "io.h"
#include "hotkeys.h"
#include "setup.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;
char Repertoire_config[TAILLE_CHEMIN_FICHIER];
char Repertoire_donnees[TAILLE_CHEMIN_FICHIER];
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,");
    SFont_Write(Ecran, MyFont, 8,30,"Delete to remove a hot-key and Escape to validate or cancel.");
    Cadre(3,47,630,10,86);
    SFont_Write(Ecran,MyFont,8   ,48,"Option");
    SFont_Write(Ecran,MyFont,8*40,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(39*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,64,630,340,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(39*8,46,1,360,255);
    Cadre(74*8,46,1,360,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()
{
  char Nom_Fichier[TAILLE_CHEMIN_FICHIER];
  FILE* Fichier;
  long int Taille_fichier;
  byte Numero_chunk;
  word Taille_chunk;
  byte * Ptr;
  int i;
  strcpy(Nom_Fichier, Repertoire_config);
  strcat(Nom_Fichier, "gfx2.cfg");
  Fichier = fopen(Nom_Fichier,"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_curseurpixels))[(y*32+x)] != 255)
              Masque_icone[(y*32+x)/8] |=0x80>>(x&7);
        SDL_WM_SetIcon(Icone,Masque_icone);
      }
    }
    Ecran = SDL_SetVideoMode(640,480,8,0);
    SDL_WM_SetCaption ("Grafx2 configuration tool","Gfx2Cfg");
    SDL_EnableKeyRepeat(250, 32);
    SDL_EnableUNICODE(SDL_ENABLE);
        /* On initialise SFont */
    strcpy(Nom_fichier, Repertoire_donnees);
    strcat(Nom_fichier, "fonts/8pxfont.png");
    MyFont = SFont_InitFont(IMG_Load(Nom_fichier));
        if(MyFont==NULL)
        {
            SDL_Quit();
            exit(0);
        }
        Dessiner_ecran_principal();
        if(!Initialiser_config())
        {
            Setup();
            Enregistrer_config();
            /* On fait un peu de nettoyage avant de s'en aller */
            SFont_FreeFont(MyFont);
            SDL_Quit();
            exit(0);
          }
        else
        {
            SFont_FreeFont(MyFont);
            SDL_Quit();
            exit(1);
          }
  }
  else
  {
        puts("Error: you mustn't run this setup program from a read-only drive!\n");
        puts("The most probable cause of this error is that you are running this program");
        puts("from a CD-Rom or a protected floppy disk.");
        puts("You should try to copy all the files of Grafx2 on a hard drive or to");
        puts("unprotect your floppy disk if you really want to run it from this outdated medium.");
        exit(1);
  }
  return 0;
}