//Active le tampon Annuler
#define UNDO_BUFFER_ACTIF
//Nombre maximal d'opérations annulables. La mémoire va être calculée en fonction de ça.
#define OPMAX 100000
int MAXUNDORAM=20000000;
//Calcule la mémoire à utiliser de manière à pouvoir annuler OPMAX opérations.
#define CALC_MEMOIRE_UNDO
//Si CALC_MEMOIRE_UNDO est inactif, on alloue un bloc de taille fixe. Le nombre d'
//opérations qui seront annulables dépendra de la taille de la carte...
//#define ALLOC_UNDO_FIXE 20000000

//Grandeurs/position souris tileset
int gdrXt=128, tposX=0, tposY=0;
int gdrXtc=128;
int basegdrXtc=128;
int bSizingTileset=0;
POINT pSizingPos;
SD_PARAMS *gblSdParam;

#define LIEN_INVALIDE 255
#define TAILLE_BLOCCOPIE (1024*1024*sizeof(MAP))
#define MAXBLOCS 5

int modeArrondi=0;

#define ArronditX(val)	{ if (modeArrondi) val&=~(grilleX-1); }
#define ArronditHautX(val)	{ if (modeArrondi && val&(grilleX-1)) val=((val)&~(grilleX-1))+grilleX; }
#define ArronditY(val)	{ if (modeArrondi) val&=~(grilleY-1); }
#define ArronditHautY(val)	{ if (modeArrondi && val&(grilleY-1)) val=((val)&~(grilleY-1))+grilleY; }
#define ArronditTileX(val)	{ val&=~(tileX-1); }
#define ArronditTileY(val)	{ val&=~(tileY-1); }

int listeSelection, selectionPointee, typeCoordCopie=0, CopieXprecise, CopieYprecise;
//int mouseOffsetX, mouseOffsetY;
int grilleX=8, grilleY=8;

#define MAX_LST_SEL_MUL 1024
int lstSelMulNbre=0;					//Nombre de sélections
int lstSelMulListe[MAX_LST_SEL_MUL];
SPRITE_LISTE lstCopyBuf;				//Copier/Coller des listes


unsigned char liens[MAX_FONDS][MAX_FONDS];
int gdrX=0, gdrY=0, gdrXz=0, gdrYz=0, zoomPrecis=0, majRequise=0, grille=0;
double zoom=1.0;
int fenBits;

HWND gblHEdit;


const unsigned long Charset[80*3]=	{
	0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0
};

unsigned char tempalette[6]={255,255,255,0,0,0};



void DessNombre (int x,int y,int nombre,int coul)		{
	int i,j,xx,yy,k;
	unsigned char *ptr=(unsigned char *)&coul;

	tempalette[5]=*ptr++;
	tempalette[4]=*ptr++;
	tempalette[3]=*ptr++;

	xx=x+tileX/2;
	yy=y+tileY/2-1;

	i=ModeTexte?4:2;
	j=0;
	
	do	{
		k=nombre&0xf;
		nombre>>=4;
		SpritePalSansMasque(Bits3,xx,yy,3,5,(unsigned long*)Charset+15*k,tempalette);
		xx-=4;
		j++;
		if (j==2)	{
			xx+=8;
			yy-=6;
		}
		if (combleZeros)		{
			if (j>=i)
				break;
		}
		else	{
			if ((!nombre && j==2) || j>=i)
				break;
		}
	} while(1);
}

#define BASEDIT_X 10
#define BASEDIT_Y 10
void CreeBarresDefil(HWND hDlg);
unsigned char *gblPal;
unsigned long *gblMotifs;
MAP *gblMap;
int num_edit, tileBaseX, tileBaseY;
int fond_actif[MAX_FONDS]; //, fond_editable[MAX_FONDS];
int fond_a_sauver[MAX_FONDS];
ELEMENT *ele_fond[MAX_FONDS];
PARAM params[MAX_FONDS];
int fondActif;
double parallaxeX=1, parallaxeY=1;
int gblTypeMap;


ELEMENT *gblEls;
int motifChoisi=2, scrollMotifs=0, selMap=0, selCopie=0;
int posX, posY, posDepartX, posDepartY, posDepartAbsolueX, posDepartAbsolueY, rposX, rposY;
int transparenceTileset=75;
int derTickCount, diffTickCount=0;
MAP (*blocCopie)[1024]=NULL;
unsigned char blocCopieOk[MAXBLOCS+1];
SPRITE_LISTE *listeCopie;

int CopieX=0, CopieY=0, DebutX=0, DebutY=0, FinX=0, FinY=0;
int profondeurSel=0, selectionBase=0;

int tamX, tamY;
#define Stocke(param)		(p->param=param)
#define Charge(param)		(param=p->param)

#define AccesMap(p,x,y)		(p->gblMap[p->tailleX*(y)+(x)])

void DessineEcran(int posX, int posY);
void SauveAnnulerFond(int fond);
void SauveAnnulerListe(int fond);
#define GblMap(x,y)	(gblMap[tamX*(y)+(x)])

