Committing in .
[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 #ifdef __VMS__
30 #pragma message disable nosimpint
31 #endif
32 #include <Xm/Xm.h>
33 #include <Xm/CutPaste.h>
34 #ifdef __VMS__
35 #pragma message enable nosimpint
36 #endif
37
38 #include <string.h>
39
40 // IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
41 // IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
42
43 static bool gs_clipboardIsOpen = FALSE;
44
45 bool wxOpenClipboard()
46 {
47 if (!gs_clipboardIsOpen)
48 {
49 gs_clipboardIsOpen = TRUE;
50 return TRUE;
51 }
52 else
53 return FALSE;
54 }
55
56 bool wxCloseClipboard()
57 {
58 if (gs_clipboardIsOpen)
59 {
60 gs_clipboardIsOpen = FALSE;
61 return TRUE;
62 }
63 else
64 return FALSE;
65 }
66
67 bool wxEmptyClipboard()
68 {
69 // No equivalent in Motif
70 return TRUE;
71 }
72
73 bool wxClipboardOpen()
74 {
75 return gs_clipboardIsOpen;
76 }
77
78 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
79 {
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(),
92 window, "TEXT", (XtPointer) 0, 0, & numBytes, & privateId) ;
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;
100 }
101
102 bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj, int WXUNUSED(width), int WXUNUSED(height))
103 {
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,
135 "TEXT",
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;
150 }
151
152 wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
153 {
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,
178 "TEXT",
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
208 return NULL;
209 }
210
211 wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
212 {
213 // Only wxDF_TEXT supported
214 if (dataFormat == wxDF_TEXT)
215 return wxDF_TEXT;
216 else
217 return wxDF_INVALID;
218 }
219
220 wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
221 {
222 // Not supported
223 return (wxDataFormat) wxDF_INVALID;
224 }
225
226 bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int WXUNUSED(maxCount))
227 {
228 // Only wxDF_TEXT supported
229 if (dataFormat == wxDF_TEXT)
230 {
231 strcpy(formatName, "TEXT");
232 return TRUE;
233 }
234 else
235 return FALSE;
236 }
237
238 //-----------------------------------------------------------------------------
239 // wxClipboard
240 //-----------------------------------------------------------------------------
241
242 IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
243
244 wxClipboard::wxClipboard()
245 {
246 m_open = FALSE;
247 }
248
249 wxClipboard::~wxClipboard()
250 {
251 Clear();
252 }
253
254 void wxClipboard::Clear()
255 {
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();
264 }
265
266 bool wxClipboard::Open()
267 {
268 wxCHECK_MSG( !m_open, FALSE, "clipboard already open" );
269
270 m_open = TRUE;
271
272 return wxOpenClipboard();
273 }
274
275 bool wxClipboard::SetData( wxDataObject *data )
276 {
277 wxCHECK_MSG( data, FALSE, "data is invalid" );
278 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
279
280 Clear();
281
282 return AddData( data );
283 }
284
285 bool 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 )
292 {
293 case wxDF_TEXT:
294 case wxDF_OEMTEXT:
295 {
296 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
297 wxString str(textDataObject->GetText());
298 return wxSetClipboardData(format, (wxObject*) (const char*) str);
299 }
300 #if 0
301 case wxDF_BITMAP:
302 case wxDF_DIB:
303 {
304 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
305 wxBitmap bitmap(bitmapDataObject->GetBitmap());
306 return wxSetClipboardData(data->GetType(), & bitmap);
307 break;
308 }
309 #endif // 0
310 }
311
312 return FALSE;
313 }
314
315 void wxClipboard::Close()
316 {
317 wxCHECK_RET( m_open, "clipboard not open" );
318
319 m_open = FALSE;
320 wxCloseClipboard();
321 }
322
323 bool wxClipboard::IsSupported( const wxDataFormat& format)
324 {
325 return wxIsClipboardFormatAvailable(format);
326 }
327
328 bool wxClipboard::GetData( wxDataObject& data )
329 {
330 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
331
332 wxDataFormat::NativeFormat format = data.GetPreferredFormat().GetType();
333 switch ( format )
334 {
335 case wxDF_TEXT:
336 case wxDF_OEMTEXT:
337 {
338 wxTextDataObject& textDataObject = (wxTextDataObject &) data;
339 char* s = (char*) wxGetClipboardData(format);
340 if (s)
341 {
342 textDataObject.SetText(s);
343 delete[] s;
344 return TRUE;
345 }
346 else
347 return FALSE;
348 break;
349 }
350 /*
351 case wxDF_BITMAP:
352 case wxDF_DIB:
353 {
354 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
355 wxBitmap* bitmap = (wxBitmap*) wxGetClipboardData(data->GetType());
356 if (bitmap)
357 {
358 bitmapDataObject->SetBitmap(* bitmap);
359 delete bitmap;
360 return TRUE;
361 }
362 else
363 return FALSE;
364 break;
365 }
366 */
367 default:
368 {
369 #ifndef __VMS
370 // VMS complains that this statement is/causes unreachability
371 return FALSE;
372 #endif
373 }
374 }
375
376 return FALSE;
377 }
378
379 #if 0
380
381 /*
382 * Old clipboard implementation by Matthew Flatt
383 */
384
385 wxClipboard *wxTheClipboard = NULL;
386
387 void wxInitClipboard()
388 {
389 if (!wxTheClipboard)
390 wxTheClipboard = new wxClipboard;
391 }
392
393 wxClipboard::wxClipboard()
394 {
395 clipOwner = NULL;
396 cbString = NULL;
397 }
398
399 wxClipboard::~wxClipboard()
400 {
401 if (clipOwner)
402 clipOwner->BeingReplaced();
403 if (cbString)
404 delete[] cbString;
405 }
406
407 static int FormatStringToID(char *str)
408 {
409 if (!strcmp(str, "TEXT"))
410 return wxDF_TEXT;
411
412 return wxRegisterClipboardFormat(str);
413 }
414
415 void 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 }
455
456 wxClipboardClient *wxClipboard::GetClipboardClient()
457 {
458 return clipOwner;
459 }
460
461 void wxClipboard::SetClipboardString(char *str, long time)
462 {
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
474 if (wxOpenClipboard()) {
475 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
476 got_selection = FALSE;
477 else
478 got_selection = wxCloseClipboard();
479 } else
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
490 char *wxClipboard::GetClipboardString(long time)
491 {
492 char *str;
493 long length;
494
495 str = GetClipboardData("TEXT", &length, time);
496 if (!str) {
497 str = new char[1];
498 *str = 0;
499 }
500
501 return str;
502 }
503
504 char *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) {
512 if (!strcmp(format, "TEXT"))
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 }
526 }
527 #endif
528
529 #endif // wxUSE_CLIPBOARD