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>
39 #include <glib-object.h>
41 #define MIN_ENTRY_WIDTH 150
42 #define DRAW_TIMEOUT 20
43 #define INNER_BORDER 2
45 /* Initial size of buffer, in bytes */
48 /* Maximum size of text buffer, in bytes */
49 #define MAX_SIZE G_MAXUSHORT
58 static void gtk_entry_class_init (GtkEntryClass *klass);
59 static void gtk_entry_init (GtkEntry *entry);
60 static void gtk_entry_set_arg (GtkObject *object,
63 static void gtk_entry_get_arg (GtkObject *object,
66 static void gtk_entry_finalize (GObject *object);
67 static void gtk_entry_realize (GtkWidget *widget);
68 static void gtk_entry_unrealize (GtkWidget *widget);
69 static void gtk_entry_draw_focus (GtkWidget *widget);
70 static void gtk_entry_size_request (GtkWidget *widget,
71 GtkRequisition *requisition);
72 static void gtk_entry_size_allocate (GtkWidget *widget,
73 GtkAllocation *allocation);
74 static void gtk_entry_draw (GtkWidget *widget,
76 static gint gtk_entry_expose (GtkWidget *widget,
77 GdkEventExpose *event);
78 static gint gtk_entry_button_press (GtkWidget *widget,
79 GdkEventButton *event);
80 static gint gtk_entry_button_release (GtkWidget *widget,
81 GdkEventButton *event);
82 static gint gtk_entry_motion_notify (GtkWidget *widget,
83 GdkEventMotion *event);
84 static gint gtk_entry_key_press (GtkWidget *widget,
86 static gint gtk_entry_focus_in (GtkWidget *widget,
87 GdkEventFocus *event);
88 static gint gtk_entry_focus_out (GtkWidget *widget,
89 GdkEventFocus *event);
90 static void gtk_entry_draw_text (GtkEntry *entry);
91 static void gtk_entry_ensure_layout (GtkEntry *entry);
92 static void gtk_entry_draw_cursor (GtkEntry *entry);
93 static void gtk_entry_style_set (GtkWidget *widget,
94 GtkStyle *previous_style);
95 static void gtk_entry_state_changed (GtkWidget *widget,
96 GtkStateType previous_state);
97 static void gtk_entry_queue_draw (GtkEntry *entry);
98 static gint gtk_entry_find_position (GtkEntry *entry,
100 static void gtk_entry_get_cursor_locations (GtkEntry *entry,
103 static void entry_adjust_scroll (GtkEntry *entry);
104 static void gtk_entry_insert_text (GtkEditable *editable,
105 const gchar *new_text,
106 gint new_text_length,
108 static void gtk_entry_delete_text (GtkEditable *editable,
111 static void gtk_entry_update_text (GtkEditable *editable,
114 static gchar * gtk_entry_get_chars (GtkEditable *editable,
121 /* Binding actions */
122 static void gtk_entry_move_cursor (GtkEditable *editable,
125 static void gtk_entry_move_word (GtkEditable *editable,
127 static void gtk_entry_move_to_column (GtkEditable *editable,
129 static void gtk_entry_kill_char (GtkEditable *editable,
131 static void gtk_entry_kill_word (GtkEditable *editable,
133 static void gtk_entry_kill_line (GtkEditable *editable,
137 static void gtk_move_forward_character (GtkEntry *entry);
138 static void gtk_move_backward_character (GtkEntry *entry);
139 static void gtk_move_forward_word (GtkEntry *entry);
140 static void gtk_move_backward_word (GtkEntry *entry);
141 static void gtk_move_beginning_of_line (GtkEntry *entry);
142 static void gtk_move_end_of_line (GtkEntry *entry);
143 static void gtk_delete_forward_character (GtkEntry *entry);
144 static void gtk_delete_backward_character (GtkEntry *entry);
145 static void gtk_delete_forward_word (GtkEntry *entry);
146 static void gtk_delete_backward_word (GtkEntry *entry);
147 static void gtk_delete_line (GtkEntry *entry);
148 static void gtk_delete_to_line_end (GtkEntry *entry);
149 static void gtk_select_word (GtkEntry *entry,
151 static void gtk_select_line (GtkEntry *entry,
155 static void gtk_entry_set_selection (GtkEditable *editable,
159 static void gtk_entry_set_position_from_editable (GtkEditable *editable,
162 static void gtk_entry_commit_cb (GtkIMContext *context,
167 static GtkWidgetClass *parent_class = NULL;
168 static GdkAtom ctext_atom = GDK_NONE;
170 static const GtkTextFunction control_keys[26] =
172 (GtkTextFunction)gtk_move_beginning_of_line, /* a */
173 (GtkTextFunction)gtk_move_backward_character, /* b */
174 (GtkTextFunction)gtk_editable_copy_clipboard, /* c */
175 (GtkTextFunction)gtk_delete_forward_character, /* d */
176 (GtkTextFunction)gtk_move_end_of_line, /* e */
177 (GtkTextFunction)gtk_move_forward_character, /* f */
179 (GtkTextFunction)gtk_delete_backward_character, /* h */
182 (GtkTextFunction)gtk_delete_to_line_end, /* k */
192 (GtkTextFunction)gtk_delete_line, /* u */
193 (GtkTextFunction)gtk_editable_paste_clipboard, /* v */
194 (GtkTextFunction)gtk_delete_backward_word, /* w */
195 (GtkTextFunction)gtk_editable_cut_clipboard, /* x */
200 static const GtkTextFunction alt_keys[26] =
203 (GtkTextFunction)gtk_move_backward_word, /* b */
205 (GtkTextFunction)gtk_delete_forward_word, /* d */
207 (GtkTextFunction)gtk_move_forward_word, /* f */
232 gtk_entry_get_type (void)
234 static GtkType entry_type = 0;
238 static const GtkTypeInfo entry_info =
242 sizeof (GtkEntryClass),
243 (GtkClassInitFunc) gtk_entry_class_init,
244 (GtkObjectInitFunc) gtk_entry_init,
245 /* reserved_1 */ NULL,
246 /* reserved_2 */ NULL,
247 (GtkClassInitFunc) NULL,
250 entry_type = gtk_type_unique (GTK_TYPE_EDITABLE, &entry_info);
257 gtk_entry_class_init (GtkEntryClass *class)
259 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
260 GtkObjectClass *object_class;
261 GtkWidgetClass *widget_class;
262 GtkEditableClass *editable_class;
264 object_class = (GtkObjectClass*) class;
265 widget_class = (GtkWidgetClass*) class;
266 editable_class = (GtkEditableClass*) class;
267 parent_class = gtk_type_class (GTK_TYPE_EDITABLE);
269 gobject_class->finalize = gtk_entry_finalize;
271 gtk_object_add_arg_type ("GtkEntry::max_length", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MAX_LENGTH);
272 gtk_object_add_arg_type ("GtkEntry::visibility", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBILITY);
274 object_class->set_arg = gtk_entry_set_arg;
275 object_class->get_arg = gtk_entry_get_arg;
277 widget_class->realize = gtk_entry_realize;
278 widget_class->unrealize = gtk_entry_unrealize;
279 widget_class->draw_focus = gtk_entry_draw_focus;
280 widget_class->size_request = gtk_entry_size_request;
281 widget_class->size_allocate = gtk_entry_size_allocate;
282 widget_class->draw = gtk_entry_draw;
283 widget_class->expose_event = gtk_entry_expose;
284 widget_class->button_press_event = gtk_entry_button_press;
285 widget_class->button_release_event = gtk_entry_button_release;
286 widget_class->motion_notify_event = gtk_entry_motion_notify;
287 widget_class->key_press_event = gtk_entry_key_press;
288 widget_class->focus_in_event = gtk_entry_focus_in;
289 widget_class->focus_out_event = gtk_entry_focus_out;
290 widget_class->style_set = gtk_entry_style_set;
291 widget_class->state_changed = gtk_entry_state_changed;
293 editable_class->insert_text = gtk_entry_insert_text;
294 editable_class->delete_text = gtk_entry_delete_text;
295 editable_class->changed = (void (*)(GtkEditable *)) entry_adjust_scroll;
297 editable_class->move_cursor = gtk_entry_move_cursor;
298 editable_class->move_word = gtk_entry_move_word;
299 editable_class->move_to_column = gtk_entry_move_to_column;
301 editable_class->kill_char = gtk_entry_kill_char;
302 editable_class->kill_word = gtk_entry_kill_word;
303 editable_class->kill_line = gtk_entry_kill_line;
305 editable_class->update_text = gtk_entry_update_text;
306 editable_class->get_chars = gtk_entry_get_chars;
307 editable_class->set_selection = gtk_entry_set_selection;
308 editable_class->set_position = gtk_entry_set_position_from_editable;
312 gtk_entry_set_arg (GtkObject *object,
318 entry = GTK_ENTRY (object);
323 gtk_entry_set_max_length (entry, GTK_VALUE_UINT (*arg));
326 gtk_entry_set_visibility (entry, GTK_VALUE_BOOL (*arg));
334 gtk_entry_get_arg (GtkObject *object,
340 entry = GTK_ENTRY (object);
345 GTK_VALUE_UINT (*arg) = entry->text_max_length;
348 GTK_VALUE_BOOL (*arg) = GTK_EDITABLE (entry)->visible;
351 arg->type = GTK_TYPE_INVALID;
357 gtk_entry_init (GtkEntry *entry)
359 GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
361 entry->text_area = NULL;
363 entry->text_size = MIN_SIZE;
364 entry->text = g_malloc (entry->text_size);
365 entry->text[0] = '\0';
367 entry->text_length = 0;
368 entry->text_max_length = 0;
370 entry->scroll_offset = 0;
375 /* This object is completely private. No external entity can gain a reference
376 * to it; so we create it here and destroy it in finalize().
378 entry->im_context = gtk_im_multicontext_new ();
380 gtk_signal_connect (GTK_OBJECT (entry->im_context), "commit",
381 GTK_SIGNAL_FUNC (gtk_entry_commit_cb), entry);
387 return GTK_WIDGET (gtk_type_new (GTK_TYPE_ENTRY));
391 gtk_entry_new_with_max_length (guint16 max)
395 entry = gtk_type_new (GTK_TYPE_ENTRY);
396 entry->text_max_length = max;
398 return GTK_WIDGET (entry);
402 gtk_entry_set_text (GtkEntry *entry,
407 GtkEditable *editable;
409 g_return_if_fail (entry != NULL);
410 g_return_if_fail (GTK_IS_ENTRY (entry));
411 g_return_if_fail (text != NULL);
413 editable = GTK_EDITABLE (entry);
415 gtk_entry_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
418 gtk_editable_insert_text (editable, text, strlen (text), &tmp_pos);
419 editable->current_pos = tmp_pos;
423 gtk_entry_append_text (GtkEntry *entry,
428 g_return_if_fail (entry != NULL);
429 g_return_if_fail (GTK_IS_ENTRY (entry));
430 g_return_if_fail (text != NULL);
432 tmp_pos = entry->text_length;
433 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
437 gtk_entry_prepend_text (GtkEntry *entry,
442 g_return_if_fail (entry != NULL);
443 g_return_if_fail (GTK_IS_ENTRY (entry));
444 g_return_if_fail (text != NULL);
447 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
451 gtk_entry_set_position (GtkEntry *entry,
454 g_return_if_fail (entry != NULL);
455 g_return_if_fail (GTK_IS_ENTRY (entry));
457 if ((position == -1) || (position > entry->text_length))
458 GTK_EDITABLE(entry)->current_pos = entry->text_length;
460 GTK_EDITABLE(entry)->current_pos = position;
461 entry_adjust_scroll (entry);
465 gtk_entry_set_position_from_editable (GtkEditable *editable,
468 gtk_entry_set_position (GTK_ENTRY (editable), position);
472 gtk_entry_set_visibility (GtkEntry *entry,
475 g_return_if_fail (entry != NULL);
476 g_return_if_fail (GTK_IS_ENTRY (entry));
478 GTK_EDITABLE (entry)->visible = visible ? TRUE : FALSE;
480 gtk_entry_queue_draw (entry);
484 gtk_entry_set_editable(GtkEntry *entry,
487 g_return_if_fail (entry != NULL);
488 g_return_if_fail (GTK_IS_ENTRY (entry));
490 gtk_editable_set_editable (GTK_EDITABLE (entry), editable);
494 gtk_entry_get_text (GtkEntry *entry)
496 g_return_val_if_fail (entry != NULL, NULL);
497 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
503 gtk_entry_finalize (GObject *object)
507 g_return_if_fail (GTK_IS_ENTRY (object));
509 entry = GTK_ENTRY (object);
512 g_object_unref (G_OBJECT (entry->layout));
514 gtk_object_unref (GTK_OBJECT (entry->im_context));
517 gtk_timeout_remove (entry->timer);
519 entry->text_size = 0;
522 g_free (entry->text);
525 G_OBJECT_CLASS (parent_class)->finalize (object);
529 gtk_entry_realize (GtkWidget *widget)
532 GtkEditable *editable;
533 GtkRequisition requisition;
534 GdkWindowAttr attributes;
535 gint attributes_mask;
537 g_return_if_fail (widget != NULL);
538 g_return_if_fail (GTK_IS_ENTRY (widget));
540 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
541 entry = GTK_ENTRY (widget);
542 editable = GTK_EDITABLE (widget);
544 gtk_widget_get_child_requisition (widget, &requisition);
546 attributes.window_type = GDK_WINDOW_CHILD;
547 attributes.x = widget->allocation.x;
548 attributes.y = widget->allocation.y + (widget->allocation.height -
549 requisition.height) / 2;
550 attributes.width = widget->allocation.width;
551 attributes.height = requisition.height;
552 attributes.wclass = GDK_INPUT_OUTPUT;
553 attributes.visual = gtk_widget_get_visual (widget);
554 attributes.colormap = gtk_widget_get_colormap (widget);
555 attributes.event_mask = gtk_widget_get_events (widget);
556 attributes.event_mask |= (GDK_EXPOSURE_MASK |
557 GDK_BUTTON_PRESS_MASK |
558 GDK_BUTTON_RELEASE_MASK |
559 GDK_BUTTON1_MOTION_MASK |
560 GDK_BUTTON3_MOTION_MASK |
561 GDK_POINTER_MOTION_HINT_MASK |
562 GDK_ENTER_NOTIFY_MASK |
563 GDK_LEAVE_NOTIFY_MASK |
565 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
567 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
568 gdk_window_set_user_data (widget->window, entry);
570 attributes.x = widget->style->xthickness;
571 attributes.y = widget->style->ythickness;
572 attributes.width = widget->allocation.width - attributes.x * 2;
573 attributes.height = requisition.height - attributes.y * 2;
574 attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
575 attributes_mask |= GDK_WA_CURSOR;
577 entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
578 gdk_window_set_user_data (entry->text_area, entry);
580 widget->style = gtk_style_attach (widget->style, widget->window);
582 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
583 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
585 gdk_window_show (entry->text_area);
587 if (editable->selection_start_pos != editable->selection_end_pos)
588 gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
590 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
594 gtk_entry_unrealize (GtkWidget *widget)
598 g_return_if_fail (widget != NULL);
599 g_return_if_fail (GTK_IS_ENTRY (widget));
601 entry = GTK_ENTRY (widget);
603 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
605 if (entry->text_area)
607 gdk_window_set_user_data (entry->text_area, NULL);
608 gdk_window_destroy (entry->text_area);
609 entry->text_area = NULL;
610 gdk_cursor_destroy (entry->cursor);
611 entry->cursor = NULL;
614 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
615 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
619 gtk_entry_draw_focus (GtkWidget *widget)
624 g_return_if_fail (widget != NULL);
625 g_return_if_fail (GTK_IS_ENTRY (widget));
627 if (GTK_WIDGET_DRAWABLE (widget))
631 gdk_window_get_size (widget->window, &width, &height);
633 if (GTK_WIDGET_HAS_FOCUS (widget))
641 gtk_paint_shadow (widget->style, widget->window,
642 GTK_STATE_NORMAL, GTK_SHADOW_IN,
643 NULL, widget, "entry",
644 x, y, width, height);
646 if (GTK_WIDGET_HAS_FOCUS (widget))
648 gdk_window_get_size (widget->window, &width, &height);
649 gtk_paint_focus (widget->style, widget->window,
650 NULL, widget, "entry",
651 0, 0, width - 1, height - 1);
657 gtk_entry_size_request (GtkWidget *widget,
658 GtkRequisition *requisition)
661 PangoFontMetrics metrics;
665 g_return_if_fail (widget != NULL);
666 g_return_if_fail (GTK_IS_ENTRY (widget));
667 g_return_if_fail (requisition != NULL);
669 entry = GTK_ENTRY (widget);
671 /* We do this to deal with direction changes - should that be a signal?
675 g_object_unref (G_OBJECT (entry->layout));
676 entry->layout = NULL;
679 gtk_entry_ensure_layout (entry);
681 /* hackish for now, get metrics
683 font = pango_context_load_font (pango_layout_get_context (entry->layout),
684 widget->style->font_desc);
685 lang = pango_context_get_lang (pango_layout_get_context (entry->layout));
686 pango_font_get_metrics (font, lang, &metrics);
689 g_object_unref (G_OBJECT (font));
691 entry->ascent = metrics.ascent;
693 requisition->width = MIN_ENTRY_WIDTH + (widget->style->xthickness + INNER_BORDER) * 2;
694 requisition->height = ((metrics.ascent + metrics.descent) / PANGO_SCALE +
695 (widget->style->ythickness + INNER_BORDER) * 2);
699 gtk_entry_size_allocate (GtkWidget *widget,
700 GtkAllocation *allocation)
703 GtkEditable *editable;
705 g_return_if_fail (widget != NULL);
706 g_return_if_fail (GTK_IS_ENTRY (widget));
707 g_return_if_fail (allocation != NULL);
709 widget->allocation = *allocation;
710 entry = GTK_ENTRY (widget);
711 editable = GTK_EDITABLE (widget);
713 if (GTK_WIDGET_REALIZED (widget))
715 /* We call gtk_widget_get_child_requisition, since we want (for
716 * backwards compatibility reasons) the realization here to
717 * be affected by the usize of the entry, if set
719 GtkRequisition requisition;
720 gtk_widget_get_child_requisition (widget, &requisition);
722 gdk_window_move_resize (widget->window,
724 allocation->y + (allocation->height - requisition.height) / 2,
725 allocation->width, requisition.height);
726 gdk_window_move_resize (entry->text_area,
727 widget->style->xthickness,
728 widget->style->ythickness,
729 allocation->width - widget->style->xthickness * 2,
730 requisition.height - widget->style->ythickness * 2);
734 /* And make sure the cursor is on screen */
735 entry_adjust_scroll (entry);
739 gtk_entry_draw (GtkWidget *widget,
744 g_return_if_fail (widget != NULL);
745 g_return_if_fail (GTK_IS_ENTRY (widget));
746 g_return_if_fail (area != NULL);
748 entry = GTK_ENTRY (widget);
750 if (GTK_WIDGET_DRAWABLE (widget))
752 GdkRectangle tmp_area = *area;
754 tmp_area.x -= widget->style->xthickness;
755 tmp_area.y -= widget->style->xthickness;
757 gdk_window_begin_paint_rect (entry->text_area, &tmp_area);
758 gtk_widget_draw_focus (widget);
759 gtk_entry_draw_text (GTK_ENTRY (widget));
760 gtk_entry_draw_cursor (GTK_ENTRY (widget));
761 gdk_window_end_paint (entry->text_area);
766 gtk_entry_expose (GtkWidget *widget,
767 GdkEventExpose *event)
771 g_return_val_if_fail (widget != NULL, FALSE);
772 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
773 g_return_val_if_fail (event != NULL, FALSE);
775 entry = GTK_ENTRY (widget);
777 if (widget->window == event->window)
778 gtk_widget_draw_focus (widget);
779 else if (entry->text_area == event->window)
781 gtk_entry_draw_text (GTK_ENTRY (widget));
782 gtk_entry_draw_cursor (GTK_ENTRY (widget));
789 gtk_entry_button_press (GtkWidget *widget,
790 GdkEventButton *event)
793 GtkEditable *editable;
796 g_return_val_if_fail (widget != NULL, FALSE);
797 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
798 g_return_val_if_fail (event != NULL, FALSE);
800 if (ctext_atom == GDK_NONE)
801 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
803 entry = GTK_ENTRY (widget);
804 editable = GTK_EDITABLE (widget);
806 if (entry->button && (event->button != entry->button))
809 entry->button = event->button;
811 if (!GTK_WIDGET_HAS_FOCUS (widget))
812 gtk_widget_grab_focus (widget);
814 if (event->button == 1)
818 case GDK_BUTTON_PRESS:
819 gtk_grab_add (widget);
821 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
822 /* Set it now, so we display things right. We'll unset it
823 * later if things don't work out */
824 editable->has_selection = TRUE;
825 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
826 editable->current_pos = editable->selection_start_pos;
829 case GDK_2BUTTON_PRESS:
830 gtk_select_word (entry, event->time);
833 case GDK_3BUTTON_PRESS:
834 gtk_select_line (entry, event->time);
843 else if (event->type == GDK_BUTTON_PRESS)
845 if ((event->button == 2) && editable->editable)
847 if (editable->selection_start_pos == editable->selection_end_pos ||
848 editable->has_selection)
849 editable->current_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
850 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
851 ctext_atom, event->time);
855 gtk_grab_add (widget);
857 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
858 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
859 editable->has_selection = FALSE;
860 editable->current_pos = editable->selection_start_pos;
862 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
863 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
873 gtk_entry_button_release (GtkWidget *widget,
874 GdkEventButton *event)
877 GtkEditable *editable;
879 g_return_val_if_fail (widget != NULL, FALSE);
880 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
881 g_return_val_if_fail (event != NULL, FALSE);
883 entry = GTK_ENTRY (widget);
884 editable = GTK_EDITABLE (widget);
886 if (entry->button != event->button)
891 if (event->button == 1)
893 gtk_grab_remove (widget);
895 editable->has_selection = FALSE;
896 if (editable->selection_start_pos != editable->selection_end_pos)
898 if (gtk_selection_owner_set (widget,
899 GDK_SELECTION_PRIMARY,
901 editable->has_selection = TRUE;
903 gtk_entry_queue_draw (entry);
907 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
908 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
913 else if (event->button == 3)
915 gtk_grab_remove (widget);
924 gtk_entry_motion_notify (GtkWidget *widget,
925 GdkEventMotion *event)
930 g_return_val_if_fail (widget != NULL, FALSE);
931 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
932 g_return_val_if_fail (event != NULL, FALSE);
934 entry = GTK_ENTRY (widget);
936 if (entry->button == 0)
940 if (event->is_hint || (entry->text_area != event->window))
941 gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
943 GTK_EDITABLE(entry)->selection_end_pos = gtk_entry_find_position (entry, x + entry->scroll_offset);
944 GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
945 entry_adjust_scroll (entry);
946 gtk_entry_queue_draw (entry);
952 gtk_entry_key_press (GtkWidget *widget,
956 GtkEditable *editable;
961 gint extend_selection;
964 g_return_val_if_fail (widget != NULL, FALSE);
965 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
966 g_return_val_if_fail (event != NULL, FALSE);
968 entry = GTK_ENTRY (widget);
969 editable = GTK_EDITABLE (widget);
972 if(editable->editable == FALSE)
975 initial_pos = editable->current_pos;
977 extend_selection = event->state & GDK_SHIFT_MASK;
978 extend_start = FALSE;
980 if (extend_selection)
982 if (editable->selection_start_pos == editable->selection_end_pos)
984 editable->selection_start_pos = editable->current_pos;
985 editable->selection_end_pos = editable->current_pos;
988 extend_start = (editable->current_pos == editable->selection_start_pos);
991 switch (event->keyval)
995 if (event->state & GDK_CONTROL_MASK)
996 gtk_delete_backward_word (entry);
998 gtk_delete_backward_character (entry);
1002 gtk_delete_line (entry);
1006 if (event->state & GDK_SHIFT_MASK)
1008 extend_selection = FALSE;
1009 gtk_editable_paste_clipboard (editable);
1011 else if (event->state & GDK_CONTROL_MASK)
1013 gtk_editable_copy_clipboard (editable);
1017 /* gtk_toggle_insert(entry) -- IMPLEMENT */
1022 if (event->state & GDK_CONTROL_MASK)
1023 gtk_delete_forward_word (entry);
1024 else if (event->state & GDK_SHIFT_MASK)
1026 extend_selection = FALSE;
1027 gtk_editable_cut_clipboard (editable);
1030 gtk_delete_forward_character (entry);
1034 gtk_move_beginning_of_line (entry);
1038 gtk_move_end_of_line (entry);
1042 if (event->state & GDK_CONTROL_MASK)
1043 gtk_move_backward_word (entry);
1045 gtk_move_backward_character (entry);
1049 if (event->state & GDK_CONTROL_MASK)
1050 gtk_move_forward_word (entry);
1052 gtk_move_forward_character (entry);
1056 gtk_widget_activate (widget);
1058 /* The next two keys should not be inserted literally. Any others ??? */
1063 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1065 key = event->keyval;
1067 if (event->state & GDK_CONTROL_MASK)
1069 if ((key >= 'A') && (key <= 'Z'))
1072 if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1074 (* control_keys[key - 'a']) (editable, event->time);
1079 else if (event->state & GDK_MOD1_MASK)
1081 if ((key >= 'A') && (key <= 'Z'))
1084 if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1086 (* alt_keys[key - 'a']) (editable, event->time);
1092 gtk_im_context_filter_keypress (entry->im_context, event);
1097 /* since we emit signals from within the above code,
1098 * the widget might already be destroyed or at least
1101 if (GTK_WIDGET_REALIZED (editable) &&
1102 return_val && (editable->current_pos != initial_pos))
1104 if (extend_selection)
1106 if (editable->current_pos < editable->selection_start_pos)
1107 editable->selection_start_pos = editable->current_pos;
1108 else if (editable->current_pos > editable->selection_end_pos)
1109 editable->selection_end_pos = editable->current_pos;
1113 editable->selection_start_pos = editable->current_pos;
1115 editable->selection_end_pos = editable->current_pos;
1120 editable->selection_start_pos = 0;
1121 editable->selection_end_pos = 0;
1124 gtk_editable_claim_selection (editable,
1125 editable->selection_start_pos != editable->selection_end_pos,
1128 entry_adjust_scroll (entry);
1129 gtk_entry_queue_draw (entry);
1136 gtk_entry_focus_in (GtkWidget *widget,
1137 GdkEventFocus *event)
1139 g_return_val_if_fail (widget != NULL, FALSE);
1140 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1141 g_return_val_if_fail (event != NULL, FALSE);
1143 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1144 gtk_widget_draw_focus (widget);
1145 gtk_entry_queue_draw (GTK_ENTRY (widget));
1147 gtk_im_context_focus_in (GTK_ENTRY (widget)->im_context);
1153 gtk_entry_focus_out (GtkWidget *widget,
1154 GdkEventFocus *event)
1156 g_return_val_if_fail (widget != NULL, FALSE);
1157 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1158 g_return_val_if_fail (event != NULL, FALSE);
1160 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1161 gtk_widget_draw_focus (widget);
1162 gtk_entry_queue_draw (GTK_ENTRY (widget));
1164 gtk_im_context_focus_out (GTK_ENTRY (widget)->im_context);
1170 gtk_entry_ensure_layout (GtkEntry *entry)
1172 GtkWidget *widget = GTK_WIDGET (entry);
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 = g_utf8_offset_to_pointer (entry->text,
1217 MIN (editable->selection_start_pos, editable->selection_end_pos)) - entry->text;
1218 gint end_index = g_utf8_offset_to_pointer (entry->text,
1219 MAX (editable->selection_start_pos, editable->selection_end_pos)) - entry->text;
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 = g_utf8_next_char (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 = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
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->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 = g_utf8_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 = g_utf8_offset_to_pointer (entry->text, *position) - entry->text;
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 = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
1545 gint end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text;
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 = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
1598 end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text;
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 = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
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 = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
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 = g_utf8_next_char (entry->text + new_index) - entry->text;
1664 editable->current_pos = g_utf8_pointer_to_offset (entry->text, 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;