#include <sys/stat.h>
#include <ctype.h>
+#include <gtk/gtk.h>
#include "wx/gtk/private.h"
+#include "wx/gtk/private/gtk2-compat.h"
// ----------------------------------------------------------------------------
// helpers
NULL );
gtk_text_buffer_apply_tag (text_buffer, tag, start, end);
}
+ if ( font.GetStrikethrough() )
+ {
+ g_snprintf(buf, sizeof(buf), "WXFONTSTRIKETHROUGH");
+ 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,
+ "strikethrough-set", TRUE,
+ "strikethrough", TRUE,
+ NULL );
+ gtk_text_buffer_apply_tag (text_buffer, tag, start, end);
+ }
}
if (attr.HasTextColour())
GtkJustification align;
switch (attr.GetAlignment())
{
- default:
- align = GTK_JUSTIFY_LEFT;
- break;
case wxTEXT_ALIGNMENT_RIGHT:
align = GTK_JUSTIFY_RIGHT;
break;
case wxTEXT_ALIGNMENT_CENTER:
align = GTK_JUSTIFY_CENTER;
break;
+ case wxTEXT_ALIGNMENT_JUSTIFIED:
+#ifdef __WXGTK3__
+ align = GTK_JUSTIFY_FILL;
+ break;
+#elif GTK_CHECK_VERSION(2,11,0)
// gtk+ doesn't support justify before gtk+-2.11.0 with pango-1.17 being available
// (but if new enough pango isn't available it's a mere gtk warning)
-#if GTK_CHECK_VERSION(2,11,0)
- case wxTEXT_ALIGNMENT_JUSTIFIED:
if (!gtk_check_version(2,11,0))
+ {
align = GTK_JUSTIFY_FILL;
- else
- align = GTK_JUSTIFY_LEFT;
- break;
+ break;
+ }
+ // fallthrough
#endif
+ default:
+ align = GTK_JUSTIFY_LEFT;
+ break;
}
g_snprintf(buf, sizeof(buf), "WXALIGNMENT %d", align);
for( n = 0; n < WXSIZEOF(URIPrefixes); ++n )
{
prefix_len = strlen(URIPrefixes[n]);
- if((len > prefix_len) && !strncasecmp(text, URIPrefixes[n], prefix_len))
+ if((len > prefix_len) && !wxStrnicmp(text, URIPrefixes[n], prefix_len))
break;
}
}
//-----------------------------------------------------------------------------
-// clipboard events: "copy-clipboard", "cut-clipboard", "paste-clipboard"
+// "mark_set"
//-----------------------------------------------------------------------------
-// common part of the event handlers below
-static void
-handle_text_clipboard_callback( GtkWidget *widget, wxTextCtrl *win,
- wxEventType eventType, const gchar * signal_name)
-{
- wxClipboardTextEvent event( eventType, win->GetId() );
- event.SetEventObject( win );
- if ( win->HandleWindowEvent( event ) )
- {
- // don't let the default processing to take place if we did something
- // ourselves in the event handler
- g_signal_stop_emission_by_name (widget, signal_name);
- }
-}
-
extern "C" {
-static void
-gtk_copy_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
-{
- handle_text_clipboard_callback(
- widget, win, wxEVT_COMMAND_TEXT_COPY, "copy-clipboard" );
-}
-
-static void
-gtk_cut_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
+static void mark_set(GtkTextBuffer*, GtkTextIter*, GtkTextMark* mark, GSList** markList)
{
- handle_text_clipboard_callback(
- widget, win, wxEVT_COMMAND_TEXT_CUT, "cut-clipboard" );
-}
-
-static void
-gtk_paste_clipboard_callback( GtkWidget *widget, wxTextCtrl *win )
-{
- handle_text_clipboard_callback(
- widget, win, wxEVT_COMMAND_TEXT_PASTE, "paste-clipboard" );
+ if (gtk_text_mark_get_name(mark) == NULL)
+ *markList = g_slist_prepend(*markList, mark);
}
}
m_text = NULL;
m_showPositionOnThaw = NULL;
+ m_anonymousMarkList = NULL;
}
wxTextCtrl::~wxTextCtrl()
{
+ if (m_anonymousMarkList)
+ g_slist_free(m_anonymousMarkList);
}
wxTextCtrl::wxTextCtrl( wxWindow *parent,
if (multi_line)
{
+ m_buffer = gtk_text_buffer_new(NULL);
+ gulong sig_id = g_signal_connect(m_buffer, "mark_set", G_CALLBACK(mark_set), &m_anonymousMarkList);
// Create view
- m_text = gtk_text_view_new();
-
- m_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_text) );
+ m_text = gtk_text_view_new_with_buffer(m_buffer);
+ // gtk_text_view_set_buffer adds its own reference
+ g_object_unref(m_buffer);
+ g_signal_handler_disconnect(m_buffer, sig_id);
// create "ShowPosition" marker
GtkTextIter iter;
? GTK_POLICY_NEVER
: GTK_POLICY_AUTOMATIC );
// for ScrollLines/Pages
- m_scrollBar[1] = (GtkRange*)((GtkScrolledWindow*)m_widget)->vscrollbar;
+ m_scrollBar[1] = GTK_RANGE(gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(m_widget)));
// Insert view into scrolled window
gtk_container_add( GTK_CONTAINER(m_widget), m_text );
GtkTextIter start, end;
// We create our wxUrl tag here for slight efficiency gain - we
- // don't have to check for the tag existance in callbacks,
+ // don't have to check for the tag existence in callbacks,
// hereby it's guaranteed to exist.
gtk_text_buffer_create_tag(m_buffer, "wxUrl",
"foreground", "blue",
}
- g_signal_connect (m_text, "copy-clipboard",
- G_CALLBACK (gtk_copy_clipboard_callback), this);
- g_signal_connect (m_text, "cut-clipboard",
- G_CALLBACK (gtk_cut_clipboard_callback), this);
- g_signal_connect (m_text, "paste-clipboard",
- G_CALLBACK (gtk_paste_clipboard_callback), this);
+ GTKConnectClipboardSignals(m_text);
m_cursor = wxCursor( wxCURSOR_IBEAM );
// Insert the text
wxGtkTextInsert( m_text, m_buffer, m_defaultStyle, buffer );
- GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(m_widget) );
// Scroll to cursor, but only if scrollbar thumb is at the very bottom
// won't work when frozen, text view is not using m_buffer then
- if (!IsFrozen() && wxIsSameDouble(adj->value, adj->upper - adj->page_size))
+ if (!IsFrozen())
{
- gtk_text_view_scroll_to_mark( GTK_TEXT_VIEW(m_text),
- gtk_text_buffer_get_insert( m_buffer ), 0.0, FALSE, 0.0, 1.0 );
+ GtkAdjustment* adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(m_widget));
+ const double value = gtk_adjustment_get_value(adj);
+ const double upper = gtk_adjustment_get_upper(adj);
+ const double page_size = gtk_adjustment_get_page_size(adj);
+ if (wxIsSameDouble(value, upper - page_size))
+ {
+ gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(m_text),
+ gtk_text_buffer_get_insert(m_buffer), 0, false, 0, 1);
+ }
}
}
}
else // single line control
{
- if ( pos <= GTK_ENTRY(m_text)->text_length )
+ if (pos <= gtk_entry_get_text_length(GTK_ENTRY(m_text)))
{
if ( y )
*y = 0;
}
}
+wxPoint wxTextCtrl::DoPositionToCoords(long pos) const
+{
+ if ( !IsMultiLine() )
+ {
+ // Single line text entry (GtkTextEntry) doesn't have support for
+ // getting the coordinates for the given offset. Perhaps we could
+ // find them ourselves by using GetTextExtent() but for now just leave
+ // it unimplemented, this function is more useful for multiline
+ // controls anyhow.
+ return wxDefaultPosition;
+ }
+
+ // Window coordinates for the given position is calculated by getting
+ // the buffer coordinates and converting them to window coordinates.
+ GtkTextView *textview = GTK_TEXT_VIEW(m_text);
+
+ GtkTextIter iter;
+ gtk_text_buffer_get_iter_at_offset(m_buffer, &iter, pos);
+
+ GdkRectangle bufferCoords;
+ gtk_text_view_get_iter_location(textview, &iter, &bufferCoords);
+
+ gint winCoordX = 0,
+ winCoordY = 0;
+ gtk_text_view_buffer_to_window_coords(textview, GTK_TEXT_WINDOW_WIDGET,
+ bufferCoords.x, bufferCoords.y,
+ &winCoordX, &winCoordY);
+
+ return wxPoint(winCoordX, winCoordY);
+}
+
int wxTextCtrl::GetNumberOfLines() const
{
if ( IsMultiLine() )
// disabled and enabled mode, or we end up with a different colour under the
// text.
wxColour oldColour = GetBackgroundColour();
- if (oldColour.Ok())
+ if (oldColour.IsOk())
{
// Need to set twice or it'll optimize the useful stuff out
if (oldColour == * wxWHITE)
if ( IsMultiLine() )
{
- return gtk_text_view_get_editable(GTK_TEXT_VIEW(m_text));
+ return gtk_text_view_get_editable(GTK_TEXT_VIEW(m_text)) != 0;
}
else
{
}
else
{
- return GTK_ENTRY(m_text)->text_area;
+#ifdef __WXGTK3__
+ // no access to internal GdkWindows
+ return NULL;
+#else
+ return gtk_entry_get_text_window(GTK_ENTRY(m_text));
+#endif
}
}
if ( !wxControl::SetBackgroundColour( colour ) )
return false;
- if (!m_backgroundColour.Ok())
+ if (!m_backgroundColour.IsOk())
return false;
// change active background color too
// Obtain a copy of the default attributes
GtkTextAttributes * const
pattr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(m_text));
- wxON_BLOCK_EXIT1( g_free, pattr );
+ wxON_BLOCK_EXIT1(gtk_text_attributes_unref, pattr);
// And query GTK for the attributes at the given position using it as base
if ( !gtk_text_iter_get_attributes(&positioni, pattr) )
void wxTextCtrl::DoApplyWidgetStyle(GtkRcStyle *style)
{
- gtk_widget_modify_style(m_text, style);
+ GTKApplyStyle(m_text, style);
}
void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
// removing buffer dramatically speeds up insertion:
g_object_ref(m_buffer);
GtkTextBuffer* buf_new = gtk_text_buffer_new(NULL);
- GtkTextMark* mark = GTK_TEXT_VIEW(m_text)->first_para_mark;
gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), buf_new);
// gtk_text_view_set_buffer adds its own reference
g_object_unref(buf_new);
- // This mark should be deleted when the buffer is changed,
- // but it's not (in GTK+ up to at least 2.10.6).
+ // These marks should be deleted when the buffer is changed,
+ // but they are not (in GTK+ up to at least 3.0.1).
// Otherwise these anonymous marks start to build up in the buffer,
// and Freeze takes longer and longer each time it is called.
- if (GTK_IS_TEXT_MARK(mark) && !gtk_text_mark_get_deleted(mark))
- gtk_text_buffer_delete_mark(m_buffer, mark);
+ if (m_anonymousMarkList)
+ {
+ for (GSList* item = m_anonymousMarkList; item; item = item->next)
+ {
+ GtkTextMark* mark = static_cast<GtkTextMark*>(item->data);
+ if (GTK_IS_TEXT_MARK(mark) && !gtk_text_mark_get_deleted(mark))
+ gtk_text_buffer_delete_mark(m_buffer, mark);
+ }
+ g_slist_free(m_anonymousMarkList);
+ m_anonymousMarkList = NULL;
+ }
}
}
if ( HasFlag(wxTE_MULTILINE) )
{
// reattach buffer:
+ gulong sig_id = g_signal_connect(m_buffer, "mark_set", G_CALLBACK(mark_set), &m_anonymousMarkList);
gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), m_buffer);
g_object_unref(m_buffer);
+ g_signal_handler_disconnect(m_buffer, sig_id);
if (m_showPositionOnThaw != NULL)
{
gtk_text_iter_forward_to_tag_toggle(&end, tag);
// Native context menu is probably not desired on an URL.
- // Consider making this dependant on ProcessEvent(wxTextUrlEvent) return value
+ // Consider making this dependent on ProcessEvent(wxTextUrlEvent) return value
if(event.GetEventType() == wxEVT_RIGHT_DOWN)
event.Skip(false);