Reformatted Motif headers; added __WXX11__ symbol support to common headers;
[wxWidgets.git] / src / x11 / 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 return FALSE;
370 }
371 }
372 return FALSE;
373 }
374
375 #if 0
376
377 /*
378 * Old clipboard implementation by Matthew Flatt
379 */
380
381 wxClipboard *wxTheClipboard = NULL;
382
383 void wxInitClipboard()
384 {
385 if (!wxTheClipboard)
386 wxTheClipboard = new wxClipboard;
387 }
388
389 wxClipboard::wxClipboard()
390 {
391 clipOwner = NULL;
392 cbString = NULL;
393 }
394
395 wxClipboard::~wxClipboard()
396 {
397 if (clipOwner)
398 clipOwner->BeingReplaced();
399 if (cbString)
400 delete[] cbString;
401 }
402
403 static int FormatStringToID(char *str)
404 {
405 if (!strcmp(str, "TEXT"))
406 return wxDF_TEXT;
407
408 return wxRegisterClipboardFormat(str);
409 }
410
411 void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
412 {
413 bool got_selection;
414
415 if (clipOwner)
416 clipOwner->BeingReplaced();
417 clipOwner = client;
418 if (cbString) {
419 delete[] cbString;
420 cbString = NULL;
421 }
422
423 if (wxOpenClipboard()) {
424 char **formats, *data;
425 int i;
426 int ftype;
427 long size;
428
429 formats = clipOwner->formats.ListToArray(FALSE);
430 for (i = clipOwner->formats.Number(); i--; ) {
431 ftype = FormatStringToID(formats[i]);
432 data = clipOwner->GetData(formats[i], &size);
433 if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
434 got_selection = FALSE;
435 break;
436 }
437 }
438
439 if (i < 0)
440 got_selection = wxCloseClipboard();
441 } else
442 got_selection = FALSE;
443
444 got_selection = FALSE; // Assume another process takes over
445
446 if (!got_selection) {
447 clipOwner->BeingReplaced();
448 clipOwner = NULL;
449 }
450 }
451
452 wxClipboardClient *wxClipboard::GetClipboardClient()
453 {
454 return clipOwner;
455 }
456
457 void wxClipboard::SetClipboardString(char *str, long time)
458 {
459 bool got_selection;
460
461 if (clipOwner) {
462 clipOwner->BeingReplaced();
463 clipOwner = NULL;
464 }
465 if (cbString)
466 delete[] cbString;
467
468 cbString = str;
469
470 if (wxOpenClipboard()) {
471 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
472 got_selection = FALSE;
473 else
474 got_selection = wxCloseClipboard();
475 } else
476 got_selection = FALSE;
477
478 got_selection = FALSE; // Assume another process takes over
479
480 if (!got_selection) {
481 delete[] cbString;
482 cbString = NULL;
483 }
484 }
485
486 char *wxClipboard::GetClipboardString(long time)
487 {
488 char *str;
489 long length;
490
491 str = GetClipboardData("TEXT", &length, time);
492 if (!str) {
493 str = new char[1];
494 *str = 0;
495 }
496
497 return str;
498 }
499
500 char *wxClipboard::GetClipboardData(char *format, long *length, long time)
501 {
502 if (clipOwner) {
503 if (clipOwner->formats.Member(format))
504 return clipOwner->GetData(format, length);
505 else
506 return NULL;
507 } else if (cbString) {
508 if (!strcmp(format, "TEXT"))
509 return copystring(cbString);
510 else
511 return NULL;
512 } else {
513 if (wxOpenClipboard()) {
514 receivedString = (char *)wxGetClipboardData(FormatStringToID(format),
515 length);
516 wxCloseClipboard();
517 } else
518 receivedString = NULL;
519
520 return receivedString;
521 }
522 }
523 #endif
524
525 #endif // wxUSE_CLIPBOARD