Release 970509
[wine] / windows / clipboard.c
1 /*
2  * 'Wine' Clipboard function handling
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *
7  */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xatom.h>
18 #include "windows.h"
19 #include "win.h"
20 #include "heap.h"
21 #include "message.h"
22 #include "clipboard.h"
23 #include "xmalloc.h"
24 #include "stddebug.h"
25 #include "debug.h"
26
27 #define  CF_REGFORMATBASE       0xC000
28
29 typedef struct tagCLIPFORMAT {
30     WORD        wFormatID;
31     WORD        wRefCount;
32     WORD        wDataPresent;
33     LPSTR       Name;
34     HANDLE16    hData;
35     DWORD       BufSize;
36     struct tagCLIPFORMAT *PrevFormat;
37     struct tagCLIPFORMAT *NextFormat;
38 } CLIPFORMAT, *LPCLIPFORMAT;
39
40 /* *************************************************************************
41  *                      internal variables
42  */
43
44 static HWND32 hWndClipOwner  = 0;   /* current clipboard owner */
45 static HWND32 hWndClipWindow = 0;   /* window that opened clipboard */
46 static HWND32 hWndViewer     = 0;   /* start of viewers chain */
47
48 static BOOL32 bClipChanged  = FALSE;
49 static WORD LastRegFormat = CF_REGFORMATBASE;
50
51 static Bool   selectionWait = False;
52 static Bool   selectionAcquired = False;
53 static Window selectionWindow = None;
54 static Window selectionPrevWindow = None;
55
56 static CLIPFORMAT ClipFormats[16]  = {
57     { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, 0, NULL, &ClipFormats[1] },
58     { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, 0, &ClipFormats[0], &ClipFormats[2] },
59     { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, 0, &ClipFormats[1], &ClipFormats[3] },
60     { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, 0, &ClipFormats[2], &ClipFormats[4] },
61     { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, 0, &ClipFormats[3], &ClipFormats[5] },
62     { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, 0, &ClipFormats[4], &ClipFormats[6] },
63     { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, 0, &ClipFormats[5], &ClipFormats[7] },
64     { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, 0, &ClipFormats[6], &ClipFormats[8] },
65     { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, 0, &ClipFormats[7], &ClipFormats[9] },
66     { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, 0, &ClipFormats[8], &ClipFormats[10] },
67     { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, 0, &ClipFormats[9], &ClipFormats[11] },
68     { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, 0, &ClipFormats[10], &ClipFormats[12] },
69     { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, 0, &ClipFormats[11], &ClipFormats[13] },
70     { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, 0, &ClipFormats[12], &ClipFormats[14] },
71     { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, 0, &ClipFormats[13], &ClipFormats[15] },
72     { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, 0, &ClipFormats[14], NULL }
73     };
74
75 /**************************************************************************
76  *                      CLIPBOARD_CheckSelection
77  */
78 static void CLIPBOARD_CheckSelection(WND* pWnd)
79 {
80   dprintf_clipboard(stddeb,"\tchecking %08x\n", (unsigned)pWnd->window);
81
82   if( selectionAcquired && selectionWindow != None &&
83       pWnd->window == selectionWindow )
84   {
85     selectionPrevWindow = selectionWindow;
86     selectionWindow = None;
87
88     if( pWnd->next ) 
89          selectionWindow = pWnd->next->window;
90     else if( pWnd->parent )
91              if( pWnd->parent->child != pWnd ) 
92                  selectionWindow = pWnd->parent->child->window;
93
94     dprintf_clipboard(stddeb,"\tswitching selection from %08x to %08x\n", 
95                     (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
96
97     if( selectionWindow != None )
98     {
99         XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
100         if( XGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
101             selectionWindow = None;
102     }
103   }
104 }
105
106 /**************************************************************************
107  *                      CLIPBOARD_DisOwn
108  *
109  * Called from DestroyWindow().
110  */
111 void CLIPBOARD_DisOwn(WND* pWnd)
112 {
113   LPCLIPFORMAT lpFormat = ClipFormats;
114
115   dprintf_clipboard(stddeb,"DisOwn: clipboard owner = %04x, sw = %08x\n", 
116                                 hWndClipOwner, (unsigned)selectionWindow);
117
118   if( pWnd->hwndSelf == hWndClipOwner)
119   {
120     SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
121
122     /* check if all formats were rendered */
123
124     while(lpFormat)
125     { 
126        if( lpFormat->wDataPresent && !lpFormat->hData )
127          {
128            dprintf_clipboard(stddeb,"\tdata missing for clipboard format %i\n", lpFormat->wFormatID); 
129            lpFormat->wDataPresent = 0;
130          }
131        lpFormat = lpFormat->NextFormat;
132     }
133     hWndClipOwner = 0;
134   }
135
136   /* now try to salvage current selection from being destroyed by X */
137
138   CLIPBOARD_CheckSelection(pWnd);
139 }
140
141 /**************************************************************************
142  *                      CLIPBOARD_DeleteRecord
143  */
144 static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange)
145 {
146   if( lpFormat->wFormatID >= CF_GDIOBJFIRST &&
147       lpFormat->wFormatID <= CF_GDIOBJLAST )
148       DeleteObject32(lpFormat->hData);
149   else if( lpFormat->hData )
150            GlobalFree16(lpFormat->hData);
151
152   lpFormat->wDataPresent = 0; 
153   lpFormat->hData = 0;
154
155   if( bChange ) bClipChanged = TRUE;
156 }
157
158 /**************************************************************************
159  *                      CLIPBOARD_RequestXSelection
160  */
161 static BOOL32 CLIPBOARD_RequestXSelection()
162 {
163   HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32();
164
165   if( !hWnd ) return FALSE;
166
167   dprintf_clipboard(stddeb,"Requesting selection...\n");
168
169   /* request data type XA_STRING, later
170    * CLIPBOARD_ReadSelection() will be invoked 
171    * from the SelectionNotify event handler */
172
173   XConvertSelection(display,XA_PRIMARY,XA_STRING,
174                     XInternAtom(display,"PRIMARY_TEXT",False),
175                     WIN_GetXWindow(hWnd),CurrentTime);
176
177   /* wait until SelectionNotify is processed */
178
179   selectionWait=True;
180   while(selectionWait) 
181         EVENT_WaitXEvent( TRUE, FALSE );
182
183   /* we treat Unix text as CF_OEMTEXT */
184   dprintf_clipboard(stddeb,"\tgot CF_OEMTEXT = %i\n", 
185                     ClipFormats[CF_OEMTEXT-1].wDataPresent);
186
187   return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent;
188 }
189
190 /**************************************************************************
191  *                      CLIPBOARD_IsPresent
192  */
193 BOOL32 CLIPBOARD_IsPresent(WORD wFormat)
194 {
195     LPCLIPFORMAT lpFormat = ClipFormats; 
196
197     /* special case */
198
199     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
200         return lpFormat[CF_TEXT-1].wDataPresent ||
201                lpFormat[CF_OEMTEXT-1].wDataPresent;
202
203     while(TRUE) {
204         if (lpFormat == NULL) return FALSE;
205         if (lpFormat->wFormatID == wFormat) break;
206         lpFormat = lpFormat->NextFormat;
207         }
208
209     return (lpFormat->wDataPresent);
210 }
211
212 /**************************************************************************
213  *            OpenClipboard16   (USER.137)
214  */
215 BOOL16 OpenClipboard16( HWND16 hWnd )
216 {
217     return OpenClipboard32( hWnd );
218 }
219
220
221 /**************************************************************************
222  *            OpenClipboard32   (USER32.406)
223  */
224 BOOL32 OpenClipboard32( HWND32 hWnd )
225 {
226     BOOL32 bRet = FALSE;
227     dprintf_clipboard(stddeb,"OpenClipboard(%04x) = ", hWnd);
228
229     if (!hWndClipWindow)
230        {
231          hWndClipWindow = hWnd;
232          bRet = TRUE;
233        }
234     bClipChanged = FALSE;
235
236     dprintf_clipboard(stddeb,"%i\n", bRet);
237     return bRet;
238 }
239
240
241 /**************************************************************************
242  *            CloseClipboard16   (USER.138)
243  */
244 BOOL16 CloseClipboard16(void)
245 {
246     return CloseClipboard32();
247 }
248
249
250 /**************************************************************************
251  *            CloseClipboard32   (USER32.53)
252  */
253 BOOL32 CloseClipboard32(void)
254 {
255     dprintf_clipboard(stddeb,"CloseClipboard(); !\n");
256
257     if (hWndClipWindow == 0) return FALSE;
258     hWndClipWindow = 0;
259
260     if (bClipChanged && hWndViewer) SendMessage16(hWndViewer,WM_DRAWCLIPBOARD,0,0L);
261
262     return TRUE;
263 }
264
265
266 /**************************************************************************
267  *            EmptyClipboard16   (USER.139)
268  */
269 BOOL16 EmptyClipboard16(void)
270 {
271     return EmptyClipboard32();
272 }
273
274
275 /**************************************************************************
276  *            EmptyClipboard32   (USER32.168)
277  */
278 BOOL32 EmptyClipboard32(void)
279 {
280     LPCLIPFORMAT lpFormat = ClipFormats; 
281
282     dprintf_clipboard(stddeb,"EmptyClipboard()\n");
283
284     if (hWndClipWindow == 0) return FALSE;
285
286     /* destroy private objects */
287
288     if (hWndClipOwner)
289         SendMessage16(hWndClipOwner,WM_DESTROYCLIPBOARD,0,0L);
290   
291     while(lpFormat) 
292       {
293         if ( lpFormat->wDataPresent || lpFormat->hData )
294              CLIPBOARD_DeleteRecord( lpFormat, TRUE );
295
296         lpFormat = lpFormat->NextFormat;
297       }
298
299     hWndClipOwner = hWndClipWindow;
300
301     if(selectionAcquired)
302     {
303         selectionAcquired       = False;
304         selectionPrevWindow     = selectionWindow;
305         selectionWindow         = None;
306
307         dprintf_clipboard(stddeb, "\tgiving up selection (spw = %08x)\n", 
308                                         (unsigned)selectionPrevWindow);
309
310         XSetSelectionOwner(display,XA_PRIMARY,None,CurrentTime);
311     }
312     return TRUE;
313 }
314
315
316 /**************************************************************************
317  *            GetClipboardOwner16   (USER.140)
318  */
319 HWND16 GetClipboardOwner16(void)
320 {
321     return hWndClipOwner;
322 }
323
324
325 /**************************************************************************
326  *            GetClipboardOwner32   (USER32.224)
327  */
328 HWND32 GetClipboardOwner32(void)
329 {
330     return hWndClipOwner;
331 }
332
333
334 /**************************************************************************
335  *            SetClipboardData16   (USER.141)
336  */
337 HANDLE16 SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
338 {
339     LPCLIPFORMAT lpFormat = ClipFormats; 
340     Window       owner;
341
342     dprintf_clipboard(stddeb,
343                 "SetClipboardData(%04X, %04x) !\n", wFormat, hData);
344
345     while(TRUE) 
346       {
347         if (lpFormat == NULL) return 0;
348         if (lpFormat->wFormatID == wFormat) break;
349         lpFormat = lpFormat->NextFormat;
350       }
351
352     /* Acquire X selection if text format */
353
354     if( !selectionAcquired && 
355         (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
356     {
357       owner = WIN_GetXWindow(hWndClipWindow);
358       XSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime);
359       if( XGetSelectionOwner(display,XA_PRIMARY) == owner )
360       {
361         selectionAcquired = True;
362         selectionWindow = owner;
363
364         dprintf_clipboard(stddeb,"Grabbed X selection, owner=(%08x)\n", 
365                                                 (unsigned) owner);
366       }
367     }
368
369     if ( lpFormat->wDataPresent || lpFormat->hData ) 
370     {
371         CLIPBOARD_DeleteRecord(lpFormat, TRUE);
372
373         /* delete existing CF_TEXT/CF_OEMTEXT aliases */
374
375         if( wFormat == CF_TEXT && ClipFormats[CF_OEMTEXT-1].hData
376             && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
377             CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
378         if( wFormat == CF_OEMTEXT && ClipFormats[CF_TEXT-1].hData
379             && !ClipFormats[CF_TEXT-1].wDataPresent )
380             CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
381     }
382
383     bClipChanged = TRUE;
384     lpFormat->wDataPresent = 1;
385     lpFormat->hData = hData;          /* 0 is legal, see WM_RENDERFORMAT */
386
387     return lpFormat->hData;
388 }
389
390
391 /**************************************************************************
392  *            SetClipboardData32   (USER32.469)
393  */
394 HANDLE32 SetClipboardData32( UINT32 wFormat, HANDLE32 hData )
395 {
396     fprintf( stderr, "SetClipboardData: empty stub\n" );
397     return 0;
398 }
399
400
401 /**************************************************************************
402  *                      CLIPBOARD_RenderFormat
403  */
404 static BOOL32 CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat)
405 {
406  if( lpFormat->wDataPresent && !lpFormat->hData )
407    if( IsWindow32(hWndClipOwner) )
408        SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
409                      (WPARAM16)lpFormat->wFormatID,0L);
410    else
411    {
412        dprintf_clipboard(stddeb,"\thWndClipOwner (%04x) is lost!\n", 
413                                       hWndClipOwner);
414        hWndClipOwner = 0; lpFormat->wDataPresent = 0;
415        return FALSE;
416    }
417  return (lpFormat->hData) ? TRUE : FALSE;
418 }
419
420 /**************************************************************************
421  *                      CLIPBOARD_RenderText
422  */
423 static BOOL32 CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget, LPCLIPFORMAT lpSource)
424 {
425   UINT16 size = GlobalSize16( lpSource->hData );
426   LPCSTR        lpstrS = (LPSTR)GlobalLock16(lpSource->hData);
427   LPSTR         lpstrT;
428
429   if( !lpstrS ) return FALSE;
430   dprintf_clipboard(stddeb,"\tconverting from '%s' to '%s', %i chars\n",
431                                       lpSource->Name, lpTarget->Name, size);
432
433   lpTarget->hData = GlobalAlloc16(GMEM_ZEROINIT, size); 
434   lpstrT = (LPSTR)GlobalLock16(lpTarget->hData);
435
436   if( lpstrT )
437   {
438     if( lpSource->wFormatID == CF_TEXT )
439         CharToOemBuff32A(lpstrS, lpstrT, size);
440     else
441         OemToCharBuff32A(lpstrS, lpstrT, size);
442     dprintf_clipboard(stddeb,"\tgot %s\n", lpstrT);
443     return TRUE;
444   }
445
446   lpTarget->hData = 0;
447   return FALSE;
448 }
449
450 /**************************************************************************
451  *             GetClipboardData16   (USER.142)
452  */
453 HANDLE16 GetClipboardData16( UINT16 wFormat )
454 {
455     LPCLIPFORMAT lpRender = ClipFormats; 
456     LPCLIPFORMAT lpUpdate = NULL;
457
458     if (!hWndClipWindow) return 0;
459
460     dprintf_clipboard(stddeb,"GetClipboardData(%04X)\n", wFormat);
461
462     if( wFormat == CF_TEXT && !lpRender[CF_TEXT-1].wDataPresent 
463                            &&  lpRender[CF_OEMTEXT-1].wDataPresent )
464     {
465         lpRender = &ClipFormats[CF_OEMTEXT-1];
466         lpUpdate = &ClipFormats[CF_TEXT-1];
467
468         dprintf_clipboard(stddeb,"\tOEMTEXT -> TEXT\n");
469     }
470     else if( wFormat == CF_OEMTEXT && !lpRender[CF_OEMTEXT-1].wDataPresent
471                                    &&  lpRender[CF_TEXT-1].wDataPresent )
472     {
473         lpRender = &ClipFormats[CF_TEXT-1];
474         lpUpdate = &ClipFormats[CF_OEMTEXT-1];
475         
476         dprintf_clipboard(stddeb,"\tTEXT -> OEMTEXT\n");
477     }
478     else
479     {
480       while(TRUE) 
481       {
482         if (lpRender == NULL) return 0;
483         if (lpRender->wFormatID == wFormat) break;
484         lpRender = lpRender->NextFormat;
485       }
486       lpUpdate = lpRender;
487     }
488    
489     if( !CLIPBOARD_RenderFormat(lpRender) ) return 0; 
490     if( lpUpdate != lpRender &&
491         !lpUpdate->hData ) CLIPBOARD_RenderText(lpUpdate, lpRender);
492
493     dprintf_clipboard(stddeb,"\treturning %04x (type %i)\n", 
494                               lpUpdate->hData, lpUpdate->wFormatID);
495     return lpUpdate->hData;
496 }
497
498
499 /**************************************************************************
500  *             GetClipboardData32   (USER32.221)
501  */
502 HANDLE32 GetClipboardData32( UINT32 wFormat )
503 {
504     fprintf( stderr, "GetClipboardData32: empty stub\n" );
505     return 0;
506 }
507
508 /**************************************************************************
509  *           CountClipboardFormats16   (USER.143)
510  */
511 INT16 CountClipboardFormats16(void)
512 {
513     return CountClipboardFormats32();
514 }
515
516
517 /**************************************************************************
518  *           CountClipboardFormats32   (USER32.62)
519  */
520 INT32 CountClipboardFormats32(void)
521 {
522     INT32 FormatCount = 0;
523     LPCLIPFORMAT lpFormat = ClipFormats; 
524
525     dprintf_clipboard(stddeb,"CountClipboardFormats()\n");
526
527     if( !selectionAcquired ) CLIPBOARD_RequestXSelection();
528
529     FormatCount += abs(lpFormat[CF_TEXT-1].wDataPresent -
530                        lpFormat[CF_OEMTEXT-1].wDataPresent); 
531
532     while(TRUE) {
533         if (lpFormat == NULL) break;
534         if (lpFormat->wDataPresent) 
535             {
536                dprintf_clipboard(stddeb, "\tdata found for format %i\n", lpFormat->wFormatID);
537
538                FormatCount++;
539             }
540         lpFormat = lpFormat->NextFormat;
541         }
542
543     dprintf_clipboard(stddeb,"\ttotal %d\n", FormatCount);
544     return FormatCount;
545 }
546
547
548 /**************************************************************************
549  *            EnumClipboardFormats16   (USER.144)
550  */
551 UINT16 EnumClipboardFormats16( UINT16 wFormat )
552 {
553     return EnumClipboardFormats32( wFormat );
554 }
555
556
557 /**************************************************************************
558  *            EnumClipboardFormats32   (USER32.178)
559  */
560 UINT32 EnumClipboardFormats32( UINT32 wFormat )
561 {
562     LPCLIPFORMAT lpFormat = ClipFormats; 
563
564     dprintf_clipboard(stddeb,"EnumClipboardFormats(%04X)\n", wFormat);
565
566     if( !hWndClipWindow ) return 0;
567
568     if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) 
569          && !selectionAcquired) CLIPBOARD_RequestXSelection();
570
571     if (wFormat == 0)
572         if (lpFormat->wDataPresent || ClipFormats[CF_OEMTEXT-1].wDataPresent) 
573             return lpFormat->wFormatID;
574         else 
575             wFormat = lpFormat->wFormatID; /* and CF_TEXT is not available */
576
577     /* walk up to the specified format record */
578
579     while(TRUE) {
580         if (lpFormat == NULL) return 0;
581         if (lpFormat->wFormatID == wFormat) break;
582         lpFormat = lpFormat->NextFormat;
583         }
584
585     /* find next format with available data */
586
587     lpFormat = lpFormat->NextFormat;
588     while(TRUE) {
589         if (lpFormat == NULL) return 0;
590         if (lpFormat->wDataPresent ||
591                (lpFormat->wFormatID == CF_OEMTEXT &&
592                 ClipFormats[CF_TEXT-1].wDataPresent)) break;
593         lpFormat = lpFormat->NextFormat;
594         }
595
596     return lpFormat->wFormatID;
597 }
598
599
600 /**************************************************************************
601  *            RegisterClipboardFormat16  (USER.145)
602  */
603 UINT16 RegisterClipboardFormat16( LPCSTR FormatName )
604 {
605     LPCLIPFORMAT lpNewFormat; 
606     LPCLIPFORMAT lpFormat = ClipFormats; 
607
608     if (FormatName == NULL) return 0;
609
610     dprintf_clipboard(stddeb,"RegisterClipboardFormat('%s') !\n", FormatName);
611
612     /* walk format chain to see if it's already registered */
613
614     while(TRUE) {
615         if ( !strcmp(lpFormat->Name,FormatName) )
616            {
617              lpFormat->wRefCount++;
618              return lpFormat->wFormatID;
619            }
620  
621         if ( lpFormat->NextFormat == NULL ) break;
622
623         lpFormat = lpFormat->NextFormat;
624         }
625
626     /* allocate storage for new format entry */
627
628     lpNewFormat = (LPCLIPFORMAT)xmalloc(sizeof(CLIPFORMAT));
629     lpFormat->NextFormat = lpNewFormat;
630     lpNewFormat->wFormatID = LastRegFormat;
631     lpNewFormat->wRefCount = 1;
632
633     lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
634     strcpy(lpNewFormat->Name, FormatName);
635
636     lpNewFormat->wDataPresent = 0;
637     lpNewFormat->hData = 0;
638     lpNewFormat->BufSize = 0;
639     lpNewFormat->PrevFormat = lpFormat;
640     lpNewFormat->NextFormat = NULL;
641
642     return LastRegFormat++;
643 }
644
645
646 /**************************************************************************
647  *            RegisterClipboardFormat32A   (USER32.430)
648  */
649 UINT32 RegisterClipboardFormat32A( LPCSTR formatName )
650 {
651     return RegisterClipboardFormat16( formatName );
652 }
653
654
655 /**************************************************************************
656  *            RegisterClipboardFormat32W   (USER32.431)
657  */
658 UINT32 RegisterClipboardFormat32W( LPCWSTR formatName )
659 {
660     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
661     UINT32 ret = RegisterClipboardFormat32A( aFormat );
662     HeapFree( GetProcessHeap(), 0, aFormat );
663     return ret;
664 }
665
666 /**************************************************************************
667  *            GetClipboardFormatName16   (USER.146)
668  */
669 INT16 GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
670 {
671     return GetClipboardFormatName32A( wFormat, retStr, maxlen );
672 }
673
674
675 /**************************************************************************
676  *            GetClipboardFormatName32A   (USER32.222)
677  */
678 INT32 GetClipboardFormatName32A( UINT32 wFormat, LPSTR retStr, INT32 maxlen )
679 {
680     LPCLIPFORMAT lpFormat = ClipFormats; 
681
682     dprintf_clipboard(stddeb,
683         "GetClipboardFormatName(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
684
685     while(TRUE) {
686         if (lpFormat == NULL) return 0;
687         if (lpFormat->wFormatID == wFormat) break;
688         lpFormat = lpFormat->NextFormat;
689         }
690
691     if (lpFormat->Name == NULL || 
692         lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
693
694     dprintf_clipboard(stddeb,
695                 "GetClipboardFormat // Name='%s' !\n", lpFormat->Name);
696
697     lstrcpyn32A( retStr, lpFormat->Name, maxlen );
698     return strlen(retStr);
699 }
700
701
702 /**************************************************************************
703  *            GetClipboardFormatName32W   (USER32.223)
704  */
705 INT32 GetClipboardFormatName32W( UINT32 wFormat, LPWSTR retStr, INT32 maxlen )
706 {
707     LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
708     INT32 ret = GetClipboardFormatName32A( wFormat, p, maxlen );
709     lstrcpynAtoW( retStr, p, maxlen );
710     HeapFree( GetProcessHeap(), 0, p );
711     return ret;
712 }
713
714
715 /**************************************************************************
716  *            SetClipboardViewer16   (USER.147)
717  */
718 HWND16 SetClipboardViewer16( HWND16 hWnd )
719 {
720     return SetClipboardViewer32( hWnd );
721 }
722
723
724 /**************************************************************************
725  *            SetClipboardViewer32   (USER32.470)
726  */
727 HWND32 SetClipboardViewer32( HWND32 hWnd )
728 {
729     HWND32 hwndPrev = hWndViewer;
730
731     dprintf_clipboard(stddeb,"SetClipboardViewer(%04x)\n", hWnd);
732
733     hWndViewer = hWnd;
734     return hwndPrev;
735 }
736
737
738 /**************************************************************************
739  *           GetClipboardViewer16   (USER.148)
740  */
741 HWND16 GetClipboardViewer16(void)
742 {
743     return hWndViewer;
744 }
745
746
747 /**************************************************************************
748  *           GetClipboardViewer32   (USER32.225)
749  */
750 HWND32 GetClipboardViewer32(void)
751 {
752     return hWndViewer;
753 }
754
755
756 /**************************************************************************
757  *           ChangeClipboardChain16   (USER.149)
758  */
759 BOOL16 ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
760 {
761     return ChangeClipboardChain32(hWnd,hWndNext);
762 }
763
764 /**************************************************************************
765  *           ChangeClipboardChain32   (USER32.21)
766  */
767 BOOL32 ChangeClipboardChain32(HWND32 hWnd, HWND32 hWndNext)
768 {
769     BOOL32 bRet = 0;
770
771     dprintf_clipboard(stdnimp, "ChangeClipboardChain(%04x, %04x)\n", hWnd, hWndNext);
772
773     if( hWndViewer )
774       bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
775                              (WPARAM16)hWnd, (LPARAM)hWndNext);   
776     else
777       dprintf_clipboard(stddeb,"ChangeClipboardChain: hWndViewer is lost\n");
778
779     if( hWnd == hWndViewer ) hWndViewer = hWndNext;
780
781     return bRet;
782 }
783
784
785
786 /**************************************************************************
787  *           IsClipboardFormatAvailable16   (USER.193)
788  */
789 BOOL16 IsClipboardFormatAvailable16( UINT16 wFormat )
790 {
791     return IsClipboardFormatAvailable32( wFormat );
792 }
793
794
795 /**************************************************************************
796  *           IsClipboardFormatAvailable32   (USER32.339)
797  */
798 BOOL32 IsClipboardFormatAvailable32( UINT32 wFormat )
799 {
800     dprintf_clipboard(stddeb,"IsClipboardFormatAvailable(%04X) !\n", wFormat);
801
802     if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) &&
803         !selectionAcquired ) CLIPBOARD_RequestXSelection();
804
805     return CLIPBOARD_IsPresent(wFormat);
806 }
807
808
809 /**************************************************************************
810  *             GetOpenClipboardWindow16   (USER.248)
811  */
812 HWND16 GetOpenClipboardWindow16(void)
813 {
814     return hWndClipWindow;
815 }
816
817
818 /**************************************************************************
819  *             GetOpenClipboardWindow32   (USER32.276)
820  */
821 HWND32 GetOpenClipboardWindow32(void)
822 {
823     return hWndClipWindow;
824 }
825
826
827 /**************************************************************************
828  *             GetPriorityClipboardFormat16   (USER.402)
829  */
830 INT16 GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
831 {
832     fprintf( stderr, "GetPriorityClipboardFormat16(%p, %d): stub\n",
833              lpPriorityList, nCount );
834     return 0;
835 }
836
837
838 /**************************************************************************
839  *             GetPriorityClipboardFormat32   (USER32
840  */
841 INT32 GetPriorityClipboardFormat32( UINT32 *lpPriorityList, INT32 nCount )
842 {
843     fprintf( stderr, "GetPriorityClipboardFormat32(%p, %d): stub\n",
844              lpPriorityList, nCount );
845     return 0;
846 }
847
848
849 /**************************************************************************
850  *                      CLIPBOARD_ReadSelection
851  *
852  * Called from the SelectionNotify event handler. 
853  */
854 void CLIPBOARD_ReadSelection(Window w,Atom prop)
855 {
856     HANDLE16     hText = 0;
857     LPCLIPFORMAT lpFormat = ClipFormats; 
858
859     dprintf_clipboard(stddeb,"ReadSelection callback\n");
860
861     if(prop != None)
862     {
863         Atom            atype=AnyPropertyType;
864         int             aformat;
865         unsigned long   nitems,remain;
866         unsigned char*  val=NULL;
867
868         dprintf_clipboard(stddeb,"\tgot property %s\n",XGetAtomName(display,prop));
869
870         /* TODO: Properties longer than 64K */
871
872         if(XGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
873             &atype, &aformat, &nitems, &remain, &val) != Success)
874             dprintf_clipboard(stddeb,"\tcouldn't read property\n");
875         else
876         {
877            dprintf_clipboard(stddeb,"\tType %s,Format %d,nitems %ld,value %s\n",
878                              XGetAtomName(display,atype),aformat,nitems,val);
879
880            if(atype == XA_STRING && aformat == 8)
881            {
882               int       i,inlcount = 0;
883               char*     lpstr;
884
885               dprintf_clipboard(stddeb,"\tselection is '%s'\n",val);
886
887               for(i=0; i <= nitems; i++)
888                   if( val[i] == '\n' ) inlcount++;
889
890               if( nitems )
891               {
892                 hText=GlobalAlloc16(GMEM_MOVEABLE, nitems + inlcount + 1);
893                 if( (lpstr = (char*)GlobalLock16(hText)) )
894                   for(i=0,inlcount=0; i <= nitems; i++)
895                   {
896                      if( val[i] == '\n' ) lpstr[inlcount++]='\r';
897                      lpstr[inlcount++]=val[i];
898                   }
899                 else hText = 0;
900               }
901            }
902            XFree(val);
903         }
904    }
905
906    /* delete previous CF_TEXT and CF_OEMTEXT data */
907
908    if( hText )
909    {
910      lpFormat = &ClipFormats[CF_TEXT-1];
911      if (lpFormat->wDataPresent || lpFormat->hData) 
912          CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
913      lpFormat = &ClipFormats[CF_OEMTEXT-1];
914      if (lpFormat->wDataPresent || lpFormat->hData) 
915          CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
916
917      lpFormat->wDataPresent = 1;
918      lpFormat->hData = hText;
919    }
920
921    selectionWait=False;
922 }
923
924 /**************************************************************************
925  *                      CLIPBOARD_ReleaseSelection
926  *
927  * Wine might have lost XA_PRIMARY selection because of
928  * EmptyClipboard() or other client. 
929  */
930 void CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd)
931 {
932   /* w is the window that lost selection,
933    * 
934    * selectionPrevWindow is nonzero if CheckSelection() was called. 
935    */
936
937   dprintf_clipboard(stddeb,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", 
938           (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
939
940   if( selectionAcquired )
941     if( w == selectionWindow || selectionPrevWindow == None)
942     {
943       /* alright, we really lost it */
944
945       selectionAcquired = False;
946       selectionWindow = None; 
947
948       /* but we'll keep existing data for internal use */
949     }
950     else if( w == selectionPrevWindow )
951     {
952       w =  XGetSelectionOwner(display, XA_PRIMARY);
953
954       if( w == None )
955         XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
956     }
957
958   selectionPrevWindow = None;
959 }
960