
void DessineListeEdit(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;
	int z;

	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)/grilleX)*grilleX;
	dY=(int)((scrlY*parallaxeY)/grilleY)*grilleY;
//	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
	}*/
	int ticks=GetTickCount()%1024, v;
	ticks/=2;
	if (ticks>=256)
		v=ticks%256;
	else
		v=255-ticks%256;

	if (v==0)
		v=1;

	for (z=0;z<gblSpriteListe.nbSprites;z++)			{
		i=_SD(gblSpriteListe,z)->type;
		i=VerifConditions(i,fond,gfxmask);
		x=_SD(gblSpriteListe,z)->x-dX;
		y=_SD(gblSpriteListe,z)->y-dY;
		
//		i&=gfxmask;
		//Motif non-valide (ne devrait pas arriver)
		if (i>=taille || i<0)
			goto pasafficher;

		for (yy=0;yy<tileBaseY;yy+=8)
			for (xx=0;xx<tileBaseX;xx+=8)		{
				if (emul_gba)
					DessineTile(Bits3,x+xx,y+yy,&p,(i*tileBaseX*tileBaseY)/64+(tileBaseX/8)*(yy/8)+(xx/8),transparence);
				else if (!transparence)
					SpritePal(Bits3,x+xx,y+yy,8,8,motifs+(i*tileBaseX*tileBaseY)+64*(tileBaseX/8)*(yy/8)+64*(xx/8),palette);
				else
					TransSpritePal(Bits3,x+xx,y+yy,8,8,motifs+(i*tileBaseX*tileBaseY)+64*(tileBaseX/8)*(yy/8)+64*(xx/8),palette,transparence);
			}
			if (lstSelMulNbre)		{
				for (i=0;i<lstSelMulNbre;i++)
					if (lstSelMulListe[i]==z)		{
						TransRect(Bits3,x-1,y,tileX+2,tileY+2,RGB(0,0,255),128);
						TransCadre(Bits3,x,y,tileX,tileY,RGB(255,v,0),128);
					}
			}
			else if (z==listeSelection)		{
				TransRect(Bits3,x-1,y,tileX+2,tileY+2,RGB(0,0,255),128);
				TransCadre(Bits3,x,y,tileX,tileY,RGB(255,v,0),128);
			}
pasafficher:
			;
//		#pragma UTILISER GRILLEX ET GRILLEY
//		if (fond==fondActif && grille)
//			TransRectFond(Bits3,x*tileX,y*tileY+1,tileX,tileY,couleurGrille,transGrille);
		
	}

	//Dessine la grille
	if (fond==fondActif && grille && grilleX>=4 && grilleY>=4)			{
		fX = gdrXz, fY = gdrYz;
		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);
			}
		}
	}


/*	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);

					i&=gfxmask;
					//Motif non-valide (ne devrait pas arriver)
					if (!emul_gba)		{
						if (i>=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));
		}
	}*/

	tailleX*=tileX;
	tailleY*=tileY;
}

