summaryrefslogtreecommitdiffstats
path: root/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff')
-rw-r--r--meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff1308
1 files changed, 1308 insertions, 0 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff
new file mode 100644
index 0000000000..fae911305c
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkentry.c.diff
@@ -0,0 +1,1308 @@
+--- gtk+-2.6.4/gtk/gtkentry.c 2005-02-04 17:36:02.000000000 +0200
++++ gtk+-2.6.4/gtk/gtkentry.c 2005-04-06 16:19:36.466994536 +0300
+@@ -24,6 +24,10 @@
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
++ /* Modified for Nokia Oyj during 2002-2003. See CHANGES file for list
++ * of changes.
++ */
++
+ #include <config.h>
+ #include <string.h>
+
+@@ -53,6 +57,7 @@
+ #include "gtktreeselection.h"
+ #include "gtkentryprivate.h"
+ #include "gtkcelllayout.h"
++#include "gtkscrolledwindow.h"
+
+ #define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key"
+
+@@ -60,6 +65,8 @@
+ #define DRAW_TIMEOUT 20
+ #define INNER_BORDER 2
+ #define COMPLETION_TIMEOUT 300
++#define HILDON_EDITED_CHARACTER_MAX 8
++#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */
+
+ /* Initial size of buffer, in bytes */
+ #define MIN_SIZE 16
+@@ -75,6 +82,18 @@
+ {
+ gfloat xalign;
+ gint insert_pos;
++ /* Hildon additions:
++ * following variables are needed
++ * for Hildon password 'preview'
++ * functionality; last inputted character
++ * is showed for defined period, before it is
++ * rendered to '*'
++ */
++ gchar hildon_edited_character[HILDON_EDITED_CHARACTER_MAX];
++ gboolean hildon_edited_character_timeout;
++ gint hildon_edited_character_length;
++ gboolean keep_focus;
++ gboolean menu_popped;
+ };
+
+ enum {
+@@ -104,7 +123,9 @@
+ PROP_WIDTH_CHARS,
+ PROP_SCROLL_OFFSET,
+ PROP_TEXT,
+- PROP_XALIGN
++ PROP_XALIGN,
++ PROP_AUTOCAP,
++ PROP_INPUT_MODE
+ };
+
+ static guint signals[LAST_SIGNAL] = { 0 };
+@@ -324,6 +345,23 @@
+ gint *y,
+ gint *width,
+ gint *height);
++static void gtk_entry_update_scrolled_window (GtkEntry *entry);
++static void gtk_entry_set_autocap (GtkEntry *entry,
++ gboolean autocap);
++static gboolean gtk_entry_get_autocap (GtkEntry *entry);
++static void gtk_entry_set_input_mode (GtkEntry *entry,
++ gboolean mode);
++static gint gtk_entry_get_input_mode (GtkEntry *entry);
++
++/*Change for Hildon
++ *returns an iterator to the character at position x,y of the
++ *layout
++ *returns NULL if no iterator was found at that position
++ *Caller must call pango_layout_free_iter on the returned iterator
++ */
++static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y );
++
++static gboolean hildon_remove_visible_character( gpointer data );
+
+ /* Completion */
+ static gint gtk_entry_completion_timeout (gpointer data);
+@@ -523,7 +561,25 @@
+ P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+-
++
++ g_object_class_install_property (gobject_class,
++ PROP_AUTOCAP,
++ g_param_spec_boolean ("autocap",
++ P_("auto capitalization"),
++ P_("Enable autocap support"),
++ TRUE,
++ G_PARAM_READABLE | G_PARAM_WRITABLE));
++
++ g_object_class_install_property (gobject_class,
++ PROP_INPUT_MODE,
++ g_param_spec_int ("input_mode",
++ P_("input mode"),
++ P_("Define widget's input mode"),
++ 0,
++ 9, /* keep me updated */
++ 0,
++ G_PARAM_READABLE | G_PARAM_WRITABLE));
++
+ g_object_class_install_property (gobject_class,
+ PROP_HAS_FRAME,
+ g_param_spec_boolean ("has_frame",
+@@ -593,6 +649,40 @@
+ 0.0,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
++ gtk_widget_class_install_style_property (widget_class,
++ g_param_spec_int ("horizontal-border",
++ P_("Horizontal borders for entry"),
++ P_("Set left/right borders"),
++ 0,
++ G_MAXINT,
++ INNER_BORDER,
++ G_PARAM_READWRITE));
++
++ gtk_widget_class_install_style_property (widget_class,
++ g_param_spec_int ("vertical-border",
++ P_("Vertical borders for entry"),
++ P_("Set top/bottom borders"),
++ 0,
++ G_MAXINT,
++ INNER_BORDER,
++ G_PARAM_READWRITE));
++
++ gtk_widget_class_install_style_property (widget_class,
++ g_param_spec_int ("icon-width",
++ P_("Icon Width"),
++ P_("Size of the purpose icon."),
++ 0,
++ G_MAXINT,
++ 0,
++ G_PARAM_READWRITE));
++
++ gtk_widget_class_install_style_property (widget_class,
++ g_param_spec_boolean ("show-last-char",
++ P_("Show last char in invisible mode for a while"),
++ P_("Last char is shown before it is rendered to asterisk"),
++ FALSE,
++ G_PARAM_READABLE | G_PARAM_WRITABLE));
++
+ signals[POPULATE_POPUP] =
+ g_signal_new ("populate_popup",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+@@ -853,6 +943,22 @@
+ iface->start_editing = gtk_entry_start_editing;
+ }
+
++/* HILDON: Timed function to hide the most recently inputted character in password mode
++*/
++static gboolean
++ hildon_remove_visible_character( gpointer data )
++{
++ g_return_val_if_fail (GTK_IS_WIDGET (data), FALSE);
++
++ GtkEntry * entry = GTK_ENTRY( data );
++
++ /* Force the string to redrawn, but now without a visible character */
++ gtk_entry_recompute( entry );
++
++ /* Return false so this timeout is not called again and destroyed */
++ return FALSE;
++}
++
+ static void
+ gtk_entry_set_property (GObject *object,
+ guint prop_id,
+@@ -867,9 +973,10 @@
+ {
+ gboolean new_value = g_value_get_boolean (value);
+
++ gtk_widget_set_sensitive( GTK_WIDGET( entry ), entry->editable );
+ if (new_value != entry->editable)
+ {
+- if (!new_value)
++ if (!new_value)
+ {
+ gtk_entry_reset_im_context (entry);
+ if (GTK_WIDGET_HAS_FOCUS (entry))
+@@ -896,6 +1003,14 @@
+ case PROP_VISIBILITY:
+ gtk_entry_set_visibility (entry, g_value_get_boolean (value));
+ break;
++
++ case PROP_AUTOCAP:
++ gtk_entry_set_autocap (entry, g_value_get_boolean (value));
++ break;
++
++ case PROP_INPUT_MODE:
++ gtk_entry_set_input_mode (entry, g_value_get_int (value));
++ break;
+
+ case PROP_HAS_FRAME:
+ gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
+@@ -954,6 +1069,12 @@
+ case PROP_VISIBILITY:
+ g_value_set_boolean (value, entry->visible);
+ break;
++ case PROP_AUTOCAP:
++ g_value_set_boolean (value, gtk_entry_get_autocap (entry));
++ break;
++ case PROP_INPUT_MODE:
++ g_value_set_int (value, gtk_entry_get_input_mode (entry));
++ break;
+ case PROP_HAS_FRAME:
+ g_value_set_boolean (value, entry->has_frame);
+ break;
+@@ -1000,7 +1121,20 @@
+ entry->width_chars = -1;
+ entry->is_cell_renderer = FALSE;
+ entry->editing_canceled = FALSE;
+- entry->has_frame = TRUE;
++#ifdef HILDON_SINGLE_LINE_EDITOR
++ entry->has_frame = FALSE;
++#else
++ entry->has_frame = TRUE;
++#endif
++
++ /* Hildon */
++ memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX );
++ priv->hildon_edited_character_length = 0;
++ priv->hildon_edited_character_timeout = FALSE;
++
++ priv->keep_focus = FALSE;
++ priv->menu_popped = FALSE;
++
+ priv->xalign = 0.0;
+
+ gtk_drag_dest_set (GTK_WIDGET (entry),
+@@ -1013,6 +1147,10 @@
+ * to it; so we create it here and destroy it in finalize().
+ */
+ entry->im_context = gtk_im_multicontext_new ();
++ /* Set default stuff. */
++ gtk_entry_set_autocap (entry, TRUE);
++ gtk_entry_set_input_mode (entry, 0); /* alpha-numeric-special */
++ g_object_set (G_OBJECT (entry->im_context), "use-show-hide", TRUE, NULL);
+
+ g_signal_connect (entry->im_context, "commit",
+ G_CALLBACK (gtk_entry_commit_cb), entry);
+@@ -1058,7 +1196,8 @@
+ gtk_entry_finalize (GObject *object)
+ {
+ GtkEntry *entry = GTK_ENTRY (object);
+-
++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry));
++
+ gtk_entry_set_completion (entry, NULL);
+
+ if (entry->cached_layout)
+@@ -1072,6 +1211,9 @@
+ if (entry->recompute_idle)
+ g_source_remove (entry->recompute_idle);
+
++ if (priv->hildon_edited_character_timeout)
++ g_source_remove (priv->hildon_edited_character_timeout);
++
+ entry->text_size = 0;
+
+ if (entry->text)
+@@ -1213,7 +1355,14 @@
+ PangoFontMetrics *metrics;
+ gint xborder, yborder;
+ PangoContext *context;
+-
++ gint border_x, border_y;
++ gint icon_width;
++
++ gtk_widget_style_get (widget,
++ "horizontal-border", &border_x,
++ "vertical-border", &border_y,
++ "icon-width", &icon_width, NULL);
++
+ gtk_widget_ensure_style (widget);
+ context = gtk_widget_get_pango_context (widget);
+ metrics = pango_context_get_metrics (context,
+@@ -1225,21 +1374,22 @@
+
+ _gtk_entry_get_borders (entry, &xborder, &yborder);
+
+- xborder += INNER_BORDER;
+- yborder += INNER_BORDER;
++ xborder += border_x<<1;
++ yborder += border_y<<1;
+
+ if (entry->width_chars < 0)
+- requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
++ requisition->width = MIN_ENTRY_WIDTH + xborder;
+ else
+ {
+ gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
+ gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
+ gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE;
+
+- requisition->width = char_pixels * entry->width_chars + xborder * 2;
++ requisition->width = char_pixels * entry->width_chars + xborder;
+ }
+-
+- requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;
++
++ requisition->width += icon_width;
++ requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder;
+
+ pango_font_metrics_unref (metrics);
+ }
+@@ -1253,23 +1403,39 @@
+ {
+ gint xborder, yborder;
+ GtkRequisition requisition;
++ gint icon_width;
+ GtkWidget *widget = GTK_WIDGET (entry);
+
++ gtk_widget_style_get (widget, "icon-width", &icon_width, NULL);
++
+ gtk_widget_get_child_requisition (widget, &requisition);
+
+ _gtk_entry_get_borders (entry, &xborder, &yborder);
+
+ if (x)
+- *x = xborder;
++ *x = xborder + icon_width;
+
+ if (y)
++ {
+ *y = yborder;
++ if( widget->allocation.height < requisition.height )
++ *y += ((widget->allocation.height - requisition.height) / 2);
++ if( *y < yborder )
++ *y = yborder;
++ }
+
+ if (width)
+- *width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
++ *width = GTK_WIDGET (entry)->allocation.width - xborder * 2 - icon_width;
+
+ if (height)
+- *height = requisition.height - yborder * 2;
++ {
++ if( widget->allocation.height < requisition.height )
++ *height = widget->allocation.height - yborder * 2;
++ else
++ *height = widget->requisition.height - yborder * 2;
++ if( *height <=0 )
++ *height = 1;
++ }
+ }
+
+ static void
+@@ -1289,10 +1455,9 @@
+
+ if (y)
+ {
+- if (entry->is_cell_renderer)
+- *y = widget->allocation.y;
+- else
+- *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2;
++ *y = widget->allocation.y;
++ if( widget->allocation.height > requisition.height )
++ *y += ((widget->allocation.height - requisition.height) / 2);
+ }
+
+ if (width)
+@@ -1300,10 +1465,10 @@
+
+ if (height)
+ {
+- if (entry->is_cell_renderer)
+- *height = widget->allocation.height;
+- else
++ if( widget->allocation.height > requisition.height )
+ *height = requisition.height;
++ else
++ *height = widget->allocation.height;
+ }
+ }
+
+@@ -1383,20 +1548,19 @@
+ GdkEventExpose *event)
+ {
+ GtkEntry *entry = GTK_ENTRY (widget);
++ gint area_width, area_height;
++
++ get_widget_window_size (entry, NULL, NULL, &area_width, &area_height);
+
+ if (widget->window == event->window)
+- gtk_entry_draw_frame (widget);
++ {
++ gtk_paint_box (widget->style, widget->window,
++ GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
++ NULL, widget, "entry_frame",
++ 0, 0, area_width, area_height);
++ }
+ else if (entry->text_area == event->window)
+ {
+- gint area_width, area_height;
+-
+- get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
+-
+- gtk_paint_flat_box (widget->style, entry->text_area,
+- GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
+- NULL, widget, "entry_bg",
+- 0, 0, area_width, area_height);
+-
+ if ((entry->visible || entry->invisible_char != 0) &&
+ GTK_WIDGET_HAS_FOCUS (widget) &&
+ entry->selection_bound == entry->current_pos && entry->cursor_visible)
+@@ -1490,16 +1654,19 @@
+ return FALSE;
+
+ entry->button = event->button;
+-
++
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ entry->in_click = TRUE;
+ gtk_widget_grab_focus (widget);
+ entry->in_click = FALSE;
+ }
+-
++
++ /* Hildon: we need to reset IM context so pre-edit string can be committed */
++ gtk_entry_reset_im_context (entry);
++
+ tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
+-
++
+ if (event->button == 1)
+ {
+ gboolean have_selection = gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end);
+@@ -1509,8 +1676,6 @@
+
+ if (event->state & GDK_SHIFT_MASK)
+ {
+- gtk_entry_reset_im_context (entry);
+-
+ if (!have_selection) /* select from the current position to the clicked position */
+ sel_start = sel_end = entry->current_pos;
+
+@@ -1575,9 +1740,20 @@
+ entry->drag_start_x = event->x + entry->scroll_offset;
+ entry->drag_start_y = event->y + entry->scroll_offset;
+ }
+- else
+- gtk_editable_set_position (editable, tmp_pos);
+- break;
++ else {
++ /* HILDON: do not move the cursor inside the textarea if invisible
++ * as per the specifications */
++ if (!entry->visible)
++ if(tmp_pos == strlen(gtk_entry_get_text(entry))){
++ gtk_editable_set_position( editable, entry->text_length);
++ } else {
++ gtk_editable_select_region (editable, 0, -1);
++ }
++ else
++ gtk_editable_set_position (editable, tmp_pos);
++ }
++
++ break;
+
+ case GDK_2BUTTON_PRESS:
+ /* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
+@@ -1614,8 +1790,16 @@
+ }
+ else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
+ {
++ /* Hildon: if we are in password mode selection and Cut & Copy should
++ be disabled. */
++ if (!entry->visible)
++ {
++ gtk_editable_set_position (GTK_EDITABLE(entry), 0);
++ }
++
+ gtk_entry_do_popup (entry, event);
+ entry->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */
++ priv->keep_focus = TRUE;
+
+ return TRUE;
+ }
+@@ -1632,11 +1816,23 @@
+ if (event->window != entry->text_area || entry->button != event->button)
+ return FALSE;
+
++ if (entry->editable)
++ gtk_im_context_show (entry->im_context);
++
+ if (entry->in_drag)
+ {
+ gint tmp_pos = gtk_entry_find_position (entry, entry->drag_start_x);
+
+- gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos);
++ /* HILDON: If not visible, do not allow cursor to be positioned inside the string */
++ if (!entry->visible){
++ if(tmp_pos == strlen(gtk_entry_get_text(entry))){
++ gtk_editable_set_position( GTK_EDITABLE(entry), entry->text_length);
++ } else {
++ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
++ }
++ } else {
++ gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos);
++ }
+
+ entry->in_drag = 0;
+ }
+@@ -1822,6 +2018,13 @@
+ }
+ }
+
++ if (event->keyval == GDK_Return)
++ return FALSE;
++ if (event->keyval == GDK_KP_Enter)
++ g_signal_emit_by_name (G_OBJECT(gtk_widget_get_ancestor (widget,
++ GTK_TYPE_WINDOW)), "move-focus",
++ GTK_DIR_TAB_FORWARD);
++
+ if (GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
+ /* Activate key bindings
+ */
+@@ -1835,6 +2038,8 @@
+ GdkEventKey *event)
+ {
+ GtkEntry *entry = GTK_ENTRY (widget);
++
++ gtk_entry_update_scrolled_window( entry );
+
+ if (entry->editable)
+ {
+@@ -1853,7 +2058,35 @@
+ GdkEventFocus *event)
+ {
+ GtkEntry *entry = GTK_ENTRY (widget);
+-
++ GtkEntryPrivate *priv;
++
++ priv = GTK_ENTRY_GET_PRIVATE (widget);
++ /* Hildon : If the text doesn't fit the entry, upon focusing
++ * to an text field, move the caret to the end of the entry.
++ * Force the entry to recompute, otherwise it doesn't update
++ * if the cursor is currently at the end*/
++ /* hildon : If the text has no selection and focus returned with
++ other means than pointer click, set cursor before first
++ character of the text, otherwise behave normally */
++
++ if (!entry->in_click)
++ {
++ /*gboolean has_selection;
++ has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), NULL, NULL);
++ if (!has_selection)
++ {
++ gtk_editable_set_position (GTK_EDITABLE (entry), -1);
++ }*//*FIXME need a better hack here*/
++ /* Hildon: If in SecretEditor mode highlight selection if entry got focus
++ * otherways than mouse/stylus */
++ if (!entry->visible && priv->keep_focus)
++ {
++ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
++ }
++ }
++
++ gtk_entry_recompute (GTK_ENTRY (entry));
++
+ gtk_widget_queue_draw (widget);
+
+ if (entry->editable)
+@@ -1876,6 +2109,8 @@
+ GdkEventFocus *event)
+ {
+ GtkEntry *entry = GTK_ENTRY (widget);
++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (widget);
++ guint tmp_pos;
+ GtkEntryCompletion *completion;
+
+ gtk_widget_queue_draw (widget);
+@@ -1886,6 +2121,20 @@
+ gtk_im_context_focus_out (entry->im_context);
+ }
+
++ tmp_pos = gtk_editable_get_position (GTK_EDITABLE (widget));
++ if (priv->keep_focus){
++ if (!entry->visible)
++ gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos);
++ priv->keep_focus = FALSE;
++ }
++ else {
++ if (priv->menu_popped)
++ priv->menu_popped = FALSE;
++ else gtk_editable_set_position (GTK_EDITABLE (widget), tmp_pos);
++ }
++
++ gtk_widget_queue_draw(widget);
++
+ gtk_entry_check_cursor_blink (entry);
+
+ g_signal_handlers_disconnect_by_func (gdk_keymap_get_for_display (gtk_widget_get_display (widget)),
+@@ -1902,7 +2151,6 @@
+ static void
+ gtk_entry_grab_focus (GtkWidget *widget)
+ {
+- GtkEntry *entry = GTK_ENTRY (widget);
+ gboolean select_on_focus;
+
+ GTK_WIDGET_CLASS (parent_class)->grab_focus (widget);
+@@ -1912,8 +2160,8 @@
+ &select_on_focus,
+ NULL);
+
+- if (select_on_focus && entry->editable && !entry->in_click)
+- gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
++/* Hildon : When focusing to an entry, it shouldn't become
++ * highlighted. */
+ }
+
+ static void
+@@ -1987,7 +2235,7 @@
+
+ if (new_text_length > 63)
+ g_free (text);
+-
++ gtk_entry_update_scrolled_window( entry );
+ g_object_unref (editable);
+ }
+
+@@ -2074,7 +2322,7 @@
+ if (end < 0)
+ end = entry->text_length;
+
+- gtk_entry_reset_im_context (entry);
++ /*gtk_entry_reset_im_context (entry);*//*FIXME tmp kludge, might break something*/
+
+ gtk_entry_set_positions (entry,
+ MIN (end, entry->text_length),
+@@ -2168,13 +2416,19 @@
+ {
+ gint index;
+ gint n_chars;
++ gboolean show_last_char = FALSE;
+
+ GtkEntry *entry = GTK_ENTRY (editable);
+-
++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (GTK_WIDGET (entry));
+ if (new_text_length < 0)
+ new_text_length = strlen (new_text);
+
+ n_chars = g_utf8_strlen (new_text, new_text_length);
++
++
++ gtk_widget_style_get (GTK_WIDGET (entry), "show-last-char",
++ &show_last_char, NULL);
++
+ if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
+ {
+ gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (entry)));
+@@ -2238,6 +2492,14 @@
+
+ if (entry->selection_bound > *position)
+ entry->selection_bound += n_chars;
++
++ /* Hildon: store this addition IF it was only 1 char (user inputted) and we are currently in secret mode (invisible) */
++
++ if (show_last_char && n_chars == 1 && !entry->visible && (new_text_length < HILDON_EDITED_CHARACTER_MAX)) {
++ memset( &priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX );
++ priv->hildon_edited_character_length = new_text_length;
++ memcpy( &priv->hildon_edited_character, new_text, new_text_length ); /* Guaranteed to be < total length */
++ }
+
+ *position += n_chars;
+
+@@ -2339,6 +2601,11 @@
+
+ gtk_entry_reset_im_context (entry);
+
++ /* Hildon, if not visible set the position to the end */
++ /* New SecretEditor specs say that with cursor should move
++ * With left/right arrows
++ */
++
+ if (entry->current_pos != entry->selection_bound && !extend_selection)
+ {
+ /* If we have a current selection and aren't extending it, move to the
+@@ -2445,7 +2712,7 @@
+ gint start_pos = entry->current_pos;
+ gint end_pos = entry->current_pos;
+
+- gtk_entry_reset_im_context (entry);
++ /* Hildon: code removed - backspace should not clear the word completion */
+
+ if (!entry->editable)
+ return;
+@@ -2515,7 +2782,8 @@
+ GtkEditable *editable = GTK_EDITABLE (entry);
+ gint prev_pos;
+
+- gtk_entry_reset_im_context (entry);
++/* gtk_entry_reset_im_context (entry); */ /*backspace should not clear
++ the word completion*/
+
+ if (!entry->editable || !entry->text)
+ return;
+@@ -2883,21 +3151,28 @@
+ ++i;
+ }
+ }
+-
++
++#define HILDON_EDITED_CHARACTER_MS 600 /* 0.6 seconds */
++
+ static PangoLayout *
+ gtk_entry_create_layout (GtkEntry *entry,
+ gboolean include_preedit)
+ {
+ GtkWidget *widget = GTK_WIDGET (entry);
++ GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+ PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL);
+ PangoAttrList *tmp_attrs = pango_attr_list_new ();
+
+ gchar *preedit_string = NULL;
+ gint preedit_length = 0;
+ PangoAttrList *preedit_attrs = NULL;
++ gboolean show_last_char = FALSE;
+
+ pango_layout_set_single_paragraph_mode (layout, TRUE);
+
++ gtk_widget_style_get (widget, "show-last-char",
++ &show_last_char, NULL);
++
+ if (include_preedit)
+ {
+ gtk_im_context_get_preedit_string (entry->im_context,
+@@ -3003,7 +3278,49 @@
+ else
+ invisible_char = ' '; /* just pick a char */
+
+- append_char (str, invisible_char, entry->text_length);
++ if (!show_last_char)
++ append_char (str, invisible_char, entry->text_length);
++ else if (show_last_char)
++ {
++ /* Hildon */
++ if (priv->hildon_edited_character_length > 0)
++ {
++
++ /* If we have an outstanding timeout, remove it, because the character it is set to hide
++ * is already hidden now. We do this first to prevent possible race conditions if the timout
++ * were to trigger while in here
++ */
++
++ if (priv->hildon_edited_character_timeout)
++ {
++ g_source_remove( priv->hildon_edited_character_timeout );
++ priv->hildon_edited_character_timeout = FALSE;
++ }
++
++ /* Draw the secret character length-1 times, because the last char will be visible */
++ append_char (str, invisible_char, entry->text_length > 1 ? entry->text_length - 1 : 0);
++
++ /* Add our visible char, the most recently inputted one */
++ g_string_append_len (str, (char *)&priv->hildon_edited_character, priv->hildon_edited_character_length);
++
++ /* Now remove this last inputted character, don't need it anymore */
++
++ memset( priv->hildon_edited_character, 0x00, HILDON_EDITED_CHARACTER_MAX );
++ priv->hildon_edited_character_length = 0;
++
++ priv->hildon_edited_character_timeout = g_timeout_add( HILDON_EDITED_CHARACTER_MS, (GSourceFunc)
++ hildon_remove_visible_character, entry );
++
++ }
++ else
++ {
++ /* No last character known. This could be for example because the application has filled
++ * in the password already. In that case we of course don't want to view it
++ */
++ append_char (str, invisible_char, entry->text_length);
++ }
++ }
++
+ pango_layout_set_text (layout, str->str, str->len);
+ g_string_free (str, TRUE);
+ }
+@@ -3048,12 +3365,17 @@
+ gint area_width, area_height;
+ gint y_pos;
+ PangoLayoutLine *line;
+-
++ gint border_x, border_y;
++
++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x,
++ "vertical-border", &border_y,
++ NULL);
++
+ layout = gtk_entry_ensure_layout (entry, TRUE);
+
+ get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
+
+- area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER);
++ area_height = PANGO_SCALE * (area_height - 2 * border_y);
+
+ line = pango_layout_get_lines (layout)->data;
+ pango_layout_line_get_extents (line, NULL, &logical_rect);
+@@ -3070,10 +3392,10 @@
+ else if (y_pos + logical_rect.height > area_height)
+ y_pos = area_height - logical_rect.height;
+
+- y_pos = INNER_BORDER + y_pos / PANGO_SCALE;
++ y_pos = border_y + y_pos / PANGO_SCALE;
+
+ if (x)
+- *x = INNER_BORDER - entry->scroll_offset;
++ *x = border_x - entry->scroll_offset;
+
+ if (y)
+ *y = y_pos;
+@@ -3083,6 +3405,10 @@
+ gtk_entry_draw_text (GtkEntry *entry)
+ {
+ GtkWidget *widget;
++ gint border_y, border_x;
++
++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x,
++ "vertical-border", &border_y, NULL);
+
+ if (!entry->visible && entry->invisible_char == 0)
+ return;
+@@ -3092,14 +3418,76 @@
+ PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
+ gint x, y;
+ gint start_pos, end_pos;
++ GdkRectangle clip_rect;
+
+ widget = GTK_WIDGET (entry);
+
+ get_layout_position (entry, &x, &y);
+
++ /* Use a clipping rectangle so that we always get enough empty space around
++ * the text.
++ */
++ clip_rect.x = border_x;
++ clip_rect.y = 0;
++
++ gdk_drawable_get_size (entry->text_area, &clip_rect.width, &clip_rect.height);
++ clip_rect.width -= border_x * 2;
++
++ /*changes for Hildon
++ *Reduce the size of the clip rect, so that only full characters are displayed
++ */
++
++ /* NOTE: Commented out because it does not work with bidi text where
++the indexes are in random
++ * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself
++ * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec
++ * until gtkentry itself is fixed. (bug #477)
++ */
++
++ /* Better yet, let's enable this only when not in RTL mode */
++
++ /* Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem
++ * and we tested patched gtkentry with pango version 1.3.2 and it appears to be fixed. Section is commented
++ out until we upgrade to new version of pango
++ if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL)
++ {
++ PangoRectangle char_rect; // used for getting character's onscreen pos
++ PangoLayoutIter *iter; // used to iterate over the text
++
++ // get the position of the character currently at the clip border
++ iter = get_char_at_pos( layout, (clip_rect.x + clip_rect.width + entry->scroll_offset), 0 );
++ if ( iter )
++ {
++ // get the position of that character on the screen
++ pango_layout_iter_get_char_extents( iter, &char_rect );
++ char_rect.x /= PANGO_SCALE;
++ char_rect.x -= entry->scroll_offset;
++ char_rect.width /= PANGO_SCALE;
++
++ // if the ending position is > the clip rectangle, then the
++ // character is only partially visible, and we should
++ // clip the entire character.
++
++ if ( char_rect.x + char_rect.width > clip_rect.x + clip_rect.width )
++ {
++ clip_rect.width = char_rect.x;
++ }
++
++ pango_layout_iter_free( iter );
++ }
++
++ }
++ */
++ /******************************************************************/
++
++ gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], &clip_rect);
++
+ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
+ x, y,
+ layout);
++
++ gdk_gc_set_clip_rectangle (widget->style->text_gc [widget->state], NULL);
++
+
+ if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
+ {
+@@ -3128,7 +3516,7 @@
+ {
+ GdkRectangle rect;
+
+- rect.x = INNER_BORDER - entry->scroll_offset + ranges[2 * i];
++ rect.x = border_x - entry->scroll_offset + ranges[2 * i];
+ rect.y = y;
+ rect.width = ranges[2 * i + 1];
+ rect.height = logical_rect.height;
+@@ -3177,14 +3565,18 @@
+ {
+ GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry)));
+ PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
++ gint border_x, border_y;
+
++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x,
++ "vertical-border", &border_y,
++ NULL);
+ if (GTK_WIDGET_DRAWABLE (entry))
+ {
+ GtkWidget *widget = GTK_WIDGET (entry);
+ GdkRectangle cursor_location;
+ gboolean split_cursor;
+
+- gint xoffset = INNER_BORDER - entry->scroll_offset;
++ gint xoffset = border_x - entry->scroll_offset;
+ gint strong_x, weak_x;
+ gint text_area_height;
+ PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+@@ -3221,9 +3613,9 @@
+ }
+
+ cursor_location.x = xoffset + x1;
+- cursor_location.y = INNER_BORDER;
++ cursor_location.y = border_y;
+ cursor_location.width = 0;
+- cursor_location.height = text_area_height - 2 * INNER_BORDER ;
++ cursor_location.height = text_area_height - 2 * border_y;
+
+ draw_insertion_cursor (entry,
+ &cursor_location, TRUE, dir1,
+@@ -3249,11 +3641,8 @@
+ static void
+ gtk_entry_reset_im_context (GtkEntry *entry)
+ {
+- if (entry->need_im_reset)
+- {
+- entry->need_im_reset = 0;
+- gtk_im_context_reset (entry->im_context);
+- }
++ /* Hildon: We want reset to be sent more often */
++ gtk_im_context_reset (entry->im_context);
+ }
+
+ static gint
+@@ -3266,8 +3655,12 @@
+ gint pos;
+ gboolean trailing;
+ const gchar *text;
+- gint cursor_index;
+-
++ gint border_x, cursor_index;
++
++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x,
++ NULL);
++ x -= border_x;
++
+ layout = gtk_entry_ensure_layout (entry, TRUE);
+ text = pango_layout_get_text (layout);
+ cursor_index = g_utf8_offset_to_pointer (text, entry->current_pos) - text;
+@@ -3355,12 +3748,17 @@
+ PangoLayout *layout;
+ PangoLayoutLine *line;
+ PangoRectangle logical_rect;
++ gint border_x, border_y;
++
++ gtk_widget_style_get (GTK_WIDGET (entry), "horizontal-border", &border_x,
++ "vertical-border", &border_y,
++ NULL);
+
+ if (!GTK_WIDGET_REALIZED (entry))
+ return;
+
+ gdk_drawable_get_size (entry->text_area, &text_area_width, NULL);
+- text_area_width -= 2 * INNER_BORDER;
++ text_area_width -= 2 * border_x;
+
+ layout = gtk_entry_ensure_layout (entry, TRUE);
+ line = pango_layout_get_lines (layout)->data;
+@@ -3390,13 +3788,13 @@
+ entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset);
+
+ /* And make sure cursors are on screen. Note that the cursor is
+- * actually drawn one pixel into the INNER_BORDER space on
++ * actually drawn one pixel into the border_x space on
+ * the right, when the scroll is at the utmost right. This
+ * looks better to to me than confining the cursor inside the
+ * border entirely, though it means that the cursor gets one
+ * pixel closer to the edge of the widget on the right than
+ * on the left. This might need changing if one changed
+- * INNER_BORDER from 2 to 1, as one would do on a
++ * border_x from 2 to 1, as one would do on a
+ * small-screen-real-estate display.
+ *
+ * We always make sure that the strong cursor is on screen, and
+@@ -3430,6 +3828,52 @@
+ entry->scroll_offset += weak_xoffset - text_area_width;
+ }
+
++ /*Changes for Hildon
++ * now we make it so that if a character is partially visible,
++ * then we also scroll that off the screen.
++ */
++
++ /* NOTE: Commented out because it does not work with bidi text where the indexes are in random
++ * left-right or right-left order. Code causes Pango assert aborts. Because gtkentry itself
++ * is broken with regard to bidi anyway (bug #478) we ignore this requirement of the spec
++ * until gtkentry itself is fixed. (bug #477)
++ */
++
++ /* Better yet, let's disable this (for now) only when using RTL text */
++
++/*Note: BUG #857. patched gtkentry crashed when pasting scalable fonts. This is pango problem
++ * and we tested patched gtkentry with pango version 1.3.2 and it appears to be fixed. Section is comment ed out until we upgrade to new version of pango
++ if (gtk_widget_get_direction( entry ) != GTK_TEXT_DIR_RTL)
++ {
++ PangoLayoutIter *iter = get_char_at_pos( layout, entry->scroll_offset, 0 );
++ // if we found the char we were looking for
++ if ( iter )
++ {
++ PangoRectangle char_rect; // used for getting character's onscreen pos
++
++ // get the position of that character on the screen
++ pango_layout_iter_get_char_extents( iter, &char_rect );
++ char_rect.x /= PANGO_SCALE;
++
++ // if the starting position is < the current scroll offset, then the
++ // character is only partially visible, and we should scroll to the
++ // start of the next character instead
++
++ if ( char_rect.x < entry->scroll_offset )
++ {
++ if ( pango_layout_iter_next_char( iter ) )
++ {
++ pango_layout_iter_get_char_extents( iter, &char_rect);
++ entry->scroll_offset = char_rect.x / PANGO_SCALE;
++ }
++ }
++
++ pango_layout_iter_free( iter );
++ }
++
++
++ }*/
++
+ g_object_notify (G_OBJECT (entry), "scroll_offset");
+ }
+
+@@ -3552,8 +3996,9 @@
+ pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
+
+ /* Find the next word end */
++ /*Hildon: cursor should seek to the start of the next word*/
+ new_pos++;
+- while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end)
++ while (new_pos < n_attrs && !log_attrs[new_pos].is_word_start)
+ new_pos++;
+
+ g_free (log_attrs);
+@@ -3648,14 +4093,9 @@
+
+ if (entry->visible)
+ return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
+- else if (!entry->invisible_char)
++ /*Hildon: when not visible, no chars are public*/
++ else
+ return g_strdup ("");
+- else
+- {
+- GString *str = g_string_new (NULL);
+- append_char (str, entry->invisible_char, end - start);
+- return g_string_free (str, FALSE);
+- }
+ }
+
+ static void
+@@ -3678,9 +4118,12 @@
+
+ if (text)
+ {
+- gint pos, start, end;
++ gint pos, start, end, index;
+ GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
+
++ /* when pasting multiline text, ignore everything but the first line */
++ for (index = 0; text[index] != 0 && text[index] != '\n'; index++);
++
+ if (completion)
+ {
+ g_signal_handler_block (entry, completion->priv->changed_id);
+@@ -3692,7 +4135,7 @@
+ gtk_editable_delete_text (editable, start, end);
+
+ pos = entry->current_pos;
+- gtk_editable_insert_text (editable, text, -1, &pos);
++ gtk_editable_insert_text (editable, text, index, &pos);
+ gtk_editable_set_position (editable, pos);
+
+ if (completion)
+@@ -3888,6 +4331,7 @@
+ {
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
++ g_object_set(G_OBJECT(entry->im_context), "visibility", visible, NULL);
+ entry->visible = visible ? TRUE : FALSE;
+ g_object_notify (G_OBJECT (entry), "visibility");
+ gtk_entry_recompute (entry);
+@@ -4569,6 +5013,7 @@
+ GdkEventButton *event)
+ {
+ PopupInfo *info = g_new (PopupInfo, 1);
++ GtkEntryPrivate *priv;
+
+ /* In order to know what entries we should make sensitive, we
+ * ask for the current targets of the clipboard, and when
+@@ -4576,6 +5021,8 @@
+ */
+ info->entry = g_object_ref (entry);
+
++ priv = GTK_ENTRY_GET_PRIVATE (entry);
++
+ if (event)
+ {
+ info->button = event->button;
+@@ -4591,6 +5038,8 @@
+ gdk_atom_intern ("TARGETS", FALSE),
+ popup_targets_received,
+ info);
++
++ priv->menu_popped = TRUE;
+ }
+
+ static gboolean
+@@ -5389,3 +5838,156 @@
+
+ return completion;
+ }
++
++static PangoLayoutIter *get_char_at_pos( PangoLayout *layout, gint x, gint y )
++{
++ gint index = 0; /*the index of the first character */
++ gint trailing = 0; /*not used*/
++ PangoLayoutIter *iter; /*used to iterate over the text*/
++ gboolean valid_char = TRUE;
++
++ /*get the position of the character currently at the scroll offset*/
++ pango_layout_xy_to_index( layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing );
++ iter = pango_layout_get_iter( layout );
++
++ /*iterate until we get to the character at the same index*/
++ while ( valid_char && pango_layout_iter_get_index( iter ) != index )
++ {
++ valid_char = pango_layout_iter_next_char( iter );
++ }
++
++ if ( valid_char == FALSE )
++ iter = NULL;
++
++ return iter;
++}
++
++static void gtk_entry_update_scrolled_window( GtkEntry *entry)
++{
++ GtkWidget *parent;
++ GtkWidget *widget;
++ GtkWidget *direct_parent = NULL;
++ GtkScrolledWindow *sw = NULL;
++ gboolean need_update = FALSE;
++ GtkAdjustment *vadjustment;
++ gdouble value;
++
++ widget = parent = GTK_WIDGET(entry);
++ if(parent->parent != NULL)
++ direct_parent = parent->parent;
++ while(parent && !GTK_WIDGET_TOPLEVEL(parent))
++ {
++ if(GTK_IS_SCROLLED_WINDOW(parent))
++ {
++ need_update = TRUE;
++ sw = GTK_SCROLLED_WINDOW(parent);
++ break;
++ }
++ parent = parent->parent;
++ }
++
++ if(need_update)
++ {
++ gint x=0, y=0;
++ vadjustment = gtk_scrolled_window_get_vadjustment(sw);
++ value = gtk_adjustment_get_value(vadjustment);
++
++ if(direct_parent != NULL)
++ gtk_widget_translate_coordinates( direct_parent, parent,
++ widget->allocation.x, widget->allocation.y, &x, &y );
++
++ if( (gdouble) y < 0 )
++ {
++ value = value + (gdouble) y;
++ if (value < vadjustment->lower)
++ value = vadjustment->lower;
++ }
++ else if( (gdouble )y + widget->allocation.height > vadjustment->page_size)
++ {
++ value = value + (gdouble)y + widget->allocation.height
++ - vadjustment->page_size;
++ if(value > vadjustment->upper - vadjustment->page_size)
++ value = vadjustment->upper - vadjustment->page_size;
++ }
++ gtk_adjustment_set_value(vadjustment, value);
++ gtk_scrolled_window_set_vadjustment(sw, GTK_ADJUSTMENT(vadjustment));
++ }
++}
++
++/*
++ * gtk_entry_set_autocap:
++ * @entry: a #GtkEntry
++ * @autocap: autocap
++ *
++ * Sets autocapitalization of the widget.
++ */
++static void
++gtk_entry_set_autocap (GtkEntry *entry,
++ gboolean autocap)
++{
++ g_return_if_fail (GTK_IS_ENTRY (entry));
++
++ if (gtk_entry_get_autocap (entry) != autocap)
++ {
++ g_object_set (G_OBJECT (entry->im_context), "autocap", autocap, NULL);
++ g_object_notify (G_OBJECT (entry), "autocap");
++ }
++}
++
++/*
++ * gtk_entry_get_autocap:
++ * @entry: a #GtkEntry
++ *
++ * Gets autocapitalization state of the widget.
++ *
++ * Return value: a state
++ */
++static gboolean
++gtk_entry_get_autocap (GtkEntry *entry)
++{
++ gboolean autocap;
++ g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
++
++ g_object_get (G_OBJECT (entry->im_context), "autocap", &autocap, NULL);
++
++ return autocap;
++}
++
++/*
++ * gtk_entry_set_input_mode:
++ * @entry: a #GtkEntry
++ * @autocap: input mode
++ *
++ * Sets autocapitalization of the widget.
++ */
++static void
++gtk_entry_set_input_mode (GtkEntry *entry,
++ gint mode)
++{
++ g_return_if_fail (GTK_IS_ENTRY (entry));
++
++ if (gtk_entry_get_input_mode (entry) != mode)
++ {
++ g_object_set (G_OBJECT (entry->im_context), "input_mode", mode, NULL);
++ g_object_notify (G_OBJECT (entry), "input_mode");
++ }
++}
++
++/*
++ * gtk_entry_get_input_mode:
++ * @entry: a #GtkEntry
++ *
++ * Gets input mode of the widget.
++ *
++ * Return value: input mode
++ */
++static gint
++gtk_entry_get_input_mode (GtkEntry *entry)
++{
++ gint mode;
++ g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE);
++
++ g_object_get (G_OBJECT (entry->im_context), "input_mode", &mode, NULL);
++
++ return mode;
++}