]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/clipbrd.cpp
fixed crash under GTK+ 2.0
[wxWidgets.git] / src / motif / clipbrd.cpp
index e22f9f83497c7d6eae46afbbe6b81a3d4883291d..41afb324d308b393539aa8c0419f494b445858d6 100644 (file)
 #pragma implementation "clipbrd.h"
 #endif
 
+#include "wx/defs.h"
+
+#if wxUSE_CLIPBOARD
+
 #include "wx/app.h"
 #include "wx/frame.h"
 #include "wx/bitmap.h"
 #include "wx/utils.h"
 #include "wx/metafile.h"
 #include "wx/clipbrd.h"
+#include "wx/dataobj.h"
+
+#ifdef __VMS__
+#pragma message disable nosimpint
+#endif
+#include <Xm/Xm.h>
+#include <Xm/CutPaste.h>
+#ifdef __VMS__
+#pragma message enable nosimpint
+#endif
 
 #include <string.h>
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
-IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
-#endif
+// IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
+// IMPLEMENT_ABSTRACT_CLASS(wxClipboardClient, wxObject)
+
+static bool gs_clipboardIsOpen = FALSE;
 
 bool wxOpenClipboard()
 {
-    // TODO
-    return FALSE;
+    if (!gs_clipboardIsOpen)
+    {
+        gs_clipboardIsOpen = TRUE;
+        return TRUE;
+    }
+    else
+        return FALSE;
 }
 
 bool wxCloseClipboard()
 {
-    // TODO
-    return FALSE;
+    if (gs_clipboardIsOpen)
+    {
+        gs_clipboardIsOpen = FALSE;
+        return TRUE;
+    }
+    else
+        return FALSE;
 }
 
 bool wxEmptyClipboard()
 {
-    // TODO
-    return FALSE;
+    // No equivalent in Motif
+    return TRUE;
 }
 
 bool wxClipboardOpen()
 {
-    // TODO
-    return FALSE;
+    return gs_clipboardIsOpen;
 }
 
-bool wxIsClipboardFormatAvailable(int dataFormat)
+bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
 {
-    // TODO
-    return FALSE;
+    // Only text is supported.
+    if (dataFormat != wxDF_TEXT)
+        return FALSE;
+
+    unsigned long numBytes = 0;
+    long privateId = 0;
+    
+    Window window = (Window) 0;
+    if (wxTheApp->GetTopWindow())
+        window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
+
+    int success = XmClipboardRetrieve((Display*) wxGetDisplay(),
+      window, "TEXT", (XtPointer) 0, 0, & numBytes, & privateId) ;
+
+    // Assume only text is supported. If we have anything at all,
+    // or the clipboard is locked so we're not sure, we say we support it.
+    if (success == ClipboardNoData)
+        return FALSE;
+    else
+        return TRUE;
 }
 
-bool wxSetClipboardData(int dataFormat, wxObject *obj, int width, int height)
+bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj, int WXUNUSED(width), int WXUNUSED(height))
 {
-    // TODO
-    return FALSE;
+    if (dataFormat != wxDF_TEXT)
+        return FALSE;
+
+    char* data = (char*) obj;
+
+    XmString text = XmStringCreateSimple ("CLIPBOARD");
+    Window window = (Window) 0;
+    if (wxTheApp->GetTopWindow())
+        window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
+
+    long itemId = 0;
+    int result = 0;
+
+    while ((result =
+      XmClipboardStartCopy((Display*) wxGetDisplay(),
+       window, 
+       text,
+       XtLastTimestampProcessed((Display*) wxGetDisplay()),
+       (Widget) 0,
+       (XmCutPasteProc) 0,
+       & itemId)) != ClipboardSuccess)
+
+       ;
+
+    XmStringFree (text);
+
+    long dataId = 0;
+    while ((result =
+      XmClipboardCopy((Display*) wxGetDisplay(),
+       window, 
+       itemId,
+       "TEXT",
+       (XtPointer) data,
+       strlen(data) + 1,
+       0,
+       & dataId)) != ClipboardSuccess)
+
+       ;
+
+    while (( result =
+       XmClipboardEndCopy((Display*) wxGetDisplay(),
+         window, itemId) ) != ClipboardSuccess)
+
+       ;
+    
+    return TRUE;
 }
 
