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