/*  Grafx2 - The Ultimate 256-color bitmap paint program
    Copyright 2008	Franck Charlet
    Copyright 2007-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.
********************************************************************************
    Graphical interface management functions (windows, menu, cursor)
*/
#include 
#include  // strncpy() strlen()
#include "windows.h"
#include "global.h"
#include "graph.h"
#include "moteur.h"
#include "divers.h"
#include "sdlscreen.h"
// Affichage d'un pixel dans le menu (le menu doit être visible)
void Pixel_dans_barre_d_outil(word X,word Y,byte Couleur)
{
  Block(X*Menu_Facteur_X,(Y*Menu_Facteur_Y)+Menu_Ordonnee,Menu_Facteur_X,Menu_Facteur_Y,Couleur);
}
  // Affichage d'un pixel dans la fenêtre (la fenêtre doit être visible)
void Pixel_dans_fenetre(word X,word Y,byte Couleur)
{
    Block((X*Menu_Facteur_X)+Fenetre_Pos_X,(Y*Menu_Facteur_Y)+Fenetre_Pos_Y,Menu_Facteur_X,Menu_Facteur_Y,Couleur);
}
// -- Affichages de différents cadres dans une fenêtre -----------------------
  // -- Cadre général avec couleurs paramètrables --
void Fenetre_Afficher_cadre_general(word Pos_X,word Pos_Y,word Largeur,word Hauteur,
                                    byte Couleur_HG,byte Couleur_BD,byte Couleur_S,byte Couleur_CHG,byte Couleur_CBD)
// Paramètres de couleurs:
// Couleur_HG =Bords Haut et Gauche
// Couleur_BD =Bords Bas et Droite
// Couleur_S  =Coins Haut-Droite et Bas-Gauche
// Couleur_CHG=Coin Haut-Gauche
// Couleur_CBD=Coin Bas-Droite
{
  // Bord haut (sans les extrémités)
  Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X),
        Fenetre_Pos_Y+(Pos_Y*Menu_Facteur_Y),
        (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_HG);
  // Bord bas (sans les extrémités)
  Block(Fenetre_Pos_X+((Pos_X+1)*Menu_Facteur_X),
        Fenetre_Pos_Y+((Pos_Y+Hauteur-1)*Menu_Facteur_Y),
        (Largeur-2)*Menu_Facteur_X,Menu_Facteur_Y,Couleur_BD);
  // Bord gauche (sans les extrémités)
  Block(Fenetre_Pos_X+(Pos_X*Menu_Facteur_X),
        Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y),
        Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_HG);
  // Bord droite (sans les extrémités)
  Block(Fenetre_Pos_X+((Pos_X+Largeur-1)*Menu_Facteur_X),
        Fenetre_Pos_Y+((Pos_Y+1)*Menu_Facteur_Y),
        Menu_Facteur_X,(Hauteur-2)*Menu_Facteur_Y,Couleur_BD);
  // Coin haut gauche
  Pixel_dans_fenetre(Pos_X,Pos_Y,Couleur_CHG);
  // Coin haut droite
  Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y,Couleur_S);
  // Coin bas droite
  Pixel_dans_fenetre(Pos_X+Largeur-1,Pos_Y+Hauteur-1,Couleur_CBD);
  // Coin bas gauche
  Pixel_dans_fenetre(Pos_X,Pos_Y+Hauteur-1,Couleur_S);
}
  // -- Cadre dont tout le contour est d'une seule couleur --
void Fenetre_Afficher_cadre_mono(word Pos_X,word Pos_Y,word Largeur,word Hauteur,byte Couleur)
{
  Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,Couleur,Couleur,Couleur,Couleur,Couleur);
}
  // -- Cadre creux: foncé en haut-gauche et clair en bas-droite --
void Fenetre_Afficher_cadre_creux(word Pos_X,word Pos_Y,word Largeur,word Hauteur)
{
  Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Fonce,CM_Blanc,CM_Clair,CM_Fonce,CM_Blanc);
}
  // -- Cadre bombé: clair en haut-gauche et foncé en bas-droite --
void Fenetre_Afficher_cadre_bombe(word Pos_X,word Pos_Y,word Largeur,word Hauteur)
{
  Fenetre_Afficher_cadre_general(Pos_X,Pos_Y,Largeur,Hauteur,CM_Blanc,CM_Fonce,CM_Clair,CM_Blanc,CM_Fonce);
}
  // -- Cadre de séparation: un cadre bombé dans un cadre creux (3D!!!) --
void Fenetre_Afficher_cadre(word Pos_X,word Pos_Y,word Largeur,word Hauteur)
{
  Fenetre_Afficher_cadre_creux(Pos_X,Pos_Y,Largeur,Hauteur);
  Fenetre_Afficher_cadre_bombe(Pos_X+1,Pos_Y+1,Largeur-2,Hauteur-2);
}
//-- Affichages relatifs à la palette dans le menu ---------------------------
  // -- Affichage des couleurs courante (fore/back) de pinceau dans le menu --
