DirectDraw status updated.
Use cooperative window for drawing in xlib implementation if possible.
Slightly restructured IDirectDrawSurface::Blt so it doesn't crash.

diff --git a/documentation/status/directdraw b/documentation/status/directdraw
index 04b0e1a..a19ca49 100644
--- a/documentation/status/directdraw
+++ b/documentation/status/directdraw
@@ -23,13 +23,6 @@
 	  framebuffer into the addressspace of the process.
 	- Blocks all other X windowed applications.
 
-TODO:
-	- Add more implementations of the DirectDraw API.
-	  Primary candidate is a raw Xlib implementation (one with/one without
-	  XShm extension).
-	  An additional layer (basically a HAL) will be required to decide on 
-	  case-by-case basis which implementation to use.
-
 Status:
    - Diablo [640x480x8]:
      The movies play with speed comparable to the MS DDRAW one.
@@ -49,12 +42,10 @@
      but it crashes as soon as you arrive at Blue Point Station...
   
    - Monkey Island 3 [640x480x8]:
-     Goes to the easy/hard selection screen, then hangs due to multithreaded
-     windows-messagehandling problems.
+     WINE-CVS-981116: 
+     	Works, using DGA and Xlib. (Mousecontrol is a bit off in windowed mode.)
    
    - DiscWorld 2 [640x480x8]:
-     [Crashes with 'cli' in WINE released version. Yes. Privileged instructions
-      in 32bit code. Will they ever learn...]
      Plays through nearly all intro movies. Sound and animation skip a lot of
      stuff (possible DirectSound asynchronization problem).
    
@@ -68,7 +59,5 @@
      DirectInput.
   
    - WingCommander Prophecy Demo (using software renderer) [640x480x16]:
-     [Crashes with an invalid opcode (outb, probably to test for 3dFX) in the
-      WINE release version.]
      Plays trailer, hangs in selection screen (no keyboard input, DirectInput
      problem).
diff --git a/graphics/ddraw.c b/graphics/ddraw.c
index aa2beba..27fbf4d 100644
--- a/graphics/ddraw.c
+++ b/graphics/ddraw.c
@@ -1,8 +1,9 @@
-/*		DirectDraw using DGA or Xlib
+/*		DirectDraw using DGA or Xlib(XSHM)
  *
  * Copyright 1997,1998 Marcus Meissner
  */
-/* When DirectVideo mode is enabled you can no longer use 'normal' X 
+/* XF86DGA:
+ * When DirectVideo mode is enabled you can no longer use 'normal' X 
  * applications nor can you switch to a virtual console. Also, enabling
  * only works, if you have switched to the screen where the application
  * is running.
@@ -10,7 +11,6 @@
  * - A terminal connected to the serial port. Can be bought used for cheap.
  *   (This is the method I am using.)
  * - Another machine connected over some kind of network.
- *
  */
 
 #include "config.h"
@@ -49,7 +49,7 @@
 /* define this if you want to play Diablo using XF86DGA. (bug workaround) */
 #undef DIABLO_HACK
 
-/* restore signal handlers overwritten by XF86DGA 
+/* Restore signal handlers overwritten by XF86DGA 
  * this is a define, for it will only work in emulator mode
  */
 #undef RESTORE_SIGNALS
@@ -350,7 +350,7 @@
 		return DD_OK;
 
   /* Only redraw the screen when unlocking the buffer that is on screen */
-  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen))
+  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) {
 #ifdef HAVE_LIBXXSHM
     if (this->s.ddraw->e.xlib.xshm_active)
       TSXShmPutImage(display,
@@ -370,6 +370,7 @@
 				0, 0, 0, 0,
 				this->t.xlib.image->width,
 		  this->t.xlib.image->height);
+  }
   
 	if (this->s.palette && this->s.palette->cm)
 		TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm);
@@ -428,7 +429,7 @@
 	}
   
 #ifdef HAVE_LIBXXSHM
-	if (this->s.ddraw->e.xlib.xshm_active)
+	if (this->s.ddraw->e.xlib.xshm_active) {
 	  TSXShmPutImage(display,
 			 this->s.ddraw->e.xlib.drawable,
 			 DefaultGCOfScreen(screen),
@@ -437,7 +438,7 @@
 			 flipto->t.xlib.image->width,
 			 flipto->t.xlib.image->height,
 			 False);
-	else
+	} else
 #endif
 	TSXPutImage(display,
 				this->s.ddraw->e.xlib.drawable,
@@ -460,7 +461,6 @@
 		this->s.surface = flipto->s.surface;
 		flipto->s.surface = surf;
 	}
