]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/clipbrd.cpp
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
index 8adca083d289f63850d253539cb5e025925dbbec..1c3cc69c94d5fdad1791b9138261dbb4ebe4f3e0 100644 (file)
@@ -1,8 +1,7 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        gtk/clipbrd.cpp
+// Name:        src/gtk1/clipbrd.cpp
 // Purpose:
 // Author:      Robert Roebling
 // Purpose:
 // Author:      Robert Roebling
-// Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // Copyright:   (c) 1998 Robert Roebling
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#include "wx/clipbrd.h"
-
 #if wxUSE_CLIPBOARD
 
 #if wxUSE_CLIPBOARD
 
-#include "wx/dataobj.h"
-#include "wx/utils.h"
-#include "wx/log.h"
+#include "wx/clipbrd.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/log.h"
+    #include "wx/utils.h"
+    #include "wx/dataobj.h"
+#endif
 
 #include <glib.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 
 
 #include <glib.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 
-//-----------------------------------------------------------------------------
-// thread system
-//-----------------------------------------------------------------------------
-
-#if wxUSE_THREADS
-#endif
-
 //-----------------------------------------------------------------------------
 // data
 //-----------------------------------------------------------------------------
 
 GdkAtom  g_clipboardAtom   = 0;
 GdkAtom  g_targetsAtom     = 0;
 //-----------------------------------------------------------------------------
 // data
 //-----------------------------------------------------------------------------
 
 GdkAtom  g_clipboardAtom   = 0;
 GdkAtom  g_targetsAtom     = 0;
+GdkAtom  g_timestampAtom   = 0;
 
 // the trace mask we use with wxLogTrace() - call
 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
 // (there will be a *lot* of them!)
 
 // the trace mask we use with wxLogTrace() - call
 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
 // (there will be a *lot* of them!)
-static const wxChar *TRACE_CLIPBOARD = _T("clipboard");
+#define TRACE_CLIPBOARD "clipboard"
 
 //-----------------------------------------------------------------------------
 // reminder
 
 //-----------------------------------------------------------------------------
 // reminder
@@ -83,22 +78,23 @@ targets_selection_received( GtkWidget *WXUNUSED(widget),
         GdkAtom type = selection_data->type;
         if ( type != GDK_SELECTION_TYPE_ATOM )
         {
         GdkAtom type = selection_data->type;
         if ( type != GDK_SELECTION_TYPE_ATOM )
         {
-            if ( strcmp(gdk_atom_name(type), "TARGETS") )
+            gchar* atom_name = gdk_atom_name(type);
+            if ( strcmp(atom_name, "TARGETS") )
             {
                 wxLogTrace( TRACE_CLIPBOARD,
             {
                 wxLogTrace( TRACE_CLIPBOARD,
-                            _T("got unsupported clipboard target") );
+                            wxT("got unsupported clipboard target") );
 
 
-                clipboard->m_waiting = FALSE;
+                clipboard->m_waiting = false;
+                g_free(atom_name);
                 return;
             }
                 return;
             }
+            g_free(atom_name);
         }
 
         }
 
-#ifdef __WXDEBUG__
         wxDataFormat clip( selection_data->selection );
         wxLogTrace( TRACE_CLIPBOARD,
                     wxT("selection received for targets, clipboard %s"),
                     clip.GetId().c_str() );
         wxDataFormat clip( selection_data->selection );
         wxLogTrace( TRACE_CLIPBOARD,
                     wxT("selection received for targets, clipboard %s"),
                     clip.GetId().c_str() );
-#endif // __WXDEBUG__
 
         // the atoms we received, holding a list of targets (= formats)
         GdkAtom *atoms = (GdkAtom *)selection_data->data;
 
         // the atoms we received, holding a list of targets (= formats)
         GdkAtom *atoms = (GdkAtom *)selection_data->data;
@@ -117,14 +113,14 @@ targets_selection_received( GtkWidget *WXUNUSED(widget),
 
             if (format == clipboard->m_targetRequested)
             {
 
             if (format == clipboard->m_targetRequested)
             {
-                clipboard->m_waiting = FALSE;
-                clipboard->m_formatSupported = TRUE;
+                clipboard->m_waiting = false;
+                clipboard->m_formatSupported = true;
                 return;
             }
         }
     }
 
                 return;
             }
         }
     }
 
-    clipboard->m_waiting = FALSE;
+    clipboard->m_waiting = false;
 }
 }
 
 }
 }
 
