]> git.saurik.com Git - wxWidgets.git/blob - src/motif/clipbrd.cpp
Avoid crash during global destruction.
[wxWidgets.git] / src / motif / clipbrd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: clipbrd.cpp
3 // Purpose: Clipboard functionality
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #pragma implementation "clipbrd.h"
15 #endif
16
17 #include "wx/defs.h"
18
19 #if wxUSE_CLIPBOARD
20
21 #include "wx/app.h"
22 #include "wx/frame.h"
23 #include "wx/bitmap.h"
24 #include "wx/utils.h"
25 #include "wx/metafile.h"
26 #include "wx/clipbrd.h"
27 #include "wx/dataobj.h"
28
29 #include "wx/listimpl.cpp"
30 WX_DEFINE_LIST(wxDataObjectList);
31
32 #ifdef __VMS__
33 #pragma message disable nosimpint
34 #endif
35 #include <Xm/Xm.h>
36 #include <Xm/CutPaste.h>
37 #ifdef __VMS__
38 #pragma message enable nosimpint
39 #endif
40
41 #include <string.h>
42
43 // IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
44 // IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
45
46 static bool gs_clipboardIsOpen = FALSE;
47
48 bool wxOpenClipboard()
49 {
50 if (!gs_clipboardIsOpen)
51 {
52 gs_clipboardIsOpen = TRUE;
53 return TRUE;
54 }
55 else
56 return FALSE;
57 }
58
59 bool wxCloseClipboard()
60 {
61 if (gs_clipboardIsOpen)
62 {
63 gs_clipboardIsOpen = FALSE;
64 return TRUE;
65 }
66 else
67 return FALSE;
68 }
69
70 bool wxEmptyClipboard()
71 {
72 // No equivalent in Motif
73 return TRUE;
74 }
75
76 bool wxClipboardOpen()
77 {
78 return gs_clipboardIsOpen;
79 }
80
81 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
82 {
83 // Only text is supported.
84 if (dataFormat != wxDF_TEXT)
85 return FALSE;
86
87 unsigned long numBytes = 0;
88 long privateId = 0;
89
90 Window window = (Window) 0;
91 if (wxTheApp->GetTopWindow())
92 window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
93
94 int success = XmClipboardRetrieve((Display*) wxGetDisplay(),
95 window, "TEXT", (XtPointer) 0, 0, & numBytes, & privateId) ;
96
97 // Assume only text is supported. If we have anything at all,
98 // or the clipboard is locked so we're not sure, we say we support it.
99 if (success == ClipboardNoData)
100 return FALSE;
101 else
102 return TRUE;
103 }
104
105 bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj, int WXUNUSED(width), int WXUNUSED(height))
106 {
107 if (dataFormat != wxDF_TEXT)
108 return FALSE;
109
110 char* data = (char*) obj;
111
112 XmString text = XmStringCreateSimple ("CLIPBOARD");
113 Window window = (Window) 0;
114 if (wxTheApp->GetTopWindow())
115 window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
116
117 long itemId = 0;
118 int result = 0;
119
120 while ((result =
121 XmClipboardStartCopy((Display*) wxGetDisplay(),
122 window,
123 text,
124 XtLastTimestampProcessed((Display*) wxGetDisplay()),
125 (Widget) 0,
126 (XmCutPasteProc) 0,
127 & itemId)) != ClipboardSuccess)
128
129 ;
130
131 XmStringFree (text);
132
133 long dataId = 0;
134 while ((result =
135 XmClipboardCopy((Display*) wxGetDisplay(),
136 window,
137 itemId,
138 "TEXT",
139 (XtPointer) data,
140 strlen(data) + 1,
141 0,
142 & dataId)) != ClipboardSuccess)
143
144 ;
145
146 while (( result =
147 XmClipboardEndCopy((Display*) wxGetDisplay(),
148 window, itemId) ) != ClipboardSuccess)
149
150 ;
151
152 return TRUE;
153 }
154
155 wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
156 {
157 if (dataFormat != wxDF_TEXT)
158 return (wxObject*) NULL;
159
160 bool done = FALSE;
161 long id = 0;
162 unsigned long numBytes = 0;
163 int result = 0;
164 Window window = (Window) 0;
165 if (wxTheApp->GetTopWindow())
166 window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
167
168 int currentDataSize = 256;
169 char* data = new char[currentDataSize];
170
171 while (!done)
172 {
173 if (result == ClipboardTruncate)
174 {
175 delete[] data;
176 currentDataSize = 2*currentDataSize;
177 data = new char[currentDataSize];
178 }
179 result = XmClipboardRetrieve((Display*) wxGetDisplay(),
180 window,
181 "TEXT",
182 (XtPointer) data,
183 currentDataSize,
184 &numBytes,
185 &id);
186
187 switch (result)
188 {
189 case ClipboardSuccess:
190 {
191 if (len)
192 *len = strlen(data) + 1;
193 return (wxObject*) data;
194 break;
195 }
196 case ClipboardTruncate:
197 case ClipboardLocked:
198 {
199 break;
200 }
201 default:
202 case ClipboardNoData:
203 {
204 return (wxObject*) NULL;
205 break;
206 }
207 }
208
209 }
210
211 return NULL;
212 }
213
214 wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
215 {
216 // Only wxDF_TEXT supported
217 if (dataFormat == wxDF_TEXT)
218 return wxDF_TEXT;
219 else
220 return wxDF_INVALID;
221 }
222
223 wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
224 {
225 // Not supported
226 return (wxDataFormat) wxDF_INVALID;
227 }
228
229 bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int WXUNUSED(maxCount))
230 {
231 // Only wxDF_TEXT supported
232 if (dataFormat == wxDF_TEXT)
233 {
234 strcpy(formatName, "TEXT");
235 return TRUE;
236 }
237 else
238 return FALSE;
239 }
240
241 //-----------------------------------------------------------------------------
242 // wxClipboard
243 //-----------------------------------------------------------------------------
244
245 IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
246
247 wxClipboard::wxClipboard()
248 {
249 m_open = FALSE;
250 }
251
252 wxClipboard::~wxClipboard()
253 {
254 Clear();
255 }
256
257 void wxClipboard::Clear()
258 {
259 wxDataObjectList::Node* node = m_data.GetFirst();
260 while (node)
261 {
262 wxDataObject* data = node->GetData();
263 delete data;
264 node = node->GetNext();
265 }
266 m_data.Clear();
267 }
268
269 bool wxClipboard::Open()
270 {
271 wxCHECK_MSG( !m_open, FALSE, "clipboard already open" );
272
273 m_open = TRUE;
274
275 return wxOpenClipboard();
276 }
277
278 bool wxClipboard::SetData( wxDataObject *data )
279 {
280 wxCHECK_MSG( data, FALSE, "data is invalid" );
281 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
282
283 Clear();
284
285 return AddData( data );
286 }
287
288 bool wxClipboard::AddData( wxDataObject *data )
289 {
290 wxCHECK_MSG( data, FALSE, "data is invalid" );
291 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
292
293 wxDataFormat::NativeFormat format = data->GetPreferredFormat().GetType();
294 switch ( format )
295 {
296 case wxDF_TEXT:
297 case wxDF_OEMTEXT:
298 {
299 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
300 wxString str(textDataObject->GetText());
301 return wxSetClipboardData(format, (wxObject*) (const char*) str);
302 }
303 #if 0
304 case wxDF_BITMAP:
305 case wxDF_DIB:
306 {
307 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
308 wxBitmap bitmap(bitmapDataObject->GetBitmap());
309 return wxSetClipboardData(data->GetType(), & bitmap);
310 break;
311 }
312 #endif // 0
313 }
314
315 return FALSE;
316 }
317
318 void wxClipboard::Close()
319 {
320 wxCHECK_RET( m_open, "clipboard not open" );
321
322 m_open = FALSE;
323 wxCloseClipboard();
324 }
325
326 bool wxClipboard::IsSupported( const wxDataFormat& format)
327 {
328 return wxIsClipboardFormatAvailable(format);
329 }
330
331 bool wxClipboard::GetData( wxDataObject& data )
332 {
333 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
334
335 wxDataFormat::NativeFormat format = data.GetPreferredFormat().GetType();
336 switch ( format )
337 {
338 case wxDF_TEXT:
339 case wxDF_OEMTEXT:
340 {
341 wxTextDataObject& textDataObject = (wxTextDataObject &) data;
342 char* s = (char*) wxGetClipboardData(format);
343 if (s)
344 {
345 textDataObject.SetText(s);
346 delete[] s;
347 return TRUE;
348 }
349 else
350 return FALSE;
351 break;
352 }
353 /*
354 case wxDF_BITMAP:
355 case wxDF_DIB:
356 {
357 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
358 wxBitmap* bitmap = (wxBitmap*) wxGetClipboardData(data->GetType());
359 if (bitmap)
360 {
361 bitmapDataObject->SetBitmap(* bitmap);
362 delete bitmap;
363 return TRUE;
364 }
365 else
366 return FALSE;
367 break;
368 }
369 */
370 default:
371 {
372 #ifndef __VMS
373 // VMS complains that this statement is/causes unreachability
374 return FALSE;
375 #endif
376 }
377 }
378
379 return FALSE;
380 }
381
382 #if 0
383
384 /*
385 * Old clipboard implementation by Matthew Flatt
386 */
387
388 wxClipboard *wxTheClipboard = NULL;
389
390 void wxInitClipboard()
391 {
392 if (!wxTheClipboard)
393 wxTheClipboard = new wxClipboard;
394 }
395
396 wxClipboard::wxClipboard()
397 {
398 clipOwner = NULL;
399 cbString = NULL;
400 }
401
402 wxClipboard::~wxClipboard()
403 {
404 if (clipOwner)
405 clipOwner->BeingReplaced();
406 if (cbString)
407 delete[] cbString;
408 }
409
410 static int FormatStringToID(char *str)
411 {
412 if (!strcmp(str, "TEXT"))
413 return wxDF_TEXT;
414
415 return wxRegisterClipboardFormat(str);
416 }
417
418 void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
419 {
420 bool got_selection;
421
422 if (clipOwner)
423 clipOwner->BeingReplaced();
424 clipOwner = client;
425 if (cbString) {
426 delete[] cbString;
427 cbString = NULL;
428 }
429
430 if (wxOpenClipboard()) {
431 char **formats, *data;
432 int i;
433 int ftype;
434 long size;
435
436 formats = clipOwner->formats.ListToArray(FALSE);
437 for (i = clipOwner->formats.Number(); i--; ) {
438 ftype = FormatStringToID(formats[i]);
439 data = clipOwner->GetData(formats[i], &size);
440 if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
441 got_selection = FALSE;
442 break;
443 }
444 }
445
446 if (i < 0)
447 got_selection = wxCloseClipboard();
448 } else
449 got_selection = FALSE;
450
451 got_selection = FALSE; // Assume another process takes over
452
453 if (!got_selection) {
454 clipOwner->BeingReplaced();
455 clipOwner = NULL;
456 }
457 }
458
459 wxClipboardClient *wxClipboard::GetClipboardClient()
460 {
461 return clipOwner;
462 }
463
464 void wxClipboard::SetClipboardString(char *str, long time)
465 {
466 bool got_selection;
467
468 if (clipOwner) {
469 clipOwner->BeingReplaced();
470 clipOwner = NULL;
471 }
472 if (cbString)
473 delete[] cbString;
474
475 cbString = str;
476
477 if (wxOpenClipboard()) {
478 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
479 got_selection = FALSE;
480 else
481 got_selection = wxCloseClipboard();
482 } else
483 got_selection = FALSE;
484
485 got_selection = FALSE; // Assume another process takes over
486
487 if (!got_selection) {
488 delete[] cbString;
489 cbString = NULL;
490 }
491 }
492
493 char *wxClipboard::GetClipboardString(long time)
494 {
495 char *str;
496 long length;
497
498 str = GetClipboardData("TEXT", &length, time);
499 if (!str) {
500 str = new char[1];
501 *str = 0;
502 }
503
504 return str;
505 }
506
507 char *wxClipboard::GetClipboardData(char *format, long *length, long time)
508 {
509 if (clipOwner) {
510 if (clipOwner->formats.Member(format))
511 return clipOwner->GetData(format, length);
512 else
513 return NULL;
514 } else if (cbString) {
515 if (!strcmp(format, "TEXT"))
516 return copystring(cbString);
517 else
518 return NULL;
519 } else {
520 if (wxOpenClipboard()) {
521 receivedString = (char *)wxGetClipboardData(FormatStringToID(format),
522 length);
523 wxCloseClipboard();
524 } else
525 receivedString = NULL;
526
527 return receivedString;
528 }
529 }
530 #endif
531
532 #endif // wxUSE_CLIPBOARD