X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8312c461b8bae95adf2f75c7be4e6bab3b1ceb47..f1d6804f7c1a398dd0616ccf15cb0f96ea07f5e0:/src/gtk/textctrl.cpp?ds=sidebyside diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 703ceccd9c..182d64038a 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -54,7 +54,8 @@ static void wxGtkOnRemoveTag(GtkTextBuffer *buffer, } extern "C" { -static void wxGtkTextApplyTagsFromAttr(GtkTextBuffer *text_buffer, +static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, + GtkTextBuffer *text_buffer, const wxTextAttr& attr, GtkTextIter *start, GtkTextIter *end) @@ -69,10 +70,9 @@ static void wxGtkTextApplyTagsFromAttr(GtkTextBuffer *text_buffer, if (attr.HasFont()) { - char *font_string; PangoFontDescription *font_description = attr.GetFont().GetNativeFontInfo()->description; - font_string = pango_font_description_to_string(font_description); - g_snprintf(buf, sizeof(buf), "WXFONT %s", font_string); + wxGtkString font_string(pango_font_description_to_string(font_description)); + g_snprintf(buf, sizeof(buf), "WXFONT %s", font_string.c_str()); tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), buf ); if (!tag) @@ -80,7 +80,6 @@ static void wxGtkTextApplyTagsFromAttr(GtkTextBuffer *text_buffer, "font-desc", font_description, NULL ); gtk_text_buffer_apply_tag (text_buffer, tag, start, end); - g_free (font_string); if (attr.GetFont().GetUnderlined()) { @@ -159,6 +158,109 @@ static void wxGtkTextApplyTagsFromAttr(GtkTextBuffer *text_buffer, "justification", align, NULL ); gtk_text_buffer_apply_tag( text_buffer, tag, ¶_start, ¶_end ); } + + if (attr.HasLeftIndent()) + { + // Indentation attribute + + // Clear old indentation tags + GtkTextIter para_start, para_end = *end; + gtk_text_buffer_get_iter_at_line( text_buffer, + ¶_start, + gtk_text_iter_get_line(start) ); + gtk_text_iter_forward_line(¶_end); + + remove_handler_id = g_signal_connect (text_buffer, "remove_tag", + G_CALLBACK(wxGtkOnRemoveTag), + gpointer("WXINDENT")); + gtk_text_buffer_remove_all_tags( text_buffer, ¶_start, ¶_end ); + g_signal_handler_disconnect (text_buffer, remove_handler_id); + + // Convert indent from 1/10th of a mm into pixels + float factor; +#if GTK_CHECK_VERSION(2,2,0) + if (!gtk_check_version(2,2,0)) + factor = (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / + gdk_screen_get_width_mm(gtk_widget_get_screen(text)) / 10; + else +#endif + factor = (float)gdk_screen_width() / gdk_screen_width_mm() / 10; + + const int indent = (int)(factor * attr.GetLeftIndent()); + const int subIndent = (int)(factor * attr.GetLeftSubIndent()); + + gint gindent; + gint gsubindent; + + if (subIndent >= 0) + { + gindent = indent; + gsubindent = -subIndent; + } + else + { + gindent = -subIndent; + gsubindent = indent; + } + + g_snprintf(buf, sizeof(buf), "WXINDENT %d %d", gindent, gsubindent); + tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), + buf ); + if (!tag) + tag = gtk_text_buffer_create_tag( text_buffer, buf, + "left-margin", gindent, "indent", gsubindent, NULL ); + gtk_text_buffer_apply_tag (text_buffer, tag, ¶_start, ¶_end); + } + + if (attr.HasTabs()) + { + // Set tab stops + + // Clear old tabs + GtkTextIter para_start, para_end = *end; + gtk_text_buffer_get_iter_at_line( text_buffer, + ¶_start, + gtk_text_iter_get_line(start) ); + gtk_text_iter_forward_line(¶_end); + + remove_handler_id = g_signal_connect (text_buffer, "remove_tag", + G_CALLBACK(wxGtkOnRemoveTag), + gpointer("WXTABS")); + gtk_text_buffer_remove_all_tags( text_buffer, ¶_start, ¶_end ); + g_signal_handler_disconnect (text_buffer, remove_handler_id); + + const wxArrayInt& tabs = attr.GetTabs(); + + wxString tagname = _T("WXTABS"); + g_snprintf(buf, sizeof(buf), "WXTABS"); + for (size_t i = 0; i < tabs.GetCount(); i++) + tagname += wxString::Format(_T(" %d"), tabs[i]); + + const wxWX2MBbuf buf = tagname.mb_str(wxConvUTF8); + + tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), + buf ); + if (!tag) + { + // Factor to convert from 1/10th of a mm into pixels + float factor; +#if GTK_CHECK_VERSION(2,2,0) + if (!gtk_check_version(2,2,0)) + factor = (float)gdk_screen_get_width(gtk_widget_get_screen(text)) / + gdk_screen_get_width_mm(gtk_widget_get_screen(text)) / 10; + else +#endif + factor = (float)gdk_screen_width() / gdk_screen_width_mm() / 10; + + PangoTabArray* tabArray = pango_tab_array_new(tabs.GetCount(), TRUE); + for (size_t i = 0; i < tabs.GetCount(); i++) + pango_tab_array_set_tab(tabArray, i, PANGO_TAB_LEFT, (gint)(tabs[i] * factor)); + tag = gtk_text_buffer_create_tag( text_buffer, buf, + "tabs", tabArray, NULL ); + pango_tab_array_free(tabArray); + } + gtk_text_buffer_apply_tag (text_buffer, tag, ¶_start, ¶_end); + } } } @@ -179,7 +281,7 @@ static void wxGtkTextInsert(GtkWidget *text, gtk_text_buffer_get_iter_at_offset (text_buffer, &start, start_offset); - wxGtkTextApplyTagsFromAttr(text_buffer, attr, &start, &iter); + wxGtkTextApplyTagsFromAttr(text, text_buffer, attr, &start, &iter); } } @@ -450,9 +552,7 @@ gtk_text_changed_callback( GtkWidget *widget, wxTextCtrl *win ) if ( win->MarkDirtyOnChange() ) win->MarkDirty(); - wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->GetId() ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); + win->SendTextUpdatedEvent(); } } @@ -546,9 +646,10 @@ END_EVENT_TABLE() void wxTextCtrl::Init() { m_dontMarkDirty = - m_ignoreNextUpdate = m_modified = false; + m_countUpdatesToIgnore = 0; + SetUpdateFont(false); m_text = NULL; @@ -787,13 +888,11 @@ wxString wxTextCtrl::GetValue() const gtk_text_buffer_get_start_iter( m_buffer, &start ); GtkTextIter end; gtk_text_buffer_get_end_iter( m_buffer, &end ); - gchar *text = gtk_text_buffer_get_text( m_buffer, &start, &end, TRUE ); + wxGtkString text(gtk_text_buffer_get_text(m_buffer, &start, &end, true)); const wxWxCharBuffer buf = wxGTK_CONV_BACK(text); if ( buf ) tmp = buf; - - g_free( text ); } else { @@ -824,7 +923,15 @@ wxFontEncoding wxTextCtrl::GetTextEncoding() const return enc; } -void wxTextCtrl::SetValue( const wxString &value ) +bool wxTextCtrl::IsEmpty() const +{ + if ( IsMultiLine() ) + return gtk_text_buffer_get_char_count(m_buffer) != 0; + + return wxTextCtrlBase::IsEmpty(); +} + +void wxTextCtrl::DoSetValue( const wxString &value, int flags ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); @@ -835,31 +942,31 @@ void wxTextCtrl::SetValue( const wxString &value ) m_modified = false; DontMarkDirtyOnNextChange(); - if ( IsMultiLine() ) + const wxCharBuffer buffer(wxGTK_CONV_ENC(value, GetTextEncoding())); + if ( !buffer ) { - const wxCharBuffer buffer(wxGTK_CONV_ENC(value, GetTextEncoding())); - if ( !buffer ) - { - // see comment in WriteText() as to why we must warn the user about - // this - wxLogWarning(_("Failed to set text in the text control.")); - return; - } + // see comment in WriteText() as to why we must warn the user about + // this + wxLogWarning(_("Failed to set text in the text control.")); + return; + } - if (gtk_text_buffer_get_char_count(m_buffer) != 0) - IgnoreNextTextUpdate(); + // if the control is not empty, two "changed" signals are emitted, + // otherwise only one and we need to ignore either both or one of them + int ignore = flags & SetValue_SendEvent ? 0 : 1; + if ( !IsEmpty() ) + ignore++; + if ( ignore ) + IgnoreNextTextUpdate(ignore); + + if ( IsMultiLine() ) + { gtk_text_buffer_set_text( m_buffer, buffer, strlen(buffer) ); } else // single line { - // gtk_entry_set_text() emits two "changed" signals if the control is - // not empty because internally it calls gtk_editable_delete_text() and - // gtk_editable_insert_text() but we want to have only one event - if ( !GetValue().empty() ) - IgnoreNextTextUpdate(); - - gtk_entry_set_text( GTK_ENTRY(m_text), wxGTK_CONV(value) ); + gtk_entry_set_text( GTK_ENTRY(m_text), buffer ); } // GRG, Jun/2000: Changed this after a lot of discussion in @@ -942,22 +1049,22 @@ void wxTextCtrl::AppendText( const wxString &text ) wxString wxTextCtrl::GetLineText( long lineNo ) const { + wxString result; if ( IsMultiLine() ) { GtkTextIter line; gtk_text_buffer_get_iter_at_line(m_buffer,&line,lineNo); GtkTextIter end = line; gtk_text_iter_forward_to_line_end(&end); - gchar *text = gtk_text_buffer_get_text(m_buffer,&line,&end,TRUE); - wxString result(wxGTK_CONV_BACK(text)); - g_free(text); - return result; + wxGtkString text(gtk_text_buffer_get_text(m_buffer, &line, &end, true)); + result = wxGTK_CONV_BACK(text); } else { - if (lineNo == 0) return GetValue(); - return wxEmptyString; + if (lineNo == 0) + result = GetValue(); } + return result; } void wxTextCtrl::OnDropFiles( wxDropFilesEvent &WXUNUSED(event) ) @@ -1182,9 +1289,9 @@ void wxTextCtrl::DiscardEdits() bool wxTextCtrl::IgnoreTextUpdate() { - if ( m_ignoreNextUpdate ) + if ( m_countUpdatesToIgnore > 0 ) { - m_ignoreNextUpdate = false; + m_countUpdatesToIgnore--; return true; } @@ -1648,7 +1755,7 @@ bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr& style ) // colours for the others wxTextAttr attr = wxTextAttr::Combine(style, m_defaultStyle, this); - wxGtkTextApplyTagsFromAttr( m_buffer, attr, &starti, &endi ); + wxGtkTextApplyTagsFromAttr( m_widget, m_buffer, attr, &starti, &endi ); return true; }