-wxObject *wxGetClipboardData(int dataFormat, long *len)
+wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
 {
-    // TODO
+    if (dataFormat != wxDF_TEXT)
+        return (wxObject*) NULL;
+
+    bool done = FALSE;
+    long id = 0;
+    unsigned long numBytes = 0;
+    int result = 0;
+    Window window = (Window) 0;
+    if (wxTheApp->GetTopWindow())
+        window = XtWindow( (Widget) wxTheApp->GetTopWindow()->GetTopWidget() );
+
+    int currentDataSize = 256;
+    char* data = new char[currentDataSize];
+
+    while (!done)
+    {
+        if (result == ClipboardTruncate)
+        {
+            delete[] data;
+            currentDataSize = 2*currentDataSize;
+            data = new char[currentDataSize];
+       }
+        result = XmClipboardRetrieve((Display*) wxGetDisplay(),
+          window,
+          "TEXT",
+          (XtPointer) data,
+          currentDataSize,
+          &numBytes,
+          &id);
+
+        switch (result)
+         {
+         case ClipboardSuccess:
+           {
+              if (len)
+                *len = strlen(data) + 1;
+              return (wxObject*) data;
+              break;
+           }
+         case ClipboardTruncate:
+         case ClipboardLocked:
+           {
+              break;
+           }
+          default:
+         case ClipboardNoData:
+           {
+              return (wxObject*) NULL;
+              break;
+           }
+         }
+          
+    }
+
     return NULL;
 }
 
-int  wxEnumClipboardFormats(int dataFormat)
+wxDataFormat  wxEnumClipboardFormats(wxDataFormat dataFormat)
 {
-    // TODO
-    return 0;
+    // Only wxDF_TEXT supported
+    if (dataFormat == wxDF_TEXT)
+       return wxDF_TEXT;
+    else
+       return wxDF_INVALID;
 }
 
-int  wxRegisterClipboardFormat(char *formatName)
+wxDataFormat  wxRegisterClipboardFormat(char *WXUNUSED(formatName))
 {
-    // TODO
-    return 0;
+    // Not supported
+    return (wxDataFormat) wxDF_INVALID;
 }
 
-bool wxGetClipboardFormatName(int dataFormat, char *formatName, int maxCount)
+bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int WXUNUSED(maxCount))
 {
-    // TODO
-    return FALSE;
+    // Only wxDF_TEXT supported
+    if (dataFormat == wxDF_TEXT)
+    {
+       strcpy(formatName, "TEXT");
+       return TRUE;
+    }
+    else
+       return FALSE;
 }
 
-/*
- * Generalized clipboard implementation by Matthew Flatt
- */
+//-----------------------------------------------------------------------------
+// wxClipboard
+//-----------------------------------------------------------------------------
 
-wxClipboard *wxTheClipboard = NULL;
+IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
 
-void wxInitClipboard()
+wxClipboard::wxClipboard()
 {
-  if (!wxTheClipboard)
-    wxTheClipboard = new wxClipboard;
+    m_open = FALSE;
 }
 
-wxClipboard::wxClipboard()
+wxClipboard::~wxClipboard()
 {
-  clipOwner = NULL;
-  cbString = NULL;
+    Clear();  
 }
 
-wxClipboard::~wxClipboard()
+void wxClipboard::Clear()
 {
-  if (clipOwner)
-    clipOwner->BeingReplaced();
-  if (cbString)
-    delete[] cbString;
+    wxNode* node = m_data.First();
+    while (node)
+    {
+        wxDataObject* data = (wxDataObject*) node->Data();
+        delete data;
+        node = node->Next();
+    }
+    m_data.Clear();
 }
 
-static int FormatStringToID(char *str)
+bool wxClipboard::Open()
 {
-  if (!strcmp(str, "TEXT"))
-    return wxDF_TEXT;
+    wxCHECK_MSG( !m_open, FALSE, "clipboard already open" );
+  
+    m_open = TRUE;
 
-  return wxRegisterClipboardFormat(str);
+    return wxOpenClipboard();
 }
 