HWND hScroll1, hScroll2, hScroll3, hBtOk, hBtAnnuler, hBtRefaire, hStatut, hBtOpts, hLigneRedim;
LRESULT CALLBACK Fond(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void SauveAnnuler();

typedef struct		{
	MAP *undoBuffer;
	int modifie;
	int nOperations, nTotalOperations;
	unsigned long MAXMEM;
	int dernierEnreg;
} UNDO_BUFFER;

UNDO_BUFFER undos[MAX_FONDS];

int RelaToAbsX(int absolue)		{
	return absolue+((int)(scrollX*parallaxeX)&~(grilleX-1));
}

int RelaToAbsY(int absolue)		{
	return absolue+((int)(scrollY*parallaxeY)&~(grilleY-1));
}

int AbsToRelaX(int relative)		{
	return relative-((int)(scrollX*parallaxeX)&~(grilleX-1));
}

int AbsToRelaY(int relative)		{
	return relative-((int)(scrollY*parallaxeY)&~(grilleY-1));
}

/*int RelaToAbsX(int absolue)		{
	return absolue+((int)((scrollX&~(tileX-1))*parallaxeX));
}

int RelaToAbsY(int absolue)		{
	return absolue+((int)((scrollY&~(tileY-1))*parallaxeY));
}

int AbsToRelaX(int relative)		{
	return relative-((int)((scrollX&~(tileX-1))*parallaxeX));
}

int AbsToRelaY(int relative)		{
	return relative-((int)((scrollY&~(tileY-1))*parallaxeY));
}*/

#include "Specimen.h"
#include "onglets.h"

int CopieBlocsListe(int fond, int buffer, int dX, int dY, int fX, int fY);

int CopieBlocsFond(int fond, int buffer, int dX, int dY, int fX, int fY)		{
	PARAM *p;
	MAP (*bloc)[1024]=NULL;
	int i, j;

	//Paramètres du fond sélectionné
	p=&params[fond];
	EcritParamsStandard(fond);
	if (p->gblTypeMap==TYPE_LISTE)		{
		return CopieBlocsListe(fond,buffer,dX,dY,fX,fY);
	}

	bloc=blocCopie+1024*buffer;

	if (dX%tileX<0)		dX-=tileX;
	if (dY%tileY<0)		dY-=tileY;
	//Sûrement pas nécessaire
	if (fX%tileX<0)		fX-=tileX;
	if (fY%tileY<0)		fY-=tileY;

	//Divise par la taille des tiles
	dX/=p->tileX, fX/=p->tileX;
	dY/=p->tileY, fY/=p->tileY;

	//Ajoute le scrolling à toutes les variables
	dX+=(int)(scrollX*p->parallaxeX/p->tileX), dY+=(int)(scrollY*p->parallaxeY/p->tileY),
	fX+=(int)(scrollX*p->parallaxeX/p->tileX), fY+=(int)(scrollY*p->parallaxeY/p->tileY);

/*	//Divise par la taille des tiles
	dX/=p->tileX, fX/=p->tileX;
	dY/=p->tileY, fY/=p->tileY;*/

	//Le rectangle a été dirigé vers le haut ou la gauche -> inverse
	if (fX<dX)		{
		i=fX;
		fX=dX;
		dX=i;
	}
	if (fY<dY)		{
		i=fY;
		fY=dY;
		dY=i;
	}

	//Vérifications pour que le rectangle soit dans la map
	if (dX<0)
		dX=0;
	if (dY<0)
		dY=0;
	if (fX>=p->tailleX)
		fX=p->tailleX-1;
	if (fY>=p->tailleY)
		fY=p->tailleY-1;
	//Achèvement final (on ne peut plus rien faire)
	if (dX>=p->tailleX || dY>=p->tailleY || fX<0 || fY<0)
		return 0;

	CopieSpec=0;

	//Sélection trop grande -> annulée
	if (fX-dX>=1024 || fY-dY>=1024)		{
		MessageBox(gblHEdit,"Sélection trop grosse pour être copiée","Oups...",MB_ICONERROR);
		return 0;
	}

	//Taille de la sélection active
	CopieX=fX-dX+1, CopieY=fY-dY+1;

	//Copie les blocs
	for (j=dY;j<=fY;j++)
		for (i=dX;i<=fX;i++)
			bloc[j-dY][i-dX]=AccesMap(p,i,j);

	if (fond==fondActif)
		SetBits(bloc[0][0]);

	return 1;
}

void CopieBlocs(int xx0, int yy0, int xx1, int yy1, int unPlan)		{
	int i,j;
	int x0, y0, x1, y1;
	//Sauvegarde des coordonnées
	DebutX=xx0, DebutY=yy0;
	FinX=xx1, FinY=yy1;

	CopieX=0; CopieY=0; typeCoordCopie=0;
	CopieXprecise=CopieYprecise=0;
	if (unPlan)			{
		x0=xx0, y0=yy0, x1=xx1, y1=yy1;
		profondeurSel=CopieBlocsFond(fondActif,0,x0,y0,x1,y1);
		if (CopieXprecise==0 || CopieYprecise==0)
			CopieXprecise=CopieX*tileX, CopieYprecise=CopieY*tileY;
	}
	else	{
		profondeurSel=0;
		for (i=0;i<MAXBLOCS && liens[fondActif][i]!=LIEN_INVALIDE;i++)			{
			x0=xx0, y0=yy0, x1=xx1, y1=yy1;
			if (params[fondActif].gblTypeMap==TYPE_MAP && params[liens[fondActif][i]].gblTypeMap==TYPE_LISTE)			{
				if (y0>y1)		{
					j=y1;
					y1=y0;
					y0=j;
				}
				if (x0>x1)		{
					j=x1;
					x1=x0;
					x0=j;
				}
//				x0=(x0/tileX)*tileX, x1=(x1/tileX+1)*tileX, y0=(y0/tileY)*tileY, y1=(y1/tileY+1)*tileY;
			}
			profondeurSel++;
			blocCopieOk[i] = CopieBlocsFond(liens[fondActif][i],i,x0,y0,x1,y1);
		}
		if (CopieXprecise==0 || CopieYprecise==0)
			CopieXprecise=CopieX*tileX, CopieYprecise=CopieY*tileY;
	}
	if (CopieXprecise==0 || CopieYprecise==0)
		CopieXprecise=CopieYprecise=CopieX=CopieY=0;
	selectionBase=fondActif;
}

void AjouteObjetListe(int fond, int x, int y, int type);
void ColleBlocsListe(int fond, int buffer, int dX, int dY, int fX, int fY);

void ColleBlocsFond(int fond, int buffer, int dX, int dY, int fX, int fY)		{
	PARAM *p;
	MAP (*bloc)[1024]=NULL;
	int i, j, tmp;

	//Paramètres du fond sélectionné
	p=&params[fond];
	EcritParamsStandard(fond);
	if (p->gblTypeMap==TYPE_LISTE)		{
		ColleBlocsListe(fond,buffer,dX,dY,fX,fY);
		return;
	}

	//Pas de morceau de map sélectionné
	if (!selMap)
		return;

	bloc=blocCopie+1024*buffer;

/*	//Pour palier à un problème
	if (dX<0)	dX-=p->tileX-1;
	if (dY<0)	dY-=p->tileY-1;
	if (fX<0)	fX-=p->tileX-1;
	if (fY<0)	fY-=p->tileY-1;*/

	if (dX%tileX<0)		dX-=tileX;
	if (dY%tileY<0)		dY-=tileY;
	//Sûrement pas nécessaire
	if (fX%tileX<0)		fX-=tileX;
	if (fY%tileY<0)		fY-=tileY;

	//Divise par la taille des tiles
	dX/=p->tileX, fX/=p->tileX;
	dY/=p->tileY, fY/=p->tileY;

	//Ajoute le scrolling à toutes les variables
	dX+=(int)(scrollX*p->parallaxeX/p->tileX), dY+=(int)(scrollY*p->parallaxeY/p->tileY),
	fX+=(int)(scrollX*p->parallaxeX/p->tileX), fY+=(int)(scrollY*p->parallaxeY/p->tileY);

	//Le rectangle a été dirigé vers le haut ou la gauche -> inverse
	if (fX<dX)		{
		i=fX;
		fX=dX;
		dX=i;
	}
	if (fY<dY)		{
		i=fY;
		fY=dY;
		dY=i;
	}

	//Vérifications pour que le rectangle soit dans la map
	if (dX<0)
		dX=0;
	if (dY<0)
		dY=0;
	if (fX>=p->tailleX)
		fX=p->tailleX-1;
	if (fY>=p->tailleY)
		fY=p->tailleY-1;
	//Si les arguments fournis sont vraiment n'importe quoi...
	if (dX>=p->tailleX || dY>=p->tailleY || fX<0 || fY<0)
		return;

	//Copie les blocs
	for (j=dY;j<=fY;j++)
		for (i=dX;i<=fX;i++)		{
			if (CopieX>0 && CopieY>0)	{
				tmp=bloc[(j-dY)%CopieY][(i-dX)%CopieX];
				if (tmp!=masqueInvisible && (tmp!=0 || !masqueZero))
					AccesMap(p,i,j)=tmp;
			}
			else
				AccesMap(p,i,j)=motifChoisi;
		}
//	SauveAnnulerFond(fond);
}

void AjouteObjetListe(int fond, int x, int y, int type)		{
	SPRITE_DEF *sd=_SD(params[fond].gblSpriteListe,params[fond].gblSpriteListe.nbSprites);
	SD_PARAMS *sdp;
	memset(sd,0,params[fond].gblSpriteListe.sizeofSD);
	if (params[fond].gblSpriteListe.nbSprites>=NB_MAX_ELE_LISTE)			{
		MessageBox(gblHEdit, "Trop d'éléments, veuillez allonger la liste dans les options", "Erreur", MB_ICONEXCLAMATION);
		return;
	}
	sd->x=x;
	sd->y=y;
	sd->type=type;

	int i;
	sdp=params[fond].gblSdParam;
	for (i=0;i<sdp->sdNumParams;i++)		{
		if (sdp->sdTypeParam[i]==SDT_ENTIER)			{
			int *ptr;
			ptr= (int*)((char*)sd->params+GetParamOffset(i));
			*ptr = GetEntier(sdp->sdTexteDefaut[i]);
		}
		else if (sdp->sdTypeParam[i]==SDT_BRUT)			{
			char *cptr;
			cptr=(char*)sd->params+GetParamOffset(i);
			strcpy(cptr,sdp->sdTexteDefaut[i]);
		}
	}
	params[fond].gblSpriteListe.nbSprites++;
}

void ColleBlocs(int xx0, int yy0, int xx1, int yy1, int unPlan)		{
	int x0, y0, x1, y1;
	int i,j;
	if (profondeurSel==0)
		return;
	else if (profondeurSel==1)		{
		x0=xx0, y0=yy0, x1=xx1, y1=yy1;
		ColleBlocsFond(fondActif,0,x0,y0,x1,y1);
	}
	else	{
//		Debug("%i %i %i %i",xx0,yy0,xx1,yy1);
		for (i=0;i<profondeurSel && i<MAXBLOCS && liens[fondActif][i]!=LIEN_INVALIDE;i++)			{
			//[plus d'actualité] IMPORTANT: Lors du mix liste/map, la sélection ne fonctionnera pas correctement à partir de la map (puisqu'il suffit
			//de sélectionner une zone de 1x1 pour coller une tile de 16x16, les objets ne sont pas inclus dans la zone de 1x1)
			x0=xx0, y0=yy0, x1=xx1, y1=yy1;
			//Bidouille pour arrondir les objets à des positions valable lors du mix liste/map!
			if (params[fondActif].gblTypeMap==TYPE_MAP && params[liens[fondActif][i]].gblTypeMap==TYPE_LISTE)		{
//				x0=(x0/tileX)*tileX, x1=(x1/tileX)*tileX, y0=(y0/tileY)*tileY, y1=(y1/tileY)*tileY;
				if (y0>y1)		{
					j=y1;
					y1=y0;
					y0=j;
				}
				if (x0>x1)		{
					j=x1;
					x1=x0;
					x0=j;
				}
				//Pour palier à un problème
				if (x0<0)	x0-=tileX-1;
				if (y0<0)	y0-=tileY-1;
				if (x1<0)	x1-=tileX-1;
				if (y1<0)	y1-=tileY-1;
				x0=(x0/tileX)*tileX, x1=(x1/tileX+1)*tileX, y0=(y0/tileY)*tileY, y1=(y1/tileY+1)*tileY;
			}
			//Un plan -> colle juste le plan correspondant
			if ((!unPlan || liens[fondActif][i]==fondActif) && blocCopieOk[i])
				ColleBlocsFond(liens[fondActif][i],i,x0,y0,x1,y1);
		}
	}
	SauveAnnuler();
}

void EcritParamsStandard(int fond)		{
	PARAM *p;
	p=&params[fond];
	grilleX=p->grilleX;
	grilleY=p->grilleY;
	parallaxeX=p->parallaxeX/params[fondActif].parallaxeX;
	parallaxeY=p->parallaxeY/params[fondActif].parallaxeY;
	if (/*p->gblTypeMap == TYPE_LISTE &&*/ fond!=fondActif)
		grilleX=p->tileX, grilleY=p->tileY;
	if (p->emul_gba)
		gbatilmask = 1023;
	else
		gbatilmask = 0xffffffff;
}

void LitParam(PARAM *p)		{
	p->taille=taille;
	p->tailleX=tailleX;
	p->tailleY=tailleY;
	p->tileX=tileX;
	p->tileY=tileY;
	p->tileBaseX=tileBaseX;
	p->tileBaseY=tileBaseY;
	p->blocBase=blocBase;
	p->ModeTexte=ModeTexte;
	p->gfxmask=gfxmask;
	p->gblMap=gblMap;
	p->gblMotifs=gblMotifs;
	p->gblPal=gblPal;
	p->b16coul=b16coul;
	p->parallaxeX=parallaxeX;
	p->parallaxeY=parallaxeY;
	strcpy(p->gblcMap,gblcMap);
	strcpy(p->gblcTil,gblcTil);
	strcpy(p->gblcPal,gblcPal);
	strcpy(p->gblcNomC,gblcNomC);

	p->gblSpriteListe=gblSpriteListe;
	p->gblTypeMap=gblTypeMap;

	p->grilleX=grilleX;
	p->grilleY=grilleY;
	p->bTil32Bits=bTil32Bits;
	p->gblSdParam=gblSdParam;
	strcpy(p->gblTypeSd,gblTypeSd);
	//LENT!
	memcpy(p->gblUserData, gblUserData, sizeof(gblUserData));
	p->emul_gba=emul_gba;
}

void EcritParam(PARAM *p)		{
	//Restauration des paramètres
	taille=p->taille;
	tailleX=p->tailleX;
	tailleY=p->tailleY;
	tileX=p->tileX;
	tileY=p->tileY;
	tileBaseX=p->tileBaseX;
	tileBaseY=p->tileBaseY;
	blocBase=p->blocBase;
	ModeTexte=p->ModeTexte;
	gfxmask=p->gfxmask;
	gblMap=p->gblMap;
	gblMotifs=p->gblMotifs;
	gblPal=p->gblPal;
	b16coul=p->b16coul;
	parallaxeX=p->parallaxeX;
	parallaxeY=p->parallaxeY;
	strcpy(gblcMap,p->gblcMap);
	strcpy(gblcTil,p->gblcTil);
	strcpy(gblcPal,p->gblcPal);
	strcpy(gblcNomC,p->gblcNomC);

	gblSpriteListe=p->gblSpriteListe;
	gblTypeMap=p->gblTypeMap;

	grilleX=p->grilleX;
	grilleY=p->grilleY;
	bTil32Bits=p->bTil32Bits;
	gblSdParam=p->gblSdParam;
	strcpy(gblTypeSd,p->gblTypeSd);
	//LENT!
	memcpy(gblUserData, p->gblUserData, sizeof(gblUserData));
	emul_gba=p->emul_gba;

	//Calcul des variables manquantes
	tamX=tailleX;
	tamY=tailleY;

	if (p->emul_gba)
		gbatilmask = 1023;
	else
		gbatilmask = 0xffffffff;
/*	sprintf(str,"%i %i (%i %i/ %i %i)",tamX,tamY, tailleX,tailleY, tileX,tileY);
	if (fondActif)
		MessageBox(NULL,str,"",0);*/
}


void MAJBoutonsAnnuler()		{
	UNDO_BUFFER *ub;
	ub=&undos[fondActif];

	if (!ub->undoBuffer)
		return;

	//Même pas assez de mémoire pour 1 map
	if (ub->nOperations<=0)		{
		EnableWindow(hBtAnnuler,FALSE);
//		EnableWindow(hBtRefaire,FALSE);
//		return;
	}
	if (ub->nOperations>0)
		EnableWindow(hBtAnnuler,TRUE);
	else
		EnableWindow(hBtAnnuler,FALSE);
	if (ub->nTotalOperations==ub->nOperations)
		EnableWindow(hBtRefaire,FALSE);
	else
		EnableWindow(hBtRefaire,TRUE);
}

void MajTitre()		{
	UNDO_BUFFER *ub;
	ub=&undos[fondActif];
	char str[1000];

	if (!ub->undoBuffer)
		return;

	if (ub->nOperations!=ub->dernierEnreg || ub->modifie)
		sprintf(str,"%s* - Editeur de maps",SansLeSlash(ele_fond[fondActif]->nom_court));
	else
		sprintf(str,"%s - Editeur de maps",SansLeSlash(ele_fond[fondActif]->nom_court));
	SetWindowText(gblHEdit,str);
}

/*void SauveAnnuler()		{
	UNDO_BUFFER *ub;
	ub=&undos[fondActif];
	unsigned long i;

	ub->nOperations++;
	MajTitre();
	ub->nOperations--;

	i=ub->MAXMEM;
	ub->MAXMEM=sizeof(short)*((ub->nOperations+2)*((tailleX/tileX)*(tailleY/tileY)));
	utilMemoire+=(ub->MAXMEM-i);

	ub->undoBuffer=(unsigned short*)realloc(ub->undoBuffer,ub->MAXMEM);

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	ub->nOperations++;
	memcpy(ub->undoBuffer+(ub->nOperations*((tailleX/tileX)*(tailleY/tileY))),gblMap,2*(tailleX/tileX)*(tailleY/tileY));
	if (ub->nOperations>0)
		EnableWindow(hBtAnnuler,TRUE);

	if (utilMemoire<1024000)				//Jusqu'à 1000 ko (pas tout à fait 1 Mo) -> x ko
		sprintf(str,"Mém: %i ko",utilMemoire/1024);
	else if (utilMemoire<10485760)			//Jusqu'à 10 Mo -> x.xx Mo
		sprintf(str,"Mém: %#.2f Mo",utilMemoire/1048576.0);
	else if (utilMemoire<104857600)			//Jusqu'à 100 Mo -> xx.x Mo
		sprintf(str,"Mém: %#.1f Mo",utilMemoire/1048576.0);
	else if (utilMemoire<1048576000)		//Jusqu'à 1 Go -> xxx Mo
		sprintf(str,"Mém: %i Mo",utilMemoire/1048576);
	else									//A partir d'un 1 Go -> x.xx Go. Le maximum est de 2 Go, après, il y a overflow. Pour éviter, déclarer MAXMEM et i en tant que __int64.
		sprintf(str,"Mém: %#.2f Go",utilMemoire/1073741824.0);

	SetWindowText(hStatut,str);
	EnableWindow(hBtRefaire,FALSE);
	ub->nTotalOperations=ub->nOperations;
}*/

//Sauve le tampon annuler pour un des fonds particuliers
void SauveAnnulerFond(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	ub=&undos[fond];
	p=&params[fond];
	unsigned long i;

	if (p->gblTypeMap==TYPE_LISTE)			{
		SauveAnnulerListe(fond);
		return;
	}

	if ((ub->nOperations>=OPMAX || utilMemoire>=MAXUNDORAM) && ub->nOperations>=2)			{
		memmove(ub->undoBuffer, ub->undoBuffer+(1*((p->tailleX)*(p->tailleY))), sizeof(MAP)*(ub->nOperations)*((p->tailleX)*(p->tailleY)));
		ub->modifie=TRUE;					//De toutes façons modifié car le tampon annuler ne peut contenir tout...
		ub->nOperations--;
	}
	i=ub->MAXMEM;
	ub->MAXMEM=sizeof(MAP)*((ub->nOperations+2)*((p->tailleX)*(p->tailleY)));
	utilMemoire+=(ub->MAXMEM-i);

	ub->undoBuffer=(MAP*)realloc(ub->undoBuffer,ub->MAXMEM);

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	ub->nOperations++;
	memcpy(ub->undoBuffer+(ub->nOperations*((p->tailleX)*(p->tailleY))),p->gblMap, sizeof(MAP)*(p->tailleX)*(p->tailleY));
	if (fond==fondActif && ub->nOperations>0)
		EnableWindow(hBtAnnuler,TRUE);

	if (utilMemoire<10240)					//Jusqu'à 10 ko -> x.xx ko
		sprintf(str,"Mém: %#.2f ko",utilMemoire/1024.0);
	else if (utilMemoire<102400)			//Jusqu'à 100 ko -> x.x ko
		sprintf(str,"Mém: %#.1f ko",utilMemoire/1024.0);
	else if (utilMemoire<1024000)			//Jusqu'à 1000 ko (pas tout à fait 1 Mo) -> x ko
		sprintf(str,"Mém: %i ko",utilMemoire/1024);
	else if (utilMemoire<10485760)			//Jusqu'à 10 Mo -> x.xx Mo
		sprintf(str,"Mém: %#.2f Mo",utilMemoire/1048576.0);
	else if (utilMemoire<104857600)			//Jusqu'à 100 Mo -> xx.x Mo
		sprintf(str,"Mém: %#.1f Mo",utilMemoire/1048576.0);
	else if (utilMemoire<1048576000)		//Jusqu'à 1 Go -> xxx Mo
		sprintf(str,"Mém: %i Mo",utilMemoire/1048576);
	else									//A partir d'un 1 Go -> x.xx Go. Le maximum est de 2 Go, après, il y a overflow. Pour éviter, déclarer MAXMEM et i en tant que __int64.
		sprintf(str,"Mém: %#.2f Go",utilMemoire/1073741824.0);

	SetWindowText(hStatut,str);
	if (fond==fondActif)		{
		EnableWindow(hBtRefaire,FALSE);
		MajTitre();
	}
	ub->nTotalOperations=ub->nOperations;
}

void SauveAnnuler()		{
	int i;
	for (i=0;liens[fondActif][i]!=LIEN_INVALIDE;i++)			{
		if (params[liens[fondActif][i]].gblTypeMap==TYPE_LISTE)
			SauveAnnulerListe(liens[fondActif][i]);
		else
			SauveAnnulerFond(liens[fondActif][i]);
	}
}
/*
void Annuler()		{
	UNDO_BUFFER *ub;
	ub=&undos[fondActif];

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	if (ub->nOperations<=0)		{
//		MessageBox(NULL,"Tu ne peux annuler puisque tu n'as rien fait!","Mince alors!",MB_ICONERROR);
		return;
	}
	ub->nOperations--;
	memcpy(gblMap,ub->undoBuffer+(ub->nOperations*((tailleX/tileX)*(tailleY/tileY))),2*(tailleX/tileX)*(tailleY/tileY));
	if (ub->nOperations<=0)
		EnableWindow(hBtAnnuler,FALSE);
	else
		EnableWindow(hBtAnnuler,TRUE);
	EnableWindow(hBtRefaire,TRUE);
	MajTitre();
}*/

void AnnulerListe(int fond);

void AnnulerFond(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	ub=&undos[fond];
	p=&params[fond];
	if (p->gblTypeMap==TYPE_LISTE)			{
		AnnulerListe(fond);
		return;
	}

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	if (ub->nOperations<=0)		{
//		MessageBox(NULL,"Tu ne peux annuler puisque tu n'as rien fait!","Mince alors!",MB_ICONERROR);
		return;
	}
	ub->nOperations--;
	memcpy(p->gblMap,ub->undoBuffer+(ub->nOperations*((p->tailleX)*(p->tailleY))), sizeof(MAP)*(p->tailleX)*(p->tailleY));

	//S'il s'agit du fond actif, on met les informations à jour
	if (fond==fondActif)		{
		if (ub->nOperations<=0)
			EnableWindow(hBtAnnuler,FALSE);
		else
			EnableWindow(hBtAnnuler,TRUE);
		EnableWindow(hBtRefaire,TRUE);
		MajTitre();
	}
}

void Annuler()		{
	int i;
	for (i=0;liens[fondActif][i]!=LIEN_INVALIDE;i++)
		AnnulerFond(liens[fondActif][i]);
}

/*void Refaire()		{
	UNDO_BUFFER *ub;
	ub=&undos[fondActif];

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	if (ub->nOperations>=ub->nTotalOperations)
		return;
	ub->nOperations++;
	memcpy(gblMap,ub->undoBuffer+(ub->nOperations*((tailleX/tileX)*(tailleY/tileY))),2*(tailleX/tileX)*(tailleY/tileY));
//	sprintf(str,"%i %i",nOperations,nTotalOperations);
//	MessageBox(NULL,str,"",0);
	if (ub->nOperations>=ub->nTotalOperations)
		EnableWindow(hBtRefaire,FALSE);
	else
		EnableWindow(hBtRefaire,TRUE);
	if (ub->nOperations<=0)
		EnableWindow(hBtAnnuler,FALSE);
	else
		EnableWindow(hBtAnnuler,TRUE);
	MajTitre();
}*/

void RefaireListe(int fond);

void RefaireFond(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	ub=&undos[fond];
	p=&params[fond];

	if (p->gblTypeMap==TYPE_LISTE)			{
		RefaireListe(fond);
		return;
	}

	//Pas pu allouer...
	if (!ub->undoBuffer)
		return;

	if (ub->nOperations>=ub->nTotalOperations)
		return;
	ub->nOperations++;
	memcpy(p->gblMap,ub->undoBuffer+(ub->nOperations*((p->tailleX)*(p->tailleY))), sizeof(MAP)*(p->tailleX)*(p->tailleY));
//	sprintf(str,"%i %i",nOperations,nTotalOperations);
//	MessageBox(NULL,str,"",0);

	if (fond==fondActif)		{
		if (ub->nOperations>=ub->nTotalOperations)
			EnableWindow(hBtRefaire,FALSE);
		else
			EnableWindow(hBtRefaire,TRUE);
		if (ub->nOperations<=0)
			EnableWindow(hBtAnnuler,FALSE);
		else
			EnableWindow(hBtAnnuler,TRUE);
		MajTitre();
	}
}

void Refaire()		{
	int i;
	for (i=0;liens[fondActif][i]!=LIEN_INVALIDE;i++)
		RefaireFond(liens[fondActif][i]);
}


void VideUndoBufferFond(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	ub=&undos[fond];
	p=&params[fond];

/*#ifdef UNDO_BUFFER_ACTIF
	#ifdef CALC_MEMOIRE_UNDO
		if (ub->undoBuffer)
			free(ub->undoBuffer);
		ub->MAXMEM=tamX*tamY*sizeof(short)*OPMAX;
		ub->undoBuffer=(unsigned short *)malloc(ub->MAXMEM);
	#endif
#endif
		ub->nOperations=-1;
		SauveAnnuler();
		ub->modifie=TRUE;*/

		//Réinitialisation de la mémoire pour le buffer annuler.
		utilMemoire-=ub->MAXMEM;
		ub->MAXMEM=0;
		free(ub->undoBuffer);
		ub->undoBuffer=NULL;
		ub->nOperations=-1;
		SauveAnnulerFond(fond);
		ub->modifie=1;
		MajTitre();
		MAJBoutonsAnnuler();
}

void VideUndoBuffer()		{
	int i;
	for (i=0;liens[fondActif][i]!=LIEN_INVALIDE;i++)
		VideUndoBufferFond(liens[fondActif][i]);
}


#include "listes.h"

void DessineTilesetScrl(unsigned char *palette,unsigned long *motifs, int scrlY)			{
	int x,y,i, pY, xx,yy, j, choixSouris,w;
	int ticks=GetTickCount()%1024,v;
//	EffaceEcran();
	ColoreCadre(Bits3,0,0,gdrXt,gdrYz,cFond);
//	palette[0]=(cFond&0x00ff0000)>>16;
//	palette[1]=(cFond&0x0000ff00)>>8;
//	palette[2]=cFond&0x000000ff;

	if (!palette || !motifs)
		return;

	i=diffTickCount;
	ticks/=2;
/*	if (ticks>=256)		{
		if (ticks>=384)
			v=RGB(255-2*(ticks-384),0,255);
		else
			v=RGB(255,0,2*(ticks-256));
	}
	else		{
		if (ticks>=128)
			v=RGB(255,0,255-2*(ticks-128));
		else
			v=RGB(2*(ticks-256),0,255);
	}*/
/*	if (ticks>=256)
		v=RGB(255-ticks%256,0,ticks%256);
	else
		v=RGB(ticks%256,0,255-ticks%256);*/

	if (ticks<256)
		v=RGB(255,ticks%256,0);
	else
		v=RGB(255,255-ticks%256,0);

	if (ticks>=256)
		w=RGB(0,ticks%256,255);
	else
		w=RGB(0,255-ticks%256,255);

	while(i>0)		{
		if (posX>=BASEDIT_X+gdrX+44 && posX<BASEDIT_X+gdrX+44+gdrXtc && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
			if (transparenceTileset<255)
				transparenceTileset+=5;
		}
		else		{
			if (CopieX==0 && CopieY==0)		{
				if (transparenceTileset>75)
					transparenceTileset-=5;
				if (transparenceTileset<75)
					transparenceTileset+=5;
			}
			else		{
				if (transparenceTileset>25)
					transparenceTileset-=5;
			}
		}
		i-=10;
	}

	pY=scrlY/tileY;
	i=(gdrXt/tileX)*pY+blocBase;
	choixSouris=(tposX)/tileX+(gdrXt/tileX)*((tposY)/tileY+scrollMotifs/tileY)+blocBase;

	for (y=0;y<gdrYz;y+=tileY)		{
		for (x=0;x<gdrXt;x+=tileX)		{
			if (i>=taille)
				goto fin;
			if (posX>=BASEDIT_X+gdrX+44 && posX<BASEDIT_X+gdrX+44+gdrXtc && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
				if (CopieX==0 && CopieY==0)		{
					if (i==motifChoisi+blocBase)
						j=255;
					else
						j=transparenceTileset;
				}
				else
					j=transparenceTileset;

				for (yy=0;yy<tileY;yy+=8)
					for (xx=0;xx<tileX;xx+=8)		{
						TransSpritePalSansMasque(Bits3,x+xx,y+yy,8,8,motifs+(i*tileX*tileY)+64*(tileX/8)*(yy/8)+64*(xx/8),palette,j);
					}
				if (transparenceTileset>75)		{
					if (i==motifChoisi+blocBase)
						TransCadre(Bits3,x,y,tileX,tileY,w,(transparenceTileset-75)/2);
					if (i==choixSouris)
						TransCadre(Bits3,x,y,tileX,tileY,v,(transparenceTileset-75)/2);
				}
			}
			else	{
				if (CopieX==0 && CopieY==0)		{
					if (i==motifChoisi+blocBase)
						j=255;
					else
						j=transparenceTileset;
				}
				else
					j=transparenceTileset;

				for (yy=0;yy<tileY;yy+=8)
					for (xx=0;xx<tileX;xx+=8)		{
						TransSpritePalSansMasque(Bits3,x+xx,y+yy,8,8,motifs+(i*tileX*tileY)+64*(tileX/8)*(yy/8)+64*(xx/8),palette,j);
					}
				if (transparenceTileset>75 && i==motifChoisi+blocBase)
					TransCadre(Bits3,x,y,tileX,tileY,w,(transparenceTileset-75)/2);
			}

//			SpritePalSansMasque(x,y,8,8,motifs+(i*tileX*tileY),palette);
//			ColoreCadre(x,y,16,16,RGB(255,0,0));
			i++;
		}
	}
fin:
	;
}

void DessineMapEdit(unsigned char *palette, unsigned long *motifs, MAP *map, int scrlX, int scrlY, int transparence, int fond)			{
	int x,y,i, xx, yy, fX, fY;
	int dX, dY;
	PARAM p;

	p.gblMap=map;
	p.gblMotifs=motifs;
	p.gblPal=palette;
	p.b16coul=b16coul;

	i=0;
	palette[0]=(cFond&0x00ff0000)>>16;
	palette[1]=(cFond&0x0000ff00)>>8;
	palette[2]=cFond&0x000000ff;

	dX=(int)(scrlX*parallaxeX/tileX);
	dY=(int)(scrlY*parallaxeY/tileY);
//	mX=scrlX%tileX;
//	mY=scrlY%tileY;
	if (tailleX-dX>gdrXz/tileX)
		fX=gdrXz/tileX+1;
	else
		fX=tailleX-dX;
	if (tailleY-dY>gdrYz/tileY)
		fY=gdrYz/tileY+1;
	else		{
		fY=tailleY-dY;
		//Il faudra dessiner une ligne de limitation
	}

	for (y=0;y<fY;y++)		{
		for (x=0;x<fX;x++)		{
			i=map[tailleX*(y+dY)+x+dX]+blocBase;
			if (!Editer)		{
				if (MODE_TEXTE)		{
					DessNombre(x*tileX,y*tileY,i,RGB(0,0,0));
				}
				else	{
					i=VerifConditions(i,fond,gfxmask);

					//Motif non-valide (ne devrait pas arriver)
//					if (!emul_gba)		{
						if ((i&gbatilmask)>=taille || i<0)
							goto pasafficher;
//							continue;
//					}

					for (yy=0;yy<tileBaseY;yy+=8)
						for (xx=0;xx<tileBaseX;xx+=8)		{
							if (emul_gba)
								DessineTile(Bits3,x*tileX+xx,y*tileY+yy,&p,(i*tileBaseX*tileBaseY)/64+(tileBaseX/8)*(yy/8)+(xx/8),transparence);
							else if (!transparence)
								SpritePal(Bits3,x*tileX+xx,y*tileY+yy,8,8,motifs+(i*tileBaseX*tileBaseY)+64*(tileBaseX/8)*(yy/8)+64*(xx/8),palette);
							else
								TransSpritePal(Bits3,x*tileX+xx,y*tileY+yy,8,8,motifs+(i*tileBaseX*tileBaseY)+64*(tileBaseX/8)*(yy/8)+64*(xx/8),palette,transparence);
						}
				}
pasafficher:
				;
/*				if (fond==fondActif && grille)
					TransRectFond(Bits3,x*tileX,y*tileY+1,tileX,tileY,couleurGrille,transGrille);*/
			}
//			ColoreCadre(x,y,16,16,RGB(255,0,0));
		}
	}

	//Dessine la grille
	if (fond==fondActif && grille && grilleX>=4 && grilleY>=4)			{
		dX=(int)(scrlX*parallaxeX);
		dY=(int)(scrlY*parallaxeY);
		fX=gdrXz;
		fY=gdrYz;
		ArronditTileX(dX);
		ArronditTileY(dY);
		if (fX+dX>=tailleX*tileX)
			fX=tailleX*tileX-dX-1;
		if (fY+dY>=tailleY*tileY)
			fY=tailleY*tileY-dY-1;
		for (y=-(dY%grilleY);y<fY;y+=grilleY)		{
			for (x=-(dX%grilleX);x<fX;x+=grilleX)		{
				TransRectFond(Bits3,x,y+1,grilleX,grilleY,couleurGrille,transGrille);
			}
		}
	}
	tailleX*=tileX;
	tailleY*=tileY;
}

/*int EcritMap(int nEdit)		{
	FILE *ecri;
	ELEMENT *els=gblEls;
	int nEcrits, i,j;
	unsigned short *map=gblMap;
	char str[1000];

	ecri=fopen(gblcMap,"w");
	if (!ecri)		{
		MessageBox(gblHDlg,"Impossible d'ouvrir le fichier en écriture.\nLe nom est probablement faux.",gblcMap,MB_ICONERROR);
		return 0;
	}

//	faitNomCourt(gblcMap,nom_court);
//	sprintf(str,"//%s\n//Converti avec GBA Graphics par Brünni\n//Map (%s,%s)\n//Taille: %i*%i*%i*%i\n//Mémoire: %i octets\n\nconst unsigned char %s_tiles[%i]=	{\n",elements[nE].nom_base,elements[nE].nom_map,tileX,tileY,tailleX,tailleY,(tailleX/tileX)*(tailleY/tileY)*2,elements[nbreElements].nom_court,(tailleX/tileX)*(tailleY/tileY));
	sprintf(str,"//%s\n"
		"//Converti avec GBA Graphics par Brünni\n"
		"//Map (\"%s\",\"%s\",%i,%x)\n"
		"//Taille: %i*%i * %i*%i\n"
		"//Mémoire: %i octets\n"
		"const unsigned %s %s_map[%i][%i]=	{\n	{"
		,gblcMap,
		gblcPal,gblcTil,blocBase,gfxmask,
		tileX,tileY,tailleX/tileX,tailleY/tileY,
		(tailleX/tileX)*(tailleY/tileY)*(ModeTexte?2:1),
		ModeTexte?"short":"char",
		ele_fond[nEdit]->nom_court,(tailleY/tileY),(tailleX/tileX));
	fputs(str,ecri);

	nEcrits=0;
	for (j=0;j<tailleY/tileY;j++)		{
		for (i=0;i<tailleX/tileX;i++)		{
			if (j==tailleY/tileY-1 && i==tailleX/tileX-1)		{
				if (ModeTexte)
					sprintf(str,"0x%04x}\n};\n",map[(tailleX/tileX)*j+i]);
				else
					sprintf(str,"0x%02x}\n};\n",map[(tailleX/tileX)*j+i]);
				fputs(str,ecri);
			}
			else	{
				if (ModeTexte)		{
					if (i==tailleX/tileX-1)		{
						sprintf(str,"0x%04x},\n	{",map[(tailleX/tileX)*j+i]);
						fputs(str,ecri);
						nEcrits=0;
						continue;
					}
					else
						sprintf(str,"0x%04x, ",map[(tailleX/tileX)*j+i]);
				}
				else		{
					if (i==tailleX/tileX-1)		{
						sprintf(str,"0x%02x},\n	{",map[(tailleX/tileX)*j+i]);
						fputs(str,ecri);
						nEcrits=0;
						continue;
					}
					else
						sprintf(str,"0x%02x, ",map[(tailleX/tileX)*j+i]);
				}
				fputs(str,ecri);
				nEcrits++;
				if (nEcrits%8==0)
					fputc('\n',ecri);
			}
		}
	}

	fclose(ecri);

	sprintf(str,"onsave %s",ele_fond[nEdit]->nom_court);
	OuvreFichierConfig(fichierConfigAOuvrir,str);

	return 1;
}*/

void analyseChaineTypes(FILE *f, char *chneFormat, SPRITE_DEF *sd)			{
	char tmpStr[100];
	int i;
	SD_PARAMS *sdp=&sdParams[gblSdModele];
	int bOk;

	while(*chneFormat)		{
		if (*chneFormat=='#')		{
			i=0;
			chneFormat++;
			while(*chneFormat && *chneFormat!='#' && i<sizeof(tmpStr)-1)
				tmpStr[i++]=*chneFormat++;
			if (*chneFormat==0)
				break;
			tmpStr[i]=0;
			if (!strcmp(tmpStr,"type"))
				fprintf(f,"%i",sd->type);
			else if (!strcmp(tmpStr,"x"))
				fprintf(f,"%i",sd->x);
			else if (!strcmp(tmpStr,"y"))
				fprintf(f,"%i",sd->y);
			else		{
				bOk=FALSE;
				for (i=0;i<sdp->sdNumParams && !bOk;i++)			{
					if (!strcmp(tmpStr,sdp->sdNomsParams[i]))			{
						//ECRIT LE DEBUT DE LA CHAINE
								//#"<param>"# par exemple
/*								strcpy(variable, tmpStr);
								v=0;
								incrementDiff=-1;
								signe_ok=0;
								while(variable[v]!='>' && variable[v])			{
									if (variable[v]=='<')
										signe_ok=v;
									v++;
								}
								if (variable[signe_ok]=='<' && v>=0)			{
									if (variable[v]=='>')			{
										variable[signe_ok]=0;
										fputs(variable, f);
									}
								}*/
						//ECRIT LE PARAMETRE DE LA CHAINE
						if (sdp->sdTypeParam[i]==SDT_ENTIER)			{
							int *ptr;
							ptr= (int*)((char*)sd->params+GetParamOffset(i));
							fprintf(f,"%i",(int)*ptr);
							bOk=TRUE;
						}
						else if (sdp->sdTypeParam[i]==SDT_BRUT)			{
							char *cptr;
							cptr=(char*)sd->params+GetParamOffset(i);
							fputs(cptr, f);
							bOk=TRUE;
						}
								//ECRIT LA FIN DE LA CHAINE
/*								if (variable[v]=='>')			{
									v++;
									fputs(variable+v, f);
								}*/
					}
				}
			}
		}
		else
			fputc(*chneFormat,f);
		chneFormat++;
	}
}

int EcritListeFond(int fond)		{
	SPRITE_LISTE listeSauve;
	FILE *ecri;
	ELEMENT *els=gblEls;
	UNDO_BUFFER *ub;
	PARAM *p;
	int i,j;
	MAP *map;
	char str[1000];

	p=&params[fond];
	ub=&undos[fond];

	map=p->gblMap;

	ChoisitFormatFichierExtension(p->gblcMap);
	ecri=fopen(p->gblcMap,"wb");
	if (!ecri)		{
		MessageBox(gblHDlg,"Impossible d'ouvrir le fichier en écriture.\nLe nom est probablement faux.",p->gblcMap,MB_ICONERROR);
		return 0;
	}

//	FaitNomC(ele_fond[fond]->nom_court);
	tailleX=p->tailleX, tailleY=p->tailleY;

	ReinitSymTable();
	PrepareSymTable(0);
	InitSymbole(0,p->gblcMap);									//%file%
//	InitSymbole(1,&p->tailleX);									//%sizex%
//	InitSymbole(2,&p->tailleY);									//%sizey%
	InitSymbole(3,p->gblSpriteListe.nbSprites);					//%size%
	InitSymbole(4,p->gblSpriteListe.nbSprites*p->gblSpriteListe.sizeofSD);		//%memory%
	InitSymbole(5,p->gblcNomC);									//%name%
//	InitSymbole(5,NomC);										//%name%
	InitSymbole(6,p->gblcTil);									//%link%
	InitSymbole(7,&p->tileX);									//%tilex%
	InitSymbole(8,&p->tileY);									//%tiley%
	InitSymbole(10,p->gblTypeSd);								//%type%
	memcpy(gblUserData, p->gblUserData, sizeof(gblUserData));
	InitSymbole(15,p->gblSdParam->sdNomModele);					//%model%
/*	InitSymbole(9,ModeTexte?16:8);								//%depth%
	if (ModeTexte)
		InitSymbole(10,type16);									//%type%
	else
		InitSymbole(10,type8);									//%type%*/

	EcritChaineFiltree(lst_declaration,ecri);

	//TRI
	int nBest, bX, bY;
	int *listeX;
	listeSauve.sd=(SPRITE_DEF*)malloc(NB_MAX_ELE_LISTE*p->gblSpriteListe.sizeofSD);
	listeSauve.sizeofSD=p->gblSpriteListe.sizeofSD;
	listeX=(int*)malloc(NB_MAX_ELE_LISTE*sizeof(int));
	
	for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
		listeX[i]=_SD(p->gblSpriteListe,i)->x;
	}

	for (j=0;j<p->gblSpriteListe.nbSprites;j++)		{
		nBest=-1;
		bX=bY=0x7fffffff;
		for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
			if ((_SD(p->gblSpriteListe,i)->x<bX) || (_SD(p->gblSpriteListe,i)->x==bX && _SD(p->gblSpriteListe,i)->y<=bY))		{
//				if (_SD(p->gblSpriteListe,i)->y<=bY)		{
					bX=_SD(p->gblSpriteListe,i)->x;
					bY=_SD(p->gblSpriteListe,i)->y;
					nBest=i;
//				}
			}
		}

		memcpy(_SD(listeSauve,j),_SD(p->gblSpriteListe,nBest), p->gblSpriteListe.sizeofSD);
		_SD(p->gblSpriteListe,nBest)->x=0x7ffffff0;
	}