@@ -141,7 +137,7 @@ selection_received( GtkWidget *WXUNUSED(widget),
 {
     if (!wxTheClipboard)
     {
 {
     if (!wxTheClipboard)
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 
         return;
     }
 
@@ -149,13 +145,13 @@ selection_received( GtkWidget *WXUNUSED(widget),
 
     if (!data_object)
     {
 
     if (!data_object)
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 
     if (selection_data->length <= 0)
     {
         return;
     }
 
     if (selection_data->length <= 0)
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 
         return;
     }
 
@@ -164,7 +160,7 @@ selection_received( GtkWidget *WXUNUSED(widget),
     // make sure we got the data in the correct format
     if (!data_object->IsSupportedFormat( format ) )
     {
     // make sure we got the data in the correct format
     if (!data_object->IsSupportedFormat( format ) )
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 
         return;
     }
 
@@ -174,15 +170,15 @@ selection_received( GtkWidget *WXUNUSED(widget),
     // if so, copy data to target object
     if (selection_data->type != GDK_SELECTION_TYPE_STRING)
     {
     // if so, copy data to target object
     if (selection_data->type != GDK_SELECTION_TYPE_STRING)
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 #endif
 
     data_object->SetData( format, (size_t) selection_data->length, (const char*) selection_data->data );
 
         return;
     }
 #endif
 
     data_object->SetData( format, (size_t) selection_data->length, (const char*) selection_data->data );
 
-    wxTheClipboard->m_formatSupported = TRUE;
-    clipboard->m_waiting = FALSE;
+    wxTheClipboard->m_formatSupported = true;
+    clipboard->m_waiting = false;
 }
 }
 
 }
 }
 
@@ -198,16 +194,16 @@ selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
 
     if (event->selection == GDK_SELECTION_PRIMARY)
     {
 
     if (event->selection == GDK_SELECTION_PRIMARY)
     {
-        wxTheClipboard->m_ownsPrimarySelection = FALSE;
+        wxTheClipboard->m_ownsPrimarySelection = false;
     }
     else
     if (event->selection == g_clipboardAtom)
     {
     }
     else
     if (event->selection == g_clipboardAtom)
     {
-        wxTheClipboard->m_ownsClipboard = FALSE;
+        wxTheClipboard->m_ownsClipboard = false;
     }
     else
     {
     }
     else
     {
-        wxTheClipboard->m_waiting = FALSE;
+        wxTheClipboard->m_waiting = false;
         return FALSE;
     }
 
         return FALSE;
     }
 
@@ -219,12 +215,11 @@ selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
         {
             wxLogTrace(TRACE_CLIPBOARD, wxT("wxClipboard will get cleared" ));
 
         {
             wxLogTrace(TRACE_CLIPBOARD, wxT("wxClipboard will get cleared" ));
 
-            delete wxTheClipboard->m_data;
-            wxTheClipboard->m_data = (wxDataObject*) NULL;
+            wxDELETE(wxTheClipboard->m_data);
         }
     }
 
         }
     }
 
-    wxTheClipboard->m_waiting = FALSE;
+    wxTheClipboard->m_waiting = false;
     return TRUE;
 }
 }
     return TRUE;
 }
 }
@@ -239,7 +234,7 @@ selection_handler( GtkWidget *WXUNUSED(widget),
                    GtkSelectionData *selection_data,
                    guint WXUNUSED(info),
                    guint WXUNUSED(time),
                    GtkSelectionData *selection_data,
                    guint WXUNUSED(info),
                    guint WXUNUSED(time),
-                   gpointer WXUNUSED(data) )
+                   gpointer signal_data )
 {
     if (!wxTheClipboard) return;
 
 {
     if (!wxTheClipboard) return;
 
@@ -247,17 +242,34 @@ selection_handler( GtkWidget *WXUNUSED(widget),
 
     wxDataObject *data = wxTheClipboard->m_data;
 
 
     wxDataObject *data = wxTheClipboard->m_data;
 
+    // ICCCM says that TIMESTAMP is a required atom.
+    // In particular, it satisfies Klipper, which polls
+    // TIMESTAMP to see if the clipboards content has changed.
+    // It shall return the time which was used to set the data.
+    if (selection_data->target == g_timestampAtom)
+    {
+        guint timestamp = GPOINTER_TO_UINT (signal_data);
+        gtk_selection_data_set(selection_data,
+                               GDK_SELECTION_TYPE_INTEGER,
+                               32,
+                               (guchar*)&(timestamp),
+                               sizeof(timestamp));
+        wxLogTrace(TRACE_CLIPBOARD,
+                   wxT("Clipboard TIMESTAMP requested, returning timestamp=%u"),
+                   timestamp);
+        return;
+    }
+
     wxDataFormat format( selection_data->target );
 
     wxDataFormat format( selection_data->target );
 
-#ifdef __WXDEBUG__
     wxLogTrace(TRACE_CLIPBOARD,
     wxLogTrace(TRACE_CLIPBOARD,
-               _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s"),
+               wxT("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"),
                format.GetId().c_str(),
                wxString::FromAscii(gdk_atom_name(selection_data->target)).c_str(),
                wxString::FromAscii(gdk_atom_name(selection_data->type)).c_str(),
                format.GetId().c_str(),
                wxString::FromAscii(gdk_atom_name(selection_data->target)).c_str(),
                wxString::FromAscii(gdk_atom_name(selection_data->type)).c_str(),
-               wxString::FromAscii(gdk_atom_name(selection_data->selection)).c_str()
+               wxString::FromAscii(gdk_atom_name(selection_data->selection)).c_str(),
+               GPOINTER_TO_UINT( signal_data )
                );
                );
-#endif
 
     if (!data->IsSupportedFormat( format )) return;
 
 
     if (!data->IsSupportedFormat( format )) return;
 
@@ -275,7 +287,7 @@ selection_handler( GtkWidget *WXUNUSED(widget),
             GDK_SELECTION_TYPE_STRING,
             8 * sizeof(gchar),
             (unsigned char*) d,
             GDK_SELECTION_TYPE_STRING,
             8 * sizeof(gchar),
             (unsigned char*) d,
-            size-1 );
+            size );
 
     free(d);
 }
 
     free(d);
 }
