- clean-up of texture 'loading'
- added SetColorKey callback for already loaded textures

diff --git a/graphics/d3dtexture.c b/graphics/d3dtexture.c
index 2dfeadf..5f4fea0 100644
--- a/graphics/d3dtexture.c
+++ b/graphics/d3dtexture.c
@@ -23,6 +23,72 @@
    texture memory) */
 #undef TEXTURE_SNOOP
 
+#ifdef TEXTURE_SNOOP
+#define SNOOP_PALETTED() 									\
+      {												\
+	FILE *f;										\
+	char buf[32];										\
+	int x, y;										\
+												\
+	sprintf(buf, "%d.pnm", This->tex_name);							\
+	f = fopen(buf, "wb");									\
+	fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);			\
+	for (y = 0; y < src_d->dwHeight; y++) {							\
+	  for (x = 0; x < src_d->dwWidth; x++) {						\
+	    unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+	    fputc(table[c][0], f);								\
+	    fputc(table[c][1], f);								\
+	    fputc(table[c][2], f);								\
+	  }											\
+	}											\
+	fclose(f);										\
+      }
+
+#define SNOOP_5650()											\
+	  {												\
+	    FILE *f;											\
+	    char buf[32];										\
+	    int x, y;											\
+	    												\
+	    sprintf(buf, "%d.pnm", This->tex_name);							\
+	    f = fopen(buf, "wb");									\
+	    fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);				\
+	    for (y = 0; y < src_d->dwHeight; y++) {							\
+	      for (x = 0; x < src_d->dwWidth; x++) {							\
+		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+		fputc((c & 0xF800) >> 8, f);								\
+		fputc((c & 0x07E0) >> 3, f);								\
+		fputc((c & 0x001F) << 3, f);								\
+	      }												\
+	    }												\
+	    fclose(f);											\
+	  }
+
+#define SNOOP_5551()											\
+	  {												\
+	    FILE *f;											\
+	    char buf[32];										\
+	    int x, y;											\
+	    												\
+	    sprintf(buf, "%d.pnm", This->tex_name);							\
+	    f = fopen(buf, "wb");									\
+	    fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);				\
+	    for (y = 0; y < src_d->dwHeight; y++) {							\
+	      for (x = 0; x < src_d->dwWidth; x++) {							\
+		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+		fputc((c & 0xF800) >> 8, f);								\
+		fputc((c & 0x07C0) >> 3, f);								\
+		fputc((c & 0x003E) << 2, f);								\
+	      }												\
+	    }												\
+	    fclose(f);											\
+	  }
+#else
+#define SNOOP_PALETTED()
+#define SNOOP_5650()
+#define SNOOP_5551()
+#endif
+
 static ICOM_VTABLE(IDirect3DTexture2) texture2_vtable;
 static ICOM_VTABLE(IDirect3DTexture) texture_vtable;
 
@@ -56,6 +122,91 @@
   return (LPDIRECT3DTEXTURE)tex;
 }
 
+/*******************************************************************************
+ *			   IDirectSurface callback methods
+ */
+HRESULT WINAPI  SetColorKey_cb(IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
+{
+  DDSURFACEDESC	*tex_d;
+  int bpp;
+  GLuint current_texture;
+  
+  TRACE(ddraw, "(%p) : colorkey callback\n", texture);
+
+  /* Get the texture description */
+  tex_d = &(texture->surface->s.surface_desc);
+  bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
+	 1 /* 8 bit of palette index */:
+	 tex_d->ddpfPixelFormat.x.dwRGBBitCount / 8 /* RGB bits for each colors */ );
+  
+  /* Now, save the current texture */
+  glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
+
+  /* If the GetHandle was not done yet, it's an error */
+  if (texture->tex_name == 0) {
+    ERR(ddraw, "Unloaded texture !\n");
+    return DD_OK;
+  }
+  glBindTexture(GL_TEXTURE_2D, texture->tex_name);
+
+  if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
+    FIXME(ddraw, "Todo Paletted\n");
+  } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
+    if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 8) {
+      FIXME(ddraw, "Todo 3_3_2_0\n");
+    } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 16) {
+      if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000000) {
+	/* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
+	unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
+							    HEAP_ZERO_MEMORY,
+							    tex_d->dwWidth * tex_d->dwHeight * bpp);
+	unsigned short *src = (unsigned short *) tex_d->y.lpSurface;
+	int x, y;
+
+	for (y = 0; y < tex_d->dwHeight; y++) {
+	  for (x = 0; x < tex_d->dwWidth; x++) {
+	    unsigned short cpixel = src[x + y * tex_d->dwWidth];
+	    
+	    if ((dwFlags & DDCKEY_SRCBLT) &&
+		(cpixel >= ckey->dwColorSpaceLowValue) &&
+		(cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
+	      dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
+	    else                                         /* Alpha bit is set => this pixel will be seen */
+	      dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001; 
+	  }
+	}
+
+	glTexImage2D(GL_TEXTURE_2D,
+		     0,
+		     GL_RGBA,
+		     tex_d->dwWidth, tex_d->dwHeight,
+		     0,
+		     GL_RGBA,
+		     GL_UNSIGNED_SHORT_5_5_5_1,
+		     dest);
+
+	/* Frees the temporary surface */
+	HeapFree(GetProcessHeap(),0,dest);
+      } else if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000001) {
+	FIXME(ddraw, "Todo 5_5_5_1\n");
+      } else if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x0000000F) {
+	FIXME(ddraw, "Todo 4_4_4_4\n");
+      } else {
+	ERR(ddraw, "Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
+      }
+    } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 24) {
+      FIXME(ddraw, "Todo 8_8_8_0\n");
+    } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 32) {
+      FIXME(ddraw, "Todo 8_8_8_8\n");
+    } else {
+      ERR(ddraw, "Unhandled texture format (bad RGB count)\n");
+    }
+  } else {
+    ERR(ddraw, "Unhandled texture format (neither RGB nor INDEX)\n");
+  }
+
+  return DD_OK;
+}
 
 /*******************************************************************************
  *				IDirect3DTexture2 methods
@@ -189,7 +340,7 @@
   DDSURFACEDESC	*src_d, *dst_d;
   TRACE(ddraw, "(%p)->(%p)\n", This, ilpD3DTexture2);
 
-  TRACE(ddraw, "Copied to surface %p, surface %p\n", This->surface, ilpD3DTexture2->surface);
+  TRACE(ddraw, "Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
 
   /* Suppress the ALLOCONLOAD flag */
   This->surface->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