//	_SD(p->gblSpriteListe,nBest)->x=0x7fffffff;

	for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
		_SD(p->gblSpriteListe,i)->x=listeX[i];
	}

	for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
		if (lst_nbChaqueX>0)		{
			if (i%lst_nbChaqueX==0)
				EcritChaineFiltree(lst_chaque_x,ecri);
		}
		analyseChaineTypes(ecri,lst_chaque_valeur_ok,_SD(listeSauve,i));
		EcritChaineFiltree(lst_fin_ligne,ecri);
	}
	EcritChaineFiltree(lst_fin_declaration,ecri);

	fclose(ecri);

	sprintf(str,"onsave %s",ele_fond[fond]->nom_court);
	OuvreFichierConfig(fichierConfigAOuvrir,str);

	ub->dernierEnreg=ub->nOperations;
	ub->modifie=0;
	MajTitre();

	free(listeSauve.sd);
	free(listeX);

	Console_Print_Simple("Liste sauvée: %s",ele_fond[fond]->nom_court);
	return 1;
}

int EcritMapFond(int fond)		{
	FILE *ecri;
	ELEMENT *els=gblEls;
	UNDO_BUFFER *ub;
	PARAM *p;
	int i,j;
	MAP *map;
	char str[1000];

	p=&params[fond];
	ub=&undos[fond];

	if (p->gblTypeMap==TYPE_LISTE)		{
		return EcritListeFond(fond);
	}

	map=p->gblMap;

	ChoisitFormatFichierExtension(p->gblcMap);
	ecri=fopen(p->gblcMap,"wb");
	if (!ecri)		{
		MessageBox(gblHDlg,"Impossible d'ouvrir le fichier en écriture.\nLe nom est probablement faux.",p->gblcMap,MB_ICONERROR);
		return 0;
	}

//	FaitNomC(ele_fond[fond]->nom_court);
	tailleX=p->tailleX, tailleY=p->tailleY;

	ReinitSymTable();
	PrepareSymTable(0);
	InitSymbole(0,p->gblcMap);									//%file%
	InitSymbole(1,&p->tailleX);									//%sizex%
	InitSymbole(2,&p->tailleY);									//%sizey%
	if (ModeTexte==2)
		InitSymbole(4,p->tailleX*p->tailleY*4);					//%memory%
	else if (ModeTexte==1)
		InitSymbole(4,p->tailleX*p->tailleY*2);					//%memory%
	else
		InitSymbole(4,p->tailleX*p->tailleY);					//%memory%
	InitSymbole(5,p->gblcNomC);									//%name%
//	InitSymbole(5,NomC);										//%name%
	InitSymbole(6,p->gblcTil);									//%link%
	InitSymbole(7,&p->tileX);									//%tilex%
	InitSymbole(8,&p->tileY);									//%tiley%
	if (ModeTexte==0)
		InitSymbole(9,8);										//%depth%
	else if (ModeTexte==1)
		InitSymbole(9,16);										//%depth%
	else if (ModeTexte==2)
		InitSymbole(9,32);										//%depth%
	if (ModeTexte==2)
		InitSymbole(10,type32);									//%type%
	else if (ModeTexte==1)
		InitSymbole(10,type16);									//%type%
	else
		InitSymbole(10,type8);									//%type%
	memcpy(gblUserData, p->gblUserData, sizeof(gblUserData));

	EcritChaineFiltree(map_declaration,ecri);

//	faitNomCourt(gblcMap,nom_court);
//	sprintf(str,"//%s\n//Converti avec GBA Graphics par Brünni\n//Map (%s,%s)\n//Taille: %i*%i*%i*%i\n//Mémoire: %i octets\n\nconst unsigned char %s_tiles[%i]=	{\n",elements[nE].nom_base,elements[nE].nom_map,tileX,tileY,tailleX,tailleY,(tailleX/tileX)*(tailleY/tileY)*2,elements[nbreElements].nom_court,(tailleX/tileX)*(tailleY/tileY));
/*	sprintf(str,"//%s\n"
		"//Converti avec GBA Graphics par Brünni\n"
		"//Map (\"%s\",\"%s\",%i,%x)\n"
		"//Taille: %i*%i * %i*%i\n"
		"//Mémoire: %i octets\n"
		"const unsigned %s %s_map[%i][%i]=	{\n	{"
		,p->gblcMap,
		p->gblcPal,p->gblcTil,p->blocBase,p->gfxmask,
		p->tileBaseX,p->tileBaseY,p->tailleX,p->tailleY,
		(p->tailleX)*(p->tailleY)*(p->ModeTexte?2:1),
		p->ModeTexte?"short":"char",
		NomC,(p->tailleY),(p->tailleX));
	fputs(str,ecri);*/

	for (j=0;j<tailleY;j++)		{
		for (i=0;i<tailleX;i++)		{
			if (map_nbChaqueX>0 && i>0 && i%map_nbChaqueX==0)
				EcritChaineFiltree(map_chaque_x,ecri);

			if (ModeTexte==2)
				myprintf(ecri,map_chaque_valeur_3,map[tailleX*j+i]);
			else if (ModeTexte==1)
				myprintf(ecri,map_chaque_valeur_1,map[tailleX*j+i]);
			else
				myprintf(ecri,map_chaque_valeur_2,map[tailleX*j+i]);

//			nEcrits++;
		}
		EcritChaineFiltree(map_fin_ligne,ecri);
	}
	EcritChaineFiltree(map_fin_declaration,ecri);

/*	nEcrits=0;
	for (j=0;j<p->tailleY;j++)		{
		for (i=0;i<p->tailleX;i++)		{
			if (j==p->tailleY-1 && i==p->tailleX-1)		{
				if (p->ModeTexte)
					sprintf(str,"0x%04x}\n};\n",map[(p->tailleX)*j+i]);
				else
					sprintf(str,"0x%02x}\n};\n",map[(p->tailleX)*j+i]);
				fputs(str,ecri);
			}
			else	{
				if (p->ModeTexte)		{
					if (i==p->tailleX-1)		{
						sprintf(str,"0x%04x},\n	{",map[(p->tailleX)*j+i]);
						fputs(str,ecri);
						nEcrits=0;
						continue;
					}
					else
						sprintf(str,"0x%04x, ",map[(p->tailleX)*j+i]);
				}
				else		{
					if (i==p->tailleX-1)		{
						sprintf(str,"0x%02x},\n	{",map[(p->tailleX)*j+i]);
						fputs(str,ecri);
						nEcrits=0;
						continue;
					}
					else
						sprintf(str,"0x%02x, ",map[(p->tailleX)*j+i]);
				}
				fputs(str,ecri);
				nEcrits++;
				if (nEcrits%8==0)
					fputc('\n',ecri);
			}
		}
	}*/

	fclose(ecri);

	sprintf(str,"onsave %s",ele_fond[fond]->nom_court);
	OuvreFichierConfig(fichierConfigAOuvrir,str);

	ub->dernierEnreg=ub->nOperations;
	ub->modifie=0;
	MajTitre();

	Console_Print_Simple("Map sauvée: %s",ele_fond[fond]->nom_court);
	return 1;
}

void EcritMap()		{
	int i;
	for (i=0;liens[fondActif][i]!=LIEN_INVALIDE;i++)
		EcritMapFond(liens[fondActif][i]);
}



void BougeTruc(HWND hWndTruc, int x, int y)		{
	SetWindowPos(hWndTruc,HWND_TOP,x,y,0,0,SWP_NOSIZE|SWP_NOZORDER);
	RedrawWindow(hWndTruc,NULL,NULL,RDW_INVALIDATE|RDW_ERASE);
}


enum {OM_FOND=1, OM_FMTTILES, OM_PROPREPALETTE, OM_HEXA, OM_ZERO, OM_TRANSPARENT, OM_OPERATION, OM_DEPLACER, OM_OPTIONS, OM_FONDHEXA, OM_SPECIMEN, OM_LIER, OM_BITS};

int MenuEditeur(HWND hWnd)	{
	HMENU hmenu, hPopup, hPopup2, hPopup3;
	int choix;
	int i;
	POINT pt;

	GetCursorPos(&pt);
	hmenu=CreatePopupMenu();
//	AppendMenu(hmenu,MF_STRING|MF_DISABLED,0,"Menu");
//	AppendMenu(hmenu,MF_SEPARATOR,0,NULL);
//	AppendMenu(hmenu,MF_STRING,OM_FOND,"Ajouter un fond...\t   Ctrl+M");
//	if (nMaps>1)		{
		hPopup=CreatePopupMenu();

			hPopup3=CreatePopupMenu();
			for (i=0;i<nMaps;i++)
				//Si vous adaptez le nombre de maps éditables en même temps, n'oubliez pas de faire suivre le i+20!
				AppendMenu(hPopup3,MF_STRING|((i==fondActif)?MF_CHECKED:0),i+MAX_FONDS*2,ele_fond[i]->nom_court);
			AppendMenu(hPopup,MF_STRING|MF_POPUP,(unsigned int)hPopup3,"Actif...");

			hPopup2=CreatePopupMenu();
			for (i=0;i<nMaps;i++)
				AppendMenu(hPopup2,MF_STRING/*|(fond_actif[i]?MF_CHECKED:0)*/,i+MAX_FONDS,ele_fond[i]->nom_court);
			AppendMenu(hPopup,MF_STRING|MF_POPUP,(unsigned int)hPopup2,"Propriétés...");

		AppendMenu(hPopup,MF_STRING,OM_FOND,"Ajouter un fond...\t   Ctrl+M");
		AppendMenu(hPopup,MF_STRING,OM_LIER,"Lier...");

		AppendMenu(hPopup,MF_STRING|(proprePalette?MF_CHECKED:0),OM_PROPREPALETTE,"Une palette par fond");
		AppendMenu(hPopup,MF_STRING|(fondTransparent?MF_CHECKED:0),OM_TRANSPARENT,"Fonds transparents");

		AppendMenu(hmenu,MF_STRING|MF_POPUP,(unsigned int)hPopup,"Fonds...");
//	}

	hPopup=CreatePopupMenu();
	if (MODE_TEXTE)		{
		hPopup2=CreatePopupMenu();
		AppendMenu(hPopup2,MF_STRING,OM_HEXA,"Annuler\t   Ctrl+H");
		AppendMenu(hPopup2,MF_STRING|(combleZeros?MF_CHECKED:0),OM_ZERO,"Combler avec des 0");
		AppendMenu(hPopup2,MF_STRING|(fondHexa?MF_CHECKED:0),OM_FONDHEXA,"Map graphique en fond");
		AppendMenu(hPopup,MF_STRING|MF_CHECKED|MF_POPUP,(unsigned int)hPopup2,"Mode hexa");
	}
	else
		AppendMenu(hPopup,MF_STRING,OM_HEXA,"Mode hexa\t   Ctrl+H");
	AppendMenu(hPopup,MF_STRING|(IsWindowVisible(hDlgBits)?MF_CHECKED:MF_UNCHECKED),OM_BITS,"Grille des bits");
	AppendMenu(hPopup,MF_STRING|((bSpecimenAffiche && gblHSpec)?MF_CHECKED:0)|(gblHSpec?0:MF_GRAYED),OM_SPECIMEN,"Map spécimen");
	AppendMenu(hmenu,MF_STRING|MF_POPUP,(unsigned int)hPopup,"Outils...");

	AppendMenu(hmenu,MF_STRING,OM_OPTIONS,"Options...");

//	if (!MODE_TEXTE)
//		AppendMenu(hmenu,MF_STRING,OM_FMTTILES,"Format des blocs");

	if (CopieX==0 && CopieY==0)				//Quelque chose de copier
		AppendMenu(hmenu,MF_STRING | MF_GRAYED,OM_OPERATION,"Opération sur sélection");
	else
		AppendMenu(hmenu,MF_STRING,OM_OPERATION,"Opération sur sélection");

	AppendMenu(hmenu,MF_STRING,OM_DEPLACER,"Déplacements...");
//	AppendMenu(hmenu,MF_STRING|MF_POPUP,(unsigned int)hProcedures,"Procédures");

	choix=TrackPopupMenu(hmenu,TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,pt.x,pt.y,0,hWnd,NULL);
	DestroyMenu(hmenu);
/*	if (choix>=MAX_FONDS && choix<MAX_FONDS+nMaps)
		fond_actif[choix-MAX_FONDS]=!fond_actif[choix-MAX_FONDS];*/
	return choix;
}

int AjouteListe(int nElement);

int AjouteFond(int nElement)		{
	int i;
	PARAM param;
	UNDO_BUFFER *ub;
	ub=&undos[nMaps];

	if ((elements[nElement].type&MASQUE_TYPE)==TYPE_LISTE)		{
		return AjouteListe(nElement);
	}

	for (i=0;i<nMaps;i++)				//Existe déjà?
		if (ele_fond[i]==&elements[nElement])
			return 2;

	LitParam(&param);

	gblPal=(unsigned char*)malloc(3*256);
//	gblMotifs=(unsigned char*)malloc(tileX*tileY*TILEMAX);
	gblMotifs=NULL;
	//Décommenter pour obtenir la consommation mémoire dans l'éditeur (il y en a ailleurs à décommenter encore)
//	utilMemoire+=3*256+tileX*tileY*TILEMAX;

	//Lecture de la map (va également charger une palette et un tileset)
	gblMap=NULL;
	gblTypeMap=TYPE_MAP;
	
	if (!LitMap(gblPal,&gblMotifs,&gblMap,nElement))
		return 1;

	tamX=tailleX;
	tamY=tailleY;
	tailleX*=tileX;
	tailleY*=tileY;
	grilleX=tileX;
	grilleY=tileY;

	//Initialisation de la mémoire pour le buffer annuler.
	ub->MAXMEM=0;
	ub->undoBuffer=NULL;
/*	if (ub->undoBuffer)
		ub->modifie=FALSE;
	else
		ub->modifie=TRUE;*/
	ub->nOperations=-1;
	ub->dernierEnreg=0;
	ub->modifie=0;

	tailleX/=tileX;
	tailleY/=tileY;
	tileBaseX=tileX;
	tileBaseY=tileY;
	ele_fond[nMaps]=&elements[nElement];
	fond_actif[nMaps]=1;
	fond_a_sauver[nMaps]=1;
	gblSdParam=&sdParams[gblSdModele];
	parallaxeX=1;
	parallaxeY=1;
	emul_gba=0;

	LitParam(&params[nMaps]);

//	i=fondActif;
//	fondActif=nMaps;
	SauveAnnulerFond(nMaps);
//	fondActif=i;

/*	sprintf(str,"(%i %i/ %i %i)",tailleX,tailleY, tileX,tileY);
	MessageBox(gblHEdit,str,"",0);*/

	//Remplacer cette partie par un "ChoisitFond(fondActif)" lorsque ça devient trop compliqué. Le code se trouve dans MenuEditeur.
	EcritParam(&params[fondActif]);
	tailleX*=tileX;
	tailleY*=tileY;
	nMaps++;

	Console_Print_Simple("Map ouverte: %s",elements[nElement].nom_court);
	return 0;
}

int AjouteListe(int nElement)		{
	int i;
	PARAM param;
	UNDO_BUFFER *ub;
	ub=&undos[nMaps];

	for (i=0;i<nMaps;i++)				//Existe déjà?
		if (ele_fond[i]==&elements[nElement])
			return 2;

	LitParam(&param);

	gblPal=(unsigned char*)malloc(3*256);
//	gblMotifs=(unsigned char*)malloc(tileX*tileY*TILEMAX);
	gblMotifs=NULL;
	//Décommenter pour obtenir la consommation mémoire dans l'éditeur (il y en a ailleurs à décommenter encore)
//	utilMemoire+=3*256+tileX*tileY*TILEMAX;

	//Lecture de la map (va également charger une palette et un tileset)
	gblMap=NULL;

	//Initialisation de la liste
	gblSpriteListe.sizeofSD=sizeof(SPRITE_DEF);
	gblSpriteListe.sd=(SPRITE_DEF*)malloc(NB_MAX_ELE_LISTE*sizeof(SPRITE_DEF));
	gblSpriteListe.nbSprites=0;

	gblTypeMap=TYPE_LISTE;
	if (!LitListe(gblPal,&gblMotifs,&gblMap,nElement))
		return 1;

	tamX=tailleX;
	tamY=tailleY;
	tailleX*=tileX;
	tailleY*=tileY;
	grilleX=tileX;
	grilleY=tileY;

	//Initialisation de la mémoire pour le buffer annuler.
	ub->MAXMEM=0;
	ub->undoBuffer=NULL;
/*	if (ub->undoBuffer)
		ub->modifie=FALSE;
	else
		ub->modifie=TRUE;*/
	ub->nOperations=-1;
	ub->dernierEnreg=0;
	ub->modifie=0;

	tailleX/=tileX;
	tailleY/=tileY;
	tileBaseX=tileX;
	tileBaseY=tileY;
	ele_fond[nMaps]=&elements[nElement];
	fond_actif[nMaps]=1;
	fond_a_sauver[nMaps]=1;
	gblSdParam=&sdParams[gblSdModele];
	parallaxeX=1;
	parallaxeY=1;
	emul_gba=0;

	LitParam(&params[nMaps]);

//	i=fondActif;
//	fondActif=nMaps;
	SauveAnnulerListe(nMaps);
//	fondActif=i;

/*	sprintf(str,"(%i %i/ %i %i)",tailleX,tailleY, tileX,tileY);
	MessageBox(gblHEdit,str,"",0);*/

	//Remplacer cette partie par un "ChoisitFond(fondActif)" lorsque ça devient trop compliqué. Le code se trouve dans MenuEditeur.
	EcritParam(&params[fondActif]);
	tailleX*=tileX;
	tailleY*=tileY;
	nMaps++;

	Console_Print_Simple("Liste ouverte: %s",elements[nElement].nom_court);
	return 0;
}

#include "mapparams.h"
#include "editeurConsole.h"
#define WM_MOUSEWHEEL                   0x020A

void MAJValeur(HWND hDlg)		{
	sprintf(str,"%x",motifChoisi);
	SetDlgItemText(hDlg,IDC_EDIT1,str);
	SendDlgItemMessage(hDlg,IDC_EDIT1,EM_SETSEL,10,10);
}

void VerifieSiSourisSortDesBords()		{
	if (RelaToAbsX(rposX)<0)
		rposX = 0;
	if (RelaToAbsY(rposY)<0)
		rposY = 0;

	if (RelaToAbsX(rposX)>=tailleX)
		rposX = AbsToRelaX(tailleX) - 1;
	if (RelaToAbsY(rposY)>=tailleY)
		rposY = AbsToRelaY(tailleY) - 1;

	if ((rposX+tileX)-(rposX+tileX)%tileX>gdrXz)
		rposX=gdrXz-gdrXz%tileX-1;
	if ((rposY+tileY)-(rposY+tileY)%tileY>gdrYz)
		rposY=gdrYz-gdrYz%tileY-1;
}

void ControleScrollY()		{
	int tailleMax, bMajBarre;
	PARAM *p = &params[fondActif];

	bMajBarre=0;
	//HACK: remplacer tailleY par tailleY+(int)(1/parallaxeY)
//	tailleMax = (int)(((p->tailleY*p->tileY+(int)(p->tileY/p->parallaxeY))-gdrYz)/p->parallaxeY);
	tailleMax = (int)(((p->tailleY*p->tileY+p->tileY-1)-gdrYz)/p->parallaxeY);
/*	if (tailleMax % grilleY)
		tailleMax = tailleMax - tailleMax%grilleY + grilleY;*/
	//Remet la position dans la gamme possible
	if (scrollY>tailleMax)			{
		scrollY=tailleMax;
		bMajBarre=1;
	}
	if (scrollY<0)		{
		scrollY=0;
		bMajBarre=1;
	}
	scrollY -= scrollY%p->grilleY;

	//Met à jour la barre.
/*	if (bMajBarre)
		SetScrollPos(hScroll1,SB_CTL,scrollY,TRUE);*/
}

void ControleScrollX()		{
	int tailleMax;
	int bMajBarre;
	PARAM *p = &params[fondActif];
	bMajBarre=0;
	//HACK: remplacer tailleX par tailleX+(int)(1/parallaxeX)
//	tailleMax = (int)(((tailleX-1+(int)(tileX/parallaxeX))-gdrXz)/parallaxeX);
	tailleMax = (int)(((p->tailleX*p->tileX+p->tileX-1)-gdrXz)/p->parallaxeX);
//	if (tailleMax % grilleX)
//		tailleMax = tailleMax - tailleMax%grilleX + grilleX;
	//Remet la position dans la gamme possible
	if (scrollX>tailleMax)			{
		scrollX=tailleMax;
		bMajBarre=1;
	}
	if (scrollX<0)			{
		scrollX=0;
		bMajBarre=1;
	}
	scrollX -= scrollX%grilleX;

	//Met à jour la barre.
/*	if (bMajBarre)
		SetScrollPos(hScroll2,SB_CTL,scrollX,TRUE);*/
}