-
 	return 0;
 }
 
@@ -562,11 +562,15 @@
 
 	if (rsrc) {
 		memcpy(&xsrc,rsrc,sizeof(xsrc));
-	} else if (src) {
+	} else {
+		if (src) {
 		xsrc.top	= 0;
 		xsrc.bottom	= src->s.height;
 		xsrc.left	= 0;
 		xsrc.right	= src->s.width;
+		} else {
+		    memset(&xsrc,0,sizeof(xsrc));
+		}
 	}
 
 	dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
@@ -590,7 +594,15 @@
 			xline += this->s.lpitch;
 		}
 		dwFlags &= ~(DDBLT_COLORFILL);
-	} else { 	  /* Once we have done colorfill, we do not do anything else... */
+	}
+
+	if (!src) {
+	    if (dwFlags) {
+	      TRACE(ddraw,"\t(src=NULL):Unsupported flags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n");
+	    }
+	    return 0;
+	}
+
 	if (	(xsrc.top ==0) && (xsrc.bottom ==this->s.height) &&
 		(xsrc.left==0) && (xsrc.right  ==this->s.width) &&
 		(xdst.top ==0) && (xdst.bottom ==this->s.height) &&
@@ -598,11 +610,7 @@
 		!dwFlags
 	) {
 		memcpy(this->s.surface,src->s.surface,this->s.height*this->s.lpitch);
-		return 0;
 	} else {
-	  /* Non full screen Blit. In this case, we need to copy line per line.
-	     WARNING : if the program behaves badly (ie sizes of structures are different
-	               or buffer not big enough) this may crash Wine... */
 	  int bpp = this->s.ddraw->d.depth / 8;
 	  int height = xsrc.bottom - xsrc.top;
 	  int width = (xsrc.right - xsrc.left) * bpp;
@@ -614,12 +622,10 @@
 		   width);
 	  }
 	}
-	}
 	
-	if (dwFlags) {
-	  TRACE(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n");
+	if (dwFlags && FIXME_ON(ddraw)) {
+	  FIXME(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);
 	}
-	
 	return 0;
 }
 
@@ -635,7 +641,7 @@
   if (!this->s.ddraw->e.xlib.paintable)
     return ret;
 
-  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen))
+  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) {
 #ifdef HAVE_LIBXXSHM
     if (this->s.ddraw->e.xlib.xshm_active)
       TSXShmPutImage(display,
@@ -655,6 +661,7 @@
 		  0, 0, 0, 0,
 		  this->t.xlib.image->width,
 		  this->t.xlib.image->height);
+  }
   if (this->s.palette && this->s.palette->cm)
     TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm);
 
@@ -754,9 +761,8 @@
 	if (!--(this->ref)) {
 		this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
 
-    if( this->s.backbuffer ) {
+		if( this->s.backbuffer )
 		  this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
- 		}
 
     if (this->t.xlib.image != NULL) {
 		this->t.xlib.image->data = NULL;
@@ -809,9 +815,7 @@
 	*lpdsf = this->s.backbuffer;
  
         if( this->s.backbuffer )
-        {
           this->s.backbuffer->lpvtbl->fnAddRef( this->s.backbuffer );
-        }
 
 	return 0;
 }
@@ -1738,6 +1742,10 @@
 	return 0;
 }
 
+/* 
+ * The Xlib Implementation tries to use the passed hwnd as drawing window,
+ * even when the approbiate bitmasks are not specified.
+ */
 static HRESULT WINAPI IDirectDraw2_SetCooperativeLevel(
 	LPDIRECTDRAW2 this,HWND32 hwnd,DWORD cooplevel
 ) {
@@ -1769,13 +1777,54 @@
 	return 0;
 }
 
