]> git.saurik.com Git - wxWidgets.git/blame - src/motif/clipbrd.cpp
Added (untested) support for sub-locales.
[wxWidgets.git] / src / motif / clipbrd.cpp
CommitLineData
4bb6408c
JS
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"
2d120f83
JS
23#include "wx/dataobj.h"
24
25#include <Xm/Xm.h>
26#include <Xm/CutPaste.h>
4bb6408c
JS
27
28#include <string.h>
29
30#if !USE_SHARED_LIBRARY
2d120f83
JS
31// IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
32// IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
4bb6408c
JS
33#endif
34
2d120f83
JS
35static bool gs_clipboardIsOpen = FALSE;
36
4bb6408c
JS
37bool wxOpenClipboard()
38{
2d120f83
JS
39 if (!gs_clipboardIsOpen)
40 {
41 gs_clipboardIsOpen = TRUE;
42 return TRUE;
43 }
44 else
45 return FALSE;
4bb6408c
JS
46}
47
48bool wxCloseClipboard()
49{
2d120f83
JS
50 if (gs_clipboardIsOpen)
51 {
52 gs_clipboardIsOpen = FALSE;
53 return TRUE;
54 }
55 else
56 return FALSE;
4bb6408c
JS
57}
58
59bool wxEmptyClipboard()
60{
2d120f83
JS
61 // No equivalent in Motif
62 return TRUE;
4bb6408c
JS
63}
64
65bool wxClipboardOpen()
66{
2d120f83 67 return gs_clipboardIsOpen;
4bb6408c
JS
68}
69
2d120f83 70bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
4bb6408c 71{
2d120f83
JS
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;
4bb6408c
JS
92}
93
2d120f83 94bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj, int width, int height)
4bb6408c 95{
2d120f83
JS
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;
4bb6408c
JS
142}
143
2d120f83 144wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
4bb6408c 145{
2d120f83
JS
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
4bb6408c
JS
200 return NULL;
201}
202
2d120f83 203wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
4bb6408c 204{
2d120f83
JS
205 // Only wxDF_TEXT supported
206 if (dataFormat == (wxDataFormat) 0)
207 return wxDF_TEXT;
208 else
209 return (wxDataFormat) 0;
4bb6408c
JS
210}
211
2d120f83 212wxDataFormat wxRegisterClipboardFormat(char *formatName)
4bb6408c 213{
2d120f83
JS
214 // Not supported
215 return (wxDataFormat) 0;
4bb6408c
JS
216}
217
2d120f83 218bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int maxCount)
4bb6408c 219{
2d120f83
JS
220 // Only wxDF_TEXT supported
221 if (dataFormat == wxDF_TEXT)
222 {
223 strcpy(formatName, "TEXT");
224 return TRUE;
225 }
226 else
227 return FALSE;
4bb6408c
JS
228}
229
2d120f83
JS
230//-----------------------------------------------------------------------------
231// wxClipboard
232//-----------------------------------------------------------------------------
4bb6408c 233
2d120f83 234IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
4bb6408c 235
2d120f83 236wxClipboard* wxTheClipboard = (wxClipboard*) NULL;
4bb6408c
JS
237
238wxClipboard::wxClipboard()
239{
2d120f83 240 m_open = FALSE;
4bb6408c
JS
241}
242
243wxClipboard::~wxClipboard()
244{
2d120f83 245 Clear();
4bb6408c
JS
246}
247
2d120f83 248void wxClipboard::Clear()
4bb6408c 249{
2d120f83
JS
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();
4bb6408c
JS
258}
259
2d120f83 260bool wxClipboard::Open()
4bb6408c 261{
2d120f83
JS
262 wxCHECK_MSG( !m_open, FALSE, "clipboard already open" );
263
264 m_open = TRUE;
4bb6408c 265
2d120f83
JS
266 return wxOpenClipboard();
267}
4bb6408c 268
2d120f83
JS
269bool 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 }
4bb6408c 297
2d120f83
JS
298 return FALSE;
299}
4bb6408c 300
2d120f83
JS
301void wxClipboard::Close()
302{
303 wxCHECK_RET( m_open, "clipboard not open" );
304
305 m_open = FALSE;
306 wxCloseClipboard();
4bb6408c
JS
307}
308
2d120f83 309bool wxClipboard::IsSupportedFormat( wxDataFormat format, const wxString& WXUNUSED(id) )
4bb6408c 310{
2d120f83 311 return wxIsClipboardFormatAvailable(format);
4bb6408c
JS
312}
313
2d120f83 314bool wxClipboard::GetData( wxDataObject *data )
4bb6408c 315{
2d120f83
JS
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}
4bb6408c 357
2d120f83
JS
358//-----------------------------------------------------------------------------
359// wxClipboardModule
360//-----------------------------------------------------------------------------
4bb6408c 361
2d120f83 362IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
4bb6408c 363
2d120f83
JS
364bool wxClipboardModule::OnInit()
365{
366 wxTheClipboard = new wxClipboard();
367
368 return TRUE;
369}
4bb6408c 370
2d120f83
JS
371void 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
384wxClipboard *wxTheClipboard = NULL;
385
386void wxInitClipboard()
387{
388 if (!wxTheClipboard)
389 wxTheClipboard = new wxClipboard;
390}
4bb6408c 391
2d120f83
JS
392wxClipboard::wxClipboard()
393{
394 clipOwner = NULL;
4bb6408c 395 cbString = NULL;
4bb6408c
JS
396}
397
2d120f83
JS
398wxClipboard::~wxClipboard()
399{
400 if (clipOwner)
401 clipOwner->BeingReplaced();
402 if (cbString)
403 delete[] cbString;
404}
405
406static int FormatStringToID(char *str)
4bb6408c 407{
2d120f83
JS
408 if (!strcmp(str, "TEXT"))
409 return wxDF_TEXT;
410
411 return wxRegisterClipboardFormat(str);
412}
4bb6408c 413
2d120f83
JS
414void 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}
4bb6408c 454
2d120f83
JS
455wxClipboardClient *wxClipboard::GetClipboardClient()
456{
457 return clipOwner;
4bb6408c
JS
458}
459
2d120f83 460void wxClipboard::SetClipboardString(char *str, long time)
4bb6408c 461{
2d120f83
JS
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
4bb6408c 473 if (wxOpenClipboard()) {
2d120f83
JS
474 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
475 got_selection = FALSE;
476 else
477 got_selection = wxCloseClipboard();
4bb6408c 478 } else
2d120f83
JS
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
489char *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}
4bb6408c 502
2d120f83
JS
503char *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 }
4bb6408c 525}
2d120f83 526#endif
4bb6408c 527