void Afficher_foreback(void)
{
  if (Menu_visible)
  {
    Block((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7,Back_color);
    Block((LARGEUR_MENU-13)*Menu_Facteur_X,Menu_Ordonnee+(Menu_Facteur_Y<<1),Menu_Facteur_X<<3,Menu_Facteur_Y*5,Fore_color);
    UpdateRect((LARGEUR_MENU-17)*Menu_Facteur_X,Menu_Ordonnee+Menu_Facteur_Y,Menu_Facteur_X<<4,Menu_Facteur_Y*7);
  }
}
  // -- Tracer un cadre de couleur autour de la Fore_color dans le menu --
void Encadrer_couleur_menu(byte Couleur)
{
  word Debut_X,Debut_Y,Fin_X,Fin_Y;
  word Indice;
  if ((Fore_color>=Couleur_debut_palette) && (Fore_color>3)*Menu_Taille_couleur)*Menu_Facteur_X;
      Debut_Y=Menu_Ordonnee+((1+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y);
      Block(Debut_X,Debut_Y,(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur);
      Block(Debut_X,Debut_Y+(Menu_Facteur_Y<<2),(Menu_Taille_couleur+1)*Menu_Facteur_X,Menu_Facteur_Y,Couleur);
      Block(Debut_X,Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur);
      Block(Debut_X+(Menu_Taille_couleur*Menu_Facteur_X),Debut_Y+Menu_Facteur_Y,Menu_Facteur_X,Menu_Facteur_Y*3,Couleur);
    }
    else
    {
      if (Couleur==CM_Noir)
      {
        Debut_X=(LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur)*Menu_Facteur_X;
        Debut_Y=Menu_Ordonnee+((2+(((Fore_color-Couleur_debut_palette)&7)<<2))*Menu_Facteur_Y);
        Block(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X,
              Menu_Facteur_Y<<2,Fore_color);
        UpdateRect(Debut_X,Debut_Y,Menu_Taille_couleur*Menu_Facteur_X,Menu_Facteur_Y*4); // TODO On met à jour toute la palette... peut mieux faire
      }
      else
      {
        Debut_X=LARGEUR_MENU+1+((Fore_color-Couleur_debut_palette)>>3)*Menu_Taille_couleur;
        Debut_Y=2+(((Fore_color-Couleur_debut_palette)&7)<<2);
        Fin_X=Debut_X+Menu_Taille_couleur-1;
        Fin_Y=Debut_Y+3;
        for (Indice=Debut_X; Indice<=Fin_X; Indice++)
          Block(Indice*Menu_Facteur_X,Menu_Ordonnee+(Debut_Y*Menu_Facteur_Y),
                Menu_Facteur_X,Menu_Facteur_Y,
                ((Indice+Debut_Y)&1)?CM_Blanc:CM_Noir);
        for (Indice=Debut_Y+1; Indice>3)*Menu_Taille_couleur)*Menu_Facteur_X,
              Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y),
              (Menu_Taille_couleur-1)*Menu_Facteur_X,
              Menu_Facteur_Y*3,
              Couleur_debut_palette+Couleur);
    else
      for (Couleur=0;Couleur<64;Couleur++)
        Block((LARGEUR_MENU+1+(Couleur>>3)*Menu_Taille_couleur)*Menu_Facteur_X,
              Menu_Ordonnee+((2+((Couleur&7)<<2))*Menu_Facteur_Y),
              Menu_Taille_couleur*Menu_Facteur_X,
              Menu_Facteur_Y<<2,
              Couleur_debut_palette+Couleur);
    Encadrer_couleur_menu(CM_Blanc);
    UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y);
  }
}
  // -- Recalculer l'origine de la palette dans le menu pour rendre la
  //    Fore_color visible --
void Recadrer_palette(void)
{
  byte Ancienne_couleur=Couleur_debut_palette;
  if (Fore_color=Couleur_debut_palette+64)
      Couleur_debut_palette+=8;
  }
  if (Ancienne_couleur!=Couleur_debut_palette)
    Afficher_palette_du_menu();
}
  // -- Afficher tout le menu --
void Afficher_menu(void)
{
  word Pos_X;
  word Pos_Y;
  char Chaine[4];
  if (Menu_visible)
  {
    // Affichage du sprite du menu
    for (Pos_Y=0;Pos_Y=Principal_X_Zoom) ))
      {
        if ( (Operation_en_cours!=OPERATION_PIPETTE)
          && (Operation_en_cours!=OPERATION_REMPLACER) )
          Print_dans_menu("X:       Y:             ",0);
        else
        {
          Print_dans_menu("X:       Y:       (    )",0);
          Num2str(Pipette_Couleur,Chaine,3);
          Print_dans_menu(Chaine,20);
          Print_general(170*Menu_Facteur_X,Menu_Ordonnee_Texte," ",0,Pipette_Couleur);
        }
        Print_coordonnees();
      }
      Print_nom_fichier();
    }
    UpdateRect(0,Menu_Ordonnee,Largeur_ecran,HAUTEUR_MENU*Menu_Facteur_Y); // on met toute la largur à jour, ça inclut la palette et la zone d'étant avec le nom du fichier
  }
}
// -- Affichage de texte -----------------------------------------------------
  // -- Afficher une chaîne n'importe où à l'écran --
