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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "gdk/gdkkeysyms.h"
24 #include "gdk/gdki18n.h"
27 #include "gtkselection.h"
28 #include "gtksignal.h"
30 #define MIN_ENTRY_WIDTH 150
31 #define DRAW_TIMEOUT 20
32 #define INNER_BORDER 2
44 typedef void (*GtkTextFunction) (GtkEntry *entry, GdkEventKey *event);
45 typedef void (*GtkEntrySignal1) (GtkObject *object,
50 typedef void (*GtkEntrySignal2) (GtkObject *object,
56 static void gtk_entry_marshal_signal_1 (GtkObject *object,
60 static void gtk_entry_marshal_signal_2 (GtkObject *object,
65 static void gtk_entry_class_init (GtkEntryClass *klass);
66 static void gtk_entry_init (GtkEntry *entry);
67 static void gtk_entry_finalize (GtkObject *object);
68 static void gtk_entry_realize (GtkWidget *widget);
69 static void gtk_entry_unrealize (GtkWidget *widget);
70 static void gtk_entry_draw_focus (GtkWidget *widget);
71 static void gtk_entry_size_request (GtkWidget *widget,
72 GtkRequisition *requisition);
73 static void gtk_entry_size_allocate (GtkWidget *widget,
74 GtkAllocation *allocation);
75 static void gtk_entry_make_backing_pixmap (GtkEntry *entry,
76 gint width, gint height);
77 static void gtk_entry_draw (GtkWidget *widget,
79 static gint gtk_entry_expose (GtkWidget *widget,
80 GdkEventExpose *event);
81 static gint gtk_entry_button_press (GtkWidget *widget,
82 GdkEventButton *event);
83 static gint gtk_entry_button_release (GtkWidget *widget,
84 GdkEventButton *event);
85 static gint gtk_entry_motion_notify (GtkWidget *widget,
86 GdkEventMotion *event);
87 static gint gtk_entry_key_press (GtkWidget *widget,
89 static gint gtk_entry_focus_in (GtkWidget *widget,
90 GdkEventFocus *event);
91 static gint gtk_entry_focus_out (GtkWidget *widget,
92 GdkEventFocus *event);
93 static gint gtk_entry_selection_clear (GtkWidget *widget,
94 GdkEventSelection *event);
95 static void gtk_entry_selection_handler (GtkWidget *widget,
96 GtkSelectionData *selection_data,
98 static void gtk_entry_selection_received (GtkWidget *widget,
99 GtkSelectionData *selection_data);
100 static void gtk_entry_draw_text (GtkEntry *entry);
101 static void gtk_entry_draw_cursor (GtkEntry *entry);
102 static void gtk_entry_draw_cursor_on_drawable
104 GdkDrawable *drawable);
105 static void gtk_entry_queue_draw (GtkEntry *entry);
106 static gint gtk_entry_timer (gpointer data);
107 static gint gtk_entry_position (GtkEntry *entry,
109 void gtk_entry_adjust_scroll (GtkEntry *entry);
110 static void gtk_entry_grow_text (GtkEntry *entry);
111 static void gtk_entry_insert_text (GtkEntry *entry,
112 const gchar *new_text,
113 gint new_text_length,
115 static void gtk_entry_delete_text (GtkEntry *entry,
118 static void gtk_real_entry_insert_text (GtkEntry *entry,
119 const gchar *new_text,
120 gint new_text_length,
122 static void gtk_real_entry_delete_text (GtkEntry *entry,
126 static gint move_backward_character (gchar *str, gint index);
127 static void gtk_move_forward_character (GtkEntry *entry);
128 static void gtk_move_backward_character (GtkEntry *entry);
129 static void gtk_move_forward_word (GtkEntry *entry);
130 static void gtk_move_backward_word (GtkEntry *entry);
131 static void gtk_move_beginning_of_line (GtkEntry *entry);
132 static void gtk_move_end_of_line (GtkEntry *entry);
133 static void gtk_delete_forward_character (GtkEntry *entry);
134 static void gtk_delete_backward_character (GtkEntry *entry);
135 static void gtk_delete_forward_word (GtkEntry *entry);
136 static void gtk_delete_backward_word (GtkEntry *entry);
137 static void gtk_delete_line (GtkEntry *entry);
138 static void gtk_delete_to_line_end (GtkEntry *entry);
139 static void gtk_delete_selection (GtkEntry *entry);
140 static void gtk_select_word (GtkEntry *entry);
141 static void gtk_select_line (GtkEntry *entry);
142 static void gtk_entry_cut_clipboard (GtkEntry *entry,
144 static void gtk_entry_copy_clipboard (GtkEntry *entry,
146 static void gtk_entry_paste_clipboard (GtkEntry *entry,
149 static GtkWidgetClass *parent_class = NULL;
150 static gint entry_signals[LAST_SIGNAL] = { 0 };
151 static GdkAtom ctext_atom = GDK_NONE;
152 static GdkAtom text_atom = GDK_NONE;
153 static GdkAtom clipboard_atom = GDK_NONE;
155 static GtkTextFunction control_keys[26] =
157 (GtkTextFunction)gtk_move_beginning_of_line, /* a */
158 (GtkTextFunction)gtk_move_backward_character, /* b */
159 gtk_entry_copy_clipboard, /* c */
160 (GtkTextFunction)gtk_delete_forward_character, /* d */
161 (GtkTextFunction)gtk_move_end_of_line, /* e */
162 (GtkTextFunction)gtk_move_forward_character, /* f */
164 (GtkTextFunction)gtk_delete_backward_character, /* h */
167 (GtkTextFunction)gtk_delete_to_line_end, /* k */
177 (GtkTextFunction)gtk_delete_line, /* u */
178 gtk_entry_paste_clipboard, /* v */
179 (GtkTextFunction)gtk_delete_backward_word, /* w */
180 gtk_entry_cut_clipboard, /* x */
185 static GtkTextFunction alt_keys[26] =
188 (GtkTextFunction)gtk_move_backward_word, /* b */
190 (GtkTextFunction)gtk_delete_forward_word, /* d */
192 (GtkTextFunction)gtk_move_forward_word, /* f */
217 gtk_entry_get_type ()
219 static guint entry_type = 0;
223 GtkTypeInfo entry_info =
227 sizeof (GtkEntryClass),
228 (GtkClassInitFunc) gtk_entry_class_init,
229 (GtkObjectInitFunc) gtk_entry_init,
230 (GtkArgSetFunc) NULL,
231 (GtkArgGetFunc) NULL,
234 entry_type = gtk_type_unique (gtk_widget_get_type (), &entry_info);
241 gtk_entry_class_init (GtkEntryClass *class)
243 GtkObjectClass *object_class;
244 GtkWidgetClass *widget_class;
246 object_class = (GtkObjectClass*) class;
247 widget_class = (GtkWidgetClass*) class;
249 parent_class = gtk_type_class (gtk_widget_get_type ());
251 entry_signals[INSERT_TEXT] =
252 gtk_signal_new ("insert_text",
255 GTK_SIGNAL_OFFSET (GtkEntryClass, insert_text),
256 gtk_entry_marshal_signal_1,
258 GTK_TYPE_STRING, GTK_TYPE_INT,
260 entry_signals[DELETE_TEXT] =
261 gtk_signal_new ("delete_text",
264 GTK_SIGNAL_OFFSET (GtkEntryClass, delete_text),
265 gtk_entry_marshal_signal_2,
267 GTK_TYPE_INT, GTK_TYPE_INT);
268 entry_signals[CHANGED] =
269 gtk_signal_new ("changed",
272 GTK_SIGNAL_OFFSET (GtkEntryClass, changed),
273 gtk_signal_default_marshaller,
275 entry_signals[SET_TEXT] =
276 gtk_signal_new ("set_text",
279 GTK_SIGNAL_OFFSET (GtkEntryClass, set_text),
280 gtk_signal_default_marshaller,
282 entry_signals[ACTIVATE] =
283 gtk_signal_new ("activate",
286 GTK_SIGNAL_OFFSET (GtkEntryClass, activate),
287 gtk_signal_default_marshaller,
290 gtk_object_class_add_signals (object_class, entry_signals, LAST_SIGNAL);
292 object_class->finalize = gtk_entry_finalize;
294 widget_class->realize = gtk_entry_realize;
295 widget_class->unrealize = gtk_entry_unrealize;
296 widget_class->draw_focus = gtk_entry_draw_focus;
297 widget_class->size_request = gtk_entry_size_request;
298 widget_class->size_allocate = gtk_entry_size_allocate;
299 widget_class->draw = gtk_entry_draw;
300 widget_class->expose_event = gtk_entry_expose;
301 widget_class->button_press_event = gtk_entry_button_press;
302 widget_class->button_release_event = gtk_entry_button_release;
303 widget_class->motion_notify_event = gtk_entry_motion_notify;
304 widget_class->key_press_event = gtk_entry_key_press;
305 widget_class->focus_in_event = gtk_entry_focus_in;
306 widget_class->focus_out_event = gtk_entry_focus_out;
307 widget_class->selection_clear_event = gtk_entry_selection_clear;
308 widget_class->selection_received = gtk_entry_selection_received;
310 class->insert_text = gtk_real_entry_insert_text;
311 class->delete_text = gtk_real_entry_delete_text;
312 class->changed = gtk_entry_adjust_scroll;
313 class->set_text = NULL; /* user defined handling */
314 class->activate = NULL; /* user defined handling */
318 gtk_entry_init (GtkEntry *entry)
320 GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
322 entry->text_area = NULL;
323 entry->backing_pixmap = NULL;
325 entry->text_size = 0;
326 entry->text_length = 0;
327 entry->text_max_length = 0;
328 entry->current_pos = 0;
329 entry->selection_start_pos = 0;
330 entry->selection_end_pos = 0;
331 entry->scroll_offset = 0;
332 entry->have_selection = FALSE;
336 entry->clipboard_text = NULL;
343 clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
345 gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
346 GDK_TARGET_STRING, gtk_entry_selection_handler,
348 gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
349 GDK_TARGET_STRING, gtk_entry_selection_handler,
353 text_atom = gdk_atom_intern ("TEXT", FALSE);
355 gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
357 gtk_entry_selection_handler,
359 gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
361 gtk_entry_selection_handler,
365 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
367 gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
369 gtk_entry_selection_handler,
371 gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
373 gtk_entry_selection_handler,
376 gtk_entry_grow_text (entry);
382 return GTK_WIDGET (gtk_type_new (gtk_entry_get_type ()));
386 gtk_entry_new_with_max_length (guint16 max)
389 entry = gtk_type_new (gtk_entry_get_type ());
390 entry->text_max_length = max;
391 return GTK_WIDGET (entry);
395 gtk_entry_set_text (GtkEntry *entry,
400 g_return_if_fail (entry != NULL);
401 g_return_if_fail (GTK_IS_ENTRY (entry));
402 g_return_if_fail (text != NULL);
404 gtk_real_entry_delete_text (entry, 0, entry->text_length);
407 gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
408 entry->current_pos = tmp_pos;
410 entry->selection_start_pos = 0;
411 entry->selection_end_pos = 0;
413 if (GTK_WIDGET_DRAWABLE (entry))
414 gtk_entry_draw_text (entry);
416 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
420 gtk_entry_append_text (GtkEntry *entry,
425 g_return_if_fail (entry != NULL);
426 g_return_if_fail (GTK_IS_ENTRY (entry));
428 tmp_pos = entry->text_length;
429 gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
430 entry->current_pos = tmp_pos;
432 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
436 gtk_entry_prepend_text (GtkEntry *entry,
441 g_return_if_fail (entry != NULL);
442 g_return_if_fail (GTK_IS_ENTRY (entry));
445 gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
446 entry->current_pos = tmp_pos;
448 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
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 entry->current_pos = entry->text_length;
461 entry->current_pos = position;
465 gtk_entry_set_visibility (GtkEntry *entry,
468 g_return_if_fail (entry != NULL);
469 g_return_if_fail (GTK_IS_ENTRY (entry));
471 entry->visible = visible;
475 gtk_entry_set_editable(GtkEntry *entry,
478 g_return_if_fail (entry != NULL);
479 g_return_if_fail (GTK_IS_ENTRY (entry));
480 entry->editable = editable;
481 gtk_entry_queue_draw(entry);
485 gtk_entry_get_text (GtkEntry *entry)
487 static char empty_str[2] = "";
489 g_return_val_if_fail (entry != NULL, NULL);
490 g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
499 gtk_entry_marshal_signal_1 (GtkObject *object,
504 GtkEntrySignal1 rfunc;
506 rfunc = (GtkEntrySignal1) func;
508 (* rfunc) (object, GTK_VALUE_STRING (args[0]), GTK_VALUE_INT (args[1]),
509 GTK_VALUE_POINTER (args[2]), func_data);
513 gtk_entry_marshal_signal_2 (GtkObject *object,
518 GtkEntrySignal2 rfunc;
520 rfunc = (GtkEntrySignal2) func;
522 (* rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]),
527 gtk_entry_finalize (GtkObject *object)
531 g_return_if_fail (object != NULL);
532 g_return_if_fail (GTK_IS_ENTRY (object));
534 entry = GTK_ENTRY (object);
539 gdk_ic_destroy (entry->ic);
545 gtk_timeout_remove (entry->timer);
547 entry->text_size = 0;
549 g_free (entry->text);
552 if (entry->backing_pixmap)
553 gdk_pixmap_unref (entry->backing_pixmap);
555 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
559 gtk_entry_realize (GtkWidget *widget)
562 GdkWindowAttr attributes;
563 gint attributes_mask;
565 g_return_if_fail (widget != NULL);
566 g_return_if_fail (GTK_IS_ENTRY (widget));
568 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
569 entry = GTK_ENTRY (widget);
571 attributes.window_type = GDK_WINDOW_CHILD;
572 attributes.x = widget->allocation.x;
573 attributes.y = widget->allocation.y;
574 attributes.width = widget->allocation.width;
575 attributes.height = widget->allocation.height;
576 attributes.wclass = GDK_INPUT_OUTPUT;
577 attributes.visual = gtk_widget_get_visual (widget);
578 attributes.colormap = gtk_widget_get_colormap (widget);
579 attributes.event_mask = gtk_widget_get_events (widget);
580 attributes.event_mask |= (GDK_EXPOSURE_MASK |
581 GDK_BUTTON_PRESS_MASK |
582 GDK_BUTTON_RELEASE_MASK |
583 GDK_BUTTON1_MOTION_MASK |
584 GDK_BUTTON3_MOTION_MASK |
585 GDK_POINTER_MOTION_HINT_MASK |
586 GDK_ENTER_NOTIFY_MASK |
587 GDK_LEAVE_NOTIFY_MASK |
589 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
591 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
592 gdk_window_set_user_data (widget->window, entry);
594 attributes.x = widget->style->klass->xthickness + INNER_BORDER;
595 attributes.y = widget->style->klass->ythickness + INNER_BORDER;
596 attributes.width = widget->allocation.width - attributes.x * 2;
597 attributes.height = widget->allocation.height - attributes.y * 2;
598 attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
599 attributes_mask |= GDK_WA_CURSOR;
601 entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
602 gdk_window_set_user_data (entry->text_area, entry);
604 widget->style = gtk_style_attach (widget->style, widget->window);
606 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
607 gdk_window_set_background (entry->text_area, &widget->style->base[GTK_STATE_NORMAL]);
617 GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing |
618 GdkIMPreeditPosition |
619 GdkIMStatusNone | GdkIMStatusNothing;
621 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
622 supported_style &= ~GdkIMPreeditPosition;
624 style = gdk_im_decide_style (supported_style);
625 switch (style & GdkIMPreeditMask)
627 case GdkIMPreeditPosition:
628 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
630 g_warning ("over-the-spot style requires fontset");
633 gdk_window_get_size (entry->text_area, &width, &height);
637 rect.height = height;
640 entry->ic = gdk_ic_new (entry->text_area, entry->text_area,
642 "spotLocation", &spot,
644 "fontSet", GDK_FONT_XFONT (widget->style->font),
648 entry->ic = gdk_ic_new (entry->text_area, entry->text_area,
652 if (entry->ic == NULL)
653 g_warning ("Can't create input context.");
656 GdkColormap *colormap;
658 mask = gdk_window_get_events (entry->text_area);
659 mask |= gdk_ic_get_events (entry->ic);
660 gdk_window_set_events (entry->text_area, mask);
662 if ((colormap = gtk_widget_get_colormap (widget)) !=
663 gtk_widget_get_default_colormap ())
665 gdk_ic_set_attr (entry->ic, "preeditAttributes",
666 "colorMap", GDK_COLORMAP_XCOLORMAP (colormap),
669 gdk_ic_set_attr (entry->ic,"preeditAttributes",
670 "foreground", widget->style->fg[GTK_STATE_NORMAL].pixel,
671 "background", widget->style->base[GTK_STATE_NORMAL].pixel,
677 gdk_window_show (entry->text_area);
681 gtk_entry_unrealize (GtkWidget *widget)
685 g_return_if_fail (widget != NULL);
686 g_return_if_fail (GTK_IS_ENTRY (widget));
688 entry = GTK_ENTRY (widget);
690 if (entry->text_area)
692 gdk_window_set_user_data (entry->text_area, NULL);
693 gdk_window_destroy (entry->text_area);
694 entry->text_area = NULL;
695 gdk_cursor_destroy (entry->cursor);
696 entry->cursor = NULL;
699 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
700 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
704 gtk_entry_draw_focus (GtkWidget *widget)
709 g_return_if_fail (widget != NULL);
710 g_return_if_fail (GTK_IS_ENTRY (widget));
712 if (GTK_WIDGET_DRAWABLE (widget))
716 gdk_window_get_size (widget->window, &width, &height);
718 if (GTK_WIDGET_HAS_FOCUS (widget))
727 gdk_draw_rectangle (widget->window,
728 widget->style->base_gc[GTK_WIDGET_STATE(widget)],
729 FALSE, x + 2, y + 2, width - 5, height - 5);
732 gtk_draw_shadow (widget->style, widget->window,
733 GTK_STATE_NORMAL, GTK_SHADOW_IN,
734 x, y, width, height);
736 if (GTK_WIDGET_HAS_FOCUS (widget))
738 gdk_window_get_size (widget->window, &width, &height);
739 gdk_draw_rectangle (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
740 FALSE, 0, 0, width - 1, height - 1);
743 gtk_entry_draw_cursor (GTK_ENTRY (widget));
748 gtk_entry_size_request (GtkWidget *widget,
749 GtkRequisition *requisition)
751 g_return_if_fail (widget != NULL);
752 g_return_if_fail (GTK_IS_ENTRY (widget));
753 g_return_if_fail (requisition != NULL);
755 requisition->width = MIN_ENTRY_WIDTH + (widget->style->klass->xthickness + INNER_BORDER) * 2;
756 requisition->height = (widget->style->font->ascent +
757 widget->style->font->descent +
758 (widget->style->klass->ythickness + INNER_BORDER) * 2);
762 gtk_entry_size_allocate (GtkWidget *widget,
763 GtkAllocation *allocation)
767 g_return_if_fail (widget != NULL);
768 g_return_if_fail (GTK_IS_ENTRY (widget));
769 g_return_if_fail (allocation != NULL);
771 widget->allocation = *allocation;
772 entry = GTK_ENTRY (widget);
774 if (GTK_WIDGET_REALIZED (widget))
776 gdk_window_move_resize (widget->window,
778 allocation->y + (allocation->height - widget->requisition.height) / 2,
779 allocation->width, widget->requisition.height);
780 gdk_window_move_resize (entry->text_area,
781 widget->style->klass->xthickness + INNER_BORDER,
782 widget->style->klass->ythickness + INNER_BORDER,
783 allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
784 widget->requisition.height - (widget->style->klass->ythickness + INNER_BORDER) * 2);
786 entry->scroll_offset = 0;
787 gtk_entry_adjust_scroll (entry);
789 if (entry->ic && (gdk_ic_get_style (entry->ic) & GdkIMPreeditPosition))
794 gdk_window_get_size (entry->text_area, &width, &height);
798 rect.height = height;
799 gdk_ic_set_attr (entry->ic, "preeditAttributes", "area", &rect, NULL);
806 gtk_entry_draw (GtkWidget *widget,
809 g_return_if_fail (widget != NULL);
810 g_return_if_fail (GTK_IS_ENTRY (widget));
811 g_return_if_fail (area != NULL);
813 if (GTK_WIDGET_DRAWABLE (widget))
815 gtk_widget_draw_focus (widget);
816 gtk_entry_draw_text (GTK_ENTRY (widget));
821 gtk_entry_expose (GtkWidget *widget,
822 GdkEventExpose *event)
826 g_return_val_if_fail (widget != NULL, FALSE);
827 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
828 g_return_val_if_fail (event != NULL, FALSE);
830 entry = GTK_ENTRY (widget);
832 if (widget->window == event->window)
833 gtk_widget_draw_focus (widget);
834 else if (entry->text_area == event->window)
835 gtk_entry_draw_text (GTK_ENTRY (widget));
841 gtk_entry_button_press (GtkWidget *widget,
842 GdkEventButton *event)
847 g_return_val_if_fail (widget != NULL, FALSE);
848 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
849 g_return_val_if_fail (event != NULL, FALSE);
851 if (ctext_atom == GDK_NONE)
852 ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
854 entry = GTK_ENTRY (widget);
855 if (!GTK_WIDGET_HAS_FOCUS (widget))
856 gtk_widget_grab_focus (widget);
858 if (event->button == 1)
862 case GDK_BUTTON_PRESS:
863 gtk_grab_add (widget);
865 tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
866 gtk_entry_select_region (entry, tmp_pos, tmp_pos);
867 entry->current_pos = entry->selection_start_pos;
870 case GDK_2BUTTON_PRESS:
871 gtk_select_word (entry);
874 case GDK_3BUTTON_PRESS:
875 gtk_select_line (entry);
882 else if (event->type == GDK_BUTTON_PRESS)
884 if (event->button == 2)
886 if (entry->selection_start_pos == entry->selection_end_pos ||
887 entry->have_selection)
888 entry->current_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
889 gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
890 ctext_atom, event->time);
894 gtk_grab_add (widget);
896 tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
897 gtk_entry_select_region (entry, tmp_pos, tmp_pos);
898 entry->have_selection = FALSE;
899 entry->current_pos = entry->selection_start_pos;
907 gtk_entry_button_release (GtkWidget *widget,
908 GdkEventButton *event)
912 g_return_val_if_fail (widget != NULL, FALSE);
913 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
914 g_return_val_if_fail (event != NULL, FALSE);
916 if (event->button == 1)
918 entry = GTK_ENTRY (widget);
919 gtk_grab_remove (widget);
921 entry->have_selection = FALSE;
922 if (entry->selection_start_pos != entry->selection_end_pos)
924 if (gtk_selection_owner_set (widget,
925 GDK_SELECTION_PRIMARY,
928 entry->have_selection = TRUE;
929 gtk_entry_queue_draw (entry);
934 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
935 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
938 else if (event->button == 3)
940 gtk_grab_remove (widget);
941 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
942 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
949 gtk_entry_motion_notify (GtkWidget *widget,
950 GdkEventMotion *event)
955 g_return_val_if_fail (widget != NULL, FALSE);
956 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
957 g_return_val_if_fail (event != NULL, FALSE);
959 entry = GTK_ENTRY (widget);
962 if (event->is_hint || (entry->text_area != event->window))
963 gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
965 entry->selection_end_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
966 entry->current_pos = entry->selection_end_pos;
967 gtk_entry_adjust_scroll (entry);
968 gtk_entry_queue_draw (entry);
974 gtk_entry_key_press (GtkWidget *widget,
981 gint extend_selection;
984 g_return_val_if_fail (widget != NULL, FALSE);
985 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
986 g_return_val_if_fail (event != NULL, FALSE);
988 entry = GTK_ENTRY (widget);
991 if(entry->editable == FALSE)
994 extend_selection = event->state & GDK_SHIFT_MASK;
995 extend_start = FALSE;
997 if (extend_selection)
999 if (entry->selection_start_pos == entry->selection_end_pos)
1001 entry->selection_start_pos = entry->current_pos;
1002 entry->selection_end_pos = entry->current_pos;
1005 extend_start = (entry->current_pos == entry->selection_start_pos);
1008 switch (event->keyval)
1012 if (entry->selection_start_pos != entry->selection_end_pos)
1013 gtk_delete_selection (entry);
1014 else if (event->state & GDK_CONTROL_MASK)
1015 gtk_delete_backward_word (entry);
1017 gtk_delete_backward_character (entry);
1021 gtk_delete_line (entry);
1025 if (event->state & GDK_SHIFT_MASK)
1027 extend_selection = FALSE;
1028 gtk_entry_paste_clipboard (entry, event);
1030 else if (event->state & GDK_CONTROL_MASK)
1032 gtk_entry_copy_clipboard (entry, event);
1036 /* gtk_toggle_insert(entry) -- IMPLEMENT */
1041 if (event->state & GDK_CONTROL_MASK)
1042 gtk_delete_line (entry);
1043 else if (event->state & GDK_SHIFT_MASK)
1044 gtk_entry_cut_clipboard (entry, event);
1046 gtk_delete_forward_character (entry);
1050 gtk_move_beginning_of_line (entry);
1054 gtk_move_end_of_line (entry);
1058 gtk_move_backward_character (entry);
1062 gtk_move_forward_character (entry);
1066 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[ACTIVATE]);
1068 /* The next two keys should not be inserted literally. Any others ??? */
1073 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1075 key = event->keyval;
1077 if (event->state & GDK_CONTROL_MASK)
1079 if ((key >= 'A') && (key <= 'Z'))
1082 if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1084 (* control_keys[key - 'a']) (entry, event);
1089 else if (event->state & GDK_MOD1_MASK)
1091 if ((key >= 'A') && (key <= 'Z'))
1094 if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1096 (* alt_keys[key - 'a']) (entry, event);
1102 if (event->length > 0)
1104 extend_selection = FALSE;
1105 gtk_delete_selection (entry);
1107 tmp_pos = entry->current_pos;
1108 gtk_entry_insert_text (entry, event->string, event->length, &tmp_pos);
1109 entry->current_pos = tmp_pos;
1118 if (extend_selection)
1120 if (entry->current_pos < entry->selection_start_pos)
1121 entry->selection_start_pos = entry->current_pos;
1122 else if (entry->current_pos > entry->selection_end_pos)
1123 entry->selection_end_pos = entry->current_pos;
1127 entry->selection_start_pos = entry->current_pos;
1129 entry->selection_end_pos = entry->current_pos;
1134 entry->selection_start_pos = 0;
1135 entry->selection_end_pos = 0;
1139 if (entry->selection_start_pos != entry->selection_end_pos)
1141 if (gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time))
1143 entry->have_selection = TRUE;
1144 gtk_entry_queue_draw (entry);
1149 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
1150 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
1152 /* end of alex stuff */
1154 gtk_entry_adjust_scroll (entry);
1155 gtk_entry_queue_draw (entry);
1162 gtk_entry_focus_in (GtkWidget *widget,
1163 GdkEventFocus *event)
1165 g_return_val_if_fail (widget != NULL, FALSE);
1166 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1167 g_return_val_if_fail (event != NULL, FALSE);
1169 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1170 gtk_widget_draw_focus (widget);
1173 if (GTK_ENTRY(widget)->ic)
1174 gdk_im_begin (GTK_ENTRY(widget)->ic, GTK_ENTRY(widget)->text_area);
1181 gtk_entry_focus_out (GtkWidget *widget,
1182 GdkEventFocus *event)
1184 g_return_val_if_fail (widget != NULL, FALSE);
1185 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1186 g_return_val_if_fail (event != NULL, FALSE);
1188 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1189 gtk_widget_draw_focus (widget);
1199 gtk_entry_selection_clear (GtkWidget *widget,
1200 GdkEventSelection *event)
1204 g_return_val_if_fail (widget != NULL, FALSE);
1205 g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
1206 g_return_val_if_fail (event != NULL, FALSE);
1208 /* Let the selection handling code know that the selection
1209 * has been changed, since we've overriden the default handler */
1210 gtk_selection_clear (widget, event);
1212 entry = GTK_ENTRY (widget);
1214 if (event->selection == GDK_SELECTION_PRIMARY)
1216 if (entry->have_selection)
1218 entry->have_selection = FALSE;
1219 gtk_entry_queue_draw (entry);
1222 else if (event->selection == clipboard_atom)
1224 g_free (entry->clipboard_text);
1225 entry->clipboard_text = NULL;
1232 gtk_entry_selection_handler (GtkWidget *widget,
1233 GtkSelectionData *selection_data,
1237 gint selection_start_pos;
1238 gint selection_end_pos;
1243 g_return_if_fail (widget != NULL);
1244 g_return_if_fail (GTK_IS_ENTRY (widget));
1246 entry = GTK_ENTRY (widget);
1248 if (selection_data->selection == GDK_SELECTION_PRIMARY)
1250 selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
1251 selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
1252 str = &entry->text[selection_start_pos];
1253 length = selection_end_pos - selection_start_pos;
1255 else /* CLIPBOARD */
1257 if (!entry->clipboard_text)
1258 return; /* Refuse */
1260 str = entry->clipboard_text;
1261 length = strlen (entry->clipboard_text);
1264 if (selection_data->target == GDK_SELECTION_TYPE_STRING)
1266 gtk_selection_data_set (selection_data,
1267 GDK_SELECTION_TYPE_STRING,
1268 8*sizeof(gchar), str, length);
1270 else if (selection_data->target == text_atom ||
1271 selection_data->target == ctext_atom)
1281 gdk_string_to_compound_text (str, &encoding, &format, &text, &new_length);
1282 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1283 gdk_free_compound_text (text);
1289 gtk_entry_selection_received (GtkWidget *widget,
1290 GtkSelectionData *selection_data)
1296 enum {INVALID, STRING, CTEXT} type;
1298 g_return_if_fail (widget != NULL);
1299 g_return_if_fail (GTK_IS_ENTRY (widget));
1301 entry = GTK_ENTRY (widget);
1303 if (selection_data->type == GDK_TARGET_STRING)
1305 else if (selection_data->type == ctext_atom)
1310 if (type == INVALID || selection_data->length < 0)
1312 /* avoid infinite loop */
1313 if (selection_data->target != GDK_TARGET_STRING)
1314 gtk_selection_convert (widget, selection_data->selection,
1315 GDK_TARGET_STRING, GDK_CURRENT_TIME);
1321 if ((entry->selection_start_pos != entry->selection_end_pos) &&
1322 (!entry->have_selection ||
1323 (selection_data->selection == clipboard_atom)))
1327 /* Don't want to call gtk_delete_selection here if we are going
1328 * to reclaim the selection to avoid extra server traffic */
1329 if (entry->have_selection)
1331 gtk_entry_delete_text (entry,
1332 MIN (entry->selection_start_pos, entry->selection_end_pos),
1333 MAX (entry->selection_start_pos, entry->selection_end_pos));
1336 gtk_delete_selection (entry);
1339 tmp_pos = old_pos = entry->current_pos;
1344 selection_data->data[selection_data->length] = 0;
1345 gtk_entry_insert_text (entry, selection_data->data,
1346 strlen (selection_data->data), &tmp_pos);
1347 entry->current_pos = tmp_pos;
1355 count = gdk_text_property_to_text_list (selection_data->type,
1356 selection_data->format,
1357 selection_data->data,
1358 selection_data->length,
1360 for (i=0; i<count; i++)
1362 gtk_entry_insert_text (entry, list[i], strlen (list[i]), &tmp_pos);
1363 entry->current_pos = tmp_pos;
1366 gdk_free_text_list (list);
1369 case INVALID: /* quiet compiler */
1374 gtk_entry_select_region (entry, old_pos, entry->current_pos);
1376 gtk_entry_queue_draw (entry);
1380 gtk_entry_make_backing_pixmap (GtkEntry *entry, gint width, gint height)
1382 gint pixmap_width, pixmap_height;
1384 if (!entry->backing_pixmap)
1387 entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1393 /* reallocate if sizes don't match */
1394 gdk_window_get_size (entry->backing_pixmap,
1395 &pixmap_width, &pixmap_height);
1396 if ((pixmap_width != width) || (pixmap_height != height))
1398 gdk_pixmap_unref (entry->backing_pixmap);
1399 entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1407 gtk_entry_draw_text (GtkEntry *entry)
1410 GtkStateType selected_state;
1411 gint selection_start_pos;
1412 gint selection_end_pos;
1413 gint selection_start_xoffset;
1414 gint selection_end_xoffset;
1417 GdkDrawable *drawable;
1418 gint use_backing_pixmap;
1420 g_return_if_fail (entry != NULL);
1421 g_return_if_fail (GTK_IS_ENTRY (entry));
1425 gtk_timeout_remove (entry->timer);
1429 if (!entry->visible)
1431 gtk_entry_draw_cursor (entry);
1435 if (GTK_WIDGET_DRAWABLE (entry))
1437 widget = GTK_WIDGET (entry);
1441 gdk_window_clear (entry->text_area);
1442 if (entry->editable)
1443 gtk_entry_draw_cursor (entry);
1447 gdk_window_get_size (entry->text_area, &width, &height);
1450 If the widget has focus, draw on a backing pixmap to avoid flickering
1451 and copy it to the text_area.
1452 Otherwise draw to text_area directly for better speed.
1454 use_backing_pixmap = GTK_WIDGET_HAS_FOCUS (widget) && (entry->text != NULL);
1455 if (use_backing_pixmap)
1457 gtk_entry_make_backing_pixmap (entry, width, height);
1458 drawable = entry->backing_pixmap;
1459 gdk_draw_rectangle (drawable,
1460 widget->style->base_gc[GTK_WIDGET_STATE(widget)],
1468 drawable = entry->text_area;
1469 gdk_window_clear (entry->text_area);
1472 y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
1473 y += widget->style->font->ascent;
1475 if (entry->selection_start_pos != entry->selection_end_pos)
1477 selected_state = GTK_STATE_SELECTED;
1478 if (!entry->have_selection)
1479 selected_state = GTK_STATE_ACTIVE;
1481 selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
1482 selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
1484 selection_start_xoffset = gdk_text_width (widget->style->font,
1486 selection_start_pos);
1487 selection_end_xoffset = gdk_text_width (widget->style->font,
1491 if (selection_start_pos > 0)
1492 gdk_draw_text (drawable, widget->style->font,
1493 widget->style->fg_gc[GTK_STATE_NORMAL],
1494 -entry->scroll_offset, y,
1495 entry->text, selection_start_pos);
1497 gdk_draw_rectangle (drawable,
1498 widget->style->bg_gc[selected_state],
1500 -entry->scroll_offset + selection_start_xoffset,
1502 selection_end_xoffset - selection_start_xoffset,
1505 gdk_draw_text (drawable, widget->style->font,
1506 widget->style->fg_gc[selected_state],
1507 -entry->scroll_offset + selection_start_xoffset, y,
1508 entry->text + selection_start_pos,
1509 selection_end_pos - selection_start_pos);
1511 if (selection_end_pos < entry->text_length)
1512 gdk_draw_string (drawable, widget->style->font,
1513 widget->style->fg_gc[GTK_STATE_NORMAL],
1514 -entry->scroll_offset + selection_end_xoffset, y,
1515 entry->text + selection_end_pos);
1521 gdk_gc_get_values (widget->style->fg_gc[GTK_STATE_NORMAL], &values);
1522 gdk_draw_string (drawable, widget->style->font,
1523 widget->style->fg_gc[GTK_STATE_NORMAL],
1524 -entry->scroll_offset, y,
1528 if (entry->editable)
1529 gtk_entry_draw_cursor_on_drawable (entry, drawable);
1531 if (use_backing_pixmap)
1532 gdk_draw_pixmap(entry->text_area,
1533 widget->style->fg_gc[GTK_STATE_NORMAL],
1534 entry->backing_pixmap,
1535 0, 0, 0, 0, width, height);
1540 gtk_entry_draw_cursor (GtkEntry *entry)
1542 g_return_if_fail (entry != NULL);
1543 g_return_if_fail (GTK_IS_ENTRY (entry));
1545 gtk_entry_draw_cursor_on_drawable (entry, entry->text_area);
1549 gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
1554 gint text_area_height;
1556 g_return_if_fail (entry != NULL);
1557 g_return_if_fail (GTK_IS_ENTRY (entry));
1559 if (GTK_WIDGET_DRAWABLE (entry))
1561 widget = GTK_WIDGET (entry);
1563 if (entry->current_pos > 0 && entry->visible)
1564 xoffset = gdk_text_width (widget->style->font, entry->text, entry->current_pos);
1567 xoffset -= entry->scroll_offset;
1569 if (GTK_WIDGET_HAS_FOCUS (widget) &&
1570 (entry->selection_start_pos == entry->selection_end_pos))
1571 gc = widget->style->fg_gc[GTK_STATE_NORMAL];
1573 gc = widget->style->base_gc[GTK_WIDGET_STATE(widget)];
1575 gdk_window_get_size (entry->text_area, NULL, &text_area_height);
1576 gdk_draw_line (drawable, gc, xoffset, 0, xoffset, text_area_height);
1578 if (gdk_im_ready() && entry->ic &&
1579 gdk_ic_get_style (entry->ic) & GdkIMPreeditPosition)
1584 spot.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2;
1585 gdk_ic_set_attr (entry->ic, "preeditAttributes", "spotLocation", &spot, NULL);
1592 gtk_entry_queue_draw (GtkEntry *entry)
1594 g_return_if_fail (entry != NULL);
1595 g_return_if_fail (GTK_IS_ENTRY (entry));
1598 entry->timer = gtk_timeout_add (DRAW_TIMEOUT, gtk_entry_timer, entry);
1602 gtk_entry_timer (gpointer data)
1606 g_return_val_if_fail (data != NULL, FALSE);
1608 entry = GTK_ENTRY (data);
1610 gtk_entry_draw_text (entry);
1616 gtk_entry_position (GtkEntry *entry,
1625 g_return_val_if_fail (entry != NULL, 0);
1626 g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
1633 for (; i < entry->text_length; i+=len)
1635 len = mblen (entry->text+i, MB_CUR_MAX);
1636 /* character not supported in current locale is included */
1639 char_width = gdk_text_width (GTK_WIDGET (entry)->style->font,
1640 entry->text + i, len);
1642 if (x < (sum + char_width / 2))
1654 gtk_entry_adjust_scroll (GtkEntry *entry)
1657 gint text_area_width;
1659 g_return_if_fail (entry != NULL);
1660 g_return_if_fail (GTK_IS_ENTRY (entry));
1662 if (!entry->text_area)
1665 gdk_window_get_size (entry->text_area, &text_area_width, NULL);
1667 if (entry->current_pos > 0)
1668 xoffset = gdk_text_width (GTK_WIDGET (entry)->style->font, entry->text, entry->current_pos);
1671 xoffset -= entry->scroll_offset;
1674 entry->scroll_offset += xoffset;
1675 else if (xoffset > text_area_width)
1676 entry->scroll_offset += (xoffset - text_area_width) + 1;
1680 gtk_entry_grow_text (GtkEntry *entry)
1685 g_return_if_fail (entry != NULL);
1686 g_return_if_fail (GTK_IS_ENTRY (entry));
1688 previous_size = entry->text_size;
1689 if (!entry->text_size)
1690 entry->text_size = 128;
1692 entry->text_size *= 2;
1693 entry->text = g_realloc (entry->text, entry->text_size);
1695 for (i = previous_size; i < entry->text_size; i++)
1696 entry->text[i] = '\0';
1700 gtk_entry_insert_text (GtkEntry *entry,
1701 const gchar *new_text,
1702 gint new_text_length,
1708 g_return_if_fail (entry != NULL);
1709 g_return_if_fail (GTK_IS_ENTRY (entry));
1711 if (new_text_length <= 64)
1714 text = g_new (gchar, new_text_length);
1716 strncpy (text, new_text, new_text_length);
1718 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[INSERT_TEXT],
1719 text, new_text_length, position);
1720 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
1722 if (new_text_length > 64)
1727 gtk_entry_delete_text (GtkEntry *entry,
1731 g_return_if_fail (entry != NULL);
1732 g_return_if_fail (GTK_IS_ENTRY (entry));
1734 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[DELETE_TEXT],
1735 start_pos, end_pos);
1736 gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
1740 gtk_real_entry_insert_text (GtkEntry *entry,
1741 const gchar *new_text,
1742 gint new_text_length,
1751 g_return_if_fail (entry != NULL);
1752 g_return_if_fail (GTK_IS_ENTRY (entry));
1754 /* Make sure we do not exceed the maximum size of the entry. */
1755 if (entry->text_max_length != 0 &&
1756 new_text_length + entry->text_length > entry->text_max_length)
1757 new_text_length = entry->text_max_length - entry->text_length;
1759 /* Don't insert anything, if there was nothing to insert. */
1760 if (new_text_length <= 0)
1763 start_pos = *position;
1764 end_pos = start_pos + new_text_length;
1765 last_pos = new_text_length + entry->text_length;
1767 if (entry->selection_start_pos >= *position)
1768 entry->selection_start_pos += new_text_length;
1769 if (entry->selection_end_pos >= *position)
1770 entry->selection_end_pos += new_text_length;
1772 while (last_pos >= entry->text_size)
1773 gtk_entry_grow_text (entry);
1776 for (i = last_pos - 1; i >= end_pos; i--)
1777 text[i] = text[i- (end_pos - start_pos)];
1778 for (i = start_pos; i < end_pos; i++)
1779 text[i] = new_text[i - start_pos];
1781 entry->text_length += new_text_length;
1782 *position = end_pos;
1786 gtk_real_entry_delete_text (GtkEntry *entry,
1791 gint deletion_length;
1794 g_return_if_fail (entry != NULL);
1795 g_return_if_fail (GTK_IS_ENTRY (entry));
1797 if (entry->selection_start_pos > start_pos)
1798 entry->selection_start_pos -= MIN(end_pos, entry->selection_start_pos) - start_pos;
1799 if (entry->selection_end_pos > start_pos)
1800 entry->selection_end_pos -= MIN(end_pos, entry->selection_end_pos) - start_pos;
1802 if ((start_pos < end_pos) &&
1804 (end_pos <= entry->text_length))
1807 deletion_length = end_pos - start_pos;
1809 for (i = end_pos; i < entry->text_length; i++)
1810 text[i - deletion_length] = text[i];
1812 for (i = entry->text_length - deletion_length; i < entry->text_length; i++)
1815 entry->text_length -= deletion_length;
1816 entry->current_pos = start_pos;
1822 gtk_move_forward_character (GtkEntry *entry)
1826 if (entry->current_pos < entry->text_length)
1828 len = mblen (entry->text+entry->current_pos, MB_CUR_MAX);
1829 entry->current_pos += (len>0)? len:1;
1831 if (entry->current_pos > entry->text_length)
1832 entry->current_pos = entry->text_length;
1836 move_backward_character (gchar *str, gint index)
1843 for (i=0,len=0; i<index; i+=len)
1845 len = mblen (str+i, MB_CUR_MAX);
1853 gtk_move_backward_character (GtkEntry *entry)
1855 /* this routine is correct only if string is state-independent-encoded */
1857 if (0 < entry->current_pos)
1859 entry->current_pos = move_backward_character (entry->text,
1860 entry->current_pos);
1861 if (entry->current_pos < 0)
1862 entry->current_pos = 0;
1867 gtk_move_forward_word (GtkEntry *entry)
1877 i = entry->current_pos;
1879 len = mbtowc (&c, text+i, MB_CUR_MAX);
1881 for (; i < entry->text_length; i+=len)
1883 len = mbtowc (&c, text+i, MB_CUR_MAX);
1884 if (len < 1 || iswalnum(c))
1888 for (; i < entry->text_length; i+=len)
1890 len = mbtowc (&c, text+i, MB_CUR_MAX);
1891 if (len < 1 || !iswalnum(c))
1895 entry->current_pos = i;
1896 if (entry->current_pos > entry->text_length)
1897 entry->current_pos = entry->text_length;
1902 gtk_move_backward_word (GtkEntry *entry)
1912 i=move_backward_character(text, entry->current_pos);
1913 if (i < 0) /* Per */
1915 entry->selection_start_pos = 0;
1916 entry->selection_end_pos = 0;
1920 len = mbtowc (&c, text+i, MB_CUR_MAX);
1922 for (; i >= 0; i=move_backward_character(text, i))
1924 len = mbtowc (&c, text+i, MB_CUR_MAX);
1929 for (; i >= 0; i=move_backward_character(text, i))
1931 len = mbtowc (&c, text+i, MB_CUR_MAX);
1942 entry->current_pos = i;
1947 gtk_move_beginning_of_line (GtkEntry *entry)
1949 entry->current_pos = 0;
1953 gtk_move_end_of_line (GtkEntry *entry)
1955 entry->current_pos = entry->text_length;
1959 gtk_delete_forward_character (GtkEntry *entry)
1963 if (entry->selection_start_pos != entry->selection_end_pos)
1964 gtk_delete_selection (entry);
1967 old_pos = entry->current_pos;
1968 gtk_move_forward_character (entry);
1969 gtk_entry_delete_text (entry, old_pos, entry->current_pos);
1974 gtk_delete_backward_character (GtkEntry *entry)
1978 if (entry->selection_start_pos != entry->selection_end_pos)
1979 gtk_delete_selection (entry);
1982 old_pos = entry->current_pos;
1983 gtk_move_backward_character (entry);
1984 gtk_entry_delete_text (entry, entry->current_pos, old_pos);
1989 gtk_delete_forward_word (GtkEntry *entry)
1993 if (entry->selection_start_pos != entry->selection_end_pos)
1994 gtk_delete_selection (entry);
1997 old_pos = entry->current_pos;
1998 gtk_move_forward_word (entry);
1999 gtk_entry_delete_text (entry, old_pos, entry->current_pos);
2004 gtk_delete_backward_word (GtkEntry *entry)
2008 if (entry->selection_start_pos != entry->selection_end_pos)
2009 gtk_delete_selection (entry);
2012 old_pos = entry->current_pos;
2013 gtk_move_backward_word (entry);
2014 gtk_entry_delete_text (entry, entry->current_pos, old_pos);
2019 gtk_delete_line (GtkEntry *entry)
2021 gtk_entry_delete_text (entry, 0, entry->text_length);
2025 gtk_delete_to_line_end (GtkEntry *entry)
2027 gtk_entry_delete_text (entry, entry->current_pos, entry->text_length);
2031 gtk_delete_selection (GtkEntry *entry)
2033 if (entry->selection_start_pos != entry->selection_end_pos)
2034 gtk_entry_delete_text (entry,
2035 MIN (entry->selection_start_pos, entry->selection_end_pos),
2036 MAX (entry->selection_start_pos, entry->selection_end_pos));
2038 entry->selection_start_pos = 0;
2039 entry->selection_end_pos = 0;
2041 if (entry->have_selection)
2043 entry->have_selection = FALSE;
2044 if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == GTK_WIDGET (entry)->window)
2045 gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
2050 gtk_select_word (GtkEntry *entry)
2055 gtk_move_backward_word (entry);
2056 start_pos = entry->current_pos;
2057 end_pos = entry->current_pos;
2059 gtk_move_forward_word (entry);
2060 end_pos = entry->current_pos;
2062 gtk_entry_select_region (entry, start_pos, end_pos);
2066 gtk_select_line (GtkEntry *entry)
2068 gtk_entry_select_region (entry, 0, entry->text_length);
2069 entry->current_pos = entry->selection_end_pos;
2073 gtk_entry_select_region (GtkEntry *entry,
2077 entry->have_selection = TRUE;
2079 entry->selection_start_pos = start;
2080 entry->selection_end_pos = end;
2082 gtk_widget_queue_draw (GTK_WIDGET (entry));
2086 gtk_entry_cut_clipboard (GtkEntry *entry, GdkEventKey *event)
2088 gtk_entry_copy_clipboard (entry, event);
2089 gtk_delete_selection (entry);
2091 gtk_entry_queue_draw (entry);
2095 gtk_entry_copy_clipboard (GtkEntry *entry, GdkEventKey *event)
2097 gint selection_start_pos;
2098 gint selection_end_pos;
2100 selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
2101 selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
2103 if (selection_start_pos != selection_end_pos)
2105 if (gtk_selection_owner_set (GTK_WIDGET (entry),
2111 c = entry->text[selection_end_pos];
2112 entry->text[selection_end_pos] = 0;
2113 entry->clipboard_text = g_strdup (entry->text + selection_start_pos);
2114 entry->text[selection_end_pos] = c;
2120 gtk_entry_paste_clipboard (GtkEntry *entry, GdkEventKey *event)
2122 gtk_selection_convert (GTK_WIDGET(entry),
2123 clipboard_atom, ctext_atom, event->time);
2127 gtk_entry_set_max_length (GtkEntry *entry, guint16 max)
2129 g_return_if_fail (entry != NULL);
2130 g_return_if_fail (GTK_IS_ENTRY (entry));
2132 entry->text_max_length = max;