2 * 'Wine' Clipboard function handling
4 * Copyright 1994 Martin Ayotte
5 static char Copyright[] = "Copyright Martin Ayotte, 1994";
11 #include <sys/types.h>
16 #include <X11/Xatom.h>
19 #include "clipboard.h"
23 typedef struct tagCLIPFORMAT
{
32 typedef CLIPFORMAT FAR
* LPCLIPFORMAT
;
34 static HWND hWndClipboardOwner
= 0;
35 static HWND hWndViewer
= 0;
36 static WORD LastRegFormat
= 0xC000;
37 static Bool wait_for_selection
= False
;
38 static Bool wineOwnsSelection
= False
;
40 CLIPFORMAT ClipFormats
[12] = {
41 { CF_TEXT
, 1, "Text", (HANDLE
)NULL
, 0, NULL
, &ClipFormats
[1] },
42 { CF_BITMAP
, 1, "Bitmap", (HANDLE
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2] },
43 { CF_METAFILEPICT
, 1, "MetaFile Picture", (HANDLE
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3] },
44 { CF_SYLK
, 1, "Sylk", (HANDLE
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4] },
45 { CF_DIF
, 1, "DIF", (HANDLE
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5] },
46 { CF_TIFF
, 1, "TIFF", (HANDLE
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6] },
47 { CF_OEMTEXT
, 1, "OEM Text", (HANDLE
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7] },
48 { CF_DIB
, 1, "DIB", (HANDLE
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8] },
49 { CF_PALETTE
, 1, "Palette", (HANDLE
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9] },
50 { CF_PENDATA
, 1, "PenData", (HANDLE
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10] },
51 { CF_RIFF
, 1, "RIFF", (HANDLE
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11] },
52 { CF_WAVE
, 1, "Wave", (HANDLE
)NULL
, 0, &ClipFormats
[10], NULL
}
55 /**************************************************************************
56 * OpenClipboard [USER.137]
58 BOOL
OpenClipboard(HWND hWnd
)
60 if (hWndClipboardOwner
!= 0) return FALSE
;
61 hWndClipboardOwner
= hWnd
;
62 dprintf_clipboard(stddeb
,"OpenClipboard(%04X); !\n", hWnd
);
67 /**************************************************************************
68 * CloseClipboard [USER.138]
72 if (hWndClipboardOwner
== 0) return FALSE
;
73 hWndClipboardOwner
= 0;
74 dprintf_clipboard(stddeb
,"CloseClipboard(); !\n");
79 /**************************************************************************
80 * EmptyClipboard [USER.139]
84 LPCLIPFORMAT lpFormat
= ClipFormats
;
85 if (hWndClipboardOwner
== 0) return FALSE
;
86 dprintf_clipboard(stddeb
,"EmptyClipboard(); !\n");
88 if (lpFormat
== NULL
) break;
89 if (lpFormat
->hData
!= 0) {
90 GlobalFree(lpFormat
->hData
);
93 lpFormat
= lpFormat
->NextFormat
;
95 if(wineOwnsSelection
){
96 dprintf_clipboard(stddeb
,"Losing selection\n");
97 wineOwnsSelection
=False
;
98 XSetSelectionOwner(display
,XA_PRIMARY
,None
,CurrentTime
);
104 /**************************************************************************
105 * GetClipboardOwner [USER.140]
107 HWND
GetClipboardOwner()
109 dprintf_clipboard(stddeb
,
110 "GetClipboardOwner() = %04X !\n", hWndClipboardOwner
);
111 return hWndClipboardOwner
;
115 /**************************************************************************
116 * SetClipboardData [USER.141]
118 HANDLE
SetClipboardData(WORD wFormat
, HANDLE hData
)
120 LPCLIPFORMAT lpFormat
= ClipFormats
;
121 dprintf_clipboard(stddeb
,
122 "SetClipboardDate(%04X, %04X) !\n", wFormat
, hData
);
124 if (lpFormat
== NULL
) return 0;
125 if (lpFormat
->wFormatID
== wFormat
) break;
126 lpFormat
= lpFormat
->NextFormat
;
128 /* doc says we shouldn't use CurrentTime */
129 /* should we become owner of CLIPBOARD as well? */
130 XSetSelectionOwner(display
,XA_PRIMARY
,WIN_GetXWindow(hWndClipboardOwner
),CurrentTime
);
131 wineOwnsSelection
= True
;
132 dprintf_clipboard(stddeb
,"Getting selection\n");
133 if (lpFormat
->hData
!= 0) GlobalFree(lpFormat
->hData
);
134 lpFormat
->hData
= hData
;
135 return lpFormat
->hData
;
139 /**************************************************************************
140 * GetClipboardData [USER.142]
142 HANDLE
GetClipboardData(WORD wFormat
)
144 LPCLIPFORMAT lpFormat
= ClipFormats
;
145 dprintf_clipboard(stddeb
,"GetClipboardData(%04X) !\n", wFormat
);
146 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
)
147 { wait_for_selection
=True
;
148 dprintf_clipboard(stddeb
,"Requesting selection\n");
149 XConvertSelection(display
,XA_PRIMARY
,XA_STRING
,
150 XInternAtom(display
,"PRIMARY_TEXT",False
),
151 WIN_GetXWindow(hWndClipboardOwner
),CurrentTime
);
152 /* TODO: need time-out for broken clients */
153 while(wait_for_selection
)MSG_WaitXEvent(-1);
156 if (lpFormat
== NULL
) return 0;
157 if (lpFormat
->wFormatID
== wFormat
) break;
158 lpFormat
= lpFormat
->NextFormat
;
160 return lpFormat
->hData
;
164 /**************************************************************************
165 * CountClipboardFormats [USER.143]
167 int CountClipboardFormats()
170 LPCLIPFORMAT lpFormat
= ClipFormats
;
172 if (lpFormat
== NULL
) break;
173 if (lpFormat
->hData
!= 0) {
174 dprintf_clipboard(stddeb
,
175 "CountClipboardFormats // Find Not Empty (%04X) !\n",
179 lpFormat
= lpFormat
->NextFormat
;
181 dprintf_clipboard(stddeb
,"CountClipboardFormats() = %d !\n", FormatCount
);
186 /**************************************************************************
187 * EnumClipboardFormats [USER.144]
189 WORD
EnumClipboardFormats(WORD wFormat
)
191 LPCLIPFORMAT lpFormat
= ClipFormats
;
192 dprintf_clipboard(stddeb
,"EnumClipboardFormats(%04X) !\n", wFormat
);
194 if (lpFormat
->hData
!= 0)
195 return lpFormat
->wFormatID
;
197 wFormat
= lpFormat
->wFormatID
;
200 if (lpFormat
== NULL
) return 0;
201 if (lpFormat
->wFormatID
== wFormat
) break;
202 lpFormat
= lpFormat
->NextFormat
;
204 dprintf_clipboard(stddeb
,"EnumClipboardFormats // Find Last (%04X) !\n",
205 lpFormat
->wFormatID
);
206 lpFormat
= lpFormat
->NextFormat
;
208 if (lpFormat
== NULL
) return 0;
209 if (lpFormat
->hData
!= 0) break;
210 lpFormat
= lpFormat
->NextFormat
;
212 dprintf_clipboard(stddeb
,
213 "EnumClipboardFormats // Find Not Empty Id=%04X hData=%04X !\n",
214 lpFormat
->wFormatID
, lpFormat
->hData
);
215 return lpFormat
->wFormatID
;
219 /**************************************************************************
220 * RegisterClipboardFormat [USER.145]
222 WORD
RegisterClipboardFormat(LPCSTR FormatName
)
224 LPCLIPFORMAT lpNewFormat
;
225 LPCLIPFORMAT lpFormat
= ClipFormats
;
226 if (FormatName
== NULL
) return 0;
228 if (lpFormat
->NextFormat
== NULL
) break;
229 lpFormat
= lpFormat
->NextFormat
;
231 lpNewFormat
= (LPCLIPFORMAT
)malloc(sizeof(CLIPFORMAT
));
232 if (lpNewFormat
== NULL
) return 0;
233 lpFormat
->NextFormat
= lpNewFormat
;
234 dprintf_clipboard(stddeb
,"RegisterClipboardFormat('%s') !\n", FormatName
);
235 lpNewFormat
->wFormatID
= LastRegFormat
;
236 lpNewFormat
->wRefCount
= 1;
237 lpNewFormat
->Name
= (LPSTR
)malloc(strlen(FormatName
) + 1);
238 if (lpNewFormat
->Name
== NULL
) {
242 strcpy(lpNewFormat
->Name
, FormatName
);
243 lpNewFormat
->hData
= 0;
244 lpNewFormat
->BufSize
= 0;
245 lpNewFormat
->PrevFormat
= lpFormat
;
246 lpNewFormat
->NextFormat
= NULL
;
247 return LastRegFormat
++;
251 /**************************************************************************
252 * GetClipboardFormatName [USER.146]
254 int GetClipboardFormatName(WORD wFormat
, LPSTR retStr
, short maxlen
)
256 LPCLIPFORMAT lpFormat
= ClipFormats
;
257 dprintf_clipboard(stddeb
,
258 "GetClipboardFormat(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
260 if (lpFormat
== NULL
) return 0;
261 if (lpFormat
->wFormatID
== wFormat
) break;
262 lpFormat
= lpFormat
->NextFormat
;
264 if (lpFormat
->Name
== NULL
) return 0;
265 dprintf_clipboard(stddeb
,
266 "GetClipboardFormat // Name='%s' !\n", lpFormat
->Name
);
267 maxlen
= min(maxlen
- 1, strlen(lpFormat
->Name
));
268 dprintf_clipboard(stddeb
,"GetClipboardFormat // maxlen=%d !\n", maxlen
);
269 memcpy(retStr
, lpFormat
->Name
, maxlen
);
275 /**************************************************************************
276 * SetClipboardViewer [USER.147]
278 HWND
SetClipboardViewer(HWND hWnd
)
280 HWND hwndPrev
= hWndViewer
;
281 dprintf_clipboard(stddeb
,"SetClipboardViewer(%04X) !\n", hWnd
);
287 /**************************************************************************
288 * GetClipboardViewer [USER.148]
290 HWND
GetClipboardViewer()
292 dprintf_clipboard(stddeb
,"GetClipboardFormat() = %04X !\n", hWndViewer
);
297 /**************************************************************************
298 * ChangeClipboardChain [USER.149]
300 BOOL
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
302 dprintf_clipboard(stdnimp
,
303 "ChangeClipboardChain(%04X, %04X) !\n", hWnd
, hWndNext
);
309 /**************************************************************************
310 * IsClipboardFormatAvailable [USER.193]
312 BOOL
IsClipboardFormatAvailable(WORD wFormat
)
314 LPCLIPFORMAT lpFormat
= ClipFormats
;
315 dprintf_clipboard(stddeb
,"IsClipboardFormatAvailable(%04X) !\n", wFormat
);
316 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
) /* obtain selection as text if possible */
317 return GetClipboardData(CF_TEXT
)!=0;
319 if (lpFormat
== NULL
) return FALSE
;
320 if (lpFormat
->wFormatID
== wFormat
) break;
321 lpFormat
= lpFormat
->NextFormat
;
323 return (lpFormat
->hData
!= 0);
327 /**************************************************************************
328 * GetOpenClipboardWindow [USER.248]
330 HWND
GetOpenClipboardWindow()
332 dprintf_clipboard(stddeb
,
333 "GetOpenClipboardWindow() = %04X !\n", hWndClipboardOwner
);
334 return hWndClipboardOwner
;
338 /**************************************************************************
339 * GetPriorityClipboardFormat [USER.402]
341 int GetPriorityClipboardFormat(WORD FAR
*lpPriorityList
, short nCount
)
343 dprintf_clipboard(stdnimp
,
344 "GetPriorityClipboardFormat(%p, %d) !\n", lpPriorityList
, nCount
);
350 /**************************************************************************
351 * CLIPBOARD_ReadSelection
353 * The current selection owner has set prop at our window w
354 * Transfer the property contents into the Clipboard
356 void CLIPBOARD_ReadSelection(Window w
,Atom prop
)
359 LPCLIPFORMAT lpFormat
= ClipFormats
;
365 unsigned long nitems
,remain
;
366 unsigned char *val
=NULL
;
367 dprintf_clipboard(stddeb
,"Received prop %s\n",XGetAtomName(display
,prop
));
368 /* TODO: Properties longer than 64K */
369 if(XGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
370 &atype
, &aformat
, &nitems
, &remain
, &val
)!=Success
)
371 printf("couldn't read property\n");
372 dprintf_clipboard(stddeb
,"Type %s,Format %d,nitems %ld,value %s\n",
373 XGetAtomName(display
,atype
),aformat
,nitems
,val
);
374 if(atype
!=XA_STRING
|| aformat
!=8){
375 fprintf(stderr
,"Property not set\n");
378 dprintf_clipboard(stddeb
,"Selection is %s\n",val
);
379 hText
=GlobalAlloc(GMEM_MOVEABLE
, nitems
);
380 memcpy(GlobalLock(hText
),val
,nitems
+1);
386 if (lpFormat
== NULL
) return;
387 if (lpFormat
->wFormatID
== CF_TEXT
) break;
388 lpFormat
= lpFormat
->NextFormat
;
390 if (lpFormat
->hData
!= 0) GlobalFree(lpFormat
->hData
);
391 wait_for_selection
=False
;
392 lpFormat
->hData
= hText
;
393 dprintf_clipboard(stddeb
,"Received selection\n");
396 /**************************************************************************
397 * CLIPBOARD_ReleaseSelection
399 * Wine lost the primary selection.
400 * Empty the clipboard, but don't set the current owner to None.
401 * Make sure current get/put attempts fail.
403 void CLIPBOARD_ReleaseSelection(HWND hwnd
)
405 wineOwnsSelection
=False
;