- 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;
+}