X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkeditable.c;h=43dfd45564fc675cd5e31682d3fcb48230946ad1;hb=0cc688aa92b8fe5452b63fb49c51204498a2988b;hp=4a5ec13f228be4adccfe631494effa43ba5e6049;hpb=1941bf4cbf30ba6a0b63ae2f881a6f7d6c13a677;p=~andy%2Fgtk diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c index 4a5ec13f2..43dfd4556 100644 --- a/gtk/gtkeditable.c +++ b/gtk/gtkeditable.c @@ -2,672 +2,471 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . */ -#include -#include -#ifdef USE_XIM -#include "gdk/gdkx.h" -#endif -#include "gdk/gdkkeysyms.h" -#include "gdk/gdki18n.h" -#include "gtkeditable.h" -#include "gtkmain.h" -#include "gtkselection.h" -#include "gtksignal.h" - -#define MIN_EDITABLE_WIDTH 150 -#define DRAW_TIMEOUT 20 -#define INNER_BORDER 2 - -enum { - INSERT_TEXT, - DELETE_TEXT, - UPDATE_TEXT, - GET_CHARS, - SET_SELECTION, - CHANGED, - LAST_SIGNAL -}; - - -typedef void (*GtkEditableSignal1) (GtkObject *object, - gpointer arg1, - gint arg2, - gpointer arg3, - gpointer data); -typedef void (*GtkEditableSignal2) (GtkObject *object, - gint arg1, - gint arg2, - gpointer data); - -typedef gpointer (*GtkEditableSignal3) (GtkObject *object, - gint arg1, - gint arg2, - gpointer data); - - -static void gtk_editable_marshal_signal_1 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args); -static void gtk_editable_marshal_signal_2 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args); -static void gtk_editable_marshal_signal_3 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args); - -static void gtk_editable_class_init (GtkEditableClass *klass); -static void gtk_editable_init (GtkEditable *editable); -static void gtk_editable_finalize (GtkObject *object); -static gint gtk_editable_selection_clear (GtkWidget *widget, - GdkEventSelection *event); -static void gtk_editable_selection_handler (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); -static void gtk_editable_selection_received (GtkWidget *widget, - GtkSelectionData *selection_data); - -static void gtk_editable_set_selection (GtkEditable *editable, - gint start, - gint end); - -static GtkWidgetClass *parent_class = NULL; -static gint editable_signals[LAST_SIGNAL] = { 0 }; -static GdkAtom ctext_atom = GDK_NONE; -static GdkAtom text_atom = GDK_NONE; -static GdkAtom clipboard_atom = GDK_NONE; - -guint -gtk_editable_get_type () -{ - static guint editable_type = 0; - if (!editable_type) - { - GtkTypeInfo editable_info = - { - "GtkEditable", - sizeof (GtkEditable), - sizeof (GtkEditableClass), - (GtkClassInitFunc) gtk_editable_class_init, - (GtkObjectInitFunc) gtk_editable_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL, - }; - - editable_type = gtk_type_unique (gtk_widget_get_type (), &editable_info); - } +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ - return editable_type; -} +/** + * SECTION:gtkeditable + * @Short_description: Interface for text-editing widgets + * @Title: GtkEditable + * + * The #GtkEditable interface is an interface which should be implemented by + * text editing widgets, such as #GtkEntry and #GtkSpinButton. It contains functions + * for generically manipulating an editable widget, a large number of action + * signals used for key bindings, and several signals that an application can + * connect to to modify the behavior of a widget. + * + * As an example of the latter usage, by connecting + * the following handler to #GtkEditable::insert-text, an application + * can convert all entry into a widget into uppercase. + * + * + * Forcing entry to uppercase. + * + * #include <ctype.h> + * + * void + * insert_text_handler (GtkEditable *editable, + * const gchar *text, + * gint length, + * gint *position, + * gpointer data) + * { + * gchar *result = g_utf8_strup (text, length); + * + * g_signal_handlers_block_by_func (editable, + * (gpointer) insert_text_handler, data); + * gtk_editable_insert_text (editable, result, length, position); + * g_signal_handlers_unblock_by_func (editable, + * (gpointer) insert_text_handler, data); + * + * g_signal_stop_emission_by_name (editable, "insert_text"); + * + * g_free (result); + * } + * + * + */ -static void -gtk_editable_class_init (GtkEditableClass *class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - - parent_class = gtk_type_class (gtk_widget_get_type ()); - - editable_signals[INSERT_TEXT] = - gtk_signal_new ("insert_text", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, insert_text), - gtk_editable_marshal_signal_1, - GTK_TYPE_NONE, 3, - GTK_TYPE_STRING, GTK_TYPE_INT, - GTK_TYPE_POINTER); - editable_signals[DELETE_TEXT] = - gtk_signal_new ("delete_text", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, delete_text), - gtk_editable_marshal_signal_2, - GTK_TYPE_NONE, 2, - GTK_TYPE_INT, GTK_TYPE_INT); - editable_signals[UPDATE_TEXT] = - gtk_signal_new ("update_text", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, update_text), - gtk_editable_marshal_signal_2, - GTK_TYPE_NONE, 2, - GTK_TYPE_INT, GTK_TYPE_INT); - editable_signals[GET_CHARS] = - gtk_signal_new ("get_chars", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, get_chars), - gtk_editable_marshal_signal_3, - GTK_TYPE_POINTER, 2, - GTK_TYPE_INT, GTK_TYPE_INT); - editable_signals[SET_SELECTION] = - gtk_signal_new ("set_selection", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, set_selection), - gtk_editable_marshal_signal_2, - GTK_TYPE_NONE, 2, - GTK_TYPE_INT, GTK_TYPE_INT); - editable_signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkEditableClass, changed), - gtk_signal_default_marshaller, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, editable_signals, LAST_SIGNAL); - - object_class->finalize = gtk_editable_finalize; - - widget_class->selection_clear_event = gtk_editable_selection_clear; - widget_class->selection_received = gtk_editable_selection_received; - - class->insert_text = NULL; - class->delete_text = NULL; - class->update_text = NULL; - class->get_chars = NULL; - class->set_selection = NULL; - class->changed = NULL; -} +#include "config.h" +#include -static void -gtk_editable_init (GtkEditable *editable) -{ - GTK_WIDGET_SET_FLAGS (editable, GTK_CAN_FOCUS); - - editable->selection_start_pos = 0; - editable->selection_end_pos = 0; - editable->has_selection = FALSE; - editable->editable = 1; - editable->clipboard_text = NULL; - -#ifdef USE_XIM - editable->ic = NULL; -#endif - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); - - gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY, - GDK_TARGET_STRING, gtk_editable_selection_handler, - NULL); - gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom, - GDK_TARGET_STRING, gtk_editable_selection_handler, - NULL); - - if (!text_atom) - text_atom = gdk_atom_intern ("TEXT", FALSE); - - gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY, - text_atom, - gtk_editable_selection_handler, - NULL); - gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom, - text_atom, - gtk_editable_selection_handler, - NULL); - - if (!ctext_atom) - ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE); - - gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY, - ctext_atom, - gtk_editable_selection_handler, - NULL); - gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom, - ctext_atom, - gtk_editable_selection_handler, - NULL); -} +#include "gtkeditable.h" +#include "gtkmarshalers.h" +#include "gtkintl.h" -static void -gtk_editable_marshal_signal_1 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args) -{ - GtkEditableSignal1 rfunc; - rfunc = (GtkEditableSignal1) func; +static void gtk_editable_base_init (gpointer g_class); - (* rfunc) (object, GTK_VALUE_STRING (args[0]), GTK_VALUE_INT (args[1]), - GTK_VALUE_POINTER (args[2]), func_data); -} -static void -gtk_editable_marshal_signal_2 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args) +GType +gtk_editable_get_type (void) { - GtkEditableSignal2 rfunc; + static GType editable_type = 0; - rfunc = (GtkEditableSignal2) func; - - (* rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]), - func_data); -} - -static void -gtk_editable_marshal_signal_3 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args) -{ - GtkEditableSignal3 rfunc; - gpointer *return_val; + if (!editable_type) + { + const GTypeInfo editable_info = + { + sizeof (GtkEditableInterface), /* class_size */ + gtk_editable_base_init, /* base_init */ + NULL, /* base_finalize */ + }; - rfunc = (GtkEditableSignal3) func; + editable_type = g_type_register_static (G_TYPE_INTERFACE, I_("GtkEditable"), + &editable_info, 0); + } - return_val = GTK_RETLOC_POINTER (args[2]); - - *return_val = (* rfunc) (object, - GTK_VALUE_INT (args[0]), - GTK_VALUE_INT (args[1]), - func_data); + return editable_type; } static void -gtk_editable_finalize (GtkObject *object) +gtk_editable_base_init (gpointer g_class) { - GtkEditable *editable; - - g_return_if_fail (object != NULL); - g_return_if_fail (GTK_IS_EDITABLE (object)); + static gboolean initialized = FALSE; - editable = GTK_EDITABLE (object); - -#ifdef USE_XIM - if (editable->ic) + if (! initialized) { - gdk_ic_destroy (editable->ic); - editable->ic = NULL; + /** + * GtkEditable::insert-text: + * @editable: the object which received the signal + * @new_text: the new text to insert + * @new_text_length: the length of the new text, in bytes, + * or -1 if new_text is nul-terminated + * @position: (inout) (type int): the position, in characters, + * at which to insert the new text. this is an in-out + * parameter. After the signal emission is finished, it + * should point after the newly inserted text. + * + * This signal is emitted when text is inserted into + * the widget by the user. The default handler for + * this signal will normally be responsible for inserting + * the text, so by connecting to this signal and then + * stopping the signal with g_signal_stop_emission(), it + * is possible to modify the inserted text, or prevent + * it from being inserted entirely. + */ + g_signal_new (I_("insert-text"), + GTK_TYPE_EDITABLE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEditableInterface, insert_text), + NULL, NULL, + _gtk_marshal_VOID__STRING_INT_POINTER, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_POINTER); + + /** + * GtkEditable::delete-text: + * @editable: the object which received the signal + * @start_pos: the starting position + * @end_pos: the end position + * + * This signal is emitted when text is deleted from + * the widget by the user. The default handler for + * this signal will normally be responsible for deleting + * the text, so by connecting to this signal and then + * stopping the signal with g_signal_stop_emission(), it + * is possible to modify the range of deleted text, or + * prevent it from being deleted entirely. The @start_pos + * and @end_pos parameters are interpreted as for + * gtk_editable_delete_text(). + */ + g_signal_new (I_("delete-text"), + GTK_TYPE_EDITABLE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEditableInterface, delete_text), + NULL, NULL, + _gtk_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + /** + * GtkEditable::changed: + * @editable: the object which received the signal + * + * The ::changed signal is emitted at the end of a single + * user-visible operation on the contents of the #GtkEditable. + * + * E.g., a paste operation that replaces the contents of the + * selection will cause only one signal emission (even though it + * is implemented by first deleting the selection, then inserting + * the new content, and may cause multiple ::notify::text signals + * to be emitted). + */ + g_signal_new (I_("changed"), + GTK_TYPE_EDITABLE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkEditableInterface, changed), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + initialized = TRUE; } -#endif - - (* GTK_OBJECT_CLASS (parent_class)->finalize) (object); } +/** + * gtk_editable_insert_text: + * @editable: a #GtkEditable + * @new_text: the text to append + * @new_text_length: the length of the text in bytes, or -1 + * @position: (inout): location of the position text will be inserted at + * + * Inserts @new_text_length bytes of @new_text into the contents of the + * widget, at position @position. + * + * Note that the position is in characters, not in bytes. + * The function updates @position to point after the newly inserted text. + * + * Virtual: do_insert_text + */ void gtk_editable_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position) { - gchar buf[64]; - gchar *text; - - g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_EDITABLE (editable)); + g_return_if_fail (position != NULL); - if (new_text_length <= 64) - text = buf; - else - text = g_new (gchar, new_text_length); - - strncpy (text, new_text, new_text_length); - - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[INSERT_TEXT], - text, new_text_length, position); - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]); - - if (new_text_length > 64) - g_free (text); + if (new_text_length < 0) + new_text_length = strlen (new_text); + + GTK_EDITABLE_GET_IFACE (editable)->do_insert_text (editable, new_text, new_text_length, position); } +/** + * gtk_editable_delete_text: + * @editable: a #GtkEditable + * @start_pos: start position + * @end_pos: end position + * + * Deletes a sequence of characters. The characters that are deleted are + * those characters at positions from @start_pos up to, but not including + * @end_pos. If @end_pos is negative, then the characters deleted + * are those from @start_pos to the end of the text. + * + * Note that the positions are specified in characters, not bytes. + * + * Virtual: do_delete_text + */ void gtk_editable_delete_text (GtkEditable *editable, gint start_pos, gint end_pos) { - g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_EDITABLE (editable)); - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[DELETE_TEXT], - start_pos, end_pos); - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]); -} - -static void -gtk_editable_update_text (GtkEditable *editable, - gint start_pos, - gint end_pos) -{ - g_return_if_fail (editable != NULL); - g_return_if_fail (GTK_IS_EDITABLE (editable)); - - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[UPDATE_TEXT], - start_pos, end_pos); + GTK_EDITABLE_GET_IFACE (editable)->do_delete_text (editable, start_pos, end_pos); } +/** + * gtk_editable_get_chars: + * @editable: a #GtkEditable + * @start_pos: start of text + * @end_pos: end of text + * + * Retrieves a sequence of characters. The characters that are retrieved + * are those characters at positions from @start_pos up to, but not + * including @end_pos. If @end_pos is negative, then the characters + * retrieved are those characters from @start_pos to the end of the text. + * + * Note that positions are specified in characters, not bytes. + * + * Return value: a pointer to the contents of the widget as a + * string. This string is allocated by the #GtkEditable + * implementation and should be freed by the caller. + */ gchar * -gtk_editable_get_chars (GtkEditable *editable, - gint start, - gint end) +gtk_editable_get_chars (GtkEditable *editable, + gint start_pos, + gint end_pos) { - gchar *retval = NULL; - - g_return_val_if_fail (editable != NULL, NULL); g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL); - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[GET_CHARS], - start, end, &retval); - - return retval; + return GTK_EDITABLE_GET_IFACE (editable)->get_chars (editable, start_pos, end_pos); } -static void -gtk_editable_set_selection (GtkEditable *editable, - gint start_pos, - gint end_pos) +/** + * gtk_editable_set_position: + * @editable: a #GtkEditable + * @position: the position of the cursor + * + * Sets the cursor position in the editable to the given value. + * + * The cursor is displayed before the character with the given (base 0) + * index in the contents of the editable. The value must be less than or + * equal to the number of characters in the editable. A value of -1 + * indicates that the position should be set after the last character + * of the editable. Note that @position is in characters, not in bytes. + */ +void +gtk_editable_set_position (GtkEditable *editable, + gint position) { - g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_EDITABLE (editable)); - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[SET_SELECTION], - start_pos, end_pos); + GTK_EDITABLE_GET_IFACE (editable)->set_position (editable, position); } -static gint -gtk_editable_selection_clear (GtkWidget *widget, - GdkEventSelection *event) +/** + * gtk_editable_get_position: + * @editable: a #GtkEditable + * + * Retrieves the current position of the cursor relative to the start + * of the content of the editable. + * + * Note that this position is in characters, not in bytes. + * + * Return value: the cursor position + */ +gint +gtk_editable_get_position (GtkEditable *editable) { - GtkEditable *editable; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_EDITABLE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - /* Let the selection handling code know that the selection - * has been changed, since we've overriden the default handler */ - gtk_selection_clear (widget, event); + g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0); - editable = GTK_EDITABLE (widget); - - if (event->selection == GDK_SELECTION_PRIMARY) - { - if (editable->has_selection) - { - editable->has_selection = FALSE; - gtk_editable_update_text (editable, editable->selection_start_pos, - editable->selection_end_pos); - } - } - else if (event->selection == clipboard_atom) - { - g_free (editable->clipboard_text); - editable->clipboard_text = NULL; - } - - return FALSE; + return GTK_EDITABLE_GET_IFACE (editable)->get_position (editable); } -static void -gtk_editable_selection_handler (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data) +/** + * gtk_editable_get_selection_bounds: + * @editable: a #GtkEditable + * @start_pos: (out) (allow-none): location to store the starting position, or %NULL + * @end_pos: (out) (allow-none): location to store the end position, or %NULL + * + * Retrieves the selection bound of the editable. start_pos will be filled + * with the start of the selection and @end_pos with end. If no text was + * selected both will be identical and %FALSE will be returned. + * + * Note that positions are specified in characters, not bytes. + * + * Return value: %TRUE if an area is selected, %FALSE otherwise + */ +gboolean +gtk_editable_get_selection_bounds (GtkEditable *editable, + gint *start_pos, + gint *end_pos) { - GtkEditable *editable; - gint selection_start_pos; - gint selection_end_pos; - - gchar *str; - gint length; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_EDITABLE (widget)); - - editable = GTK_EDITABLE (widget); - - if (selection_data->selection == GDK_SELECTION_PRIMARY) - { - selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos); - selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos); - str = gtk_editable_get_chars(editable, - selection_start_pos, - selection_end_pos); - length = selection_end_pos - selection_start_pos; - } - else /* CLIPBOARD */ - { - if (!editable->clipboard_text) - return; /* Refuse */ - - str = editable->clipboard_text; - length = strlen (editable->clipboard_text); - } + gint tmp_start, tmp_end; + gboolean result; - if (selection_data->target == GDK_SELECTION_TYPE_STRING) - { - gtk_selection_data_set (selection_data, - GDK_SELECTION_TYPE_STRING, - 8*sizeof(gchar), str, length); - } - else if (selection_data->target == text_atom || - selection_data->target == ctext_atom) - { - guchar *text; - gchar c; - GdkAtom encoding; - gint format; - gint new_length; - - c = str[length]; - str[length] = '\0'; - gdk_string_to_compound_text (str, &encoding, &format, &text, &new_length); - gtk_selection_data_set (selection_data, encoding, format, text, new_length); - gdk_free_compound_text (text); - str[length] = c; - } - - if (str != editable->clipboard_text) - g_free (str); -} - -static void -gtk_editable_selection_received (GtkWidget *widget, - GtkSelectionData *selection_data) -{ - GtkEditable *editable; - gint reselect; - gint old_pos; - gint tmp_pos; - enum {INVALID, STRING, CTEXT} type; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_EDITABLE (widget)); - - editable = GTK_EDITABLE (widget); - - if (selection_data->type == GDK_TARGET_STRING) - type = STRING; - else if (selection_data->type == ctext_atom) - type = CTEXT; - else - type = INVALID; - - if (type == INVALID || selection_data->length < 0) - { - /* avoid infinite loop */ - if (selection_data->target != GDK_TARGET_STRING) - gtk_selection_convert (widget, selection_data->selection, - GDK_TARGET_STRING, GDK_CURRENT_TIME); - return; - } - - reselect = FALSE; - - if ((editable->selection_start_pos != editable->selection_end_pos) && - (!editable->has_selection || - (selection_data->selection == clipboard_atom))) - { - reselect = TRUE; - - /* Don't want to call gtk_editable_delete_selection here if we are going - * to reclaim the selection to avoid extra server traffic */ - if (editable->has_selection) - { - gtk_editable_delete_text (editable, - MIN (editable->selection_start_pos, editable->selection_end_pos), - MAX (editable->selection_start_pos, editable->selection_end_pos)); - } - else - gtk_editable_delete_selection (editable); - } + g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE); - tmp_pos = old_pos = editable->current_pos; + result = GTK_EDITABLE_GET_IFACE (editable)->get_selection_bounds (editable, &tmp_start, &tmp_end); - switch (type) - { - case STRING: - selection_data->data[selection_data->length] = 0; - gtk_editable_insert_text (editable, selection_data->data, - strlen (selection_data->data), &tmp_pos); - editable->current_pos = tmp_pos; - break; - case CTEXT: - { - gchar **list; - gint count; - gint i; - - count = gdk_text_property_to_text_list (selection_data->type, - selection_data->format, - selection_data->data, - selection_data->length, - &list); - for (i=0; icurrent_pos = tmp_pos; - } - if (count > 0) - gdk_free_text_list (list); - } - break; - case INVALID: /* quiet compiler */ - break; - } + if (start_pos) + *start_pos = MIN (tmp_start, tmp_end); + if (end_pos) + *end_pos = MAX (tmp_start, tmp_end); - if (reselect) - gtk_editable_set_selection (editable, old_pos, editable->current_pos); + return result; } +/** + * gtk_editable_delete_selection: + * @editable: a #GtkEditable + * + * Deletes the currently selected text of the editable. + * This call doesn't do anything if there is no selected text. + */ void gtk_editable_delete_selection (GtkEditable *editable) { - guint start; - guint end; - - if (!editable->editable) - return; - - start = editable->selection_start_pos; - end = editable->selection_end_pos; + gint start, end; - editable->selection_start_pos = 0; - editable->selection_end_pos = 0; - - if (start != end) - gtk_editable_delete_text (editable, MIN (start, end), MAX (start,end)); + g_return_if_fail (GTK_IS_EDITABLE (editable)); - if (editable->has_selection) - { - editable->has_selection = FALSE; - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == GTK_WIDGET (editable)->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - } + if (gtk_editable_get_selection_bounds (editable, &start, &end)) + gtk_editable_delete_text (editable, start, end); } +/** + * gtk_editable_select_region: + * @editable: a #GtkEditable + * @start_pos: start of region + * @end_pos: end of region + * + * Selects a region of text. The characters that are selected are + * those characters at positions from @start_pos up to, but not + * including @end_pos. If @end_pos is negative, then the + * characters selected are those characters from @start_pos to + * the end of the text. + * + * Note that positions are specified in characters, not bytes. + * + * Virtual: set_selection_bounds + */ void -gtk_editable_claim_selection (GtkEditable *editable, - gboolean claim, - guint32 time) +gtk_editable_select_region (GtkEditable *editable, + gint start_pos, + gint end_pos) { - g_return_if_fail (GTK_WIDGET_REALIZED (editable)); + g_return_if_fail (GTK_IS_EDITABLE (editable)); - if (claim) - { - if (gtk_selection_owner_set (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY, time)) - editable->has_selection = TRUE; - } - else - { - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == - GTK_WIDGET(editable)->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, time); - } + GTK_EDITABLE_GET_IFACE (editable)->set_selection_bounds (editable, start_pos, end_pos); } +/** + * gtk_editable_cut_clipboard: + * @editable: a #GtkEditable + * + * Removes the contents of the currently selected content in the editable and + * puts it on the clipboard. + */ void -gtk_editable_select_region (GtkEditable *editable, - gint start, - gint end) +gtk_editable_cut_clipboard (GtkEditable *editable) { - if (GTK_WIDGET_REALIZED (editable)) - gtk_editable_claim_selection (editable, start != end, GDK_CURRENT_TIME); - - gtk_editable_set_selection (editable, start, end); + g_return_if_fail (GTK_IS_EDITABLE (editable)); + + g_signal_emit_by_name (editable, "cut-clipboard"); } +/** + * gtk_editable_copy_clipboard: + * @editable: a #GtkEditable + * + * Copies the contents of the currently selected content in the editable and + * puts it on the clipboard. + */ void -gtk_editable_cut_clipboard (GtkEditable *editable, guint32 time) +gtk_editable_copy_clipboard (GtkEditable *editable) { - gtk_editable_copy_clipboard (editable, time); - gtk_editable_delete_selection (editable); + g_return_if_fail (GTK_IS_EDITABLE (editable)); + + g_signal_emit_by_name (editable, "copy-clipboard"); } +/** + * gtk_editable_paste_clipboard: + * @editable: a #GtkEditable + * + * Pastes the content of the clipboard to the current position of the + * cursor in the editable. + */ void -gtk_editable_copy_clipboard (GtkEditable *editable, guint32 time) +gtk_editable_paste_clipboard (GtkEditable *editable) { - gint selection_start_pos; - gint selection_end_pos; - - selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos); - selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos); - - if (selection_start_pos != selection_end_pos) - { - if (gtk_selection_owner_set (GTK_WIDGET (editable), - clipboard_atom, - time)) - editable->clipboard_text = gtk_editable_get_chars (editable, - selection_start_pos, - selection_end_pos); - } + g_return_if_fail (GTK_IS_EDITABLE (editable)); + + g_signal_emit_by_name (editable, "paste-clipboard"); } +/** + * gtk_editable_set_editable: + * @editable: a #GtkEditable + * @is_editable: %TRUE if the user is allowed to edit the text + * in the widget + * + * Determines if the user can edit the text in the editable + * widget or not. + */ void -gtk_editable_paste_clipboard (GtkEditable *editable, guint32 time) +gtk_editable_set_editable (GtkEditable *editable, + gboolean is_editable) { - if (editable->editable) - gtk_selection_convert (GTK_WIDGET(editable), - clipboard_atom, ctext_atom, time); + g_return_if_fail (GTK_IS_EDITABLE (editable)); + + g_object_set (editable, + "editable", is_editable != FALSE, + NULL); } -void -gtk_editable_changed (GtkEditable *editable) +/** + * gtk_editable_get_editable: + * @editable: a #GtkEditable + * + * Retrieves whether @editable is editable. See + * gtk_editable_set_editable(). + * + * Return value: %TRUE if @editable is editable. + */ +gboolean +gtk_editable_get_editable (GtkEditable *editable) { - gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]); + gboolean value; + + g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE); + + g_object_get (editable, "editable", &value, NULL); + + return value; }