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