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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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-2000. 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_direction_changed (GtkWidget *widget,
96 GtkTextDirection previous_dir);
97 static void gtk_entry_state_changed (GtkWidget *widget,
98 GtkStateType previous_state);
99 static void gtk_entry_queue_draw (GtkEntry *entry);
100 static gint gtk_entry_find_position (GtkEntry *entry,
102 static void gtk_entry_get_cursor_locations (GtkEntry *entry,
105 static void entry_adjust_scroll (GtkEntry *entry);
106 static void gtk_entry_insert_text (GtkEditable *editable,
107 const gchar *new_text,
108 gint new_text_length,
110 static void gtk_entry_delete_text (GtkEditable *editable,
113 static void gtk_entry_update_text (GtkEditable *editable,
116 static gchar *gtk_entry_get_chars (GtkEditable *editable,
120 /* Binding actions */
121 static void gtk_entry_move_cursor (GtkEditable *editable,
124 static void gtk_entry_move_word (GtkEditable *editable,
126 static void gtk_entry_move_to_column (GtkEditable *editable,
128 static void gtk_entry_kill_char (GtkEditable *editable,
130 static void gtk_entry_kill_word (GtkEditable *editable,
132 static void gtk_entry_kill_line (GtkEditable *editable,
136 static void gtk_move_forward_character (GtkEntry *entry);
137 static void gtk_move_backward_character (GtkEntry *entry);
138 static void gtk_move_forward_word (GtkEntry *entry);
139 static void gtk_move_backward_word (GtkEntry *entry);
140 static void gtk_move_beginning_of_line (GtkEntry *entry);
141 static void gtk_move_end_of_line (GtkEntry *entry);
142 static void gtk_delete_forward_character (GtkEntry *entry);
143 static void gtk_delete_backward_character (GtkEntry *entry);
144 static void gtk_delete_forward_word (GtkEntry *entry);
145 static void gtk_delete_backward_word (GtkEntry *entry);
146 static void gtk_delete_line (GtkEntry *entry);
147 static void gtk_delete_to_line_end (GtkEntry *entry);
148 static void gtk_select_word (GtkEntry *entry,
150 static void gtk_select_line (GtkEntry *entry,
154 static void gtk_entry_set_selection (GtkEditable *editable,
158 static void gtk_entry_set_position_from_editable (GtkEditable *editable,
161 static void gtk_entry_commit_cb (GtkIMContext *context,
166 static GtkWidgetClass *parent_class = NULL;
167 static GdkAtom ctext_atom = GDK_NONE;
169 static const GtkTextFunction control_keys[26] =
171 (GtkTextFunction)gtk_move_beginning_of_line, /* a */
172 (GtkTextFunction)gtk_move_backward_character, /* b */
173 (GtkTextFunction)gtk_editable_copy_clipboard, /* c */
174 (GtkTextFunction)gtk_delete_forward_character, /* d */
175 (GtkTextFunction)gtk_move_end_of_line, /* e */
176 (GtkTextFunction)gtk_move_forward_character, /* f */
178 (GtkTextFunction)gtk_delete_backward_character, /* h */
181 (GtkTextFunction)gtk_delete_to_line_end, /* k */
191 (GtkTextFunction)gtk_delete_line, /* u */
192 (GtkTextFunction)gtk_editable_paste_clipboard, /* v */
193 (GtkTextFunction)gtk_delete_backward_word, /* w */
194 (GtkTextFunction)gtk_editable_cut_clipboard, /* x */
199 static const GtkTextFunction alt_keys[26] =
202 (GtkTextFunction)gtk_move_backward_word, /* b */
204 (GtkTextFunction)gtk_delete_forward_word, /* d */
206 (GtkTextFunction)gtk_move_forward_word, /* f */
231 gtk_entry_get_type (void)
233 static GtkType entry_type = 0;
237 static const GtkTypeInfo entry_info =
241 sizeof (GtkEntryClass),
242 (GtkClassInitFunc) gtk_entry_class_init,
243 (GtkObjectInitFunc) gtk_entry_init,
244 /* reserved_1 */ NULL,
245 /* reserved_2 */ NULL,
246 (GtkClassInitFunc) NULL,
249 entry_type = gtk_type_unique (GTK_TYPE_EDITABLE, &entry_info);
256 gtk_entry_class_init (GtkEntryClass *class)
258 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
259 GtkObjectClass *object_class;
260 GtkWidgetClass *widget_class;
261 GtkEditableClass *editable_class;
263 object_class = (GtkObjectClass*) class;
264 widget_class = (GtkWidgetClass*) class;
265 editable_class = (GtkEditableClass*) class;
266 parent_class = gtk_type_class (GTK_TYPE_EDITABLE);
268 gobject_class->finalize = gtk_entry_finalize;
270 gtk_object_add_arg_type ("GtkEntry::max_length", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MAX_LENGTH);
271 gtk_object_add_arg_type ("GtkEntry::visibility", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBILITY);
273 object_class->set_arg = gtk_entry_set_arg;
274 object_class->get_arg = gtk_entry_get_arg;
276 widget_class->realize = gtk_entry_realize;
277 widget_class->unrealize = gtk_entry_unrealize;
278 widget_class->draw_focus = gtk_entry_draw_focus;
279 widget_class->size_request = gtk_entry_size_request;
280 widget_class->size_allocate = gtk_entry_size_allocate;
281 widget_class->draw = gtk_entry_draw;
282 widget_class->expose_event = gtk_entry_expose;
283 widget_class->button_press_event = gtk_entry_button_press;
284 widget_class->button_release_event = gtk_entry_button_release;
285 widget_class->motion_notify_event = gtk_entry_motion_notify;
286 widget_class->key_press_event = gtk_entry_key_press;
287 widget_class->focus_in_event = gtk_entry_focus_in;
288 widget_class->focus_out_event = gtk_entry_focus_out;
289 widget_class->style_set = gtk_entry_style_set;
290 widget_class->direction_changed = gtk_entry_direction_changed;
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;
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);
513 g_object_unref (G_OBJECT (entry->layout));
515 gtk_object_unref (GTK_OBJECT (entry->im_context));
518 gtk_timeout_remove (entry->timer);
520 entry->text_size = 0;
523 g_free (entry->text);
526 G_OBJECT_CLASS (parent_class)->finalize (object);
530 gtk_entry_realize (GtkWidget *widget)
533 GtkEditable *editable;
534 GtkRequisition requisition;
535 GdkWindowAttr attributes;
536 gint attributes_mask;
538 g_return_if_fail (widget != NULL);
539 g_return_if_fail (GTK_IS_ENTRY (widget));
541 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
542 entry = GTK_ENTRY (widget);
543 editable = GTK_EDITABLE (widget);
545 gtk_widget_get_child_requisition (widget, &requisition);
547 attributes.window_type = GDK_WINDOW_CHILD;
548 attributes.x = widget->allocation.x;
549 attributes.y = widget->allocation.y + (widget->allocation.height -
550 requisition.height) / 2;
551 attributes.width = widget->allocation.width;
552 attributes.height = requisition.height;
553 attributes.wclass = GDK_INPUT_OUTPUT;
554 attributes.visual = gtk_widget_get_visual (widget);
555 attributes.colormap = gtk_widget_get_colormap (widget);
556 attributes.event_mask = gtk_widget_get_events (widget);
557 attributes.event_mask |= (GDK_EXPOSURE_MASK |
558 GDK_BUTTON_PRESS_MASK |
559 GDK_BUTTON_RELEASE_MASK |
560 GDK_BUTTON1_MOTION_MASK |
561 GDK_BUTTON3_MOTION_MASK |
562 GDK_POINTER_MOTION_HINT_MASK |
563 GDK_ENTER_NOTIFY_MASK |
564 GDK_LEAVE_NOTIFY_MASK |
566 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
568 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
569 gdk_window_set_user_data (widget->window, entry);
571 attributes.x = widget->style->xthickness;
572 attributes.y = widget->style->ythickness;
573 attributes.width = widget->allocation.width - attributes.x * 2;
574 attributes.height = requisition.height - attributes.y * 2;
575 attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
576 attributes_mask |= GDK_WA_CURSOR;
578 entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
579 gdk_window_set_user_data (entry->text_area, entry);
581 widget->style = gtk_style_attach (widget->style, widget->window);
583 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
584 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
586 gdk_window_show (entry->text_area);
588 if (editable->selection_start_pos != editable->selection_end_pos)
589 gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
591 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
593 entry_adjust_scroll (entry);
597 gtk_entry_unrealize (GtkWidget *widget)
601 g_return_if_fail (widget != NULL);
602 g_return_if_fail (GTK_IS_ENTRY (widget));
604 entry = GTK_ENTRY (widget);
606 gtk_im_context_set_client_window (entry->im_context, entry->text_area);
608 if (entry->text_area)
610 gdk_window_set_user_data (entry->text_area, NULL);
611 gdk_window_destroy (entry->text_area);
612 entry->text_area = NULL;
613 gdk_cursor_destroy (entry->cursor);
614 entry->cursor = NULL;
617 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
618 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
622 gtk_entry_draw_focus (GtkWidget *widget)
627 g_return_if_fail (widget != NULL);
628 g_return_if_fail (GTK_IS_ENTRY (widget));
630 if (GTK_WIDGET_DRAWABLE (widget))
634 gdk_window_get_size (widget->window, &width, &height);
636 if (GTK_WIDGET_HAS_FOCUS (widget))
644 gtk_paint_shadow (widget->style, widget->window,
645 GTK_STATE_NORMAL, GTK_SHADOW_IN,
646 NULL, widget, "entry",
647 x, y, width, height);
649 if (GTK_WIDGET_HAS_FOCUS (widget))
651 gdk_window_get_size (widget->window, &width, &height);
652 gtk_paint_focus (widget->style, widget->window,
653 NULL, widget, "entry",
654 0, 0, width - 1, height - 1);
660 gtk_entry_size_request (GtkWidget *widget,
661 GtkRequisition *requisition)
664 PangoFontMetrics metrics;
668 g_return_if_fail (widget != NULL);
669 g_return_if_fail (GTK_IS_ENTRY (widget));
670 g_return_if_fail (requisition != NULL);
672 entry = GTK_ENTRY (widget);
674 gtk_entry_ensure_layout (entry);
676 /* hackish for now, get metrics
678 font = pango_context_load_font (pango_layout_get_context (entry->layout),
679 widget->style->font_desc);
680 lang = pango_context_get_lang (pango_layout_get_context (entry->layout));
681 pango_font_get_metrics (font, lang, &metrics);
684 g_object_unref (G_OBJECT (font));
686 entry->ascent = metrics.ascent;
687 entry->descent = metrics.descent;
689 requisition->width = MIN_ENTRY_WIDTH + (widget->style->xthickness + INNER_BORDER) * 2;
690 requisition->height = ((metrics.ascent + metrics.descent) / PANGO_SCALE +
691 (widget->style->ythickness + INNER_BORDER) * 2);
695 gtk_entry_size_allocate (GtkWidget *widget,
696 GtkAllocation *allocation)
699 GtkEditable *editable;
701 g_return_if_fail (widget != NULL);
702 g_return_if_fail (GTK_IS_ENTRY (widget));
703 g_return_if_fail (allocation != NULL);
705 widget->allocation = *allocation;
706 entry = GTK_ENTRY (widget);
707 editable = GTK_EDITABLE (widget);
709 if (GTK_WIDGET_REALIZED (widget))
711 /* We call gtk_widget_get_child_requisition, since we want (for
712 * backwards compatibility reasons) the realization here to
713 * be affected by the usize of the entry, if set
715 GtkRequisition requisition;
716 gtk_widget_get_child_requisition (widget, &requisition);
718 gdk_window_move_resize (widget->window,
720 allocation->y + (allocation->height - requisition.height) / 2,
721 allocation->width, requisition.height);
722 gdk_window_move_resize (entry->text_area,
723 widget->style->xthickness,
724 widget->style->ythickness,
725 allocation->width - widget->style->xthickness * 2,
726 requisition.height - widget->style->ythickness * 2);
728 /* And make sure the cursor is on screen */
729 entry_adjust_scroll (entry);
734 gtk_entry_draw (GtkWidget *widget,
739 g_return_if_fail (widget != NULL);
740 g_return_if_fail (GTK_IS_ENTRY (widget));
741 g_return_if_fail (area != NULL);
743 entry = GTK_ENTRY (widget);
745 if (GTK_WIDGET_DRAWABLE (widget))
747 GdkRectangle tmp_area = *area;
749 tmp_area.x -= widget->style->xthickness;
750 tmp_area.y -= widget->style->xthickness;
752 gdk_window_begin_paint_rect (entry->text_area, &tmp_area);
753 gtk_widget_draw_focus (widget);
754 gtk_entry_draw_text (GTK_ENTRY (widget));
755 gtk_entry_draw_cursor (GTK_ENTRY (widget));
756 gdk_window_end_paint (entry->text_area);
761 gtk_entry_expose (GtkWidget *widget,
762 GdkEventExpose *event)
766 g_return_val_if_fail (widget != NULL, FALSE);
767 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
768 g_return_val_if_fail (event != NULL, FALSE);
770 entry = GTK_ENTRY (widget);
772 if (widget->window == event->window)
773 gtk_widget_draw_focus (widget);
774 else if (entry->text_area == event->window)
776 gtk_entry_draw_text (GTK_ENTRY (widget));
777 gtk_entry_draw_cursor (GTK_ENTRY (widget));
784 gtk_entry_button_press (GtkWidget *widget,
785 GdkEventButton *event)
788 GtkEditable *editable;
791 g_return_val_if_fail (widget != NULL, FALSE);
792 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
793 g_return_val_if_fail (event != NULL, FALSE);
795 if (ctext_atom == GDK_NONE)
796 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
798 entry = GTK_ENTRY (widget);
799 editable = GTK_EDITABLE (widget);
801 if (entry->button && (event->button != entry->button))
804 entry->button = event->button;
806 if (!GTK_WIDGET_HAS_FOCUS (widget))
807 gtk_widget_grab_focus (widget);
809 if (event->button == 1)
813 case GDK_BUTTON_PRESS:
814 gtk_grab_add (widget);
816 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
817 /* Set it now, so we display things right. We'll unset it
818 * later if things don't work out */
819 editable->has_selection = TRUE;
820 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
821 editable->current_pos = editable->selection_start_pos;
824 case GDK_2BUTTON_PRESS:
825 gtk_select_word (entry, event->time);
828 case GDK_3BUTTON_PRESS:
829 gtk_select_line (entry, event->time);
838 else if (event->type == GDK_BUTTON_PRESS)
840 if ((event->button == 2) && editable->editable)
842 if (editable->selection_start_pos == editable->selection_end_pos ||
843 editable->has_selection)
844 editable->current_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
845 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
846 ctext_atom, event->time);
850 gtk_grab_add (widget);
852 tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
853 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
854 editable->has_selection = FALSE;
855 editable->current_pos = editable->selection_start_pos;
857 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
858 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
868 gtk_entry_button_release (GtkWidget *widget,
869 GdkEventButton *event)
872 GtkEditable *editable;
874 g_return_val_if_fail (widget != NULL, FALSE);
875 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
876 g_return_val_if_fail (event != NULL, FALSE);
878 entry = GTK_ENTRY (widget);
879 editable = GTK_EDITABLE (widget);
881 if (entry->button != event->button)
886 if (event->button == 1)
888 gtk_grab_remove (widget);
890 editable->has_selection = FALSE;
891 if (editable->selection_start_pos != editable->selection_end_pos)
893 if (gtk_selection_owner_set (widget,
894 GDK_SELECTION_PRIMARY,
896 editable->has_selection = TRUE;
898 gtk_entry_queue_draw (entry);
902 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
903 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
908 else if (event->button == 3)
910 gtk_grab_remove (widget);
919 gtk_entry_motion_notify (GtkWidget *widget,
920 GdkEventMotion *event)
925 g_return_val_if_fail (widget != NULL, FALSE);
926 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
927 g_return_val_if_fail (event != NULL, FALSE);
929 entry = GTK_ENTRY (widget);
931 if (entry->button == 0)
935 if (event->is_hint || (entry->text_area != event->window))
936 gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
938 GTK_EDITABLE(entry)->selection_end_pos = gtk_entry_find_position (entry, x + entry->scroll_offset);
939 GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
940 entry_adjust_scroll (entry);
941 gtk_entry_queue_draw (entry);
947 gtk_entry_key_press (GtkWidget *widget,
951 GtkEditable *editable;
956 gint extend_selection;
959 g_return_val_if_fail (widget != NULL, FALSE);
960 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
961 g_return_val_if_fail (event != NULL, FALSE);
963 entry = GTK_ENTRY (widget);
964 editable = GTK_EDITABLE (widget);
967 if(editable->editable == FALSE)
970 initial_pos = editable->current_pos;
972 extend_selection = event->state & GDK_SHIFT_MASK;
973 extend_start = FALSE;
975 if (extend_selection)
977 if (editable->selection_start_pos == editable->selection_end_pos)
979 editable->selection_start_pos = editable->current_pos;
980 editable->selection_end_pos = editable->current_pos;
983 extend_start = (editable->current_pos == editable->selection_start_pos);
986 switch (event->keyval)
990 if (event->state & GDK_CONTROL_MASK)
991 gtk_delete_backward_word (entry);
993 gtk_delete_backward_character (entry);
997 gtk_delete_line (entry);
1001 if (event->state & GDK_SHIFT_MASK)
1003 extend_selection = FALSE;
1004 gtk_editable_paste_clipboard (editable);
1006 else if (event->state & GDK_CONTROL_MASK)
1008 gtk_editable_copy_clipboard (editable);
1012 /* gtk_toggle_insert(entry) -- IMPLEMENT */
1017 if (event->state & GDK_CONTROL_MASK)
1018 gtk_delete_forward_word (entry);
1019 else if (event->state & GDK_SHIFT_MASK)
1021 extend_selection = FALSE;
1022 gtk_editable_cut_clipboard (editable);
1025 gtk_delete_forward_character (entry);
1029 gtk_move_beginning_of_line (entry);
1033 gtk_move_end_of_line (entry);
1037 if (event->state & GDK_CONTROL_MASK)
1038 gtk_move_backward_word (entry);
1040 gtk_move_backward_character (entry);
1044 if (event->state & GDK_CONTROL_MASK)
1045 gtk_move_forward_word (entry);
1047 gtk_move_forward_character (entry);
1051 gtk_widget_activate (widget);
1053 /* The next two keys should not be inserted literally. Any others ??? */
1058 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1060 key = event->keyval;
1062 if (event->state & GDK_CONTROL_MASK)
1064 if ((key >= 'A') && (key <= 'Z'))
1067 if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1069 (* control_keys[key - 'a']) (editable, event->time);
1074 else if (event->state & GDK_MOD1_MASK)
1076 if ((key >= 'A') && (key <= 'Z'))
1079 if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1081 (* alt_keys[key - 'a']) (editable, event->time);
1087 gtk_im_context_filter_keypress (entry->im_context, event);
1092 /* since we emit signals from within the above code,
1093 * the widget might already be destroyed or at least
1096 if (GTK_WIDGET_REALIZED (editable) &&
1097 return_val && (editable->current_pos != initial_pos))
1099 if (extend_selection)
1101 if (editable->current_pos < editable->selection_start_pos)
1102 editable->selection_start_pos = editable->current_pos;
1103 else if (editable->current_pos > editable->selection_end_pos)
1104 editable->selection_end_pos = editable->current_pos;
1108 editable->selection_start_pos = editable->current_pos;
1110 editable->selection_end_pos = editable->current_pos;
1115 editable->selection_start_pos = 0;
1116 editable->selection_end_pos = 0;
1119 gtk_editable_claim_selection (editable,
1120 editable->selection_start_pos != editable->selection_end_pos,
1123 entry_adjust_scroll (entry);
1124 gtk_entry_queue_draw (entry);
1131 gtk_entry_focus_in (GtkWidget *widget,
1132 GdkEventFocus *event)
1134 g_return_val_if_fail (widget != NULL, FALSE);
1135 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1136 g_return_val_if_fail (event != NULL, FALSE);
1138 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1139 gtk_widget_draw_focus (widget);
1140 gtk_entry_queue_draw (GTK_ENTRY (widget));
1142 gtk_im_context_focus_in (GTK_ENTRY (widget)->im_context);
1148 gtk_entry_focus_out (GtkWidget *widget,
1149 GdkEventFocus *event)
1151 g_return_val_if_fail (widget != NULL, FALSE);
1152 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1153 g_return_val_if_fail (event != NULL, FALSE);
1155 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1156 gtk_widget_draw_focus (widget);
1157 gtk_entry_queue_draw (GTK_ENTRY (widget));
1159 gtk_im_context_focus_out (GTK_ENTRY (widget)->im_context);
1165 gtk_entry_ensure_layout (GtkEntry *entry)
1167 GtkWidget *widget = GTK_WIDGET (entry);
1171 entry->layout = gtk_widget_create_pango_layout (widget, NULL);
1172 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1177 gtk_entry_draw_text (GtkEntry *entry)
1180 PangoLayoutLine *line;
1181 GtkEditable *editable = GTK_EDITABLE (entry);
1183 g_return_if_fail (entry != NULL);
1184 g_return_if_fail (GTK_IS_ENTRY (entry));
1186 if (GTK_WIDGET_DRAWABLE (entry))
1188 PangoRectangle logical_rect;
1189 gint area_width, area_height;
1192 gdk_window_get_size (entry->text_area, &area_width, &area_height);
1193 area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER);
1195 widget = GTK_WIDGET (entry);
1197 gtk_paint_flat_box (widget->style, entry->text_area,
1198 GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
1199 NULL, widget, "entry_bg",
1200 0, 0, area_width, area_height);
1202 gtk_entry_ensure_layout (entry);
1204 line = pango_layout_get_lines (entry->layout)->data;
1205 pango_layout_line_get_extents (line, NULL, &logical_rect);
1207 /* Align primarily for locale's ascent/descent */
1208 y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
1209 entry->ascent + logical_rect.y);
1211 /* Now see if we need to adjust to fit in actual drawn string */
1212 if (logical_rect.height > area_height)
1213 y_pos = (area_height - logical_rect.height) / 2;
1216 else if (y_pos + logical_rect.height > area_height)
1217 y_pos = area_height - logical_rect.height;
1219 y_pos = INNER_BORDER + y_pos / PANGO_SCALE;
1221 gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
1222 INNER_BORDER - entry->scroll_offset, y_pos,
1225 if (editable->selection_start_pos != editable->selection_end_pos)
1229 gint start_index = g_utf8_offset_to_pointer (entry->text,
1230 MIN (editable->selection_start_pos, editable->selection_end_pos)) - entry->text;
1231 gint end_index = g_utf8_offset_to_pointer (entry->text,
1232 MAX (editable->selection_start_pos, editable->selection_end_pos)) - entry->text;
1233 GtkStateType selected_state = editable->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
1234 GdkRegion *clip_region = gdk_region_new ();
1236 pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges);
1238 for (i=0; i < n_ranges; i++)
1242 rect.x = INNER_BORDER - entry->scroll_offset + ranges[2*i] / PANGO_SCALE;
1244 rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE;
1245 rect.height = logical_rect.height / PANGO_SCALE;
1247 gdk_draw_rectangle (entry->text_area, widget->style->bg_gc [selected_state], TRUE,
1248 rect.x, rect.y, rect.width, rect.height);
1250 gdk_region_union_with_rect (clip_region, &rect);
1253 gdk_gc_set_clip_region (widget->style->fg_gc [selected_state], clip_region);
1254 gdk_draw_layout (entry->text_area, widget->style->fg_gc [selected_state],
1255 INNER_BORDER - entry->scroll_offset, y_pos,
1257 gdk_gc_set_clip_region (widget->style->fg_gc [selected_state], NULL);
1259 gdk_region_destroy (clip_region);
1266 gtk_entry_draw_cursor (GtkEntry *entry)
1268 g_return_if_fail (entry != NULL);
1269 g_return_if_fail (GTK_IS_ENTRY (entry));
1271 if (GTK_WIDGET_DRAWABLE (entry))
1273 GtkWidget *widget = GTK_WIDGET (entry);
1274 GtkEditable *editable = GTK_EDITABLE (entry);
1276 if (GTK_WIDGET_HAS_FOCUS (widget) &&
1277 (editable->selection_start_pos == editable->selection_end_pos))
1279 gint xoffset = INNER_BORDER - entry->scroll_offset;
1280 gint strong_x, weak_x;
1281 gint text_area_height;
1283 gdk_window_get_size (entry->text_area, NULL, &text_area_height);
1285 gtk_entry_get_cursor_locations (entry, &strong_x, &weak_x);
1287 gdk_draw_line (entry->text_area, widget->style->bg_gc[GTK_STATE_SELECTED],
1288 xoffset + strong_x, INNER_BORDER,
1289 xoffset + strong_x, text_area_height - INNER_BORDER);
1291 if (weak_x != strong_x)
1292 gdk_draw_line (entry->text_area, widget->style->fg_gc[GTK_STATE_NORMAL],
1293 xoffset + weak_x, INNER_BORDER,
1294 xoffset + weak_x, text_area_height - INNER_BORDER);
1301 gtk_entry_queue_draw (GtkEntry *entry)
1303 g_return_if_fail (entry != NULL);
1304 g_return_if_fail (GTK_IS_ENTRY (entry));
1306 if (GTK_WIDGET_REALIZED (entry))
1308 GdkRectangle rect = { 0 };
1310 gdk_window_get_size (entry->text_area, &rect.width, &rect.height);
1311 gdk_window_invalidate_rect (entry->text_area, &rect, 0);
1317 gtk_entry_timer (gpointer data)
1321 GDK_THREADS_ENTER ();
1323 entry = GTK_ENTRY (data);
1326 GDK_THREADS_LEAVE ();
1333 gtk_entry_find_position (GtkEntry *entry,
1336 PangoLayoutLine *line;
1341 gtk_entry_ensure_layout (entry);
1343 line = pango_layout_get_lines (entry->layout)->data;
1344 pango_layout_line_x_to_index (line, x * PANGO_SCALE, &index, &trailing);
1346 pos = g_utf8_pointer_to_offset (entry->text, entry->text + index);
1355 gtk_entry_get_cursor_locations (GtkEntry *entry,
1359 GtkEditable *editable = GTK_EDITABLE (entry);
1362 PangoRectangle strong_pos, weak_pos;
1364 gtk_entry_ensure_layout (entry);
1366 index = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
1367 pango_layout_get_cursor_pos (entry->layout, index, &strong_pos, &weak_pos);
1370 *strong_x = strong_pos.x / PANGO_SCALE;
1373 *weak_x = weak_pos.x / PANGO_SCALE;
1377 entry_adjust_scroll (GtkEntry *entry)
1380 gint min_offset, max_offset;
1381 gint text_area_width;
1382 gint strong_x, weak_x;
1383 gint strong_xoffset, weak_xoffset;
1384 PangoLayoutLine *line;
1385 PangoRectangle logical_rect;
1387 g_return_if_fail (entry != NULL);
1388 g_return_if_fail (GTK_IS_ENTRY (entry));
1390 widget = GTK_WIDGET (entry);
1392 if (!entry->layout || !GTK_WIDGET_REALIZED (entry))
1395 gdk_window_get_size (entry->text_area, &text_area_width, NULL);
1396 text_area_width -= 2 * INNER_BORDER;
1398 line = pango_layout_get_lines (entry->layout)->data;
1400 /* Display as much text as we can */
1402 pango_layout_line_get_extents (line, NULL, &logical_rect);
1404 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1407 max_offset = MAX (min_offset, logical_rect.width / PANGO_SCALE - text_area_width);
1411 max_offset = logical_rect.width / PANGO_SCALE - text_area_width;
1412 min_offset = MIN (0, max_offset);
1415 entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset);
1417 /* And make sure cursors are on screen. Note that the cursor is
1418 * actually drawn one pixel into the INNER_BORDER space on
1419 * the right, when the scroll is at the utmost right. This
1420 * looks better to to me than confining the cursor inside the
1421 * border entirely, though it means that the cursor gets one
1422 * pixel closer to the the edge of the widget on the right than
1423 * on the left. This might need changing if one changed
1424 * INNER_BORDER from 2 to 1, as one would do on a
1425 * small-screen-real-estate display.
1427 * We always make sure that the strong cursor is on screen, and
1428 * put the weak cursor on screen if possible.
1431 gtk_entry_get_cursor_locations (entry, &strong_x, &weak_x);
1433 strong_xoffset = strong_x - entry->scroll_offset;
1435 if (strong_xoffset < 0)
1437 entry->scroll_offset += strong_xoffset;
1440 else if (strong_xoffset > text_area_width)
1442 entry->scroll_offset += strong_xoffset - text_area_width;
1443 strong_xoffset = text_area_width;
1446 weak_xoffset = weak_x - entry->scroll_offset;
1448 if (weak_xoffset < 0 && strong_xoffset - weak_xoffset <= text_area_width)
1450 entry->scroll_offset += weak_xoffset;
1452 else if (weak_xoffset > text_area_width &&
1453 strong_xoffset - (weak_xoffset - text_area_width) >= 0)
1455 entry->scroll_offset += weak_xoffset - text_area_width;
1458 gtk_widget_queue_draw (GTK_WIDGET (entry));
1462 gtk_entry_insert_text (GtkEditable *editable,
1463 const gchar *new_text,
1464 gint new_text_length,
1472 g_return_if_fail (editable != NULL);
1473 g_return_if_fail (GTK_IS_ENTRY (editable));
1474 g_return_if_fail (position != NULL);
1475 g_return_if_fail (*position >= 0 || *position < GTK_ENTRY (editable)->text_size);
1477 entry = GTK_ENTRY (editable);
1478 widget = GTK_WIDGET (editable);
1480 if (new_text_length < 0)
1481 new_text_length = strlen (new_text);
1483 n_chars = g_utf8_strlen (new_text, new_text_length);
1484 if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
1487 n_chars = entry->text_max_length - entry->text_length;
1490 if (new_text_length + entry->n_bytes + 1 > entry->text_size)
1492 while (new_text_length + entry->n_bytes + 1 > entry->text_size)
1494 if (entry->text_size == 0)
1495 entry->text_size = MIN_SIZE;
1498 if (2 * (guint)entry->text_size < MAX_SIZE &&
1499 2 * (guint)entry->text_size > entry->text_size)
1500 entry->text_size *= 2;
1503 entry->text_size = MAX_SIZE;
1504 new_text_length = entry->text_size - new_text_length - 1;
1510 entry->text = g_realloc (entry->text, entry->text_size);
1513 index = g_utf8_offset_to_pointer (entry->text, *position) - entry->text;
1515 g_memmove (entry->text + index + new_text_length, entry->text + index, entry->n_bytes - index);
1516 memcpy (entry->text + index, new_text, new_text_length);
1518 entry->n_bytes += new_text_length;
1519 entry->text_length += n_chars;
1521 /* NUL terminate for safety and convenience */
1522 entry->text[entry->n_bytes] = '\0';
1524 if (editable->current_pos > *position)
1525 editable->current_pos += n_chars;
1527 if (editable->selection_start_pos > *position)
1528 editable->selection_start_pos += n_chars;
1530 if (editable->selection_end_pos > *position)
1531 editable->selection_end_pos += n_chars;
1533 *position += n_chars;
1536 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1538 gtk_entry_queue_draw (entry);
1542 gtk_entry_delete_text (GtkEditable *editable,
1548 g_return_if_fail (editable != NULL);
1549 g_return_if_fail (GTK_IS_ENTRY (editable));
1551 entry = GTK_ENTRY (editable);
1554 end_pos = entry->text_length;
1556 if ((start_pos < end_pos) &&
1558 (end_pos <= entry->text_length))
1560 gint start_index = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
1561 gint end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text;
1563 g_memmove (entry->text + start_index, entry->text + end_index, entry->n_bytes - end_index);
1564 entry->text_length -= (end_pos - start_pos);
1565 entry->n_bytes -= (end_index - start_index);
1567 if (editable->current_pos > start_pos)
1568 editable->current_pos -= MIN (editable->current_pos, end_pos) - start_pos;
1570 if (editable->selection_start_pos > start_pos)
1571 editable->selection_start_pos -= MIN (editable->selection_start_pos, end_pos) - start_pos;
1573 if (editable->selection_end_pos > start_pos)
1574 editable->selection_end_pos -= MIN (editable->selection_end_pos, end_pos) - start_pos;
1578 gtk_entry_queue_draw (entry);
1581 pango_layout_set_text (entry->layout, entry->text, entry->n_bytes);
1585 gtk_entry_update_text (GtkEditable *editable,
1589 GtkEntry *entry = GTK_ENTRY (editable);
1591 gtk_entry_queue_draw (entry);
1595 gtk_entry_get_chars (GtkEditable *editable,
1600 gint start_index, end_index;
1602 g_return_val_if_fail (editable != NULL, NULL);
1603 g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL);
1605 entry = GTK_ENTRY (editable);
1608 end_pos = entry->text_length;
1610 start_pos = MIN (entry->text_length, start_pos);
1611 end_pos = MIN (entry->text_length, end_pos);
1613 start_index = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
1614 end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text;
1616 return g_strndup (entry->text + start_index, end_index - start_index);
1620 gtk_entry_move_cursor (GtkEditable *editable,
1627 entry = GTK_ENTRY (editable);
1629 index = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
1631 /* Horizontal motion */
1633 if ((gint)editable->current_pos < -x)
1634 editable->current_pos = 0;
1635 else if (editable->current_pos + x > entry->text_length)
1636 editable->current_pos = entry->text_length;
1638 editable->current_pos += x;
1640 /* Ignore vertical motion */
1644 gtk_entry_move_cursor_visually (GtkEditable *editable,
1650 entry = GTK_ENTRY (editable);
1652 index = g_utf8_offset_to_pointer (entry->text, editable->current_pos) - entry->text;
1654 gtk_entry_ensure_layout (entry);
1658 int new_index, new_trailing;
1662 pango_layout_move_cursor_visually (entry->layout, index, 0, 1, &new_index, &new_trailing);
1667 pango_layout_move_cursor_visually (entry->layout, index, 0, -1, &new_index, &new_trailing);
1671 if (new_index < 0 || new_index == G_MAXINT)
1675 index = g_utf8_next_char (entry->text + new_index) - entry->text;
1680 editable->current_pos = g_utf8_pointer_to_offset (entry->text, entry->text + index);
1684 gtk_move_forward_character (GtkEntry *entry)
1686 gtk_entry_move_cursor_visually (GTK_EDITABLE (entry), 1);
1690 gtk_move_backward_character (GtkEntry *entry)
1692 gtk_entry_move_cursor_visually (GTK_EDITABLE (entry), -1);
1696 gtk_entry_move_word (GtkEditable *editable,
1700 gtk_move_forward_word (GTK_ENTRY (editable));
1702 gtk_move_backward_word (GTK_ENTRY (editable));
1706 gtk_move_forward_word (GtkEntry *entry)
1708 GtkEditable *editable;
1711 editable = GTK_EDITABLE (entry);
1713 /* Prevent any leak of information */
1714 if (!editable->visible)
1716 editable->current_pos = entry->text_length;
1720 if (entry->text && (editable->current_pos < entry->text_length))
1722 PangoLogAttr *log_attrs;
1723 gint n_attrs, old_pos;
1725 gtk_entry_ensure_layout (entry);
1726 pango_layout_get_log_attrs (entry->layout, &log_attrs, &n_attrs);
1728 i = old_pos = editable->current_pos;
1730 /* Advance over white space */
1731 while (i < n_attrs && log_attrs[i].is_white)
1734 /* Find the next word beginning */
1736 while (i < n_attrs && !log_attrs[i].is_word_stop)
1739 editable->current_pos = MAX (entry->text_length, i);
1741 /* Back up over white space */
1742 while (i > 0 && log_attrs[i - 1].is_white)
1746 editable->current_pos = i;
1753 gtk_move_backward_word (GtkEntry *entry)
1755 GtkEditable *editable;
1758 editable = GTK_EDITABLE (entry);
1760 /* Prevent any leak of information */
1761 if (!editable->visible)
1763 editable->current_pos = 0;
1767 if (entry->text && editable->current_pos > 0)
1769 PangoLogAttr *log_attrs;
1772 gtk_entry_ensure_layout (entry);
1773 pango_layout_get_log_attrs (entry->layout, &log_attrs, &n_attrs);
1775 i = editable->current_pos - 1;
1777 /* Find the previous word beginning */
1778 while (i > 0 && !log_attrs[i].is_word_stop)
1786 gtk_entry_move_to_column (GtkEditable *editable, gint column)
1790 entry = GTK_ENTRY (editable);
1792 if (column < 0 || column > entry->text_length)
1793 editable->current_pos = entry->text_length;
1795 editable->current_pos = column;
1799 gtk_move_beginning_of_line (GtkEntry *entry)
1801 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
1805 gtk_move_end_of_line (GtkEntry *entry)
1807 gtk_entry_move_to_column (GTK_EDITABLE (entry), -1);
1811 gtk_entry_kill_char (GtkEditable *editable,
1814 if (editable->selection_start_pos != editable->selection_end_pos)
1815 gtk_editable_delete_selection (editable);
1818 gint old_pos = editable->current_pos;
1821 gtk_entry_move_cursor (editable, 1, 0);
1822 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1826 gtk_entry_move_cursor (editable, -1, 0);
1827 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1833 gtk_delete_forward_character (GtkEntry *entry)
1835 gtk_entry_kill_char (GTK_EDITABLE (entry), 1);
1839 gtk_delete_backward_character (GtkEntry *entry)
1841 gtk_entry_kill_char (GTK_EDITABLE (entry), -1);
1845 gtk_entry_kill_word (GtkEditable *editable,
1848 if (editable->selection_start_pos != editable->selection_end_pos)
1849 gtk_editable_delete_selection (editable);
1852 gint old_pos = editable->current_pos;
1855 gtk_entry_move_word (editable, 1);
1856 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1860 gtk_entry_move_word (editable, -1);
1861 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1867 gtk_delete_forward_word (GtkEntry *entry)
1869 gtk_entry_kill_word (GTK_EDITABLE (entry), 1);
1873 gtk_delete_backward_word (GtkEntry *entry)
1875 gtk_entry_kill_word (GTK_EDITABLE (entry), -1);
1879 gtk_entry_kill_line (GtkEditable *editable,
1882 gint old_pos = editable->current_pos;
1885 gtk_entry_move_to_column (editable, -1);
1886 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
1890 gtk_entry_move_to_column (editable, 0);
1891 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
1896 gtk_delete_line (GtkEntry *entry)
1898 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
1899 gtk_entry_kill_line (GTK_EDITABLE (entry), 1);
1903 gtk_delete_to_line_end (GtkEntry *entry)
1905 gtk_editable_delete_text (GTK_EDITABLE(entry), GTK_EDITABLE(entry)->current_pos, entry->text_length);
1909 gtk_select_word (GtkEntry *entry,
1912 GtkEditable *editable;
1916 editable = GTK_EDITABLE (entry);
1918 gtk_move_backward_word (entry);
1919 start_pos = editable->current_pos;
1921 gtk_move_forward_word (entry);
1922 end_pos = editable->current_pos;
1924 editable->has_selection = TRUE;
1925 gtk_entry_set_selection (editable, start_pos, end_pos);
1926 gtk_editable_claim_selection (editable, start_pos != end_pos, time);
1930 gtk_select_line (GtkEntry *entry,
1933 GtkEditable *editable;
1935 editable = GTK_EDITABLE (entry);
1937 editable->has_selection = TRUE;
1938 gtk_entry_set_selection (editable, 0, entry->text_length);
1939 gtk_editable_claim_selection (editable, entry->text_length != 0, time);
1941 editable->current_pos = editable->selection_end_pos;
1945 gtk_entry_set_selection (GtkEditable *editable,
1951 g_return_if_fail (editable != NULL);
1952 g_return_if_fail (GTK_IS_ENTRY (editable));
1954 entry = GTK_ENTRY (editable);
1957 end = GTK_ENTRY (editable)->text_length;
1959 editable->selection_start_pos = start;
1960 editable->selection_end_pos = end;
1962 gtk_entry_queue_draw (GTK_ENTRY (editable));
1966 gtk_entry_select_region (GtkEntry *entry,
1970 gtk_editable_select_region (GTK_EDITABLE (entry), start, end);
1974 gtk_entry_set_max_length (GtkEntry *entry,
1977 g_return_if_fail (entry != NULL);
1978 g_return_if_fail (GTK_IS_ENTRY (entry));
1980 if (max && entry->text_length > max)
1981 gtk_editable_delete_text (GTK_EDITABLE(entry), max, -1);
1983 entry->text_max_length = max;
1988 gtk_entry_style_set (GtkWidget *widget,
1989 GtkStyle *previous_style)
1991 GtkEntry *entry = GTK_ENTRY (widget);
1993 if (previous_style && GTK_WIDGET_REALIZED (widget))
1995 entry_adjust_scroll (entry);
1997 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
1998 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2002 pango_layout_context_changed (entry->layout);
2006 gtk_entry_direction_changed (GtkWidget *widget,
2007 GtkTextDirection previous_dir)
2009 GtkEntry *entry = GTK_ENTRY (widget);
2012 pango_layout_context_changed (entry->layout);
2014 GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
2018 gtk_entry_state_changed (GtkWidget *widget,
2019 GtkStateType previous_state)
2021 g_return_if_fail (widget != NULL);
2022 g_return_if_fail (GTK_IS_ENTRY (widget));
2024 if (GTK_WIDGET_REALIZED (widget))
2026 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2027 gdk_window_set_background (GTK_ENTRY (widget)->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2030 if (GTK_WIDGET_DRAWABLE (widget))
2031 gtk_widget_queue_clear(widget);
2035 gtk_entry_commit_cb (GtkIMContext *context,
2039 GtkEditable *editable = GTK_EDITABLE (entry);
2040 gint tmp_pos = editable->current_pos;
2042 gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
2043 editable->current_pos = tmp_pos;