Delay the creation of the X atoms until we really need them, to allow
getting more of them in one call.
Use XGetAtomNames to retrieve all the selection atoms at once.

diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index 3fe78a4..090bee3 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -58,6 +58,7 @@
  *    and vice versa. If a native format is available in the selection, it takes
  *    precedence, in order to avoid unnecessary conversions.
  *
+ * FIXME: global format list needs a critical section
  */
 
 #include "config.h"
@@ -123,7 +124,7 @@
     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
 HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget,
     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
-static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop);
+static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop);
 static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID);
 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
@@ -257,11 +258,10 @@
 /**************************************************************************
  *		X11DRV_InitClipboard
  */
-void X11DRV_InitClipboard(Display *display)
+void X11DRV_InitClipboard(void)
 {
     INT i;
     HKEY hkey;
-    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
 
     if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
     {
@@ -272,18 +272,6 @@
         RegCloseKey(hkey);
     }
 
-    /* Register known formats */
-    while (lpFormat)
-    {
-        if (!lpFormat->wFormatID)
-            lpFormat->wFormatID = GlobalAddAtomA(lpFormat->Name);
-
-        if (!lpFormat->drvData)
-            lpFormat->drvData = TSXInternAtom(display, lpFormat->Name, False);
-
-	lpFormat = lpFormat->NextFormat;
-    }
-
     /* Register known mapping between window formats and X properties */
     for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
         X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat,
@@ -292,6 +280,64 @@
 
 
 /**************************************************************************
+ *                intern_atoms
+ *
+ * Intern atoms for formats that don't have one yet.
+ */
+static void intern_atoms(void)
+{
+    LPWINE_CLIPFORMAT format;
+    int i, count;
+    char **names;
+    Atom *atoms;
+
+    for (format = ClipFormats, count = 0; format; format = format->NextFormat)
+        if (!format->drvData) count++;
+    if (!count) return;
+
+    names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
+    atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
+
+    for (format = ClipFormats, i = 0; format; format = format->NextFormat)
+        if (!format->drvData) names[i++] = format->Name;
+
+    wine_tsx11_lock();
+    XInternAtoms( thread_display(), names, count, False, atoms );
+    wine_tsx11_unlock();
+
+    for (format = ClipFormats, i = 0; format; format = format->NextFormat)
+        if (!format->drvData) format->drvData = atoms[i];
+
+    HeapFree( GetProcessHeap(), 0, names );
+    HeapFree( GetProcessHeap(), 0, atoms );
+}
+
+
+/**************************************************************************
+ *		register_format
+ *
+ * Register a custom X clipboard format.
+ */
+static WINE_CLIPFORMAT *register_format( LPCSTR FormatName, Atom prop )
+{
+    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
+
+    TRACE("'%s'\n", FormatName);
+
+    /* walk format chain to see if it's already registered */
+    while (lpFormat)
+    {
+	if ( !strcasecmp(lpFormat->Name, FormatName) && 
+	     (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
+	     return lpFormat;
+	lpFormat = lpFormat->NextFormat;
+    }
+
+    return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
+}
+
+
+/**************************************************************************
  *                X11DRV_CLIPBOARD_LookupFormat
  */
 LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
@@ -305,7 +351,7 @@
 
 	lpFormat = lpFormat->NextFormat;
     }
-
+    if (!lpFormat->drvData) intern_atoms();
     return lpFormat;
 }
 
@@ -315,17 +361,21 @@
  */
 LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
 {
-    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
-
-    while(lpFormat)
+    for (;;)
     {
-        if (lpFormat->drvData == drvData) 
-            break;
+        LPWINE_CLIPFORMAT lpFormat = ClipFormats;
+        BOOL need_intern = FALSE;
 
-	lpFormat = lpFormat->NextFormat;
+        while(lpFormat)
+        {
+            if (lpFormat->drvData == drvData) return lpFormat;
+            if (!lpFormat->drvData) need_intern = TRUE;
+            lpFormat = lpFormat->NextFormat;
+        }
+        if (!need_intern) return NULL;
+        intern_atoms();
+        /* restart the search for the new atoms */
     }
-
-    return lpFormat;
 }
 
 
@@ -400,7 +450,7 @@
 /**************************************************************************
  *		InsertClipboardFormat
  */
-static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
+static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
 {
     LPWINE_CLIPFORMAT lpFormat;
     LPWINE_CLIPFORMAT lpNewFormat;
@@ -412,14 +462,14 @@
     if(lpNewFormat == NULL) 
     {
         WARN("No more memory for a new format!\n");
-        return 0;
+        return NULL;
     }
 
     if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1)))
     {
         WARN("No more memory for the new format name!\n");
         HeapFree(GetProcessHeap(), 0, lpNewFormat);
-        return 0;
+        return NULL;
     }
 
     strcpy(lpNewFormat->Name, FormatName);
