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.
24 #include "gdk/gdkkeysyms.h"
25 #include "gdk/gdki18n.h"
28 #include "gtkselection.h"
29 #include "gtksignal.h"
30 #include "gtkprivate.h"
32 #define MIN_ENTRY_WIDTH 150
33 #define DRAW_TIMEOUT 20
34 #define INNER_BORDER 2
36 static void gtk_entry_class_init (GtkEntryClass *klass);
37 static void gtk_entry_init (GtkEntry *entry);
38 static void gtk_entry_finalize (GtkObject *object);
39 static void gtk_entry_realize (GtkWidget *widget);
40 static void gtk_entry_unrealize (GtkWidget *widget);
41 static void gtk_entry_draw_focus (GtkWidget *widget);
42 static void gtk_entry_size_request (GtkWidget *widget,
43 GtkRequisition *requisition);
44 static void gtk_entry_size_allocate (GtkWidget *widget,
45 GtkAllocation *allocation);
46 static void gtk_entry_make_backing_pixmap (GtkEntry *entry,
47 gint width, gint height);
48 static void gtk_entry_draw (GtkWidget *widget,
50 static gint gtk_entry_expose (GtkWidget *widget,
51 GdkEventExpose *event);
52 static gint gtk_entry_button_press (GtkWidget *widget,
53 GdkEventButton *event);
54 static gint gtk_entry_button_release (GtkWidget *widget,
55 GdkEventButton *event);
56 static gint gtk_entry_motion_notify (GtkWidget *widget,
57 GdkEventMotion *event);
58 static gint gtk_entry_key_press (GtkWidget *widget,
60 static gint gtk_entry_focus_in (GtkWidget *widget,
61 GdkEventFocus *event);
62 static gint gtk_entry_focus_out (GtkWidget *widget,
63 GdkEventFocus *event);
64 static void gtk_entry_draw_text (GtkEntry *entry);
65 static void gtk_entry_draw_cursor (GtkEntry *entry);
66 static void gtk_entry_draw_cursor_on_drawable
68 GdkDrawable *drawable);
69 static void gtk_entry_style_set (GtkWidget *widget,
70 GtkStyle *previous_style);
71 static void gtk_entry_queue_draw (GtkEntry *entry);
72 static gint gtk_entry_timer (gpointer data);
73 static gint gtk_entry_position (GtkEntry *entry,
75 void gtk_entry_adjust_scroll (GtkEntry *entry);
76 static void gtk_entry_grow_text (GtkEntry *entry);
77 static void gtk_entry_insert_text (GtkEditable *editable,
78 const gchar *new_text,
81 static void gtk_entry_delete_text (GtkEditable *editable,
84 static void gtk_entry_update_text (GtkEditable *editable,
87 static gchar *gtk_entry_get_chars (GtkEditable *editable,
92 static void gtk_entry_move_cursor (GtkEditable *editable,
95 static void gtk_entry_move_word (GtkEditable *editable,
97 static void gtk_entry_move_to_column (GtkEditable *editable,
99 static void gtk_entry_kill_char (GtkEditable *editable,
101 static void gtk_entry_kill_word (GtkEditable *editable,
103 static void gtk_entry_kill_line (GtkEditable *editable,
107 static void gtk_move_forward_character (GtkEntry *entry);
108 static void gtk_move_backward_character (GtkEntry *entry);
109 static void gtk_move_forward_word (GtkEntry *entry);
110 static void gtk_move_backward_word (GtkEntry *entry);
111 static void gtk_move_beginning_of_line (GtkEntry *entry);
112 static void gtk_move_end_of_line (GtkEntry *entry);
113 static void gtk_delete_forward_character (GtkEntry *entry);
114 static void gtk_delete_backward_character (GtkEntry *entry);
115 static void gtk_delete_forward_word (GtkEntry *entry);
116 static void gtk_delete_backward_word (GtkEntry *entry);
117 static void gtk_delete_line (GtkEntry *entry);
118 static void gtk_delete_to_line_end (GtkEntry *entry);
119 static void gtk_select_word (GtkEntry *entry,
121 static void gtk_select_line (GtkEntry *entry,
125 static void gtk_entry_set_selection (GtkEditable *editable,
129 static void gtk_entry_recompute_offsets (GtkEntry *entry);
130 static gint gtk_entry_find_char (GtkEntry *entry,
132 static gint gtk_entry_find_position (GtkEntry *entry,
134 static void gtk_entry_set_position_from_editable (GtkEditable *editable,
137 static GtkWidgetClass *parent_class = NULL;
138 static GdkAtom ctext_atom = GDK_NONE;
140 static GtkTextFunction control_keys[26] =
142 (GtkTextFunction)gtk_move_beginning_of_line, /* a */
143 (GtkTextFunction)gtk_move_backward_character, /* b */
144 (GtkTextFunction)gtk_editable_copy_clipboard, /* c */
145 (GtkTextFunction)gtk_delete_forward_character, /* d */
146 (GtkTextFunction)gtk_move_end_of_line, /* e */
147 (GtkTextFunction)gtk_move_forward_character, /* f */
149 (GtkTextFunction)gtk_delete_backward_character, /* h */
152 (GtkTextFunction)gtk_delete_to_line_end, /* k */
162 (GtkTextFunction)gtk_delete_line, /* u */
163 (GtkTextFunction)gtk_editable_paste_clipboard, /* v */
164 (GtkTextFunction)gtk_delete_backward_word, /* w */
165 (GtkTextFunction)gtk_editable_cut_clipboard, /* x */
170 static GtkTextFunction alt_keys[26] =
173 (GtkTextFunction)gtk_move_backward_word, /* b */
175 (GtkTextFunction)gtk_delete_forward_word, /* d */
177 (GtkTextFunction)gtk_move_forward_word, /* f */
202 gtk_entry_get_type (void)
204 static guint entry_type = 0;
208 GtkTypeInfo entry_info =
212 sizeof (GtkEntryClass),
213 (GtkClassInitFunc) gtk_entry_class_init,
214 (GtkObjectInitFunc) gtk_entry_init,
215 (GtkArgSetFunc) NULL,
216 (GtkArgGetFunc) NULL,
219 entry_type = gtk_type_unique (gtk_editable_get_type (), &entry_info);
226 gtk_entry_class_init (GtkEntryClass *class)
228 GtkObjectClass *object_class;
229 GtkWidgetClass *widget_class;
230 GtkEditableClass *editable_class;
232 object_class = (GtkObjectClass*) class;
233 widget_class = (GtkWidgetClass*) class;
234 editable_class = (GtkEditableClass*) class;
236 parent_class = gtk_type_class (gtk_editable_get_type ());
238 object_class->finalize = gtk_entry_finalize;
240 widget_class->realize = gtk_entry_realize;
241 widget_class->unrealize = gtk_entry_unrealize;
242 widget_class->draw_focus = gtk_entry_draw_focus;
243 widget_class->size_request = gtk_entry_size_request;
244 widget_class->size_allocate = gtk_entry_size_allocate;
245 widget_class->draw = gtk_entry_draw;
246 widget_class->expose_event = gtk_entry_expose;
247 widget_class->button_press_event = gtk_entry_button_press;
248 widget_class->button_release_event = gtk_entry_button_release;
249 widget_class->motion_notify_event = gtk_entry_motion_notify;
250 widget_class->key_press_event = gtk_entry_key_press;
251 widget_class->focus_in_event = gtk_entry_focus_in;
252 widget_class->focus_out_event = gtk_entry_focus_out;
253 widget_class->style_set = gtk_entry_style_set;
255 editable_class->insert_text = gtk_entry_insert_text;
256 editable_class->delete_text = gtk_entry_delete_text;
257 editable_class->changed = (void (*)(GtkEditable *)) gtk_entry_adjust_scroll;
259 editable_class->move_cursor = gtk_entry_move_cursor;
260 editable_class->move_word = gtk_entry_move_word;
261 editable_class->move_to_column = gtk_entry_move_to_column;
263 editable_class->kill_char = gtk_entry_kill_char;
264 editable_class->kill_word = gtk_entry_kill_word;
265 editable_class->kill_line = gtk_entry_kill_line;
267 editable_class->update_text = gtk_entry_update_text;
268 editable_class->get_chars = gtk_entry_get_chars;
269 editable_class->set_selection = gtk_entry_set_selection;
270 editable_class->set_position = gtk_entry_set_position_from_editable;
274 gtk_entry_init (GtkEntry *entry)
276 GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
278 entry->text_area = NULL;
279 entry->backing_pixmap = NULL;
281 entry->text_size = 0;
282 entry->text_length = 0;
283 entry->text_max_length = 0;
284 entry->scroll_offset = 0;
290 entry->char_pos = NULL;
291 entry->char_offset = NULL;
293 gtk_entry_grow_text (entry);
299 return GTK_WIDGET (gtk_type_new (gtk_entry_get_type ()));
303 gtk_entry_new_with_max_length (guint16 max)
306 entry = gtk_type_new (gtk_entry_get_type ());
307 entry->text_max_length = max;
308 return GTK_WIDGET (entry);
312 gtk_entry_set_text (GtkEntry *entry,
317 GtkEditable *editable;
319 g_return_if_fail (entry != NULL);
320 g_return_if_fail (GTK_IS_ENTRY (entry));
321 g_return_if_fail (text != NULL);
323 editable = GTK_EDITABLE (entry);
325 gtk_entry_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
328 gtk_editable_insert_text (editable, text, strlen (text), &tmp_pos);
329 editable->current_pos = tmp_pos;
331 editable->selection_start_pos = 0;
332 editable->selection_end_pos = 0;
334 if (GTK_WIDGET_DRAWABLE (entry))
335 gtk_entry_draw_text (entry);
339 gtk_entry_append_text (GtkEntry *entry,
344 g_return_if_fail (entry != NULL);
345 g_return_if_fail (GTK_IS_ENTRY (entry));
346 g_return_if_fail (text != NULL);
348 tmp_pos = entry->text_length;
349 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
350 GTK_EDITABLE(entry)->current_pos = tmp_pos;
354 gtk_entry_prepend_text (GtkEntry *entry,
359 g_return_if_fail (entry != NULL);
360 g_return_if_fail (GTK_IS_ENTRY (entry));
361 g_return_if_fail (text != NULL);
364 gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
365 GTK_EDITABLE(entry)->current_pos = tmp_pos;
369 gtk_entry_set_position (GtkEntry *entry,
372 g_return_if_fail (entry != NULL);
373 g_return_if_fail (GTK_IS_ENTRY (entry));
375 if ((position == -1) || (position > entry->text_length))
376 GTK_EDITABLE(entry)->current_pos = entry->text_length;
378 GTK_EDITABLE(entry)->current_pos = position;
382 gtk_entry_set_position_from_editable (GtkEditable *editable,
385 gtk_entry_set_position (GTK_ENTRY (editable), position);
389 gtk_entry_set_visibility (GtkEntry *entry,
392 g_return_if_fail (entry != NULL);
393 g_return_if_fail (GTK_IS_ENTRY (entry));
395 entry->visible = visible;
396 gtk_entry_recompute_offsets (entry);
397 gtk_widget_queue_draw (GTK_WIDGET (entry));
401 gtk_entry_set_editable(GtkEntry *entry,
404 g_return_if_fail (entry != NULL);
405 g_return_if_fail (GTK_IS_ENTRY (entry));
407 GTK_EDITABLE (entry)->editable = editable;
408 gtk_entry_queue_draw (entry);
412 gtk_entry_get_text (GtkEntry *entry)
414 static char empty_str[2] = "";
416 g_return_val_if_fail (entry != NULL, NULL);
417 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
425 gtk_entry_finalize (GtkObject *object)
429 g_return_if_fail (object != NULL);
430 g_return_if_fail (GTK_IS_ENTRY (object));
432 entry = GTK_ENTRY (object);
435 if (GTK_EDITABLE(entry)->ic)
437 gdk_ic_destroy (GTK_EDITABLE(entry)->ic);
438 GTK_EDITABLE(entry)->ic = NULL;
443 gtk_timeout_remove (entry->timer);
445 entry->text_size = 0;
447 g_free (entry->text);
449 g_free (entry->char_pos);
450 if (entry->char_offset)
451 g_free (entry->char_offset);
454 if (entry->backing_pixmap)
455 gdk_pixmap_unref (entry->backing_pixmap);
457 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
461 gtk_entry_realize (GtkWidget *widget)
464 GtkEditable *editable;
465 GdkWindowAttr attributes;
466 gint attributes_mask;
468 g_return_if_fail (widget != NULL);
469 g_return_if_fail (GTK_IS_ENTRY (widget));
471 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
472 entry = GTK_ENTRY (widget);
473 editable = GTK_EDITABLE (widget);
475 attributes.window_type = GDK_WINDOW_CHILD;
476 attributes.x = widget->allocation.x;
477 attributes.y = widget->allocation.y + (widget->allocation.height -
478 widget->requisition.height) / 2;
479 attributes.width = widget->allocation.width;
480 attributes.height = widget->requisition.height;
481 attributes.wclass = GDK_INPUT_OUTPUT;
482 attributes.visual = gtk_widget_get_visual (widget);
483 attributes.colormap = gtk_widget_get_colormap (widget);
484 attributes.event_mask = gtk_widget_get_events (widget);
485 attributes.event_mask |= (GDK_EXPOSURE_MASK |
486 GDK_BUTTON_PRESS_MASK |
487 GDK_BUTTON_RELEASE_MASK |
488 GDK_BUTTON1_MOTION_MASK |
489 GDK_BUTTON3_MOTION_MASK |
490 GDK_POINTER_MOTION_HINT_MASK |
491 GDK_ENTER_NOTIFY_MASK |
492 GDK_LEAVE_NOTIFY_MASK |
494 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
496 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
497 gdk_window_set_user_data (widget->window, entry);
499 attributes.x = widget->style->klass->xthickness + INNER_BORDER;
500 attributes.y = widget->style->klass->ythickness + INNER_BORDER;
501 attributes.width = widget->allocation.width - attributes.x * 2;
502 attributes.height = widget->requisition.height - attributes.y * 2;
503 attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
504 attributes_mask |= GDK_WA_CURSOR;
506 entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
507 gdk_window_set_user_data (entry->text_area, entry);
509 widget->style = gtk_style_attach (widget->style, widget->window);
511 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
512 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_STATE_NORMAL]);
522 GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing |
523 GdkIMPreeditPosition |
524 GdkIMStatusNone | GdkIMStatusNothing;
526 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
527 supported_style &= ~GdkIMPreeditPosition;
529 style = gdk_im_decide_style (supported_style);
530 switch (style & GdkIMPreeditMask)
532 case GdkIMPreeditPosition:
533 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
535 g_warning ("over-the-spot style requires fontset");
538 gdk_window_get_size (entry->text_area, &width, &height);
542 rect.height = height;
545 editable->ic = gdk_ic_new (entry->text_area, entry->text_area,
547 "spotLocation", &spot,
549 "fontSet", GDK_FONT_XFONT (widget->style->font),
553 editable->ic = gdk_ic_new (entry->text_area, entry->text_area,
557 if (editable->ic == NULL)
558 g_warning ("Can't create input context.");
561 GdkColormap *colormap;
563 mask = gdk_window_get_events (entry->text_area);
564 mask |= gdk_ic_get_events (editable->ic);
565 gdk_window_set_events (entry->text_area, mask);
567 if ((colormap = gtk_widget_get_colormap (widget)) !=
568 gtk_widget_get_default_colormap ())
570 gdk_ic_set_attr (editable->ic, "preeditAttributes",
571 "colorMap", GDK_COLORMAP_XCOLORMAP (colormap),
574 gdk_ic_set_attr (editable->ic,"preeditAttributes",
575 "foreground", widget->style->fg[GTK_STATE_NORMAL].pixel,
576 "background", widget->style->base[GTK_STATE_NORMAL].pixel,
582 gdk_window_show (entry->text_area);
584 if (editable->selection_start_pos != editable->selection_end_pos)
585 gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
587 gtk_entry_recompute_offsets (entry);
591 gtk_entry_unrealize (GtkWidget *widget)
595 g_return_if_fail (widget != NULL);
596 g_return_if_fail (GTK_IS_ENTRY (widget));
598 entry = GTK_ENTRY (widget);
600 if (entry->text_area)
602 gdk_window_set_user_data (entry->text_area, NULL);
603 gdk_window_destroy (entry->text_area);
604 entry->text_area = NULL;
605 gdk_cursor_destroy (entry->cursor);
606 entry->cursor = NULL;
609 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
610 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
614 gtk_entry_draw_focus (GtkWidget *widget)
619 g_return_if_fail (widget != NULL);
620 g_return_if_fail (GTK_IS_ENTRY (widget));
622 if (GTK_WIDGET_DRAWABLE (widget))
626 gdk_window_get_size (widget->window, &width, &height);
628 if (GTK_WIDGET_HAS_FOCUS (widget))
637 gdk_draw_rectangle (widget->window,
638 widget->style->base_gc[GTK_WIDGET_STATE(widget)],
639 FALSE, x + 2, y + 2, width - 5, height - 5);
642 gtk_draw_shadow (widget->style, widget->window,
643 GTK_STATE_NORMAL, GTK_SHADOW_IN,
644 x, y, width, height);
646 if (GTK_WIDGET_HAS_FOCUS (widget))
648 gdk_window_get_size (widget->window, &width, &height);
649 gdk_draw_rectangle (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
650 FALSE, 0, 0, width - 1, height - 1);
653 if (GTK_EDITABLE (widget)->editable)
654 gtk_entry_draw_cursor (GTK_ENTRY (widget));
659 gtk_entry_size_request (GtkWidget *widget,
660 GtkRequisition *requisition)
662 g_return_if_fail (widget != NULL);
663 g_return_if_fail (GTK_IS_ENTRY (widget));
664 g_return_if_fail (requisition != NULL);
666 requisition->width = MIN_ENTRY_WIDTH + (widget->style->klass->xthickness + INNER_BORDER) * 2;
667 requisition->height = (widget->style->font->ascent +
668 widget->style->font->descent +
669 (widget->style->klass->ythickness + INNER_BORDER) * 2);
673 gtk_entry_size_allocate (GtkWidget *widget,
674 GtkAllocation *allocation)
677 GtkEditable *editable;
679 g_return_if_fail (widget != NULL);
680 g_return_if_fail (GTK_IS_ENTRY (widget));
681 g_return_if_fail (allocation != NULL);
683 widget->allocation = *allocation;
684 entry = GTK_ENTRY (widget);
685 editable = GTK_EDITABLE (widget);
687 if (GTK_WIDGET_REALIZED (widget))
689 gdk_window_move_resize (widget->window,
691 allocation->y + (allocation->height - widget->requisition.height) / 2,
692 allocation->width, widget->requisition.height);
693 gdk_window_move_resize (entry->text_area,
694 widget->style->klass->xthickness + INNER_BORDER,
695 widget->style->klass->ythickness + INNER_BORDER,
696 allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
697 widget->requisition.height - (widget->style->klass->ythickness + INNER_BORDER) * 2);
699 /* And make sure the cursor is on screen */
700 gtk_entry_adjust_scroll (entry);
703 if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition))
708 gdk_window_get_size (entry->text_area, &width, &height);
712 rect.height = height;
713 gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL);
720 gtk_entry_draw (GtkWidget *widget,
723 g_return_if_fail (widget != NULL);
724 g_return_if_fail (GTK_IS_ENTRY (widget));
725 g_return_if_fail (area != NULL);
727 if (GTK_WIDGET_DRAWABLE (widget))
729 gtk_widget_draw_focus (widget);
730 gtk_entry_draw_text (GTK_ENTRY (widget));
735 gtk_entry_expose (GtkWidget *widget,
736 GdkEventExpose *event)
740 g_return_val_if_fail (widget != NULL, FALSE);
741 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
742 g_return_val_if_fail (event != NULL, FALSE);
744 entry = GTK_ENTRY (widget);
746 if (widget->window == event->window)
747 gtk_widget_draw_focus (widget);
748 else if (entry->text_area == event->window)
749 gtk_entry_draw_text (GTK_ENTRY (widget));
755 gtk_entry_button_press (GtkWidget *widget,
756 GdkEventButton *event)
759 GtkEditable *editable;
762 g_return_val_if_fail (widget != NULL, FALSE);
763 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
764 g_return_val_if_fail (event != NULL, FALSE);
766 if (ctext_atom == GDK_NONE)
767 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
769 entry = GTK_ENTRY (widget);
770 editable = GTK_EDITABLE (widget);
772 if (entry->button && (event->button != entry->button))
775 entry->button = event->button;
777 if (!GTK_WIDGET_HAS_FOCUS (widget))
778 gtk_widget_grab_focus (widget);
780 if (event->button == 1)
784 case GDK_BUTTON_PRESS:
785 gtk_grab_add (widget);
787 tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
788 /* Set it now, so we display things right. We'll unset it
789 * later if things don't work out */
790 editable->has_selection = TRUE;
791 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
792 editable->current_pos = editable->selection_start_pos;
795 case GDK_2BUTTON_PRESS:
796 gtk_select_word (entry, event->time);
799 case GDK_3BUTTON_PRESS:
800 gtk_select_line (entry, event->time);
807 else if (event->type == GDK_BUTTON_PRESS)
809 if ((event->button == 2) && editable->editable)
811 if (editable->selection_start_pos == editable->selection_end_pos ||
812 editable->has_selection)
813 editable->current_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
814 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
815 ctext_atom, event->time);
819 gtk_grab_add (widget);
821 tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
822 gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
823 editable->has_selection = FALSE;
824 editable->current_pos = editable->selection_start_pos;
826 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
827 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
835 gtk_entry_button_release (GtkWidget *widget,
836 GdkEventButton *event)
839 GtkEditable *editable;
841 g_return_val_if_fail (widget != NULL, FALSE);
842 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
843 g_return_val_if_fail (event != NULL, FALSE);
845 entry = GTK_ENTRY (widget);
846 editable = GTK_EDITABLE (widget);
848 if (entry->button != event->button)
853 if (event->button == 1)
855 gtk_grab_remove (widget);
857 editable->has_selection = FALSE;
858 if (editable->selection_start_pos != editable->selection_end_pos)
860 if (gtk_selection_owner_set (widget,
861 GDK_SELECTION_PRIMARY,
863 editable->has_selection = TRUE;
865 gtk_entry_queue_draw (entry);
869 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
870 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
873 else if (event->button == 3)
875 gtk_grab_remove (widget);
882 gtk_entry_motion_notify (GtkWidget *widget,
883 GdkEventMotion *event)
888 g_return_val_if_fail (widget != NULL, FALSE);
889 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
890 g_return_val_if_fail (event != NULL, FALSE);
892 entry = GTK_ENTRY (widget);
894 if (entry->button == 0)
898 if (event->is_hint || (entry->text_area != event->window))
899 gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
901 GTK_EDITABLE(entry)->selection_end_pos = gtk_entry_position (entry, x + entry->scroll_offset);
902 GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
903 gtk_entry_adjust_scroll (entry);
904 gtk_entry_queue_draw (entry);
910 gtk_entry_key_press (GtkWidget *widget,
914 GtkEditable *editable;
919 gint extend_selection;
922 g_return_val_if_fail (widget != NULL, FALSE);
923 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
924 g_return_val_if_fail (event != NULL, FALSE);
926 entry = GTK_ENTRY (widget);
927 editable = GTK_EDITABLE (widget);
930 if(editable->editable == FALSE)
933 initial_pos = editable->current_pos;
935 extend_selection = event->state & GDK_SHIFT_MASK;
936 extend_start = FALSE;
938 if (extend_selection)
940 if (editable->selection_start_pos == editable->selection_end_pos)
942 editable->selection_start_pos = editable->current_pos;
943 editable->selection_end_pos = editable->current_pos;
946 extend_start = (editable->current_pos == editable->selection_start_pos);
949 switch (event->keyval)
953 if (event->state & GDK_CONTROL_MASK)
954 gtk_delete_backward_word (entry);
956 gtk_delete_backward_character (entry);
960 gtk_delete_line (entry);
964 if (event->state & GDK_SHIFT_MASK)
966 extend_selection = FALSE;
967 gtk_editable_paste_clipboard (editable);
969 else if (event->state & GDK_CONTROL_MASK)
971 gtk_editable_copy_clipboard (editable);
975 /* gtk_toggle_insert(entry) -- IMPLEMENT */
980 if (event->state & GDK_CONTROL_MASK)
981 gtk_delete_forward_word (entry);
982 else if (event->state & GDK_SHIFT_MASK)
984 extend_selection = FALSE;
985 gtk_editable_cut_clipboard (editable);
988 gtk_delete_forward_character (entry);
992 gtk_move_beginning_of_line (entry);
996 gtk_move_end_of_line (entry);
1000 if (event->state & GDK_CONTROL_MASK)
1001 gtk_move_backward_word (entry);
1003 gtk_move_backward_character (entry);
1007 if (event->state & GDK_CONTROL_MASK)
1008 gtk_move_forward_word (entry);
1010 gtk_move_forward_character (entry);
1014 gtk_signal_emit_by_name (GTK_OBJECT (entry), "activate");
1016 /* The next two keys should not be inserted literally. Any others ??? */
1021 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1023 key = event->keyval;
1025 if (event->state & GDK_CONTROL_MASK)
1027 if ((key >= 'A') && (key <= 'Z'))
1030 if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1032 (* control_keys[key - 'a']) (editable, event->time);
1037 else if (event->state & GDK_MOD1_MASK)
1039 if ((key >= 'A') && (key <= 'Z'))
1042 if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1044 (* alt_keys[key - 'a']) (editable, event->time);
1050 if (event->length > 0)
1054 extend_selection = FALSE;
1055 gtk_editable_delete_selection (editable);
1057 tmp_pos = editable->current_pos;
1058 gtk_editable_insert_text (editable, event->string, event->length, &tmp_pos);
1059 editable->current_pos = tmp_pos;
1066 if (return_val && (editable->current_pos != initial_pos))
1068 if (extend_selection)
1070 if (editable->current_pos < editable->selection_start_pos)
1071 editable->selection_start_pos = editable->current_pos;
1072 else if (editable->current_pos > editable->selection_end_pos)
1073 editable->selection_end_pos = editable->current_pos;
1077 editable->selection_start_pos = editable->current_pos;
1079 editable->selection_end_pos = editable->current_pos;
1084 editable->selection_start_pos = 0;
1085 editable->selection_end_pos = 0;
1088 gtk_editable_claim_selection (editable,
1089 editable->selection_start_pos != editable->selection_end_pos,
1092 gtk_entry_adjust_scroll (entry);
1093 gtk_entry_queue_draw (entry);
1100 gtk_entry_focus_in (GtkWidget *widget,
1101 GdkEventFocus *event)
1103 g_return_val_if_fail (widget != NULL, FALSE);
1104 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1105 g_return_val_if_fail (event != NULL, FALSE);
1107 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1108 gtk_widget_draw_focus (widget);
1111 if (GTK_EDITABLE(widget)->ic)
1112 gdk_im_begin (GTK_EDITABLE(widget)->ic, GTK_ENTRY(widget)->text_area);
1119 gtk_entry_focus_out (GtkWidget *widget,
1120 GdkEventFocus *event)
1122 g_return_val_if_fail (widget != NULL, FALSE);
1123 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1124 g_return_val_if_fail (event != NULL, FALSE);
1126 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1127 gtk_widget_draw_focus (widget);
1137 gtk_entry_make_backing_pixmap (GtkEntry *entry, gint width, gint height)
1139 gint pixmap_width, pixmap_height;
1141 if (!entry->backing_pixmap)
1144 entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1150 /* reallocate if sizes don't match */
1151 gdk_window_get_size (entry->backing_pixmap,
1152 &pixmap_width, &pixmap_height);
1153 if ((pixmap_width != width) || (pixmap_height != height))
1155 gdk_pixmap_unref (entry->backing_pixmap);
1156 entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1164 gtk_entry_draw_text (GtkEntry *entry)
1167 GtkEditable *editable;
1168 GtkStateType selected_state;
1174 gint selection_start_char;
1175 gint selection_end_char;
1176 gint selection_start_pos;
1177 gint selection_end_pos;
1178 gint selection_start_xoffset;
1179 gint selection_end_xoffset;
1182 GdkDrawable *drawable;
1183 gint use_backing_pixmap;
1187 g_return_if_fail (entry != NULL);
1188 g_return_if_fail (GTK_IS_ENTRY (entry));
1192 gtk_timeout_remove (entry->timer);
1196 if (GTK_WIDGET_DRAWABLE (entry))
1198 widget = GTK_WIDGET (entry);
1199 editable = GTK_EDITABLE (entry);
1203 gdk_window_clear (entry->text_area);
1204 if (editable->editable)
1205 gtk_entry_draw_cursor (entry);
1209 gdk_window_get_size (entry->text_area, &width, &height);
1212 If the widget has focus, draw on a backing pixmap to avoid flickering
1213 and copy it to the text_area.
1214 Otherwise draw to text_area directly for better speed.
1216 use_backing_pixmap = GTK_WIDGET_HAS_FOCUS (widget) && (entry->text != NULL);
1217 if (use_backing_pixmap)
1219 gtk_entry_make_backing_pixmap (entry, width, height);
1220 drawable = entry->backing_pixmap;
1221 gdk_draw_rectangle (drawable,
1222 widget->style->base_gc[GTK_WIDGET_STATE(widget)],
1230 drawable = entry->text_area;
1231 gdk_window_clear (entry->text_area);
1234 y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
1235 y += widget->style->font->ascent;
1237 start_char = gtk_entry_find_position (entry, entry->scroll_offset);
1238 start_pos = entry->char_pos[start_char];
1239 start_xoffset = entry->char_offset[start_char] - entry->scroll_offset;
1241 end_char = gtk_entry_find_position (entry, entry->scroll_offset + width);
1242 end_pos = entry->char_pos[end_char];
1243 if (end_pos < entry->text_length)
1246 selected_state = GTK_STATE_SELECTED;
1247 if (!editable->has_selection)
1248 selected_state = GTK_STATE_ACTIVE;
1250 selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
1251 selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
1253 selection_start_pos = CLAMP (selection_start_pos, start_pos, end_pos);
1254 selection_end_pos = CLAMP (selection_end_pos, start_pos, end_pos);
1256 selection_start_char = gtk_entry_find_char(entry,selection_start_pos);
1257 selection_end_char = gtk_entry_find_char(entry,selection_end_pos);
1259 selection_start_xoffset =
1260 entry->char_offset[selection_start_char] - entry->scroll_offset;
1261 selection_end_xoffset =
1262 entry->char_offset[selection_end_char] -entry->scroll_offset;
1264 /* if entry->visible, print a bunch of stars. If not, print the standard text. */
1267 toprint = entry->text + start_pos;
1273 stars = g_malloc (end_char - start_char);
1274 for (i = 0; i < end_char - start_char; i++)
1278 /* Since '*' is always one byte, work in bytes */
1279 start_pos = start_char;
1280 selection_start_pos = selection_start_char;
1281 selection_end_pos = selection_end_char;
1285 if (selection_start_pos > start_pos)
1286 gdk_draw_text (drawable, widget->style->font,
1287 widget->style->fg_gc[GTK_STATE_NORMAL],
1290 selection_start_pos - start_pos);
1292 if ((selection_end_pos >= start_pos) &&
1293 (selection_start_pos < end_pos) &&
1294 (selection_start_pos != selection_end_pos))
1296 gdk_draw_rectangle (drawable,
1297 widget->style->bg_gc[selected_state],
1299 selection_start_xoffset,
1301 selection_end_xoffset - selection_start_xoffset,
1304 gdk_draw_text (drawable, widget->style->font,
1305 widget->style->fg_gc[selected_state],
1306 selection_start_xoffset, y,
1307 toprint + selection_start_pos - start_pos,
1308 selection_end_pos - selection_start_pos);
1311 if (selection_end_pos < end_pos)
1312 gdk_draw_text (drawable, widget->style->font,
1313 widget->style->fg_gc[GTK_STATE_NORMAL],
1314 selection_end_xoffset, y,
1315 toprint + selection_end_pos - start_pos,
1316 end_pos - selection_end_pos);
1318 /* free the space allocated for the stars if it's neccessary. */
1319 if (!entry->visible)
1322 if (editable->editable)
1323 gtk_entry_draw_cursor_on_drawable (entry, drawable);
1325 if (use_backing_pixmap)
1326 gdk_draw_pixmap(entry->text_area,
1327 widget->style->fg_gc[GTK_STATE_NORMAL],
1328 entry->backing_pixmap,
1329 0, 0, 0, 0, width, height);
1334 gtk_entry_draw_cursor (GtkEntry *entry)
1336 g_return_if_fail (entry != NULL);
1337 g_return_if_fail (GTK_IS_ENTRY (entry));
1339 gtk_entry_draw_cursor_on_drawable (entry, entry->text_area);
1343 gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
1346 GtkEditable *editable;
1349 gint text_area_height;
1351 g_return_if_fail (entry != NULL);
1352 g_return_if_fail (GTK_IS_ENTRY (entry));
1354 if (GTK_WIDGET_DRAWABLE (entry))
1356 widget = GTK_WIDGET (entry);
1357 editable = GTK_EDITABLE (entry);
1359 xoffset = entry->char_offset[gtk_entry_find_char (entry, editable->current_pos)];
1360 xoffset -= entry->scroll_offset;
1362 if (GTK_WIDGET_HAS_FOCUS (widget) &&
1363 (editable->selection_start_pos == editable->selection_end_pos))
1364 gc = widget->style->fg_gc[GTK_STATE_NORMAL];
1366 gc = widget->style->base_gc[GTK_WIDGET_STATE(widget)];
1368 gdk_window_get_size (entry->text_area, NULL, &text_area_height);
1369 gdk_draw_line (drawable, gc, xoffset, 0, xoffset, text_area_height);
1371 if (gdk_im_ready() && editable->ic &&
1372 gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)
1377 spot.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2;
1378 gdk_ic_set_attr (editable->ic, "preeditAttributes", "spotLocation", &spot, NULL);
1385 gtk_entry_queue_draw (GtkEntry *entry)
1387 g_return_if_fail (entry != NULL);
1388 g_return_if_fail (GTK_IS_ENTRY (entry));
1391 entry->timer = gtk_timeout_add (DRAW_TIMEOUT, gtk_entry_timer, entry);
1395 gtk_entry_timer (gpointer data)
1399 g_return_val_if_fail (data != NULL, FALSE);
1401 entry = GTK_ENTRY (data);
1403 gtk_entry_draw_text (entry);
1409 gtk_entry_find_position (GtkEntry *entry,
1413 gint end = entry->nchars;
1418 if (x >= entry->char_offset[end])
1421 /* invariant - char_offset[start] <= x < char_offset[end] */
1423 while (start != end)
1425 half = (start+end)/2;
1428 else if (entry->char_offset[half] <= x)
1438 gtk_entry_position (GtkEntry *entry,
1441 return entry->char_pos[gtk_entry_find_position(entry, x)];
1445 gtk_entry_adjust_scroll (GtkEntry *entry)
1447 gint xoffset, max_offset;
1448 gint text_area_width;
1450 g_return_if_fail (entry != NULL);
1451 g_return_if_fail (GTK_IS_ENTRY (entry));
1453 if (!entry->text_area)
1456 gdk_window_get_size (entry->text_area, &text_area_width, NULL);
1458 /* Display as much text as we can */
1459 max_offset = MAX(0, entry->char_offset[entry->nchars] - text_area_width);
1461 if (entry->scroll_offset > max_offset)
1462 entry->scroll_offset = max_offset;
1464 /* And make sure cursor is on screen */
1465 xoffset = entry->char_offset[gtk_entry_find_char (entry, GTK_EDITABLE(entry)->current_pos)];
1466 xoffset -= entry->scroll_offset;
1469 entry->scroll_offset += xoffset;
1471 else if (xoffset > text_area_width)
1472 entry->scroll_offset += xoffset - text_area_width + 1;
1476 gtk_entry_grow_text (GtkEntry *entry)
1481 g_return_if_fail (entry != NULL);
1482 g_return_if_fail (GTK_IS_ENTRY (entry));
1484 previous_size = entry->text_size;
1485 if (!entry->text_size)
1486 entry->text_size = 128;
1488 entry->text_size *= 2;
1489 entry->text = g_realloc (entry->text, entry->text_size);
1490 entry->char_pos = g_realloc (entry->char_pos,
1491 entry->text_size * sizeof(guint16));
1492 entry->char_offset = g_realloc (entry->char_offset,
1493 entry->text_size * sizeof(guint));
1495 if (entry->text_length == 0) /* initial allocation */
1497 entry->char_pos[0] = 0;
1498 entry->char_offset[0] = 0;
1501 for (i = previous_size; i < entry->text_size; i++)
1502 entry->text[i] = '\0';
1506 gtk_entry_insert_text (GtkEditable *editable,
1507 const gchar *new_text,
1508 gint new_text_length,
1521 gint insertion_chars;
1522 guint16 *insertion_pos = NULL; /* Quiet the compiler */
1526 g_return_if_fail (editable != NULL);
1527 g_return_if_fail (GTK_IS_ENTRY (editable));
1529 entry = GTK_ENTRY (editable);
1531 if (new_text_length < 0)
1532 new_text_length = strlen (new_text);
1534 /* The algorithms here will work as long as, the text size (a
1535 * multiple of 2), fits into a guint16 but we specify a shorter
1536 * maximum length so that if the user pastes a very long text, there
1537 * is not a long hang from the slow X_LOCALE functions. */
1539 if (entry->text_max_length == 0)
1542 max_length = MIN (2047, entry->text_max_length);
1544 /* Make sure we do not exceed the maximum size of the entry. */
1545 if (new_text_length + entry->text_length > max_length)
1546 new_text_length = max_length - entry->text_length;
1548 /* Don't insert anything, if there was nothing to insert. */
1549 if (new_text_length <= 0)
1552 /* Find the length of the inserted text in characters, chop off
1553 partial/invalid characters */
1558 insertion_pos = g_new (guint16, new_text_length+1);
1559 insertion_chars = 0;
1561 for (i=0; i<new_text_length; i+=len)
1563 len = mblen (&new_text[i], MIN(MB_CUR_MAX,new_text_length-i));
1566 insertion_pos[insertion_chars] = i;
1569 insertion_pos[insertion_chars] = i;
1571 new_text_length = i;
1574 insertion_chars = new_text_length;
1576 /* Make sure we are inserting at integral character position */
1577 start_char = gtk_entry_find_char (entry, *position);
1578 start_pos = entry->char_pos[start_char];
1580 end_pos = start_pos + new_text_length;
1581 last_pos = new_text_length + entry->text_length;
1583 if (editable->selection_start_pos >= *position)
1584 editable->selection_start_pos += new_text_length;
1585 if (editable->selection_end_pos >= *position)
1586 editable->selection_end_pos += new_text_length;
1588 while (last_pos >= entry->text_size)
1589 gtk_entry_grow_text (entry);
1592 for (i = last_pos - 1; i >= end_pos; i--)
1593 text[i] = text[i- (end_pos - start_pos)];
1594 for (i = start_pos; i < end_pos; i++)
1595 text[i] = new_text[i - start_pos];
1599 /* Fix up the character positions */
1601 end_char = start_char + insertion_chars;
1602 last_char = entry->nchars + insertion_chars;
1604 for (i = last_char; i >= end_char; i--)
1606 = entry->char_pos[i - insertion_chars] + new_text_length;
1608 for (i = 1; i < insertion_chars ; i++)
1609 entry->char_pos[start_char+i] =
1610 entry->char_pos[start_char] + insertion_pos[i];
1612 g_free (insertion_pos);
1617 last_char = last_pos;
1619 for (i = start_char ; i <= last_char ; i++)
1620 entry->char_pos[i] = i;
1623 /* Fix up the the character offsets */
1625 if (GTK_WIDGET_REALIZED (entry))
1629 for (i = last_char; i >= end_char; i--)
1630 entry->char_offset[i]
1631 = entry->char_offset[i - insertion_chars];
1633 for (i=start_char; i<end_char; i++)
1635 entry->char_offset[i] = entry->char_offset[start_char] + offset;
1638 offset += gdk_text_width (GTK_WIDGET (entry)->style->font,
1639 entry->text + entry->char_pos[i],
1640 entry->char_pos[i+1] - entry->char_pos[i]);
1644 offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1);
1647 for (i = end_char ; i <= last_char ; i++)
1648 entry->char_offset[i] += offset;
1651 entry->text_length += new_text_length;
1652 entry->nchars += insertion_chars;
1653 *position = end_pos;
1655 gtk_entry_queue_draw (entry);
1658 /* Recompute the x offsets of all characters in the buffer */
1660 gtk_entry_recompute_offsets (GtkEntry *entry)
1665 for (i=0; i<entry->nchars; i++)
1667 entry->char_offset[i] = offset;
1670 offset += gdk_text_width (GTK_WIDGET (entry)->style->font,
1671 entry->text + entry->char_pos[i],
1672 entry->char_pos[i+1] - entry->char_pos[i]);
1676 offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1);
1680 entry->char_offset[i] = offset;
1683 /* Given a position in the entry, find the character index of the
1684 * last character with position <= the given position
1687 gtk_entry_find_char (GtkEntry *entry, gint position)
1690 gint end = entry->nchars;
1693 if (position >= entry->char_pos[end])
1698 /* invariant - char_pos[start] <= position < char_pos[end] */
1700 while (start != end)
1702 half = (start+end)/2;
1705 else if (entry->char_pos[half] <= position)
1715 gtk_entry_delete_text (GtkEditable *editable,
1720 gint deletion_length;
1727 g_return_if_fail (editable != NULL);
1728 g_return_if_fail (GTK_IS_ENTRY (editable));
1730 entry = GTK_ENTRY (editable);
1733 end_pos = entry->text_length;
1735 start_char = gtk_entry_find_char (entry, start_pos);
1736 end_char = gtk_entry_find_char (entry, end_pos);
1737 start_pos = entry->char_pos[start_char];
1738 end_pos = entry->char_pos[end_char];
1740 if (editable->selection_start_pos > start_pos)
1741 editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos;
1742 if (editable->selection_end_pos > start_pos)
1743 editable->selection_end_pos -= MIN(end_pos, editable->selection_end_pos) - start_pos;
1745 if ((start_pos < end_pos) &&
1747 (end_pos <= entry->text_length))
1750 deletion_length = end_pos - start_pos;
1752 /* Fix up the character offsets */
1753 if (GTK_WIDGET_REALIZED (entry))
1755 gint deletion_width =
1756 entry->char_offset[end_char] - entry->char_offset[start_char];
1758 for (i = 0 ; i <= entry->nchars - end_char; i++)
1759 entry->char_offset[start_char+i] = entry->char_offset[end_char+i] - deletion_width;
1762 for (i = end_pos; i < entry->text_length; i++)
1763 text[i - deletion_length] = text[i];
1765 for (i = entry->text_length - deletion_length; i < entry->text_length; i++)
1768 for (i = 0 ; i <= entry->nchars - end_char; i++)
1769 entry->char_pos[start_char+i] = entry->char_pos[end_char+i] - deletion_length;
1771 entry->nchars -= end_char - start_char;
1773 entry->text_length -= deletion_length;
1774 editable->current_pos = start_pos;
1777 gtk_entry_queue_draw (entry);
1781 gtk_entry_update_text (GtkEditable *editable,
1785 gtk_entry_queue_draw (GTK_ENTRY(editable));
1789 gtk_entry_get_chars (GtkEditable *editable,
1797 g_return_val_if_fail (editable != NULL, NULL);
1798 g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL);
1800 entry = GTK_ENTRY (editable);
1803 end_pos = entry->text_length;
1805 start_pos = MIN(entry->text_length, start_pos);
1806 end_pos = MIN(entry->text_length, end_pos);
1808 if (start_pos <= end_pos)
1810 c = entry->text[end_pos];
1811 entry->text[end_pos] = '\0';
1813 retval = g_strdup (&entry->text[start_pos]);
1815 entry->text[end_pos] = c;
1824 gtk_entry_move_cursor (GtkEditable *editable,
1831 entry = GTK_ENTRY (editable);
1833 /* Horizontal motion */
1840 if (editable->current_pos < entry->text_length)
1842 len = mblen (entry->text+editable->current_pos, MB_CUR_MAX);
1843 editable->current_pos += (len>0)? len:1;
1845 if (editable->current_pos > entry->text_length)
1846 editable->current_pos = entry->text_length;
1850 if (editable->current_pos < entry->text_length)
1851 editable->current_pos ++;
1859 if (0 < editable->current_pos)
1862 editable->current_pos =
1863 entry->char_pos[gtk_entry_find_char (entry, editable->current_pos - 1)];
1865 editable->current_pos--;
1870 /* Ignore vertical motion */
1874 gtk_move_forward_character (GtkEntry *entry)
1876 gtk_entry_move_cursor (GTK_EDITABLE (entry), 1, 0);
1880 gtk_move_backward_character (GtkEntry *entry)
1882 gtk_entry_move_cursor (GTK_EDITABLE (entry), -1, 0);
1886 gtk_entry_move_word (GtkEditable *editable,
1892 gtk_move_forward_word (GTK_ENTRY (editable));
1897 gtk_move_backward_word (GTK_ENTRY (editable));
1902 gtk_move_forward_word (GtkEntry *entry)
1904 GtkEditable *editable;
1910 editable = GTK_EDITABLE (entry);
1912 if (entry->text && (editable->current_pos < entry->text_length))
1915 i = editable->current_pos;
1919 len = mbtowc (&c, text+i, MB_CUR_MAX);
1921 for (; i < entry->text_length; i+=len)
1923 len = mbtowc (&c, text+i, MB_CUR_MAX);
1924 if (len < 1 || iswalnum(c))
1928 for (; i < entry->text_length; i+=len)
1930 len = mbtowc (&c, text+i, MB_CUR_MAX);
1931 if (len < 1 || !iswalnum(c))
1935 editable->current_pos = i;
1936 if (editable->current_pos > entry->text_length)
1937 editable->current_pos = entry->text_length;
1941 if (!isalnum (text[i]))
1942 for (; i < entry->text_length; i++)
1944 if (isalnum(text[i]))
1948 for (; i < entry->text_length; i++)
1950 if (!isalnum(text[i]))
1954 editable->current_pos = i;
1960 gtk_move_backward_word (GtkEntry *entry)
1962 GtkEditable *editable;
1967 editable = GTK_EDITABLE (entry);
1969 if (entry->text && editable->current_pos > 0)
1975 i = gtk_entry_find_char (entry, editable->current_pos - 1);
1977 mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX);
1981 mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX);
1988 mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX);
1999 editable->current_pos = entry->char_pos[i];
2003 i = editable->current_pos - 1;
2005 if (!isalnum(text[i]))
2008 if (isalnum(text[i]))
2014 if (!isalnum(text[i]))
2024 editable->current_pos = i;
2031 gtk_entry_move_to_column (GtkEditable *editable, gint column)
2035 entry = GTK_ENTRY (editable);
2037 if (column < 0 || column > entry->nchars)
2038 editable->current_pos = entry->text_length;
2040 editable->current_pos = entry->char_pos[column];
2044 gtk_move_beginning_of_line (GtkEntry *entry)
2046 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
2050 gtk_move_end_of_line (GtkEntry *entry)
2052 gtk_entry_move_to_column (GTK_EDITABLE (entry), -1);
2056 gtk_entry_kill_char (GtkEditable *editable,
2059 if (editable->selection_start_pos != editable->selection_end_pos)
2060 gtk_editable_delete_selection (editable);
2063 gint old_pos = editable->current_pos;
2066 gtk_entry_move_cursor (editable, 1, 0);
2067 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2071 gtk_entry_move_cursor (editable, -1, 0);
2072 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2078 gtk_delete_forward_character (GtkEntry *entry)
2080 gtk_entry_kill_char (GTK_EDITABLE (entry), 1);
2084 gtk_delete_backward_character (GtkEntry *entry)
2086 gtk_entry_kill_char (GTK_EDITABLE (entry), -1);
2090 gtk_entry_kill_word (GtkEditable *editable,
2093 if (editable->selection_start_pos != editable->selection_end_pos)
2094 gtk_editable_delete_selection (editable);
2097 gint old_pos = editable->current_pos;
2100 gtk_entry_move_word (editable, 1);
2101 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2105 gtk_entry_move_word (editable, -1);
2106 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2112 gtk_delete_forward_word (GtkEntry *entry)
2114 gtk_entry_kill_word (GTK_EDITABLE (entry), 1);
2118 gtk_delete_backward_word (GtkEntry *entry)
2120 gtk_entry_kill_word (GTK_EDITABLE (entry), -1);
2124 gtk_entry_kill_line (GtkEditable *editable,
2127 gint old_pos = editable->current_pos;
2130 gtk_entry_move_to_column (editable, -1);
2131 gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2135 gtk_entry_move_to_column (editable, 0);
2136 gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2141 gtk_delete_line (GtkEntry *entry)
2143 gtk_entry_move_to_column (GTK_EDITABLE (entry), 0);
2144 gtk_entry_kill_line (GTK_EDITABLE (entry), 1);
2148 gtk_delete_to_line_end (GtkEntry *entry)
2150 gtk_editable_delete_text (GTK_EDITABLE(entry), GTK_EDITABLE(entry)->current_pos, entry->text_length);
2154 gtk_select_word (GtkEntry *entry,
2157 GtkEditable *editable;
2161 editable = GTK_EDITABLE (entry);
2163 gtk_move_backward_word (entry);
2164 start_pos = editable->current_pos;
2166 gtk_move_forward_word (entry);
2167 end_pos = editable->current_pos;
2169 editable->has_selection = TRUE;
2170 gtk_entry_set_selection (editable, start_pos, end_pos);
2171 gtk_editable_claim_selection (editable, start_pos != end_pos, time);
2175 gtk_select_line (GtkEntry *entry,
2178 GtkEditable *editable;
2180 editable = GTK_EDITABLE (entry);
2182 editable->has_selection = TRUE;
2183 gtk_entry_set_selection (editable, 0, entry->text_length);
2184 gtk_editable_claim_selection (editable, entry->text_length != 0, time);
2186 editable->current_pos = editable->selection_end_pos;
2190 gtk_entry_set_selection (GtkEditable *editable,
2194 g_return_if_fail (editable != NULL);
2195 g_return_if_fail (GTK_IS_ENTRY (editable));
2198 end = GTK_ENTRY (editable)->text_length;
2200 editable->selection_start_pos = start;
2201 editable->selection_end_pos = end;
2203 gtk_entry_queue_draw (GTK_ENTRY (editable));
2207 gtk_entry_select_region (GtkEntry *entry,
2211 gtk_editable_select_region (GTK_EDITABLE (entry), start, end);
2215 gtk_entry_set_max_length (GtkEntry *entry,
2218 g_return_if_fail (entry != NULL);
2219 g_return_if_fail (GTK_IS_ENTRY (entry));
2221 if (max && entry->text_length > max)
2222 gtk_editable_delete_text(GTK_EDITABLE(entry), max, -1);
2223 entry->text_max_length = max;
2227 gtk_entry_style_set (GtkWidget *widget,
2228 GtkStyle *previous_style)
2233 g_return_if_fail (widget != NULL);
2234 g_return_if_fail (GTK_IS_ENTRY (widget));
2236 if (previous_style && GTK_WIDGET_REALIZED (widget))
2238 entry = GTK_ENTRY (widget);
2240 scroll_char = gtk_entry_find_position (entry, entry->scroll_offset);
2241 gtk_entry_recompute_offsets (GTK_ENTRY (widget));
2242 entry->scroll_offset = entry->char_offset[scroll_char];
2243 gtk_entry_adjust_scroll (entry);
2245 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
2246 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_STATE_NORMAL]);
2249 if (GTK_WIDGET_DRAWABLE (widget))
2250 gdk_window_clear (widget->window);