void EffaceElementListe(int fond, int element)		{
	char *dst=(char*)_SD(params[fond].gblSpriteListe,element), *src=(char*)_SD(params[fond].gblSpriteListe,element+1);
	int taille=(NB_MAX_ELE_LISTE-element-1)*params[fond].gblSpriteListe.sizeofSD;
	memmove(dst,src,taille);
	params[fond].gblSpriteListe.nbSprites--;
}

unsigned long GetMaxMotif(int modetexte)			{
	if (modetexte==2)
		return 0xffffffff;
	else if (modetexte==0)
		return 0xff;
	else
		return 0xffff;
}


LRESULT CALLBACK DlgEditeur(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HDC hdcEcran;
	int i,j, ii;
	int sCode, nPos;
	int ptX, ptY, pX,pY;
	static BOOL touches[256]={0}, fActive=1;
	static int tFenX=0, tFenY=0, difference;
	RECT rect, rect2;
	PARAM param;
	MAP *ancMap;
	UNDO_BUFFER *ub=&undos[fondActif];
	static int WheelScroll=0, bButtonDown, nDepasse;
	MEMORYSTATUS ms;
	int wmSizeReturnFrom=0;
	char nom_fichier[1000];
	static int diffClientX, diffClientY;
	static int maxSizeofSD;

	switch (message)
	{
		case WM_INITDIALOG:
			//La mémoire est maximum pour l'undobuffer est de la taille de la mémoire libre sur deux
			GlobalMemoryStatus(&ms);
			MAXUNDORAM=ms.dwAvailPhys/4;

			RedimDIB(1280,1024,FALSE);
			Console_Init();
			Console_Print("Bienvenue!");

			editeurOuvert=1;
			nMaps=0;
			utilMemoire=0;
			gblHSpec=0;
			nPlansLies=0;
			fenBits=0;
			hDlgBits=0;
			lstSelMulNbre=0;
			listeSelection=-1;
			bSizingTileset=0;
			basegdrXtc=128;
			grille=0;
			grilleX=8, grilleY=8;
			combleZeros=0;
			fondHexa=1;
			MODE_TEXTE=0;
			couleurGrille=RGB(64,64,64);
			transGrille=96;
			AlphaPremPlan=160;
			gfxAlphaFonds=128;
			hexAlphaFonds=96;
			zoom=1;
			zoomPrecis=0;
			bSpecimenAffiche=1;

			memset(ele_fond, 0, sizeof(ele_fond));

			//Initialise les liens -> chaque map pointe sur elle-même :)
			for (i=0;i<MAX_FONDS;i++)		{
				liens[i][0]=i;
				liens[i][1]=LIEN_INVALIDE;
				n_conditions[i]=0;
			}

			GetClientRect(hDlg,&rect);
			tFenX=rect.right-rect.left;
			tFenY=rect.bottom-rect.top;
			i=tileX, j=tileY;
			if ((i!=8 && i!=16 && i!=32 && i!=64) || (j!=8 && j!=16 && j!=32 && j!=64))	{
				MessageBox(hDlg,"Le format de votre map n'est pas utilisable sous l'éditeur; la largeur et la hauteur doivent être une de ces valeurs:\n8, 16, 32, 64.\nDésolé, mais vous ne pourrez pas ouvrir ce fichier ici.","Mince!",MB_ICONERROR);
				editeurOuvert=0;
				DestroyWindow(hDlg);
				PostQuitMessage(0);
				return TRUE;
			}
			gblHEdit=hDlg;
			hStatut=CreateWindow ("Static", "Mém: 0 ko",WS_CHILD | WS_VISIBLE | WS_TABSTOP,
				BASEDIT_X+200,BASEDIT_Y+282,100,20, hDlg, NULL, hInst, NULL);
			SendMessage(hStatut,WM_SETFONT,(WPARAM)hFonte,MAKELPARAM(1, 0));
			hBtAnnuler=CreateWindow ("Button", "Annuler",WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED,
				BASEDIT_X,BASEDIT_Y+280,60,20, hDlg, NULL, hInst, NULL);
			SendMessage(hBtAnnuler,WM_SETFONT,(WPARAM)hFonte,MAKELPARAM(1, 0));
			hBtRefaire=CreateWindow ("Button", "Refaire",WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED,
				BASEDIT_X+70,BASEDIT_Y+280,60,20, hDlg, NULL, hInst, NULL);
			SendMessage(hBtRefaire,WM_SETFONT,(WPARAM)hFonte,MAKELPARAM(1, 0));
			hBtOpts=CreateWindow ("Button", "Menu",WS_CHILD | WS_VISIBLE | WS_TABSTOP,
				BASEDIT_X+315,BASEDIT_Y+280,60,20, hDlg, NULL, hInst, NULL);
			SendMessage(hBtOpts,WM_SETFONT,(WPARAM)hFonte,MAKELPARAM(1, 0));
			hBtOk=CreateWindow ("Button", "Coller",WS_CHILD | WS_VISIBLE | WS_TABSTOP,
				BASEDIT_X+385,BASEDIT_Y+280,60,20, hDlg, NULL, hInst, NULL);
			SendMessage(hBtOk,WM_SETFONT,(WPARAM)hFonte,MAKELPARAM(1, 0));
//			tamX=tailleX/tileX;
//			tamY=tailleY/tileY;
			scrollMotifs=scrollX=scrollY=motifChoisi=0;
			derTickCount=GetTickCount();
			//Récupère le hdc de la fenêtre pour pouvoir dessiner dessus
			hdcEcran=GetDC(hDlg);
/*#ifdef UNDO_BUFFER_ACTIF
	#ifdef CALC_MEMOIRE_UNDO
			MAXMEM=tamX*tamY*sizeof(short)*OPMAX;
	#else
			MAXMEM=ALLOC_UNDO_FIXE;
	#endif
			undoBuffer=(unsigned short *)malloc(MAXMEM);
			if (undoBuffer)
				modifie=FALSE;
			else
				modifie=TRUE;
#else
			//Désactivé
			undoBuffer=NULL;
			modifie=TRUE;
#endif*/
			hScroll1=hScroll2=hScroll3=0;
			CopieSpec=0;
			CacheTravail();
			if (!blocCopie)		{
				blocCopie=(MAP (*)[1024])malloc(TAILLE_BLOCCOPIE*(MAXBLOCS+1));
				memset(blocCopie, 0, TAILLE_BLOCCOPIE*(MAXBLOCS+1));
			}

			MODE_TEXTE=0;
			fondActif=0;
			AjouteFond(num_edit);
			MajTitre();
			SetDlgItemText(hDlg,IDC_EDIT1,"0");

			//Création du dialogue spécimen
			CreateDialog(hInst,(LPCTSTR)IDD_SPECIMEN,hDlg,(DLGPROC)ProcSpecimen);

			//Ouvre le fichier .spt de config de l'éditeur de maps
			GetNomFichierConfigMap(nom_fichier, elements[num_edit].nom_fichier);
			OuvreFichierConfig(nom_fichier, NULL);

			//Exécution du script d'ouverture
			sprintf(str,"onopen %s",elements[num_edit].nom_court);
			OuvreFichierConfig(fichierConfigAOuvrir,str);
			if (!retourScript || nMaps<=0)		 {
				editeurOuvert=0;
				DestroyWindow(hDlg);
				PostQuitMessage(0);
				return TRUE;
			}

			if (!MODE_TEXTE)
				ShowWindow(GetDlgItem(hDlg,IDC_EDIT1),SW_HIDE);
			tileBaseX=tileX;
			tileBaseY=tileY;
			SetTimer(hDlg,1,editTiming,NULL);
			if (nPlansLies<=0)			{			//Si aucun plan n'a été associé au spécimen, on le quitte
				DestroyWindow(gblHSpec);
				gblHSpec=NULL;
			}
			else		{
				ShowWindow(gblHSpec, bSpecimenAffiche?SW_SHOW:SW_HIDE);
			}

			if (fenBits)			{
				SetWindowPos(hDlgBits,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				MAP (*bloc)[1024]=NULL;
				bloc=(MAP (*)[1024])BufferActif();
				SetBits(bloc[0][0]);
			}
			if (CopieX>1 || CopieY>1)
				EnableWindow(hBtOk,TRUE);
			else
				EnableWindow(hBtOk,FALSE);

#pragma warning ("Attention ici!")
/*			AjouteListe(7);
			FctLieMap("1,2");*/

			listeCopie=(SPRITE_LISTE*)malloc(MAXBLOCS*sizeof(SPRITE_LISTE));
			//Problème: trouve la map qui a le plus gros sizeofSD et stocke dans maxSizeofSD
/*			maxSizeofSD = 0;
			for (i=0;i<nMaps;i++)			{
				if (params[i].gblSpriteListe.sizeofSD > maxSizeofSD)
					maxSizeofSD = params[i].gblSpriteListe.sizeofSD;
			}
			if (maxSizeofSD > 0)		{
				for (i=0;i<MAXBLOCS;i++)		{
					listeCopie[i].nbSprites=0;
					listeCopie[i].sd=(SPRITE_DEF*)malloc(NB_MAX_ELE_LISTE*maxSizeofSD);
					listeCopie[i].sizeofSD = maxSizeofSD;
				}
			}*/
			//Prend la taille du modèle en cours
			for (i=0;i<MAXBLOCS;i++)		{
				listeCopie[i].nbSprites=0;
				listeCopie[i].sd=(SPRITE_DEF*)malloc(NB_MAX_ELE_LISTE*sdParams[gblSdModele].sizeofSD);
				listeCopie[i].sizeofSD = maxSizeofSD;
			}

			listeSelection=-1;
			selectionPointee=0;
			hLigneRedim=GetDlgItem(hDlg, IDC_LIGNE);
			//Change le curseur sur la barre de redimensionnement
			SetClassLong(hLigneRedim, GCL_HCURSOR, (LONG) LoadCursor(NULL,IDC_SIZEWE));
			return TRUE;



		case WM_SIZE:
#define FENEDIT_X (i-tFenX+BASEDIT_X)
#define FENEDIT_Y (j-tFenY+BASEDIT_Y)
			i = LOWORD(lParam);  // width of client area 
			j = HIWORD(lParam); // height of client area 
wm_size_01:
//			if (i-tFenX<-50 || j-tFenY<-200)
//				break;
			RECT rect;
			if (basegdrXtc<64)
				basegdrXtc=64;
			GetClientRect(hDlg, &rect);
			if (basegdrXtc>rect.right-128)
				basegdrXtc=rect.right-128;

			gdrX=i-tFenX+384-basegdrXtc;
			gdrY=j-tFenY+256;
			GetWindowRect(hDlg, &rect2);
			GetClientRect(hDlg, &rect);
			diffClientX = (rect2.right-rect2.left) - (rect.right-rect.left);
			diffClientY = (rect2.bottom-rect2.top) - (rect.bottom-rect.top);

MAJ:
			gdrXz=(int)(gdrX/zoom);
			gdrYz=(int)(gdrY/zoom);

			//Largeur du tileset: 128
			gdrXt=(int)(basegdrXtc/zoom)&~(tileX-1);
			gdrXtc=(int)(gdrXt*zoom);
			if (gdrXtc < tileX*zoom)
				gdrXtc = (int)(tileX*zoom);
			if (gdrXt < tileX)
				gdrXt = tileX;
//			gdrYt=gdrYz;

			BougeTruc(GetDlgItem(hDlg,IDC_EDIT1),FENEDIT_X+330,BASEDIT_X);
			BougeTruc(hBtOk,FENEDIT_X+385,FENEDIT_Y+280);
			BougeTruc(hBtAnnuler,BASEDIT_X,FENEDIT_Y+280);
			BougeTruc(hBtRefaire,BASEDIT_X+70,FENEDIT_Y+280);
			BougeTruc(hBtOpts,FENEDIT_X+315,FENEDIT_Y+280);
			BougeTruc(hStatut,BASEDIT_X+200+(i-tFenX)/2,FENEDIT_Y+282);
			SetWindowPos(GetDlgItem(hDlg, IDC_LIGNE), HWND_TOP, BASEDIT_X+gdrX+25, BASEDIT_Y, 5, gdrY, SWP_NOZORDER);
			CreeBarresDefil(hDlg);
			if (MODE_TEXTE)
				ShowWindow(hScroll3,SW_HIDE);

			SetFocus(hDlg);
			if (wmSizeReturnFrom == 1)
				goto wm_size_return_here_01;
			break;

		case WM_SIZING:
			RECT *lprc;
			lprc = (LPRECT) lParam;
			if (lprc->right - lprc->left - diffClientX < 256)
				lprc->right = 256+lprc->left + diffClientX;
			if (lprc->bottom - lprc->top - diffClientY < 256)
				lprc->bottom = 256+lprc->top + diffClientY;
			break;

		case WM_SETCURSOR:
			if (WheelScroll || bSizingTileset)
				return TRUE;
			break;
/*			if ((HWND) wParam == hDlg && !bSizingTileset)
				SetCursor(LoadCursor(NULL,IDC_ARROW));
			return TRUE;*/

/*		case WM_ERASEBKGND:
			return TRUE;*/

		//Le bouton gauche annule la sélection
		case WM_RBUTTONDOWN:
			if (selectionPointee)	{
				selectionPointee=0;
			}
			else if (selMap)		{
				selMap=0;
			}
			else if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
				bButtonDown = 1;
				SetCapture(hDlg);
				posDepartAbsolueX=RelaToAbsX(rposX);
				posDepartAbsolueY=RelaToAbsY(rposY);
				posDepartX=posDepartAbsolueX/tileX;
				posDepartY=posDepartAbsolueY/tileY;
				GetAsyncKeyState(VK_CONTROL);
//				if (gblTypeMap == TYPE_MAP || GetAsyncKeyState(VK_CONTROL))
					selCopie=1;
//				else
//					lstSelMulNbre=0;
			}
			else if (posX>=BASEDIT_X+gdrX+44 && posX<BASEDIT_X+gdrX+44+gdrXtc && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY && !MODE_TEXTE)	{
			}
			else	{
apparaitMenu:
				i=MenuEditeur(hDlg);
choisitMap:
				lstSelMulNbre=0;
				listeSelection=-1;
				if (i>=MAX_FONDS*2 && i<MAX_FONDS*2+nMaps && fondActif!=(i-2*MAX_FONDS))			{				//Une map sélectionnée
					MAP (*bloc)[1024];
					//Restaure les dimensions
					params[fondActif].tileX=tileBaseX;
					params[fondActif].tileY=tileBaseY;
					//On prend un nouveau fond
					fondActif=i-MAX_FONDS*2;
					//Ecrit les paramètres
					EcritParam(&params[fondActif]);
					tailleX*=tileX;
					tailleY*=tileY;
					MAJBoutonsAnnuler();
					MajTitre();
					//Ecrit les bits
					bloc=(MAP (*)[1024])BufferActif();
					SetBits(bloc[0][0]);
					goto switchModeHexa2;
				}
				else if (i>=MAX_FONDS && i<MAX_FONDS+nMaps)			{				//Une map sélectionnée
					gblNoFondProprietes = i-MAX_FONDS;
optionsFond:
					DialogBox(hInst,(LPCTSTR)IDD_OPTIONSFONDONGLETS,hDlg,(DLGPROC)DlgOptionsFondOnglets);
				}
				else if (i==OM_BITS)		{
					if (fenBits)		{
						if (IsWindowVisible(hDlgBits))
							ShowWindow(hDlgBits,SW_HIDE);
						else
							ShowWindow(hDlgBits,SW_SHOW);
					}
					else
						CreateDialog(hInst,(LPCTSTR)IDD_BITS,hDlg,(DLGPROC)DlgBits);
				}
				else if (i==OM_OPTIONS)		{
showOptions:
//					if (DialogBox(hInst,(LPCTSTR)IDD_OPTIONSEDITEUR,hDlg,(DLGPROC)ProcOptions)==1)
					i=DialogBox(hInst,(LPCTSTR)IDD_OPTIONSEDITEURONGLETS,hDlg,(DLGPROC)DlgOptionsEditeurOnglets);
					if (i==IDC_FMTTILES)
						goto formatTiles;
					else if (i==IDC_OPTIONSFOND)		{
						gblNoFondProprietes = fondActif;
						goto optionsFond;
					}
				}
				else if (i==OM_SPECIMEN)		{
voitSpecimen:
					bSpecimenAffiche = !bSpecimenAffiche;
					ShowWindow(gblHSpec, bSpecimenAffiche?SW_SHOW:SW_HIDE);
				}
				else if (i==OM_TRANSPARENT)		{
					fondTransparent=!fondTransparent;
				}
				else if (i==OM_FONDHEXA)		{
					fondHexa=!fondHexa;
				}
				else if (i==OM_ZERO)		{
					combleZeros=!combleZeros;
				}
				else if (i==OM_HEXA)		{
switchModeHexa:
					MODE_TEXTE=!MODE_TEXTE;
switchModeHexa2:
					tailleX/=tileX;
					tailleY/=tileY;
					if (MODE_TEXTE)		{
						params[fondActif].tileX=16;
						params[fondActif].tileY=16;
					}
					else		{
						params[fondActif].tileX=params[fondActif].tileBaseX;
						params[fondActif].tileY=params[fondActif].tileBaseY;
					}
					tailleX*=params[fondActif].tileX;
					tailleY*=params[fondActif].tileY;
					CreeBarresDefil(gblHEdit);
					if (MODE_TEXTE)		{
						ColoreCadre(Bits3,0,0,gdrXt,gdrY,cFond);
/*						if (zoom!=1.0)
							StretchBlt(hdcEcran,BASEDIT_X+gdrX+44,BASEDIT_Y,128,gdrY,hdcEdit,0,0,gdrXt,gdrY,SRCCOPY);
						else*/
							BitBlt(hdcEcran,BASEDIT_X+gdrX+44,BASEDIT_Y,gdrXt,gdrY,hdcEdit,0,0,SRCCOPY);
						ShowWindow(GetDlgItem(hDlg,IDC_EDIT1),SW_SHOW);
						ShowWindow(hScroll3,SW_HIDE);
						SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
						MAJValeur(hDlg);
					}
					else		{
						ShowWindow(GetDlgItem(hDlg,IDC_EDIT1),SW_HIDE);
						ShowWindow(hScroll3,SW_SHOW);
						SetFocus(hDlg);
					}
				}
				else if (i==OM_FOND)		{
ajouteFond:
					if (nMaps>=MAX_FONDS)	{
						MessageBox(hDlg,"La limite du nombre de fonds est atteinte!","Erreur",MB_ICONERROR);
						break;
					}
					j=DialogBox(hInst,(LPCTSTR)IDD_FOND,hDlg,(DLGPROC)Fond);
					if (j>=0)		{
						ii=TrouveNiemeElementCarteListe(j+1);
						AjouteFond(ii);
					}
				}
				else if (i==OM_LIER)		{
					DialogBox(hInst,(LPCTSTR)IDD_LIAISON,hDlg,(DLGPROC)DlgLier);
				}
				else if (i==OM_DEPLACER)		{
					DialogBox(hInst,(LPCTSTR)IDD_DEPLACEMENT,hDlg,(DLGPROC)DlgDeplace);
				}
				else if (i==OM_OPERATION)		{
					DialogBox(hInst,(LPCTSTR)IDD_OPERATIONS,hDlg,(DLGPROC)DlgOperations);
				}
				else if (i==OM_PROPREPALETTE)		{
					proprePalette=!proprePalette;
				}
				else if (i==OM_FMTTILES)		{
					int x,y,xx,yy;
					MAP *nvMap;
formatTiles:
					LitParam(&param);
					if (DialogBox(hInst,(LPCTSTR)IDD_TILES,hDlg,(DLGPROC)DlgTiles)==IDOK)			{
						tailleX/=param.tileX;
						tailleY/=param.tileY;
						i=tailleX;
						j=tailleY;
						i*=param.tileX/8;
						j*=param.tileY/8;
						ancMap=(MAP*)malloc(i*j*sizeof(MAP));
						if (!ancMap)		{
							MessageBox(hDlg,"Mémoire insuffisante...","Erreur",MB_ICONERROR);
							break;
						}
						memset(ancMap,0,i*j*sizeof(MAP));
						for (y=0;y<tailleY;y++)		{
							for (x=0;x<tailleX;x++)		{
								ii=gblMap[tailleX*y+x]+blocBase;
								//Motif non-valide (ne devrait pas arriver)
/*								sprintf(str,"%i %i %i %i\n"
									"tailleX*y+x=%i*%i+%i=%i\n"
									"ii*((tileX*tileY)/64)=%i*((%i*%i)/64)=%i",
									i*(param.tileY/8)*y+(param.tileX/8)*x,
									i*(param.tileY/8)*y+(param.tileX/8)*x+1,
									i*((param.tileY/8)*y+1)+(param.tileX/8)*x,
									i*((param.tileY/8)*y+1)+(param.tileX/8)*x+1,
									tailleX,y,x,tailleX*y+x,
									ii,tileX,tileY,ii*((tileX*tileY)/64)
								);
								MessageBox(hDlg,str,"Trace",MB_ICONINFORMATION);
								tailleX/=param.tileX;
								tailleY/=param.tileY;*/
								if (ii>=taille || ii<0)
									continue;
								for (yy=0;yy<param.tileY/8;yy++)
									for (xx=0;xx<param.tileX/8;xx++)		{
										ancMap[i*((param.tileY/8)*y+yy)+(param.tileX/8)*x+xx]=ii*((param.tileX*param.tileY)/64)+xx+yy*(param.tileY/8);
//										sprintf(str,"%i %i",i*((param.tileY/8)*y+yy)+(param.tileX/8)*x+xx,ii*((tileX*tileY)/64)+xx+yy*(tileY/8));
//										MessageBox(hDlg,str,"Trace",MB_ICONINFORMATION);
									}
/*									for (yy=0;yy<tileY;yy+=8)
									for (xx=0;xx<tileX;xx+=8)		{
										SpritePal(x*tileX+xx,y*tileY+yy,8,8,motifs+(i*tileX*tileY)+64*(tileX/8)*(yy/8)+64*(xx/8),palette);
								}*/
					//			ColoreCadre(x,y,16,16,RGB(255,0,0));
							}
						}
						tailleX=tamX=i;
						tailleY=tamY=j;
						i=i/(tileX/8);
						j=j/(tileY/8);
						taille*=(param.tileX*param.tileY)/64;

						nvMap=(MAP*)malloc(i*j*sizeof(MAP));
						if (!nvMap)		{
							EcritParam(&param);
							tamX=tailleX;
							tamY=tailleY;
							MessageBox(hDlg,"Mémoire insuffisante","Oups...",MB_ICONERROR);
							break;
						}
						for (y=0;y<j;y++)		{
							for (x=0;x<i;x++)		{
								ii=ancMap[tailleX*(tileY/8)*y+(tileX/8)*x];
/*								sprintf(str,"Source: %i\nDestination: %i\nDonnée source: %i\nDonnée destination: %i",tailleX*(tileY/8)*y+(tileX/8)*x,i*y+x,ii,ii/((tileX*tileY)/64));
								MessageBox(hDlg,str,"Trace",0);
								tailleX/=tileX;
								tailleY/=tileY;*/
								nvMap[i*y+x]=ii/((tileX*tileY)/64);
							}
						}
//						EcritParam(&param);
						tailleX=tamX=i;
						tailleY=tamY=j;
						gblMap=nvMap;
						taille/=(tileX*tileY)/64;
						tileBaseX=tileX;
						tileBaseY=tileY;

						free(ancMap);

						VideUndoBuffer();

						//LitParam DOIT avoir des dimensions non-multipliées par celles des blocs.
						LitParam(&params[fondActif]);
					}
				}
			}
			break;

		case WM_MBUTTONDOWN:
			SetCapture(hDlg);
			WheelScroll=2;
			SetCursor(LoadCursor(NULL,IDC_SIZEALL));
//			goto scroll_wheel;
			break;

		case WM_MBUTTONUP:
			if (WheelScroll)		{
				ReleaseCapture();
				WheelScroll=0;
				SetCursor(LoadCursor(NULL,IDC_ARROW));
//				goto scroll_wheel;
			}
			break;

		//Démarre la sélection
		case WM_LBUTTONDBLCLK:
		case WM_LBUTTONDOWN:
			int tmpSourisX, tmpSourisY;
			if (selCopie)		{
				selCopie=0;
				break;
			}
			if (gblTypeMap==TYPE_LISTE)			{
//				tmpSourisX=(int)(rposX+scrollX*parallaxeX), tmpSourisY=(int)(rposY+scrollY*parallaxeY);
				tmpSourisX=RelaToAbsX(rposX), tmpSourisY=RelaToAbsY(rposY);
//				ArronditX(tmpSourisX);
//				ArronditY(tmpSourisY);
				if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)			{
					if ((listeSelection != -1 || lstSelMulNbre>0) && message==WM_LBUTTONDBLCLK)		{			//Double-clic
						if (DialogBox(hInst,(LPCTSTR)IDD_ATTRIBUTS,hDlg,(DLGPROC)DlgAttributs)==IDOK)
							SauveAnnuler();
						break;
					}
//					if (CopieX==0 && CopieY==0)			{
						j=listeSelection;
						listeSelection=-1;

						for (i=0;i<params[fondActif].gblSpriteListe.nbSprites;i++)		{
							SPRITE_DEF *sd;
							sd=_SD(params[fondActif].gblSpriteListe,i);
							if (sd->x+tileX>tmpSourisX && sd->x<=tmpSourisX && sd->y+tileY>tmpSourisY && sd->y<=tmpSourisY)		{
								listeSelection=i;
							}
						}
						if (j!=-1)			{
							GetAsyncKeyState(VK_CONTROL);
							if (GetAsyncKeyState(VK_CONTROL))		{
								if (!lstSelMulNbre)		{
									lstSelMulNbre=2;
									lstSelMulListe[0]=j;
									lstSelMulListe[1]=listeSelection;
								}
								else		{
									lstSelMulAjObjet(listeSelection,1);
								}
							}
							else if (lstSelMulNbre)				{
								//Est-ce qu'on a sélectionné un élément de la liste?
								for (i=0;i<lstSelMulNbre;i++)			{
									if (lstSelMulListe[i] == listeSelection)
										break;
								}
								//Non? -> supprime la liste
								if (i >= lstSelMulNbre)			{
									lstSelMulNbre=0;
								}
							}
						}
						if (listeSelection==-1)		{
							//Cliqué sur rien du tout -> annule la sélection multiple
							if (lstSelMulNbre)		{
								GetAsyncKeyState(VK_CONTROL);
								if (!GetAsyncKeyState(VK_CONTROL))
									lstSelMulNbre=0;
							}
							else if (motifChoisi!=0)			{
								//Clic normal sur rien et pas de sélection en cours -> colle l'objet
								if (CopieX==0 && CopieY==0 && j==-1)
									ColleBlocs(rposX,rposY,rposX,rposY,0);
							}
							else if (!(CopieX==0 && CopieY==0))		{
								if (lstSelMulNbre)		{
									lstSelMulNbre=0;
									listeSelection=-1;
								}
								else	{
									bButtonDown = 1;
									SetCapture(hDlg);
									posDepartAbsolueX=RelaToAbsX(rposX);
									posDepartAbsolueY=RelaToAbsY(rposY);
									posDepartX=posDepartAbsolueX/tileX;
									posDepartY=posDepartAbsolueY/tileY;
									selMap=1;
								}
							}
						}
/*						else if (listeSelection==j && message==WM_LBUTTONDBLCLK)		{			//Double-clic
							if (DialogBox(hInst,(LPCTSTR)IDD_ATTRIBUTS,hDlg,(DLGPROC)DlgAttributs)==IDOK)
								SauveAnnuler();
						}*/
						else	{
/*							mouseOffsetX=tmpSourisX-_SD(params[fondActif].gblSpriteListe,listeSelection)->x;
							mouseOffsetY=tmpSourisY-_SD(params[fondActif].gblSpriteListe,listeSelection)->y;*/
							bButtonDown = 1;
							SetCapture(hDlg);
							selectionPointee=listeSelection+1;
							motifChoisi=0;
							CopieX=CopieY=0;
						}
//					}
/*					else			{
					}*/
				}
			}
			else	{
				if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
	/*				posDepartAbsolueX=(rposX/tileX)*tileX;
					posDepartAbsolueY=(rposY/tileY)*tileY;*/
					bButtonDown = 1;
					SetCapture(hDlg);
					posDepartAbsolueX=RelaToAbsX(rposX);
					posDepartAbsolueY=RelaToAbsY(rposY);
					posDepartX=posDepartAbsolueX/tileX;
					posDepartY=posDepartAbsolueY/tileY;
					selMap=1;
				}
			}
			break;

		//Là aussi
		case WM_LBUTTONUP:
			//Fin de redimensionnement d'un tileset
			if (bSizingTileset)		{
				ReleaseCapture();
				break;
			}
			ReleaseCapture();
			if (posX>=BASEDIT_X+gdrX+44 && posX<BASEDIT_X+gdrX+44+gdrXtc && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY && !MODE_TEXTE)		{
				i=(tposX)/tileX+(gdrXt/tileX)*(tposY/tileY+scrollMotifs/tileY);
				if (i>=0 && i<taille)			{
					int t, j;
					if (n_conditions[fondActif])		{
						for (t=0;t<n_conditions[fondActif];t++)		{
							j=s_conditions[fondActif][t].debut-s_conditions[fondActif][t].difference;
							if (s_conditions[fondActif][t].exact)		{
								if (i==j)		{
									i+=s_conditions[fondActif][t].difference;
									break;
								}
							}
							else		{
								if (i>=j && i<=(int)(j+(s_conditions[fondActif][t].fin-s_conditions[fondActif][t].debut)))		{
									i+=s_conditions[fondActif][t].difference;
									break;
								}
							}
						}
					}
					motifChoisi=i;
					Console_Print("Motif: %i (%04x)",motifChoisi,motifChoisi);
				}
				CopieX=CopieY=0;
				CopieSpec=0;
				profondeurSel=1;
			}
			else if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
				if (selMap)		{
					ptX=(rposX);
					ptY=(rposY);
					pX=AbsToRelaX(posDepartAbsolueX);
					pY=AbsToRelaY(posDepartAbsolueY);
//					ArronditX(rposX); ArronditY(rposY);

					if (bArronditSelection && gblTypeMap==TYPE_LISTE)		{
						ArronditX(pX); ArronditY(pY);
						ArronditHautX(ptX); ArronditHautY(ptY);
						ptX--; ptY--;
					}

					GetAsyncKeyState(VK_CONTROL);
					i=GetAsyncKeyState(VK_CONTROL);
					ColleBlocs(pX,pY,ptX,ptY,i?1:0);
				}
				else if (selectionPointee && params[fondActif].gblTypeMap==TYPE_LISTE)		{
					rposX=RelaToAbsX(rposX), rposY=RelaToAbsY(rposY);
					ArronditX(rposX);
					ArronditY(rposY);
//					rposX+=(int)(scrollX*parallaxeX); rposY+=(int)(scrollY*parallaxeY);
//					rposX-=mouseOffsetX; rposY-=mouseOffsetY;
					if (lstSelMulNbre)		{
						//selection pointée est ajouté d'un car si l'objet 0 est sélectionné, selectionPointee doit être >=1
						int tempOffsetX=rposX-_SD(params[fondActif].gblSpriteListe,selectionPointee-1)->x;
						int tempOffsetY=rposY-_SD(params[fondActif].gblSpriteListe,selectionPointee-1)->y;
						if (tempOffsetX!=0 || tempOffsetY!=0)		{
							for (i=0;i<lstSelMulNbre;i++)		{
								_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x+=tempOffsetX;
								_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y+=tempOffsetY;
								ArronditX(_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x);
								ArronditX(_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y);
								if (_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x<0)
									_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x=0;
								if (_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x+tileX>tailleX)
									_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x=tailleX-tileX;
								if (_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y<0)
									_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y=0;
								if (_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y+tileY>tailleY)
									_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y=tailleY-tileY;
//								ArronditX(_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->x);
//								ArronditY(_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i])->y);
							}
							SauveAnnuler();
						}
					}
					else			{
//						ArronditX(rposX); ArronditY(rposY);
						if (_SD(params[fondActif].gblSpriteListe,listeSelection)->x!=rposX || _SD(params[fondActif].gblSpriteListe,listeSelection)->y!=rposY)		{
							_SD(params[fondActif].gblSpriteListe,listeSelection)->x=rposX;
							_SD(params[fondActif].gblSpriteListe,listeSelection)->y=rposY;
							SauveAnnuler();
						}
					}
					rposX-=(int)(scrollX*parallaxeX); rposY-=(int)(scrollY*parallaxeY);
					selectionPointee=0;
				}
			}
			selMap=0;
			break;

		//Là aussi
		case WM_RBUTTONUP:
			ReleaseCapture();
			if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
				if (selCopie)		{
					if (gblTypeMap==TYPE_LISTE)			{
						ptX=rposX;
						ptY=rposY;
						pX=AbsToRelaX(posDepartAbsolueX);
						pY=AbsToRelaY(posDepartAbsolueY);

						if (bArronditSelection && gblTypeMap==TYPE_LISTE)		{
							ArronditX(pX); ArronditY(pY);
							ArronditHautX(ptX); ArronditHautY(ptY);
							ptX--; ptY--;
						}

						GetAsyncKeyState(VK_CONTROL);
						i=GetAsyncKeyState(VK_CONTROL);
						if (i /*&& lstSelMulNbre*/)			{
							motifChoisi = 0;
							CopieX=CopieY=0;
							lstSelMulAjBlocs(fondActif,pX,pY,ptX,ptY);
						}
						else
							CopieBlocs(pX,pY,ptX,ptY,i);
					}
					else	{
						ptX=(rposX);
						ptY=(rposY);
						pX=AbsToRelaX(posDepartAbsolueX);
						pY=AbsToRelaY(posDepartAbsolueY);

						GetAsyncKeyState(VK_CONTROL);
						i=GetAsyncKeyState(VK_CONTROL);

						CopieBlocs(pX,pY,ptX,ptY,i);

						//S'il n'a séléctionné qu'un bloc, on annule la copie et sélectionne le motif correspondant (il faut également que la map ne soit pas liée pour ça)
						if (CopieX==1 && CopieY==1 && (liens[fondActif][1]==LIEN_INVALIDE || i))		{
							motifChoisi=blocCopie[0][0];
							Console_Print("Motif: %i (%04x)",motifChoisi,motifChoisi);
							CopieX=CopieY=0;
							CopieSpec=0;
							profondeurSel=1;
								EnableWindow(hBtOk,FALSE);
								EnableWindow(GetDlgItem(hDlg,IDC_EDIT1),TRUE);
								MAJValeur(hDlg);
								SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
						}
						else	{
								EnableWindow(hBtOk,TRUE);
								EnableWindow(GetDlgItem(hDlg,IDC_EDIT1),FALSE);
								SetFocus(hDlg);
						}
					}
				}
			}
			selCopie=0;
			break;

		case WM_MOUSEMOVE:
			int ancPosX, ancPosY;
			ancPosX=posX, ancPosY=posY;
			posX=(short)LOWORD(lParam);
			posY=(short)HIWORD(lParam);
			//Clic du milieu
			if (WheelScroll)		{
				static POINT wsptSav, wsptNew;
				int wsdiffX, wsdiffY;
				GetCursorPos(&wsptNew);
				wsptNew.x = (int)(wsptNew.x/zoom);
				wsptNew.y = (int)(wsptNew.y/zoom);
				//Première fois?
				if (WheelScroll==2)		{
					//initialiser wsptSav
					wsptSav=wsptNew;
					wsptSav.x-=grilleX/2;
					wsptSav.y-=grilleY/2;
					WheelScroll=1;
				}
				SetCursor(LoadCursor(NULL,IDC_SIZEALL));
				wsdiffX=(int)((wsptNew.x-wsptSav.x))&~(grilleX-1);
				wsdiffY=(int)((wsptNew.y-wsptSav.y))&~(grilleY-1);
				scrollX-=(int)(wsdiffX/parallaxeX);
				scrollY-=(int)(wsdiffY/parallaxeY);
				wsptSav.x+=wsdiffX;
				wsptSav.y+=wsdiffY;
				ControleScrollX();
				ControleScrollY();
				SetScrollPos(hScroll1,SB_CTL,scrollY,TRUE);
				SetScrollPos(hScroll2,SB_CTL,scrollX,TRUE);
			}
			else if (bButtonDown)			{
				nDepasse=0;
				if (posX<BASEDIT_X)
					posX=BASEDIT_X, nDepasse|=1;
				if (posY<BASEDIT_Y)
					posY=BASEDIT_Y, nDepasse|=2;
				if (posX>=BASEDIT_X+gdrX)
					posX=BASEDIT_X+gdrX-1, nDepasse|=4;
				if (posY>=BASEDIT_Y+gdrY)
					posY=BASEDIT_Y+gdrY-1, nDepasse|=8;
				rposX=(int)((posX-BASEDIT_X)/zoom);
				rposY=(int)((posY-BASEDIT_Y)/zoom);
				//Vérifie si on sort des bords
				VerifieSiSourisSortDesBords();
			}
			//Zone map
			else if (posX>=BASEDIT_X && posX<BASEDIT_X+gdrX && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY)		{
				rposX=(int)((posX-BASEDIT_X)/zoom);
				rposY=(int)((posY-BASEDIT_Y)/zoom);
				//Vérifie si on sort des bords
				VerifieSiSourisSortDesBords();
			}
			//Zone tileset
			else if (posX>=BASEDIT_X+gdrX+44 && posX<BASEDIT_X+gdrX+44+gdrXtc && posY>=BASEDIT_Y && posY<BASEDIT_Y+gdrY && !MODE_TEXTE)		{
				tposX=(int)((posX-(BASEDIT_X+gdrX+44))/zoom);
				tposY=(int)((posY-BASEDIT_Y)/zoom);
			}
			break;


		//ATTENTION! La sélection avec roulement de la souris ne marche pas pour les conditions!
		case WM_MOUSEWHEEL:
			i=(short) HIWORD(wParam);
			GetAsyncKeyState(VK_CONTROL);
			//Control+mollette = zoom
			if (GetAsyncKeyState(VK_CONTROL))		{
				double ancZoom=zoom;
				if (i>0 && zoom<4.0)
					zoom+=0.5;
				else if (i<0 && zoom>1)
					zoom-=0.5;
				if (zoom!=ancZoom)		{
					//On doit simuler un WM_SIZE pour mettre à jour tout ça
					GetClientRect(hDlg,&rect);
					i=rect.right;
					j=rect.bottom;
					Console_Print("Zoom: %i%%",(int)(zoom*100));
					wmSizeReturnFrom = 0;
					goto wm_size_01;
				}
			}
			else	{
				if (i && (CopieX || CopieY))		{
					CopieX=CopieY=0;
					CopieSpec=0;
					profondeurSel=1;
						EnableWindow(hBtOk,FALSE);
						EnableWindow(GetDlgItem(hDlg,IDC_EDIT1),TRUE);
						SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
				}
				else	{
					unsigned long maxMotif=GetMaxMotif(ModeTexte);
					if (MODE_TEXTE)		{
						if (i>0)
							motifChoisi--;
						else if (i<0)
							motifChoisi++;
					}
					else	{
						if (i>0 && motifChoisi>0)
							motifChoisi--;
						else if (i<0 && (unsigned long)motifChoisi<maxMotif) // if (i<0 && motifChoisi<taille-blocBase-1)
							motifChoisi++;
					}
					motifChoisi&=maxMotif;
					MAJValeur(hDlg);
				}
				Console_Print("Motif: %i (%04x)",motifChoisi,motifChoisi);
			}
			break;

		case WM_CAPTURECHANGED:
			bButtonDown = 0;
			WheelScroll = 0;
			bSizingTileset=0;
			break;

		case WM_ACTIVATE:
			fActive=LOWORD(wParam);
			break;

		case WM_TIMER:
			int k, vitesse, lastBasegdrX;
			BOOL bMajBarre;
			POINT curPos;

			//On utilise le fond actif
			EcritParam(&params[fondActif]);

			if (params[fondActif].gblTypeMap == TYPE_MAP)		{
				//Obligatoire car scrolling basé sur ça
				if (params[fondActif].grilleX < params[fondActif].tileX)
					params[fondActif].grilleX = params[fondActif].tileX;
				if (params[fondActif].grilleY < params[fondActif].tileY)
					params[fondActif].grilleY = params[fondActif].tileY;
			}

			if (bSizingTileset)		{
				GetCursorPos(&curPos);
				if (ABS(curPos.x-pSizingPos.x)>0)			{
					lastBasegdrX = basegdrXtc;
					basegdrXtc-=curPos.x-pSizingPos.x;
					if (basegdrXtc<64)
						basegdrXtc=64;
					//On doit simuler un WM_SIZE pour mettre à jour tout ça
					GetClientRect(hDlg, &rect);
					if (basegdrXtc>rect.right-128)		{
						basegdrXtc = (rect.right-128);
					}
					pSizingPos.x -= basegdrXtc-lastBasegdrX;
					if (ABS(basegdrXtc-lastBasegdrX)>0)		{
						i=rect.right;
						j=rect.bottom;
						wmSizeReturnFrom = 1;
						goto wm_size_01;
wm_size_return_here_01:
						;
					}
				}
			}

			//Bouton du milieu enfoncé