+/* Small helper to either use the cooperative window or create a new 
+ * one (for mouse and keyboard input) and drawing in the Xlib implementation.
+ */
+static void _common_IDirectDraw_SetDisplayMode(LPDIRECTDRAW this) {
+	RECT32	rect;
+
+	/* Do not destroy the application supplied cooperative window */
+	if (this->d.window && this->d.window != this->d.mainWindow) {
+		DestroyWindow32(this->d.window);
+		this->d.window = 0;
+	}
+	/* Sanity check cooperative window before assigning it to drawing. */
+	if (	IsWindow32(this->d.mainWindow) &&
+		IsWindowVisible32(this->d.mainWindow)
+	) {
+		GetWindowRect32(this->d.mainWindow,&rect);
+		if (((rect.right-rect.left) >= this->d.width)	&&
+		    ((rect.bottom-rect.top) >= this->d.height)
+		)
+			this->d.window = this->d.mainWindow;
+	}
+	/* ... failed, create new one. */
+	if (!this->d.window) {
+	    this->d.window = CreateWindowEx32A(
+		    0,
+		    "WINE_DirectDraw",
+		    "WINE_DirectDraw",
+		    WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME,
+		    0,0,
+		    this->d.width,
+		    this->d.height,
+		    0,
+		    0,
+		    0,
+		    NULL
+	    );
+	    /*Store THIS with the window. We'll use it in the window procedure*/
+	    SetWindowLong32A(this->d.window,ddrawXlibThisOffset,(LONG)this);
+	    ShowWindow32(this->d.window,TRUE);
+	    UpdateWindow32(this->d.window);
+	}
+}
 
 static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode(
 	LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
 ) {
 #ifdef HAVE_LIBXXF86DGA
 	int	i,*depths,depcount;
-	HWND32 window;
 
 	TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", this, width, height, depth);
 
@@ -1794,31 +1843,13 @@
 	}
 	this->d.width	= width;
 	this->d.height	= height;
+	this->d.depth	= depth;
+
 	/* adjust fb_height, so we don't overlap */
 	if (this->e.dga.fb_height < height)
 		this->e.dga.fb_height = height;
-	this->d.depth	= depth;
+	_common_IDirectDraw_SetDisplayMode(this);
 
-	/* First, create a window for this mode. Apparently, some games
-	   (such as Monkey Island III) do not do this properly for themselves. */
-	window = CreateWindowEx32A(
-		0,
-		"WINE_DirectDraw",
-		"WINE_DirectDraw",
-		WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME,
-		0,0,
-		width,
-		height,
-		0,
-		0,
-		0,
-		NULL
-	);
-	SetWindowLong32A(window,ddrawXlibThisOffset,(LONG)this);
-	ShowWindow32(window,TRUE);
-	UpdateWindow32(window);
-	assert(window);
-	
 	/* FIXME: this function OVERWRITES several signal handlers. 
 	 * can we save them? and restore them later? In a way that
 	 * it works for the library too?
@@ -1856,44 +1887,17 @@
 		MessageBox32A(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
 		return DDERR_UNSUPPORTEDMODE;
 	}
-	
-	if (this->d.window)
-		DestroyWindow32(this->d.window);
-	this->d.window = CreateWindowEx32A(
-		0,
-		"WINE_DirectDraw",
-		"WINE_DirectDraw",
-		WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME,
-		0,0,
-		width,
-		height,
-		0,
-		0,
-		0,
-		NULL
-	);
-
-        /* Store this with the window. We'll use it for the window procedure */
-	SetWindowLong32A(this->d.window,ddrawXlibThisOffset,(LONG)this);
-
-	this->e.xlib.paintable = 1;
-
-	ShowWindow32(this->d.window,TRUE);
-	UpdateWindow32(this->d.window);
-
-	assert(this->d.window);
-
-        this->e.xlib.drawable  = WIN_FindWndPtr(this->d.window)->window;  
-
-        /* We don't have a context for this window. Host off the desktop */
-        if( !this->e.xlib.drawable )
-        {
-           this->e.xlib.drawable = WIN_GetDesktop()->window;
-        }
-
 	this->d.width	= width;
 	this->d.height	= height;
 	this->d.depth	= depth;
+
+	_common_IDirectDraw_SetDisplayMode(this);
+
+	this->e.xlib.paintable = 1;
+        this->e.xlib.drawable  = WIN_FindWndPtr(this->d.window)->window;  
+        /* We don't have a context for this window. Host off the desktop */
+        if( !this->e.xlib.drawable )
+           this->e.xlib.drawable = WIN_GetDesktop()->window;
 	return 0;
 }
 
@@ -1922,11 +1926,11 @@
 	TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2);
 	/* FIXME: Xlib */
 	caps1->dwVidMemTotal = 2048*1024;