void DessineEcranListe(int posX, int posY)		{
	int i,j,ii,x,y, ptX,ptY,pX,pY;
	int ticks=GetTickCount()%1024;
	int v, temps;
	MAP *map=gblMap;
	unsigned long *motifs=gblMotifs;
	unsigned char *palette=gblPal;
	static int aposX, aposY, fixe=0, derTickCount=0;
	PARAM p;

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

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

	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 (selectionPointee && params[fondActif].gblTypeMap==TYPE_LISTE)			{
				//Ajout
//				i+=(int)(scrollX*parallaxeX); j+=(int)(scrollY*parallaxeY);
				//End Ajout
//				i-=mouseOffsetX;
//				j-=mouseOffsetY;
				ArronditX(i); ArronditY(j);
				//Ajout
//				i-=(int)(scrollX*parallaxeX); j-=(int)(scrollY*parallaxeY);
				//End Ajout
				ii=_SD(params[fondActif].gblSpriteListe,listeSelection)->type;
				ii=VerifConditions(ii,fondActif,gfxmask);
				if ((ii&gbatilmask)>=taille)
					goto __rate;
				for (y=0;y<tileY;y+=8)
					for (x=0;x<tileX;x+=8)		{
						if (emul_gba)
							DessineTileSansMasque(Bits3,i+x,j+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
						else
							TransSpritePalSansMasque(Bits3,i+x,j+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
					}
				TransRect(Bits3,i-1,j,tileX+2,tileY+2,RGB(0,0,255),128);
				TransCadre(Bits3,i,j,tileX,tileY,RGB(255,v,0),128);
__rate:
				;
			}
			else if (motifChoisi>0)	{
				ArronditX(i); ArronditY(j);
	/*			if (CopieX>0 && CopieY>0)
					ii=bloc[0][0]+blocBase;
				else*/
					ii=motifChoisi+blocBase;
				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+x,j+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
							else
								TransSpritePalSansMasque(Bits3,i+x,j+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
						}
				}
			}
		}
		else if (selMap)	{
			ptX=RelaToAbsX(posX);
			ptY=RelaToAbsY(posY);
			pX=posDepartAbsolueX;
			pY=posDepartAbsolueY;
			if (ptX<pX)		{
				i=pX;
				pX=ptX;
				ptX=i;
			}
			if (ptY<pY)		{
				i=pY;
				pY=ptY;
				ptY=i;
			}

			ptX=AbsToRelaX(ptX);
			ptY=AbsToRelaY(ptY);
			pX=AbsToRelaX(pX);
			pY=AbsToRelaY(pY);

			ArronditX(pX); ArronditY(pY);
			ArronditHautX(ptX); ArronditHautY(ptY);

//				if (ptY>=tailleY || ptX>=tailleX)
//					return;
				if (CopieX>0 && CopieY>0)			{
/*					for (i=0;i<listeCopie[fondActif].nbSprites;i++)		{
						if (listeCopie[fondActif].sd[i].x>=pX && listeCopie[fondActif].sd[i].x<=ptX && listeCopie[fondActif].sd[i].y>=pY && listeCopie[fondActif].sd[i].y<=ptY)		{
						ii=listeCopie[fondActif].sd[i].type;
						ii=VerifConditions(ii,fondActif);
						if (ii>=taille && !emul_gba)
							goto rate;
						for (y=0;y<tileY;y+=8)
							for (x=0;x<tileX;x+=8)		{
								if (emul_gba)
									DessineTileSansMasque(Bits3,ptX+x,ptY+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
								else
									TransSpritePalSansMasque(Bits3,ptX+x,ptY+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
							}
						}
					}*/
					int nbIterationsX, nbIterationsY, distX, distY, nbXsauv;
					int xX, yY, dX, dY, fX, fY;
					dX=pX, dY=pY, fX=ptX, fY=ptY;
		//Si la sélection est petite -> colle tout
/*					if (fX-dX==0)			fX+=CopieXprecise+1;
					if (fY-dY==0)			fY+=CopieYprecise+1;*/
					nbIterationsX=(fX-dX-1)/CopieXprecise;
					nbIterationsY=(fY-dY-1)/CopieYprecise;
					if ((fX-dX-1)%CopieXprecise)	nbIterationsX++;
					if ((fY-dY-1)%CopieYprecise)	nbIterationsY++;
					distX=fX-dX, distY=fY-dY;
					nbXsauv=nbIterationsX;
					//OK!!!
			//		Debug("%i %i",nbIterationsX,nbIterationsY);
					TransRect(Bits3,dX,dY,(fX-dX+1),(fY-dY+1),RGB(0,0,128),v);
					TransCadre(Bits3,dX+1,dY,(fX-dX-1),(fY-dY-1),RGB(128,192,255),v);
					for (;nbIterationsY--;dY+=CopieYprecise)			{
						for (;nbIterationsX--;dX+=CopieXprecise)			{
							for (i=0;i<listeCopie[fondActif].nbSprites;i++)			{
			//					if (_SD(listeCopie[buffer],i)->x>=dX && _SD(listeCopie[buffer],i)->x+tileX<=fX && _SD(listeCopie[buffer],i)->y>=dY && _SD(listeCopie[buffer],i)->y+tileY<=fY)			{
								if (_SD(listeCopie[fondActif],i)->x<fX-dX && _SD(listeCopie[fondActif],i)->y<fY-dY)		{
									ii=_SD(listeCopie[fondActif],i)->type;
									ii=VerifConditions(ii,fondActif,params[fondActif].gfxmask);
									xX=_SD(listeCopie[fondActif],i)->x+dX;
									yY=_SD(listeCopie[fondActif],i)->y+dY;
									if ((ii&gbatilmask)>=taille)
										goto rate;
									for (y=0;y<tileY;y+=8)			{
										for (x=0;x<tileX;x+=8)		{
											if (emul_gba)
												DessineTile(Bits3,xX+x,yY+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
											else
												TransSpritePal(Bits3,xX+x,yY+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
										}
									}
/*
									memcpy(_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites),
										_SD(listeCopie[buffer],i),sizeofSD);
									_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites)->x+=dX;
									_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites)->y+=dY;
									p->gblSpriteListe.nbSprites++;*/
								}
							}
						}
						nbIterationsX=nbXsauv;
						dX-=CopieXprecise*nbIterationsX;
					}
/*					TransRect(Bits3,pX,pY,(ptX-pX+1),(ptY-pY+1),RGB(0,0,128),v);
					TransCadre(Bits3,pX+1,pY,(ptX-pX-1),(ptY-pY-1),RGB(128,192,255),v);*/
				}
				else	{
					ii=motifChoisi+blocBase;
					ii=VerifConditions(ii,fondActif,gfxmask);
					if ((ii&gbatilmask)>=taille)
						goto rate;
					for (y=0;y<tileY;y+=8)
						for (x=0;x<tileX;x+=8)		{
							if (emul_gba)
								DessineTileSansMasque(Bits3,ptX+x,ptY+y,&p,(ii*tileX*tileY)/64+(tileX/8)*(y/8)+(x/8),v);
							else
								TransSpritePalSansMasque(Bits3,ptX+x,ptY+y,8,8,motifs+(ii*tileX*tileY)+64*(tileX/8)*(y/8)+64*(x/8),palette,v);
						}
rate:
					;
				}
		}
		else if (selCopie)	{
			ptX=RelaToAbsX(posX);
			ptY=RelaToAbsY(posY);
			pX=posDepartAbsolueX;
			pY=posDepartAbsolueY;
			if (ptX<pX)		{
				i=pX;
				pX=ptX;
				ptX=i;
			}
			if (ptY<pY)		{
				i=pY;
				pY=ptY;
				ptY=i;
			}

			ptX=AbsToRelaX(ptX);
			ptY=AbsToRelaY(ptY);
			pX=AbsToRelaX(pX);
			pY=AbsToRelaY(pY);

			ArronditX(pX); ArronditY(pY);
			ArronditHautX(ptX); ArronditHautY(ptY);

			TransCadre(Bits3,pX,pY,(ptX-pX+1),(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);
}

int CopieBlocsListe(int fond, int buffer, int dX, int dY, int fX, int fY)		{
	PARAM *p;
	int i;

	//Paramètres du fond sélectionné
	p=&params[fond];

	//Add-on récent
	dX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	dY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;
	fX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	fY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;

	//Ajoute le scrolling à toutes les variables - add-on récent
/*	dX+=(int)(scrollX*p->parallaxeX+0.5), dY+=(int)(scrollY*p->parallaxeY+0.5),
	fX+=(int)(scrollX*p->parallaxeX+0.5), fY+=(int)(scrollY*p->parallaxeY+0.5);*/

/*	//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;
	}
	ArronditX(dX); ArronditY(dY);
	ArronditHautX(fX); ArronditHautY(fY);

	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;
	}*/

	listeCopie[buffer].nbSprites=0;
	listeCopie[buffer].sizeofSD=p->gblSpriteListe.sizeofSD;
	for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
		if (p->gblSpriteListe.nbSprites>=NB_MAX_ELE_LISTE)
			break;
		if (_SD(p->gblSpriteListe,i)->x+tileX>dX && _SD(p->gblSpriteListe,i)->x<fX && _SD(p->gblSpriteListe,i)->y+tileY>dY && _SD(p->gblSpriteListe,i)->y<fY)		{
			memcpy(_SD(listeCopie[buffer],listeCopie[buffer].nbSprites),_SD(p->gblSpriteListe,i), listeCopie[buffer].sizeofSD);
			_SD(listeCopie[buffer],listeCopie[buffer].nbSprites)->x-=dX;
			_SD(listeCopie[buffer],listeCopie[buffer].nbSprites)->y-=dY;
			listeCopie[buffer].nbSprites++;
		}
	}

	//Taille de la sélection active
//	if (CopieX==0 && CopieY==0)		{
		typeCoordCopie=1;
		CopieX=(fX-dX-1), CopieY=(fY-dY-1);
		if (CopieX%tileX>0)		CopieX+=tileX;
		if (CopieY%tileY>0)		CopieY+=tileY;
		CopieX/=tileX, CopieY/=tileY;
//	}
	CopieXprecise=(fX-dX), CopieYprecise=(fY-dY);

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

	return 1;
}

void lstSelMulAjObjet(int no_obj, int intervertit)		{
	int i;
	for (i=0;i<lstSelMulNbre;i++)		{
		if (lstSelMulListe[i]==no_obj)		{
			//Existe déjà -> supprime
			for (;i<lstSelMulNbre-1;i++)
				lstSelMulListe[i]=lstSelMulListe[i+1];
			lstSelMulNbre--;
			return;
		}
	}
	lstSelMulListe[lstSelMulNbre++]=no_obj;
}

int lstSelMulAjBlocs(int fond, int dX, int dY, int fX, int fY)		{
	PARAM *p;
	int i;

	//Paramètres du fond sélectionné
	p=&params[fond];

	//Add-on récent
	dX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	dY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;
	fX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	fY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;

	//Ajoute le scrolling à toutes les variables - add-on récent
/*	dX+=(int)(scrollX*p->parallaxeX), dY+=(int)(scrollY*p->parallaxeY),
	fX+=(int)(scrollX*p->parallaxeX), fY+=(int)(scrollY*p->parallaxeY);*/


/*	//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;
	}
	ArronditX(dX); ArronditY(dY);
	ArronditHautX(fX); ArronditHautY(fY);

	for (i=0;i<p->gblSpriteListe.nbSprites;i++)		{
		if (_SD(p->gblSpriteListe,i)->x+tileX>dX && _SD(p->gblSpriteListe,i)->x<fX && _SD(p->gblSpriteListe,i)->y+tileY>dY && _SD(p->gblSpriteListe,i)->y<fY)		{
			lstSelMulAjObjet(i,1);
		}
	}

	return 1;
}

//Sauve le tampon annuler pour un des fonds particuliers
void SauveAnnulerListe(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	int sizeofSD;

	ub=&undos[fond];
	p=&params[fond];
	unsigned long i;

	sizeofSD=params[fond].gblSpriteListe.sizeofSD;
	if ((ub->nOperations>=OPMAX || utilMemoire>=MAXUNDORAM) && ub->nOperations>=2)			{
		memmove(ub->undoBuffer, (char*)ub->undoBuffer+(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD), (ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD));
		ub->modifie=TRUE;					//De toutes façons modifié car le tampon annuler ne peut contenir tout...
		ub->nOperations--;
	}
	i=ub->MAXMEM;
	ub->MAXMEM=(ub->nOperations+2)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD);
	utilMemoire+=(ub->MAXMEM-i);

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

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

	ub->nOperations++;
	memcpy((char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD),&p->gblSpriteListe,sizeof(SPRITE_LISTE));
	memcpy((char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD)+sizeof(SPRITE_LISTE),p->gblSpriteListe.sd,NB_MAX_ELE_LISTE*sizeofSD);

	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 AnnulerListe(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	int sizeofSD;
	ub=&undos[fond];
	p=&params[fond];
	sizeofSD=params[fond].gblSpriteListe.sizeofSD;

	//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--;
#pragma message ("ATTENTION_PAS_DE_REALLOC_DU_SD_SINON_PLANTAGE_ICI_CAR_GBLSPRITELISTE_STOCKE_UN_POINTEUR")
	memcpy(&p->gblSpriteListe,(char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD),sizeof(SPRITE_LISTE));
	memcpy(p->gblSpriteListe.sd,(char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD)+sizeof(SPRITE_LISTE),sizeofSD*NB_MAX_ELE_LISTE);

	//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 RefaireListe(int fond)		{
	UNDO_BUFFER *ub;
	PARAM *p;
	int sizeofSD;
	ub=&undos[fond];
	p=&params[fond];
	sizeofSD=params[fond].gblSpriteListe.sizeofSD;

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

	if (ub->nOperations>=ub->nTotalOperations)
		return;
	ub->nOperations++;
	memcpy(&p->gblSpriteListe,(char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD),sizeof(SPRITE_LISTE));
	memcpy(p->gblSpriteListe.sd,(char*)ub->undoBuffer+(ub->nOperations)*(sizeof(SPRITE_LISTE)+NB_MAX_ELE_LISTE*sizeofSD)+sizeof(SPRITE_LISTE),sizeofSD*NB_MAX_ELE_LISTE);
//	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 EffaceElementListe(int fond, int element);

void ColleBlocsListe(int fond, int buffer, int dX, int dY, int fX, int fY)		{
	PARAM *p;
	int i;

	p=&params[fond];
	//Ajoute le scrolling à toutes les variables - add-on récent
	dX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	dY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;
	fX+=(int)((scrollX*p->parallaxeX)/p->grilleX)*p->grilleX;
	fY+=(int)((scrollY*p->parallaxeY)/p->grilleY)*p->grilleY;
/*	//Ajoute le scrolling à toutes les variables
	dX+=(int)(scrollX*p->parallaxeX+0.5), dY+=(int)(scrollY*p->parallaxeY+0.5),
	fX+=(int)(scrollX*p->parallaxeX+0.5), fY+=(int)(scrollY*p->parallaxeY+0.5);*/
	//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;
	}

	ArronditX(dX); ArronditY(dY); ArronditHautX(fX); ArronditHautY(fY);

	if (CopieX==0 && CopieY==0)
		AjouteObjetListe(fond,dX,dY,motifChoisi);
	else	{
		int nbIterationsX, nbIterationsY, distX, distY, nbXsauv;
		//Si la sélection est petite -> colle tout
/*		if (fX-dX==0)			fX+=CopieXprecise+1;
		if (fY-dY==0)			fY+=CopieYprecise+1;*/
		nbIterationsX=(fX-dX-1)/CopieXprecise;
		nbIterationsY=(fY-dY-1)/CopieYprecise;
		if ((fX-dX-1)%CopieXprecise)	nbIterationsX++;
		if ((fY-dY-1)%CopieYprecise)	nbIterationsY++;
		distX=fX-dX, distY=fY-dY;
		nbXsauv=nbIterationsX;
		//OK!!!
//		Debug("%i %i",nbIterationsX,nbIterationsY);

		//Efface d'abord ce qui se trouve par là
		for (i=p->gblSpriteListe.nbSprites-1;i>=0;i--)		{
			if (_SD(p->gblSpriteListe,i)->x+tileX>dX && _SD(p->gblSpriteListe,i)->x<fX && _SD(p->gblSpriteListe,i)->y+tileY>dY && _SD(p->gblSpriteListe,i)->y<fY)		{
				EffaceElementListe(fond, i);
			}
		}

		//Copie en série
		for (;nbIterationsY--;dY+=CopieYprecise)			{
			for (;nbIterationsX--;dX+=CopieXprecise)			{
				for (i=0;i<listeCopie[buffer].nbSprites;i++)			{
//					if (_SD(listeCopie[buffer],i)->x>=dX && _SD(listeCopie[buffer],i)->x+tileX<=fX && _SD(listeCopie[buffer],i)->y>=dY && _SD(listeCopie[buffer],i)->y+tileY<=fY)			{
					if (p->gblSpriteListe.nbSprites>=NB_MAX_ELE_LISTE)			{
						MessageBox(gblHEdit, "Trop d'éléments, veuillez allonger la liste dans les options", "Erreur", MB_ICONEXCLAMATION);
						break;
					}
					if (_SD(listeCopie[buffer],i)->x<fX-dX && _SD(listeCopie[buffer],i)->y<fY-dY)		{
						memcpy(_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites),
							_SD(listeCopie[buffer],i),listeCopie[buffer].sizeofSD);
						_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites)->x+=dX;
						_SD(p->gblSpriteListe,p->gblSpriteListe.nbSprites)->y+=dY;
						p->gblSpriteListe.nbSprites++;
					}
				}
			}
			nbIterationsX=nbXsauv;
			dX-=CopieXprecise*nbIterationsX;
		}
	}

//	SauveAnnulerFond(fond);
}

