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("NPFMT
"); !\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() = "NPFMT
" !\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, "NPFMT
") !\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 (!hWndClipboardOwner
) return 0;
147 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
)
148 { wait_for_selection
=True
;
149 dprintf_clipboard(stddeb
,"Requesting selection\n");
150 XConvertSelection(display
,XA_PRIMARY
,XA_STRING
,
151 XInternAtom(display
,"PRIMARY_TEXT",False
),
152 WIN_GetXWindow(hWndClipboardOwner
),CurrentTime
);
153 /* TODO: need time-out for broken clients */
154 while(wait_for_selection
)MSG_WaitXEvent(-1);
157 if (lpFormat
== NULL
) return 0;
158 if (lpFormat
->wFormatID
== wFormat
) break;
159 lpFormat
= lpFormat
->NextFormat
;
161 return lpFormat
->hData
;
165 /**************************************************************************
166 * CountClipboardFormats [USER.143]
168 int CountClipboardFormats()
171 LPCLIPFORMAT lpFormat
= ClipFormats
;
173 if (lpFormat
== NULL
) break;
174 if (lpFormat
->hData
!= 0) {
175 dprintf_clipboard(stddeb
,
176 "CountClipboardFormats // Find Not Empty ("NPFMT
") !\n",
180 lpFormat
= lpFormat
->NextFormat
;
182 dprintf_clipboard(stddeb
,"CountClipboardFormats() = %d !\n", FormatCount
);
187 /**************************************************************************
188 * EnumClipboardFormats [USER.144]
190 WORD
EnumClipboardFormats(WORD wFormat
)
192 LPCLIPFORMAT lpFormat
= ClipFormats
;
193 dprintf_clipboard(stddeb
,"EnumClipboardFormats(%04X) !\n", wFormat
);
195 if (lpFormat
->hData
!= 0)
196 return lpFormat
->wFormatID
;
198 wFormat
= lpFormat
->wFormatID
;
201 if (lpFormat
== NULL
) return 0;
202 if (lpFormat
->wFormatID
== wFormat
) break;
203 lpFormat
= lpFormat
->NextFormat
;
205 dprintf_clipboard(stddeb
,"EnumClipboardFormats // Find Last (%04X) !\n",
206 lpFormat
->wFormatID
);
207 lpFormat
= lpFormat
->NextFormat
;
209 if (lpFormat
== NULL
) return 0;
210 if (lpFormat
->hData
!= 0) break;
211 lpFormat
= lpFormat
->NextFormat
;
213 dprintf_clipboard(stddeb
,
214 "EnumClipboardFormats // Find Not Empty Id=%04X hData="NPFMT
" !\n",
215 lpFormat
->wFormatID
, lpFormat
->hData
);
216 return lpFormat
->wFormatID
;
220 /**************************************************************************
221 * RegisterClipboardFormat [USER.145]
223 WORD
RegisterClipboardFormat(LPCSTR FormatName
)
225 LPCLIPFORMAT lpNewFormat
;
226 LPCLIPFORMAT lpFormat
= ClipFormats
;
227 if (FormatName
== NULL
) return 0;
229 if (lpFormat
->NextFormat
== NULL
) break;
230 lpFormat
= lpFormat
->NextFormat
;
232 lpNewFormat
= (LPCLIPFORMAT
)malloc(sizeof(CLIPFORMAT
));
233 if (lpNewFormat
== NULL
) return 0;
234 lpFormat
->NextFormat
= lpNewFormat
;
235 dprintf_clipboard(stddeb
,"RegisterClipboardFormat('%s') !\n", FormatName
);
236 lpNewFormat
->wFormatID
= LastRegFormat
;
237 lpNewFormat
->wRefCount
= 1;
238 lpNewFormat
->Name
= (LPSTR
)malloc(strlen(FormatName
) + 1);
239 if (lpNewFormat
->Name
== NULL
) {
243 strcpy(lpNewFormat
->Name
, FormatName
);
244 lpNewFormat
->hData
= 0;
245 lpNewFormat
->BufSize
= 0;
246 lpNewFormat
->PrevFormat
= lpFormat
;
247 lpNewFormat
->NextFormat
= NULL
;
248 return LastRegFormat
++;
252 /**************************************************************************
253 * GetClipboardFormatName [USER.146]
255 int GetClipboardFormatName(WORD wFormat
, LPSTR retStr
, short maxlen
)
257 LPCLIPFORMAT lpFormat
= ClipFormats
;
258 dprintf_clipboard(stddeb
,
259 "GetClipboardFormat(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
261 if (lpFormat
== NULL
) return 0;
262 if (lpFormat
->wFormatID
== wFormat
) break;
263 lpFormat
= lpFormat
->NextFormat
;
265 if (lpFormat
->Name
== NULL
) return 0;
266 dprintf_clipboard(stddeb
,
267 "GetClipboardFormat // Name='%s' !\n", lpFormat
->Name
);
268 maxlen
= MIN(maxlen
- 1, strlen(lpFormat
->Name
));
269 dprintf_clipboard(stddeb
,"GetClipboardFormat // maxlen=%d !\n", maxlen
);
270 memcpy(retStr
, lpFormat
->Name
, maxlen
);
276 /**************************************************************************
277 * SetClipboardViewer [USER.147]
279 HWND
SetClipboardViewer(HWND hWnd
)
281 HWND hwndPrev
= hWndViewer
;
282 dprintf_clipboard(stddeb
,"SetClipboardViewer("NPFMT
") !\n", hWnd
);
288 /**************************************************************************
289 * GetClipboardViewer [USER.148]
291 HWND
GetClipboardViewer()
293 dprintf_clipboard(stddeb
,"GetClipboardFormat() = "NPFMT
" !\n", hWndViewer
);
298 /**************************************************************************
299 * ChangeClipboardChain [USER.149]
301 BOOL
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
303 dprintf_clipboard(stdnimp
,
304 "ChangeClipboardChain("NPFMT
", "NPFMT
") !\n", hWnd
, hWndNext
);
310 /**************************************************************************
311 * IsClipboardFormatAvailable [USER.193]
313 BOOL
IsClipboardFormatAvailable(WORD wFormat
)
315 LPCLIPFORMAT lpFormat
= ClipFormats
;
316 dprintf_clipboard(stddeb
,"IsClipboardFormatAvailable(%04X) !\n", wFormat
);
317 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
) /* obtain selection as text if possible */
318 return GetClipboardData(CF_TEXT
)!=0;
320 if (lpFormat
== NULL
) return FALSE
;
321 if (lpFormat
->wFormatID
== wFormat
) break;
322 lpFormat
= lpFormat
->NextFormat
;
324 return (lpFormat
->hData
!= 0);
328 /**************************************************************************
329 * GetOpenClipboardWindow [USER.248]
331 HWND
GetOpenClipboardWindow()
333 dprintf_clipboard(stddeb
,
334 "GetOpenClipboardWindow() = "NPFMT
" !\n", hWndClipboardOwner
);
335 return hWndClipboardOwner
;
339 /**************************************************************************
340 * GetPriorityClipboardFormat [USER.402]
342 int GetPriorityClipboardFormat(WORD FAR
*lpPriorityList
, short nCount
)
344 dprintf_clipboard(stdnimp
,
345 "GetPriorityClipboardFormat(%p, %d) !\n", lpPriorityList
, nCount
);
351 /**************************************************************************
352 * CLIPBOARD_ReadSelection
354 * The current selection owner has set prop at our window w
355 * Transfer the property contents into the Clipboard
357 void CLIPBOARD_ReadSelection(Window w
,Atom prop
)
360 LPCLIPFORMAT lpFormat
= ClipFormats
;
366 unsigned long nitems
,remain
;
367 unsigned char *val
=NULL
;
368 dprintf_clipboard(stddeb
,"Received prop %s\n",XGetAtomName(display
,prop
));
369 /* TODO: Properties longer than 64K */
370 if(XGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
371 &atype
, &aformat
, &nitems
, &remain
, &val
)!=Success
)
372 printf("couldn't read property\n");
373 dprintf_clipboard(stddeb
,"Type %s,Format %d,nitems %ld,value %s\n",
374 XGetAtomName(display
,atype
),aformat
,nitems
,val
);
375 if(atype
!=XA_STRING
|| aformat
!=8){
376 fprintf(stderr
,"Property not set\n");
379 dprintf_clipboard(stddeb
,"Selection is %s\n",val
);
380 hText
=GlobalAlloc(GMEM_MOVEABLE
, nitems
);
381 memcpy(GlobalLock(hText
),val
,nitems
+1);
387 if (lpFormat
== NULL
) return;
388 if (lpFormat
->wFormatID
== CF_TEXT
) break;
389 lpFormat
= lpFormat
->NextFormat
;
391 if (lpFormat
->hData
!= 0) GlobalFree(lpFormat
->hData
);
392 wait_for_selection
=False
;
393 lpFormat
->hData
= hText
;
394 dprintf_clipboard(stddeb
,"Received selection\n");
397 /**************************************************************************
398 * CLIPBOARD_ReleaseSelection
400 * Wine lost the primary selection.
401 * Empty the clipboard, but don't set the current owner to None.
402 * Make sure current get/put attempts fail.
404 void CLIPBOARD_ReleaseSelection(HWND hwnd
)
406 wineOwnsSelection
=False
;