- Add a max wait time for selection notifies.
- Add new function to the x11drv to get clipboard format names of
  externally registered formats.
- When a clipboard format is registered we should pass the global atom
  value as the format identifier.
- Clipboard format name should be treated as case insensitive.
- Serialize metafile bits when requested via a clipboard selection.
- Return format ids for native formats when mapping from properties.

diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index e7793ff..4c956bb 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -68,6 +68,7 @@
 # include <unistd.h>
 #endif
 #include <fcntl.h>
+#include <time.h>
 
 #include "ts_xlib.h"
 #include "winreg.h"
@@ -78,6 +79,9 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
 
+/* Maximum wait time for slection notify */
+#define MAXSELECTIONNOTIFYWAIT 5
+
 /* Selection masks */
 
 #define S_NOSELECTION    0
@@ -187,21 +191,20 @@
              * Otherwise register a new atom.
              */
             char str[256];
-            char *fmtName = CLIPBOARD_GetFormatName(wFormat);
+            int plen = strlen(FMT_PREFIX);
+
             strcpy(str, FMT_PREFIX);
 
-            if (fmtName)
-            {
-                strncat(str, fmtName, sizeof(str) - strlen(FMT_PREFIX));
+            if (CLIPBOARD_GetFormatName(wFormat, str + plen, sizeof(str) - plen))
                 prop = TSXInternAtom(thread_display(), str, False);
-            }
+
             break;
         }
     }
 
     if (prop == None)
         TRACE("\tNo mapping to X property for Windows clipboard format %d(%s)\n",
-              wFormat, CLIPBOARD_GetFormatName(wFormat));
+              wFormat, CLIPBOARD_GetFormatName(wFormat, NULL, 0));
 
     return prop;
 }
@@ -377,6 +380,7 @@
     Atom*	   targetList=NULL;
     Window         w;
     Window         ownerSelection = 0;
+    time_t         maxtm;
 
     TRACE("enter\n");
     /*
@@ -410,7 +414,8 @@
     /*
      * Wait until SelectionNotify is received
      */
-    while( TRUE )
+    maxtm = time(NULL) + MAXSELECTIONNOTIFYWAIT; /* Timeout after a maximum wait */
+    while( maxtm - time(NULL) > 0 )
     {
        if( XCheckTypedWindowEvent(display, w, SelectionNotify, &xe) )
            if( xe.xselection.selection == selectionCacheSrc )
@@ -624,9 +629,9 @@
 	      GlobalUnlock(hUnicodeText);
 	      if (!SetClipboardData(CF_UNICODETEXT, hUnicodeText))
 	      {
-            ERR("Not SET! Need to free our own block\n");
-		    GlobalFree(hUnicodeText);
-          }
+                  ERR("Not SET! Need to free our own block\n");
+                  GlobalFree(hUnicodeText);
+              }
 	      bRet = TRUE;
 	  }
 	  HeapFree(GetProcessHeap(), 0, lpstr);
@@ -689,15 +694,22 @@
 
       if( cBytes )
       {
-        /* Turn on the DDESHARE flag to enable shared 32 bit memory */
-        hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes );
-        if( (lpClipData = GlobalLock(hClipData)) )
-        {
-            memcpy(lpClipData, val, cBytes);
-            GlobalUnlock(hClipData);
-        }
-        else
-            hClipData = 0;
+          if (wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE)
+          {
+              hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, (HANDLE)val, cBytes, FALSE);
+          }
+          else
+          {
+              /* Turn on the DDESHARE flag to enable shared 32 bit memory */
+              hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes );
+              if( (lpClipData = GlobalLock(hClipData)) )
+              {
+                  memcpy(lpClipData, val, cBytes);
+                  GlobalUnlock(hClipData);
+              }
+              else
+                  hClipData = 0;
+          }
       }
 
       if( hClipData )
@@ -1022,9 +1034,9 @@
  *		RegisterClipboardFormat (X11DRV.@)
  *
  * Registers a custom X clipboard format
- * Returns: TRUE - success,  FALSE - failure
+ * Returns: Format id or 0 on failure
  */
-BOOL X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
+INT X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
 {
     Display *display = thread_display();
     Atom prop = None;
@@ -1042,7 +1054,7 @@
         prop = TSXInternAtom(display, str, False);
     }
 