void Print_general(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond)
{
  word  Indice;
  int Pos_X;
  int Pos_Y;
  byte *Caractere;
  short Reel_X;
  short Reel_Y;
  byte Repeat_Menu_Facteur_X;
  byte Repeat_Menu_Facteur_Y;
  Reel_Y=Y;
  for (Pos_Y=0;Pos_Y<8;Pos_Y++)
  {
    Reel_X=0; // Position dans le buffer
    for (Indice=0;Chaine[Indice]!='\0';Indice++)
    {
      // Pointeur sur le premier pixel du caractère
      Caractere=Fonte+(((unsigned char)Chaine[Indice])<<6);
      for (Pos_X=0;Pos_X<8<<3;Pos_X+=1<<3)
        for (Repeat_Menu_Facteur_X=0;Repeat_Menu_Facteur_X Taille)
  {
    Chaine_affichee[Taille-1]=CARACTERE_SUSPENSION;
  }
  Print_dans_fenetre(X, Y, Chaine_affichee, Couleur_texte, Couleur_fond);
}
  // -- Afficher une chaîne dans une fenêtre --
void Print_dans_fenetre(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond)
{
  Print_general((X*Menu_Facteur_X)+Fenetre_Pos_X,
                (Y*Menu_Facteur_Y)+Fenetre_Pos_Y,
                Chaine,Couleur_texte,Couleur_fond);
  UpdateRect(X*Menu_Facteur_X+Fenetre_Pos_X,Y*Menu_Facteur_Y+Fenetre_Pos_Y,8*Menu_Facteur_X*strlen(Chaine),8*Menu_Facteur_Y);
}
  // -- Afficher une chaîne dans le menu --
void Print_dans_menu(char * Chaine, short Position)
{
  Print_general((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,Chaine,CM_Noir,CM_Clair);
  UpdateRect((18+(Position<<3))*Menu_Facteur_X,Menu_Ordonnee_Texte,strlen(Chaine)*8*Menu_Facteur_X,8*Menu_Facteur_Y);
}
  // -- Afficher les coordonnées du pinceau dans le menu --
// Note : cette fonction n'affiche que les chiffres, pas les X: Y: qui sont dans la gestion principale, car elle est apellée très souvent.
void Print_coordonnees(void)
{
  char Tempo[5];
  if (Menu_visible)
  {
    if ( (Operation_en_cours==OPERATION_PIPETTE)
      || (Operation_en_cours==OPERATION_REMPLACER) )
    {
      if ( (Pinceau_X>=0) && (Pinceau_Y>=0)
        && (Pinceau_X12)
    {
      Nom_affiche[11]=CARACTERE_SUSPENSION;
      Taille_nom = 12;
    }
    Block((LARGEUR_MENU+2+((Menu_Taille_couleur-12)<<3))*Menu_Facteur_X,
          Menu_Ordonnee_Texte,Menu_Facteur_X*96,Menu_Facteur_Y<<3,CM_Clair);
    Debut_X=LARGEUR_MENU+2+((Menu_Taille_couleur-Taille_nom)<<3);
    Print_general(Debut_X*Menu_Facteur_X,Menu_Ordonnee_Texte,Nom_affiche,CM_Noir,CM_Clair);
  }
}
// Fonction d'affichage d'une chaine numérique avec une fonte très fine
// Spécialisée pour les compteurs RGB
void Print_compteur(short X,short Y,char * Chaine,byte Couleur_texte,byte Couleur_fond)
{
  // Macros pour écrire des litteraux binaires.
  // Ex: Ob(11110000) == 0xF0
  #define Ob(x)  ((unsigned)Ob_(0 ## x ## uL))
  #define Ob_(x) ((x & 1) | (x >> 2 & 2) | (x >> 4 & 4) | (x >> 6 & 8) |		\
	  (x >> 8 & 16) | (x >> 10 & 32) | (x >> 12 & 64) | (x >> 14 & 128))
  byte Caractere[14][8] = {
   { // 0
    Ob(00011100),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00011100)
   },
   { // 1
    Ob(00001100),
    Ob(00011100),
    Ob(00111100),
    Ob(00001100),
    Ob(00001100),
    Ob(00001100),
    Ob(00001100),
    Ob(00001100)
   },
   { // 2
    Ob(00011100),
    Ob(00110110),
    Ob(00000110),
    Ob(00000110),
    Ob(00000110),
    Ob(00001100),
    Ob(00011000),
    Ob(00111110)
   },
   { // 3
    Ob(00011100),
    Ob(00110110),
    Ob(00000110),
    Ob(00001100),
    Ob(00000110),
    Ob(00000110),
    Ob(00110110),
    Ob(00011100)
   },
   { // 4
    Ob(00001100),
    Ob(00001100),
    Ob(00011000),
    Ob(00011000),
    Ob(00110000),
    Ob(00110100),
    Ob(00111110),
    Ob(00000100)
   },
   { // 5
    Ob(00111110),
    Ob(00110000),
    Ob(00110000),
    Ob(00111100),
    Ob(00000110),
    Ob(00000110),
    Ob(00110110),
    Ob(00011100)
   },
   { // 6
    Ob(00011100),
    Ob(00110110),
    Ob(00110000),
    Ob(00111100),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00011100)
   },
   { // 7
    Ob(00111110),
    Ob(00000110),
    Ob(00000110),
    Ob(00001100),
    Ob(00011000),
    Ob(00011000),
    Ob(00011000),
    Ob(00011000)
   },
   { // 8
    Ob(00011100),
    Ob(00110110),
    Ob(00110110),
    Ob(00011100),
    Ob(00110110),
    Ob(00110110),
    Ob(00110110),
    Ob(00011100)
   },
   { // 9
    Ob(00011100),
    Ob(00110110),
    Ob(00110110),
    Ob(00011110),
    Ob(00000110),
    Ob(00000110),
    Ob(00110110),
    Ob(00011100)
   },
   { // (espace)
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000)
   },
   { // +
    Ob(00000000),
    Ob(00001000),
    Ob(00001000),
    Ob(00111110),
    Ob(00001000),
    Ob(00001000),
    Ob(00000000),
    Ob(00000000)
   },
   { // -
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00111110),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000),
    Ob(00000000)
   },
   { // +-
    Ob(00001000),
    Ob(00001000),
    Ob(00111110),
    Ob(00001000),
    Ob(00001000),
    Ob(00000000),
    Ob(00111110),
    Ob(00000000)
   } };
  word  Indice;
  short Pos_X;
  short Pos_Y;
  for (Indice=0;Chaine[Indice]!='\0';Indice++)
  {
    int Numero_car;
    switch(Chaine[Indice])
    {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        Numero_car=Chaine[Indice]-'0';
        break;
      case ' ':
      default:
        Numero_car=10;
        break;
      case '+':
        Numero_car=11;
        break;
      case '-':
        Numero_car=12;
        break;
      case '±':
        Numero_car=13;
        break;
    }
    for (Pos_Y=0;Pos_Y<8;Pos_Y++)
    {
      for (Pos_X=0;Pos_X<6;Pos_X++)
      {
        byte Couleur = (Caractere[Numero_car][Pos_Y] & (1 << (6-Pos_X))) ? Couleur_texte:Couleur_fond;
        Pixel_dans_fenetre(X+(Indice*6+Pos_X),Y+Pos_Y,Couleur);
      }
    }
  }
  UpdateRect(Fenetre_Pos_X+X*Menu_Facteur_X,Fenetre_Pos_Y+Y*Menu_Facteur_Y,strlen(Chaine)*Menu_Facteur_X*6,8*Menu_Facteur_Y);
}
//---- Fenêtre demandant de confirmer une action et renvoyant la réponse -----
byte Demande_de_confirmation(char * Message)
{
  short Bouton_clicke;
  word  Largeur_de_la_fenetre;
  Largeur_de_la_fenetre=(strlen(Message)<<3)+20;
  if (Largeur_de_la_fenetre<120)
    Largeur_de_la_fenetre=120;
  Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Confirmation");
  Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair);
  Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre/3)-20     ,37,40,14,"Yes",1,1,SDLK_y); // 1
  Fenetre_Definir_bouton_normal(((Largeur_de_la_fenetre<<1)/3)-20,37,40,14,"No" ,1,1,SDLK_n); // 2
  UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60);
  Afficher_curseur();
  do
  {
    Bouton_clicke=Fenetre_Bouton_clicke();
    if (Touche==SDLK_RETURN) Bouton_clicke=1;
    if (Touche==SDLK_ESCAPE) Bouton_clicke=2;
  }
  while (Bouton_clicke<=0);
  Fermer_fenetre();
  Afficher_curseur();
  return (Bouton_clicke==1)? 1 : 0;
}
//---- Fenêtre avertissant de quelque chose et attendant un click sur OK -----
void Warning_message(char * Message)
{
  short Bouton_clicke;
  word  Largeur_de_la_fenetre;
  Largeur_de_la_fenetre=(strlen(Message)<<3)+20;
  if (Largeur_de_la_fenetre<120)
    Largeur_de_la_fenetre=120;
  Ouvrir_fenetre(Largeur_de_la_fenetre,60,"Warning!");
  Print_dans_fenetre((Largeur_de_la_fenetre>>1)-(strlen(Message)<<2),20,Message,CM_Noir,CM_Clair);
  Fenetre_Definir_bouton_normal((Largeur_de_la_fenetre>>1)-20     ,37,40,14,"OK",1,1,SDLK_RETURN); // 1
  UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X*Largeur_de_la_fenetre,Menu_Facteur_Y*60);
  Afficher_curseur();
  do
    Bouton_clicke=Fenetre_Bouton_clicke();
  while ((Bouton_clicke<=0) && (Touche!=SDLK_ESCAPE) && (Touche!=SDLK_o));
  Fermer_fenetre();
  Afficher_curseur();
}
  // -- Redessiner le sprite d'un bouton dans le menu --
