X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6c5ac6e1f1a5a3400b51f3bf61d061cf3ed3857a..de5fadb41534fca448bd68d3ff942f80efa87f76:/src/gtk1/textctrl.cpp?ds=sidebyside diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index ec25530e46..b7dd3a877d 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -23,9 +23,13 @@ #include #include // for fabs -#include "gdk/gdk.h" -#include "gtk/gtk.h" -#include "gdk/gdkkeysyms.h" +// TODO: reimplement wxTextCtrl using GtkTextView +#ifdef __WXGTK20__ + #define GTK_ENABLE_BROKEN // need this to get GtkText at all +#endif // __WXGTK20__ + +#include "wx/gtk/private.h" +#include //----------------------------------------------------------------------------- // idle system @@ -41,6 +45,28 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +// ---------------------------------------------------------------------------- +// helpers +// ---------------------------------------------------------------------------- + +static void wxGtkTextInsert(GtkWidget *text, + const wxTextAttr& attr, + const char *txt, + size_t len) +{ + GdkFont *font = attr.HasFont() ? attr.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = attr.HasTextColour() ? attr.GetTextColour().GetColor() + : NULL; + + GdkColor *colBg = attr.HasBackgroundColour() + ? attr.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(text), font, colFg, colBg, txt, len ); +} + // ---------------------------------------------------------------------------- // "insert_text" for GtkEntry // ---------------------------------------------------------------------------- @@ -86,7 +112,7 @@ gtk_insert_text_callback(GtkEditable *editable, //----------------------------------------------------------------------------- static void -gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) +gtk_text_changed_callback( GtkWidget *widget, wxTextCtrl *win ) { if ( win->IgnoreTextUpdate() ) return; @@ -190,7 +216,7 @@ bool wxTextCtrl::Create( wxWindow *parent, bool multi_line = (style & wxTE_MULTILINE) != 0; if (multi_line) { -#if (GTK_MINOR_VERSION > 2) +#ifdef __WXGTK13__ /* a multi-line edit control: create a vertical scrollbar by default and horizontal if requested */ bool bHasHScrollbar = (style & wxHSCROLL) != 0; @@ -212,7 +238,7 @@ bool wxTextCtrl::Create( wxWindow *parent, /* always wrap words */ gtk_text_set_word_wrap( GTK_TEXT(m_text), TRUE ); -#if (GTK_MINOR_VERSION > 2) +#ifdef __WXGTK13__ /* put the horizontal scrollbar in the lower left hand corner */ if (bHasHScrollbar) { @@ -245,7 +271,7 @@ bool wxTextCtrl::Create( wxWindow *parent, } m_parent->DoAddChild( this ); - + m_focusWidget = m_text; PostCreation(); @@ -274,7 +300,7 @@ bool wxTextCtrl::Create( wxWindow *parent, { gint tmp = 0; -#if GTK_MINOR_VERSION == 0 +#if !GTK_CHECK_VERSION(1, 2, 0) // if we don't realize it, GTK 1.0.6 dies with a SIGSEGV in // gtk_editable_insert_text() gtk_widget_realize(m_text); @@ -290,8 +316,7 @@ bool wxTextCtrl::Create( wxWindow *parent, if (multi_line) { /* bring editable's cursor uptodate. bug in GTK. */ - - GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); + SET_EDITABLE_POS(m_text, gtk_text_get_point( GTK_TEXT(m_text) )); } } @@ -423,131 +448,80 @@ void wxTextCtrl::WriteText( const wxString &text ) if ( m_windowStyle & wxTE_MULTILINE ) { - /* this moves the cursor pos to behind the inserted text */ - gint len = GTK_EDITABLE(m_text)->current_pos; + // After cursor movements, gtk_text_get_point() is wrong by one. + gtk_text_set_point( GTK_TEXT(m_text), GET_EDITABLE_POS(m_text) ); // 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; + GetInsertionPoint(); - GdkColor *colBg = m_defaultStyle.HasBackgroundColour() - ? m_defaultStyle.GetBackgroundColour().GetColor() - : NULL; - - gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); + wxGtkTextInsert(m_text, m_defaultStyle, txt, txtlen); } else // no style { + gint len = GET_EDITABLE_POS(m_text); 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 back uptodate. + SET_EDITABLE_POS(m_text, gtk_text_get_point( GTK_TEXT(m_text) )); } 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 = GET_EDITABLE_POS(m_text); 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. + len += text.Len(); - /* bring entry's cursor uptodate. bug in GTK. */ - gtk_entry_set_position( GTK_ENTRY(m_text), GTK_EDITABLE(m_text)->current_pos ); + // Bring entry's cursor uptodate. + gtk_entry_set_position( GTK_ENTRY(m_text), len ); } + + m_modified = TRUE; } void wxTextCtrl::AppendText( const wxString &text ) { - wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - - 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 + SetInsertionPointEnd(); + WriteText( text ); +} +wxString wxTextCtrl::GetLineText( long lineNo ) const +{ if (m_windowStyle & wxTE_MULTILINE) { - if ( !m_defaultStyle.IsDefault() ) - { - wxFont font = m_defaultStyle.HasFont() ? m_defaultStyle.GetFont() - : m_font; - GdkFont *fnt = font.Ok() ? font.GetInternalFont() : NULL; - - wxColour col = m_defaultStyle.HasTextColour() - ? m_defaultStyle.GetTextColour() - : m_foregroundColour; - GdkColor *colFg = col.Ok() ? col.GetColor() : NULL; + gint len = gtk_text_get_length( GTK_TEXT(m_text) ); + char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len ); - col = m_defaultStyle.HasBackgroundColour() - ? m_defaultStyle.GetBackgroundColour() - : m_backgroundColour; - GdkColor *colBg = col.Ok() ? col.GetColor() : NULL; + if (text) + { + wxString buf(wxT("")); + long i; + int currentLine = 0; + for (i = 0; currentLine != lineNo && text[i]; i++ ) + if (text[i] == '\n') + currentLine++; + // Now get the text + int j; + for (j = 0; text[i] && text[i] != '\n'; i++, j++ ) + buf += text[i]; - gtk_text_insert( GTK_TEXT(m_text), fnt, colFg, colBg, txt, txtlen ); + g_free( text ); + return buf; } - else // no style + else { - /* we'll insert at the last position */ - gint len = gtk_text_get_length( GTK_TEXT(m_text) ); - gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); + return wxEmptyString; } - - /* bring editable's cursor uptodate. bug in GTK. */ - GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); } - else // single line - { - gtk_entry_append_text( GTK_ENTRY(m_text), txt ); - } -} - -wxString wxTextCtrl::GetLineText( long lineNo ) const -{ - if (m_windowStyle & wxTE_MULTILINE) - { - gint len = gtk_text_get_length( GTK_TEXT(m_text) ); - char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len ); - - if (text) + else { - wxString buf(wxT("")); - long i; - int currentLine = 0; - for (i = 0; currentLine != lineNo && text[i]; i++ ) - if (text[i] == '\n') - currentLine++; - // Now get the text - int j; - for (j = 0; text[i] && text[i] != '\n'; i++, j++ ) - buf += text[i]; - - g_free( text ); - return buf; + if (lineNo == 0) return GetValue(); + return wxEmptyString; } - else - return wxEmptyString; - } - else - { - if (lineNo == 0) return GetValue(); - return wxEmptyString; - } } void wxTextCtrl::OnDropFiles( wxDropFilesEvent &WXUNUSED(event) ) @@ -672,7 +646,7 @@ void wxTextCtrl::SetInsertionPoint( long pos ) /* bring editable's cursor uptodate. another bug in GTK. */ - GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); + SET_EDITABLE_POS(m_text, gtk_text_get_point( GTK_TEXT(m_text) )); } else { @@ -680,7 +654,7 @@ void wxTextCtrl::SetInsertionPoint( long pos ) /* bring editable's cursor uptodate. bug in GTK. */ - GTK_EDITABLE(m_text)->current_pos = (guint32)pos; + SET_EDITABLE_POS(m_text, (guint32)pos); } } @@ -820,16 +794,26 @@ void wxTextCtrl::SetSelection( long from, long to ) gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to ); } -void wxTextCtrl::ShowPosition( long WXUNUSED(pos) ) +void wxTextCtrl::ShowPosition( long pos ) { -// SetInsertionPoint( pos ); + if (m_windowStyle & wxTE_MULTILINE) + { + GtkAdjustment *vp = GTK_TEXT(m_text)->vadj; + float totalLines = (float) GetNumberOfLines(); + long posX; + long posY; + PositionToXY(pos, &posX, &posY); + float posLine = (float) posY; + float p = (posLine/totalLines)*(vp->upper - vp->lower) + vp->lower; + gtk_adjustment_set_value(GTK_TEXT(m_text)->vadj, p); + } } long wxTextCtrl::GetInsertionPoint() const { wxCHECK_MSG( m_text != NULL, 0, wxT("invalid text ctrl") ); - return (long) GTK_EDITABLE(m_text)->current_pos; + return (long) GET_EDITABLE_POS(m_text); } long wxTextCtrl::GetLastPosition() const @@ -874,33 +858,21 @@ void wxTextCtrl::Cut() { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); -#if (GTK_MINOR_VERSION > 0) - gtk_editable_cut_clipboard( GTK_EDITABLE(m_text) ); -#else - gtk_editable_cut_clipboard( GTK_EDITABLE(m_text), 0 ); -#endif + gtk_editable_cut_clipboard( GTK_EDITABLE(m_text) DUMMY_CLIPBOARD_ARG ); } void wxTextCtrl::Copy() { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); -#if (GTK_MINOR_VERSION > 0) - gtk_editable_copy_clipboard( GTK_EDITABLE(m_text) ); -#else - gtk_editable_copy_clipboard( GTK_EDITABLE(m_text), 0 ); -#endif + gtk_editable_copy_clipboard( GTK_EDITABLE(m_text) DUMMY_CLIPBOARD_ARG ); } void wxTextCtrl::Paste() { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); -#if (GTK_MINOR_VERSION > 0) - gtk_editable_paste_clipboard( GTK_EDITABLE(m_text) ); -#else - gtk_editable_paste_clipboard( GTK_EDITABLE(m_text), 0 ); -#endif + gtk_editable_paste_clipboard( GTK_EDITABLE(m_text) DUMMY_CLIPBOARD_ARG ); } // Undo/redo @@ -936,21 +908,27 @@ void wxTextCtrl::GetSelection(long* fromOut, long* toOut) const { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - long from, to; + gint from, to; +#ifdef __WXGTK20__ + if ( !gtk_editable_get_selection_bounds(GTK_EDITABLE(m_text), &from, &to) ) +#else if ( !(GTK_EDITABLE(m_text)->has_selection) ) +#endif { from = to = GetInsertionPoint(); } else // got selection { +#ifndef __WXGTK20__ from = (long) GTK_EDITABLE(m_text)->selection_start_pos; to = (long) GTK_EDITABLE(m_text)->selection_end_pos; +#endif if ( from > to ) { // exchange them to be compatible with wxMSW - long tmp = from; + gint tmp = from; from = to; to = tmp; } @@ -966,7 +944,11 @@ bool wxTextCtrl::IsEditable() const { wxCHECK_MSG( m_text != NULL, FALSE, wxT("invalid text ctrl") ); +#ifdef __WXGTK20__ + return gtk_editable_get_editable(GTK_EDITABLE(m_text)); +#else return GTK_EDITABLE(m_text)->editable; +#endif } bool wxTextCtrl::IsModified() const @@ -993,15 +975,22 @@ void wxTextCtrl::OnChar( wxKeyEvent &key_event ) if ((key_event.KeyCode() == WXK_RETURN) && !(m_windowStyle & wxTE_MULTILINE)) { + // This will invoke the dialog default action, such + // as the clicking the default button. + wxWindow *top_frame = m_parent; while (top_frame->GetParent() && !(top_frame->IsTopLevel())) top_frame = top_frame->GetParent(); - GtkWindow *window = GTK_WINDOW(top_frame->m_widget); - - if (window->default_widget) + + if (top_frame && GTK_IS_WINDOW(top_frame->m_widget)) { - gtk_widget_activate (window->default_widget); - return; + GtkWindow *window = GTK_WINDOW(top_frame->m_widget); + + if (window->default_widget) + { + gtk_widget_activate (window->default_widget); + return; + } } } @@ -1026,7 +1015,7 @@ bool wxTextCtrl::SetFont( const wxFont &font ) { wxCHECK_MSG( m_text != NULL, FALSE, wxT("invalid text ctrl") ); - if ( !wxWindowBase::SetFont(font) ) + if ( !wxTextCtrlBase::SetFont(font) ) { // font didn't change, nothing to do return FALSE; @@ -1088,7 +1077,7 @@ bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) if (!m_widget->window) return FALSE; - wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ); + wxColour sysbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); if (sysbg.Red() == colour.Red() && sysbg.Green() == colour.Green() && sysbg.Blue() == colour.Blue()) @@ -1115,7 +1104,7 @@ bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) return TRUE; } -bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr &style ) +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) */ @@ -1149,19 +1138,13 @@ bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr &style ) 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 ); + // use the attributes from style which are set in it and fall back + // first to the default style and then to the text control default + // colours for the others + wxGtkTextInsert(m_text, + wxTextAttr::Combine(style, m_defaultStyle, this), + txt, + txtlen); /* does not seem to help under GTK+ 1.2 !!! gtk_editable_set_position( GTK_EDITABLE(m_text), old_pos ); */