]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/clipbrd.cpp
significantly simplify this file by using token pasting in #incoude and #pragma comme...
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
index 1d1e0bc844eb682b8b550eb2f50831ea411d1c5b..2d1ade92eccd9e7d8693f876022a2754e92ee708 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        gtk/clipbrd.cpp
+// Name:        src/gtk1/clipbrd.cpp
 // Purpose:
 // Author:      Robert Roebling
 // Id:          $Id$
 // Purpose:
 // Author:      Robert Roebling
 // Id:          $Id$
 // 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;
-
-#if defined(__WXGTK20__) && wxUSE_UNICODE
-extern GdkAtom g_altTextAtom;
-#endif
+GdkAtom  g_timestampAtom   = 0;
 
 // the trace mask we use with wxLogTrace() - call
 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
 
 // the trace mask we use with wxLogTrace() - call
 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
@@ -87,14 +79,17 @@ 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,
                             _T("got unsupported clipboard target") );
 
             {
                 wxLogTrace( TRACE_CLIPBOARD,
                             _T("got unsupported clipboard target") );
 
-                clipboard->m_waiting = FALSE;
+                clipboard->m_waiting = false;
+                g_free(atom_name);
                 return;
             }
                 return;
             }
+            g_free(atom_name);
         }
 
 #ifdef __WXDEBUG__
         }
 
 #ifdef __WXDEBUG__
@@ -115,20 +110,20 @@ targets_selection_received( GtkWidget *WXUNUSED(widget),
                         wxT("selection received for targets, format %s"),
                         format.GetId().c_str() );
 
                         wxT("selection received for targets, format %s"),
                         format.GetId().c_str() );
 
-//            printf( "format %s requested %s\n", 
+//            printf( "format %s requested %s\n",
 //                    gdk_atom_name( atoms[i] ),
 //                    gdk_atom_name( clipboard->m_targetRequested ) );
 
             if (format == clipboard->m_targetRequested)
             {
 //                    gdk_atom_name( atoms[i] ),
 //                    gdk_atom_name( 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;
 }
 }
 
 }
 }
 
@@ -145,7 +140,7 @@ selection_received( GtkWidget *WXUNUSED(widget),
 {
     if (!wxTheClipboard)
     {
 {
     if (!wxTheClipboard)
     {
-        clipboard->m_waiting = FALSE;
+        clipboard->m_waiting = false;
         return;
     }
 
         return;
     }
 
@@ -153,13 +148,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;
     }
 
@@ -168,7 +163,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;
     }
 
@@ -178,15 +173,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;
 }
 }
 
 }
 }
 
@@ -202,16 +197,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;
     }
 
@@ -228,7 +223,7 @@ selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
         }
     }
 
         }
     }
 
-    wxTheClipboard->m_waiting = FALSE;
+    wxTheClipboard->m_waiting = false;
     return TRUE;
 }
 }
     return TRUE;
 }
 }
@@ -243,7 +238,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;
 
@@ -251,18 +246,37 @@ 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,
+                   _T("Clipboard TIMESTAMP requested, returning timestamp=%u"),
+                   timestamp);
+        return;
+    }
+
     wxDataFormat format( selection_data->target );
 
 #ifdef __WXDEBUG__
     wxLogTrace(TRACE_CLIPBOARD,
     wxDataFormat format( selection_data->target );
 
 #ifdef __WXDEBUG__
     wxLogTrace(TRACE_CLIPBOARD,
-               _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s"),
+               _T("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
                );
 #endif
-    
+
     if (!data->IsSupportedFormat( format )) return;
 
     int size = data->GetDataSize( format );
     if (!data->IsSupportedFormat( format )) return;
 
     int size = data->GetDataSize( format );
@@ -274,27 +288,12 @@ selection_handler( GtkWidget *WXUNUSED(widget),
     // Text data will be in UTF8 in Unicode mode.
     data->GetDataHere( selection_data->target, d );
 
     // Text data will be in UTF8 in Unicode mode.
     data->GetDataHere( selection_data->target, d );
 
-#ifdef __WXGTK20__
-    // NB: GTK+ requires special treatment of UTF8_STRING data, the text
-    //     would show as UTF-8 data interpreted as latin1 (?) in other
-    //     GTK+ apps if we used gtk_selection_data_set()
-    if (format == wxDataFormat(wxDF_UNICODETEXT))
-    {
-        gtk_selection_data_set_text(
-            selection_data,
-            (const gchar*)d,
-            size-1 );
-    }
-    else
-#endif
-    {
-        gtk_selection_data_set(
+    gtk_selection_data_set(
             selection_data,
             GDK_SELECTION_TYPE_STRING,
             selection_data,
             GDK_SELECTION_TYPE_STRING,
-            8*sizeof(gchar),
+            8 * sizeof(gchar),
             (unsigned char*) d,
             (unsigned char*) d,
-            size-1 );
-    }
+            size );
 
     free(d);
 }
 
     free(d);
 }
@@ -308,11 +307,11 @@ 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 = (wxDataObject*) NULL;
     m_receivedData = (wxDataObject*) NULL;
@@ -344,11 +343,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()
@@ -371,7 +369,7 @@ 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,
                                      (guint32) GDK_CURRENT_TIME );
 
             gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom,
                                      (guint32) GDK_CURRENT_TIME );
@@ -381,7 +379,7 @@ 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,
                                      (guint32) GDK_CURRENT_TIME );
 
             gtk_selection_owner_set( (GtkWidget*) NULL, GDK_SELECTION_PRIMARY,
                                      (guint32) GDK_CURRENT_TIME );
@@ -401,23 +399,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();
 
@@ -426,9 +424,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();
@@ -443,6 +441,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++)
     {
@@ -450,9 +453,9 @@ bool wxClipboard::AddData( wxDataObject *data )
                     wxT("wxClipboard now supports atom %s"),
                     array[i].GetId().c_str() );
 
                     wxT("wxClipboard now supports atom %s"),
                     array[i].GetId().c_str() );
 
-//        printf( "added %s\n", 
+//        printf( "added %s\n",
 //                    gdk_atom_name( array[i].GetFormatId() ) );
 //                    gdk_atom_name( array[i].GetFormatId() ) );
-                    
+
         gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
                                   clipboard,
                                   array[i],
         gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
                                   clipboard,
                                   array[i],
@@ -464,7 +467,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 */
@@ -491,7 +494,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
@@ -502,7 +505,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;
@@ -511,19 +514,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
@@ -533,21 +536,12 @@ bool wxClipboard::IsSupported( const wxDataFormat& format )
 
     while (m_waiting) gtk_main_iteration();
 
 
     while (m_waiting) gtk_main_iteration();
 
-#if defined(__WXGTK20__) && wxUSE_UNICODE
-    if (!m_formatSupported && format == wxDataFormat(wxDF_UNICODETEXT))
-    {
-        // Another try with plain STRING format
-        extern GdkAtom g_altTextAtom;
-        return IsSupported(g_altTextAtom);
-    }
-#endif
-
     return m_formatSupported;
 }
 
 bool wxClipboard::GetData( wxDataObject& data )
 {
     return m_formatSupported;
 }
 
 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() ];
@@ -566,19 +560,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
@@ -596,21 +590,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") );
@@ -623,12 +617,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,
@@ -636,9 +647,8 @@ bool wxClipboard::GetData( wxDataObject& data )
 
     /* return failure */
     delete[] array;
 
     /* return failure */
     delete[] array;
-    return FALSE;
+    return false;
 }
 
 #endif
   // wxUSE_CLIPBOARD
 }
 
 #endif
   // wxUSE_CLIPBOARD
-