/* Nived: l'éditeur de niveaux de BomberInstinct */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL/SDL.h>

// P.K.
#include "types.h"
#include "common.h"

/* moved to types.h P.K.
typedef struct {
  Uint8 **frame;
  int nframes;
}animation;
*/

/* moved to types.h P.K.
typedef struct {
  int decalage;
  SDL_Palette *palette;
  animation **anims;
  int nanims;
}Sprite;
*/

Sprite *sprite;
SDL_Palette *pal;
int animactive=0, framactive=0, zoom;
SDL_Color trans, grille, fond;
Uint8 *frame;
int pinceau[3];
SDL_Rect vuedusprite, vuepalette, vueanim, ajus, vueasc;
SDL_Surface *ic_flechegd, *ic_flechehb, *ic_sauver;
char nom[256];
int vitesse=75;
int dessineplus=0;
int engrand=0;
//x int dx[4]={ 0, 0,-1, 1}; // moved to common.c
//x int dy[4]={-1, 1, 0, 0};

SDL_Surface *ecran;

int init_ecran(void)
{
  char titre[256];
  if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
    printf("Impossible d'initialiser SDL: %s\n",SDL_GetError());
    exit(1);
  }
  sprintf(titre, "Spred - l'éditeur de sprites de BomberInstinct - %s - v1.1", nom);
  SDL_WM_SetCaption(titre, "Spred");
  ecran = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE|SDL_HWPALETTE);

  if ( ecran == NULL ) {
    printf("Impossible de choisir le mode 640*480 8 bits!\n%s\n", SDL_GetError());
    return 1;
  }
  atexit(SDL_Quit);
  return 0;
}


void erreur(char message[200], char param[20])
{
  printf ("\nErreur :\n%s", message);
  if (param) printf(" : %s", param);
  printf (".\n%s\n", SDL_GetError());
  exit(0);
}