@@ -442,7 +492,7 @@
     TRACE("Registering format(%d): %s drvData %d\n",
         lpNewFormat->wFormatID, FormatName, lpNewFormat->drvData);
 
-    return lpNewFormat->wFormatID;
+    return lpNewFormat;
 }
 
 
@@ -1358,15 +1408,16 @@
     }
     else
     {
-       TRACE("Type %s,Format %d,nItems %ld, Remain %ld\n",
-             TSXGetAtomName(display,atype),aformat,cSelectionTargets, remain);
+       TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
+             atype, aformat, cSelectionTargets, remain);
        /*
         * The TARGETS property should have returned us a list of atoms
         * corresponding to each selection target format supported.
         */
        if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32)
        {
-          INT i;
+          INT i, nb_atoms = 0;
+          Atom *atoms = NULL;
 
           /* Cache these formats in the clipboard cache */
           for (i = 0; i < cSelectionTargets; i++)
@@ -1378,24 +1429,45 @@
 
               if (!lpFormat)
               {
-                  LPSTR lpName = TSXGetAtomName(display, targetList[i]); 
-                  X11DRV_RegisterClipboardFormat(lpName);
-
-                  lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]);
-
-		  if (!lpFormat)
-                  {
-                      ERR("Failed to cache %s property\n", lpName);
-                      continue;
-                  }
-
-                  TSXFree(lpName);
+                  /* add it to the list of atoms that we don't know about yet */
+                  if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
+                                                 (cSelectionTargets - i) * sizeof(*atoms) );
+                  if (atoms) atoms[nb_atoms++] = targetList[i];
               }
+              else
+              {
+                  TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
+                        i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
+                  X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
+              }
+          }
 
-              TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
-                  i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
-
-              X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
+          /* query all unknown atoms in one go */
+          if (atoms)
+          {
+              char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
+              if (names)
+              {
+                  wine_tsx11_lock();
+                  XGetAtomNames( display, atoms, nb_atoms, names );
+                  wine_tsx11_unlock();
+                  for (i = 0; i < nb_atoms; i++)
+                  {
+                      WINE_CLIPFORMAT *lpFormat = register_format( names[i], atoms[i] );
+                      if (!lpFormat)
+                      {
+                          ERR("Failed to cache %s property\n", names[i]);
+                          continue;
+                      }
+                      TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
+                            i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
+                      X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
+                  }
+                  wine_tsx11_lock();
+                  for (i = 0; i < nb_atoms; i++) XFree( names[i] );
+                  wine_tsx11_unlock();
+                  HeapFree( GetProcessHeap(), 0, names );
+              }
           }
        }
 
@@ -1808,29 +1880,11 @@
  */
 INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName)
 {
-    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
-    Atom prop;
+    LPWINE_CLIPFORMAT lpFormat;
 
-    if (FormatName == NULL) 
-        return 0;
-
-    TRACE("('%s') !\n", FormatName);
-
-    /* walk format chain to see if it's already registered */
-    while(TRUE)
-    {
-	if ( !strcasecmp(lpFormat->Name, FormatName) && 
-	     (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
-	     return lpFormat->wFormatID;
-
-        if (!lpFormat->NextFormat)
-            break;
-
-	lpFormat = lpFormat->NextFormat;
-    }
-
-    prop = TSXInternAtom( thread_display(), FormatName, False );
-    return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
+    if (FormatName == NULL) return 0;
+    if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
+    return lpFormat->wFormatID;
 }