void Afficher_sprite_dans_menu(int Numero_bouton,int Numero_sprite)
{
  word Pos_X;
  word Pos_Y;
  word Pos_menu_X;
  word Pos_menu_Y;
  byte Couleur;
  for (Pos_Y=0,Pos_menu_Y=Bouton[Numero_bouton].Decalage_Y+1;Pos_Y à 64 lignes fct(Menu_Facteur)
  word Nb_couleurs   =(Debut_block<=Fin_block)?Fin_block-Debut_block+1:Debut_block-Fin_block+1;
  word Ligne_en_cours=(Debut_block<=Fin_block)?0:Total_lignes-1;
  word Debut_X       =Fenetre_Pos_X+(Menu_Facteur_X*Pos_X);
  word Largeur_ligne =Menu_Facteur_X<<4; // <=> à 16 pixels fct(Menu_Facteur)
  word Debut_Y       =Fenetre_Pos_Y+(Menu_Facteur_Y*Pos_Y);
  word Fin_Y         =Debut_Y+Total_lignes;
  word Indice;
  if (Debut_block>Fin_block)
  {
    Indice=Debut_block;
    Debut_block=Fin_block;
    Fin_block=Indice;
  }
  for (Indice=Debut_Y;Indice>3)*Menu_Taille_couleur)*Menu_Facteur_X;
      Debut_Y=Menu_Ordonnee_avant_fenetre+((2+((Couleur&7)<<2))*Menu_Facteur_Y);
      Fin_X=Debut_X+Largeur;
      Fin_Y=Debut_Y+Hauteur;
      //   On affiche le bloc en entier si on peut, sinon on le découpe autour
      // de la fenêtre.
      if ( (Debut_Y>=Coin_Y) || (Fin_X<=Fenetre_Pos_X) || (Debut_X>=Coin_X) )
        Block(Debut_X,Debut_Y,Largeur,Hauteur,Vraie_couleur);
      else
      {
        if (Debut_X>=Fenetre_Pos_X)
        {
          if ( (Fin_X>Coin_X) || (Fin_Y>Coin_Y) )
          {
            if ( (Fin_X>Coin_X) && (Fin_Y>Coin_Y) )
            {
              Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur);
              Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur);
            }
            else
            {
              if (Fin_Y>Coin_Y)
                Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur);
              else
                Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur);
            }
          }
        }
        else
        {
          if (Fin_XCoin_Y)
            {
              Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur);
              Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur);
            }
            else
              Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur);
          }
          else
          {
            if (Fin_Y>Coin_Y)
            {
              Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Coin_Y-Debut_Y,Vraie_couleur);
              Block(Coin_X,Debut_Y,Fin_X-Coin_X,Coin_Y-Debut_Y,Vraie_couleur);
              Block(Debut_X,Coin_Y,Largeur,Fin_Y-Coin_Y,Vraie_couleur);
            }
            else
            {
              Block(Debut_X,Debut_Y,Fenetre_Pos_X-Debut_X,Hauteur,Vraie_couleur);
              Block(Coin_X,Debut_Y,Fin_X-Coin_X,Hauteur,Vraie_couleur);
            }
          }
        }
      }
      {
        // Affichage du bloc directement dans le "buffer de fond" de la fenetre.
        // Cela permet au bloc de couleur d'apparaitre si on déplace la fenetre.
        short Pos_X;
        short Pos_Y;
        short Deb_X; // besoin d'une variable signée
        short Deb_Y; // besoin d'une variable signée
        // Attention aux unités
        Deb_X = ((short)Debut_X - (short)Fenetre_Pos_X);
        Deb_Y = ((short)Debut_Y - (short)Fenetre_Pos_Y);
        for (Pos_Y=Deb_Y;Pos_Y<(Deb_Y+Hauteur)&&Pos_Y=0&&Pos_Y>=0)
              Pixel_fond(Pos_X,Pos_Y,Vraie_couleur);
      }
    }
  }
  UpdateRect(LARGEUR_MENU*Menu_Facteur_X,Menu_Ordonnee_avant_fenetre,Largeur_ecran-(LARGEUR_MENU*Menu_Facteur_X),(HAUTEUR_MENU-9)*Menu_Facteur_Y);
}
// -------- Calcul des bornes de la partie d'image visible à l'écran ---------
void Calculer_limites(void)
/*
  Avant l'appel à cette fonction, les données de la loupe doivent être à jour.
*/
{
  if (Loupe_Mode)
  {
    // -- Calcul des limites de la partie non zoomée de l'image --
    Limite_Haut  =Principal_Decalage_Y;
    Limite_Gauche=Principal_Decalage_X;
    Limite_visible_Bas   =Limite_Haut+Menu_Ordonnee-1;
    Limite_visible_Droite=Limite_Gauche+Principal_Split-1;
    if (Limite_visible_Bas>=Principal_Hauteur_image)
      Limite_Bas=Principal_Hauteur_image-1;
    else
      Limite_Bas=Limite_visible_Bas;
    if (Limite_visible_Droite>=Principal_Largeur_image)
      Limite_Droite=Principal_Largeur_image-1;
    else
      Limite_Droite=Limite_visible_Droite;
    // -- Calcul des limites de la partie zoomée de l'image --
    Limite_Haut_Zoom  =Loupe_Decalage_Y;
    Limite_Gauche_Zoom=Loupe_Decalage_X;
    Limite_visible_Bas_Zoom   =Limite_Haut_Zoom+Loupe_Hauteur-1;
    Limite_visible_Droite_Zoom=Limite_Gauche_Zoom+Loupe_Largeur-1;
    if (Limite_visible_Bas_Zoom>=Principal_Hauteur_image)
      Limite_Bas_Zoom=Principal_Hauteur_image-1;
    else
      Limite_Bas_Zoom=Limite_visible_Bas_Zoom;
    if (Limite_visible_Droite_Zoom>=Principal_Largeur_image)
      Limite_Droite_Zoom=Principal_Largeur_image-1;
    else
      Limite_Droite_Zoom=Limite_visible_Droite_Zoom;
  }
  else
  {
    // -- Calcul des limites de la partie visible de l'image --
    Limite_Haut  =Principal_Decalage_Y;
    Limite_Gauche=Principal_Decalage_X;
    Limite_visible_Bas   =Limite_Haut+(Menu_visible?Menu_Ordonnee:Hauteur_ecran)-1; // A REVOIR POUR SIMPLIFICATION
    Limite_visible_Droite=Limite_Gauche+Largeur_ecran-1;
    if (Limite_visible_Bas>=Principal_Hauteur_image)
      Limite_Bas=Principal_Hauteur_image-1;
    else
      Limite_Bas=Limite_visible_Bas;
    if (Limite_visible_Droite>=Principal_Largeur_image)
      Limite_Droite=Principal_Largeur_image-1;
    else
      Limite_Droite=Limite_visible_Droite;
  }
}
// -- Calculer les coordonnées du pinceau en fonction du snap et de la loupe -
void Calculer_coordonnees_pinceau(void)
{
  if ((Loupe_Mode) && (Mouse_X>=Principal_X_Zoom))
  {
    Pinceau_X=((Mouse_X-Principal_X_Zoom)/Loupe_Facteur)+Loupe_Decalage_X;
    Pinceau_Y=(Mouse_Y/Loupe_Facteur)+Loupe_Decalage_Y;
  }
  else
  {
    Pinceau_X=Mouse_X+Principal_Decalage_X;
    Pinceau_Y=Mouse_Y+Principal_Decalage_Y;
  }
  if (Snap_Mode)
  {
    Pinceau_X=(((Pinceau_X+(Snap_Largeur>>1)-Snap_Decalage_X)/Snap_Largeur)*Snap_Largeur)+Snap_Decalage_X;
    Pinceau_Y=(((Pinceau_Y+(Snap_Hauteur>>1)-Snap_Decalage_Y)/Snap_Hauteur)*Snap_Hauteur)+Snap_Decalage_Y;
  }
}
// -- Affichage de la limite de l'image -------------------------------------
void Afficher_limites_de_l_image(void)
{
  short Debut;
  short Pos;
  short Fin;
  byte Droite_visible;
  byte Bas_visible;
  short Ancienne_Limite_Zoom;
  Droite_visible=Principal_Largeur_image<((Loupe_Mode)?Principal_Split:Largeur_ecran);
  Bas_visible   =Principal_Hauteur_imagePrincipal_Split)
  {
    Principal_Decalage_X=Loupe_Decalage_X+(Loupe_Largeur>>1)
                         -(Principal_Split>>1);
    if (Principal_Decalage_X<0)
      Principal_Decalage_X=0;
    else
    if (Principal_Largeur_imageMenu_Ordonnee)
  {
    Principal_Decalage_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1)
                         -(Menu_Ordonnee>>1);
    if (Principal_Decalage_Y<0)
      Principal_Decalage_Y=0;
    else
    if (Principal_Hauteur_image>1)-X_theorique)/Loupe_Facteur)*Loupe_Facteur);
  Principal_Split=Principal_X_Zoom-(Menu_Facteur_X*LARGEUR_BARRE_SPLIT);
  // Correction en cas de débordement sur la gauche
  while (Principal_Split*(Loupe_Facteur+1)=X_theorique)
  {
    Principal_Split-=Loupe_Facteur;
    Principal_X_Zoom-=Loupe_Facteur;
  }
}
// -------------------- Calcul des information de la loupe -------------------
void Calculer_donnees_loupe(void)
/*
  Après modification des données de la loupe, il faut recalculer les limites.
*/
{
  Calculer_split();
  Loupe_Largeur=(Largeur_ecran-Principal_X_Zoom)/Loupe_Facteur;
  Loupe_Hauteur=Menu_Ordonnee/Loupe_Facteur;
  if (Menu_Ordonnee%Loupe_Facteur)
    Loupe_Hauteur++;
  if (Loupe_Mode && Loupe_Decalage_X)
  {
    if (Principal_Largeur_image>1);
  Centre_Y=Loupe_Decalage_Y+(Loupe_Hauteur>>1);
  Loupe_Facteur=FACTEUR_ZOOM[Indice_facteur];
  Table_mul_facteur_zoom=TABLE_ZOOM[Indice_facteur];
  Calculer_donnees_loupe();
  if (Loupe_Mode)
  {
    // Recalculer le décalage de la loupe
    // Centrage "brut" de lécran par rapport à la loupe
    Loupe_Decalage_X=Centre_X-(Loupe_Largeur>>1);
    Loupe_Decalage_Y=Centre_Y-(Loupe_Hauteur>>1);
    // Correction en cas de débordement de l'image
    if (Loupe_Decalage_X+Loupe_Largeur>Principal_Largeur_image)
      Loupe_Decalage_X=Principal_Largeur_image-Loupe_Largeur;
    if (Loupe_Decalage_Y+Loupe_Hauteur>Principal_Hauteur_image)
      Loupe_Decalage_Y=Principal_Hauteur_image-Loupe_Hauteur;
    if (Loupe_Decalage_X<0)
      Loupe_Decalage_X=0;
    if (Loupe_Decalage_Y<0)
      Loupe_Decalage_Y=0;
    Recadrer_ecran_par_rapport_au_zoom();
    Pixel_Preview=Pixel_Preview_Loupe;
  }
  else
    Pixel_Preview=Pixel_Preview_Normal;
  Calculer_limites();
  Calculer_coordonnees_pinceau();
}
  // -- Afficher la barre de séparation entre les parties zoomées ou non en
  //    mode Loupe --
void Afficher_barre_de_split(void)
{
  // Partie grise du milieu
  Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Facteur_Y,
        (LARGEUR_BARRE_SPLIT-4)*Menu_Facteur_X,
        Menu_Ordonnee-(Menu_Facteur_Y<<1),CM_Clair);
  // Barre noire de gauche
  Block(Principal_Split,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir);
  // Barre noire de droite
  Block(Principal_X_Zoom-Menu_Facteur_X,0,Menu_Facteur_X,Menu_Ordonnee,CM_Noir);
  // Bord haut (blanc)
  Block(Principal_Split+Menu_Facteur_X,0,
        (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Blanc);
  // Bord gauche (blanc)
  Block(Principal_Split+Menu_Facteur_X,Menu_Facteur_Y,
        Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Blanc);
  // Bord droite (gris foncé)
  Block(Principal_X_Zoom-(Menu_Facteur_X<<1),Menu_Facteur_Y,
        Menu_Facteur_X,(Menu_Ordonnee-(Menu_Facteur_Y<<1)),CM_Fonce);
  // Bord bas (gris foncé)
  Block(Principal_Split+(Menu_Facteur_X<<1),Menu_Ordonnee-Menu_Facteur_Y,
        (LARGEUR_BARRE_SPLIT-3)*Menu_Facteur_X,Menu_Facteur_Y,CM_Fonce);
  // Coin bas gauche
  Block(Principal_Split+Menu_Facteur_X,Menu_Ordonnee-Menu_Facteur_Y,
        Menu_Facteur_X,Menu_Facteur_Y,CM_Clair);
  // Coin haut droite
  Block(Principal_X_Zoom-(Menu_Facteur_X<<1),0,
        Menu_Facteur_X,Menu_Facteur_Y,CM_Clair);
  UpdateRect(Principal_Split,0,LARGEUR_BARRE_SPLIT*Menu_Facteur_X,Menu_Ordonnee); // On réaffiche toute la partie à gauche du split, ce qui permet d'effacer son ancienne position
}
// -- Fonctions de manipulation du curseur -----------------------------------
  // -- Afficher une barre horizontale XOR zoomée
void Ligne_horizontale_XOR_Zoom(short Pos_X, short Pos_Y, short Largeur)
{
  short Pos_X_reelle=Principal_X_Zoom+(Pos_X-Loupe_Decalage_X)*Loupe_Facteur;
  short Pos_Y_reelle=(Pos_Y-Loupe_Decalage_Y)*Loupe_Facteur;
  short Largeur_reelle=Largeur*Loupe_Facteur;
  short Pos_Y_Fin=(Pos_Y_reelle+Loupe_Facteur=Principal_X_Zoom) ) )
    || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) )
    Forme=Forme_curseur;
  else
    Forme=FORME_CURSEUR_FLECHE;
  switch(Forme)
  {
    case FORME_CURSEUR_CIBLE :
      if (!Cacher_pinceau)
        Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1);
      if (!Cacher_curseur)
      {
        if (Config.Curseur==1)
        {
          Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0;
          if (Debut_Y<4)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y);
          Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0;
          if (Debut_X<4)
            Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X);
          Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0;
          if (Fin_X<4)
            Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X);
          Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0;
          if (Fin_Y<4)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+3,4-Fin_Y);
          UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y);
        }
        else
        {
          Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE;
          Debut_X=Mouse_X-Curseur_Decalage_X[Temp];
          Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp];
          for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++)
	        {
	          if( Pos_X < 0 ) continue;
            for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
            {
	            if( Pos_Y < 0 ) continue;
              Couleur=SPRITE_CURSEUR[Temp][Compteur_Y][Compteur_X];
              FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y);
              if (Couleur!=CM_Trans)
                Pixel(Pos_X,Pos_Y,Couleur);
	            if (Pos_Y > Hauteur_ecran) break;
            }
	          if (Pos_X >= Largeur_ecran) break;
	        }
          UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y);
        }
      }
      break;
    case FORME_CURSEUR_CIBLE_PIPETTE:
      if (!Cacher_pinceau)
        Afficher_pinceau(Pinceau_X,Pinceau_Y,Fore_color,1);
      if (!Cacher_curseur)
      {
        if (Config.Curseur==1)
        {
          // Barres formant la croix principale
          Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0;
          if (Debut_Y<3)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y);
          Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0;
          if (Debut_X<3)
            Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X);
          Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0;
          if (Fin_X<3)
            Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X);
          Fin_Y=(Mouse_Y+6>Menu_Ordonnee/*Hauteur_ecran*/)?Mouse_Y+6-Menu_Ordonnee/*Hauteur_ecran*/:0;
          if (Fin_Y<3)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+3,3-Fin_Y);
          // Petites barres aux extrémités
          Debut_X=(!Mouse_X);
          Debut_Y=(!Mouse_Y);
          Fin_X=(Mouse_X>=Largeur_ecran-1);
          Fin_Y=(Mouse_Y>=Menu_Ordonnee-1);
          if (Mouse_Y>5)
            Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X));
          if (Mouse_X>5)
            Ligne_verticale_XOR  (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y));
          if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break;
        for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
        {
	  if(Pos_Y<0) continue;
	  if(Pos_Y>=Hauteur_ecran) break;
          Couleur=SPRITE_CURSEUR[Forme][Compteur_Y][Compteur_X];
	  // On sauvegarde dans FOND_CURSEUR pour restaurer plus tard
	  FOND_CURSEUR[Compteur_Y][Compteur_X]=Lit_pixel(Pos_X,Pos_Y);
	  if (Couleur!=CM_Trans)
	      Pixel(Pos_X,Pos_Y,Couleur);
	}
      }
      UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y);
      break;
    case FORME_CURSEUR_CIBLE_XOR :
      Pos_X=Pinceau_X-Principal_Decalage_X;
      Pos_Y=Pinceau_Y-Principal_Decalage_Y;
      Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR
      if ((Pos_Y=Limite_Haut))
      {
        Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X);
        UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1);
      }
      if ((Pos_X=Limite_Gauche))
      {
        Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee);
        UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee);
      }
      if (Loupe_Mode)
      {
        // UPDATERECT
        if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom))
          Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur);
        if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom))
          Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur);
      }
      break;
    case FORME_CURSEUR_RECTANGLE_XOR :
      // !!! Cette forme ne peut pas être utilisée en mode Loupe !!!
      // Petite croix au centre
      Debut_X=(Mouse_X-3);
      Debut_Y=(Mouse_Y-3);
      Fin_X  =(Mouse_X+4);
      Fin_Y  =(Mouse_Y+4);
      if (Debut_X<0)
        Debut_X=0;
      if (Debut_Y<0)
        Debut_Y=0;
      if (Fin_X>Largeur_ecran)
        Fin_X=Largeur_ecran;
      if (Fin_Y>Menu_Ordonnee)
        Fin_Y=Menu_Ordonnee;
      Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X);
      Ligne_verticale_XOR  (Mouse_X,Debut_Y,Fin_Y-Debut_Y);
      // Grand rectangle autour
      Debut_X=Mouse_X-(Loupe_Largeur>>1);
      Debut_Y=Mouse_Y-(Loupe_Hauteur>>1);
      if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X)
        Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1;
      if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y)
        Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1;
      if (Debut_X<0)
        Debut_X=0;
      if (Debut_Y<0)
        Debut_Y=0;
      Fin_X=Debut_X+Loupe_Largeur-1;
      Fin_Y=Debut_Y+Loupe_Hauteur-1;
      Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur);
      Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2);
      Ligne_verticale_XOR(  Fin_X,Debut_Y+1,Loupe_Hauteur-2);
      Ligne_horizontale_XOR(Debut_X,  Fin_Y,Loupe_Largeur);
      UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y);
      break;
    default: //case FORME_CURSEUR_ROTATE_XOR :
      Debut_X=1-(Brosse_Largeur>>1);
      Debut_Y=1-(Brosse_Hauteur>>1);
      Fin_X=Debut_X+Brosse_Largeur-1;
      Fin_Y=Debut_Y+Brosse_Hauteur-1;
      if (Brosse_Centre_rotation_defini)
      {
        if ( (Brosse_Centre_rotation_X==Pinceau_X)
          && (Brosse_Centre_rotation_Y==Pinceau_Y) )
        {
          cosA=1.0;
          sinA=0.0;
        }
        else
        {
          Pos_X=Pinceau_X-Brosse_Centre_rotation_X;
          Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y;
          cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y));
          sinA=sin(acos(cosA));
          if (Pos_Y>0) sinA=-sinA;
        }
        Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1);
        Transformer_point(Fin_X  ,Debut_Y, cosA,sinA, &X2,&Y2);
        Transformer_point(Debut_X,Fin_Y  , cosA,sinA, &X3,&Y3);
        Transformer_point(Fin_X  ,Fin_Y  , cosA,sinA, &X4,&Y4);
        X1+=Brosse_Centre_rotation_X;
        Y1+=Brosse_Centre_rotation_Y;
        X2+=Brosse_Centre_rotation_X;
        Y2+=Brosse_Centre_rotation_Y;
        X3+=Brosse_Centre_rotation_X;
        Y3+=Brosse_Centre_rotation_Y;
        X4+=Brosse_Centre_rotation_X;
        Y4+=Brosse_Centre_rotation_Y;
        Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0);
        Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0);
      }
      else
      {
        X1=X3=1-Brosse_Largeur;
        Y1=Y2=Debut_Y;
        X2=X4=Pinceau_X;
        Y3=Y4=Fin_Y;
        X1+=Pinceau_X;
        Y1+=Pinceau_Y;
        Y2+=Pinceau_Y;
        X3+=Pinceau_X;
        Y3+=Pinceau_Y;
        Y4+=Pinceau_Y;
        Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0);
        Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0);
      }
      Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0);
      Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0);
      Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0);
      Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0);
  }
}
  // -- Effacer le curseur --
