merged MapBitmap() from 2.2 branch
[wxWidgets.git] / src / gtk1 / textctrl.cpp
index 841605437b58d24d1ae87b7bb8ae2a111c46e3c1..65f795181320acfd6733c45b150126fe96a46394 100644 (file)
@@ -80,7 +80,6 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
 // "focus_in_event"
 //-----------------------------------------------------------------------------
 
 // "focus_in_event"
 //-----------------------------------------------------------------------------
 
-wxWindow *FindFocusedChild(wxWindow *win);
 extern wxWindow  *g_focusWindow;
 extern bool       g_blockEventsOnDrag;
 // extern bool g_isIdle;
 extern wxWindow  *g_focusWindow;
 extern bool       g_blockEventsOnDrag;
 // extern bool g_isIdle;
@@ -152,7 +151,7 @@ static gint gtk_text_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(e
     g_sendActivateEvent = 0;
 #endif
 
     g_sendActivateEvent = 0;
 #endif
 
-    wxWindow *winFocus = FindFocusedChild(win);
+    wxWindow *winFocus = wxFindFocusedChild(win);
     if ( winFocus )
         win = winFocus;
 
     if ( winFocus )
         win = winFocus;
 
@@ -393,11 +392,21 @@ bool wxTextCtrl::Create( wxWindow *parent,
     gtk_signal_connect( GTK_OBJECT(m_text), "changed",
       GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
 
     gtk_signal_connect( GTK_OBJECT(m_text), "changed",
       GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
 
-    SetBackgroundColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) );
-    SetForegroundColour( parent->GetForegroundColour() );
+    /* we don't set a valid background colour, because the window
+       manager should use a default one */
+    m_backgroundColour = wxColour();
+
+    wxColour colFg = parent->GetForegroundColour();
+    SetForegroundColour( colFg );
 
     m_cursor = wxCursor( wxCURSOR_IBEAM );
 
 
     m_cursor = wxCursor( wxCURSOR_IBEAM );
 
+    // FIXME: is the bg colour correct here?
+    wxTextAttr attrDef( colFg,
+                        wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW),
+                        parent->GetFont() );
+    SetDefaultStyle( attrDef );
+
     Show( TRUE );
 
     return TRUE;
     Show( TRUE );
 
     return TRUE;
@@ -479,33 +488,53 @@ void wxTextCtrl::WriteText( const wxString &text )
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
-    if (text.IsEmpty()) return;
+    if ( text.empty() )
+        return;
 
 
-    if (m_windowStyle & wxTE_MULTILINE)
+#if wxUSE_UNICODE
+    wxWX2MBbuf buf = text.mbc_str();
+    const char *txt = buf;
+    size_t txtlen = strlen(buf);
+#else
+    const char *txt = text;
+    size_t txtlen = text.length();
+#endif
+
+    if ( m_windowStyle & wxTE_MULTILINE )
     {
         /* this moves the cursor pos to behind the inserted text */
         gint len = GTK_EDITABLE(m_text)->current_pos;
 
     {
         /* this moves the cursor pos to behind the inserted text */
         gint len = GTK_EDITABLE(m_text)->current_pos;
 
-#if wxUSE_UNICODE
-        wxWX2MBbuf buf = text.mbc_str();
-        gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
-#else
-        gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
-#endif
+        // if we have any special style, use it
+        if ( !m_defaultStyle.IsDefault() )
+        {
+            GdkFont *font = m_defaultStyle.HasFont()
+                                ? m_defaultStyle.GetFont().GetInternalFont()
+                                : NULL;
+
+            GdkColor *colFg = m_defaultStyle.HasTextColour()
+                                ? m_defaultStyle.GetTextColour().GetColor()
+                                : NULL;
+
+            GdkColor *colBg = m_defaultStyle.HasBackgroundColour()
+                                ? m_defaultStyle.GetBackgroundColour().GetColor()
+                                : NULL;
+
+            gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen );
+        }
+        else // no style
+        {
+            gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len );
+        }
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
     }
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
     }