/*			if (WheelScroll)		{
				static POINT wsptSav, wsptNew;
				int wsdiffX, wsdiffY;
scroll_wheel:
				GetCursorPos(&wsptNew);
				wsptNew.x/=(int)zoom;
				wsptNew.y/=(int)zoom;
				//Première fois?
				if (WheelScroll==2)		{
					//initialiser wsptSav
					wsptSav=wsptNew;
					wsptSav.x-=grilleX/2;
					wsptSav.y-=grilleY/2;
					WheelScroll=1;
				}
				SetCursor(LoadCursor(NULL,IDC_SIZEALL));
				wsdiffX=(int)((wsptNew.x-wsptSav.x))&~(grilleX-1);
				wsdiffY=(int)((wsptNew.y-wsptSav.y))&~(grilleY-1);
				scrollX-=(int)(wsdiffX/parallaxeX);
				scrollY-=(int)(wsdiffY/parallaxeY);
				wsptSav.x+=wsdiffX;
				wsptSav.y+=wsdiffY;
				ControleScrollX();
				ControleScrollY();
				SetScrollPos(hScroll1,SB_CTL,scrollY,TRUE);
				SetScrollPos(hScroll2,SB_CTL,scrollX,TRUE);
				if (!GetAsyncKeyState(VK_MBUTTON))		{
					WheelScroll=0;
					SetCursor(LoadCursor(NULL,IDC_ARROW));
				}
			}*/

			if (majRequise)		{
				EcritParam(&params[fondActif]);
				majRequise=0;
				i=gdrX+tFenX-256;
				j=gdrY+tFenY-256;
				tailleX*=tileX;
				tailleY*=tileY;
				goto MAJ;
			}

			i=GetTickCount();
			diffTickCount=i-derTickCount;
			difference+=i-derTickCount;
//			derTickCount=i;
			derTickCount+=diffTickCount;

			i=GetAsyncKeyState(VK_SHIFT);
			if (i)
				vitesse=10;
			else
				vitesse=50;

			if (i)		{
				if (params[fondActif].gblTypeMap==TYPE_LISTE)
					modeArrondi=0;
				else
					modeArrondi=1;
			}
			else
				modeArrondi=1;

			//Uniquement si bouton appuyé, on fait défiler
			if (!bButtonDown || !nDepasse || (!selMap && !selCopie && !selectionPointee))
				difference = 0;

			if (difference>=vitesse)		{
				bMajBarre=0;
				for (j=0;(difference/vitesse)>0;j++)		{
					difference-=vitesse;
/*					if (posX-BASEDIT_X<=0 && scrollX>0)
						scrollX-=(int)(tileX/parallaxeX)bMajBarre=1;
					if (posY-BASEDIT_Y<=0 && scrollY>0)
						scrollY-=(int)(tileY/parallaxeY), bMajBarre=1;
					if (posX-BASEDIT_X>=gdrX-1 && scrollX<(int)((tailleX-gdrXz)/parallaxeX))
						scrollX+=(int)(tileX/parallaxeX), bMajBarre=1;
					if (posY-BASEDIT_Y>=gdrY-1 && scrollY<(int)((tailleY-gdrYz)/parallaxeY))
						scrollY+=(int)(tileY/parallaxeY), bMajBarre=1;*/

					if (nDepasse&1)
						scrollX-=(int)(tileX/parallaxeX), /*posDepartX++, posDepartAbsolueX+=tileX,*/ bMajBarre=1;
					if (nDepasse&2)
						scrollY-=(int)(tileY/parallaxeY), /*posDepartY++, posDepartAbsolueY+=tileY,*/ bMajBarre=1;
					if (nDepasse&4)
						scrollX+=(int)(tileX/parallaxeX), /*posDepartX--, posDepartAbsolueX-=tileX,*/ bMajBarre=1;
					if (nDepasse&8)
						scrollY+=(int)(tileY/parallaxeY), /*posDepartY--, posDepartAbsolueY-=tileY,*/ bMajBarre=1;

/*					if (posX-BASEDIT_X<8 && scrollX>0)
						scrollX-=grilleX, posDepartX++, posDepartAbsolueX+=grilleX;
					if (posY-BASEDIT_Y<8 && scrollY>0)
						scrollY-=grilleY, posDepartY++, posDepartAbsolueY+=grilleY;
					if (posX-BASEDIT_X>gdrX-8 && scrollX<tailleX-gdrXz)
						scrollX+=grilleX, posDepartX--, posDepartAbsolueX-=grilleX;
					if (posY-BASEDIT_Y>gdrY-8 && scrollY<tailleY-gdrYz)
						scrollY+=grilleY, posDepartY--, posDepartAbsolueY-=grilleY;*/
				}
				if (bMajBarre)		{
					ControleScrollX();
					ControleScrollY();
					SetScrollPos(hScroll2,SB_CTL,scrollX,TRUE);
					SetScrollPos(hScroll1,SB_CTL,scrollY,TRUE);
				}
				difference+=diffTickCount;
			}

			//Récupère la couleur de fond
			i=GetPixel(hdcEcran,0,0);
			//La couleur de fond a changé?
			if (i!=cFond && i!=CLR_INVALID)		{
				cFond=i;
				DessineBlocArrondi();
			}
			//Dessine le tileset à droite
			if (!MODE_TEXTE)		{
				DessineTilesetScrl(gblPal,gblMotifs,scrollMotifs);
				if (zoom!=1.0)
					StretchBlt(hdcEcran,BASEDIT_X+gdrX+44,BASEDIT_Y,gdrXtc,gdrY,hdcEdit,0,0,gdrXt,gdrYz,SRCCOPY);
				else
					BitBlt(hdcEcran,BASEDIT_X+gdrX+44,BASEDIT_Y,gdrXt,gdrY,hdcEdit,0,0,SRCCOPY);
			}
			//Dessine la map
			if (MODE_TEXTE)
				ColoreCadre(Bits3,0,0,gdrXz,gdrYz,RGB(255,255,255));
			else
				ColoreCadre(Bits3,0,0,gdrXz,gdrYz,cFond);
			tailleX=tamX;
			tailleY=tamY;

			j=MODE_TEXTE;
			MODE_TEXTE=0;

			for (i=0;i<nMaps;i++)		{
				if (i==fondActif)						//Ne pas traiter le fond actif
					continue;

				if (fond_actif[i])		{
					EcritParam(&params[i]);
					if (fondTransparent)	{
						if (j)			//Anciennement MODE_TEXTE
							k=hexAlphaFonds;
						else// if (nMaps>1)
							k=gfxAlphaFonds;
//						else
//							k=0;
					}
					else
						k=0;
					if (gblTypeMap==TYPE_MAP)		{
						if (proprePalette)
							DessineMapEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,k,i);
						else
							//Garder la palette de base
							DessineMapEdit(params[fondActif].gblPal,gblMotifs,gblMap,scrollX,scrollY,k,i);
					}
					else if (gblTypeMap==TYPE_LISTE)		{
						if (proprePalette)
							DessineListeEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,k,i);
						else
							//Garder la palette de base
							DessineListeEdit(params[fondActif].gblPal,gblMotifs,gblMap,scrollX,scrollY,k,i);
					}
