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