void passenpleinecran()
{
  int i, ncoul;
  SDL_Surface *sauvegarde;
  SDL_Color *pal;
  ncoul=ecran->format->palette->ncolors;
  pal=(SDL_Color *)calloc(ncoul, sizeof(SDL_Color));
  for (i=0; i<ncoul; i++)
    {
      pal[i].r=ecran->format->palette->colors[i].r;
      pal[i].g=ecran->format->palette->colors[i].g;
      pal[i].b=ecran->format->palette->colors[i].b;
    }

  sauvegarde=SDL_DisplayFormat(ecran);
  SDL_FreeSurface(ecran);
  if ((ecran->flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)
    ecran = SDL_SetVideoMode(640, 480, 8,
			     SDL_HWSURFACE|SDL_HWPALETTE);
  else
    ecran = SDL_SetVideoMode(640, 480, 8,
			     SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);

  SDL_SetColors(ecran, pal, 0, ncoul);
  free(pal);
  SDL_BlitSurface(sauvegarde, NULL, ecran, NULL);
  SDL_Flip(ecran);
  SDL_FreeSurface(sauvegarde);
  return;
}


animation  * cree_animation(int nframes)
{
  int i;
  animation *anim;
  anim = (animation *)malloc(sizeof(animation));
  anim->nframes = nframes;
  anim->frame = (Uint8 **)calloc(40, sizeof *anim->frame);
  for (i=0; i<nframes; i++) {
    anim->frame[i] = (Uint8 *)malloc(1024);
    memset(anim->frame[i], 0, 1024); }
  return anim;
}


Sprite * cree_sprite(int nb_anims, int nb_coul)
{
  Sprite *spri;
  spri = (Sprite *)malloc(sizeof(Sprite));
  spri->nanims   = nb_anims;
  spri->anims    = (animation **)calloc(50, sizeof *spri->anims);
  spri->palette  = (SDL_Palette *)malloc(sizeof(SDL_Palette));
  spri->palette->colors  = (SDL_Color *)calloc(30, sizeof spri->palette->colors);
  memset(spri->palette->colors, 0, 30*3);
  spri->palette->ncolors = nb_coul;
  return spri;
}


int caseclic(int x, int y, int orig_x, int orig_y, int dim, int largeur)
{
  x=(x-orig_x)/dim;
  y=(y-orig_y)/dim;
  return (x+largeur*y);
}


void sauv(void)
{
  int i;
  memcpy(frame, sprite->anims[animactive]->frame[framactive], 1024);
  pal->ncolors=sprite->palette->ncolors;
  for (i=0; i<sprite->palette->ncolors; i++)
    {
      pal->colors[i].r=sprite->palette->colors[i].r;
      pal->colors[i].g=sprite->palette->colors[i].g;
      pal->colors[i].b=sprite->palette->colors[i].b;
    }
  return;
}


void undo(void)
{
  int i;
  Uint8 * frameb;
  SDL_Palette *palb;
  frameb=(Uint8 *)malloc(1024);
  palb=(SDL_Palette *)malloc(sizeof(SDL_Palette));
  palb->colors=(SDL_Color *)calloc(30, sizeof(SDL_Color));

  memcpy(frameb, sprite->anims[animactive]->frame[framactive], 1024);
  palb->ncolors=sprite->palette->ncolors;
  for (i=0; i<sprite->palette->ncolors; i++)
    {
      palb->colors[i].r=sprite->palette->colors[i].r;
      palb->colors[i].g=sprite->palette->colors[i].g;
      palb->colors[i].b=sprite->palette->colors[i].b;
    }
  memcpy(sprite->anims[animactive]->frame[framactive], frame, 1024);
  sprite->palette->ncolors=pal->ncolors;
  for (i=0; i<pal->ncolors; i++)
    {
      sprite->palette->colors[i].r=pal->colors[i].r;
      sprite->palette->colors[i].g=pal->colors[i].g;
      sprite->palette->colors[i].b=pal->colors[i].b;
    }
  memcpy(frame, frameb, 1024);
  pal->ncolors=palb->ncolors;
  for (i=0; i<sprite->palette->ncolors; i++)
    {
      pal->colors[i].r=palb->colors[i].r;
      pal->colors[i].g=palb->colors[i].g;
      pal->colors[i].b=palb->colors[i].b;
    }
  free(frameb);
  return;
}


Sprite * charge_sprite(FILE *spr_fich)
{
  unsigned int i, j;
  unsigned int nanims, ncoul;
  unsigned int nframes;
  unsigned char lect;
  Uint8  *pal;
  Uint8  *fr;
  Sprite *spr;
  
  fread(&lect, 1, 1, spr_fich);
  ncoul=lect;
  fread(&lect, 1, 1, spr_fich);
  nanims=lect;

  spr = cree_sprite(nanims, ncoul);
  fr  = (Uint8 *)malloc(1024);
  pal = (Uint8 *)malloc(3*ncoul);

  /* D'abord on lit la palette */

  if (fread(pal, 3, ncoul, spr_fich)!= ncoul)
    erreur("Palette du sprite corrompue", NULL);
  for (i=0; i<ncoul; i++)
    {
      spr->palette->colors[i].r = *(pal+3*i);
      spr->palette->colors[i].g = *(pal+3*i+1);
      spr->palette->colors[i].b = *(pal+3*i+2);
    }
  free(pal);

  /* Puis les anims */
  
  for (i=0; i<nanims; i++)
    {
      fread(&lect, 1, 1, spr_fich);
      nframes=lect;
      spr->anims[i] = cree_animation(nframes);
      for (j=0; j<nframes; j++)
	{
	  if (fread(spr->anims[i]->frame[j], 1, 1024, spr_fich)!=1024)
	    erreur("Contenu du sprite corrompu", NULL);
	}
    }
  free(fr);
  SDL_SetColors(ecran, spr->palette->colors, 1, spr->palette->ncolors+1);
  printf("Salut !\n");
  return spr;
}


void animcoul()
{
  int j, ncoul;
  ncoul=sprite->palette->ncolors;
  for (j=0; j<ncoul+1; j++)
    {
      SDL_SetColors(ecran, sprite->palette->colors , ncoul-j+1, j);
      SDL_SetColors(ecran, sprite->palette->colors+j, 1, ncoul-j);
    }
  return;
}


void sauvesprite(char *nom)
{
  int i, j, k;
  FILE *fich;
  fich = fopen(nom,"wb");
  if (fich==NULL) {
    printf("\nErreur:\nImpossible d'ouvrir le fichier en écriture: %s\n\n", nom);
    exit(0); }
  fputc((Uint8)sprite->palette->ncolors, fich);
  fputc((Uint8)sprite->nanims, fich);
  for (i=0; i<sprite->palette->ncolors ; i++)
    {
      fputc(sprite->palette->colors[i].r, fich);
      fputc(sprite->palette->colors[i].g, fich);
      fputc(sprite->palette->colors[i].b, fich);
    }
  for (i=0; i<sprite->nanims; i++)
    {
      fputc(sprite->anims[i]->nframes, fich);  
      for (j=0; j<sprite->anims[i]->nframes; j++)
	for (k=0; k<1024; k++)
	  fputc(sprite->anims[i]->frame[j][k], fich);
    }
  fclose(fich);
  return;
}


void sauvebmp(void)
{
  SDL_Surface *img;
  SDL_Palette *fauxpal;
  SDL_Rect src={600, 8, 32, 32};
  char nombmp[256];
  int ret;

  img=SDL_CreateRGBSurface (0, 32, 32, 8, 0, 0, 0, 0);
  
  fauxpal=img->format->palette;
  img->format->palette=ecran->format->palette;
  SDL_BlitSurface (ecran, &src, img, NULL);

#ifdef win32
  sprintf(nombmp, "image.bmp");
#else
  sprintf(nombmp, "%s.bmp", nom);
#endif
  ret=SDL_SaveBMP(img, nombmp);
  printf ("Exportation de l'image dans %s: %s\n", nombmp, ret ? "ECHEC !" : "OK");

  img->format->palette=fauxpal;
  SDL_FreeSurface(img);
  return;
}


void blitsprit(Sprite *spr, int anim, int frame, int x,int y)
{
  int i, j, loc;
  loc = x + y*640;
  if (SDL_LockSurface(ecran)<0)
    erreur("Impossible de verrouiller l'écran", NULL);
  for (i=0; i<32; i++)
    for (j=0; j<32; j++)
      if (spr->anims[anim]->frame[frame][i*32+j])
	((Uint8 *)ecran->pixels)[loc+i*640+j] = spr->anims[anim]->frame[frame][i*32+j];
  SDL_UnlockSurface(ecran);
  SDL_UpdateRect(ecran, x, y, 32, 32);
  return;
}


void animations(void)
{
  int nframes, i;
  SDL_Rect active, asc;
  nframes=sprite->anims[animactive]->nframes;
  SDL_FillRect(ecran, &vueanim, 200);
  active.w=active.h=32;
  active.y=15;
  active.x=15+framactive*32;
  SDL_FillRect(ecran, &active, 201); 
  for (i=0; i<nframes; i++)
    {
      blitsprit(sprite, animactive, i, 32*i+15, 15);
    }
  SDL_UpdateRects(ecran, 1, &vueanim);
  asc.x=5; asc.w=5;
  asc.h=42/sprite->nanims+1;
  asc.y=10+(animactive*42)/sprite->nanims;
  SDL_FillRect(ecran, &vueasc, 200);
  SDL_FillRect(ecran, &asc, 1);
  SDL_UpdateRects(ecran, 1, &vueasc);
  return;
}


void redessine()
{
  int i, j;
  SDL_Rect dest;
  dest.w=zoom-1;
  dest.h=zoom-1;
  SDL_FillRect(ecran, &vuedusprite, 201);
  for (dest.y=448-32*zoom, i=0; i<32; dest.y+=zoom, i++)
    for (dest.x=32, j=0; j<32; dest.x+=zoom, j++)
      {
	if (sprite->anims[animactive]->frame[framactive][i*32+j])
	  SDL_FillRect(ecran, &dest, sprite->anims[animactive]->frame[framactive][i*32+j]);
	else
	  {
	    dest.x++; dest.y++; dest.w--; dest.h--;
	    SDL_FillRect(ecran, &dest, 200);
	    dest.x--; dest.y--; dest.w++; dest.h++;
	  }
      }
  dest.x=560; dest.y=8; dest.w=32; dest.h=32*(1+dessineplus);
  SDL_FillRect(ecran, &dest, 0);
  dest.x=598; dest.y=6; dest.w=36; dest.h=34*(1+dessineplus);
  SDL_FillRect(ecran, &dest, 200);
  blitsprit(sprite, animactive, framactive, 600, 8);
  blitsprit(sprite, animactive, framactive, 560, 8);
  if (dessineplus && animactive+1<sprite->nanims)
    if (framactive<sprite->anims[animactive+1]->nframes)
      {
	blitsprit(sprite, animactive+1, framactive, 600, 40);
	blitsprit(sprite, animactive+1, framactive, 560, 40);
      }
  SDL_UpdateRects(ecran, 1, &vuedusprite);
  animations();
  return;
}


void toutautour(int cas, int couleur)
{
  Uint8 *frame;
  frame=sprite->anims[animactive]->frame[framactive];
  frame[cas]=pinceau[0];
  if (cas%32)
    if (frame[cas-1]==couleur)
      toutautour(cas-1, couleur);
  if (cas%32!=31)
    if (frame[cas+1]==couleur)
      toutautour(cas+1, couleur);
  if (cas/32)
    if (frame[cas-32]==couleur)
      toutautour(cas-32, couleur);
  if (cas/32!=31)
    if (frame[cas+32]==couleur)
      toutautour(cas+32, couleur);

  return;
}

void remplit(int x, int y)
{
  int orig, couleur;
  sauv();
  orig=caseclic(x, y, 31, 448-32*zoom, zoom, 32);	
  couleur=sprite->anims[animactive]->frame[framactive][orig];
  if (couleur!=pinceau[0])
    toutautour(orig, couleur);
  redessine();
  return;
}


void ajuste()
{
  int coul;
  SDL_Color rgb;
  SDL_Rect barre, curs;
  
  coul=pinceau[0] ? pinceau[0] : 200;
  rgb.r=rgb.g=rgb.b=0;
  barre.x=570; barre.y=190;
  barre.w=3; barre.h=256;
  SDL_FillRect(ecran, &ajus, 0);

  rgb.r=255; SDL_SetColors(ecran, &rgb, 150, 1);
  SDL_FillRect(ecran, &barre, 150);
  barre.x+=15; rgb.r=0; rgb.g=255; SDL_SetColors(ecran, &rgb, 151, 1);
  SDL_FillRect(ecran, &barre, 151);
  barre.x+=15; rgb.g=0; rgb.b=255; SDL_SetColors(ecran, &rgb, 152, 1);
  SDL_FillRect(ecran, &barre, 152);

  curs.x=565;
  curs.w=13; curs.h=5;
  rgb.r=ecran->format->palette->colors[coul].r;
  rgb.g=ecran->format->palette->colors[coul].g;
  rgb.b=ecran->format->palette->colors[coul].b;
  curs.y=444-rgb.r;
  SDL_FillRect(ecran, &curs, coul);
  curs.y=444-rgb.g;
  curs.x+=15;
  SDL_FillRect(ecran, &curs, coul);
  curs.y=444-rgb.b;
  curs.x+=15;
  SDL_FillRect(ecran, &curs, coul);

  SDL_UpdateRects(ecran, 1, &ajus); 
  return;
}


void dessinepalette()
{
  int i, j;
  int ncoul=sprite->palette->ncolors;
  SDL_Rect dest;
  SDL_FillRect(ecran, &vuepalette, 201);
  dest.w=dest.h=14;
  dest.y=402; dest.x=383;
  for (i=0; i<3; dest.y+=15, i++)
    for (dest.x=383, j=0; j<10; dest.x+=15, j++)
      {
	if (pinceau[0]==10*i+j){
	  dest.w=dest.h=12; dest.x++; dest.y++;
	  SDL_FillRect(ecran, &dest, pinceau[0] ? pinceau[0] : 200);
	  dest.w=dest.h=14; dest.x--; dest.y--;
	}
	else if (pinceau[1]==10*i+j){
	  dest.w=dest.h=10; dest.x+=2; dest.y+=2;
	  SDL_FillRect(ecran, &dest, pinceau[1] ? pinceau[1] : 200);
	  dest.w=dest.h=14; dest.x-=2; dest.y-=2;
	}
	else if (pinceau[2]==10*i+j){
	  dest.w=dest.h=8; dest.x+=3; dest.y+=3;
	  SDL_FillRect(ecran, &dest, pinceau[2] ? pinceau[2] : 200);
	  dest.w=dest.h=14; dest.x-=3; dest.y-=3;
	}
	else if (10*i+j<=ncoul)
	  SDL_FillRect(ecran, &dest, 10*i+j ? 10*i+j : 200);
      }
  SDL_UpdateRects(ecran, 1, &vuepalette);
  ajuste();
  return;
}


void reglecouleur(int x, int y, int bouton)
{
  int couleur=0;
  SDL_Color rgb;
  sauv();
  if (bouton==1)
    couleur=pinceau[0] ? pinceau[0] : 200;
  else if (bouton==2)
    couleur=0;
  else if (bouton==3)
    couleur=201;
  rgb.r=ecran->format->palette->colors[couleur].r;
  rgb.g=ecran->format->palette->colors[couleur].g;
  rgb.b=ecran->format->palette->colors[couleur].b;

  if (564<x && x<578)
    rgb.r=446-y;
  else if (579<x && x<593)
    rgb.g=446-y;
  else if (594<x && x<608)
    rgb.b=446-y;
  if (0<couleur && couleur<=sprite->palette->ncolors)
    {
      sprite->palette->colors[couleur-1].r=rgb.r;
      sprite->palette->colors[couleur-1].g=rgb.g;
      sprite->palette->colors[couleur-1].b=rgb.b;
    }
  SDL_SetColors(ecran, &rgb, couleur, 1);
  ajuste();
  return;
}


void decalepalette(int couleura, int couleurb)
{
  int i, coul, ncoul, ani, fra;
  SDL_Color buf;
  sauv();

  ncoul=sprite->palette->ncolors;
  buf.r=sprite->palette->colors[couleurb].r;
  buf.g=sprite->palette->colors[couleurb].g;
  buf.b=sprite->palette->colors[couleurb].b;

  sprite->palette->colors[couleurb].r=sprite->palette->colors[couleura].r;
  sprite->palette->colors[couleurb].g=sprite->palette->colors[couleura].g;
  sprite->palette->colors[couleurb].b=sprite->palette->colors[couleura].b;
      
  sprite->palette->colors[couleura].r=buf.r;
  sprite->palette->colors[couleura].g=buf.g;
  sprite->palette->colors[couleura].b=buf.b;
  
  for (ani=0; ani<sprite->nanims; ani++)
    for (fra=0; fra<sprite->anims[ani]->nframes; fra++)
      {
	for (i=0; i<1024; i++)
	  {
	    coul=sprite->anims[ani]->frame[fra][i];
	    if (coul==couleura+1)
	      sprite->anims[ani]->frame[fra][i]=couleurb+1;
	    else if (coul==couleurb+1)
	      sprite->anims[ani]->frame[fra][i]=couleura+1;
	  }
      }
  SDL_SetColors(ecran, sprite->palette->colors, 1, ncoul);
  redessine();
  return;
}


void changepalette(int x, int y, int bouton)
{
  int couleur, couleurb, ncoul;
  SDL_Event evt;
  ncoul=sprite->palette->ncolors;
  couleur = caseclic(x, y, 383, 402, 15, 10);
  if (couleur<=sprite->palette->ncolors)
    {
      pinceau[bouton-1]=couleur;
      do
	SDL_WaitEvent(&evt);
      while (evt.type!=SDL_MOUSEBUTTONUP);
      if (381<evt.button.x && evt.button.x<534 && 400<evt.button.y  && evt.button.y<447)
	{
	  couleurb = caseclic(evt.button.x, evt.button.y, 383, 402, 15, 10);
	  if (couleurb!=couleur && 0<couleurb  && 0<couleur && couleurb<=ncoul)
	    decalepalette(couleur-1, couleurb-1);
	}
    }
  else {
    sauv();
    sprite->palette->ncolors++;
    sprite->palette->colors[ncoul].r=0;
    sprite->palette->colors[ncoul].g=0;
    sprite->palette->colors[ncoul].b=0;
    SDL_SetColors(ecran, sprite->palette->colors+ncoul, ncoul+1, 1);
    pinceau[0]=ncoul+1; }
  dessinepalette();
  return;
}


void dessinepix(int x,int y, int bouton)
{
  int n;
  SDL_Event evt;
  sauv();
  do {
    if (31<x && x<31+32*zoom && 448-32*zoom<y && y<448)
      {
	n=caseclic(x, y, 31, 448-32*zoom, zoom, 32);
	sprite->anims[animactive]->frame[framactive][n] = pinceau[bouton-1];
	redessine();
      }
    SDL_WaitEvent(&evt);
    bouton = SDL_GetMouseState(&x, &y);
    if (bouton==4) bouton--; }
  while (bouton);
  return;
}


void deplace(int dir)
{
  int i, j;
  Uint8 k;
  Uint8 *buf, *frame;
  buf=(Uint8 *)malloc(1024);
  frame=sprite->anims[animactive]->frame[framactive];
  switch(dir) {
  case 0: {
    memcpy(buf, frame, 32);
    memmove(frame, frame+32, 992);
    memcpy(frame+992, buf, 32);
  }break;
  case 1: {
    memcpy(buf, frame+992, 32);
    memmove(frame+32, frame, 992);
    memcpy(frame, buf, 32);
  }break;
  case 2: {
    for(i=0; i<32; i++)
      {
	k=frame[32*i];
	memmove(frame+32*i, frame+32*i+1, 31);
	frame[32*i+31]=k;
      }
  }break;
  case 3: {
    for(i=0; i<32; i++)
      {
	k=frame[32*i+31];
	memmove(frame+32*i+1, frame+32*i, 31);
	frame[32*i]=k;
      }
  }break;
  case 4: {
    for(i=0; i<16; i++)
      {
	memcpy(buf, frame+i*32, 32);
	memmove(frame+i*32, frame+32*(31-i), 32);
	memcpy(frame+32*(31-i), buf, 32);
      }
  }break;
  case 5: {
    for(i=0; i<32; i++)
      for(j=0; j<16; j++)
	{
	  k=frame[i*32+j];
	  frame[i*32+j]=frame[i*32+31-j];
	  frame[i*32+31-j]=k;
	}
  }break;
  case 6: {
    memcpy(buf, frame, 1024);
    for(i=0; i<32; i++)
      for(j=0; j<32; j++)
	{
	  frame[i*32+j]=buf[(31-j)*32+i];
	}
  }break;
  }
  free(buf);
  redessine();
  return;
}


void changeframe(int x, int y)
{
  int frame, frameb, nframes, i;
  animation *anim;
  SDL_Event evt;
  Uint8 *pframe, *pframeb, *buf;
  frame=caseclic(x, y, 15, 15, 32, 15);
  nframes=sprite->anims[animactive]->nframes;
  sauvesprite("spred~");
  if (frame>=nframes || frame<0)
    return;
  pframe=sprite->anims[animactive]->frame[frame];
  do
    SDL_WaitEvent(&evt);
  while (evt.type!=SDL_MOUSEBUTTONUP);
  x=evt.button.x;
  y=evt.button.y;
  if (15<x && x<527 && 15<y && y<47)
    frameb=caseclic(x, y, 15, 15, 32, 15);
  else if (15<x && x<47 && 5<y && y<15 && animactive)
    {
      anim=sprite->anims[animactive-1];
      sprite->anims[animactive-1]=sprite->anims[animactive];
      sprite->anims[animactive]=anim;
      animactive--;
      redessine();
      return;
    }
  else if (15<x && x<47 && 47<y && y<57 && animactive<sprite->nanims-1)
    {
      anim=sprite->anims[animactive+1];
      sprite->anims[animactive+1]=sprite->anims[animactive];
      sprite->anims[animactive]=anim;
      animactive++;
      redessine();
      return;
    }
  else
    {
      sauv();
      for (i=frame; i<nframes-1; i++)
	memcpy(sprite->anims[animactive]->frame[i], sprite->anims[animactive]->frame[i+1], 1024);
      if (nframes>1)
	{
	  sprite->anims[animactive]->nframes--;
	  free(sprite->anims[animactive]->frame[nframes-1]);
	}
      framactive=0;
      redessine();
      return;
    }
  
  if (frame==frameb)
    {
      framactive=frame;
    }
  else if (frameb>=nframes)
    {
      sprite->anims[animactive]->nframes++;
      sprite->anims[animactive]->frame[nframes]=(Uint8 *)malloc(1024);
      memset(sprite->anims[animactive]->frame[nframes], 0, 1024);
      for (i=0; i<1024; i++)
	memcpy(sprite->anims[animactive]->frame[nframes],
	       sprite->anims[animactive]->frame[frame], 1024);
      framactive=nframes;
    }
  else
    {
      buf=(Uint8 *)malloc(1024);
      pframeb=sprite->anims[animactive]->frame[frameb];
      memcpy(buf, pframe, 1024);
      memcpy(pframe, pframeb, 1024);
      memcpy(pframeb, buf, 1024);
      free(buf);
    }
  redessine();
  return;
}


void anime(int dir_x, int dir_y)
{
  int i, brk=0;
  int framactivesg=framactive;
  SDL_Rect dest, destb;
  SDL_Event evt;
  SDL_WaitEvent(&evt);
  if (engrand)
    {
      do
	{
	  for (i=0; i<sprite->anims[animactive]->nframes; i++)
	    {
	      SDL_PumpEvents();
	      brk=SDL_GetMouseState(NULL, NULL);
	      if (brk) break;
	      SDL_Delay(vitesse);
	      framactive=i;
	      redessine();
	    }
	}
      while (!brk);
      framactive=framactivesg;
      redessine();
    }
  else if (dir_x==0 && dir_y==0)
    {
      dest.x=560; dest.y=8; dest.w=dest.h=32;
      destb.x=598; destb.y=6; destb.w=destb.h=36;
      SDL_FillRect(ecran, &dest, 0);
      SDL_FillRect(ecran, &destb, 200);
      do
	{
	  for (i=0; i<sprite->anims[animactive]->nframes; i++)
	    {
	      SDL_PumpEvents();
	      brk=SDL_GetMouseState(NULL, NULL);
	      if (brk) break;
	      SDL_Delay(vitesse);
	      blitsprit(sprite, animactive, i, 600, 8);
	      blitsprit(sprite, animactive, i, 560, 8);
	      SDL_FillRect(ecran, &dest, 0);
	      SDL_FillRect(ecran, &destb, 200);
	    }
	}
      while (!brk);
      redessine();
    }
  else
    {
      if (animactive>=4) return;
      dir_x=dx[animactive]; dir_y=dy[animactive];
      dest.x=450; dest.y=120; dest.w=dest.h=32;
      for (i=0; i<9; i++)
	{
	  SDL_Delay(vitesse);
	  SDL_FillRect(ecran, &dest, 0);
	  SDL_UpdateRects(ecran, 1, &dest);
	  dest.x=450+i*dir_x*4; dest.y=120+i*dir_y*4;
	  blitsprit(sprite, animactive, i<sprite->anims[animactive]->nframes ? i : 0, dest.x, dest.y);
	}
      SDL_Delay(300);
      SDL_FillRect(ecran, &dest, 0);
      SDL_UpdateRects(ecran, 1, &dest);
    }
  return;
}


void changeanim(int sens)
{
  if (sens<0 && animactive>0)
    {
      animactive--;
      framactive=0;
      redessine();
    }
  else if (sens>0 && animactive<sprite->nanims-1)
    {
      animactive++;
      framactive=0;
      redessine();
    }
}

void clic(int x, int y, int bouton)
{
  Uint8 *touches;
  touches=SDL_GetKeyState(NULL);
  if (31<x && x<31+32*zoom && 448-32*zoom<y && y<448)
    {
      if (touches[SDLK_SPACE]==SDL_PRESSED) {
	remplit(x, y); }
      else
	dessinepix(x, y, bouton);
    }
  else if (381<x && x<534 && 400<y && y<447)
    changepalette(x, y, bouton);
  else if (564<x && x<622 && 189<y && y<447)
    reglecouleur(x, y, bouton);
  else if (15<x && x<527 && 15<y && y<47)
    changeframe(x, y);
  else if (560<x && x<626 && 8<y && y<44)
    anime(0, 0);
  else if (15<x && x<47 && 5<y && y<15)
    changeanim(-1);
  else if (15<x && x<47 && 47<y && y<57)
    changeanim(+1);
  return;
}


void supprimecouleur(int couleur)
{
  int i, ani, fra;
  sauv();
  
  for (i=couleur-1; i<sprite->palette->ncolors-1; i++)
    {
      sprite->palette->colors[i].r=sprite->palette->colors[i+1].r;
      sprite->palette->colors[i].g=sprite->palette->colors[i+1].g;
      sprite->palette->colors[i].b=sprite->palette->colors[i+1].b;
    }
  for (ani=0; ani<sprite->nanims; ani++)
    for (fra=0; fra<sprite->anims[ani]->nframes; fra++)
      {
	for (i=0; i<1024; i++)
	  if (sprite->anims[ani]->frame[fra][i]>couleur)
	    sprite->anims[ani]->frame[fra][i]--;
      }
  sprite->palette->ncolors--;
  SDL_SetColors(ecran, sprite->palette->colors, 1, sprite->palette->ncolors);
  redessine();
  dessinepalette();
}

	
void appui(int touche, int mod)
{
  int i;
  SDL_Rect rect;
  switch(touche) {
  case SDLK_F1: {
    passenpleinecran();
  }break;
  case SDLK_s: {
    sauvesprite(nom);
  }break;
  case SDLK_LESS: {
    anime(0, 0);
  }break;
  case SDLK_c: {
    if (mod==KMOD_LCTRL)
      exit(0);
  }break;
  case SDLK_F10: {
    exit(0);
  }break;
  case SDLK_d: {
    if (mod==KMOD_LCTRL) {
      memset(sprite->anims[animactive]->frame[framactive], 0, 1024);
      redessine(); }
  }break;
  case SDLK_UP: {
    deplace(0);
  }break;
  case SDLK_DOWN: {
    deplace(1);
  }break;
  case SDLK_LEFT: {
    deplace(2);
  }break;
  case SDLK_RIGHT: {
    deplace(3);
  }break;
  case SDLK_u: {
    undo();
    redessine();
  }break;
  case SDLK_a: {
    animcoul();
  }break;
  case SDLK_g: {
    if (engrand)
      engrand=0;
    else
      engrand=1;
  }break;
  case SDLK_p: {
    if (dessineplus)
      dessineplus=0;
    else
      dessineplus=1;
    rect.x=560; rect.y=6;
    rect.w=74; rect.h=68;
    SDL_FillRect(ecran, &rect, 0);
    SDL_UpdateRects(ecran, 1, &rect);
    redessine();
  }break;
  case SDLK_n: {
    sprite->anims[sprite->nanims]=cree_animation(1);
    memcpy(sprite->anims[sprite->nanims]->frame[0],
	   sprite->anims[animactive]->frame[framactive], 1024);
    sprite->nanims++;
    redessine();
  }break;
  case SDLK_t: {
    if (mod==KMOD_LCTRL && sprite->nanims>1)
      {
	free(sprite->anims[animactive]);
	for (i=animactive; i<sprite->nanims; i++)
	  sprite->anims[i]=sprite->anims[i+1];
	sprite->nanims--;
	animactive=0;
	framactive=0;
	redessine();
      }
  }break;
  case SDLK_e: {
    if (pinceau[0] && pinceau[0]<sprite->palette->ncolors)
      supprimecouleur(pinceau[0]);
  }break;
  case SDLK_k: {
    if (mod==KMOD_LCTRL && sprite->nanims>1)
      {
	free(sprite->anims[sprite->nanims-1]);
	sprite->nanims--;
	animactive=0;
	framactive=0;
	redessine();
      }
  }break;
  case SDLK_m: {
    anime(1,1);
  }break;
  case SDLK_h: {
    deplace(4);
  }break;
  case SDLK_v: {
    deplace(5);
  }break;
  case SDLK_r: {
    deplace(6);
  }break;
  case SDLK_KP_PLUS: {
    if (vitesse>=5) vitesse-=5;
  }break;
  case SDLK_KP_MINUS: {
    if (vitesse<250) vitesse+=5;
  }break;
  case SDLK_b: {
    sauvebmp();
  }break;
  }
  return;
}


int main(int argc, char **argv)
{
  SDL_Rect chanim;
  SDL_Event evt;
  FILE *test;
  int x, y, bouton;
  frame=(Uint8 *)malloc(1024);
  pal=(SDL_Palette *)malloc(sizeof(SDL_Palette));
  pal->colors=(SDL_Color *)calloc(30, sizeof(SDL_Color));

  if (argc>1)
    strcpy(nom, argv[1]);
  else {
    printf("Nom du sprite à ouvrir (*.spr): ");
    scanf("%s", nom); }

  if (init_ecran()) return 1;

  chanim.w=32; chanim.h=10;
  chanim.x=15; chanim.y=5;
  SDL_FillRect(ecran, &chanim, 200);
  chanim.y=47;
  SDL_FillRect(ecran, &chanim, 200);
  trans.r=0; trans.g=0; trans.b=120;
  fond.r=72; fond.g=72; fond.b=138;
  pinceau[0]=1; pinceau[1]=0; pinceau[2]=0;
  grille.r=0; grille.g=0; grille.b=85;
  zoom=10;

  vuedusprite.y=447-32*zoom; vuedusprite.x=31;
  vuedusprite.w=32*zoom+1; vuedusprite.h=32*zoom+1;
  vuepalette.x=382; vuepalette.y=401;
  vuepalette.w=151; vuepalette.h=46;
  vueanim.x=15; vueanim.y=15;
  vueanim.w=512; vueanim.h=32;
  ajus.x=564; ajus.y=187;
  ajus.w=58; ajus.h=262;
  vueasc.x=5; vueasc.y=10;
  vueasc.w=5; vueasc.h=43;

  SDL_SetColors(ecran, &trans, 200, 1);
  SDL_SetColors(ecran, &grille, 201, 1);
  test=fopen(nom, "rb");
  if (test==NULL)
    {
      sprite=cree_sprite(1, 1);
      sprite->anims[0]=cree_animation(1);
      sprite->palette->colors[0].r=sprite->palette->colors[0].g=sprite->palette->colors[0].b=0;
      sauvesprite(nom);
    }
  else
    sprite=charge_sprite(test);
  redessine();
  dessinepalette();
  animations();
  SDL_SetColors(ecran, &fond, 0, 1);
  while(SDL_WaitEvent(&evt)>=0)
    {
      switch(evt.type)
	{
	  
	case SDL_MOUSEBUTTONDOWN: {
	  bouton=evt.button.button;
	  x=evt.button.x; y=evt.button.y;
	  clic(x,y,bouton);
	}break;

	case SDL_KEYDOWN: {
	  appui(evt.key.keysym.sym, evt.key.keysym.mod);
	}break;

	case SDL_QUIT: {
	  printf("Terminé correctement\n");
	  exit(0);
	}break;
	}
    }
  return 0;
}