-    else
+    else // single line
     {
         /* this moves the cursor pos to behind the inserted text */
         gint len = GTK_EDITABLE(m_text)->current_pos;
     {
         /* this moves the cursor pos to behind the inserted text */
         gint len = GTK_EDITABLE(m_text)->current_pos;
-#if wxUSE_UNICODE
-        wxWX2MBbuf buf = text.mbc_str();
-        gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
-#else
-        gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
-#endif
+        gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len );
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos += text.Len();
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos += text.Len();
@@ -519,40 +548,49 @@ void wxTextCtrl::AppendText( const wxString &text )
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
-    if (text.IsEmpty()) return;
+    if ( text.empty() )
+        return;
+
+#if wxUSE_UNICODE
+    wxWX2MBbuf buf = text.mbc_str();
+    const char *txt = buf;
+    size_t txtlen = strlen(buf);
+#else
+    const char *txt = text;
+    size_t txtlen = text.length();
+#endif
 
     if (m_windowStyle & wxTE_MULTILINE)
     {
 
     if (m_windowStyle & wxTE_MULTILINE)
     {
-        bool hasSpecialAttributes = m_font.Ok() ||
-                                    m_foregroundColour.Ok() ||
-                                    m_backgroundColour.Ok();
-        if ( hasSpecialAttributes )
+        if ( !m_defaultStyle.IsDefault() )
         {
         {
-             gtk_text_insert( GTK_TEXT(m_text),
-                              m_font.GetInternalFont(),
-                              m_foregroundColour.GetColor(),
-                              m_backgroundColour.GetColor(),
-                              text.mbc_str(), text.length());
+            GdkFont *font = m_defaultStyle.HasFont()
+                                ? m_defaultStyle.GetFont().GetInternalFont()
+                                : NULL;
+
+            GdkColor *colFg = m_defaultStyle.HasTextColour()
+                                ? m_defaultStyle.GetTextColour().GetColor()
+                                : NULL;
+
+            GdkColor *colBg = m_defaultStyle.HasBackgroundColour()
+                                ? m_defaultStyle.GetBackgroundColour().GetColor()
+                                : NULL;
 
 
+            gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen );
         }
         }
-        else
+        else // no style
         {
             /* we'll insert at the last position */
             gint len = gtk_text_get_length( GTK_TEXT(m_text) );
         {
             /* we'll insert at the last position */
             gint len = gtk_text_get_length( GTK_TEXT(m_text) );
-#if wxUSE_UNICODE
-            wxWX2MBbuf buf = text.mbc_str();
-            gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
-#else
-            gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
-#endif
+            gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len );
         }
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
     }
         }
 
         /* bring editable's cursor uptodate. bug in GTK. */
         GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
     }
-    else
+    else // single line
     {
     {
-        gtk_entry_append_text( GTK_ENTRY(m_text), text.mbc_str() );
+        gtk_entry_append_text( GTK_ENTRY(m_text), txt );
     }
 }
 
     }
 }
 
@@ -754,6 +792,7 @@ bool wxTextCtrl::Enable( bool enable )
     if (m_windowStyle & wxTE_MULTILINE)
     {
         gtk_text_set_editable( GTK_TEXT(m_text), enable );
     if (m_windowStyle & wxTE_MULTILINE)
     {
         gtk_text_set_editable( GTK_TEXT(m_text), enable );
+        OnParentEnable(enable);
     }
     else
     {
     }
     else
     {
@@ -763,6 +802,26 @@ bool wxTextCtrl::Enable( bool enable )
     return TRUE;
 }
 
     return TRUE;
 }
 
+// wxGTK-specific: called recursively by Enable,
+// to give widgets an oppprtunity to correct their colours after they
+// have been changed by Enable
+void wxTextCtrl::OnParentEnable( bool enable )
+{
+    // If we have a custom background colour, we use this colour in both
+    // disabled and enabled mode, or we end up with a different colour under the
+    // text.
+    wxColour oldColour = GetBackgroundColour();
+    if (oldColour.Ok())
+    {
+        // Need to set twice or it'll optimize the useful stuff out
+        if (oldColour == * wxWHITE)
+            SetBackgroundColour(*wxBLACK);
+        else
+            SetBackgroundColour(*wxWHITE);
+        SetBackgroundColour(oldColour);
+    }
+}
+
 void wxTextCtrl::DiscardEdits()
 {
     m_modified = FALSE;
 void wxTextCtrl::DiscardEdits()
 {
     m_modified = FALSE;
@@ -866,27 +925,6 @@ void wxTextCtrl::Paste()
 #endif
 }
 
 #endif
 }
 
