]>
Commit | Line | Data |
---|---|---|
e9576ca5 SC |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: clipbrd.cpp | |
3 | // Purpose: Clipboard functionality | |
4 | // Author: AUTHOR | |
5 | // Modified by: | |
6 | // Created: ??/??/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) AUTHOR | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | #ifdef __GNUG__ | |
13 | #pragma implementation | |
14 | #pragma implementation "clipbrd.h" | |
15 | #endif | |
16 | ||
17 | #include "wx/app.h" | |
18 | #include "wx/frame.h" | |
19 | #include "wx/bitmap.h" | |
20 | #include "wx/utils.h" | |
21 | #include "wx/metafile.h" | |
22 | #include "wx/clipbrd.h" | |
23 | ||
2f1ae414 SC |
24 | #define wxUSE_DATAOBJ 1 |
25 | ||
e9576ca5 SC |
26 | #include <string.h> |
27 | ||
7c74e7fe | 28 | // open/close |
2f1ae414 SC |
29 | |
30 | bool clipboard_opened = false ; | |
31 | ||
e9576ca5 SC |
32 | bool wxOpenClipboard() |
33 | { | |
2f1ae414 | 34 | clipboard_opened = true ; |
519cb848 | 35 | return TRUE; |
e9576ca5 SC |
36 | } |
37 | ||
38 | bool wxCloseClipboard() | |
39 | { | |
2f1ae414 | 40 | clipboard_opened = false ; |
7c74e7fe | 41 | return TRUE; |
e9576ca5 SC |
42 | } |
43 | ||
7c74e7fe | 44 | bool wxIsClipboardOpened() |
e9576ca5 | 45 | { |
2f1ae414 | 46 | return clipboard_opened; |
e9576ca5 SC |
47 | } |
48 | ||
7c74e7fe | 49 | bool wxEmptyClipboard() |
e9576ca5 | 50 | { |
2f1ae414 SC |
51 | |
52 | #if TARGET_CARBON | |
53 | OSStatus err ; | |
54 | err = ClearCurrentScrap( ); | |
55 | #else | |
56 | OSErr err ; | |
57 | err = ZeroScrap( ); | |
58 | #endif | |
59 | if ( err ) | |
60 | { | |
61 | wxLogSysError(_("Failed to empty the clipboard.")); | |
62 | return FALSE ; | |
63 | } | |
7c74e7fe | 64 | return TRUE; |
e9576ca5 SC |
65 | } |
66 | ||
2f1ae414 SC |
67 | // get/set data |
68 | ||
69 | // clipboard formats | |
70 | ||
71 | bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat) | |
e9576ca5 | 72 | { |
2f1ae414 SC |
73 | #if TARGET_CARBON |
74 | OSStatus err = noErr; | |
75 | ScrapRef scrapRef; | |
76 | ||
77 | err = GetCurrentScrap( &scrapRef ); | |
78 | if ( err != noTypeErr && err != memFullErr ) | |
79 | { | |
80 | ScrapFlavorFlags flavorFlags; | |
81 | Size byteCount; | |
82 | ||
83 | if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr) | |
84 | { | |
85 | if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr) | |
86 | { | |
87 | return TRUE ; | |
88 | } | |
89 | } | |
90 | } | |
91 | return FALSE; | |
92 | ||
93 | #else | |
94 | long offset ; | |
95 | if ( GetScrap( NULL , dataFormat.GetFormatId() , &offset ) > 0 ) | |
96 | { | |
97 | return TRUE ; | |
98 | } | |
99 | return FALSE; | |
100 | #endif | |
e9576ca5 SC |
101 | } |
102 | ||
2f1ae414 | 103 | bool wxSetClipboardData(wxDataFormat dataFormat,const void *data,int width , int height) |
e9576ca5 | 104 | { |
2f1ae414 SC |
105 | #if !TARGET_CARBON |
106 | OSErr err = noErr ; | |
107 | #else | |
108 | OSStatus err = noErr ; | |
109 | #endif | |
110 | ||
111 | switch (dataFormat.GetType()) | |
112 | { | |
113 | case wxDF_BITMAP: | |
114 | { | |
115 | /* | |
116 | wxBitmap *bitmap = (wxBitmap *)data; | |
117 | ||
118 | HDC hdcMem = CreateCompatibleDC((HDC) NULL); | |
119 | HDC hdcSrc = CreateCompatibleDC((HDC) NULL); | |
120 | HBITMAP old = (HBITMAP) | |
121 | ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP()); | |
122 | HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc, | |
123 | bitmap->GetWidth(), | |
124 | bitmap->GetHeight()); | |
125 | if (!hBitmap) | |
126 | { | |
127 | SelectObject(hdcSrc, old); | |
128 | DeleteDC(hdcMem); | |
129 | DeleteDC(hdcSrc); | |
130 | return FALSE; | |
131 | } | |
132 | ||
133 | HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap); | |
134 | BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(), | |
135 | hdcSrc, 0, 0, SRCCOPY); | |
136 | ||
137 | // Select new bitmap out of memory DC | |
138 | SelectObject(hdcMem, old1); | |
139 | ||
140 | // Set the data | |
141 | handle = ::SetClipboardData(CF_BITMAP, hBitmap); | |
142 | ||
143 | // Clean up | |
144 | SelectObject(hdcSrc, old); | |
145 | DeleteDC(hdcSrc); | |
146 | DeleteDC(hdcMem); | |
147 | */ | |
148 | break; | |
149 | } | |
e9576ca5 | 150 | |
2f1ae414 SC |
151 | case wxDF_DIB: |
152 | { | |
153 | /* | |
154 | #if wxUSE_IMAGE_LOADING_IN_MSW | |
155 | wxBitmap *bitmap = (wxBitmap *)data; | |
156 | HBITMAP hBitmap = (HBITMAP)bitmap->GetHBITMAP(); | |
157 | // NULL palette means to use the system one | |
158 | HANDLE hDIB = wxBitmapToDIB(hBitmap, (HPALETTE)NULL); | |
159 | handle = SetClipboardData(CF_DIB, hDIB); | |
160 | #endif // wxUSE_IMAGE_LOADING_IN_MSW | |
161 | */ | |
162 | break; | |
163 | } | |
7c74e7fe | 164 | |
2f1ae414 SC |
165 | #if wxUSE_METAFILE |
166 | case wxDF_METAFILE: | |
167 | { | |
168 | wxMetafile *wxMF = (wxMetafile *)data; | |
169 | PicHandle pict = wxMF->GetHMETAFILE() ; | |
170 | HLock( (Handle) pict ) ; | |
171 | #if !TARGET_CARBON | |
172 | err = PutScrap( GetHandleSize( (Handle) pict ) , 'PICT' , *pict ) ; | |
173 | #else | |
174 | ScrapRef scrap; | |
175 | err = GetCurrentScrap (&scrap); | |
176 | if ( !err ) | |
177 | { | |
178 | err = PutScrapFlavor (scrap, 'PICT', 0, GetHandleSize((Handle) pict), *pict); | |
179 | } | |
180 | #endif | |
181 | HUnlock( (Handle) pict ) ; | |
182 | break; | |
183 | } | |
184 | #endif | |
185 | case wxDF_SYLK: | |
186 | case wxDF_DIF: | |
187 | case wxDF_TIFF: | |
188 | case wxDF_PALETTE: | |
189 | default: | |
190 | { | |
191 | wxLogError(_("Unsupported clipboard format.")); | |
192 | return FALSE; | |
193 | } | |
7c74e7fe | 194 | |
2f1ae414 SC |
195 | case wxDF_OEMTEXT: |
196 | dataFormat = wxDF_TEXT; | |
197 | // fall through | |
198 | ||
199 | case wxDF_TEXT: | |
200 | { | |
201 | wxString mac ; | |
202 | if ( wxApp::s_macDefaultEncodingIsPC ) | |
203 | { | |
204 | mac = wxMacMakeMacStringFromPC((char *)data) ; | |
205 | } | |
206 | else | |
207 | { | |
208 | mac = (char *)data ; | |
209 | } | |
210 | #if !TARGET_CARBON | |
211 | err = PutScrap( mac.Length() , 'TEXT' , mac.c_str() ) ; | |
212 | #else | |
213 | ScrapRef scrap; | |
214 | err = GetCurrentScrap (&scrap); | |
215 | if ( !err ) | |
216 | { | |
217 | err = PutScrapFlavor (scrap, 'TEXT', 0, mac.Length(), mac.c_str()); | |
218 | } | |
219 | #endif | |
220 | break; | |
221 | } | |
222 | } | |
223 | ||
224 | if ( err ) | |
225 | { | |
226 | wxLogSysError(_("Failed to set clipboard data.")); | |
227 | ||
228 | return FALSE; | |
229 | } | |
230 | ||
231 | return TRUE; | |
e9576ca5 SC |
232 | } |
233 | ||
7c74e7fe | 234 | wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat) |
e9576ca5 | 235 | { |
7c74e7fe | 236 | return wxDataFormat(); |
e9576ca5 SC |
237 | } |
238 | ||
7c74e7fe | 239 | int wxRegisterClipboardFormat(wxChar *formatName) |
e9576ca5 | 240 | { |
e9576ca5 SC |
241 | return 0; |
242 | } | |
243 | ||
7c74e7fe | 244 | bool wxGetClipboardFormatName(wxDataFormat dataFormat, wxChar *formatName, int maxCount) |
e9576ca5 | 245 | { |
e9576ca5 SC |
246 | return FALSE; |
247 | } | |
248 | ||
2f1ae414 SC |
249 | void *wxGetClipboardData(wxDataFormat dataFormat, long *len) |
250 | { | |
251 | return NULL; | |
252 | } | |
253 | ||
254 | ||
e9576ca5 SC |
255 | /* |
256 | * Generalized clipboard implementation by Matthew Flatt | |
257 | */ | |
258 | ||
2f1ae414 | 259 | IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxClipboardBase) |
7c74e7fe | 260 | |
e7549107 SC |
261 | wxClipboard::wxClipboard() |
262 | { | |
263 | m_clearOnExit = FALSE; | |
264 | } | |
e9576ca5 | 265 | |
e7549107 | 266 | wxClipboard::~wxClipboard() |
e9576ca5 | 267 | { |
e7549107 SC |
268 | if ( m_clearOnExit ) |
269 | { | |
270 | Clear(); | |
271 | } | |
e9576ca5 SC |
272 | } |
273 | ||
e7549107 | 274 | void wxClipboard::Clear() |
e9576ca5 | 275 | { |
e9576ca5 SC |
276 | } |
277 | ||
e7549107 | 278 | bool wxClipboard::Flush() |
e9576ca5 | 279 | { |
e7549107 SC |
280 | return FALSE; |
281 | } | |
282 | ||
283 | bool wxClipboard::Open() | |
284 | { | |
285 | return wxOpenClipboard(); | |
286 | } | |
287 | ||
288 | bool wxClipboard::IsOpened() const | |
289 | { | |
290 | return wxIsClipboardOpened(); | |
e9576ca5 SC |
291 | } |
292 | ||
293 | static int FormatStringToID(char *str) | |
294 | { | |
295 | if (!strcmp(str, "TEXT")) | |
296 | return wxDF_TEXT; | |
297 | ||
298 | return wxRegisterClipboardFormat(str); | |
299 | } | |
300 | ||
e7549107 SC |
301 | bool wxClipboard::SetData( wxDataObject *data ) |
302 | { | |
303 | (void)wxEmptyClipboard(); | |
304 | ||
305 | if ( data ) | |
306 | return AddData(data); | |
307 | else | |
308 | return TRUE; | |
309 | } | |
310 | ||
311 | bool wxClipboard::AddData( wxDataObject *data ) | |
312 | { | |
313 | wxCHECK_MSG( data, FALSE, wxT("data is invalid") ); | |
314 | ||
315 | #if wxUSE_DATAOBJ | |
316 | wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") ); | |
317 | ||
2f1ae414 | 318 | wxDataFormat format = data->GetPreferredFormat(); |
e7549107 | 319 | |
2f1ae414 | 320 | switch ( format.GetType() ) |
e7549107 SC |
321 | { |
322 | case wxDF_TEXT: | |
323 | case wxDF_OEMTEXT: | |
324 | { | |
325 | wxTextDataObject* textDataObject = (wxTextDataObject*) data; | |
326 | wxString str(textDataObject->GetText()); | |
327 | return wxSetClipboardData(format, str.c_str()); | |
328 | } | |
329 | ||
330 | case wxDF_BITMAP: | |
331 | case wxDF_DIB: | |
332 | { | |
333 | wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data; | |
334 | wxBitmap bitmap(bitmapDataObject->GetBitmap()); | |
2f1ae414 | 335 | return wxSetClipboardData(format, &bitmap); |
e7549107 SC |
336 | } |
337 | ||
2f1ae414 | 338 | #if 0 // wxUSE_METAFILE |
e7549107 SC |
339 | case wxDF_METAFILE: |
340 | { | |
341 | wxMetafileDataObject* metaFileDataObject = | |
342 | (wxMetafileDataObject*) data; | |
343 | wxMetafile metaFile = metaFileDataObject->GetMetafile(); | |
344 | return wxSetClipboardData(wxDF_METAFILE, &metaFile, | |
345 | metaFileDataObject->GetWidth(), | |
346 | metaFileDataObject->GetHeight()); | |
347 | } | |
348 | #endif // wxUSE_METAFILE | |
349 | ||
350 | default: | |
2f1ae414 SC |
351 | // return wxSetClipboardData(data); |
352 | break ; | |
e7549107 SC |
353 | } |
354 | #else // !wxUSE_DATAOBJ | |
e7549107 | 355 | #endif |
2f1ae414 | 356 | return FALSE; |
e7549107 SC |
357 | } |
358 | ||
359 | void wxClipboard::Close() | |
360 | { | |
361 | wxCloseClipboard(); | |
362 | } | |
363 | ||
2f1ae414 | 364 | bool wxClipboard::IsSupported( const wxDataFormat &format ) |
e7549107 SC |
365 | { |
366 | return wxIsClipboardFormatAvailable(format); | |
367 | } | |
368 | ||
369 | bool wxClipboard::GetData( wxDataObject& data ) | |
370 | { | |
371 | #if wxUSE_DATAOBJ | |
372 | wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") ); | |
373 | ||
2f1ae414 | 374 | wxDataFormat format = data.GetPreferredFormat(); |
e7549107 SC |
375 | switch ( format ) |
376 | { | |
377 | case wxDF_TEXT: | |
378 | case wxDF_OEMTEXT: | |
379 | { | |
380 | wxTextDataObject& textDataObject = (wxTextDataObject &)data; | |
381 | char* s = (char*)wxGetClipboardData(format); | |
382 | if ( !s ) | |
383 | return FALSE; | |
384 | ||
385 | textDataObject.SetText(s); | |
386 | delete [] s; | |
387 | ||
388 | return TRUE; | |
389 | } | |
390 | ||
391 | case wxDF_BITMAP: | |
392 | case wxDF_DIB: | |
393 | { | |
394 | wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data; | |
2f1ae414 | 395 | wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(format ); |
e7549107 SC |
396 | if ( !bitmap ) |
397 | return FALSE; | |
398 | ||
399 | bitmapDataObject.SetBitmap(*bitmap); | |
400 | delete bitmap; | |
401 | ||
402 | return TRUE; | |
403 | } | |
2f1ae414 | 404 | #if 0 // wxUSE_METAFILE |
e7549107 SC |
405 | case wxDF_METAFILE: |
406 | { | |
407 | wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data; | |
408 | wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE); | |
409 | if ( !metaFile ) | |
410 | return FALSE; | |
411 | ||
412 | metaFileDataObject.SetMetafile(*metaFile); | |
413 | delete metaFile; | |
414 | ||
415 | return TRUE; | |
416 | } | |
417 | #endif // wxUSE_METAFILE | |
418 | } | |
419 | #else // !wxUSE_DATAOBJ | |
420 | wxFAIL_MSG( wxT("no clipboard implementation") ); | |
421 | #endif | |
422 | return FALSE; | |
423 | } | |
424 | /* | |
e9576ca5 SC |
425 | void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time) |
426 | { | |
427 | bool got_selection; | |
428 | ||
429 | if (clipOwner) | |
430 | clipOwner->BeingReplaced(); | |
431 | clipOwner = client; | |
432 | if (cbString) { | |
433 | delete[] cbString; | |
434 | cbString = NULL; | |
435 | } | |
436 | ||
437 | if (wxOpenClipboard()) { | |
438 | char **formats, *data; | |
439 | int i; | |
440 | int ftype; | |
441 | long size; | |
442 | ||
443 | formats = clipOwner->formats.ListToArray(FALSE); | |
444 | for (i = clipOwner->formats.Number(); i--; ) { | |
445 | ftype = FormatStringToID(formats[i]); | |
446 | data = clipOwner->GetData(formats[i], &size); | |
447 | if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) { | |
448 | got_selection = FALSE; | |
449 | break; | |
450 | } | |
451 | } | |
452 | ||
453 | if (i < 0) | |
454 | got_selection = wxCloseClipboard(); | |
455 | } else | |
456 | got_selection = FALSE; | |
457 | ||
458 | got_selection = FALSE; // Assume another process takes over | |
459 | ||
460 | if (!got_selection) { | |
461 | clipOwner->BeingReplaced(); | |
462 | clipOwner = NULL; | |
463 | } | |
464 | } | |
465 | ||
466 | wxClipboardClient *wxClipboard::GetClipboardClient() | |
467 | { | |
468 | return clipOwner; | |
469 | } | |
470 | ||
471 | void wxClipboard::SetClipboardString(char *str, long time) | |
e7549107 | 472 | { |
e9576ca5 SC |
473 | bool got_selection; |
474 | ||
475 | if (clipOwner) { | |
476 | clipOwner->BeingReplaced(); | |
477 | clipOwner = NULL; | |
478 | } | |
479 | if (cbString) | |
480 | delete[] cbString; | |
481 | ||
482 | cbString = str; | |
483 | ||
484 | if (wxOpenClipboard()) { | |
485 | if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str)) | |
486 | got_selection = FALSE; | |
487 | else | |
488 | got_selection = wxCloseClipboard(); | |
489 | } else | |
490 | got_selection = FALSE; | |
491 | ||
492 | got_selection = FALSE; // Assume another process takes over | |
493 | ||
494 | if (!got_selection) { | |
495 | delete[] cbString; | |
496 | cbString = NULL; | |
497 | } | |
498 | } | |
e9576ca5 SC |
499 | char *wxClipboard::GetClipboardString(long time) |
500 | { | |
501 | char *str; | |
502 | long length; | |
503 | ||
504 | str = GetClipboardData("TEXT", &length, time); | |
505 | if (!str) { | |
506 | str = new char[1]; | |
507 | *str = 0; | |
508 | } | |
509 | ||
510 | return str; | |
511 | } | |
512 | ||
e7549107 | 513 | |
e9576ca5 SC |
514 | char *wxClipboard::GetClipboardData(char *format, long *length, long time) |
515 | { | |
516 | if (clipOwner) { | |
517 | if (clipOwner->formats.Member(format)) | |
518 | return clipOwner->GetData(format, length); | |
519 | else | |
520 | return NULL; | |
521 | } else if (cbString) { | |
522 | if (!strcmp(format, "TEXT")) | |
523 | return copystring(cbString); | |
524 | else | |
525 | return NULL; | |
526 | } else { | |
527 | if (wxOpenClipboard()) { | |
528 | receivedString = (char *)wxGetClipboardData(FormatStringToID(format), | |
529 | length); | |
530 | wxCloseClipboard(); | |
531 | } else | |
532 | receivedString = NULL; | |
533 | ||
534 | return receivedString; | |
535 | } | |
536 | } | |
e7549107 | 537 | */ |
e9576ca5 | 538 |