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