void AjTypePerso(SD_PARAMS *sdp, char *nom, int type, int taille, char *defaut)		{
	int i, nObjSelect;
	if (sdp->sdNumParams>=MAX_SD)
		return;
	if (strlen(nom)==0)
		return;
	//Le nom existe déjà?
	for (i=0;i<sdp->sdNumParams;i++)		{
		if (!strcmp(nom, sdp->sdNomsParams[i]))
			break;
	}
	//Si non, nObjSelect vaudra sdNumParams
	nObjSelect=i;
	if (strlen(nom)>=TAILLE_MAX_NOM_SD)
		nom[TAILLE_MAX_NOM_SD-1]=0;
	strcpy(sdp->sdNomsParams[nObjSelect],nom);
	strcpy(sdp->sdTexteDefaut[nObjSelect], defaut);

	sdp->sdTypeParam[nObjSelect]=type;
//	if (sdp->sdNumParams==0)
		sdp->sdTaillesParam[nObjSelect]=taille;
//	else
//		sdp->sdTaillesParam[sdp->sdNumParams]=sdp->sdTaillesParam[sdp->sdNumParams-1]+taille;
	sdp->sizeofSD=CalcSdSize(sdp);
//		sizeof(SPRITE_DEF)+sdp->sdTaillesParam[sdp->sdNumParams];
	
	//Le nom n'existait pas, on le crée!
	if (nObjSelect==sdp->sdNumParams)
		sdp->sdNumParams++;
	//Le copy buffer n'est plus valide car il a changé de taille...
	if (lstCopyBuf.sd)		{
		free(lstCopyBuf.sd);
		lstCopyBuf.sd = NULL;
	}
	lstCopyBuf.nbSprites=0;
}