-void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
+bool wxClipboard::SetData( wxDataObject *data )
 {
-  bool got_selection;
+    wxCHECK_MSG( data, FALSE, "data is invalid" );
+    wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
 
-  if (clipOwner)
-    clipOwner->BeingReplaced();
-  clipOwner = client;
-  if (cbString) {
-    delete[] cbString;
-    cbString = NULL;
-  }
-
-  if (wxOpenClipboard()) {
-    char **formats, *data;
-         int i;
-    int ftype;
-    long size;
-
-    formats = clipOwner->formats.ListToArray(FALSE);
-    for (i = clipOwner->formats.Number(); i--; ) {
-      ftype = FormatStringToID(formats[i]);
-      data = clipOwner->GetData(formats[i], &size);
-      if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
-        got_selection = FALSE;
-        break;
-      }
-    }
+    Clear();
+
+    return AddData( data );
+}
 
-    if (i < 0)
-      got_selection = wxCloseClipboard();
-  } else
-    got_selection = FALSE;
+bool wxClipboard::AddData( wxDataObject *data )
+{
+    wxCHECK_MSG( data, FALSE, "data is invalid" );
+    wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
+
+    wxDataFormat::NativeFormat format = data->GetPreferredFormat().GetType();
+    switch ( format )
+    {
+        case wxDF_TEXT:
+        case wxDF_OEMTEXT:
+        {
+            wxTextDataObject* textDataObject = (wxTextDataObject*) data;
+            wxString str(textDataObject->GetText());
+            return wxSetClipboardData(format, (wxObject*) (const char*) str);
+        }
+#if 0
+        case wxDF_BITMAP:
+        case wxDF_DIB:
+        {
+            wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
+            wxBitmap bitmap(bitmapDataObject->GetBitmap());
+            return wxSetClipboardData(data->GetType(), & bitmap);
+            break;
+        }
+#endif // 0
+    }
   
-  got_selection = FALSE; // Assume another process takes over
+    return FALSE;
+}
 
-  if (!got_selection) {
-    clipOwner->BeingReplaced();
-         clipOwner = NULL;
-  }
+void wxClipboard::Close()
+{
+    wxCHECK_RET( m_open, "clipboard not open" );
+    
+    m_open = FALSE;
+    wxCloseClipboard();
 }
 
-wxClipboardClient *wxClipboard::GetClipboardClient()
+bool wxClipboard::IsSupported( const wxDataFormat& format)
 {
-  return clipOwner;
+    return wxIsClipboardFormatAvailable(format);
 }
 
-void wxClipboard::SetClipboardString(char *str, long time)
+bool wxClipboard::GetData( wxDataObject& data )
 {
-  bool got_selection;
+    wxCHECK_MSG( m_open, FALSE, "clipboard not open" );
+    
+    wxDataFormat::NativeFormat format = data.GetPreferredFormat().GetType();
+    switch ( format )
+    {
+        case wxDF_TEXT:
+        case wxDF_OEMTEXT:
+        {
+            wxTextDataObject& textDataObject = (wxTextDataObject &) data;
+            char* s = (char*) wxGetClipboardData(format);
+            if (s)
+            {
+                textDataObject.SetText(s);
+                delete[] s;
+                return TRUE;
+            }
+            else
+                return FALSE;
+            break;
+        }
+/*
+        case wxDF_BITMAP:
+        case wxDF_DIB:
+        {
+            wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
+            wxBitmap* bitmap = (wxBitmap*) wxGetClipboardData(data->GetType());
+            if (bitmap)
+            {
+                bitmapDataObject->SetBitmap(* bitmap);
+                delete bitmap;
+                return TRUE;
+            }
+            else
+                return FALSE;
+            break;
+        }
+*/
+        default:
+        {
+            return FALSE;
+        }
+    }
+    return FALSE;
+}
 
-  if (clipOwner) {
-    clipOwner->BeingReplaced();
-    clipOwner = NULL;
-  }
-  if (cbString)
-    delete[] cbString;
+#if 0
 
-  cbString = str;
+/*
+* Old clipboard implementation by Matthew Flatt
+*/
 
-  if (wxOpenClipboard()) {
-    if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
-      got_selection = FALSE;
-    else
-                got_selection = wxCloseClipboard();
-  } else
-    got_selection = FALSE;
+wxClipboard *wxTheClipboard = NULL;
 
-  got_selection = FALSE; // Assume another process takes over
+void wxInitClipboard()
+{
+    if (!wxTheClipboard)
+        wxTheClipboard = new wxClipboard;
+}
 