-	caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);		/* we can do anything */
+	caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED|DDCAPS_GDI);
 	caps1->ddsCaps.dwCaps = 0xffffffff;	/* we can do anything */
 	if (caps2) {
 		caps2->dwVidMemTotal = 2048*1024;
-		caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED);		/* we can do anything */
+		caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED|DDCAPS_GDI);
 		caps2->ddsCaps.dwCaps = 0xffffffff;	/* we can do anything */
 	}
 	/* END FIXME: Xlib */
@@ -2528,15 +2532,11 @@
 	  }
         }
         
-      }
-      else
-      {
+      } else {
         ret = DefWindowProc32A(hwnd, msg, wParam, lParam );
       } 
 
-    }
-    else
-    {
+    } else {
 	ret = DefWindowProc32A(hwnd,msg,wParam,lParam);
     }
 
diff --git a/graphics/wing.c b/graphics/wing.c
index 0216670..3654cad 100644
--- a/graphics/wing.c
+++ b/graphics/wing.c
@@ -148,7 +148,7 @@
 		    WORD	sel = 0;
 
 		    TSXShmAttach(display, &p->si);
-		    bmpObjPtr->pixmap = XShmCreatePixmap(display, rootWindow, 
+		    bmpObjPtr->pixmap = TSXShmCreatePixmap(display, rootWindow, 
 				  p->si.shmaddr, &p->si, bmpObjPtr->bitmap.bmWidth, 
 				  bmpObjPtr->bitmap.bmHeight, bmpi->biBitCount );
 		    if( bmpObjPtr->pixmap )
diff --git a/include/ddraw.h b/include/ddraw.h
index 2e5d310..8deb38a 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -935,34 +935,37 @@
 typedef struct IDirectDraw2_VTable
 {
     /*** IUnknown methods ***/
-    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
-    STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
-    STDMETHOD_(ULONG,Release) (THIS) PURE;
+/*00*/	STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE;
+/*04*/	STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+/*08*/	STDMETHOD_(ULONG,Release) (THIS) PURE;
     /*** IDirectDraw methods ***/
-    STDMETHOD(Compact)(THIS) PURE;
-    STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
-    STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
-    STDMETHOD(CreateSurface)(THIS_  LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *,
-IUnknown FAR *) PURE;
-    STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE
-FAR * ) PURE;
-    STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE;
-    STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE;
-    STDMETHOD(FlipToGDISurface)(THIS) PURE;
-    STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
-    STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
-    STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
-    STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
-    STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
-    STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
-    STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE;
-    STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
-    STDMETHOD(RestoreDisplayMode)(THIS) PURE;
-    STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE;
-    STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD, DWORD, DWORD, DWORD) PURE;
-    STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE;
+/*0C*/	STDMETHOD(Compact)(THIS) PURE;
+/*10*/	STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
+/*14*/	STDMETHOD(CreatePalette)(THIS_ DWORD,LPPALETTEENTRY,
+				 LPDIRECTDRAWPALETTE FAR*, IUnknown FAR *) PURE;
+/*18*/	STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC,LPDIRECTDRAWSURFACE
+				 FAR *, IUnknown FAR *) PURE;
+/*1C*/	STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE, 
+				    LPDIRECTDRAWSURFACE FAR * ) PURE;
+/*20*/	STDMETHOD(EnumDisplayModes)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,
+				    LPDDENUMMODESCALLBACK ) PURE;
+/*24*/	STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,
+				LPDDENUMSURFACESCALLBACK ) PURE;
+/*28*/	STDMETHOD(FlipToGDISurface)(THIS) PURE;
+/*2C*/	STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE;
+/*30*/	STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE;
+/*34*/	STDMETHOD(GetFourCCCodes)(THIS_  LPDWORD, LPDWORD ) PURE;
+/*38*/	STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE;
+/*3C*/	STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE;
+/*40*/	STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE;
+/*44*/	STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE;
+/*48*/	STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+/*4C*/	STDMETHOD(RestoreDisplayMode)(THIS) PURE;
+/*50*/	STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE;
+/*54*/	STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD, DWORD, DWORD, DWORD) PURE;
+/*58*/	STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE;
     /*** Added in the v2 interface ***/
-    STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
+/*5C*/	STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE;
 } IDirectDraw2_VTable,*LPDIRECTDRAW2_VTABLE;
 /* MUST HAVE THE SAME LAYOUT AS struct IDirectDraw */