clipboard

Aric Stewart aric at codeweavers.com
Wed Feb 21 18:55:30 CST 2001


This patch address three clipboard issues.
1st, We where not giving enough room for the null termination of the 
text string when converting from one format to another (I do not know if 
this was posted in a previous patch of mine or not, i have been busy 
recently and not paying alot of attention to what I have already posted)

2nd, We NEED to make sure we pay attention to if our call to 
SetClipboardData from the X11DRV version of the function works. if not 
we need to delete the global block we allocated. This is a sever memory 
leak with large clipboard items.

3nd, If an x selection it too large then x may give it to us in chunks. 
we where not handling this well. Additionally in my reading i found that 
sometimes X does not like being queried for large blocks all at once. So 
i instead ask for smaller chunks in a loop to retreave the a selection.

There is one part of 3 that is still unaddressed, that is the INCR type. 
Some X programs will give an INCR type to us if the selection is large. 
We currently just bail in this case. We should handle the INCR and 
actaully get the data.

-aric
-------------- next part --------------
Index: windows/clipboard.c
===================================================================
RCS file: /home/wine/wine/windows/clipboard.c,v
retrieving revision 1.36
diff -u -u -r1.36 clipboard.c
--- windows/clipboard.c	2001/02/20 01:54:08	1.36
+++ windows/clipboard.c	2001/02/22 00:43:32
@@ -617,6 +617,9 @@
 	else
 	    src_chars = strlen(lpstrS)+1;
 
+   /* Make room for NULL termination */ 
+    src_chars++;
+
 	/* Calculate number of characters in the destination buffer */
 	dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
 				     lpTarget->wFormatID, NULL, 0);
Index: windows/x11drv/clipboard.c
===================================================================
RCS file: /home/wine/wine/windows/x11drv/clipboard.c,v
retrieving revision 1.28
diff -u -u -r1.28 clipboard.c
--- windows/x11drv/clipboard.c	2001/02/12 03:49:07	1.28
+++ windows/x11drv/clipboard.c	2001/02/22 00:43:33
@@ -460,9 +460,10 @@
 {
     Atom	      atype=AnyPropertyType;
     int		      aformat;
-    unsigned long     nitems,remain,itemSize;
-    long              lRequestLength;
-    unsigned char*    val=NULL;
+    unsigned long     total,nitems,remain,itemSize,val_cnt;
+    long              lRequestLength,bwc;
+    unsigned char*    val;
+    unsigned char*    buffer;
     LPWINE_CLIPFORMAT lpFormat;
     BOOL              bRet = FALSE;
     HWND              hWndClipWindow = GetOpenClipboardWindow();
@@ -495,26 +496,40 @@
     
     TRACE("\tretrieving %ld bytes...\n", itemSize * aformat/8);
     lRequestLength = (itemSize * aformat/8)/4  + 1;
-    
-    /*
-     * Retrieve the actual property in the required X format.
-     */
-    if(TSXGetWindowProperty(display,w,prop,0,lRequestLength,False,AnyPropertyType/*reqType*/,
-                            &atype, &aformat, &nitems, &remain, &val) != Success)
+
+   bwc = aformat/8; 
+   /* we want to read the property, but not it too large of chunks or 
+      we could hang the cause problems. Lets go for 4k blocks */
+
+    if(TSXGetWindowProperty(display,w,prop,0,4096,False,
+                            AnyPropertyType/*reqType*/,
+                            &atype, &aformat, &nitems, &remain, &buffer) 
+        != Success)
     {
         WARN("\tcouldn't read property\n");
         return bRet;
     }
+   val = (char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+                          nitems*bwc);
+   memcpy(val,buffer,nitems*bwc);
+   TSXFree(buffer);
+
+   for (total = nitems*bwc,val_cnt=0; remain;)
+   {
+       val_cnt +=nitems*bwc;
+       TSXGetWindowProperty(display, w, prop,
+                          (total / 4), 4096, False,
+                          AnyPropertyType, &atype,
+                          &aformat, &nitems, &remain,
+                          &buffer);
+
+       total += nitems*bwc;
+       HeapReAlloc(GetProcessHeap(),0,val, total);
+       memcpy(&val[val_cnt], buffer, nitems*(aformat/8));
+       TSXFree(buffer);
+   }
+   nitems = total;
 
-    TRACE("\tType %s,Format %d,nitems %ld,remain %ld,value %s\n",
-          atype ? TSXGetAtomName(display,atype) : NULL, aformat,nitems,remain,val);
-    
-    if (remain)
-    {
-        WARN("\tCouldn't read entire property- selection may be too large! Remain=%ld\n", remain);
-        goto END;
-    }
-    
     /*
      * Translate the X property into the appropriate Windows clipboard
      * format, if possible.
@@ -526,8 +541,6 @@
       int 	   i,inlcount = 0;
       char*      lpstr;
  
-      TRACE("\tselection is '%s'\n",val);
- 
       for(i=0; i <= nitems; i++)
           if( val[i] == '\n' ) inlcount++;
  
@@ -553,7 +566,11 @@
 	      WCHAR *textW = GlobalLock(hUnicodeText);
 	      MultiByteToWideChar(text_cp, 0, lpstr, -1, textW, count);
 	      GlobalUnlock(hUnicodeText);
-	      SetClipboardData(CF_UNICODETEXT, hUnicodeText);
+	      if (!SetClipboardData(CF_UNICODETEXT, hUnicodeText))
+	      {
+            ERR("Not SET! Need to free our own block\n");
+		    GlobalFree(hUnicodeText);
+          }
 	      bRet = TRUE;
 	  }
 	  HeapFree(GetProcessHeap(), 0, lpstr);
@@ -654,9 +671,7 @@
     TSXDeleteProperty(display,w,prop);
     
     /* Free the retrieved property data */
-    if (val)
-       TSXFree(val);
-    
+    HeapFree(GetProcessHeap(),0,val);
     return bRet;
 }
 


More information about the wine-patches mailing list