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