//						DessineMapEdit(gblPal,til_fond[i],map_fond[i],scrollX,scrollY,k);
				}
			}

			EcritParam(&params[fondActif]);
//			EcritParam(&params[fondActif]);

			MODE_TEXTE=j;

			if (gblTypeMap==TYPE_MAP)			{
				if (fondHexa)
					DessineMapEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,hexAlphaFonds,fondActif);

				EcritParam(&params[fondActif]);

				if (nMaps>1 && fondTransparent)
					DessineMapEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,AlphaPremPlan,fondActif);
				else
					DessineMapEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,0,fondActif);

				//Dessine l'écran
//				for (i=0;i<1000;i++)
					DessineEcran(rposX,rposY);
			}
			else		{
				if (nMaps>1 && fondTransparent)
					DessineListeEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,AlphaPremPlan,fondActif);
				else
					DessineListeEdit(gblPal,gblMotifs,gblMap,scrollX,scrollY,0,fondActif);
				DessineEcranListe(rposX,rposY);
			}

			//Affiche le contenu de la console
			Console_Affiche();

			//L'image est stockée dans hdcEdit (qui contient une DIB)
			//Copie de l'image
/*			if ((gdrX&(~1))!=gdrXz*2 || (gdrY&(~1))!=gdrYz*2)
				Debug("%i %i",gdrX&(~1),gdrXz);*/
			if (zoomPrecis && zoom!=1.0)
				SetStretchBltMode(hdcEcran,HALFTONE);
			else
				SetStretchBltMode(hdcEcran,COLORONCOLOR);
			StretchBlt(hdcEcran,BASEDIT_X,BASEDIT_Y,gdrX,gdrY,hdcEdit,0,0,gdrXz,gdrYz,SRCCOPY);
//			BitBlt(hdcEcran,BASEDIT_X,BASEDIT_Y,gdrX,gdrY,hdcEdit,0,0,SRCCOPY);
			break;

		case WM_VSCROLL:
			sCode = (int) LOWORD(wParam); // scroll bar value 
			nPos = (short int) HIWORD(wParam);  // scroll box position 

			if ((HWND) lParam==hScroll3)		{
				if (sCode==SB_LINEUP)
					scrollMotifs-=gdrXt/tileX*2;
				if (sCode==SB_LINEDOWN)
					scrollMotifs+=gdrXt/tileX*2;
				if (sCode==SB_PAGEUP)
					scrollMotifs-=gdrXt/tileX*2*6;
				if (sCode==SB_PAGEDOWN)
					scrollMotifs+=gdrXt/tileX*2*6;
				if (sCode==SB_BOTTOM)
					scrollMotifs=32767;
				if (sCode==SB_TOP)
					scrollMotifs=0;
				if (sCode==SB_THUMBTRACK || sCode==SB_THUMBPOSITION)			{
					scrollMotifs=nPos;
					if (scrollMotifs%tileY>=tileY/2)
						scrollMotifs++;
				}

				SetScrollPos(hScroll3,SB_CTL,scrollMotifs,TRUE);

				//Remet la position dans la gamme possible
/*				if (scrollMotifs>tileY*((taille-blocBase)/(128/tileX)+1)-gdrY)
					scrollMotifs=tileY*((taille-blocBase)/(128/tileX)+1)-gdrY;*/
				if (scrollMotifs>tileY*((taille-blocBase)/(gdrXt/tileX)+2-gdrY/(tileY*zoom)))
					scrollMotifs=(int)(tileY*((taille-blocBase)/(gdrXt/tileX)+2-gdrY/(tileY*zoom)));
				if (scrollMotifs<0)
					scrollMotifs=0;
			}
			else		{
vscroll:
				if (selMap || selCopie)
					break;
				//Vérifie ce qu'il s'est passé et modifie la variable en fonction de ça
				if (sCode==SB_LINEUP)
					scrollY-=(int)(32.0/parallaxeY);
				if (sCode==SB_LINEDOWN)
					scrollY+=(int)(32.0/parallaxeY);
				if (sCode==SB_PAGEUP)
					scrollY-=(int)(192.0/parallaxeY);
				if (sCode==SB_PAGEDOWN)
					scrollY+=(int)(192.0/parallaxeY);
				if (sCode==SB_BOTTOM)
					scrollY=32767;
				if (sCode==SB_TOP)
					scrollY=0;
				if (sCode==SB_THUMBTRACK || sCode==SB_THUMBPOSITION)
					scrollY=nPos-(nPos%tileY);
				if (sCode!=SB_THUMBTRACK)
					SetScrollPos(hScroll1,SB_CTL,scrollY,TRUE);

				ControleScrollY();
			}
			break;

		case WM_HSCROLL:
			sCode = (int) LOWORD(wParam); // scroll bar value 
			nPos = (short int) HIWORD(wParam);  // scroll box position 

			if ((HWND) lParam==hScroll3)		{
			}
			else		{
hscroll:
				if (selMap || selCopie)
					break;
				//Vérifie ce qu'il s'est passé et modifie la variable en fonction de ça
				if (sCode==SB_LINEUP)
					scrollX-=(int)(32/parallaxeX);
				if (sCode==SB_LINEDOWN)
					scrollX+=(int)(32/parallaxeX);
				if (sCode==SB_PAGEUP)
					scrollX-=(int)(192/parallaxeX);
				if (sCode==SB_PAGEDOWN)
					scrollX+=(int)(192/parallaxeX);
				if (sCode==SB_BOTTOM)
					scrollX=32767;
				if (sCode==SB_TOP)
					scrollX=0;
				if (sCode==SB_THUMBTRACK || sCode==SB_THUMBPOSITION)
					scrollX=nPos-(nPos%tileX);
				if (sCode!=SB_THUMBTRACK)
					SetScrollPos(hScroll2,SB_CTL,scrollX,TRUE);

				ControleScrollX();
			}
			break;

		//Changer de map, wParam = n° de map
		case UM_CHANGEMAP:
			i = wParam+MAX_FONDS*2;
			//Enlever pour mettre à jour correctement
//			fondActif = wParam;
			goto choisitMap;

		case WM_COMMAND:

			switch(LOWORD(wParam))		{
				case IDC_LIGNE:
					if (HIWORD(wParam)==STN_CLICKED)			{
						GetCursorPos(&pSizingPos);
						SetCapture(hDlg);
						bSizingTileset=1;
					}
					break;
				case IDM_OPTIONS:
					goto showOptions;

				case IDM_ENTER:
					//Edite les attributs des objets sélectionnés
					if (gblTypeMap == TYPE_LISTE && (listeSelection != -1 || lstSelMulNbre>0))			{
						if (DialogBox(hInst,(LPCTSTR)IDD_ATTRIBUTS,hDlg,(DLGPROC)DlgAttributs)==IDOK)
							SauveAnnuler();
					}
					break;

				case IDM_COUPER:
				case IDM_COPIER:
					if (params[fondActif].gblTypeMap==TYPE_LISTE)		{
						if ((listeSelection!=-1 || lstSelMulNbre) && params[fondActif].gblSpriteListe.nbSprites>0)		{
							if (!lstCopyBuf.sd)				{
								lstCopyBuf.sd=(SPRITE_DEF*)malloc(MAX_LST_SEL_MUL*params[fondActif].gblSpriteListe.sizeofSD);
								lstCopyBuf.sizeofSD=params[fondActif].gblSpriteListe.sizeofSD;
							}
							if (lstSelMulNbre)		{
								for (i=0;i<lstSelMulNbre;i++)
									memcpy(_SD(lstCopyBuf,i),_SD(params[fondActif].gblSpriteListe,lstSelMulListe[i]),params[fondActif].gblSpriteListe.sizeofSD);
								lstCopyBuf.nbSprites=lstSelMulNbre;
							}
							else		{
								memcpy(_SD(lstCopyBuf,0),_SD(params[fondActif].gblSpriteListe,listeSelection),params[fondActif].gblSpriteListe.sizeofSD);
								lstCopyBuf.nbSprites=1;
							}
						}
					}
					if (LOWORD(wParam)==IDM_COPIER)				//S'il faut couper, on continue plus bas, car couper c'est copier + effacer
						break;
				case IDM_EFFACER:
					if ((listeSelection!=-1 || lstSelMulNbre) && params[fondActif].gblSpriteListe.nbSprites>0)		{
						if (lstSelMulNbre)		{
							int echange, tampon;
							//Tri décroissant
							do	{
								echange=0;
								for (i=0;i<lstSelMulNbre-1;i++)		{
									if (lstSelMulListe[i+1]>lstSelMulListe[i])		{
										echange=1;
										tampon=lstSelMulListe[i];
										lstSelMulListe[i]=lstSelMulListe[i+1];
										lstSelMulListe[i+1]=tampon;
									}
								}
							} while (echange);
							//Sans le tri, les éléments se marchent dessus (le 3 devient 2 après avoir été effacé)
							for (i=0;i<lstSelMulNbre;i++)
								EffaceElementListe(fondActif, lstSelMulListe[i]);
						}
						else
							EffaceElementListe(fondActif, listeSelection);
						lstSelMulNbre=0;
						listeSelection=-1;
						SauveAnnuler();
					}
					break;
				case IDM_MOINS:
					if (params[fondActif].grilleX>1)
						params[fondActif].grilleX/=2;
					if (params[fondActif].grilleY>1)
						params[fondActif].grilleY/=2;
					Console_Print("Grille crampon: %ix%i",params[fondActif].grilleX,params[fondActif].grilleY);
					break;
				case IDM_PLUS:
					if (params[fondActif].grilleX<64)
						params[fondActif].grilleX*=2;
					if (params[fondActif].grilleY<64)
						params[fondActif].grilleY*=2;
					Console_Print("Grille crampon: %ix%i",params[fondActif].grilleX,params[fondActif].grilleY);
					break;
				case IDM_COLLER:
					if (params[fondActif].gblTypeMap==TYPE_LISTE)		{
						int xMin=0x7fffffff, yMin=0x7fffffff;
						if (lstCopyBuf.nbSprites>0)		{
							//Trouver le x/yMin pour coller au sommet de l'écran
							for (i=0;i<lstCopyBuf.nbSprites;i++)		{
								if (_SD(lstCopyBuf,i)->x<xMin)
									xMin=_SD(lstCopyBuf,i)->x;
								if (_SD(lstCopyBuf,i)->y<yMin)
									yMin=_SD(lstCopyBuf,i)->y;
							}
							lstSelMulNbre=0;
							//On colle à 8 pixels du sommet/gauche de l'écran
//							xMin-=8, yMin-=8;
							for (i=0;i<lstCopyBuf.nbSprites;i++)		{
								if (params[fondActif].gblSpriteListe.nbSprites>=NB_MAX_ELE_LISTE)			{
									MessageBox(gblHEdit, "Trop d'éléments, veuillez allonger la liste dans les options", elements[fondActif].nom_court, MB_ICONEXCLAMATION);
									break;
								}
								memcpy(_SD(params[fondActif].gblSpriteListe,params[fondActif].gblSpriteListe.nbSprites),
									_SD(lstCopyBuf,i),params[fondActif].gblSpriteListe.sizeofSD);
								_SD(params[fondActif].gblSpriteListe,params[fondActif].gblSpriteListe.nbSprites)->x+=-xMin+(int)(scrollX*params[fondActif].parallaxeX);
								_SD(params[fondActif].gblSpriteListe,params[fondActif].gblSpriteListe.nbSprites)->y+=-yMin+(int)(scrollY*params[fondActif].parallaxeY);
								//Les sélectionne par défaut
								lstSelMulAjObjet(params[fondActif].gblSpriteListe.nbSprites++,0);
							}
							SauveAnnuler();
						}
					}
					else	{
						goto coller;
					}
					break;

				case IDM_DROITE:
					sCode=SB_LINEDOWN;
					goto hscroll;
				case IDM_GAUCHE:
					sCode=SB_LINEUP;
					goto hscroll;
				case IDM_HAUT:
					sCode=SB_LINEUP;
					goto vscroll;
				case IDM_BAS:
					sCode=SB_LINEDOWN;
					goto vscroll;

				case IDM_AIDE:
					sprintf(str, "%s\\aide.htm", cInitialDir);
					ShellExecute(hDlg, NULL, str, NULL, NULL, SW_SHOWNORMAL);
//					WinExec("explorer aide.htm",1);
					break;
				case IDM_AIDEPERSO:
					AidePerso();
					break;

				case IDM_EXECUTER:
					DialogBox(hInst,(LPCTSTR)IDD_EXECUTER,hDlg,(DLGPROC)DlgExec);
					break;
				case IDM_ANNULER:
					lParam=(LPARAM)hBtAnnuler;
					break;
				case IDM_REFAIRE:
					lParam=(WPARAM)hBtRefaire;
					break;
				case IDM_SAUVER:
					EcritMap();
					EcritFichierConfigMap();
					SetFocus(hDlg);
					break;
				case IDM_AJFOND:
					goto ajouteFond;
				case IDM_HEXA:
					goto switchModeHexa;
				case IDM_FOND1:
					i=1+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND2:
					i=2+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND3:
					i=3+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND4:
					i=4+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND5:
					i=5+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND6:
					i=6+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND7:
					i=7+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND8:
					i=8+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND9:
					i=9+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_FOND10:
					i=10+MAX_FONDS*2-1;
					goto choisitMap;
				case IDM_SPECIMEN:
					goto voitSpecimen;
			}

			if (MODE_TEXTE)		{
				if ((HWND)lParam==GetDlgItem(hDlg,IDC_EDIT1))		{
					unsigned long maxMotif=GetMaxMotif(ModeTexte);
					GetDlgItemText(hDlg,IDC_EDIT1,str,100);
					i=atox(str)&maxMotif;
					motifChoisi=i;
					Console_Print("Motif: %i (%04x)",motifChoisi,motifChoisi);
				}
			}
			if ((HWND)lParam==hBtOpts)
				goto apparaitMenu;
//				DialogBox(hInst,(LPCTSTR)IDD_OPTIONSEDITEUR,hDlg,(DLGPROC)ProcOptions);
			else if ((HWND)lParam==hBtOk)			{
coller:
				if (CopieX>1 || CopieY>1)		{
					selMap=1;
					ColleBlocs(DebutX,DebutY,FinX,FinY,0);
					selMap=0;
				}
			}
			else if ((HWND)lParam==hBtAnnuler)		{
				lstSelMulNbre=0, listeSelection=-1;
				Annuler();
			}
			else if ((HWND)lParam==hBtRefaire)			{
				lstSelMulNbre=0, listeSelection=-1;
				Refaire();
			}
			else if (LOWORD(wParam)==IDCANCEL)		{
				int ancFondActif, dejaDemande[MAX_FONDS], tmp, sauve;
				ancFondActif=fondActif;
				sauve = FALSE;
				memset(dejaDemande,0,sizeof(dejaDemande));
				for (j=0;j<nMaps;j++)		{
					ub=&undos[j];
					if (!dejaDemande[j] && (ub->nOperations!=ub->dernierEnreg || ub->modifie))		{
//						EcritParam(&params[j]);
						sprintf(str,"Voulez-vous enregistrer les modifications apportées à %s?",SansLeSlash(ele_fond[j]->nom_court));
						i=MessageBox(hDlg,str,"Question",MB_ICONINFORMATION|MB_YESNOCANCEL);
						tmp=TRUE;
					}
					else	{
						i=IDNO;
						tmp=FALSE;
					}
					AffTravail();
					if (i==IDCANCEL)		{
						fondActif=ancFondActif;
						return FALSE;
					}
					if (i==IDYES)		{
						fondActif=j;
						sauve = TRUE;
						EcritMap();
					}

					if (tmp)		{
						//Ne pas demander plusieurs fois pour les maps liées
						for (tmp=0;liens[fondActif][tmp]!=LIEN_INVALIDE;tmp++)
							dejaDemande[liens[fondActif][tmp]]=1;
					}

					if (ub->undoBuffer)		{
						free(ub->undoBuffer);
						ub->undoBuffer = NULL;
					}

//					if (i==IDNO)
//						continue;
				}
				DestroyWindow(gblHSpec);
				if (sauve || sauverParamsMapsAutomatiquement)
					EcritFichierConfigMap();
//				EndDialog(gblHSpec, -1);
				for (i=0;i<nMaps;i++)		{
					free(params[i].gblMap);
					free(params[i].gblPal);
					free(params[i].gblMotifs);
				}
				if (maxSizeofSD > 0)		{
					for (i=0;i<MAXBLOCS;i++)		{
						free(listeCopie[i].sd);
					}
				}
				editeurOuvert=0;
				if (fenBits)		{
					EndDialog(hDlgBits, IDCANCEL);
					fenBits=0;
				}
				gblHEdit=NULL;
				Dealloc_Bits();
				DestroyWindow(hDlg);
				PostQuitMessage(0);
				return TRUE;
			}
			break;
	}
    return FALSE;
}

void CreeBarresDefil(HWND hDlg)		{
	SCROLLINFO si;
	si.cbSize=sizeof(si);
	si.fMask=SIF_PAGE|SIF_POS|SIF_RANGE;
	si.nMin=0;
	DestroyWindow(hScroll1);
	DestroyWindow(hScroll2);
	DestroyWindow(hScroll3);
	hScroll1=hScroll2=hScroll3=0;
	RedrawWindow(hDlg,NULL,NULL,RDW_INVALIDATE|RDW_ERASE);

	ControleScrollX();
	ControleScrollY();

	si.nMax=(int)((tailleY)/parallaxeY);
	si.nPage=(int)(gdrYz/parallaxeY);
	if (si.nPage%tileY)
		si.nMax = si.nMax + tileY;

//	if ((signed int)(scrollY+(si.nPage/parallaxeY))>(signed)si.nMax)
	if ((signed int)(scrollY+si.nPage)>(signed)si.nMax)
//		scrollY=(signed)si.nMax-(signed int)(si.nPage/parallaxeY);
		scrollY=(signed)si.nMax-(signed int)(si.nPage);
	if (scrollY<0)
		scrollY=0;

	if (tailleY>gdrYz)		{
		si.nPos=scrollY;
		hScroll1=CreateWindow ("ScrollBar", "",WS_CHILD | WS_VISIBLE | SBS_VERT,
			BASEDIT_X+gdrX,BASEDIT_Y,16,gdrY, hDlg, NULL, hInst, NULL);
		SetScrollInfo(hScroll1,SB_CTL,&si,1);
	}

	si.nMax=(int)((tailleX)/parallaxeX);
	si.nPage=(int)(gdrXz/parallaxeX);
	if (si.nPage%tileX)
		si.nMax = si.nMax + tileX;

	if ((signed int)(scrollX+si.nPage)>(signed)si.nMax)		{
		scrollX=(signed)si.nMax-(signed int)(si.nPage);
	}
	if (scrollX<0)
		scrollX=0;

	if (tailleX>gdrXz)		{
		si.nPos=scrollX;
		hScroll2=CreateWindow ("ScrollBar", "",WS_CHILD | WS_VISIBLE | SBS_HORZ,
			BASEDIT_X,BASEDIT_Y+gdrY,gdrX,16, hDlg, NULL, hInst, NULL);
		SetScrollInfo(hScroll2,SB_CTL,&si,1);
	}

//	Debug("%i %i",(int)(tileY*zoom*((taille-blocBase)/(gdrXt/tileX)+1)),gdrY);
	if (tileY*((taille-blocBase)/(gdrXt/tileX)+1)>(int)(gdrY/zoom))		{
		si.nPos=scrollMotifs;
		si.nMax=tileY*((taille-blocBase)/(gdrXt/tileX)+1);
		si.nPage=(int)(gdrY/zoom);
		if (si.nPage%tileY)
			si.nMax = si.nMax + tileY;
		hScroll3=CreateWindow ("ScrollBar", "",WS_CHILD | WS_VISIBLE | SBS_VERT,
			BASEDIT_X+gdrX+44+gdrXtc,BASEDIT_Y,16,gdrY, hDlg, NULL, hInst, NULL);
		SetScrollInfo(hScroll3,SB_CTL,&si,1);
	}
//	scrollX=0, scrollY=0;
	scrollMotifs=0;
}


void *BufferActif()		{
	int i;
	if (profondeurSel>1)		{
		for (i=0;i<profondeurSel;i++)
			if (liens[selectionBase][i]==fondActif && CopieX>0 && CopieY>0)		{
				if (blocCopieOk[i])
					return blocCopie+1024*i;
				else
					//Le bloc copié n'existe pas; par précaution, renvoie un bloc contenant des zéros
					return blocCopie+1024*MAXBLOCS;
			}
	}
	return blocCopie;
}