@@ -289,14 +301,14 @@ IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
 
 wxClipboard::wxClipboard()
 {
 
 wxClipboard::wxClipboard()
 {
-    m_open = FALSE;
-    m_waiting = FALSE;
+    m_open = false;
+    m_waiting = false;
 
 
-    m_ownsClipboard = FALSE;
-    m_ownsPrimarySelection = FALSE;
+    m_ownsClipboard = false;
+    m_ownsPrimarySelection = false;
 
 
-    m_data = (wxDataObject*) NULL;
-    m_receivedData = (wxDataObject*) NULL;
+    m_data = NULL;
+    m_receivedData = NULL;
 
     /* we use m_targetsWidget to query what formats are available */
 
 
     /* we use m_targetsWidget to query what formats are available */
 
@@ -325,11 +337,10 @@ wxClipboard::wxClipboard()
 
     if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
     if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
 
     if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
     if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
+    if (!g_timestampAtom) g_timestampAtom = gdk_atom_intern ("TIMESTAMP", FALSE);
 
 
-    m_formatSupported = FALSE;
+    m_formatSupported = false;
     m_targetRequested = 0;
     m_targetRequested = 0;
-
-    m_usePrimary = FALSE;
 }
 
 wxClipboard::~wxClipboard()
 }
 
 wxClipboard::~wxClipboard()
@@ -352,9 +363,9 @@ void wxClipboard::Clear()
         //  it, clear_selection is called which will set m_data to zero
         if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
         {
         //  it, clear_selection is called which will set m_data to zero
         if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
         {
-            m_waiting = TRUE;
+            m_waiting = true;
 
 
-            gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom,
+            gtk_selection_owner_set( NULL, g_clipboardAtom,
                                      (guint32) GDK_CURRENT_TIME );
 
             while (m_waiting) gtk_main_iteration();
                                      (guint32) GDK_CURRENT_TIME );
 
             while (m_waiting) gtk_main_iteration();
@@ -362,19 +373,15 @@ void wxClipboard::Clear()
 
         if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
         {
 
         if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
         {
-            m_waiting = TRUE;
+            m_waiting = true;
 
 
-            gtk_selection_owner_set( (GtkWidget*) NULL, GDK_SELECTION_PRIMARY,
+            gtk_selection_owner_set( NULL, GDK_SELECTION_PRIMARY,
                                      (guint32) GDK_CURRENT_TIME );
 
             while (m_waiting) gtk_main_iteration();
         }
 
                                      (guint32) GDK_CURRENT_TIME );
 
             while (m_waiting) gtk_main_iteration();
         }
 
-        if (m_data)
-        {
-            delete m_data;
-            m_data = (wxDataObject*) NULL;
-        }
+        wxDELETE(m_data);
 
 #if wxUSE_THREADS
         /* re-enable GUI threads */
 
 #if wxUSE_THREADS
         /* re-enable GUI threads */
@@ -382,23 +389,23 @@ void wxClipboard::Clear()
     }
 
     m_targetRequested = 0;
     }
 
     m_targetRequested = 0;