-  if (!got_selection) {
-    delete[] cbString;
+wxClipboard::wxClipboard()
+{
+    clipOwner = NULL;
     cbString = NULL;
-  }
 }
 
-char *wxClipboard::GetClipboardString(long time)
+wxClipboard::~wxClipboard()
 {
-  char *str;
-  long length;
+    if (clipOwner)
+        clipOwner->BeingReplaced();
+    if (cbString)
+        delete[] cbString;
+}
 
-  str = GetClipboardData("TEXT", &length, time);
-  if (!str) {
-    str = new char[1];
-    *str = 0;
-  }
+static int FormatStringToID(char *str)
+{
+    if (!strcmp(str, "TEXT"))
+        return wxDF_TEXT;
+    
+    return wxRegisterClipboardFormat(str);
+}
 
-  return str;
+void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
+{
+    bool got_selection;
+    
+    if (clipOwner)
+        clipOwner->BeingReplaced();
+    clipOwner = client;
+    if (cbString) {
+        delete[] cbString;
+        cbString = NULL;
+    }
+    
+    if (wxOpenClipboard()) {
+        char **formats, *data;
+        int i;
+        int ftype;
+        long size;
+        
+        formats = clipOwner->formats.ListToArray(FALSE);
+        for (i = clipOwner->formats.Number(); i--; ) {
+            ftype = FormatStringToID(formats[i]);
+            data = clipOwner->GetData(formats[i], &size);
+            if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
+                got_selection = FALSE;
+                break;
+            }
+        }
+        
+        if (i < 0)
+            got_selection = wxCloseClipboard();
+    } else
+        got_selection = FALSE;
+    
+    got_selection = FALSE; // Assume another process takes over
+    
+    if (!got_selection) {
+        clipOwner->BeingReplaced();
+        clipOwner = NULL;
+    }
 }
 
-char *wxClipboard::GetClipboardData(char *format, long *length, long time)
+wxClipboardClient *wxClipboard::GetClipboardClient()
 {
-  if (clipOwner)  {
-         if (clipOwner->formats.Member(format))
-      return clipOwner->GetData(format, length);
-    else
-      return NULL;
-  } else if (cbString) {
-    if (!strcmp(format, "TEXT"))
-      return copystring(cbString);
-    else
-      return NULL;
-  } else {
+    return clipOwner;
+}
+
+void wxClipboard::SetClipboardString(char *str, long time)
+{
+    bool got_selection;
+    
+    if (clipOwner) {
+        clipOwner->BeingReplaced();
+        clipOwner = NULL;
+    }
+    if (cbString)
+        delete[] cbString;
+    
+    cbString = str;
+    
     if (wxOpenClipboard()) {
-      receivedString = (char *)wxGetClipboardData(FormatStringToID(format), 
-                                                  length);
-      wxCloseClipboard();
+        if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
+            got_selection = FALSE;
+        else
+            got_selection = wxCloseClipboard();
     } else
-      receivedString = NULL;
+        got_selection = FALSE;
+    
+    got_selection = FALSE; // Assume another process takes over
+    
+    if (!got_selection) {
+        delete[] cbString;
+        cbString = NULL;
+    }
+}
 
-    return receivedString;
-  }
+char *wxClipboard::GetClipboardString(long time)
+{
+    char *str;
+    long length;
+    
+    str = GetClipboardData("TEXT", &length, time);
+    if (!str) {
+        str = new char[1];
+        *str = 0;
+    }
+    
+    return str;
 }
 
+char *wxClipboard::GetClipboardData(char *format, long *length, long time)
+{
+    if (clipOwner)  {
+        if (clipOwner->formats.Member(format))
+            return clipOwner->GetData(format, length);
+        else
+            return NULL;
+    } else if (cbString) {
+        if (!strcmp(format, "TEXT"))
+            return copystring(cbString);
+        else
+            return NULL;
+    } else {
+        if (wxOpenClipboard()) {
+            receivedString = (char *)wxGetClipboardData(FormatStringToID(format), 
+                length);
+            wxCloseClipboard();
+        } else
+            receivedString = NULL;
+        
+        return receivedString;
+    }
+}
+#endif
+
+#endif // wxUSE_CLIPBOARD