]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/textctrl.cpp
removed useless assert from wxArray::Alloc
[wxWidgets.git] / src / gtk / textctrl.cpp
index 64c069e006a5a8e0408ec45c77b629d570c91a5a..841605437b58d24d1ae87b7bb8ae2a111c46e3c1 100644 (file)
@@ -14,7 +14,9 @@
 #include "wx/textctrl.h"
 #include "wx/utils.h"
 #include "wx/intl.h"
 #include "wx/textctrl.h"
 #include "wx/utils.h"
 #include "wx/intl.h"
+#include "wx/log.h"
 #include "wx/settings.h"
 #include "wx/settings.h"
+#include "wx/panel.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -74,6 +76,116 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
     win->CalculateScrollbar();
 }
 
     win->CalculateScrollbar();
 }
 
+//-----------------------------------------------------------------------------
+// "focus_in_event"
+//-----------------------------------------------------------------------------
+
+wxWindow *FindFocusedChild(wxWindow *win);
+extern wxWindow  *g_focusWindow;
+extern bool       g_blockEventsOnDrag;
+// extern bool g_isIdle;
+
+static gint gtk_text_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+{
+    // Necessary?
+#if 0
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+#endif
+    if (!win->m_hasVMT) return FALSE;
+    if (g_blockEventsOnDrag) return FALSE;
+
+    g_focusWindow = win;
+
+    wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel);
+    if (panel)
+    {
+        panel->SetLastFocus(win);
+    }
+
+#ifdef HAVE_XIM
+    if (win->m_ic)
+        gdk_im_begin(win->m_ic, win->m_wxwindow->window);
+#endif
+
+#if 0
+#ifdef wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnSetFocus();
+    }
+#endif // wxUSE_CARET
+#endif
+
+    wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
+    event.SetEventObject( win );
+
+    if (win->GetEventHandler()->ProcessEvent( event ))
+    {
+        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "focus_out_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_text_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
+{
+#if 0
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+#endif
+
+    if (!win->m_hasVMT) return FALSE;
+    if (g_blockEventsOnDrag) return FALSE;
+
+#if 0
+    // if the focus goes out of our app alltogether, OnIdle() will send
+    // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
+    // g_sendActivateEvent to -1
+    g_sendActivateEvent = 0;
+#endif
+
+    wxWindow *winFocus = FindFocusedChild(win);
+    if ( winFocus )
+        win = winFocus;
+
+    g_focusWindow = (wxWindow *)NULL;
+
+#ifdef HAVE_XIM
+    if (win->m_ic)
+        gdk_im_end();
+#endif
+
+#if 0
+#ifdef wxUSE_CARET
+    // caret needs to be informed about focus change
+    wxCaret *caret = win->GetCaret();
+    if ( caret )
+    {
+        caret->OnKillFocus();
+    }
+#endif // wxUSE_CARET
+#endif
+
+    wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
+    event.SetEventObject( win );
+
+    if (win->GetEventHandler()->ProcessEvent( event ))
+    {
+        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 //-----------------------------------------------------------------------------
 //  wxTextCtrl
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 //  wxTextCtrl
 //-----------------------------------------------------------------------------
@@ -215,14 +327,24 @@ bool wxTextCtrl::Create( wxWindow *parent,
     if (multi_line)
         gtk_widget_show(m_text);
 
     if (multi_line)
         gtk_widget_show(m_text);
 
-    /* we want to be notified about text changes */
-    gtk_signal_connect( GTK_OBJECT(m_text), "changed",
-      GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
-
     if (multi_line)
     {
         gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed",
           (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this );
     if (multi_line)
     {
         gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed",
           (GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this );
+
+        gtk_signal_connect( GTK_OBJECT(GTK_TEXT(m_text)), "focus_in_event",
+              GTK_SIGNAL_FUNC(gtk_text_focus_in_callback), (gpointer)this );
+
+        gtk_signal_connect( GTK_OBJECT(GTK_TEXT(m_text)), "focus_out_event",
+                           GTK_SIGNAL_FUNC(gtk_text_focus_out_callback), (gpointer)this );
+    }
+    else
+    {
+        gtk_signal_connect( GTK_OBJECT(m_text), "focus_in_event",
+              GTK_SIGNAL_FUNC(gtk_text_focus_in_callback), (gpointer)this );
+
+        gtk_signal_connect( GTK_OBJECT(m_text), "focus_out_event",
+                           GTK_SIGNAL_FUNC(gtk_text_focus_out_callback), (gpointer)this );
     }
 
     if (!value.IsEmpty())
     }
 
     if (!value.IsEmpty())
@@ -267,6 +389,10 @@ bool wxTextCtrl::Create( wxWindow *parent,
             gtk_text_set_editable( GTK_TEXT(m_text), 1 );
     }
 
             gtk_text_set_editable( GTK_TEXT(m_text), 1 );
     }
 
+    /* we want to be notified about text changes */
+    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() );
 
     SetBackgroundColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) );
     SetForegroundColour( parent->GetForegroundColour() );
 
@@ -646,6 +772,14 @@ void wxTextCtrl::SetSelection( long from, long to )
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
+    if ( (m_windowStyle & wxTE_MULTILINE) &&
+         !GTK_TEXT(m_text)->line_start_cache )
+    {
+        // tell the programmer that it didn't work
+        wxLogDebug(_T("Can't call SetSelection() before realizing the control"));
+        return;
+    }
+
     gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
 }
 
     gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
 }
 
@@ -782,20 +916,34 @@ bool wxTextCtrl::CanRedo() const
 
 // If the return values from and to are the same, there is no
 // selection.
 
 // If the return values from and to are the same, there is no
 // selection.
-void wxTextCtrl::GetSelection(long* from, long* to) const
+void wxTextCtrl::GetSelection(long* fromOut, long* toOut) const
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
 {
     wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
 
-    if (!(GTK_EDITABLE(m_text)->has_selection))
+    long from, to;
+    if ( !(GTK_EDITABLE(m_text)->has_selection) )
     {
     {
-        long i = GetInsertionPoint();
-        if (from) *from = i;
-        if (to)   *to = i;
-        return;
+        from =
+        to = GetInsertionPoint();
+    }
+    else // got selection
+    {
+        from = (long) GTK_EDITABLE(m_text)->selection_start_pos;
+        to = (long) GTK_EDITABLE(m_text)->selection_end_pos;
+
+        if ( from > to )
+        {
+            // exchange them to be compatible with wxMSW
+            long tmp = from;
+            from = to;
+            to = tmp;
+        }
     }
 
     }
 
-    if (from) *from = (long) GTK_EDITABLE(m_text)->selection_start_pos;
-    if (to)   *to = (long) GTK_EDITABLE(m_text)->selection_end_pos;
+    if ( fromOut )
+        *fromOut = from;
+    if ( toOut )
+        *toOut = to;
 }
 
 bool wxTextCtrl::IsEditable() const
 }
 
 bool wxTextCtrl::IsEditable() const