void Effacer_curseur(void)
{
  byte  Forme;
  int Debut_X; // int car sont parfois négatifs ! (quand on dessine sur un bord)
  int Debut_Y;
  short Fin_X;
  short Fin_Y;
  int Pos_X;
  int Pos_Y;
  short Compteur_X;
  short Compteur_Y;
  //short Fin_Compteur_X; // Position X ou s'arrête l'affichage de la brosse/pinceau
  //short Fin_Compteur_Y; // Position Y ou s'arrête l'affichage de la brosse/pinceau
  int   Temp;
  //byte  Couleur;
  float cosA,sinA;
  short X1,Y1,X2,Y2,X3,Y3,X4,Y4;
  if ( ( (Mouse_Y=Principal_X_Zoom) ) )
    || (Fenetre) || (Forme_curseur==FORME_CURSEUR_SABLIER) )
    Forme=Forme_curseur;
  else
    Forme=FORME_CURSEUR_FLECHE;
  switch(Forme)
  {
    case FORME_CURSEUR_CIBLE :
      if (!Cacher_curseur)
      {
        if (Config.Curseur==1)
        {
          Debut_Y=(Mouse_Y<6)?6-Mouse_Y:0;
          if (Debut_Y<4)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+Debut_Y-6,4-Debut_Y);
          Debut_X=(Mouse_X<6)?(short)6-Mouse_X:0;
          if (Debut_X<4)
            Ligne_horizontale_XOR(Mouse_X+Debut_X-6,Mouse_Y,4-Debut_X);
          Fin_X=(Mouse_X+7>Largeur_ecran)?Mouse_X+7-Largeur_ecran:0;
          if (Fin_X<4)
            Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,4-Fin_X);
          Fin_Y=(Mouse_Y+7>Hauteur_ecran)?Mouse_Y+7-Hauteur_ecran:0;
          if (Fin_Y<4)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+3,4-Fin_Y);
          UpdateRect(Mouse_X+Debut_X-6,Mouse_Y+Debut_Y-6,12-Fin_X,12-Fin_Y);
        }
        else
        {
          Temp=(Config.Curseur)?FORME_CURSEUR_CIBLE_FINE:FORME_CURSEUR_CIBLE;
          Debut_X=Mouse_X-Curseur_Decalage_X[Temp];
          Debut_Y=Mouse_Y-Curseur_Decalage_Y[Temp];
          for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
          {
            if(Pos_Y>=Hauteur_ecran) break;
            for (Pos_X=Debut_X,Compteur_X=0;Compteur_X<15;Pos_X++,Compteur_X++)
            {
              if ( (Pos_X<0) || (Pos_Y < 0)) continue;
              else if (Pos_X>=Largeur_ecran) break;
              Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]);
            }
          }
          UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Pos_X-Debut_X,Pos_Y-Debut_Y);
        }
      }
      if (!Cacher_pinceau)
      {
        Effacer_pinceau(Pinceau_X,Pinceau_Y);
      }
      break;
    case FORME_CURSEUR_CIBLE_PIPETTE:
      if (!Cacher_curseur)
      {
        if (Config.Curseur==1)
        {
          // Barres formant la croix principale
          Debut_Y=(Mouse_Y<5)?5-Mouse_Y:0;
          if (Debut_Y<3)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+Debut_Y-5,3-Debut_Y);
          Debut_X=(Mouse_X<5)?(short)5-Mouse_X:0;
          if (Debut_X<3)
            Ligne_horizontale_XOR(Mouse_X+Debut_X-5,Mouse_Y,3-Debut_X);
          Fin_X=(Mouse_X+6>Largeur_ecran)?Mouse_X+6-Largeur_ecran:0;
          if (Fin_X<3)
            Ligne_horizontale_XOR(Mouse_X+3,Mouse_Y,3-Fin_X);
          Fin_Y=(Mouse_Y+6>Hauteur_ecran)?Mouse_Y+6-Hauteur_ecran:0;
          if (Fin_Y<3)
            Ligne_verticale_XOR  (Mouse_X,Mouse_Y+3,3-Fin_Y);
          Debut_X=(!Mouse_X);
          Debut_Y=(!Mouse_Y);
          Fin_X=(Mouse_X>=Largeur_ecran-1);
          Fin_Y=(Mouse_Y>=Menu_Ordonnee-1);
          if (Mouse_Y>5)
            Ligne_horizontale_XOR(Debut_X+Mouse_X-1,Mouse_Y-6,3-(Debut_X+Fin_X));
          if (Mouse_X>5)
            Ligne_verticale_XOR  (Mouse_X-6,Debut_Y+Mouse_Y-1,3-(Debut_Y+Fin_Y));
          if (Mouse_X=0) && (Pos_X=0) && (Pos_Y=Largeur_ecran) break;
        for (Pos_Y=Debut_Y,Compteur_Y=0;Compteur_Y<15;Pos_Y++,Compteur_Y++)
	{
	    if(Pos_Y<0) continue;
	    if(Pos_Y>=Hauteur_ecran) break;
            Pixel(Pos_X,Pos_Y,FOND_CURSEUR[Compteur_Y][Compteur_X]);
	}
      }
      UpdateRect(Max(Debut_X,0),Max(Debut_Y,0),Compteur_X,Compteur_Y);
      break;
    case FORME_CURSEUR_CIBLE_XOR :
      Pos_X=Pinceau_X-Principal_Decalage_X;
      Pos_Y=Pinceau_Y-Principal_Decalage_Y;
      Compteur_X=(Loupe_Mode)?Principal_Split:Largeur_ecran; // Largeur de la barre XOR
      if ((Pos_Y=Limite_Haut))
      {
        Ligne_horizontale_XOR(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X);
        UpdateRect(0,Pinceau_Y-Principal_Decalage_Y,Compteur_X,1);
      }
      if ((Pos_X=Limite_Gauche))
      {
        Ligne_verticale_XOR(Pinceau_X-Principal_Decalage_X,0,Menu_Ordonnee);
        UpdateRect(Pinceau_X-Principal_Decalage_X,0,1,Menu_Ordonnee);
      }
      if (Loupe_Mode)
      {
        // UPDATERECT
        if ((Pinceau_Y>=Limite_Haut_Zoom) && (Pinceau_Y<=Limite_visible_Bas_Zoom))
          Ligne_horizontale_XOR_Zoom(Limite_Gauche_Zoom,Pinceau_Y,Loupe_Largeur);
        if ((Pinceau_X>=Limite_Gauche_Zoom) && (Pinceau_X<=Limite_visible_Droite_Zoom))
          Ligne_verticale_XOR_Zoom(Pinceau_X,Limite_Haut_Zoom,Loupe_Hauteur);
      }
      break;
    case FORME_CURSEUR_RECTANGLE_XOR :
      // !!! Cette forme ne peut pas être utilisée en mode Loupe !!!
      // Petite croix au centre
      Debut_X=(Mouse_X-3);
      Debut_Y=(Mouse_Y-3);
      Fin_X  =(Mouse_X+4);
      Fin_Y  =(Mouse_Y+4);
      if (Debut_X<0)
        Debut_X=0;
      if (Debut_Y<0)
        Debut_Y=0;
      if (Fin_X>Largeur_ecran)
        Fin_X=Largeur_ecran;
      if (Fin_Y>Menu_Ordonnee)
        Fin_Y=Menu_Ordonnee;
      Ligne_horizontale_XOR(Debut_X,Mouse_Y,Fin_X-Debut_X);
      Ligne_verticale_XOR  (Mouse_X,Debut_Y,Fin_Y-Debut_Y);
      // Grand rectangle autour
      Debut_X=Mouse_X-(Loupe_Largeur>>1);
      Debut_Y=Mouse_Y-(Loupe_Hauteur>>1);
      if (Debut_X+Loupe_Largeur>=Limite_Droite-Principal_Decalage_X)
        Debut_X=Limite_Droite-Loupe_Largeur-Principal_Decalage_X+1;
      if (Debut_Y+Loupe_Hauteur>=Limite_Bas-Principal_Decalage_Y)
        Debut_Y=Limite_Bas-Loupe_Hauteur-Principal_Decalage_Y+1;
      if (Debut_X<0)
        Debut_X=0;
      if (Debut_Y<0)
        Debut_Y=0;
      Fin_X=Debut_X+Loupe_Largeur-1;
      Fin_Y=Debut_Y+Loupe_Hauteur-1;
      Ligne_horizontale_XOR(Debut_X,Debut_Y,Loupe_Largeur);
      Ligne_verticale_XOR(Debut_X,Debut_Y+1,Loupe_Hauteur-2);
      Ligne_verticale_XOR(  Fin_X,Debut_Y+1,Loupe_Hauteur-2);
      Ligne_horizontale_XOR(Debut_X,  Fin_Y,Loupe_Largeur);
      UpdateRect(Debut_X,Debut_Y,Fin_X+1-Debut_X,Fin_Y+1-Debut_Y);
      break;
    default: //case FORME_CURSEUR_ROTATE_XOR :
      Debut_X=1-(Brosse_Largeur>>1);
      Debut_Y=1-(Brosse_Hauteur>>1);
      Fin_X=Debut_X+Brosse_Largeur-1;
      Fin_Y=Debut_Y+Brosse_Hauteur-1;
      if (Brosse_Centre_rotation_defini)
      {
        if ( (Brosse_Centre_rotation_X==Pinceau_X)
          && (Brosse_Centre_rotation_Y==Pinceau_Y) )
        {
          cosA=1.0;
          sinA=0.0;
        }
        else
        {
          Pos_X=Pinceau_X-Brosse_Centre_rotation_X;
          Pos_Y=Pinceau_Y-Brosse_Centre_rotation_Y;
          cosA=(float)Pos_X/sqrt((Pos_X*Pos_X)+(Pos_Y*Pos_Y));
          sinA=sin(acos(cosA));
          if (Pos_Y>0) sinA=-sinA;
        }
        Transformer_point(Debut_X,Debut_Y, cosA,sinA, &X1,&Y1);
        Transformer_point(Fin_X  ,Debut_Y, cosA,sinA, &X2,&Y2);
        Transformer_point(Debut_X,Fin_Y  , cosA,sinA, &X3,&Y3);
        Transformer_point(Fin_X  ,Fin_Y  , cosA,sinA, &X4,&Y4);
        X1+=Brosse_Centre_rotation_X;
        Y1+=Brosse_Centre_rotation_Y;
        X2+=Brosse_Centre_rotation_X;
        Y2+=Brosse_Centre_rotation_Y;
        X3+=Brosse_Centre_rotation_X;
        Y3+=Brosse_Centre_rotation_Y;
        X4+=Brosse_Centre_rotation_X;
        Y4+=Brosse_Centre_rotation_Y;
        Pixel_figure_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,0);
        Tracer_ligne_Preview_xor(Brosse_Centre_rotation_X,Brosse_Centre_rotation_Y,Pinceau_X,Pinceau_Y,0);
      }
      else
      {
        X1=X3=1-Brosse_Largeur;
        Y1=Y2=Debut_Y;
        X2=X4=Pinceau_X;
        Y3=Y4=Fin_Y;
        X1+=Pinceau_X;
        Y1+=Pinceau_Y;
        Y2+=Pinceau_Y;
        X3+=Pinceau_X;
        Y3+=Pinceau_Y;
        Y4+=Pinceau_Y;
        Pixel_figure_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,0);
        Tracer_ligne_Preview_xor(Pinceau_X-Fin_X,Pinceau_Y,Pinceau_X,Pinceau_Y,0);
      }
      Tracer_ligne_Preview_xor(X1,Y1,X2,Y2,0);
      Tracer_ligne_Preview_xor(X2,Y2,X4,Y4,0);
      Tracer_ligne_Preview_xor(X4,Y4,X3,Y3,0);
      Tracer_ligne_Preview_xor(X3,Y3,X1,Y1,0);
  }
}
// -- Fonction diverses d'affichage ------------------------------------------
  // -- Reafficher toute l'image (en prenant en compte le facteur de zoom) --
void Afficher_ecran(void)
{
  word Largeur;
  word Hauteur;
  // ---/\/\/\  Partie non zoomée: /\/\/\---
  if (Loupe_Mode)
  {
    if (Principal_Largeur_image