@@ -198,6 +349,10 @@
   dst_d = &(This->surface->s.surface_desc);
   src_d = &(ilpD3DTexture2->surface->s.surface_desc);
 
+  /* Install the callbacks to the destination surface */
+  This->surface->s.texture = This;
+  This->surface->s.SetColorKey_cb = SetColorKey_cb;
+  
   if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
     /* Should also check for same pixel format, lPitch, ... */
     ERR(ddraw, "Error in surface sizes\n");
@@ -210,7 +365,8 @@
 	       src_d->ddpfPixelFormat.x.dwRGBBitCount / 8 /* RGB bits for each colors */ );
     GLuint current_texture;
 
-    /* Not sure if this is usefull ! */
+    /* Copy the main memry texture into the surface that corresponds to the OpenGL
+       texture object. */
     memcpy(dst_d->y.lpSurface, src_d->y.lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
 
     /* Now, load the texture */
@@ -248,26 +404,9 @@
 	table[i][3] = 0xFF;
       }
       
-#ifdef TEXTURE_SNOOP
-      {
-	FILE *f;
-	char buf[32];
-	int x, y;
+      /* Texture snooping */
+      SNOOP_PALETTED();
 	
-	sprintf(buf, "%d.pnm", This->tex_name);
-	f = fopen(buf, "wb");
-	fprintf(f, "P6\n%d %d\n255\n", src_d->dwWidth, src_d->dwHeight);
-	for (y = 0; y < src_d->dwHeight; y++) {
-	  for (x = 0; x < src_d->dwWidth; x++) {
-	    unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x];
-	    fputc(table[c][0], f);
-	    fputc(table[c][1], f);
-	    fputc(table[c][2], f);
-	  }
-	}
-	fclose(f);
-      }
-#endif 
       /* Use Paletted Texture Extension */
       glColorTableEXT(GL_TEXTURE_2D,    /* target */
 		      GL_RGBA,          /* internal format */
@@ -302,26 +441,10 @@
 		     src_d->y.lpSurface);
       } else if (src_d->ddpfPixelFormat.x.dwRGBBitCount == 16) {
 	if (src_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000000) {
-#ifdef TEXTURE_SNOOP
-	  {
-	    FILE *f;
-	    char buf[32];
-	    int x, y;
 	    
-	    sprintf(buf, "%d.pnm", This->tex_name);
-	    f = fopen(buf, "wb");
-	    fprintf(f, "P6\n%d %d\n255\n", src_d->dwWidth, src_d->dwHeight);
-	    for (y = 0; y < src_d->dwHeight; y++) {
-	      for (x = 0; x < src_d->dwWidth; x++) {
-		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];
-		fputc((c & 0xF800) >> 8, f);
-		fputc((c & 0x07E0) >> 3, f);
-		fputc((c & 0x001F) << 3, f);
-	      }
-	    }
-	    fclose(f);
-	  }
-#endif
+	  /* Texture snooping */
+	  SNOOP_5650();
+	  
 	  glTexImage2D(GL_TEXTURE_2D,
 		       0,
 		       GL_RGB,
@@ -331,26 +454,8 @@
 		       GL_UNSIGNED_SHORT_5_6_5,
 		       src_d->y.lpSurface);
 	} else if (src_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000001) {
-#ifdef TEXTURE_SNOOP
-	  {
-	    FILE *f;
-	    char buf[32];
-	    int x, y;
-	    
-	    sprintf(buf, "%d.pnm", This->tex_name);
-	    f = fopen(buf, "wb");
-	    fprintf(f, "P6\n%d %d\n255\n", src_d->dwWidth, src_d->dwHeight);
-	    for (y = 0; y < src_d->dwHeight; y++) {
-	      for (x = 0; x < src_d->dwWidth; x++) {
-		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];
-		fputc((c & 0xF800) >> 8, f);
-		fputc((c & 0x07C0) >> 3, f);
-		fputc((c & 0x003E) << 2, f);
-	      }
-	    }
-	    fclose(f);
-	  }
-#endif
+	  /* Texture snooping */
+	  SNOOP_5551();
 	  
 	  glTexImage2D(GL_TEXTURE_2D,
 		       0,