Removed some TODOs in the Latex docs; changed wxMotif wxClipboard to match
[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 == (wxDataFormat) 0)
207 return wxDF_TEXT;
208 else
209 return (wxDataFormat) 0;
210 }
211
212 wxDataFormat wxRegisterClipboardFormat(char *formatName)
213 {
214 // Not supported
215 return (wxDataFormat) 0;
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 case wxDF_BITMAP:
285 case wxDF_DIB:
286 {
287 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
288 wxBitmap bitmap(bitmapDataObject->GetBitmap());
289 return wxSetClipboardData(data->GetFormat(), & bitmap);
290 break;
291 }
292 default:
293 {
294 return FALSE;
295 }
296 }
297
298 return FALSE;
299 }
300
301 void wxClipboard::Close()
302 {
303 wxCHECK_RET( m_open, "clipboard not open" );
304
305 m_open = FALSE;
306 wxCloseClipboard();
307 }
308
309 bool wxClipboard::IsSupported( wxDataFormat format)
310 {
311 return wxIsClipboardFormatAvailable(format);
312 }
313
314 bool wxClipboard::GetData( wxDataObject *data )
315 {
316 wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
317
318 switch (data->GetFormat())
319 {
320 case wxDF_TEXT:
321 case wxDF_OEMTEXT:
322 {
323 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
324 char* s = (char*) wxGetClipboardData(data->GetFormat());
325 if (s)
326 {
327 textDataObject->SetText(s);
328 delete[] s;
329 return TRUE;
330 }
331 else
332 return FALSE;
333 break;
334 }
335 case wxDF_BITMAP:
336 case wxDF_DIB:
337 {
338 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
339 wxBitmap* bitmap = (wxBitmap*) wxGetClipboardData(data->GetFormat());
340 if (bitmap)
341 {
342 bitmapDataObject->SetBitmap(* bitmap);
343 delete bitmap;
344 return TRUE;
345 }
346 else
347 return FALSE;
348 break;
349 }
350 default:
351 {
352 return FALSE;
353 }
354 }
355 return FALSE;
356 }
357
358 //-----------------------------------------------------------------------------
359 // wxClipboardModule
360 //-----------------------------------------------------------------------------
361
362 IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
363
364 bool wxClipboardModule::OnInit()
365 {
366 wxTheClipboard = new wxClipboard();
367
368 return TRUE;
369 }
370
371 void wxClipboardModule::OnExit()
372 {
373 if (wxTheClipboard) delete wxTheClipboard;
374 wxTheClipboard = (wxClipboard*) NULL;
375 }
376
377
378 #if 0
379
380 /*
381 * Old clipboard implementation by Matthew Flatt
382 */
383
384 wxClipboard *wxTheClipboard = NULL;
385
386 void wxInitClipboard()
387 {
388 if (!wxTheClipboard)
389 wxTheClipboard = new wxClipboard;
390 }
391
392 wxClipboard::wxClipboard()
393 {
394 clipOwner = NULL;
395 cbString = NULL;
396 }
397
398 wxClipboard::~wxClipboard()
399 {
400 if (clipOwner)
401 clipOwner->BeingReplaced();
402 if (cbString)
403 delete[] cbString;
404 }
405
406 static int FormatStringToID(char *str)
407 {
408 if (!strcmp(str, "TEXT"))
409 return wxDF_TEXT;
410
411 return wxRegisterClipboardFormat(str);
412 }
413
414 void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
415 {
416 bool got_selection;
417
418 if (clipOwner)
419 clipOwner->BeingReplaced();
420 clipOwner = client;
421 if (cbString) {
422 delete[] cbString;
423 cbString = NULL;
424 }
425
426 if (wxOpenClipboard()) {
427 char **formats, *data;
428 int i;
429 int ftype;
430 long size;
431
432 formats = clipOwner->formats.ListToArray(FALSE);
433 for (i = clipOwner->formats.Number(); i--; ) {
434 ftype = FormatStringToID(formats[i]);
435 data = clipOwner->GetData(formats[i], &size);
436 if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
437 got_selection = FALSE;
438 break;
439 }
440 }
441
442 if (i < 0)
443 got_selection = wxCloseClipboard();
444 } else
445 got_selection = FALSE;
446
447 got_selection = FALSE; // Assume another process takes over
448
449 if (!got_selection) {
450 clipOwner->BeingReplaced();
451 clipOwner = NULL;
452 }
453 }
454
455 wxClipboardClient *wxClipboard::GetClipboardClient()
456 {
457 return clipOwner;
458 }
459
460 void wxClipboard::SetClipboardString(char *str, long time)
461 {
462 bool got_selection;
463
464 if (clipOwner) {
465 clipOwner->BeingReplaced();
466 clipOwner = NULL;
467 }
468 if (cbString)
469 delete[] cbString;
470
471 cbString = str;
472
473 if (wxOpenClipboard()) {
474 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
475 got_selection = FALSE;
476 else
477 got_selection = wxCloseClipboard();
478 } else
479 got_selection = FALSE;
480
481 got_selection = FALSE; // Assume another process takes over
482
483 if (!got_selection) {
484 delete[] cbString;
485 cbString = NULL;
486 }
487 }
488
489 char *wxClipboard::GetClipboardString(long time)
490 {
491 char *str;
492 long length;
493
494 str = GetClipboardData("TEXT", &length, time);
495 if (!str) {
496 str = new char[1];
497 *str = 0;
498 }
499
500 return str;
501 }
502
503 char *wxClipboard::GetClipboardData(char *format, long *length, long time)
504 {
505 if (clipOwner) {
506 if (clipOwner->formats.Member(format))
507 return clipOwner->GetData(format, length);
508 else
509 return NULL;
510 } else if (cbString) {
511 if (!strcmp(format, "TEXT"))
512 return copystring(cbString);
513 else
514 return NULL;
515 } else {
516 if (wxOpenClipboard()) {
517 receivedString = (char *)wxGetClipboardData(FormatStringToID(format),
518 length);
519 wxCloseClipboard();
520 } else
521 receivedString = NULL;
522
523 return receivedString;
524 }
525 }
526 #endif
527