//Positions relatives
void DessineEcran(int posX, int posY)		{
	int i,j,ii,x,y, ptX,ptY,pX,pY;
	int ticks=GetTickCount()%1024;
	int v, tmp, temps, hauteur, largeur;
	MAP *map=gblMap;
	unsigned long *motifs=gblMotifs;
	unsigned char *palette=gblPal;
	static int aposX, aposY, fixe=0, derTickCount=0;
	char str1[1000], str2[1000];
	MAP (*bloc)[1024];
	PARAM p;

	p.gblMap=map;
	p.gblMotifs=motifs;
	p.gblPal=palette;
	p.b16coul=b16coul;

	bloc=(MAP (*)[1024])BufferActif();

//	posX-=BASEDIT_X;
//	posY-=BASEDIT_Y;
	i=posX/tileX;
	j=posY/tileY;

	ticks/=2;
	if (ticks>=256)
		v=ticks%256;
	else
		v=255-ticks%256;

	if (v==0)
		v=1;

	ii=GetTickCount();
	temps=(ii-derTickCount)/10;
	derTickCount+=temps*10;

	if (posX>=0 && posX<gdrXz && posY>=0&& posY<gdrYz)		{
		if (!selMap && !selCopie)		{
			if (i*tileX>=tailleX || j*tileY>=tailleY)
				return;
			if (CopieX>0 && CopieY>0)
				ii=bloc[0][0]+blocBase;
			else
				ii=motifChoisi+blocBase;
			if (MODE_TEXTE)
				DessNombre(i*tileX,j*tileY,ii,RGB(255-v,0,v));
			else	{
				ii=VerifConditions(ii,fondActif, gfxmask);
				if ((ii&gbatilmask)<taille)		{
					for (y=0;y<tileY;y+=8)
						for (x=0;x<tileX;x+=8)		{
							if (emul_gba)
								DessineTileSansMasque(Bits3,i*tileX+x,j*tileY+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
							else
								TransSpritePalSansMasque(Bits3,i*tileX+x,j*tileY+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
						}
				}
			}
		}
		else if (selMap)	{
			ptX=(posX);
			ptY=(posY);
			pX=AbsToRelaX(posDepartAbsolueX);
			pY=AbsToRelaY(posDepartAbsolueY);

			if (ptX<pX)		{
				i=pX;
				pX=ptX;
				ptX=i;
			}
			if (ptY<pY)		{
				i=pY;
				pY=ptY;
				ptY=i;
			}

			//Pas forcément nécessaire
			if (ptX%tileX<0)
				ptX-=tileX;
			if (ptY%tileY<0)
				ptY-=tileY;
			//Nécessaire
			if (pX%tileX<0)
				pX-=tileX;
			if (pY%tileY<0)
				pY-=tileY;
			ptX/=tileX;
			ptY/=tileY;
			pX/=tileX;
			pY/=tileY;

			if (ptY>=tailleY/tileY || ptX>=tailleX/tileX)
				return;
			for (j=pY;j<=ptY;j++)			{
				for (i=pX;i<=ptX;i++)			{
					if (CopieX>0 && CopieY>0)
						ii=bloc[(j-pY)%CopieY][(i-pX)%CopieX]+blocBase;
					else
						ii=motifChoisi+blocBase;
					if (MODE_TEXTE)		{
						DessNombre(i*tileX,j*tileY,ii,RGB(255-v,0,v));
					}
					else	{
						ii=VerifConditions(ii,fondActif,gfxmask);
						if (ii<0)
							continue;
						if ((ii&gbatilmask)>=taille)
							continue;
						for (y=0;y<tileY;y+=8)
							for (x=0;x<tileX;x+=8)		{
								if (emul_gba)
									DessineTileSansMasque(Bits3,i*tileX+x,j*tileY+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
								else
									TransSpritePalSansMasque(Bits3,i*tileX+x,j*tileY+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
							}
					}
				}
			}
		}
		else if (selCopie)	{
			ptX=(posX)/tileX;
			ptY=(posY)/tileY;
			pX=AbsToRelaX(posDepartAbsolueX)/tileX;
			pY=AbsToRelaY(posDepartAbsolueY)/tileY;
/*			ArronditX(pX); ArronditY(pY);
			pX/=tileX, pY/=tileY;*/
			if (ptX<pX)		{
				i=pX;
				pX=ptX;
				ptX=i;
			}
			if (ptY<pY)		{
				i=pY;
				pY=ptY;
				ptY=i;
			}
			if (ptY>=tailleY/tileY || ptX>=tailleX/tileX)
				return;
			TransCadre(Bits3,pX*tileX,pY*tileY,tileX*(ptX-pX+1),tileY*(ptY-pY+1),RGB(0,0,255),v);
//			AdditionneCadre(pX*tileX,pY*tileY,tileX*(ptX-pX+1),tileY*(ptY-pY+1),RGB(0,0,v));
		}

		/*
			Code de gestion du petit popup qui apparaît lorsqu'on pointe la souris sur un bloc
		*/

		if (i==aposX && j==aposY)
			fixe+=temps;
		else		{
			if (!selMap && !selCopie)
				fixe=0;
		}

		aposX=i, aposY=j;

		if (popUpInfos && fixe>=tempsPopUp)	{
			SetBkMode(hdcEdit,TRANSPARENT);
			SelectObject(hdcEdit,hFonte);
			SetTextColor(hdcEdit,RGB(255,255,255));
			if (selMap && CopieX>0 && CopieY>0)
				sprintf(str1,"Taille: %ix%i",ptX-pX+1,ptY-pY+1);
			else if (selCopie || selMap)
				sprintf(str1,"Départ: %i,%i",(int)(pX+scrollX*parallaxeX/tileX),(int)(pY+scrollY*parallaxeY/tileY));
			else
				sprintf(str1,"Position: %i,%i",(int)(i+scrollX*parallaxeX/tileX),(int)(j+scrollY*parallaxeY/tileY));
			if (selMap && CopieX>0 && CopieY>0)
				sprintf(str2,"Motif: %ix%i",CopieX,CopieY);
			else if (selCopie || selMap)
				sprintf(str2,"Taille: %ix%i",ptX-pX+1,ptY-pY+1);
			else	{
				tmp=GblMap((int)(i+scrollX*parallaxeX/tileX),(int)(j+scrollY*parallaxeY/tileY));
				sprintf(str2,"Valeur: %i (%x)",tmp,tmp);
			}

			x=0;
			for (i=0;str1[i];i++)		{
				GetCharWidth32(hdcEdit,str1[i],str1[i],&tmp);
				x+=tmp;
			}
			largeur=x;
			x=0;
			for (i=0;str2[i];i++)		{
				GetCharWidth32(hdcEdit,str2[i],str2[i],&tmp);
				x+=tmp;
			}
			if (x>largeur)
				largeur=x;

			largeur+=10;

			x=posX+16;
			y=posY+16;
			//Calcule les dimensions
			hauteur=35;
			//Calcule le positionnement
			if (x+largeur>=gdrXz)
				x=posX-largeur;
			if (y+hauteur>=gdrYz)
				y=posY-hauteur;
			//Dessine la bulle
			TransRect(Bits3,x,y,largeur,hauteur,RGB(255,0,0),128);
			TransCadre(Bits3,x+1,y,largeur-2,hauteur-2,0,128);
			TextOut(hdcEdit,x+5,y+1,str1,strlen(str1));
			TextOut(hdcEdit,x+5,y+16,str2,strlen(str2));
		}
	}


//	TransSprite(i*tileX,j*tileY,8,8,,v);
}


LRESULT CALLBACK DlgProprietesFond(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i,j, m,n, x,y;
	MAP *ancMap;
	PARAM *p;
	int doitViderUndoBuffer=0;

	switch (message)
	{
		case WM_INITDIALOG:
			EcritParam(&params[gblNoFondProprietes]);
			sprintf(str,"%i",tailleX);
			SetDlgItemText(hDlg,IDC_EDIT1,str);
			sprintf(str,"%i",tailleY);
			SetDlgItemText(hDlg,IDC_EDIT2,str);
			sprintf(str,"%i",blocBase);
			SetDlgItemText(hDlg,IDC_EDIT3,str);
			sprintf(str,"0x%x",gfxmask);
			SetDlgItemText(hDlg,IDC_EDIT4,str);
			if (MODE_TEXTE)
				EnableWindow(GetDlgItem(hDlg,IDC_FMTTILES),FALSE);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:

			if (LOWORD(wParam) == IDOK) 
			{
				EcritParam(&params[gblNoFondProprietes]);
				tailleX*=tileX, tailleY*=tileY;
				GetDlgItemText(hDlg,IDC_EDIT1,str,sizeof(str));
				i=atoi(str);
				GetDlgItemText(hDlg,IDC_EDIT2,str,sizeof(str));
				j=atoi(str);
				GetDlgItemText(hDlg,IDC_EDIT3,str,sizeof(str));
				m=GetEntier(str);
				GetDlgItemText(hDlg,IDC_EDIT4,str,sizeof(str));
				x=GetEntier(str);
				if (x!=0)
					gfxmask=x;

				if (m!=blocBase && m>=0 && m<taille)		{
					undos[gblNoFondProprietes].modifie=TRUE;
					blocBase=m;
					motifChoisi=0;
				}
				else if (m>=taille)
					MessageBox(gblHEdit,"Le numéro de motif choisi est plus grand ou égal au nombre total de motifs...","Erreur",MB_ICONERROR);

				if ((i!=tailleX/tileX || j!=tailleY/tileY) && i>0 && j>0)		{
					if (gblTypeMap==TYPE_MAP)			{
						ancMap=gblMap;
						gblMap=(MAP*)malloc(i*j*sizeof(MAP));
						if (!gblMap)	{
							i=tailleX;
							j=tailleY;
							gblMap=(MAP*)malloc(i*j*sizeof(MAP));
							MessageBox(hDlg,"Vous n'exagéreriez pas un peu sur les dimensions là non? Si vous aviez des téraoctets de mémoire vive ça irait mais là je doute que ce soit le cas! :p","Argh!",MB_ICONERROR);
							return FALSE;
						}
						memset(gblMap,0,i*j*sizeof(MAP));
						m=min(tailleX/tileX,i);
						n=min(tailleY/tileY,j);
						p=&params[gblNoFondProprietes];
						for (y=0;y<n;y++)
							for (x=0;x<m;x++)	{
								gblMap[i*y+x]=AccesMap(p,x,y);
							}
						free(p->gblMap);

						doitViderUndoBuffer=1;
					}

					tailleX=i*tileX;
					tailleY=j*tileY;
					tamX=tailleX/tileX;
					tamY=tailleY/tileY;
				}

				//LitParam DOIT avoir des dimensions non-multipliées par celles des blocs.
				if (fondActif == gblNoFondProprietes)
					CreeBarresDefil(gblHEdit);
				tailleX/=tileX;
				tailleY/=tileY;
				LitParam(&params[gblNoFondProprietes]);
				if (doitViderUndoBuffer)
					VideUndoBuffer();
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}

			break;
	}

    return FALSE;
}


// "Handler" pour la boîte de dialogue
LRESULT CALLBACK ProcOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	HWND hListe;
	int i;
	static lastFond;

	switch (message)
	{
		case WM_INITDIALOG:
			lastFond = fondActif;
			hListe=GetDlgItem(hDlg,IDC_LIST1);
			SendMessage(hListe,LB_RESETCONTENT,0,0);
			for (i=0;i<nMaps;i++)		{
				SendMessage(hListe,LB_ADDSTRING,0,(LPARAM)ele_fond[i]->nom_court);
			}
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:
			//Message de notification
			if (LOWORD(wParam) == IDC_LIST1)
			{
				if (HIWORD(wParam) == LBN_SELCHANGE)		{
					i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
					if (i!=LB_ERR)		{
						SendMessage(gblHEdit, UM_CHANGEMAP, i, 0);
					}
				}
			}


			if (LOWORD(wParam) == IDOK) 
			{
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				SendMessage(gblHEdit, UM_CHANGEMAP, lastFond, 0);
				EndDialog(hDlg, -1);
				return TRUE;
			}
			else if (LOWORD(wParam) == IDC_FMTTILES)
			{
				EndDialog(GetParent(hDlg), IDC_FMTTILES);
				return TRUE;
			}
			else if (LOWORD(wParam) == IDC_OPTIONSFOND)
			{
				EndDialog(GetParent(hDlg), IDC_OPTIONSFOND);
				return TRUE;
			}

			break;
	}

    return FALSE;
}


// "Handler" pour la boîte de dialogue
LRESULT CALLBACK ProcOptions2(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static CBoutonCouleur cBtClr;
	switch (message)
	{
		case WM_INITDIALOG:
			SendDlgItemMessage(hDlg,IDC_CHECK3,BM_SETCHECK,grille?BST_CHECKED:BST_UNCHECKED,0);
			cBtClr.OnInit(GetDlgItem(hDlg, IDC_BOUTONCOULEUR));
			cBtClr.cc.rgbResult = couleurGrille;
			sprintf(str,"%i",transGrille);
			SetDlgItemText(hDlg, IDC_EDIT11, str);

			sprintf(str,"%i",AlphaPremPlan);
			SetDlgItemText(hDlg, IDC_EDIT6, str);
			sprintf(str,"%i",gfxAlphaFonds);
			SetDlgItemText(hDlg, IDC_EDIT9, str);
			sprintf(str,"%i",hexAlphaFonds);
			SetDlgItemText(hDlg, IDC_EDIT10, str);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_DRAWITEM:
			if (cBtClr.OnDrawItem(hDlg, lParam))
				return TRUE;
			break;

		case WM_SETCURSOR:
			cBtClr.OnSetCursor(hDlg, wParam);
			break;

		case WM_COMMAND:

			if (LOWORD(wParam) == IDC_BOUTONCOULEUR)		{
				cBtClr.OnClick(hDlg);
			}

			if (LOWORD(wParam) == IDOK) 
			{
				if (SendDlgItemMessage(hDlg,IDC_CHECK3,BM_GETCHECK,0,0)==BST_CHECKED)
					grille=1;
				else
					grille=0;

				couleurGrille = cBtClr.cc.rgbResult;

				GetDlgItemText(hDlg,IDC_EDIT11,str,sizeof(str));
				if (EstUnNombre(str))
					transGrille=GetEntier(str);
				if (transGrille>255)
					transGrille=255;

				GetDlgItemText(hDlg,IDC_EDIT6,str,sizeof(str));
				if (EstUnNombre(str))
					AlphaPremPlan=GetEntier(str);
				GetDlgItemText(hDlg,IDC_EDIT9,str,sizeof(str));
				if (EstUnNombre(str))
					gfxAlphaFonds=GetEntier(str);
				GetDlgItemText(hDlg,IDC_EDIT10,str,sizeof(str));
				if (EstUnNombre(str))
					hexAlphaFonds=GetEntier(str);
				if (AlphaPremPlan>255)
					AlphaPremPlan=255;
				if (gfxAlphaFonds>255)
					gfxAlphaFonds=255;
				if (hexAlphaFonds>255)
					hexAlphaFonds=255;

				CreeBarresDefil(gblHEdit);
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

LRESULT CALLBACK ProcOptions3(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	double nvZoom;

	switch (message)
	{
		case WM_INITDIALOG:
			sprintf(str,"%f",zoom);
			SetDlgItemText(hDlg, IDC_EDIT5, str);
			SendDlgItemMessage(hDlg,IDC_CHECK2,BM_SETCHECK,zoomPrecis?BST_CHECKED:BST_UNCHECKED,0);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:

			if (LOWORD(wParam) == IDOK) 
			{
				GetDlgItemText(hDlg,IDC_EDIT5,str,sizeof(str));
				nvZoom=atof(str);
				if (nvZoom>0)		{
					zoom=nvZoom;
					majRequise=1;
				}

				if (SendDlgItemMessage(hDlg,IDC_CHECK2,BM_GETCHECK,0,0)==BST_CHECKED)
					zoomPrecis=1;
				else
					zoomPrecis=0;

				CreeBarresDefil(gblHEdit);
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK DlgProprietesFondGeneral(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	char str[1000];
	double fTemp, ancParaX;
	int nTemp;

	switch (message)
	{
		case WM_INITDIALOG:
			//Parallaxes
			sprintf(str,"%f%%", (float)params[gblNoFondProprietes].parallaxeX*100.0);
			//Max 3 décimales, sans 0
			Float_VerifieDecimalesMax(str, 3);
			Float_TronqueZeros(str);
			SetDlgItemText(hDlg,IDC_EDIT1,str);
			sprintf(str,"%f%%", (float)params[gblNoFondProprietes].parallaxeY*100.0);
			Float_VerifieDecimalesMax(str, 3);
			Float_TronqueZeros(str);
			SetDlgItemText(hDlg,IDC_EDIT2,str);

			//Grille
			sprintf(str,"%i", (int)params[gblNoFondProprietes].grilleX);
			SetDlgItemText(hDlg,IDC_EDIT3,str);
			sprintf(str,"%i", (int)params[gblNoFondProprietes].grilleY);
			SetDlgItemText(hDlg,IDC_EDIT4,str);

			SendDlgItemMessage(hDlg,IDC_CHECK1,BM_SETCHECK,fond_actif[gblNoFondProprietes]?BST_CHECKED:BST_UNCHECKED,0);
			SendDlgItemMessage(hDlg,IDC_CHECK2,BM_SETCHECK,fond_a_sauver[gblNoFondProprietes]?BST_UNCHECKED:BST_CHECKED,0);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK) 
			{
				int dejaProposeDefilement=0, i;
				//Récupère le parallaxe
				ancParaX = params[gblNoFondProprietes].parallaxeX;
				GetDlgItemText(hDlg,IDC_EDIT1,str,sizeof(str));
				fTemp = (float)atof(str)/100.0;
				if (fTemp > 1.0)		{
					if (MessageBox(hDlg, "Les valeurs de défilement parallaxe ne devraient pas être supérieures à 100%, au lieu par exemple de mettre 200% pour le plan A et 100% pour le plan B, mettez 100% pour le plan A et 50% pour le plan B...\nToutefois, GBA Graphics peut le faire pour vous. Est-ce ce que vous désirez?", "Erreur", MB_ICONINFORMATION|MB_YESNO) == IDYES)		{
						dejaProposeDefilement=1;
						for (i=0;i<nMaps;i++)
							params[i].parallaxeX /= fTemp;
						fTemp = 1.0;
					}
					else
						break;
				}
				if (fTemp != 0.0 && fTemp != params[gblNoFondProprietes].parallaxeX)
					params[gblNoFondProprietes].parallaxeX = fTemp;
				GetDlgItemText(hDlg,IDC_EDIT2,str,sizeof(str));
				fTemp = (float)atof(str)/100.0;
				if (fTemp > 1.0)		{
					if (!dejaProposeDefilement)
						i = MessageBox(hDlg, "Les valeurs de défilement parallaxe ne devraient pas être supérieures à 100%, au lieu par exemple de mettre 200% pour le plan A et 100% pour le plan B, mettez 100% pour le plan A et 50% pour le plan B...\nToutefois, GBA Graphics peut le faire pour vous. Est-ce ce que vous désirez?", "Erreur", MB_ICONINFORMATION|MB_YESNO);
					else
						i=IDYES;
					if (i==IDYES)		{
						for (i=0;i<nMaps;i++)
							params[i].parallaxeY /= fTemp;
						fTemp = 1.0;
					}
					else	{
						params[gblNoFondProprietes].parallaxeX = ancParaX;
						break;
					}
				}
				if (fTemp != 0.0 && fTemp != params[gblNoFondProprietes].parallaxeY)
					params[gblNoFondProprietes].parallaxeY = fTemp;

				//Récupère la grille
				GetDlgItemText(hDlg,IDC_EDIT3,str,sizeof(str));
				nTemp = atoi(str);
				if (nTemp != 0)
					params[gblNoFondProprietes].grilleX = nTemp;
				GetDlgItemText(hDlg,IDC_EDIT4,str,sizeof(str));
				nTemp = atoi(str);
				if (nTemp != 0)
					params[gblNoFondProprietes].grilleY = nTemp;

				if (SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_CHECKED)
					fond_actif[gblNoFondProprietes]=1;
				else
					fond_actif[gblNoFondProprietes]=0;

				if (SendDlgItemMessage(hDlg,IDC_CHECK2,BM_GETCHECK,0,0)==BST_CHECKED)
					fond_a_sauver[gblNoFondProprietes]=0;
				else
					fond_a_sauver[gblNoFondProprietes]=1;

				CreeBarresDefil(gblHEdit);
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK DlgProprietesFondAvance(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			Dialog_SetBool(hDlg, IDC_CHECK1, params[gblNoFondProprietes].emul_gba);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK) 
			{
				params[gblNoFondProprietes].emul_gba = Dialog_GetBool(hDlg, IDC_CHECK1);
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK DlgProprietesFondConditions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static S_CONDITION tblConditions[MAX_COND];
	static S_CONDITION cd;
	BOOL bCorrect;
	static int nConditions;
	int nTemp;
	int i, j;
	HWND hListe;
	char str[1000];

	switch (message)
	{
		case WM_INITDIALOG:
			nConditions = 0;
			memset(tblConditions, 0, sizeof(tblConditions));
			//Copie depuis le tableau standard des conditions
			memcpy(tblConditions, s_conditions[gblNoFondProprietes], sizeof(tblConditions));
			nConditions = n_conditions[gblNoFondProprietes];

affConditions:
			hListe=GetDlgItem(hDlg,IDC_LIST1);
			SendMessage(hListe,LB_RESETCONTENT,0,0);
			for (i=0;i<nConditions;i++)			{
				sprintf(str, "%x-%x -> %x %s", tblConditions[i].debut, tblConditions[i].fin, tblConditions[i].debut-tblConditions[i].difference, tblConditions[i].exact?"(exact)":"");
				SendMessage(hListe,LB_ADDSTRING,0,(LPARAM)str);
			}
			EnableWindow(GetDlgItem(hDlg, IDC_BUTTON2), FALSE);
			EnableWindow(GetDlgItem(hDlg, IDC_BUTTON3), FALSE);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_VKEYTOITEM:
			i = LOWORD(wParam);      // virtual-key code
			if ((HWND)lParam == GetDlgItem(hDlg, IDC_LIST1))			{
				if (i==VK_DELETE)
					goto del;
			}
			break;

		case WM_COMMAND:
			//Message de notification
			if (LOWORD(wParam) == IDC_LIST1)
			{
				if (HIWORD(wParam) == LBN_SELCHANGE)		{
					i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
					if (i==LB_ERR)		{
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON2), FALSE);
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON3), FALSE);
					}
					else		{
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON2), TRUE);
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON3), TRUE);
						sprintf(str, "0x%x", tblConditions[i].debut);
						SetDlgItemText(hDlg, IDC_EDIT1, str);
						sprintf(str, "0x%x", tblConditions[i].fin);
						SetDlgItemText(hDlg, IDC_EDIT2, str);
						sprintf(str, "0x%x", tblConditions[i].debut-tblConditions[i].difference);
						SetDlgItemText(hDlg, IDC_EDIT3, str);
						SendDlgItemMessage(hDlg,IDC_CHECK1,BM_SETCHECK,tblConditions[i].exact?BST_CHECKED:BST_UNCHECKED,0);
					}
				}
			}

			//Supprimer
			if (LOWORD(wParam) == IDC_BUTTON3)
			{
del:
				i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
				if (i!=LB_ERR)			{
					memcpy(&tblConditions[i], &tblConditions[i+1], sizeof(tblConditions)-sizeof(tblConditions[0])*(i+1));
					nConditions--;
					goto affConditions;
				}
			}

			//Ajouter / modifier
			if (LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDC_BUTTON2)
			{
				memset(&cd, 0, sizeof(cd));
				bCorrect = TRUE;
				//Récupère les paramètres de la condition
				GetDlgItemText(hDlg,IDC_EDIT1,str,sizeof(str));
				if (strlen(str) == 0)
					bCorrect = FALSE;
				nTemp = GetEntier(str);
				cd.debut = nTemp;
				GetDlgItemText(hDlg,IDC_EDIT2,str,sizeof(str));
				if (strlen(str) == 0)
					nTemp = cd.debut;
				else
					nTemp = GetEntier(str);
				cd.fin = nTemp;

				//Swapping si les paramètres sont invalides
				if (cd.debut > cd.fin)			{
					i = cd.fin;
					cd.fin = cd.debut;
					cd.debut = i;
				}

				GetDlgItemText(hDlg,IDC_EDIT3,str,sizeof(str));
				if (strlen(str) == 0)
					bCorrect = FALSE;
				nTemp = GetEntier(str);
				cd.difference = cd.debut-nTemp;

				if (SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_CHECKED)
					cd.exact=1;
				else
					cd.exact=0;
				
				if (bCorrect)			{
					//Existe déjà?
					for (j=0;j<nConditions;j++)		{
						if (!memcmp(&tblConditions[j], &cd, sizeof(cd)))
							break;
					}
					if (j>=nConditions)		{
						if (LOWORD(wParam) == IDC_BUTTON1)			{
							if (nConditions<MAX_COND)			{
								memcpy(&tblConditions[nConditions], &cd, sizeof(cd));
								nConditions++;
								goto affConditions;
							}
						}
						else if (LOWORD(wParam) == IDC_BUTTON2)			{
							i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
							if (i!=LB_ERR)			{
								memcpy(&tblConditions[i], &cd, sizeof(cd));
								goto affConditions;
							}
						}
					}
				}
			}

			if (LOWORD(wParam) == IDOK)
			{
				//Copie sur le tableau standard des conditions
				memcpy(s_conditions[gblNoFondProprietes], tblConditions, sizeof(tblConditions));
				n_conditions[gblNoFondProprietes] = nConditions;
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

//Variables utilisées
/*bitsMasqueZero=1;
char (*nomsBits)[8][TAILLE_MAX_CHAINES];
char (*bitsActives)[8];
HWND hDlgBits;*/

LRESULT CALLBACK DlgProprietesFondBits(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static char tempNomsBits[NOMBRE_BITS][TAILLE_MAX_CHAINES];
	static char tempBitsActives[NOMBRE_BITS];
	HWND hListe;
	int i;

	switch (message)
	{
		case WM_INITDIALOG:
			Alloc_Bits();
			//Copie depuis le tableau standard des bits
			memcpy(tempNomsBits, nomsBits[gblNoFondProprietes], sizeof(tempNomsBits));
			memcpy(tempBitsActives, bitsActives[gblNoFondProprietes], sizeof(tempBitsActives));

affBits:
			hListe=GetDlgItem(hDlg,IDC_LIST1);
			SendMessage(hListe,LB_RESETCONTENT,0,0);
			for (i=0;i<NOMBRE_BITS;i++)			{
				sprintf(str, "%i: %s (%s)", 15-i, tempNomsBits[i], tempBitsActives[i]?"activé":"désactivé");
				SendMessage(hListe,LB_ADDSTRING,0,(LPARAM)str);
			}
			EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), FALSE);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

		case WM_COMMAND:
			//Message de notification
			if (LOWORD(wParam) == IDC_LIST1)
			{
				if (HIWORD(wParam) == LBN_SELCHANGE)		{
					i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
					if (i==LB_ERR)		{
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), FALSE);
					}
					else		{
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), TRUE);
						SetDlgItemText(hDlg, IDC_EDIT1, tempNomsBits[i]);
						SendDlgItemMessage(hDlg,IDC_CHECK1,BM_SETCHECK,tempBitsActives[i]?BST_CHECKED:BST_UNCHECKED,0);
					}
				}
			}

			if (LOWORD(wParam) == IDC_BUTTON1)			{
					i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
					if (i!=LB_ERR)		{
						GetDlgItemText(hDlg, IDC_EDIT1, str, sizeof(str));
						strcpy(tempNomsBits[i], str);
						if (SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_CHECKED)
							tempBitsActives[i]=1;
						else
							tempBitsActives[i]=0;
						goto affBits;
					}
			}

			if (LOWORD(wParam) == IDOK)
			{
				//Copie sur le tableau standard des bits
				memcpy(nomsBits[gblNoFondProprietes], tempNomsBits, sizeof(tempNomsBits));
				memcpy(bitsActives[gblNoFondProprietes], tempBitsActives, sizeof(tempBitsActives));
				SetBits(blocCopie[0][0]);
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

LRESULT CALLBACK ProcOptions4(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i, j;
	static HWND hCombo, hListe;
	static int tempPlansSpecimen[MAX_FONDS], tempNPlans=0;
	static int tempMapLookupTable[MAX_FONDS];

	switch (message)
	{
		case WM_INITDIALOG:
			hCombo=GetDlgItem(hDlg,IDC_CARTES);
			j=0;
			for (i=0;i<nMaps;i++)		{
				if (params[i].gblTypeMap==TYPE_LISTE)
					continue;
				sprintf(str,"%i: %s",i+1,ele_fond[i]->nom_court);
				tempMapLookupTable[j++]=i;
				SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)str);
			}
			tempNPlans=nPlansLies;
			for (i=0;i<tempNPlans;i++)
				tempPlansSpecimen[i]=plans[i];

redessineliste:
			hListe=GetDlgItem(hDlg,IDC_LIST1);
			SendMessage(hListe,LB_RESETCONTENT,0,0);
			for (i=0;i<tempNPlans ;i++)			{
				sprintf(str, "%i: %s", tempPlansSpecimen[i]+1, ele_fond[tempPlansSpecimen[i]]->nom_court);
				SendMessage(hListe,LB_ADDSTRING,0,(LPARAM)str);
			}
			SetWindowText(hCombo,"(choisissez un fond)");
			EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), FALSE);
			return TRUE;

		//Support onglets
		case WM_SIZE:
			UpdateBackgroundBrush();
			break;

		case WM_CTLCOLORSTATIC:
			BOOL bHandled;
			return OnCtlColor(message, wParam, lParam, bHandled);

		case WM_ERASEBKGND:
			return TRUE;
		//End support onglets

/*		case WM_VKEYTOITEM:
			i = LOWORD(wParam);      // virtual-key code
			if ((HWND)lParam == GetDlgItem(hDlg, IDC_LIST1))			{
				if (i==VK_DELETE)
					goto del;
			}
			break;*/

		case WM_COMMAND:
			//Message de notification
			if (LOWORD(wParam) == IDC_LIST1)
			{
				if (HIWORD(wParam) == LBN_SELCHANGE)		{
					i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
					if (i==LB_ERR)
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON4), FALSE);
					else
						EnableWindow(GetDlgItem(hDlg, IDC_BUTTON4), TRUE);
				}
			}

			if (HIWORD(wParam)==CBN_SELCHANGE)		{
				GetDlgItemText(hDlg,IDC_EDIT1,str,sizeof(str)-10);
				i=SendDlgItemMessage(hDlg,IDC_CARTES,CB_GETCURSEL,0,0);
				if (i==CB_ERR)
					break;
				EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), TRUE);
				break;
			}

			if (LOWORD(wParam) == IDC_BUTTON1)			{
				i=SendDlgItemMessage(hDlg,IDC_CARTES,CB_GETCURSEL,0,0);
				if (i==CB_ERR)
					break;
				//Le même plan existe t'il déjà?
				for (j=0;j<tempNPlans;j++)
					if (tempPlansSpecimen[j]==tempMapLookupTable[i])
						break;
				//Oui? On ne l'ajoute pas
				if (j<tempNPlans)
					break;
				tempPlansSpecimen[tempNPlans] = tempMapLookupTable[i];
				tempNPlans++;
				goto redessineliste;
			}

			if (LOWORD(wParam) == IDC_BUTTON4)			{
//del:
				i=SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,0);
				if (i==CB_ERR)
					break;
				EnableWindow(GetDlgItem(hDlg, IDC_BUTTON4), FALSE);
				memcpy(tempPlansSpecimen+i, tempPlansSpecimen+i+1, sizeof(tempPlansSpecimen)-sizeof(tempPlansSpecimen[0])*(i+1));
				tempNPlans--;
				goto redessineliste;
			}

			if (LOWORD(wParam) == IDOK)
			{
				nPlansLies=0;
				for (i=0;i<tempNPlans;i++)		{
					AjoutePlanSpecimen(tempPlansSpecimen[i]);
				}
				if (nPlansLies>0)		{
					if (!gblHSpec)
						CreateDialog(hInst,(LPCTSTR)IDD_SPECIMEN, gblHEdit,(DLGPROC)ProcSpecimen);
					ShowWindow(gblHSpec, bSpecimenAffiche?SW_SHOW:SW_HIDE);
				}
				EndDialog(hDlg, 0);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}
			break;
	}

    return FALSE;
}

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK Fond(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i;

	switch (message)
	{
		case WM_INITDIALOG:
			hComboMap=GetDlgItem(hDlg,IDC_CARTES);
			AjouteMaps();
			return TRUE;

		case WM_COMMAND:

			if (LOWORD(wParam) == IDOK) 
			{
				i=SendMessage(hComboMap,CB_GETCURSEL,0,0);
				EndDialog(hDlg, i);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, -1);
				return TRUE;
			}

			break;
	}

    return FALSE;
}