-    return (prop) ? TRUE : FALSE;
+    return prop;
 }
 
 /**************************************************************************
@@ -1141,7 +1153,7 @@
         else
             bRet = FALSE;
 
-        TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat), bRet );
+        TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat, NULL, 0), bRet );
     }
 
     TRACE("Returning %d\n", bRet);
@@ -1313,3 +1325,89 @@
         else prop = &(*prop)->next;
     }
 }
+
+/**************************************************************************
+ *		X11DRV_GetClipboardFormatName
+ */
+BOOL X11DRV_GetClipboardFormatName( UINT wFormat, LPSTR retStr, UINT maxlen )
+{
+    BOOL bRet = FALSE;
+    char *itemFmtName = TSXGetAtomName(thread_display(), wFormat);
+    INT prefixlen = strlen(FMT_PREFIX);
+
+    if ( 0 == strncmp(itemFmtName, FMT_PREFIX, prefixlen ) )
+    {
+        strncpy(retStr, itemFmtName + prefixlen, maxlen);
+        bRet = TRUE;
+    }
+
+    TSXFree(itemFmtName);
+
+    return bRet;
+}
+
+
+/**************************************************************************
+ *		CLIPBOARD_SerializeMetafile
+ */
+HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, INT cbytes, BOOL out)
+{
+    HANDLE h = 0;
+
+    if (out) /* Serialize out, caller should free memory */
+    {
+        if (wformat == CF_METAFILEPICT)
+        {
+            LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
+            int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
+
+            h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
+            if (h)
+            {
+                LPVOID pdata = GlobalLock(h);
+
+                memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
+                GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
+
+                GlobalUnlock(h);
+            }
+
+            GlobalUnlock(hdata);
+        }
+        else if (wformat == CF_ENHMETAFILE)
+        {
+            int size = GetEnhMetaFileBits(hdata, 0, NULL);
+
+            h = GlobalAlloc(0, size);
+            if (h)
+            {
+                LPVOID pdata = GlobalLock(h);
+                GetEnhMetaFileBits(hdata, size, pdata);
+                GlobalUnlock(h);
+            }
+        }
+    }
+    else
+    {
+        if (wformat == CF_METAFILEPICT)
+        {
+            h = GlobalAlloc(0, sizeof(METAFILEPICT));
+            if (h)
+            {
+                LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
+
+                memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
+                pmfp->hMF = SetMetaFileBitsEx(cbytes - sizeof(METAFILEPICT),
+                                              (LPVOID)hdata + sizeof(METAFILEPICT));
+
+                GlobalUnlock(h);
+            }
+        }
+        else if (wformat == CF_ENHMETAFILE)
+        {
+            h = SetEnhMetaFileBits(cbytes, (LPVOID)hdata);
+        }
+    }
+
+    return h;
+}
diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c
index c774180..ff173bd 100644
--- a/dlls/x11drv/event.c
+++ b/dlls/x11drv/event.c
@@ -584,7 +584,7 @@
      */
     itemFmtName = TSXGetAtomName(display, target);
     TRACE("Request for %s (wFormat=%x %s)\n",
-	itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
+	itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT, NULL, 0));
     TSXFree(itemFmtName);
 
     hUnicodeText = GetClipboardData(CF_UNICODETEXT);
@@ -650,7 +650,7 @@
     itemFmtName = TSXGetAtomName(display, target);
     wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
     TRACE("Request for %s (wFormat=%x %s)\n",
-                  itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
+                  itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0 ));
     TSXFree(itemFmtName);
 
     hClipData = GetClipboardData(wFormat);
@@ -683,7 +683,7 @@
     else
     {
         FIXME("%s to PIXMAP conversion not yet implemented!\n",
-                      CLIPBOARD_GetFormatName(wFormat));
+                      CLIPBOARD_GetFormatName(wFormat, NULL, 0));
         rprop = None;
         goto END;
     }
@@ -739,6 +739,7 @@
     char * itemFmtName;
     int cBytes;
     int xRc;
+    int bemf;
 
     /*
      * Map the requested X selection property type atom name to a
@@ -747,11 +748,15 @@
     itemFmtName = TSXGetAtomName(display, target);
     wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
     TRACE("Request for %s (wFormat=%x %s)\n",
-          itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
+          itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0));
     TSXFree(itemFmtName);
 
     hClipData = GetClipboardData(wFormat);
 
+    bemf = wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE;
+    if (bemf)
+        hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, hClipData, sizeof(hClipData), TRUE);
+
     if( hClipData && (lpClipData = GlobalLock(hClipData)) )
     {
         cBytes = GlobalSize(hClipData);
@@ -772,6 +777,9 @@
         rprop = None; /* Fail the request */
     }
 
+    if (bemf) /* We must free serialized metafile data */
+        GlobalFree(hClipData);
+
     return rprop;
 }
 
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index 81fdd04..c9bd61f 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -96,5 +96,6 @@
 @ cdecl GetClipboardData(long) X11DRV_GetClipboardData
 @ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
 @ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
+@ cdecl GetClipboardFormatName(long str long) X11DRV_GetClipboardFormatName
 @ cdecl IsSelectionOwner() X11DRV_IsSelectionOwner
 @ cdecl ResetSelectionOwner(ptr long) X11DRV_ResetSelectionOwner