]> git.saurik.com Git - wxWidgets.git/blame - src/motif/clipbrd.cpp
Avoid crash during global destruction.
[wxWidgets.git] / src / motif / clipbrd.cpp
CommitLineData
4bb6408c
JS
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
dfe1eee3
VZ
17#include "wx/defs.h"
18
19#if wxUSE_CLIPBOARD
20
4bb6408c
JS
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"
2d120f83
JS
27#include "wx/dataobj.h"
28
fd304d98
MB
29#include "wx/listimpl.cpp"
30WX_DEFINE_LIST(wxDataObjectList);
31
338dd992
JJ
32#ifdef __VMS__
33#pragma message disable nosimpint
34#endif
2d120f83
JS
35#include <Xm/Xm.h>
36#include <Xm/CutPaste.h>
338dd992
JJ
37#ifdef __VMS__
38#pragma message enable nosimpint
39#endif
4bb6408c
JS
40
41#include <string.h>
42
2d120f83
JS
43// IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
44// IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
4bb6408c 45
2d120f83
JS
46static bool gs_clipboardIsOpen = FALSE;
47
4bb6408c
JS
48bool wxOpenClipboard()
49{
2d120f83
JS
50 if (!gs_clipboardIsOpen)
51 {
52 gs_clipboardIsOpen = TRUE;
53 return TRUE;
54 }
55 else
56 return FALSE;
4bb6408c
JS
57}
58
59bool wxCloseClipboard()
60{
2d120f83
JS
61 if (gs_clipboardIsOpen)
62 {
63 gs_clipboardIsOpen = FALSE;
64 return TRUE;
65 }
66 else
67 return FALSE;
4bb6408c
JS
68}
69
70bool wxEmptyClipboard()
71{
2d120f83
JS
72 // No equivalent in Motif
73 return TRUE;
4bb6408c
JS
74}
75
76bool wxClipboardOpen()
77{
2d120f83 78 return gs_clipboardIsOpen;
4bb6408c
JS
79}
80
2d120f83 81bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
4bb6408c 82{
2d120f83
JS
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(),
9b64e798 95 window, "TEXT", (XtPointer) 0, 0, & numBytes, & privateId) ;
2d120f83
JS
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;
4bb6408c
JS
103}
104
af111fc3 105bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj, int WXUNUSED(width), int WXUNUSED(height))
4bb6408c 106{
2d120f83
JS
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,
9b64e798 138 "TEXT",
2d120f83
JS
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;
4bb6408c
JS
153}
154
2d120f83 155wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
4bb6408c 156{
2d120f83
JS
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,
9b64e798 181 "TEXT",
2d120f83
JS
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
4bb6408c
JS
211 return NULL;
212}
213
2d120f83 214wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
4bb6408c 215{
2d120f83 216 // Only wxDF_TEXT supported
da175b2c 217 if (dataFormat == wxDF_TEXT)
2d120f83
JS
218 return wxDF_TEXT;
219 else
da175b2c 220 return wxDF_INVALID;
4bb6408c
JS
221}
222
af111fc3 223wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
4bb6408c 224{
2d120f83 225 // Not supported
da175b2c 226 return (wxDataFormat) wxDF_INVALID;
4bb6408c
JS
227}
228
af111fc3 229bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int WXUNUSED(maxCount))
4bb6408c 230{
2d120f83
JS
231 // Only wxDF_TEXT supported
232 if (dataFormat == wxDF_TEXT)
233 {
9b64e798 234 strcpy(formatName, "TEXT");
2d120f83
JS
235 return TRUE;
236 }
237 else
238 return FALSE;
4bb6408c
JS
239}
240
2d120f83
JS
241//-----------------------------------------------------------------------------
242// wxClipboard
243//-----------------------------------------------------------------------------
4bb6408c 244
2d120f83 245IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
4bb6408c 246
4bb6408c
JS
247wxClipboard::wxClipboard()
248{
2d120f83 249 m_open = FALSE;
4bb6408c
JS
250}
251
252wxClipboard::~wxClipboard()
253{
2d120f83 254 Clear();
4bb6408c
JS
255}
256
2d120f83 257void wxClipboard::Clear()
4bb6408c 258{
fd304d98 259 wxDataObjectList::Node* node = m_data.GetFirst();
2d120f83
JS
260 while (node)
261 {
fd304d98 262 wxDataObject* data = node->GetData();
2d120f83 263 delete data;
fd304d98 264 node = node->GetNext();
2d120f83
JS
265 }
266 m_data.Clear();
4bb6408c
JS
267}
268
2d120f83 269bool wxClipboard::Open()
4bb6408c 270{
2d120f83
JS
271 wxCHECK_MSG( !m_open, FALSE, "clipboard already open" );
272
273 m_open = TRUE;
4bb6408c 274
2d120f83
JS
275 return wxOpenClipboard();
276}
4bb6408c 277
2d120f83
JS
278bool wxClipboard::SetData( wxDataObject *data )
279{
280 wxCHECK_MSG( data, FALSE, "data is invalid" );
281 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
282
12db77ca
VZ
283 Clear();
284
285 return AddData( data );
286}
287
288bool 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 )
2d120f83
JS
295 {
296 case wxDF_TEXT:
297 case wxDF_OEMTEXT:
298 {
299 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
300 wxString str(textDataObject->GetText());
12db77ca 301 return wxSetClipboardData(format, (wxObject*) (const char*) str);
2d120f83 302 }
12db77ca 303#if 0
2d120f83
JS
304 case wxDF_BITMAP:
305 case wxDF_DIB:
306 {
307 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
308 wxBitmap bitmap(bitmapDataObject->GetBitmap());
12db77ca 309 return wxSetClipboardData(data->GetType(), & bitmap);
2d120f83
JS
310 break;
311 }
12db77ca 312#endif // 0
2d120f83 313 }
4bb6408c 314
2d120f83
JS
315 return FALSE;
316}
4bb6408c 317
2d120f83
JS
318void wxClipboard::Close()
319{
320 wxCHECK_RET( m_open, "clipboard not open" );
321
322 m_open = FALSE;
323 wxCloseClipboard();
4bb6408c
JS
324}
325
12db77ca 326bool wxClipboard::IsSupported( const wxDataFormat& format)
4bb6408c 327{
2d120f83 328 return wxIsClipboardFormatAvailable(format);
4bb6408c
JS
329}
330
12db77ca 331bool wxClipboard::GetData( wxDataObject& data )
4bb6408c 332{
2d120f83
JS
333 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
334
12db77ca
VZ
335 wxDataFormat::NativeFormat format = data.GetPreferredFormat().GetType();
336 switch ( format )
2d120f83
JS
337 {
338 case wxDF_TEXT:
339 case wxDF_OEMTEXT:
340 {
12db77ca
VZ
341 wxTextDataObject& textDataObject = (wxTextDataObject &) data;
342 char* s = (char*) wxGetClipboardData(format);
2d120f83
JS
343 if (s)
344 {
12db77ca 345 textDataObject.SetText(s);
2d120f83
JS
346 delete[] s;
347 return TRUE;
348 }
349 else
350 return FALSE;
351 break;
352 }
da175b2c 353/*
2d120f83
JS
354 case wxDF_BITMAP:
355 case wxDF_DIB:
356 {
357 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
12db77ca 358 wxBitmap* bitmap = (wxBitmap*) wxGetClipboardData(data->GetType());
2d120f83
JS
359 if (bitmap)
360 {
361 bitmapDataObject->SetBitmap(* bitmap);
362 delete bitmap;
363 return TRUE;
364 }
365 else
366 return FALSE;
367 break;
368 }
da175b2c 369*/
2d120f83
JS
370 default:
371 {
0df4f2ff
JJ
372#ifndef __VMS
373 // VMS complains that this statement is/causes unreachability
374 return FALSE;
375#endif
2d120f83
JS
376 }
377 }
0df4f2ff
JJ
378
379 return FALSE;
2d120f83 380}
4bb6408c 381
2d120f83
JS
382#if 0
383
384/*
385* Old clipboard implementation by Matthew Flatt
386*/
387
388wxClipboard *wxTheClipboard = NULL;
389
390void wxInitClipboard()
391{
392 if (!wxTheClipboard)
393 wxTheClipboard = new wxClipboard;
394}
4bb6408c 395
2d120f83
JS
396wxClipboard::wxClipboard()
397{
398 clipOwner = NULL;
4bb6408c 399 cbString = NULL;
4bb6408c
JS
400}
401
2d120f83
JS
402wxClipboard::~wxClipboard()
403{
404 if (clipOwner)
405 clipOwner->BeingReplaced();
406 if (cbString)
407 delete[] cbString;
408}
409
410static int FormatStringToID(char *str)
4bb6408c 411{
9b64e798 412 if (!strcmp(str, "TEXT"))
2d120f83
JS
413 return wxDF_TEXT;
414
415 return wxRegisterClipboardFormat(str);
416}
4bb6408c 417
2d120f83
JS
418void 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}
4bb6408c 458
2d120f83
JS
459wxClipboardClient *wxClipboard::GetClipboardClient()
460{
461 return clipOwner;
4bb6408c
JS
462}
463
2d120f83 464void wxClipboard::SetClipboardString(char *str, long time)
4bb6408c 465{
2d120f83
JS
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
4bb6408c 477 if (wxOpenClipboard()) {
2d120f83
JS
478 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
479 got_selection = FALSE;
480 else
481 got_selection = wxCloseClipboard();
4bb6408c 482 } else
2d120f83
JS
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
493char *wxClipboard::GetClipboardString(long time)
494{
495 char *str;
496 long length;
497
9b64e798 498 str = GetClipboardData("TEXT", &length, time);
2d120f83
JS
499 if (!str) {
500 str = new char[1];
501 *str = 0;
502 }
503
504 return str;
505}
4bb6408c 506
2d120f83
JS
507char *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) {
9b64e798 515 if (!strcmp(format, "TEXT"))
2d120f83
JS
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 }
4bb6408c 529}
2d120f83 530#endif
4bb6408c 531
dfe1eee3 532#endif // wxUSE_CLIPBOARD