Fixed crashes when GtkEntry's internal buffer is not available (bug 588395)

To fix this I replaced the code that creates an internal buffer
at init and construction time with code that creates a buffer
at _get_buffer() time, this is the same as GtkTextView does and
fixes the crashes for me.
This commit is contained in:
Tristan Van Berkom 2009-07-16 23:19:03 -04:00
parent 7f83be8595
commit 51149246c0

View File

@ -237,9 +237,6 @@ typedef enum
*/
static void gtk_entry_editable_init (GtkEditableClass *iface);
static void gtk_entry_cell_editable_init (GtkCellEditableIface *iface);
static GObject* gtk_entry_constructor (GType type,
guint n_props,
GObjectConstructParam *props);
static void gtk_entry_set_property (GObject *object,
guint prop_id,
const GValue *value,
@ -524,6 +521,8 @@ static void buffer_notify_max_length (GtkEntryBuffer *buffer,
GtkEntry *entry);
static void buffer_connect_signals (GtkEntry *entry);
static void buffer_disconnect_signals (GtkEntry *entry);
static GtkEntryBuffer *get_buffer (GtkEntry *entry);
G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
@ -565,7 +564,6 @@ gtk_entry_class_init (GtkEntryClass *class)
widget_class = (GtkWidgetClass*) class;
gtk_object_class = (GtkObjectClass *)class;
gobject_class->constructor = gtk_entry_constructor;
gobject_class->dispose = gtk_entry_dispose;
gobject_class->finalize = gtk_entry_finalize;
gobject_class->set_property = gtk_entry_set_property;
@ -2023,7 +2021,7 @@ gtk_entry_get_property (GObject *object,
break;
case PROP_MAX_LENGTH:
g_value_set_int (value, gtk_entry_buffer_get_max_length (priv->buffer));
g_value_set_int (value, gtk_entry_buffer_get_max_length (get_buffer (entry)));
break;
case PROP_VISIBILITY:
@ -2075,7 +2073,7 @@ gtk_entry_get_property (GObject *object,
break;
case PROP_TEXT_LENGTH:
g_value_set_uint (value, gtk_entry_buffer_get_length (priv->buffer));
g_value_set_uint (value, gtk_entry_buffer_get_length (get_buffer (entry)));
break;
case PROP_INVISIBLE_CHAR_SET:
@ -2253,34 +2251,10 @@ find_invisible_char (GtkWidget *widget)
return '*';
}
static GObject*
gtk_entry_constructor (GType type,
guint n_props,
GObjectConstructParam *props)
{
GObject *obj = G_OBJECT_CLASS (gtk_entry_parent_class)->constructor (type, n_props, props);
GtkEntryPrivate *priv;
GtkEntryBuffer *buffer;
if (obj != NULL)
{
priv = GTK_ENTRY_GET_PRIVATE (obj);
if (!priv->buffer)
{
buffer = gtk_entry_buffer_new (NULL, 0);
gtk_entry_set_buffer (GTK_ENTRY (obj), buffer);
g_object_unref (buffer);
}
}
return obj;
}
static void
gtk_entry_init (GtkEntry *entry)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
GtkEntryBuffer *buffer;
GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
@ -2320,13 +2294,6 @@ gtk_entry_init (GtkEntry *entry)
g_signal_connect (entry->im_context, "delete-surrounding",
G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
/* need to set a buffer here, so GtkEntry subclasses can do anything
* in their init() functions, just as it used to be before
* GtkEntryBuffer
*/
buffer = gtk_entry_buffer_new (NULL, 0);
gtk_entry_set_buffer (entry, buffer);
g_object_unref (buffer);
}
static gint
@ -2543,8 +2510,8 @@ gtk_entry_get_display_text (GtkEntry *entry,
gint i;
priv = GTK_ENTRY_GET_PRIVATE (entry);
text = gtk_entry_buffer_get_text (priv->buffer);
length = gtk_entry_buffer_get_length (priv->buffer);
text = gtk_entry_buffer_get_text (get_buffer (entry));
length = gtk_entry_buffer_get_length (get_buffer (entry));
if (end_pos < 0)
end_pos = length;
@ -4001,7 +3968,7 @@ gtk_entry_motion_notify (GtkWidget *widget,
if (event->y < 0)
tmp_pos = 0;
else if (event->y >= height)
tmp_pos = gtk_entry_buffer_get_length (priv->buffer);
tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
else
tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
@ -4319,13 +4286,12 @@ gtk_entry_get_chars (GtkEditable *editable,
gint end_pos)
{
GtkEntry *entry = GTK_ENTRY (editable);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
const gchar *text;
gint text_length;
gint start_index, end_index;
text = gtk_entry_buffer_get_text (priv->buffer);
text_length = gtk_entry_buffer_get_length (priv->buffer);
text = gtk_entry_buffer_get_text (get_buffer (entry));
text_length = gtk_entry_buffer_get_length (get_buffer (entry));
if (end_pos < 0)
end_pos = text_length;
@ -4344,11 +4310,10 @@ gtk_entry_real_set_position (GtkEditable *editable,
gint position)
{
GtkEntry *entry = GTK_ENTRY (editable);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
guint length;
length = gtk_entry_buffer_get_length (priv->buffer);
length = gtk_entry_buffer_get_length (get_buffer (entry));
if (position < 0 || position > length)
position = length;
@ -4372,10 +4337,9 @@ gtk_entry_set_selection_bounds (GtkEditable *editable,
gint end)
{
GtkEntry *entry = GTK_ENTRY (editable);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
guint length;
length = gtk_entry_buffer_get_length (priv->buffer);
length = gtk_entry_buffer_get_length (get_buffer (entry));
if (start < 0)
start = length;
if (end < 0)
@ -4704,23 +4668,21 @@ buffer_notify_max_length (GtkEntryBuffer *buffer,
static void
buffer_connect_signals (GtkEntry *entry)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
g_signal_connect (priv->buffer, "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
g_signal_connect (priv->buffer, "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
g_signal_connect (priv->buffer, "notify::text", G_CALLBACK (buffer_notify_text), entry);
g_signal_connect (priv->buffer, "notify::length", G_CALLBACK (buffer_notify_length), entry);
g_signal_connect (priv->buffer, "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
g_signal_connect (get_buffer (entry), "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
g_signal_connect (get_buffer (entry), "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
g_signal_connect (get_buffer (entry), "notify::text", G_CALLBACK (buffer_notify_text), entry);
g_signal_connect (get_buffer (entry), "notify::length", G_CALLBACK (buffer_notify_length), entry);
g_signal_connect (get_buffer (entry), "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
}
static void
buffer_disconnect_signals (GtkEntry *entry)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
g_signal_handlers_disconnect_by_func (priv->buffer, buffer_inserted_text, entry);
g_signal_handlers_disconnect_by_func (priv->buffer, buffer_deleted_text, entry);
g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_text, entry);
g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_length, entry);
g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_max_length, entry);
g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_inserted_text, entry);
g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_deleted_text, entry);
g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_text, entry);
g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_length, entry);
g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_max_length, entry);
}
/* Compute the X position for an offset that corresponds to the "more important
@ -4794,7 +4756,7 @@ gtk_entry_move_cursor (GtkEntry *entry,
case GTK_MOVEMENT_PARAGRAPH_ENDS:
case GTK_MOVEMENT_BUFFER_ENDS:
priv = GTK_ENTRY_GET_PRIVATE (entry);
new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (priv->buffer);
new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
break;
case GTK_MOVEMENT_DISPLAY_LINES:
case GTK_MOVEMENT_PARAGRAPHS:
@ -4852,7 +4814,7 @@ gtk_entry_move_cursor (GtkEntry *entry,
case GTK_MOVEMENT_PARAGRAPH_ENDS:
case GTK_MOVEMENT_BUFFER_ENDS:
priv = GTK_ENTRY_GET_PRIVATE (entry);
new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (priv->buffer);
new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
if (entry->current_pos == new_pos)
gtk_widget_error_bell (GTK_WIDGET (entry));
break;
@ -4894,10 +4856,9 @@ gtk_entry_delete_from_cursor (GtkEntry *entry,
gint count)
{
GtkEditable *editable = GTK_EDITABLE (entry);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
gint start_pos = entry->current_pos;
gint end_pos = entry->current_pos;
gint old_n_bytes = gtk_entry_buffer_get_bytes (priv->buffer);
gint old_n_bytes = gtk_entry_buffer_get_bytes (get_buffer (entry));
_gtk_entry_reset_im_context (entry);
@ -4963,7 +4924,7 @@ gtk_entry_delete_from_cursor (GtkEntry *entry,
break;
}
if (gtk_entry_buffer_get_bytes (priv->buffer) == old_n_bytes)
if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == old_n_bytes)
gtk_widget_error_bell (GTK_WIDGET (entry));
gtk_entry_pend_cursor_blink (entry);
@ -5848,7 +5809,6 @@ gtk_entry_get_cursor_locations (GtkEntry *entry,
gint *weak_x)
{
DisplayMode mode = gtk_entry_get_display_mode (entry);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
/* Nothing to display at all, so no cursor is relevant */
if (mode == DISPLAY_BLANK)
@ -5880,7 +5840,7 @@ gtk_entry_get_cursor_locations (GtkEntry *entry,
index += entry->preedit_length;
else
{
gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (priv->buffer);
gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (get_buffer (entry));
index += preedit_len_chars * g_unichar_to_utf8 (entry->invisible_char, NULL);
}
}
@ -6084,11 +6044,10 @@ gtk_entry_move_logically (GtkEntry *entry,
gint start,
gint count)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
gint new_pos = start;
guint length;
length = gtk_entry_buffer_get_length (priv->buffer);
length = gtk_entry_buffer_get_length (get_buffer (entry));
/* Prevent any leak of information */
if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
@ -6131,11 +6090,10 @@ gtk_entry_move_forward_word (GtkEntry *entry,
gint start,
gboolean allow_whitespace)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
gint new_pos = start;
guint length;
length = gtk_entry_buffer_get_length (priv->buffer);
length = gtk_entry_buffer_get_length (get_buffer (entry));
/* Prevent any leak of information */
if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
@ -6279,7 +6237,7 @@ paste_received (GtkClipboard *clipboard,
length = truncate_multiline (text);
/* only complete if the selection is at the end */
popup_completion = (gtk_entry_buffer_get_length (priv->buffer) ==
popup_completion = (gtk_entry_buffer_get_length (get_buffer (entry)) ==
MAX (entry->current_pos, entry->selection_bound));
if (completion)
@ -6609,11 +6567,28 @@ gtk_entry_new_with_max_length (gint max)
max = CLAMP (max, 0, GTK_ENTRY_BUFFER_MAX_SIZE);
entry = g_object_new (GTK_TYPE_ENTRY, NULL);
gtk_entry_buffer_set_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer, max);
gtk_entry_buffer_set_max_length (get_buffer (entry), max);
return GTK_WIDGET (entry);
}
static GtkEntryBuffer*
get_buffer (GtkEntry *entry)
{
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
if (priv->buffer == NULL)
{
GtkEntryBuffer *buffer;
buffer = gtk_entry_buffer_new (NULL, 0);
gtk_entry_set_buffer (entry, buffer);
g_object_unref (buffer);
}
return priv->buffer;
}
/**
* gtk_entry_get_buffer:
* @entry: a #GtkEntry
@ -6629,7 +6604,8 @@ GtkEntryBuffer*
gtk_entry_get_buffer (GtkEntry *entry)
{
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
return GTK_ENTRY_GET_PRIVATE (entry)->buffer;
return get_buffer (entry);
}
/**
@ -6719,7 +6695,7 @@ gtk_entry_set_text (GtkEntry *entry,
/* Actually setting the text will affect the cursor and selection;
* if the contents don't actually change, this will look odd to the user.
*/
if (strcmp (gtk_entry_buffer_get_text (priv->buffer), text) == 0)
if (strcmp (gtk_entry_buffer_get_text (get_buffer (entry)), text) == 0)
return;
completion = gtk_entry_get_completion (entry);
@ -6758,7 +6734,7 @@ gtk_entry_append_text (GtkEntry *entry,
g_return_if_fail (text != NULL);
priv = GTK_ENTRY_GET_PRIVATE (entry);
tmp_pos = gtk_entry_buffer_get_length (priv->buffer);
tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos);
}
@ -7030,7 +7006,7 @@ G_CONST_RETURN gchar*
gtk_entry_get_text (GtkEntry *entry)
{
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
return gtk_entry_buffer_get_text (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
return gtk_entry_buffer_get_text (get_buffer (entry));
}
/**
@ -7077,7 +7053,7 @@ gtk_entry_set_max_length (GtkEntry *entry,
gint max)
{
g_return_if_fail (GTK_IS_ENTRY (entry));
gtk_entry_buffer_set_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer, max);
gtk_entry_buffer_set_max_length (get_buffer (entry), max);
}
/**
@ -7100,7 +7076,7 @@ gint
gtk_entry_get_max_length (GtkEntry *entry)
{
g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
return gtk_entry_buffer_get_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
return gtk_entry_buffer_get_max_length (get_buffer (entry));
}
/**
@ -7125,7 +7101,7 @@ guint16
gtk_entry_get_text_length (GtkEntry *entry)
{
g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
return gtk_entry_buffer_get_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
return gtk_entry_buffer_get_length (get_buffer (entry));
}
/**
@ -9524,7 +9500,7 @@ accept_completion_callback (GtkEntry *entry)
if (completion->priv->has_completion)
gtk_editable_set_position (GTK_EDITABLE (entry),
gtk_entry_buffer_get_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer));
gtk_entry_buffer_get_length (get_buffer (entry)));
return FALSE;
}