no message
[wxWidgets.git] / src / msw / clipbrd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: clipbrd.cpp
3 // Purpose: Clipboard functionality
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "clipbrd.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/setup.h"
25 #endif
26
27 #if wxUSE_CLIPBOARD
28
29 #ifndef WX_PRECOMP
30 #include "wx/app.h"
31 #include "wx/frame.h"
32 #include "wx/bitmap.h"
33 #include "wx/utils.h"
34 #endif
35
36 #include "wx/metafile.h"
37 #include "wx/clipbrd.h"
38 #include "wx/msw/private.h"
39 #include "wx/msw/dib.h"
40
41 #include <string.h>
42
43 #if !USE_SHARED_LIBRARY
44 IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
45 IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
46 #endif
47
48 bool wxClipboardIsOpen = FALSE;
49
50 bool wxOpenClipboard(void)
51 {
52 if (wxTheApp->GetTopWindow() && !wxClipboardIsOpen)
53 {
54 wxClipboardIsOpen = (::OpenClipboard((HWND) wxTheApp->GetTopWindow()->GetHWND()) != 0);
55 return wxClipboardIsOpen;
56 }
57 else return FALSE;
58 }
59
60 bool wxCloseClipboard(void)
61 {
62 if (wxClipboardIsOpen)
63 {
64 wxClipboardIsOpen = FALSE;
65 }
66 return (::CloseClipboard() != 0);
67 }
68
69 bool wxEmptyClipboard(void)
70 {
71 return (::EmptyClipboard() != 0);
72 }
73
74 bool wxClipboardOpen(void)
75 {
76 return wxClipboardIsOpen;
77 }
78
79 bool wxIsClipboardFormatAvailable(int dataFormat)
80 {
81 return (::IsClipboardFormatAvailable(dataFormat) != 0);
82 }
83
84 bool wxSetClipboardData(int dataFormat, wxObject *obj, int width, int height)
85 {
86 switch (dataFormat)
87 {
88 case wxDF_BITMAP:
89 {
90 wxBitmap *wxBM = (wxBitmap *)obj;
91
92 HDC hdcMem = CreateCompatibleDC(NULL);
93 HDC hdcSrc = CreateCompatibleDC(NULL);
94 HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, (HBITMAP) wxBM->GetHBITMAP());
95 HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
96 wxBM->GetWidth(), wxBM->GetHeight());
97 if (!hBitmap)
98 {
99 SelectObject(hdcSrc, old);
100 DeleteDC(hdcMem);
101 DeleteDC(hdcSrc);
102 return FALSE;
103 }
104 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
105 BitBlt(hdcMem, 0, 0, wxBM->GetWidth(), wxBM->GetHeight(),
106 hdcSrc, 0, 0, SRCCOPY);
107
108 // Select new bitmap out of memory DC
109 SelectObject(hdcMem, old1);
110
111 // Set the data
112 bool success = (bool)(::SetClipboardData(CF_BITMAP, hBitmap) != 0);
113
114 // Clean up
115 SelectObject(hdcSrc, old);
116 DeleteDC(hdcSrc);
117 DeleteDC(hdcMem);
118 return success;
119 break;
120 }
121 case wxDF_DIB:
122 {
123 #if wxUSE_IMAGE_LOADING_IN_MSW
124 HBITMAP hBitmap=(HBITMAP) ((wxBitmap *)obj)->GetHBITMAP();
125 HANDLE hDIB=BitmapToDIB(hBitmap,NULL); // NULL==uses system palette
126 bool success = (::SetClipboardData(CF_DIB,hDIB) != 0);
127 #else
128 bool success=FALSE;
129 #endif
130 return success;
131 break;
132 }
133 #if wxUSE_METAFILE
134 case wxDF_METAFILE:
135 {
136 wxMetaFile *wxMF = (wxMetaFile *)obj;
137 HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
138 #ifdef __WINDOWS_386__
139 METAFILEPICT *mf = (METAFILEPICT *)MK_FP32(GlobalLock(data));
140 #else
141 METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
142 #endif
143
144 mf->mm = wxMF->GetWindowsMappingMode();
145 mf->xExt = width;
146 mf->yExt = height;
147 mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
148 GlobalUnlock(data);
149 wxMF->SetHMETAFILE((WXHANDLE) NULL);
150
151 return (SetClipboardData(CF_METAFILEPICT, data) != 0);
152 break;
153 }
154 #endif
155 case CF_SYLK:
156 case CF_DIF:
157 case CF_TIFF:
158 case CF_PALETTE:
159 {
160 return FALSE;
161 break;
162 }
163 case wxDF_OEMTEXT:
164 dataFormat = wxDF_TEXT;
165 case wxDF_TEXT:
166 width = strlen((char *)obj) + 1;
167 height = 1;
168 default:
169 {
170 char *s = (char *)obj;
171 DWORD l;
172
173 l = (width * height);
174 HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
175 if (!hGlobalMemory)
176 return FALSE;
177
178 #ifdef __WINDOWS_386__
179 LPSTR lpGlobalMemory = (LPSTR)MK_FP32(GlobalLock(hGlobalMemory));
180 #else
181 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
182 #endif
183
184 #ifdef __WIN32__
185 memcpy(lpGlobalMemory, s, l);
186 #elif defined(__WATCOMC__) && defined(__WINDOWS_386__)
187 memcpy(lpGlobalMemory, s, l);
188 #else
189 hmemcpy(lpGlobalMemory, s, l);
190 #endif
191
192 GlobalUnlock(hGlobalMemory);
193 HANDLE success = SetClipboardData(dataFormat, hGlobalMemory);
194 return (success != 0);
195 break;
196 }
197 }
198 return FALSE;
199 }
200
201 wxObject *wxGetClipboardData(int dataFormat, long *len)
202 {
203 switch (dataFormat)
204 {
205 case wxDF_BITMAP:
206 {
207 BITMAP bm;
208 HBITMAP hBitmap = (HBITMAP) GetClipboardData(CF_BITMAP);
209 if (!hBitmap)
210 return NULL;
211
212 HDC hdcMem = CreateCompatibleDC(NULL);
213 HDC hdcSrc = CreateCompatibleDC(NULL);
214
215 HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, hBitmap);
216 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
217
218 HBITMAP hNewBitmap = CreateBitmapIndirect(&bm);
219
220 if (!hNewBitmap)
221 {
222 SelectObject(hdcSrc, old);
223 DeleteDC(hdcMem);
224 DeleteDC(hdcSrc);
225 return NULL;
226 }
227
228 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hNewBitmap);
229 BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,
230 hdcSrc, 0, 0, SRCCOPY);
231
232 // Select new bitmap out of memory DC
233 SelectObject(hdcMem, old1);
234
235 // Clean up
236 SelectObject(hdcSrc, old);
237 DeleteDC(hdcSrc);
238 DeleteDC(hdcMem);
239
240 // Create and return a new wxBitmap
241 wxBitmap *wxBM = new wxBitmap;
242 wxBM->SetHBITMAP((WXHBITMAP) hNewBitmap);
243 wxBM->SetWidth(bm.bmWidth);
244 wxBM->SetHeight(bm.bmHeight);
245 wxBM->SetDepth(bm.bmPlanes);
246 wxBM->SetOk(TRUE);
247 return (wxObject *)wxBM;
248 break;
249 }
250 case wxDF_METAFILE:
251 case CF_SYLK:
252 case CF_DIF:
253 case CF_TIFF:
254 case CF_PALETTE:
255 case wxDF_DIB:
256 {
257 return FALSE;
258 break;
259 }
260 case wxDF_OEMTEXT:
261 dataFormat = wxDF_TEXT;
262 case wxDF_TEXT:
263 default:
264 {
265 HANDLE hGlobalMemory = GetClipboardData(dataFormat);
266 if (!hGlobalMemory)
267 return NULL;
268
269 int hsize = (int)GlobalSize(hGlobalMemory);
270 if (len)
271 *len = hsize;
272
273 char *s = new char[hsize];
274 if (!s)
275 return NULL;
276
277 #ifdef __WINDOWS_386__
278 LPSTR lpGlobalMemory = (LPSTR)MK_FP32(GlobalLock(hGlobalMemory));
279 #else
280 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
281 #endif
282
283 #ifdef __WIN32__
284 memcpy(s, lpGlobalMemory, GlobalSize(hGlobalMemory));
285 #elif __WATCOMC__ && defined(__WINDOWS_386__)
286 memcpy(s, lpGlobalMemory, GlobalSize(hGlobalMemory));
287 #else
288 hmemcpy(s, lpGlobalMemory, GlobalSize(hGlobalMemory));
289 #endif
290
291 GlobalUnlock(hGlobalMemory);
292
293 return (wxObject *)s;
294 break;
295 }
296 }
297 return NULL;
298 }
299
300 int wxEnumClipboardFormats(int dataFormat)
301 {
302 return ::EnumClipboardFormats(dataFormat);
303 }
304
305 int wxRegisterClipboardFormat(char *formatName)
306 {
307 return ::RegisterClipboardFormat(formatName);
308 }
309
310 bool wxGetClipboardFormatName(int dataFormat, char *formatName, int maxCount)
311 {
312 return (::GetClipboardFormatName(dataFormat, formatName, maxCount) > 0);
313 }
314
315 /*
316 * Generalized clipboard implementation by Matthew Flatt
317 */
318
319 wxClipboard *wxTheClipboard = NULL;
320
321 void wxInitClipboard(void)
322 {
323 if (!wxTheClipboard)
324 wxTheClipboard = new wxClipboard;
325 }
326
327 wxClipboard::wxClipboard()
328 {
329 clipOwner = NULL;
330 cbString = NULL;
331 }
332
333 wxClipboard::~wxClipboard()
334 {
335 if (clipOwner)
336 clipOwner->BeingReplaced();
337 if (cbString)
338 delete[] cbString;
339 }
340
341 static int FormatStringToID(char *str)
342 {
343 if (!strcmp(str, "TEXT"))
344 return wxDF_TEXT;
345
346 return wxRegisterClipboardFormat(str);
347 }
348
349 void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
350 {
351 bool got_selection;
352
353 if (clipOwner)
354 clipOwner->BeingReplaced();
355 clipOwner = client;
356 if (cbString) {
357 delete[] cbString;
358 cbString = NULL;
359 }
360
361 if (wxOpenClipboard()) {
362 char **formats, *data;
363 int i;
364 int ftype;
365 long size;
366
367 formats = clipOwner->formats.ListToArray(FALSE);
368 for (i = clipOwner->formats.Number(); i--; ) {
369 ftype = FormatStringToID(formats[i]);
370 data = clipOwner->GetData(formats[i], &size);
371 if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
372 got_selection = FALSE;
373 break;
374 }
375 }
376
377 if (i < 0)
378 got_selection = wxCloseClipboard();
379 } else
380 got_selection = FALSE;
381
382 got_selection = FALSE; // Assume another process takes over
383
384 if (!got_selection) {
385 clipOwner->BeingReplaced();
386 clipOwner = NULL;
387 }
388 }
389
390 wxClipboardClient *wxClipboard::GetClipboardClient()
391 {
392 return clipOwner;
393 }
394
395 void wxClipboard::SetClipboardString(char *str, long time)
396 {
397 bool got_selection;
398
399 if (clipOwner) {
400 clipOwner->BeingReplaced();
401 clipOwner = NULL;
402 }
403 if (cbString)
404 delete[] cbString;
405
406 cbString = str;
407
408 if (wxOpenClipboard()) {
409 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
410 got_selection = FALSE;
411 else
412 got_selection = wxCloseClipboard();
413 } else
414 got_selection = FALSE;
415
416 got_selection = FALSE; // Assume another process takes over
417
418 if (!got_selection) {
419 delete[] cbString;
420 cbString = NULL;
421 }
422 }
423
424 char *wxClipboard::GetClipboardString(long time)
425 {
426 char *str;
427 long length;
428
429 str = GetClipboardData("TEXT", &length, time);
430 if (!str) {
431 str = new char[1];
432 *str = 0;
433 }
434
435 return str;
436 }
437
438 char *wxClipboard::GetClipboardData(char *format, long *length, long time)
439 {
440 if (clipOwner) {
441 if (clipOwner->formats.Member(format))
442 return clipOwner->GetData(format, length);
443 else
444 return NULL;
445 } else if (cbString) {
446 if (!strcmp(format, "TEXT"))
447 return copystring(cbString);
448 else
449 return NULL;
450 } else {
451 if (wxOpenClipboard()) {
452 receivedString = (char *)wxGetClipboardData(FormatStringToID(format),
453 length);
454 wxCloseClipboard();
455 } else
456 receivedString = NULL;
457
458 return receivedString;
459 }
460 }
461
462
463 #endif // wxUSE_CLIPBOARD
464