1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdk/gdkkeysyms.h"
30 #include "gdk/gdki18n.h"
32 #include "gtkimmulticontext.h"
34 #include "gtkselection.h"
35 #include "gtksignal.h"
38 #include <pango/pango.h>
40 #include <glib-object.h>
42 #define MIN_ENTRY_WIDTH 150
43 #define DRAW_TIMEOUT 20
44 #define INNER_BORDER 2
46 /* Initial size of buffer, in bytes */
49 /* Maximum size of text buffer, in bytes */
50 #define MAX_SIZE G_MAXUSHORT
59 static void gtk_entry_class_init (GtkEntryClass *klass);
60 static void gtk_entry_init (GtkEntry *entry);
61 static void gtk_entry_set_arg (GtkObject *object,
64 static void gtk_entry_get_arg (GtkObject *object,
67 static void gtk_entry_finalize (GObject *object);
68 static void gtk_entry_realize (GtkWidget *widget);
69 static void gtk_entry_unrealize (GtkWidget *widget);
70 static void gtk_entry_draw_focus (GtkWidget *widget);
71 static void gtk_entry_size_request (GtkWidget *widget,
72 GtkRequisition *requisition);
73 static void gtk_entry_size_allocate (GtkWidget *widget,
74 GtkAllocation *allocation);
75 static void gtk_entry_draw (GtkWidget *widget,
77 static gint gtk_entry_expose (GtkWidget *widget,
78 GdkEventExpose *event);
79 static gint gtk_entry_button_press (GtkWidget *widget,
80 GdkEventButton *event);
81 static gint gtk_entry_button_release (GtkWidget *widget,
82 GdkEventButton *event);
83 static gint gtk_entry_motion_notify (GtkWidget *widget,
84 GdkEventMotion *event);
85 static gint gtk_entry_key_press (GtkWidget *widget,
87 static gint gtk_entry_focus_in (GtkWidget *widget,
88 GdkEventFocus *event);
89 static gint gtk_entry_focus_out (GtkWidget *widget,
90 GdkEventFocus *event);
91 static void gtk_entry_draw_text (GtkEntry *entry);
92 static void gtk_entry_ensure_layout (GtkEntry *entry);
93 static void gtk_entry_draw_cursor (GtkEntry *entry);
94 static void gtk_entry_style_set (GtkWidget *widget,
95 GtkStyle *previous_style);
96 static void gtk_entry_state_changed (GtkWidget *widget,
97 GtkStateType previous_state);
98 static void gtk_entry_queue_draw (GtkEntry *entry);
99 static gint gtk_entry_find_position (GtkEntry *entry,
101 static void gtk_entry_get_cursor_locations (GtkEntry *entry,
104 static void entry_adjust_scroll (GtkEntry *entry);
105 static void gtk_entry_insert_text (GtkEditable *editable,
106 const gchar *new_text,
107 gint new_text_length,
109 static void gtk_entry_delete_text (GtkEditable *editable,
112 static void gtk_entry_update_text (GtkEditable *editable,
115 static gchar * gtk_entry_get_chars (GtkEditable *editable,
122 /* Binding actions */
123 static void gtk_entry_move_cursor (GtkEditable *editable,
126 static void gtk_entry_move_word (GtkEditable *editable,
128 static void gtk_entry_move_to_column (GtkEditable *editable,
130 static void gtk_entry_kill_char (GtkEditable *editable,
132 static void gtk_entry_kill_word (GtkEditable *editable,
134 static void gtk_entry_kill_line (GtkEditable *editable,
138 static void gtk_move_forward_character (GtkEntry *entry);
139 static void gtk_move_backward_character (GtkEntry *entry);
140 static void gtk_move_forward_word (GtkEntry *entry);
141 static void gtk_move_backward_word (GtkEntry *entry);
142 static void gtk_move_beginning_of_line (GtkEntry *entry);
143 static void gtk_move_end_of_line (GtkEntry *entry);
144 static void gtk_delete_forward_character (GtkEntry *entry);
145 static void gtk_delete_backward_character (GtkEntry *entry);
146 static void gtk_delete_forward_word (GtkEntry *entry);
147 static void gtk_delete_backward_word (GtkEntry *entry);
148 static void gtk_delete_line (GtkEntry *entry);
149 static void gtk_delete_to_line_end (GtkEntry *entry);
150 static void gtk_select_word (GtkEntry *entry,
152 static void gtk_select_line (GtkEntry *entry,
156 static void gtk_entry_set_selection (GtkEditable *editable,
160 static void gtk_entry_set_position_from_editable (GtkEditable *editable,
163 static void gtk_entry_commit_cb (GtkIMContext *context,
168 static GtkWidgetClass *parent_class = NULL;
169 static GdkAtom ctext_atom = GDK_NONE;
171 static const GtkTextFunction control_keys[26] =
173 (GtkTextFunction)gtk_move_beginning_of_line, /* a */
174 (GtkTextFunction)gtk_move_backward_character, /* b */
175 (GtkTextFunction)gtk_editable_copy_clipboard, /* c */
176 (GtkTextFunction)gtk_delete_forward_character, /* d */
177 (GtkTextFunction)gtk_move_end_of_line, /* e */
178 (GtkTextFunction)gtk_move_forward_character, /* f */
180 (GtkTextFunction)gtk_delete_backward_character, /* h */
183 (GtkTextFunction)gtk_delete_to_line_end, /* k */
193 (GtkTextFunction)gtk_delete_line, /* u */
194 (GtkTextFunction)gtk_editable_paste_clipboard, /* v */
195 (GtkTextFunction)gtk_delete_backward_word, /* w */
196 (GtkTextFunction)gtk_editable_cut_clipboard, /* x */
201 static const GtkTextFunction alt_keys[26] =
204 (GtkTextFunction)gtk_move_backward_word, /* b */
206 (GtkTextFunction)gtk_delete_forward_word, /* d */
208 (GtkTextFunction)gtk_move_forward_word, /* f */
233 gtk_entry_get_type (void)
235 static GtkType entry_type = 0;
239 static const GtkTypeInfo entry_info =
243 sizeof (GtkEntryClass),
244 (GtkClassInitFunc) gtk_entry_class_init,
245 (GtkObjectInitFunc) gtk_entry_init,
246 /* reserved_1 */ NULL,
247 /* reserved_2 */ NULL,
248 (GtkClassInitFunc) NULL,
251 entry_type = gtk_type_unique (GTK_TYPE_EDITABLE, &entry_info);
258 gtk_entry_class_init (GtkEntryClass *class)
260 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
261 GtkObjectClass *object_class;
262 GtkWidgetClass *widget_class;
263 GtkEditableClass *editable_class;
265 object_class = (GtkObjectClass*) class;
266 widget_class = (GtkWidgetClass*) class;
267 editable_class = (GtkEditableClass*) class;
268 parent_class = gtk_type_class (GTK_TYPE_EDITABLE);
270 gobject_class->finalize = gtk_entry_finalize;
272 gtk_object_add_arg_type ("GtkEntry::max_length", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MAX_LENGTH);
273 gtk_object_add_arg_type ("GtkEntry::visibility", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBILITY);
275 object_class->set_arg = gtk_entry_set_arg;
276 object_class->get_arg = gtk_entry_get_arg;
278 widget_class->realize = gtk_entry_realize;
279 widget_class->unrealize = gtk_entry_unrealize;
280 widget_class->draw_focus = gtk_entry_draw_focus;
281 widget_class->size_request = gtk_entry_size_request;
282 widget_class->size_allocate = gtk_entry_size_allocate;
283 widget_class->draw = gtk_entry_draw;
284 widget_class->expose_event = gtk_entry_expose;
285 widget_class->button_press_event = gtk_entry_button_press;
286 widget_class->button_release_event = gtk_entry_button_release;
287 widget_class->motion_notify_event = gtk_entry_motion_notify;
288 widget_class->key_press_event = gtk_entry_key_press;
289 widget_class->focus_in_event = gtk_entry_focus_in;
290 widget_class->focus_out_event = gtk_entry_focus_out;
291 widget_class->style_set = gtk_entry_style_set;
292 widget_class->state_changed = gtk_entry_state_changed;
294 editable_class->insert_text = gtk_entry_insert_text;
295 editable_class->delete_text = gtk_entry_delete_text;
296 editable_class->changed = (void (*)(GtkEditable *)) entry_adjust_scroll;
298 editable_class->move_cursor = gtk_entry_move_cursor;
299 editable_class->move_word = gtk_entry_move_word;
300 editable_class->move_to_column = gtk_entry_move_to_column;
302 editable_class->kill_char = gtk_entry_kill_char;
303 editable_class->kill_word = gtk_entry_kill_word;
304 editable_class->kill_line = gtk_entry_kill_line;
306 editable_class->update_text = gtk_entry_update_text;
307 editable_class->get_chars = gtk_entry_get_chars;
308 editable_class->set_selection = gtk_entry_set_selection;
309 editable_class->set_position = gtk_entry_set_position_from_editable;
313 gtk_entry_set_arg (GtkObject *object,
319 entry = GTK_ENTRY (object);
324 gtk_entry_set_max_length (entry, GTK_VALUE_UINT (*arg));
327 gtk_entry_set_visibility (entry, GTK_VALUE_BOOL (*arg));
335 gtk_entry_get_arg (GtkObject *object,
341 entry = GTK_ENTRY (object);
346 GTK_VALUE_UINT (*arg) = entry->text_max_length;
349 GTK_VALUE_BOOL (*arg) = GTK_EDITABLE (entry)->visible;
352 arg->type = GTK_TYPE_INVALID;
358 gtk_entry_init (GtkEntry *entry)
360 GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
362 entry->text_area = NULL;
364 entry->text_size = MIN_SIZE;
365 entry->text = g_malloc (entry->text_size);
366 entry->text[0] = '\0';
368 entry->text_length = 0;
369 entry->text_max_length = 0;
371 entry->scroll_offset = 0;
376 /* This object is completely private. No external entity can gain a reference
377 * to it; so we create it here and destroy it in finalize().
379 entry->im_context = gtk_im_multicontext_new ();
381 gtk_signal_connect (GTK_OBJECT (entry->im_context), "commit",
382 GTK_SIGNAL_FUNC (gtk_entry_commit_cb), entry);
388 return GTK_WIDGET (gtk_type_new (GTK_TYPE_ENTRY));
392 gtk_entry_new_with_max_length (guint16 max)
396 entry = gtk_type_new (GTK_TYPE_ENTRY);
397 entry->text_max_length = max;
399 return GTK_WIDGET (entry);
403 gtk_entry_set_text (GtkEntry *entry,
408 GtkEditable *editable;
410 g_return_if_fail (entry != NULL);
411 g_return_if_fail (GTK_IS_ENTRY (entry));
412 g_return_if_fail (text != NULL);
414 editable = GTK_EDITABLE (entry);
416 gtk_entry_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
419 gtk_editable_insert_text (editable, text, strlen (text), &tmp_pos);
420 editable->current_pos = tmp_pos;
424 gtk_entry_append_text (GtkEntry *entry,
429 g_return_if_fail (entry != NULL);
430 g_return_if_fail (GTK_IS_ENTRY (entry));
431 g_return_if_fail (text != NULL);
433 tmp_pos = entry->text_length;
434 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
438 gtk_entry_prepend_text (GtkEntry *entry,
443 g_return_if_fail (entry != NULL);
444 g_return_if_fail (GTK_IS_ENTRY (entry));
445 g_return_if_fail (text != NULL);
448 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
452 gtk_entry_set_position (GtkEntry *entry,
455 g_return_if_fail (entry != NULL);
456 g_return_if_fail (GTK_IS_ENTRY (entry));
458 if ((position == -1) || (position > entry->text_length))
459 GTK_EDITABLE(entry)->current_pos = entry->text_length;
461 GTK_EDITABLE(entry)->current_pos = position;
462 entry_adjust_scroll (entry);
466 gtk_entry_set_position_from_editable (GtkEditable *editable,
469 gtk_entry_set_position (GTK_ENTRY (editable), position);
473 gtk_entry_set_visibility (GtkEntry *entry,
476 g_return_if_fail (entry != NULL);
477 g_return_if_fail (GTK_IS_ENTRY (entry));
479 GTK_EDITABLE (entry)->visible = visible ? TRUE : FALSE;
481 gtk_entry_queue_draw (entry);
485 gtk_entry_set_editable(GtkEntry *entry,
488 g_return_if_fail (entry != NULL);
489 g_return_if_fail (GTK_IS_ENTRY (entry));
491 gtk_editable_set_editable (GTK_EDITABLE (entry), editable);
495 gtk_entry_get_text (GtkEntry *entry)
497 g_return_val_if_fail (entry != NULL, NULL);
498 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
504 gtk_entry_finalize (GObject *object)
508 g_return_if_fail (GTK_IS_ENTRY (object));
510 entry = GTK_ENTRY (object);
512 gtk_object_unref (GTK_OBJECT (entry->im_context));
515 gtk_timeout_remove (entry->timer);
517 entry->text_size = 0;
520 g_free (entry->text);
523 G_OBJECT_CLASS (parent_class)->finalize (object);
527 gtk_entry_realize (GtkWidget *widget)
530 GtkEditable *editable;
531 GtkRequisition requisition;
532 GdkWindowAttr attributes;
533 gint attributes_mask;
535 g_return_if_fail (widget != NULL);
536 g_return_if_fail (GTK_IS_ENTRY (widget));
538 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
539 entry = GTK_ENTRY (widget);
540 editable = GTK_EDITABLE (widget);
542 gtk_widget_get_child_requisition (widget, &requisition);
544 attributes.window_type = GDK_WINDOW_CHILD;
545 attributes.x = widget->allocation.x;
546 attributes.y = widget->allocation.y + (widget->allocation.height -
547 requisition.height) / 2;
548 attributes.width = widget->allocation.width;
549 attributes.height = requisition.height;
550 attributes.wclass = GDK_INPUT_OUTPUT;
551 attributes.visual = gtk_widget_get_visual (widget);
552 attributes.colormap = gtk_widget_get_colormap (widget);
553 attributes.event_mask = gtk_widget_get_events (widget);
554 attributes.event_mask |= (GDK_EXPOSURE_MASK |
555 GDK_BUTTON_PRESS_MASK |
556 GDK_BUTTON_RELEASE_MASK |
557 GDK_BUTTON1_MOTION_MASK |
558 GDK_BUTTON3_MOTION_MASK |
559 GDK_POINTER_MOTION_HINT_MASK |
560 GDK_ENTER_NOTIFY_MASK |
561 GDK_LEAVE_NOTIFY_MASK |
563 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
565 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
566 gdk_window_set_user_data (widget->window, entry);
568 attributes.x = widget->style->klass->xthickness;
569 attributes.y = widget->style->klass->ythickness;
570 attributes.width = widget->allocation.width - attributes.x * 2;
571 attributes.height = requisition.height - attributes.y * 2;
572 attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
573 attributes_mask |= GDK_WA_CURSOR;
575 entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
576 gdk_window_set_user_data (entry->text_area, entry);
578 widget->style = gtk_style_attach (widget->style, widget->window);
580 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
581 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
583 gdk_window_show (entry->text_area);
585 if (editable->selection_start_pos != editable->selection_end_pos)
586 gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
588 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
592 gtk_entry_unrealize (GtkWidget *widget)
596 g_return_if_fail (widget != NULL);
597 g_return_if_fail (GTK_IS_ENTRY (widget));
599 entry = GTK_ENTRY (widget);
601 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
603 if (entry->text_area)
605 gdk_window_set_user_data (entry->text_area, NULL);
606 gdk_window_destroy (entry->text_area);
607 entry->text_area = NULL;
608 gdk_cursor_destroy (entry->cursor);
609 entry->cursor = NULL;
612 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
613 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
617 gtk_entry_draw_focus (GtkWidget *widget)
622 g_return_if_fail (widget != NULL);
623 g_return_if_fail (GTK_IS_ENTRY (widget));
625 if (GTK_WIDGET_DRAWABLE (widget))
629 gdk_window_get_size (widget->window, &width, &height);
631 if (GTK_WIDGET_HAS_FOCUS (widget))
639 gtk_paint_shadow (widget->style, widget->window,
640 GTK_STATE_NORMAL, GTK_SHADOW_IN,
641 NULL, widget, "entry",
642 x, y, width, height);
644 if (GTK_WIDGET_HAS_FOCUS (widget))
646 gdk_window_get_size (widget->window, &width, &height);
647 gtk_paint_focus (widget->style, widget->window,
648 NULL, widget, "entry",
649 0, 0, width - 1, height - 1);
655 gtk_entry_size_request (GtkWidget *widget,
656 GtkRequisition *requisition)
659 PangoFontMetrics metrics;
663 g_return_if_fail (widget != NULL);
664 g_return_if_fail (GTK_IS_ENTRY (widget));
665 g_return_if_fail (requisition != NULL);
667 entry = GTK_ENTRY (widget);
669 /* We do this to deal with direction changes - should that be a signal?
673 pango_layout_unref (entry->layout);
674 entry->layout = NULL;
677 gtk_entry_ensure_layout (entry);
679 /* hackish for now, get metrics
681 font = pango_context_load_font (pango_layout_get_context (entry->layout),
682 widget->style->font_desc);
683 lang = pango_context_get_lang (pango_layout_get_context (entry->layout));
684 pango_font_get_metrics (font, lang, &metrics);
687 g_object_unref (G_OBJECT (font));
689 entry->ascent = metrics.ascent;
691 requisition->width = MIN_ENTRY_WIDTH + (widget->style->klass->xthickness + INNER_BORDER) * 2;
692 requisition->height = ((metrics.ascent + metrics.descent) / PANGO_SCALE +
693 (widget->style->klass->ythickness + INNER_BORDER) * 2);
697 gtk_entry_size_allocate (GtkWidget *widget,
698 GtkAllocation *allocation)
701 GtkEditable *editable;
703 g_return_if_fail (widget != NULL);
704 g_return_if_fail (GTK_IS_ENTRY (widget));
705 g_return_if_fail (allocation != NULL);
707 widget->allocation = *allocation;
708 entry = GTK_ENTRY (widget);
709 editable = GTK_EDITABLE (widget);
711 if (GTK_WIDGET_REALIZED (widget))
713 /* We call gtk_widget_get_child_requisition, since we want (for
714 * backwards compatibility reasons) the realization here to
715 * be affected by the usize of the entry, if set
717 GtkRequisition requisition;
718 gtk_widget_get_child_requisition (widget, &requisition);
720 gdk_window_move_resize (widget->window,
722 allocation->y + (allocation->height - requisition.height) / 2,
723 allocation->width, requisition.height);
724 gdk_window_move_resize (entry->text_area,
725 widget->style->klass->xthickness,
726 widget->style->klass->ythickness,
727 allocation->width - widget->style->klass->xthickness * 2,
728 requisition.height - widget->style->klass->ythickness * 2);
732 /* And make sure the cursor is on screen */
733 entry_adjust_scroll (entry);
737 gtk_entry_draw (GtkWidget *widget,
742 g_return_if_fail (widget != NULL);
743 g_return_if_fail (GTK_IS_ENTRY (widget));
744 g_return_if_fail (area != NULL);
746 entry = GTK_ENTRY (widget);
748 if (GTK_WIDGET_DRAWABLE (widget))
750 GdkRectangle tmp_area = *area;
752 tmp_area.x -= widget->style->klass->xthickness;
753 tmp_area.y -= widget->style->klass->xthickness;
755 gdk_window_begin_paint_rect (entry->text_area, &tmp_area);
756 gtk_widget_draw_focus (widget);
757 gtk_entry_draw_text (GTK_ENTRY (widget));
758 gtk_entry_draw_cursor (GTK_ENTRY (widget));
759 gdk_window_end_paint (entry->text_area);
764 gtk_entry_expose (GtkWidget *widget,
765 GdkEventExpose *event)
769 g_return_val_if_fail (widget != NULL, FALSE);
770 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
771 g_return_val_if_fail (event != NULL, FALSE);
773 entry = GTK_ENTRY (widget);
775 if (widget->window == event->window)
776 gtk_widget_draw_focus (widget);
777 else if (entry->text_area == event->window)
779 gtk_entry_draw_text (GTK_ENTRY (widget));
780 gtk_entry_draw_cursor (GTK_ENTRY (widget));
787 gtk_entry_button_press (GtkWidget *widget,
788 GdkEventButton *event)
791 GtkEditable *editable;
794 g_return_val_if_fail (widget != NULL, FALSE);
795 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
796 g_return_val_if_fail (event != NULL, FALSE);
798 if (ctext_atom == GDK_NONE)
799 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
801 entry = GTK_ENTRY (widget);
802 editable = GTK_EDITABLE (widget);
804 if (entry->button && (event->button != entry->button))
807 entry->button = event->button;
809 if (!GTK_WIDGET_HAS_FOCUS (widget))
810 gtk_widget_grab_focus (widget);
812 if (event->button == 1)
816 case GDK_BUTTON_PRESS:
817 gtk_grab_add (widget);
819 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
820 /* Set it now, so we display things right. We'll unset it
821 * later if things don't work out */
822 editable->has_selection = TRUE;
823 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
824 editable->current_pos = editable->selection_start_pos;
827 case GDK_2BUTTON_PRESS:
828 gtk_select_word (entry, event->time);
831 case GDK_3BUTTON_PRESS:
832 gtk_select_line (entry, event->time);
841 else if (event->type == GDK_BUTTON_PRESS)
843 if ((event->button == 2) && editable->editable)
845 if (editable->selection_start_pos == editable->selection_end_pos ||
846 editable->has_selection)
847 editable->current_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
848 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
849 ctext_atom, event->time);
853 gtk_grab_add (widget);
855 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
856 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
857 editable->has_selection = FALSE;
858 editable->current_pos = editable->selection_start_pos;
860 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
861 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
871 gtk_entry_button_release (GtkWidget *widget,
872 GdkEventButton *event)
875 GtkEditable *editable;
877 g_return_val_if_fail (widget != NULL, FALSE);
878 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
879 g_return_val_if_fail (event != NULL, FALSE);
881 entry = GTK_ENTRY (widget);
882 editable = GTK_EDITABLE (widget);
884 if (entry->button != event->button)
889 if (event->button == 1)
891 gtk_grab_remove (widget);
893 editable->has_selection = FALSE;
894 if (editable->selection_start_pos != editable->selection_end_pos)
896 if (gtk_selection_owner_set (widget,
897 GDK_SELECTION_PRIMARY,
899 editable->has_selection = TRUE;
901 gtk_entry_queue_draw (entry);
905 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
906 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
911 else if (event->button == 3)
913 gtk_grab_remove (widget);
922 gtk_entry_motion_notify (GtkWidget *widget,
923 GdkEventMotion *event)
928 g_return_val_if_fail (widget != NULL, FALSE);
929 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
930 g_return_val_if_fail (event != NULL, FALSE);
932 entry = GTK_ENTRY (widget);
934 if (entry->button == 0)
938 if (event->is_hint || (entry->text_area != event->window))
939 gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
941 GTK_EDITABLE(entry)->selection_end_pos = gtk_entry_find_position (entry, x + entry->scroll_offset);
942 GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
943 entry_adjust_scroll (entry);
944 gtk_entry_queue_draw (entry);
950 gtk_entry_key_press (GtkWidget *widget,
954 GtkEditable *editable;
959 gint extend_selection;
962 g_return_val_if_fail (widget != NULL, FALSE);
963 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
964 g_return_val_if_fail (event != NULL, FALSE);
966 entry = GTK_ENTRY (widget);
967 editable = GTK_EDITABLE (widget);
970 if(editable->editable == FALSE)
973 initial_pos = editable->current_pos;
975 extend_selection = event->state & GDK_SHIFT_MASK;
976 extend_start = FALSE;
978 if (extend_selection)
980 if (editable->selection_start_pos == editable->selection_end_pos)
982 editable->selection_start_pos = editable->current_pos;
983 editable->selection_end_pos = editable->current_pos;
986 extend_start = (editable->current_pos == editable->selection_start_pos);
989 switch (event->keyval)
993 if (event->state & GDK_CONTROL_MASK)
994 gtk_delete_backward_word (entry);
996 gtk_delete_backward_character (entry);
1000 gtk_delete_line (entry);
1004 if (event->state & GDK_SHIFT_MASK)
1006 extend_selection = FALSE;
1007 gtk_editable_paste_clipboard (editable);
1009 else if (event->state & GDK_CONTROL_MASK)
1011 gtk_editable_copy_clipboard (editable);
1015 /* gtk_toggle_insert(entry) -- IMPLEMENT */
1020 if (event->state & GDK_CONTROL_MASK)
1021 gtk_delete_forward_word (entry);
1022 else if (event->state & GDK_SHIFT_MASK)
1024 extend_selection = FALSE;
1025 gtk_editable_cut_clipboard (editable);
1028 gtk_delete_forward_character (entry);
1032 gtk_move_beginning_of_line (entry);
1036 gtk_move_end_of_line (entry);
1040 if (event->state & GDK_CONTROL_MASK)
1041 gtk_move_backward_word (entry);
1043 gtk_move_backward_character (entry);
1047 if (event->state & GDK_CONTROL_MASK)
1048 gtk_move_forward_word (entry);
1050 gtk_move_forward_character (entry);
1054 gtk_widget_activate (widget);
1056 /* The next two keys should not be inserted literally. Any others ??? */
1061 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1063 key = event->keyval;
1065 if (event->state & GDK_CONTROL_MASK)
1067 if ((key >= 'A') && (key <= 'Z'))
1070 if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1072 (* control_keys[key - 'a']) (editable, event->time);
1077 else if (event->state & GDK_MOD1_MASK)
1079 if ((key >= 'A') && (key <= 'Z'))
1082 if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1084 (* alt_keys[key - 'a']) (editable, event->time);
1090 gtk_im_context_filter_keypress (entry->im_context, event);
1095 /* since we emit signals from within the above code,
1096 * the widget might already be destroyed or at least
1099 if (GTK_WIDGET_REALIZED (editable) &&
1100 return_val && (editable->current_pos != initial_pos))
1102 if (extend_selection)
1104 if (editable->current_pos < editable->selection_start_pos)
1105 editable->selection_start_pos = editable->current_pos;
1106 else if (editable->current_pos > editable->selection_end_pos)
1107 editable->selection_end_pos = editable->current_pos;
1111 editable->selection_start_pos = editable->current_pos;
1113 editable->selection_end_pos = editable->current_pos;
1118 editable->selection_start_pos = 0;
1119 editable->selection_end_pos = 0;
1122 gtk_editable_claim_selection (editable,
1123 editable->selection_start_pos != editable->selection_end_pos,
1126 entry_adjust_scroll (entry);
1127 gtk_entry_queue_draw (entry);
1134 gtk_entry_focus_in (GtkWidget *widget,
1135 GdkEventFocus *event)
1137 g_return_val_if_fail (widget != NULL, FALSE);
1138 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1139 g_return_val_if_fail (event != NULL, FALSE);
1141 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1142 gtk_widget_draw_focus (widget);
1143 gtk_entry_queue_draw (GTK_ENTRY (widget));
1145 gtk_im_context_focus_in (GTK_ENTRY (widget)->im_context);
1151 gtk_entry_focus_out (GtkWidget *widget,
1152 GdkEventFocus *event)
1154 g_return_val_if_fail (widget != NULL, FALSE);
1155 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1156 g_return_val_if_fail (event != NULL, FALSE);
1158 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1159 gtk_widget_draw_focus (widget);
1160 gtk_entry_queue_draw (GTK_ENTRY (widget));
1162 gtk_im_context_focus_out (GTK_ENTRY (widget)->im_context);
1168 gtk_entry_ensure_layout (GtkEntry *entry)
1170 GtkWidget *widget = GTK_WIDGET (entry);
1172 PangoAttrList *attrs;
1176 entry->layout = gtk_widget_create_pango_layout (widget);
1177 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1182 gtk_entry_draw_text (GtkEntry *entry)
1185 PangoLayoutLine *line;
1186 GtkEditable *editable = GTK_EDITABLE (entry);
1188 g_return_if_fail (entry != NULL);
1189 g_return_if_fail (GTK_IS_ENTRY (entry));
1191 if (GTK_WIDGET_DRAWABLE (entry))
1193 PangoRectangle logical_rect;
1196 gdk_window_get_size (entry->text_area, NULL, &area_height);
1197 area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER);
1199 widget = GTK_WIDGET (entry);
1201 gtk_entry_ensure_layout (entry);
1203 line = pango_layout_get_lines (entry->layout)->data;
1204 pango_layout_line_get_extents (line, NULL, &logical_rect);
1206 gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
1207 INNER_BORDER - entry->scroll_offset,
1208 INNER_BORDER + ((area_height - logical_rect.height) / 2 +
1209 entry->ascent + logical_rect.y) / PANGO_SCALE,
1212 if (editable->selection_start_pos != editable->selection_end_pos)
1216 gint start_index = unicode_offset_to_index (entry->text,
1217 MIN (editable->selection_start_pos, editable->selection_end_pos));
1218 gint end_index = unicode_offset_to_index (entry->text,
1219 MAX (editable->selection_start_pos, editable->selection_end_pos));
1220 GtkStateType selected_state = editable->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
1221 GdkRegion *clip_region = gdk_region_new ();
1223 pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges);
1225 for (i=0; i < n_ranges; i++)
1229 rect.x = INNER_BORDER - entry->scroll_offset + ranges[2*i] / PANGO_SCALE;
1230 rect.y = INNER_BORDER + (entry->ascent + logical_rect.y) / PANGO_SCALE;
1231 rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE;
1232 rect.height = logical_rect.height / PANGO_SCALE;
1234 gdk_draw_rectangle (entry->text_area, widget->style->bg_gc [selected_state], TRUE,
1235 rect.x, rect.y, rect.width, rect.height);
1237 gdk_region_union_with_rect (clip_region, &rect);
1240 gdk_gc_set_clip_region (widget->style->fg_gc [selected_state], clip_region);
1241 gdk_draw_layout (entry->text_area, widget->style->fg_gc [selected_state],
1242 INNER_BORDER - entry->scroll_offset,
1243 INNER_BORDER + ((area_height - logical_rect.height) / 2 +
1244 entry->ascent + logical_rect.y) / PANGO_SCALE,
1246 gdk_gc_set_clip_region (widget->style->fg_gc [selected_state], NULL);
1248 gdk_region_destroy (clip_region);
1255 gtk_entry_draw_cursor (GtkEntry *entry)
1257 g_return_if_fail (entry != NULL);
1258 g_return_if_fail (GTK_IS_ENTRY (entry));
1260 if (GTK_WIDGET_DRAWABLE (entry))
1262 GtkWidget *widget = GTK_WIDGET (entry);
1263 GtkEditable *editable = GTK_EDITABLE (entry);
1265 if (GTK_WIDGET_HAS_FOCUS (widget) &&
1266 (editable->selection_start_pos == editable->selection_end_pos))
1268 gint xoffset = INNER_BORDER - entry->scroll_offset;
1269 gint strong_x, weak_x;
1270 gint text_area_height;
1272 gdk_window_get_size (entry->text_area, NULL, &text_area_height);
1274 gtk_entry_get_cursor_locations (entry, &strong_x, &weak_x);
1276 gdk_draw_line (entry->text_area, widget->style->bg_gc[GTK_STATE_SELECTED],
1277 xoffset + strong_x, INNER_BORDER,
1278 xoffset + strong_x, text_area_height - INNER_BORDER);
1280 if (weak_x != strong_x)
1281 gdk_draw_line (entry->text_area, widget->style->fg_gc[GTK_STATE_NORMAL],
1282 xoffset + weak_x, INNER_BORDER,
1283 xoffset + weak_x, text_area_height - INNER_BORDER);
1290 gtk_entry_queue_draw (GtkEntry *entry)
1292 g_return_if_fail (entry != NULL);
1293 g_return_if_fail (GTK_IS_ENTRY (entry));
1295 if (GTK_WIDGET_REALIZED (entry))
1297 GdkRectangle rect = { 0 };
1299 gdk_window_get_size (entry->text_area, &rect.width, &rect.height);
1300 gdk_window_invalidate_rect (entry->text_area, &rect, 0);
1306 gtk_entry_timer (gpointer data)
1310 GDK_THREADS_ENTER ();
1312 entry = GTK_ENTRY (data);
1315 GDK_THREADS_LEAVE ();
1322 gtk_entry_find_position (GtkEntry *entry,
1325 PangoLayoutLine *line;
1329 gtk_entry_ensure_layout (entry);
1331 line = pango_layout_get_lines (entry->layout)->data;
1332 pango_layout_line_x_to_index (line, x * PANGO_SCALE, &index, &trailing);
1335 index = unicode_next_utf8 (entry->text + index) - entry->text;
1341 gtk_entry_get_cursor_locations (GtkEntry *entry,
1345 GtkEditable *editable = GTK_EDITABLE (entry);
1348 PangoRectangle strong_pos, weak_pos;
1350 gtk_entry_ensure_layout (entry);
1352 index = unicode_offset_to_index (entry->text, editable->current_pos);
1353 pango_layout_get_cursor_pos (entry->layout, index, &strong_pos, &weak_pos);
1356 *strong_x = strong_pos.x / PANGO_SCALE;
1359 *weak_x = weak_pos.x / PANGO_SCALE;
1363 entry_adjust_scroll (GtkEntry *entry)
1366 gint min_offset, max_offset;
1367 gint text_area_width;
1368 gint strong_x, weak_x;
1369 gint strong_xoffset, weak_xoffset;
1370 PangoLayoutLine *line;
1371 PangoRectangle logical_rect;
1373 g_return_if_fail (entry != NULL);
1374 g_return_if_fail (GTK_IS_ENTRY (entry));
1376 widget = GTK_WIDGET (entry);
1377 text_area_width = widget->allocation.width - 2 * (widget->style->klass->xthickness + INNER_BORDER);
1382 line = pango_layout_get_lines (entry->layout)->data;
1384 /* Display as much text as we can */
1386 pango_layout_line_get_extents (line, NULL, &logical_rect);
1388 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1391 max_offset = MAX (min_offset, logical_rect.width / PANGO_SCALE - text_area_width);
1395 max_offset = logical_rect.width / PANGO_SCALE - text_area_width;
1396 min_offset = MIN (0, max_offset);
1399 entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset);
1401 /* And make sure cursors are on screen. Note that the cursor is
1402 * actually drawn one pixel into the INNER_BORDER space on
1403 * the right, when the scroll is at the utmost right. This
1404 * looks better to to me than confining the cursor inside the
1405 * border entirely, though it means that the cursor gets one
1406 * pixel closer to the the edge of the widget on the right than
1407 * on the left. This might need changing if one changed
1408 * INNER_BORDER from 2 to 1, as one would do on a
1409 * small-screen-real-estate display.
1411 * We always make sure that the strong cursor is on screen, and
1412 * put the weak cursor on screen if possible.
1415 gtk_entry_get_cursor_locations (entry, &strong_x, &weak_x);
1417 strong_xoffset = strong_x - entry->scroll_offset;
1419 if (strong_xoffset < 0)
1421 entry->scroll_offset += strong_xoffset;
1424 else if (strong_xoffset > text_area_width)
1426 entry->scroll_offset += strong_xoffset - text_area_width;
1427 strong_xoffset = text_area_width;
1430 weak_xoffset = weak_x - entry->scroll_offset;
1432 if (weak_xoffset < 0 && strong_xoffset - weak_xoffset <= text_area_width)
1434 entry->scroll_offset += weak_xoffset;
1436 else if (weak_xoffset > text_area_width &&
1437 strong_xoffset - (weak_xoffset - text_area_width) >= 0)
1439 entry->scroll_offset += weak_xoffset - text_area_width;
1442 gtk_widget_queue_draw (GTK_WIDGET (entry));
1446 gtk_entry_insert_text (GtkEditable *editable,
1447 const gchar *new_text,
1448 gint new_text_length,
1456 g_return_if_fail (editable != NULL);
1457 g_return_if_fail (GTK_IS_ENTRY (editable));
1458 g_return_if_fail (position != NULL);
1459 g_return_if_fail (*position >= 0 || *position < GTK_ENTRY (editable)->text_size);
1461 entry = GTK_ENTRY (editable);
1462 widget = GTK_WIDGET (editable);
1464 if (new_text_length < 0)
1465 new_text_length = strlen (new_text);
1467 n_chars = unicode_strlen (new_text, new_text_length);
1468 if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
1471 n_chars = entry->text_max_length - entry->text_length;
1474 if (new_text_length + entry->n_bytes + 1 > entry->text_size)
1476 while (new_text_length + entry->n_bytes + 1 > entry->text_size)
1478 if (entry->text_size == 0)
1479 entry->text_size = MIN_SIZE;
1482 if (2 * (guint)entry->text_size < MAX_SIZE &&
1483 2 * (guint)entry->text_size > entry->text_size)
1484 entry->text_size *= 2;
1487 entry->text_size = MAX_SIZE;
1488 new_text_length = entry->text_size - new_text_length - 1;
1494 entry->text = g_realloc (entry->text, entry->text_size);
1497 index = unicode_offset_to_index (entry->text, *position);
1499 g_memmove (entry->text + index + new_text_length, entry->text + index, entry->n_bytes - index);
1500 memcpy (entry->text + index, new_text, new_text_length);
1502 entry->n_bytes += new_text_length;
1503 entry->text_length += n_chars;
1505 /* NUL terminate for safety and convenience */
1506 entry->text[entry->n_bytes] = '\0';
1508 if (editable->current_pos > *position)
1509 editable->current_pos += n_chars;
1511 if (editable->selection_start_pos > *position)
1512 editable->selection_start_pos += n_chars;
1514 if (editable->selection_end_pos > *position)
1515 editable->selection_end_pos += n_chars;
1517 *position += n_chars;
1520 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1522 gtk_entry_queue_draw (entry);
1526 gtk_entry_delete_text (GtkEditable *editable,
1532 g_return_if_fail (editable != NULL);
1533 g_return_if_fail (GTK_IS_ENTRY (editable));
1535 entry = GTK_ENTRY (editable);
1538 end_pos = entry->text_length;
1540 if ((start_pos < end_pos) &&
1542 (end_pos <= entry->text_length))
1544 gint start_index = unicode_offset_to_index (entry->text, start_pos);
1545 gint end_index = unicode_offset_to_index (entry->text, end_pos);
1547 g_memmove (entry->text + start_index, entry->text + end_index, entry->n_bytes - end_index);
1548 entry->text_length -= (end_pos - start_pos);
1549 entry->n_bytes -= (end_index - start_index);
1551 if (editable->current_pos > start_pos)
1552 editable->current_pos -= MIN (editable->current_pos, end_pos) - start_pos;
1554 if (editable->selection_start_pos > start_pos)
1555 editable->selection_start_pos -= MIN (editable->selection_start_pos, end_pos) - start_pos;
1557 if (editable->selection_end_pos > start_pos)
1558 editable->selection_end_pos -= MIN (editable->selection_end_pos, end_pos) - start_pos;
1562 gtk_entry_queue_draw (entry);
1565 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1569 gtk_entry_update_text (GtkEditable *editable,
1573 GtkEntry *entry = GTK_ENTRY (editable);
1575 gtk_entry_queue_draw (entry);
1579 gtk_entry_get_chars (GtkEditable *editable,
1584 gint start_index, end_index;
1586 g_return_val_if_fail (editable != NULL, NULL);
1587 g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL);
1589 entry = GTK_ENTRY (editable);
1592 end_pos = entry->text_length;
1594 start_pos = MIN (entry->text_length, start_pos);
1595 end_pos = MIN (entry->text_length, end_pos);
1597 start_index = unicode_offset_to_index (entry->text, start_pos);
1598 end_index = unicode_offset_to_index (entry->text, end_pos);
1600 return g_strndup (entry->text + start_index, end_index - start_index);
1604 gtk_entry_move_cursor (GtkEditable *editable,
1611 entry = GTK_ENTRY (editable);
1613 index = unicode_offset_to_index (entry->text, editable->current_pos);
1615 /* Horizontal motion */
1617 if ((gint)editable->current_pos < -x)
1618 editable->current_pos = 0;
1619 else if (editable->current_pos + x > entry->text_length)
1620 editable->current_pos = entry->text_length;
1622 editable->current_pos += x;
1624 /* Ignore vertical motion */
1628 gtk_entry_move_cursor_visually (GtkEditable *editable,
1634 entry = GTK_ENTRY (editable);
1636 index = unicode_offset_to_index (entry->text, editable->current_pos);
1638 gtk_entry_ensure_layout (entry);
1642 int new_index, new_trailing;
1646 pango_layout_move_cursor_visually (entry->layout, index, 0, 1, &new_index, &new_trailing);
1651 pango_layout_move_cursor_visually (entry->layout, index, 0, -1, &new_index, &new_trailing);
1655 if (new_index < 0 || new_index == G_MAXINT)
1659 index = unicode_next_utf8 (entry->text + new_index) - entry->text;
1664 editable->current_pos = unicode_index_to_offset (entry->text, index);
1668 gtk_move_forward_character (GtkEntry *entry)
1670 gtk_entry_move_cursor_visually (GTK_EDITABLE (entry), 1);
1674 gtk_move_backward_character (GtkEntry *entry)
1676 gtk_entry_move_cursor_visually (GTK_EDITABLE (entry), -1);
1680 gtk_entry_move_word (GtkEditable *editable,
1684 gtk_move_forward_word (GTK_ENTRY (editable));
1686 gtk_move_backward_word (GTK_ENTRY (editable));
1690 gtk_move_forward_word (GtkEntry *entry)
1692 GtkEditable *editable;
1695 editable = GTK_EDITABLE (entry);
1697 /* Prevent any leak of information */
1698 if (!editable->visible)
1700 editable->current_pos = entry->text_length;
1704 if (entry->text && (editable->current_pos < entry->text_length))
1706 PangoLogAttr *log_attrs;
1707 gint n_attrs, old_pos;
1709 gtk_entry_ensure_layout (entry);
1710 pango_layout_get_log_attrs (entry->layout, &log_attrs, &n_attrs);
1712 i = old_pos = editable->current_pos;
1714 /* Advance over white space */
1715 while (i < n_attrs && log_attrs[i].is_white)
1718 /* Find the next word beginning */
1720 while (i < n_attrs && !log_attrs[i].is_word_stop)
1723 editable->current_pos = MAX (entry->text_length, i);
1725 /* Back up over white space */
1726 while (i > 0 && log_attrs[i - 1].is_white)
1730 editable->current_pos = i;
1737 gtk_move_backward_word (GtkEntry *entry)
1739 GtkEditable *editable;
1742 editable = GTK_EDITABLE (entry);
1744 /* Prevent any leak of information */
1745 if (!editable->visible)
1747 editable->current_pos = 0;
1751 if (entry->text && editable->current_pos > 0)
1753 PangoLogAttr *log_attrs;
1756 gtk_entry_ensure_layout (entry);
1757 pango_layout_get_log_attrs (entry->layout, &log_attrs, &n_attrs);
1759 i = editable->current_pos - 1;
1761 /* Find the previous word beginning */
1762 while (i > 0 && !log_attrs[i].is_word_stop)
1770 gtk_entry_move_to_column (GtkEditable *editable, gint column)
1774 entry = GTK_ENTRY (editable);
1776 if (column < 0 || column > entry->text_length)
1777 editable->current_pos = entry->text_length;
1779 editable->current_pos = column;
1783 gtk_move_beginning_of_line (GtkEntry *entry)
1785 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
1789 gtk_move_end_of_line (GtkEntry *entry)
1791 gtk_entry_move_to_column (GTK_EDITABLE (entry), -1);
1795 gtk_entry_kill_char (GtkEditable *editable,
1798 if (editable->selection_start_pos != editable->selection_end_pos)
1799 gtk_editable_delete_selection (editable);
1802 gint old_pos = editable->current_pos;
1805 gtk_entry_move_cursor (editable, 1, 0);
1806 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1810 gtk_entry_move_cursor (editable, -1, 0);
1811 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1817 gtk_delete_forward_character (GtkEntry *entry)
1819 gtk_entry_kill_char (GTK_EDITABLE (entry), 1);
1823 gtk_delete_backward_character (GtkEntry *entry)
1825 gtk_entry_kill_char (GTK_EDITABLE (entry), -1);
1829 gtk_entry_kill_word (GtkEditable *editable,
1832 if (editable->selection_start_pos != editable->selection_end_pos)
1833 gtk_editable_delete_selection (editable);
1836 gint old_pos = editable->current_pos;
1839 gtk_entry_move_word (editable, 1);
1840 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1844 gtk_entry_move_word (editable, -1);
1845 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1851 gtk_delete_forward_word (GtkEntry *entry)
1853 gtk_entry_kill_word (GTK_EDITABLE (entry), 1);
1857 gtk_delete_backward_word (GtkEntry *entry)
1859 gtk_entry_kill_word (GTK_EDITABLE (entry), -1);
1863 gtk_entry_kill_line (GtkEditable *editable,
1866 gint old_pos = editable->current_pos;
1869 gtk_entry_move_to_column (editable, -1);
1870 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1874 gtk_entry_move_to_column (editable, 0);
1875 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1880 gtk_delete_line (GtkEntry *entry)
1882 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
1883 gtk_entry_kill_line (GTK_EDITABLE (entry), 1);
1887 gtk_delete_to_line_end (GtkEntry *entry)
1889 gtk_editable_delete_text (GTK_EDITABLE(entry), GTK_EDITABLE(entry)->current_pos, entry->text_length);
1893 gtk_select_word (GtkEntry *entry,
1896 GtkEditable *editable;
1900 editable = GTK_EDITABLE (entry);
1902 gtk_move_backward_word (entry);
1903 start_pos = editable->current_pos;
1905 gtk_move_forward_word (entry);
1906 end_pos = editable->current_pos;
1908 editable->has_selection = TRUE;
1909 gtk_entry_set_selection (editable, start_pos, end_pos);
1910 gtk_editable_claim_selection (editable, start_pos != end_pos, time);
1914 gtk_select_line (GtkEntry *entry,
1917 GtkEditable *editable;
1919 editable = GTK_EDITABLE (entry);
1921 editable->has_selection = TRUE;
1922 gtk_entry_set_selection (editable, 0, entry->text_length);
1923 gtk_editable_claim_selection (editable, entry->text_length != 0, time);
1925 editable->current_pos = editable->selection_end_pos;
1929 gtk_entry_set_selection (GtkEditable *editable,
1935 g_return_if_fail (editable != NULL);
1936 g_return_if_fail (GTK_IS_ENTRY (editable));
1938 entry = GTK_ENTRY (editable);
1941 end = GTK_ENTRY (editable)->text_length;
1943 editable->selection_start_pos = start;
1944 editable->selection_end_pos = end;
1946 gtk_entry_queue_draw (GTK_ENTRY (editable));
1950 gtk_entry_select_region (GtkEntry *entry,
1954 gtk_editable_select_region (GTK_EDITABLE (entry), start, end);
1958 gtk_entry_set_max_length (GtkEntry *entry,
1961 g_return_if_fail (entry != NULL);
1962 g_return_if_fail (GTK_IS_ENTRY (entry));
1964 if (max && entry->text_length > max)
1965 gtk_editable_delete_text (GTK_EDITABLE(entry), max, -1);
1967 entry->text_max_length = max;
1972 gtk_entry_style_set (GtkWidget *widget,
1973 GtkStyle *previous_style)
1977 g_return_if_fail (widget != NULL);
1978 g_return_if_fail (GTK_IS_ENTRY (widget));
1980 if (previous_style && GTK_WIDGET_REALIZED (widget))
1982 entry = GTK_ENTRY (widget);
1984 entry_adjust_scroll (entry);
1986 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
1987 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
1992 gtk_entry_state_changed (GtkWidget *widget,
1993 GtkStateType previous_state)
1995 g_return_if_fail (widget != NULL);
1996 g_return_if_fail (GTK_IS_ENTRY (widget));
1998 if (GTK_WIDGET_REALIZED (widget))
2000 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2001 gdk_window_set_background (GTK_ENTRY (widget)->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2004 if (GTK_WIDGET_DRAWABLE (widget))
2005 gtk_widget_queue_clear(widget);
2009 gtk_entry_commit_cb (GtkIMContext *context,
2013 GtkEditable *editable = GTK_EDITABLE (entry);
2014 gint tmp_pos = editable->current_pos;
2016 gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
2017 editable->current_pos = tmp_pos;