-    m_formatSupported = FALSE;
+    m_formatSupported = false;
 }
 
 bool wxClipboard::Open()
 {
 }
 
 bool wxClipboard::Open()
 {
-    wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
+    wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
 
 
-    m_open = TRUE;
+    m_open = true;
 
 
-    return TRUE;
+    return true;
 }
 
 bool wxClipboard::SetData( wxDataObject *data )
 {
 }
 
 bool wxClipboard::SetData( wxDataObject *data )
 {
-    wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
+    wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
 
 
-    wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
+    wxCHECK_MSG( data, false, wxT("data is invalid") );
 
     Clear();
 
 
     Clear();
 
@@ -407,9 +414,9 @@ bool wxClipboard::SetData( wxDataObject *data )
 
 bool wxClipboard::AddData( wxDataObject *data )
 {
 
 bool wxClipboard::AddData( wxDataObject *data )
 {
-    wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
+    wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
 
 
-    wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
+    wxCHECK_MSG( data, false, wxT("data is invalid") );
 
     // we can only store one wxDataObject
     Clear();
 
     // we can only store one wxDataObject
     Clear();
@@ -424,6 +431,11 @@ bool wxClipboard::AddData( wxDataObject *data )
     GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
                                      : g_clipboardAtom;
 
     GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
                                      : g_clipboardAtom;
 
+    // by default provide TIMESTAMP as a target
+    gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
+                              clipboard,
+                              g_timestampAtom,
+                              0 );
 
     for (size_t i = 0; i < m_data->GetFormatCount(); i++)
     {
 
     for (size_t i = 0; i < m_data->GetFormatCount(); i++)
     {
@@ -445,7 +457,7 @@ bool wxClipboard::AddData( wxDataObject *data )
     gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
                         "selection_get",
                         GTK_SIGNAL_FUNC(selection_handler),
     gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
                         "selection_get",
                         GTK_SIGNAL_FUNC(selection_handler),
-                        (gpointer) NULL );
+                        GUINT_TO_POINTER( gdk_event_get_time(gtk_get_current_event()) ) );
 
 #if wxUSE_THREADS
     /* disable GUI threads */
 
 #if wxUSE_THREADS
     /* disable GUI threads */
@@ -472,7 +484,7 @@ void wxClipboard::Close()
 {
     wxCHECK_RET( m_open, wxT("clipboard not open") );
 
 {
     wxCHECK_RET( m_open, wxT("clipboard not open") );
 
-    m_open = FALSE;
+    m_open = false;
 }
 
 bool wxClipboard::IsOpened() const
 }
 
 bool wxClipboard::IsOpened() const
@@ -483,7 +495,7 @@ bool wxClipboard::IsOpened() const
 bool wxClipboard::IsSupported( const wxDataFormat& format )
 {
     /* reentrance problems */
 bool wxClipboard::IsSupported( const wxDataFormat& format )
 {
     /* reentrance problems */
-    if (m_waiting) return FALSE;
+    if (m_waiting) return false;
 
     /* store requested format to be asked for by callbacks */
     m_targetRequested = format;
 
     /* store requested format to be asked for by callbacks */
     m_targetRequested = format;
@@ -492,19 +504,19 @@ bool wxClipboard::IsSupported( const wxDataFormat& format )
                 wxT("wxClipboard:IsSupported: requested format: %s"),
                 format.GetId().c_str() );
 
                 wxT("wxClipboard:IsSupported: requested format: %s"),
                 format.GetId().c_str() );
 
-    wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
+    wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
 
 
-    m_formatSupported = FALSE;
+    m_formatSupported = false;
 
     /* perform query. this will set m_formatSupported to
 
     /* perform query. this will set m_formatSupported to
-       TRUE if m_targetRequested is supported.
+       true if m_targetRequested is supported.
        also, we have to wait for the "answer" from the
        clipboard owner which is an asynchronous process.
        also, we have to wait for the "answer" from the
        clipboard owner which is an asynchronous process.
-       therefore we set m_waiting = TRUE here and wait
+       therefore we set m_waiting = true here and wait
        until the callback "targets_selection_received"
        until the callback "targets_selection_received"
-       sets it to FALSE */
+       sets it to false */
 
 
-    m_waiting = TRUE;
+    m_waiting = true;
 
     gtk_selection_convert( m_targetsWidget,
                            m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
 
     gtk_selection_convert( m_targetsWidget,
                            m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
@@ -519,7 +531,7 @@ bool wxClipboard::IsSupported( const wxDataFormat& format )
 
 bool wxClipboard::GetData( wxDataObject& data )
 {
 
 bool wxClipboard::GetData( wxDataObject& data )
 {
-    wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
+    wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
 
     /* get formats from wxDataObjects */
     wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
 
     /* get formats from wxDataObjects */
     wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
@@ -538,19 +550,19 @@ bool wxClipboard::GetData( wxDataObject& data )
         /* store requested format to be asked for by callbacks */
         m_targetRequested = format;
 
         /* store requested format to be asked for by callbacks */
         m_targetRequested = format;
 
-        wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
+        wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
 
 
-        m_formatSupported = FALSE;
+        m_formatSupported = false;
 
        /* perform query. this will set m_formatSupported to
 
        /* perform query. this will set m_formatSupported to
-          TRUE if m_targetRequested is supported.
+          true if m_targetRequested is supported.
           also, we have to wait for the "answer" from the
           clipboard owner which is an asynchronous process.
           also, we have to wait for the "answer" from the
           clipboard owner which is an asynchronous process.
-          therefore we set m_waiting = TRUE here and wait
+          therefore we set m_waiting = true here and wait
           until the callback "targets_selection_received"
           until the callback "targets_selection_received"
-          sets it to FALSE */
+          sets it to false */
 
 
-        m_waiting = TRUE;
+        m_waiting = true;
 
         gtk_selection_convert( m_targetsWidget,
                            m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
 
         gtk_selection_convert( m_targetsWidget,
                            m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
@@ -568,21 +580,21 @@ bool wxClipboard::GetData( wxDataObject& data )
         /* store requested format to be asked for by callbacks */
         m_targetRequested = format;
 
         /* store requested format to be asked for by callbacks */
         m_targetRequested = format;
 
-        wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
+        wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
 
         /* start query */
 
         /* start query */
-        m_formatSupported = FALSE;
+        m_formatSupported = false;
 
         /* ask for clipboard contents.  this will set
 
         /* ask for clipboard contents.  this will set
-           m_formatSupported to TRUE if m_targetRequested
+           m_formatSupported to true if m_targetRequested
            is supported.
            also, we have to wait for the "answer" from the
            clipboard owner which is an asynchronous process.
            is supported.
            also, we have to wait for the "answer" from the
            clipboard owner which is an asynchronous process.
-           therefore we set m_waiting = TRUE here and wait
+           therefore we set m_waiting = true here and wait
            until the callback "targets_selection_received"
            until the callback "targets_selection_received"
-           sets it to FALSE */
+           sets it to false */
 
 
-        m_waiting = TRUE;
+        m_waiting = true;
 
         wxLogTrace( TRACE_CLIPBOARD,
                     wxT("wxClipboard::GetData: format found, start convert") );
 
         wxLogTrace( TRACE_CLIPBOARD,
                     wxT("wxClipboard::GetData: format found, start convert") );
@@ -595,12 +607,29 @@ bool wxClipboard::GetData( wxDataObject& data )
 
         while (m_waiting) gtk_main_iteration();
 
 
         while (m_waiting) gtk_main_iteration();
 
-        /* this is a true error as we checked for the presence of such data before */
-        wxCHECK_MSG( m_formatSupported, FALSE, wxT("error retrieving data from clipboard") );
+        /*
+           Normally this is a true error as we checked for the presence of such
+           data before, but there are applications that may return an empty
+           string (e.g. Gnumeric-1.6.1 on Linux if an empty cell is copied)
+           which would produce a false error message here, so we check for the
+           size of the string first. In ansi, GetDataSize returns an extra
+           value (for the closing null?), with unicode, the exact number of
+           tokens is given (that is more than 1 for special characters)
+           (tested with Gnumeric-1.6.1 and OpenOffice.org-2.0.2)
+         */
+#if wxUSE_UNICODE
+        if ( format != wxDF_UNICODETEXT || data.GetDataSize(format) > 0 )
+#else // !UNICODE
+        if ( format != wxDF_TEXT || data.GetDataSize(format) > 1 )
+#endif // UNICODE / !UNICODE
+        {
+            wxCHECK_MSG( m_formatSupported, false,
+                         wxT("error retrieving data from clipboard") );
+        }
 
         /* return success */
         delete[] array;
 
         /* return success */
         delete[] array;
-        return TRUE;
+        return true;
     }
 
     wxLogTrace( TRACE_CLIPBOARD,
     }
 
     wxLogTrace( TRACE_CLIPBOARD,
@@ -608,9 +637,8 @@ bool wxClipboard::GetData( wxDataObject& data )
 
     /* return failure */
     delete[] array;
 
     /* return failure */
     delete[] array;
-    return FALSE;
+    return false;
 }
 
 #endif
   // wxUSE_CLIPBOARD
 }
 
 #endif
   // wxUSE_CLIPBOARD
-