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