Index: gtk/gtkentry.c
===================================================================
--- gtk/gtkentry.c	(revision 17093)
+++ gtk/gtkentry.c	(working copy)
@@ -85,6 +85,7 @@
   guint blink_time;  /* time in msec the cursor has blinked since last user event */
   guint real_changed : 1;
   guint change_count : 8;
+  guint invisible_char_set_explicitly : 1;
 };
 
 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
@@ -866,7 +867,7 @@
                                                                GTK_TYPE_BORDER,
                                                                GTK_PARAM_READABLE));
 
-   gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
+  gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
 						       P_("Select on focus"),
 						       P_("Whether to select the contents of an entry when it is focused"),
 						       TRUE,
@@ -886,6 +887,12 @@
                                                     P_("How long to show the last inputted character in hidden entries"),
                                                     0, G_MAXUINT, 0,
                                                     GTK_PARAM_READWRITE));
+                                                    
+  gtk_settings_install_property (g_param_spec_unichar ("gtk-invisible-char",
+						       P_("Invisible character"),
+						       P_("The character to use when masking entry contents (in \"password mode\")"),
+						       '*',
+						       GTK_PARAM_READWRITE));                                   
 
   g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate));
 }
@@ -1026,7 +1033,7 @@
       g_value_set_boxed (value, gtk_entry_get_inner_border (entry));
       break;
     case PROP_INVISIBLE_CHAR:
-      g_value_set_uint (value, entry->invisible_char);
+      g_value_set_uint (value, gtk_entry_get_invisible_char (entry));
       break;
     case PROP_ACTIVATES_DEFAULT:
       g_value_set_boolean (value, entry->activates_default);
@@ -1067,6 +1074,7 @@
   entry->editable = TRUE;
   entry->visible = TRUE;
   entry->invisible_char = '*';
+  priv->invisible_char_explicitly_set = FALSE;
   entry->dnd_position = -1;
   entry->width_chars = -1;
   entry->is_cell_renderer = FALSE;
@@ -1564,7 +1572,7 @@
 			  NULL, widget, "entry_bg", 
 			  0, 0, area_width, area_height);
       
-      if ((entry->visible || entry->invisible_char != 0) &&
+      if ((entry->visible || gtk_entry_get_invisible_char (entry) != 0) &&
 	  GTK_WIDGET_HAS_FOCUS (widget) &&
 	  entry->selection_bound == entry->current_pos && entry->cursor_visible)
 	gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
@@ -3251,9 +3259,9 @@
           preedit_len_chars = g_utf8_strlen (preedit_string, -1);
           ch_len += preedit_len_chars;
 
-          if (entry->invisible_char != 0)
-            invisible_char = entry->invisible_char;
-          else
+          invisible_char = gtk_entry_get_invisible_char (entry);
+
+          if (invisible_char == 0)
             invisible_char = ' '; /* just pick a char */
           
           append_char (tmp_string, invisible_char, ch_len);
@@ -3329,9 +3337,9 @@
                         "gtk-entry-password-hint-timeout", &password_hint_timeout,
                         NULL);
 
-          if (entry->invisible_char != 0)
-            invisible_char = entry->invisible_char;
-          else
+          invisible_char = gtk_entry_get_invisible_char (entry);
+
+          if (invisible_char == 0)
             invisible_char = ' '; /* just pick a char */
 
           password_hint = g_object_get_qdata (G_OBJECT (entry),
@@ -3459,7 +3467,7 @@
 {
   GtkWidget *widget;
   
-  if (!entry->visible && entry->invisible_char == 0)
+  if (!entry->visible && gtk_entry_get_invisible_char (entry) == 0)
     return;
   
   if (GTK_WIDGET_DRAWABLE (entry))
@@ -3678,7 +3686,9 @@
 				gint       *strong_x,
 				gint       *weak_x)
 {
-  if (!entry->visible && !entry->invisible_char)
+  gunichar invisible_char = gtk_entry_get_invisible_char (entry);
+
+  if (!entry->visible && !invisible_char)
     {
       if (strong_x)
 	*strong_x = 0;
@@ -3708,7 +3718,7 @@
 	      else
 		{
 		  gint preedit_len_chars = g_utf8_strlen (text, -1) - entry->text_length;
-		  index += preedit_len_chars * g_unichar_to_utf8 (entry->invisible_char, NULL);
+		  index += preedit_len_chars * g_unichar_to_utf8 (invisible_char, NULL);
 		}
 	    }
 	}
@@ -4037,12 +4047,14 @@
   
   if (entry->visible)
     return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
-  else if (!entry->invisible_char)
+    
+  gunichar invisible_char = gtk_entry_get_invisible_char (entry);
+  if (!invisible_char)
     return g_strdup ("");
   else
     {
       GString *str = g_string_new (NULL);
-      append_char (str, entry->invisible_char, end - start);
+      append_char (str, invisible_char, end - start);
       return g_string_free (str, FALSE);
     }
 }
@@ -4387,6 +4399,9 @@
 {
   g_return_if_fail (GTK_IS_ENTRY (entry));
 
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  priv->invisible_char_explicitly_set = TRUE;
+
   if (ch == entry->invisible_char)
     return;
 
@@ -4400,7 +4415,7 @@
  * @entry: a #GtkEntry
  *
  * Retrieves the character displayed in place of the real characters
- * for entries with visisbility set to false. See gtk_entry_set_invisible_char().
+ * for entries with visibility set to false. See gtk_entry_set_invisible_char().
  *
  * Return value: the current invisible char, or 0, if the entry does not
  *               show invisible text at all. 
@@ -4409,8 +4424,19 @@
 gtk_entry_get_invisible_char (GtkEntry *entry)
 {
   g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
+  
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  
+  if (priv->invisible_char_explicitly_set)
+    return entry->invisible_char;
 
-  return entry->invisible_char;
+  gunichar invisible_char;
+
+  g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
+                "gtk-invisible-char", &invisible_char,
+                NULL);
+
+  return invisible_char;
 }
 
 void