-bool wxTextCtrl::CanCopy() const
-{
-    // Can copy if there's a selection
-    long from, to;
-    GetSelection(& from, & to);
-    return (from != to) ;
-}
-
-bool wxTextCtrl::CanCut() const
-{
-    // Can cut if there's a selection
-    long from, to;
-    GetSelection(& from, & to);
-    return (from != to) && (IsEditable());
-}
-
-bool wxTextCtrl::CanPaste() const
-{
-    return IsEditable() ;
-}
-
 // Undo/redo
 void wxTextCtrl::Undo()
 {
 // Undo/redo
 void wxTextCtrl::Undo()
 {
@@ -1049,12 +1087,15 @@ void wxTextCtrl::UpdateFontIfNeeded()
         ChangeFontGlobally();
 }
 
         ChangeFontGlobally();
 }
 
-bool wxTextCtrl::SetForegroundColour( const wxColour &WXUNUSED(colour) )
+bool wxTextCtrl::SetForegroundColour(const wxColour& colour)
 {
 {
-    wxCHECK_MSG( m_text != NULL, FALSE, wxT("invalid text ctrl") );
+    if ( !wxControl::SetForegroundColour(colour) )
+        return FALSE;
 
 
-    // doesn't work
-    return FALSE;
+    // update default fg colour too
+    m_defaultStyle.SetTextColour(colour);
+
+    return TRUE;
 }
 
 bool wxTextCtrl::SetBackgroundColour( const wxColour &colour )
 }
 
 bool wxTextCtrl::SetBackgroundColour( const wxColour &colour )
@@ -1087,9 +1128,72 @@ bool wxTextCtrl::SetBackgroundColour( const wxColour &colour )
         gdk_window_clear( window );
     }
 
         gdk_window_clear( window );
     }
 
+    // change active background color too
+    m_defaultStyle.SetBackgroundColour( colour );
+
     return TRUE;
 }
 
     return TRUE;
 }
 
+bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr &style )
+{
+    /* VERY dirty way to do that - removes the required text and re-adds it
+       with styling (FIXME) */
+    if ( m_windowStyle & wxTE_MULTILINE )
+    {
+        if ( style.IsDefault() )
+        {
+            // nothing to do
+            return TRUE;
+        }
+
+        gint l = gtk_text_get_length( GTK_TEXT(m_text) );
+
+        wxCHECK_MSG( start >= 0 && end <= l, FALSE,
+                     _T("invalid range in wxTextCtrl::SetStyle") );
+
+        gint old_pos = gtk_editable_get_position( GTK_EDITABLE(m_text) );
+        char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), start, end );
+        wxString tmp(text,*wxConvCurrent);
+        g_free( text );
+
+        gtk_editable_delete_text( GTK_EDITABLE(m_text), start, end );
+        gtk_editable_set_position( GTK_EDITABLE(m_text), start );
+
+#if wxUSE_UNICODE
+        wxWX2MBbuf buf = tmp.mbc_str();
+        const char *txt = buf;
+        size_t txtlen = strlen(buf);
+#else
+        const char *txt = tmp;
+        size_t txtlen = tmp.length();
+#endif
+
+        GdkFont *font = style.HasFont()
+                            ? style.GetFont().GetInternalFont()
+                            : NULL;
+
+        GdkColor *colFg = style.HasTextColour()
+                            ? style.GetTextColour().GetColor()
+                            : NULL;
+
+        GdkColor *colBg = style.HasBackgroundColour()
+                            ? style.GetBackgroundColour().GetColor()
+                            : NULL;
+
+        gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen );
+
+        /* does not seem to help under GTK+ 1.2 !!!
+        gtk_editable_set_position( GTK_EDITABLE(m_text), old_pos ); */
+        SetInsertionPoint( old_pos );
+        return TRUE;
+    }
+    else // singe line
+    {
+        // cannot do this for GTK+'s Entry widget
+        return FALSE;
+    }
+}
+
 void wxTextCtrl::ApplyWidgetStyle()
 {
     if (m_windowStyle & wxTE_MULTILINE)
 void wxTextCtrl::ApplyWidgetStyle()
 {
     if (m_windowStyle & wxTE_MULTILINE)