char *EcritSymboleType(char *symbole, char *valeur, SPRITE_DEF *sd)			{
	int i;
	int mode=0;
	SD_PARAMS *sdp=&sdParams[gblSdModele];

	if (!strcmp(symbole,"type"))
		sd->type=atoi(valeur);
	else if (!strcmp(symbole,"x"))
		sd->x=atoi(valeur);
	else if (!strcmp(symbole,"y"))
		sd->y=atoi(valeur);
	else		{
		for (i=0;i<sdp->sdNumParams;i++)		{
			if (!strcmp(symbole,sdp->sdNomsParams[i]))			{
				if (sdp->sdTypeParam[i]==SDT_ENTIER)			{
					int *ptr;
					ptr= (int*)((char*)sd->params+GetParamOffset(i));
					*ptr=atoi(valeur);
					break;
				}
				else if (sdp->sdTypeParam[i]==SDT_BRUT)			{
					char *cptr;
					cptr=(char*)sd->params+GetParamOffset(i);
					strcpy(cptr, valeur);
				}
			}
		}
/*		//ATTENTION: SI PAS TROUVE, REMPLIT DE ZERO
		if (i>=sdp->sdNumParams)		{
			MessageBox(NULL,""
		}*/
	}

	return NULL;
}


//bPasErreur: 0=normal, 1=pas d'erreur, 2=importation avancée
int LitChaineTypes(int j, char *bloc, char *chaine, FILE *f, SPRITE_DEF *sd, int bPasErreur, char *fin_ligne)			{
	char *ptr=chaine;
	int taille_chaine=strlen(chaine);
	char variable[1000], chne[1000];
	int i,temp,temp2, niveau=0, lgFinLigne;

	if (fin_ligne != NULL)
		lgFinLigne = strlen(fin_ligne);

	i=0;
	while(chaine[i]!='#' && chaine[i])
		i++;

	temp=0;
	while(memcmp(bloc+j,chaine+temp,i) && j+i<taille_totale)
		j++;

	i=temp;

	while(1)			{
		temp=i, temp2=j;
		while(chaine[i]!='#' && chaine[i])
			i++, j++;

		if (!chaine[i])
			break;

		if (!memcmp(bloc+temp2,chaine+temp,i-temp))			{
			i++;
			temp=0;
			while(chaine[i]!='#' && chaine[i] && j<taille_totale && temp<sizeof(variable)-1)
				variable[temp++]=chaine[i++];
			variable[temp]=0;
			i++;

			temp=i;
			while(chaine[i]!='#' && chaine[i] && i<taille_chaine)
				i++;

			//Ce cas signifie que deux variables sont collées (%sizex%%sizey% par exemple). Il va falloir tenter
			//de déterminer la fin de la variable dans la chaîne, sachant si c'est un entier ou autre.
/*			if (i-temp==0)
				Debug("ICI");*/

			temp2=j;
			int v, signe_ok, incrementDiff;
			//#"<param>"# par exemple
			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]=='>')			{
					v++;
					//Le début correspond?
					if (!strncmp(bloc+j,variable,signe_ok))			{
						j+=signe_ok;
						signe_ok=strlen(variable+v);
						incrementDiff=0;
						while(strncmp(bloc+j, variable+v,signe_ok) && j+(i-temp)<taille_totale)
							j++, incrementDiff++;
						j++;
						temp2++;
					}
				}
			}*/

			if (bPasErreur==2)		{
				while(memcmp(fin_ligne, bloc+j, lgFinLigne) && memcmp(bloc+j,chaine+temp,i-temp) && j+(i-temp)<taille_totale)
					j++;
//				Debug("1 %s %i %i %i", variable, memcmp(fin_ligne, bloc+j, lgFinLigne), memcmp(bloc+j,chaine+temp,i-temp), j+(i-temp)<taille_totale);
			}
			else	{
				while(memcmp(bloc+j,chaine+temp,i-temp) && j+(i-temp)<taille_totale)
					j++;
			}

			if (j+(i-temp)>=taille_totale)			{
				gblErrorFlag=1;
				if (bPasErreur)
					return j;
				else		{
					Debug("Erreur de format de fichier (#)");
					return taille_totale+1;
				}
			}

			//Impossible de trouver le nombre
			if (incrementDiff==-1)
				incrementDiff=j-temp2;
			memcpy(chne,bloc+temp2,incrementDiff);
			chne[incrementDiff]=0;
			EcritSymboleType(variable,chne,sd);
			if (bPasErreur==2)		{
				if (!memcmp(fin_ligne, bloc+j, lgFinLigne))
					return j;
			}

//			Debug("%s=%s",variable,chne);

			i=temp;
		}
		else		{
			gblErrorFlag=1;
			if (bPasErreur)
				return j;
			else		{
				Debug("Le format du fichier ne correspond pas avec celui attendu. (#)");
				return taille_totale+1;
			}
		}
	}
	return j;
}

//Marche pas vraiment
/*void ReallocNbreMaxEleListe(int nbEle)			{
	int i,j;
	NB_MAX_ELE_LISTE=nbEle;
	VideUndoBuffer();
	for (i=0;i<nMaps;i++)		{
		if (params[i].gblTypeMap==TYPE_LISTE)		{
			params[i].gblSpriteListe.sd=(SPRITE_DEF*)realloc(params[i].gblSpriteListe.sd, NB_MAX_ELE_LISTE*sizeofSD);
			for (j=0;j<MAXBLOCS;j++)		{
				listeCopie[j].nbSprites=0;
				listeCopie[j].sd=(SPRITE_DEF*)realloc(listeCopie[j].sd, NB_MAX_ELE_LISTE*sizeofSD);
			}
		}
	}
}*/