#define MAX_CONDITIONS 10

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK DlgOperations(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i,j, operateur[MAX_CONDITIONS], valeur[MAX_CONDITIONS], opCondition, valCondition, test, egalite_a_tester, tmp, k, test_final;
	int liens[MAX_CONDITIONS], ops[MAX_CONDITIONS], vals[MAX_CONDITIONS], egals[MAX_CONDITIONS], n_conditions;
	MAP (*bloc)[1024];
	char operation[1000], chneCondition[1000], *condition, *opera;
	int limiter, temp, n_op, inverse;

	switch (message)
	{
		case WM_INITDIALOG:
			return TRUE;

		case WM_COMMAND:

			if (LOWORD(wParam) == IDOK) 
			{
				GetDlgItemText(hDlg,IDC_OPERATION,operation,sizeof(operation));
				GetDlgItemText(hDlg,IDC_CONDITION,chneCondition,sizeof(chneCondition));
				if (SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_CHECKED)
					limiter=TRUE;
				else
					limiter=FALSE;

				condition=chneCondition;
				opera=operation;

				for (n_op=0;n_op<MAX_CONDITIONS;n_op++)		{
					operateur[n_op]=*opera;
					opera++;
					if (*opera=='~')
						inverse=1, opera++;
					else
						inverse=0;
					valeur[n_op]=GetEntier(opera);
					if (inverse)
						valeur[n_op]=~valeur[n_op];
					if (*opera=='0')		{					//Support 0x et 0b
						opera++;
						if (*opera=='x' || *opera=='b')			{
							opera++;
							while(((*opera>='0' && *opera<='9') || (*opera>='a' && *opera<='f')) && *opera)
								opera++;
						}
					}
					while(*opera>='0' && *opera<='9' && *opera)	opera++;
					if (!(*opera))
						break;
				}

				n_op++;

				if (!condition[0])		{
					n_conditions=-1;
					goto pasdecondition;
				}

				for (n_conditions=0;n_conditions<MAX_CONDITIONS;n_conditions++)		{
					ops[n_conditions]=condition[0];
					if (condition[1]=='=')		{				//>=, <=
						vals[n_conditions]=GetEntier(condition+2);
						egals[n_conditions]=1;
					}
					else	{
						vals[n_conditions]=GetEntier(condition+1);
						egals[n_conditions]=0;
					}

					while(*condition!=' ' && *condition)
						condition++;

					if (*condition==' ')		{
						condition++;
						if (!strncmp(condition,"et ",3))	{
							condition+=3;
							liens[n_conditions+1]='&';
							continue;
						}
						else if (!strncmp(condition,"ou ",3))		{
							condition+=3;
							liens[n_conditions+1]='|';
							continue;
						}
						else		{
							MessageBox(hDlg,"Le lieur de tests est inconnu\nLieurs valides: et, ou.\nExemple: >=10 et <=13","Erreur lors de l'exécution de la condition",MB_ICONERROR);
							return FALSE;
						}
					}
					break;
				}

pasdecondition:
/*				for (i=0;i<=n_conditions;i++)		{
					sprintf(str,"%c %i %i %c",ops[i],vals[i],egals[i],liens[i]);
					MessageBox(hDlg,str,"conditions",MB_ICONERROR);
				}*/

				for (temp=0;temp<profondeurSel;temp++)				{
					if (limiter)		{
						bloc=(MAP (*)[1024])BufferActif();
						temp=profondeurSel;
					}
					else
						bloc=blocCopie+1024*temp;

					for (j=0;j<CopieY;j++)
						for (i=0;i<CopieX;i++)		{
							tmp=bloc[j][i];
							if (tmp==masqueInvisible || (tmp==0 && masqueZero))
								continue;

							if (n_conditions>=0)		{
								for (k=0;k<=n_conditions;k++)		{
									opCondition=ops[k];
									valCondition=vals[k];
									egalite_a_tester=egals[k];

									if (opCondition=='=')
										test=(tmp==valCondition);
									else if (opCondition=='&')
										test=(tmp&valCondition);
									else if (opCondition=='~')
										test=!(tmp&valCondition);
									else if (opCondition=='>')		{
										if (egalite_a_tester)
											test=(tmp>=valCondition);
										else
											test=(tmp>valCondition);
									}
									else if (opCondition=='<')		{
										if (egalite_a_tester)
											test=(tmp<=valCondition);
										else
											test=(tmp<valCondition);
									}
									else if (opCondition=='!')
										test=(tmp!=valCondition);
									else		{
										MessageBox(hDlg,"Le test à effectuer est inconnu.\nTests valides: =, <, <=, >=, >, !=\nExemple: >10","Erreur lors de l'exécution de la condition",MB_ICONERROR);
										return FALSE;
									}

									if (k>0)		{
										if (liens[k]=='&')
											test_final=test_final & test;
										else if (liens[k]=='|')
											test_final=test_final | test;
										else		{
											MessageBox(hDlg,"Une erreur qui ne devrait pas arriver est arrivée. Signalez-la au programmeur...","Point d'erreur inconnu #1",MB_ICONERROR);
											return FALSE;
										}
									}
									else
										test_final=test;
								}

								if (!test_final)
									continue;
							}

							for (k=0;k<n_op;k++)		{
								if (operateur[k]=='|')
									bloc[j][i]|=valeur[k];
								else if (operateur[k]=='&')
									bloc[j][i]&=valeur[k];
								else if (operateur[k]=='+')
									bloc[j][i]+=valeur[k];
								else if (operateur[k]=='-')
									bloc[j][i]-=valeur[k];
								else if (operateur[k]=='*')
									bloc[j][i]*=valeur[k];
								else if (operateur[k]=='/')
									bloc[j][i]/=valeur[k];
								else if (operateur[k]=='%')
									bloc[j][i]%=valeur[k];
								else if (operateur[k]=='^')
									bloc[j][i]^=valeur[k];
								else if (operateur[k]=='=')
									bloc[j][i]=valeur[k];
								else		{
									MessageBox(hDlg,"Opérateur inconnu.\nOpérateurs valides: |, &, +, -, *, /, %, ^, =.\nExemple: +10","Erreur lors de l'exécution de l'opération",MB_ICONERROR);
									return FALSE;
								}
							}
						}
				}

				EndDialog(hDlg, IDOK);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, IDCANCEL);
				return TRUE;
			}

			break;
	}

    return FALSE;
}

#define mat_temp(x,y)		(blocTemp[y*xFin+x])
enum infos_disponibles {ID_DEPART, ID_TAILLE, ID_DEPLACEMENT};

// "Handler" pour la boîte de dialogue
LRESULT CALLBACK DlgDeplace(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	char chne[1000];
	int xDep, yDep, xFin, yFin, xNouv, yNouv, x, y;
	MAP *blocTemp;
	int idDepart, idTaille, idDeplacement, i, k;				//id pour informations disponibles
	PARAM *p;
	MAP (*bloc)[1024];
	int limiter;

	switch (message)
	{
		case WM_INITDIALOG:
			return TRUE;

		case WM_COMMAND:

			if (LOWORD(wParam) == IDOK)
			{
				if (SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_CHECKED)
					limiter=TRUE;
				else
					limiter=FALSE;
				idDepart=idTaille=idDeplacement=1;
				GetDlgItemText(hDlg,IDC_EDIT1,chne,sizeof(chne));
				if (!(*chne))
					idDepart=0;
				xDep=atoi(chne);
				GetDlgItemText(hDlg,IDC_EDIT2,chne,sizeof(chne));
				if (!(*chne))
					idDepart=0;
				yDep=atoi(chne);
				GetDlgItemText(hDlg,IDC_EDIT3,chne,sizeof(chne));
				if (!(*chne))						//Aucun nombre -> champ désactivée
					idTaille=0;
				else if (*chne=='*')				//* -> sélectionne le maximum qu'il peut
					xFin=1024;
				else
					xFin=atoi(chne);
				GetDlgItemText(hDlg,IDC_EDIT4,chne,sizeof(chne));
				if (!(*chne))
					idTaille=0;
				else if (*chne=='*')				//* -> sélectionne le maximum qu'il peut
					yFin=1024;
				else
					yFin=atoi(chne);
				GetDlgItemText(hDlg,IDC_EDIT5,chne,sizeof(chne));
				if (!(*chne))
					idDeplacement=0;
				xNouv=atoi(chne);
				GetDlgItemText(hDlg,IDC_EDIT6,chne,sizeof(chne));
				if (!(*chne))
					idDeplacement=0;
				yNouv=atoi(chne);

				x=(xDep+xFin)-(tailleX/tileX);
				if (x>0)				//L'un est plus grand que l'autre
					xFin-=x;
				y=(yDep+yFin)-(tailleY/tileY);
				if (y>0)				//L'un est plus grand que l'autre
					yFin-=y;

				//Toutes les infos disponibles?
				if (idDepart && idTaille && idDeplacement)	{
					blocTemp=(MAP*)malloc(xFin*yFin*sizeof(MAP));
					if (!blocTemp)		{
						MessageBox(hDlg,"Impossible d'allouer la mémoire nécessaire pour le traitement...","Oups...",MB_ICONERROR);
						return FALSE;
					}
//					memset(blocTemp,0,xFin*yFin*sizeof(unsigned short));

					for (k=0;liens[fondActif][k]!=LIEN_INVALIDE;k++)		{
						if (limiter)
							p=&params[fondActif];
						else
							p=&params[liens[fondActif][k]];

						//Vérification des débordements sur la source
						x=(xDep+xFin)-(p->tailleX);
						if (x>0)				//L'un est plus grand que l'autre
							xFin-=x;
						y=(yDep+yFin)-(p->tailleY);
						if (y>0)				//L'un est plus grand que l'autre
							yFin-=y;

						//Calculer un éventuel débordement sur la destination...
						x=(xNouv+xFin)-(p->tailleX);
						if (x>0)				//L'un est plus grand que l'autre
							xFin-=x;					
						y=(yNouv+yFin)-(p->tailleY);
						if (y>0)				//L'un est plus grand que l'autre
							yFin-=y;

						if (p->gblTypeMap == TYPE_MAP)			{
							//Première étape: récupérer ce qui se trouve dans la zone avant de l'effacer (dans la même passe)
							for (y=0;y<yFin;y++)		{
								for (x=0;x<xFin;x++)	{
									mat_temp(x,y)=AccesMap(p,x+xDep,y+yDep);
									AccesMap(p,x+xDep,y+yDep)=0;
								}
							}

							//Remplacer la destination par la source sauvegardée.
							for (y=0;y<yFin;y++)		{
								for (x=0;x<xFin;x++)	{
									AccesMap(p,x+xNouv,y+yNouv)=mat_temp(x,y);
								}
							}
						}

						if (limiter)
							break;
					}

					free(blocTemp);
					SauveAnnuler();
				}
				else if (idDepart && idTaille && !idDeplacement)		{				//Départ et taille -> copie
					if (xFin>=1024 || yFin>=1024)		{
						MessageBox(hDlg,"La taille de la copie est limitée à 1024x1024...","Faut pas exagérer quand-même! ^^",MB_ICONERROR);
						return FALSE;
					}
					i=params[fondActif].tileX;
					DebutX=xDep*i, DebutY=yDep*i, FinX=(xFin+xDep-1)*i, FinY=(yFin+yDep-1)*i;

					for (k=0;liens[fondActif][k]!=LIEN_INVALIDE && k<MAXBLOCS;k++)		{
						if (limiter)		{
							bloc=(MAP (*)[1024])BufferActif();
							p=&params[fondActif];
						}
						else		{
							bloc=blocCopie+1024*k;
							p=&params[liens[fondActif][k]];
						}

						//Vérification des débordements
						x=(xDep+xFin)-(p->tailleX);
						if (x>0)				//L'un est plus grand que l'autre
							xFin-=x;
						y=(yDep+yFin)-(p->tailleY);
						if (y>0)				//L'un est plus grand que l'autre
							yFin-=y;

						if (p->gblTypeMap == TYPE_MAP)			{
							//Copie
							for (y=0;y<yFin;y++)		{
								for (x=0;x<xFin;x++)	{
									bloc[y][x]=AccesMap(p,x+xDep,y+yDep);
								}
							}
							if (k==fondActif || limiter)
								SetBits(bloc[0][0]);
						}

						if (limiter)		{
							k++;
							break;
						}
					}

					profondeurSel=k;
					CopieX=xFin;
					CopieY=yFin;
					CopieSpec=0;
				}
				else if ((idDepart || idDeplacement))		{
					//Faites attention: si vous spécifiez la position de départ et la taille, la sélection sera copiée dans le presse-papiers. Pour coller la taille voulue depuis la position voulue, vous devez remplir les champs taille et destination.
					if (idDepart)	{					//Départ et non déplacement fourni -> intervertit
						xNouv=xDep;
						yNouv=yDep;
					}
					if (!idTaille)		{				//Taille non-présente -> taille de la sélection
						xFin=CopieX;
						yFin=CopieY;
					}

					for (k=0;liens[fondActif][k]!=LIEN_INVALIDE && k<profondeurSel;k++)		{
						if (limiter)	{
							bloc=(MAP (*)[1024])BufferActif();
							p=&params[fondActif];
						}
						else		{
							bloc=blocCopie+1024*k;
							p=&params[liens[fondActif][k]];
						}

						//Vérifs pour les débordements
						x=(xNouv+xFin)-(tailleX/tileX);
						if (x>0)				//L'un est plus grand que l'autre
							xFin-=x;					
						y=(yNouv+yFin)-(tailleY/tileY);
						if (y>0)				//L'un est plus grand que l'autre
							yFin-=y;

						if (p->gblTypeMap == TYPE_MAP)			{
							for (y=0;y<yFin;y++)		{
								for (x=0;x<xFin;x++)		{
									if (CopieX>0 && CopieY>0)		{
										i=bloc[y%CopieY][x%CopieX];
										if (i==masqueInvisible || (i==0 && masqueZero))
											continue;
									}
									else
										i=motifChoisi;
									AccesMap(p,x+xNouv,y+yNouv)=i;
								}
							}
						}
						if (limiter)
							break;
					}

					SauveAnnuler();
				}
				else	{
					MessageBox(hDlg,"Les informations fournies sont insuffisantes.","Erreur",MB_ICONEXCLAMATION);
					return FALSE;
				}

				EndDialog(hDlg, IDOK);
				return TRUE;
			}

			if (LOWORD(wParam) == IDCANCEL)
			{
				EndDialog(hDlg, IDCANCEL);
				return TRUE;
			}

			break;
	}

    return FALSE;
}


