summaryrefslogtreecommitdiff
path: root/gtk/gtkentry.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkentry.c')
-rw-r--r--gtk/gtkentry.c137
1 files changed, 122 insertions, 15 deletions
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 9996cdd9bb..2bfc433439 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -70,7 +70,8 @@ enum {
ARG_TEXT_POSITION,
ARG_EDITABLE,
ARG_MAX_LENGTH,
- ARG_VISIBILITY
+ ARG_VISIBILITY,
+ ARG_INVISIBLE_CHAR
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -285,7 +286,8 @@ gtk_entry_class_init (GtkEntryClass *class)
gtk_object_add_arg_type ("GtkEntry::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
gtk_object_add_arg_type ("GtkEntry::max_length", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MAX_LENGTH);
gtk_object_add_arg_type ("GtkEntry::visibility", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBILITY);
-
+ gtk_object_add_arg_type ("GtkEntry::invisible_char", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_INVISIBLE_CHAR);
+
signals[INSERT_TEXT] =
gtk_signal_new ("insert_text",
GTK_RUN_LAST,
@@ -582,6 +584,9 @@ gtk_entry_set_arg (GtkObject *object,
case ARG_VISIBILITY:
gtk_entry_set_visibility (entry, GTK_VALUE_BOOL (*arg));
break;
+ case ARG_INVISIBLE_CHAR:
+ gtk_entry_set_invisible_char (entry, GTK_VALUE_INT (*arg));
+ break;
default:
break;
}
@@ -610,6 +615,9 @@ gtk_entry_get_arg (GtkObject *object,
case ARG_VISIBILITY:
GTK_VALUE_BOOL (*arg) = entry->visible;
break;
+ case ARG_INVISIBLE_CHAR:
+ GTK_VALUE_INT (*arg) = entry->invisible_char;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
@@ -627,7 +635,8 @@ gtk_entry_init (GtkEntry *entry)
entry->editable = TRUE;
entry->visible = TRUE;
-
+ entry->invisible_char = '*';
+
/* This object is completely private. No external entity can gain a reference
* to it; so we create it here and destroy it in finalize().
*/
@@ -1571,7 +1580,7 @@ gtk_entry_preedit_changed_cb (GtkIMContext *context,
&cursor_pos);
entry->preedit_length = strlen (preedit_string);
cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
- entry->preedit_cursor = g_utf8_offset_to_pointer (preedit_string, cursor_pos) - preedit_string;
+ entry->preedit_cursor = cursor_pos;
g_free (preedit_string);
gtk_entry_recompute (entry);
@@ -1615,6 +1624,25 @@ gtk_entry_recompute (GtkEntry *entry)
}
}
+static void
+append_char (GString *str,
+ gunichar ch,
+ gint count)
+{
+ gint i;
+ gint char_len;
+ gchar buf[7];
+
+ char_len = g_unichar_to_utf8 (ch, buf);
+
+ i = 0;
+ while (i < count)
+ {
+ g_string_append_len (str, buf, char_len);
+ ++i;
+ }
+}
+
static PangoLayout *
gtk_entry_create_layout (GtkEntry *entry,
gboolean include_preedit)
@@ -1639,19 +1667,69 @@ gtk_entry_create_layout (GtkEntry *entry,
gint cursor_index = g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text;
- g_string_prepend_len (tmp_string, entry->text, entry->n_bytes);
- g_string_insert (tmp_string, cursor_index, preedit_string);
+ if (entry->visible)
+ {
+ g_string_prepend_len (tmp_string, entry->text, entry->n_bytes);
+ g_string_insert (tmp_string, cursor_index, preedit_string);
+ }
+ else
+ {
+ gint ch_len;
+ gint preedit_len_chars;
+ gunichar invisible_char;
+
+ ch_len = g_utf8_strlen (entry->text, entry->n_bytes);
+ 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 = ' '; /* just pick a char */
+
+ append_char (tmp_string, invisible_char, ch_len);
+
+ /* Fix cursor index to point to invisible char corresponding
+ * to the preedit, fix preedit_length to be the length of
+ * the invisible chars representing the preedit
+ */
+ cursor_index =
+ g_utf8_offset_to_pointer (tmp_string->str, entry->current_pos) -
+ tmp_string->str;
+ preedit_length =
+ preedit_len_chars *
+ g_unichar_to_utf8 (invisible_char, NULL);
+ }
+
pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
pango_attr_list_splice (tmp_attrs, preedit_attrs,
- cursor_index, entry->preedit_length);
+ cursor_index, preedit_length);
g_string_free (tmp_string, TRUE);
-
}
else
- pango_layout_set_text (layout, entry->text, entry->n_bytes);
-
+ {
+ if (entry->visible)
+ {
+ pango_layout_set_text (layout, entry->text, entry->n_bytes);
+ }
+ else
+ {
+ GString *str = g_string_new (NULL);
+ gunichar invisible_char;
+
+ if (entry->invisible_char != 0)
+ invisible_char = entry->invisible_char;
+ else
+ invisible_char = ' '; /* just pick a char */
+
+ append_char (str, invisible_char, entry->text_length);
+ pango_layout_set_text (layout, str->str, str->len);
+ g_string_free (str, TRUE);
+ }
+ }
+
pango_layout_set_attributes (layout, tmp_attrs);
if (preedit_string)
@@ -1691,6 +1769,9 @@ gtk_entry_draw_text (GtkEntry *entry)
g_return_if_fail (entry != NULL);
g_return_if_fail (GTK_IS_ENTRY (entry));
+ if (!entry->visible && entry->invisible_char == 0)
+ return;
+
if (GTK_WIDGET_DRAWABLE (entry))
{
PangoLayout *layout = gtk_entry_get_layout (entry, TRUE);
@@ -1775,6 +1856,9 @@ gtk_entry_draw_cursor (GtkEntry *entry)
g_return_if_fail (entry != NULL);
g_return_if_fail (GTK_IS_ENTRY (entry));
+ if (!entry->visible && entry->invisible_char == 0)
+ return;
+
if (GTK_WIDGET_DRAWABLE (entry))
{
GtkWidget *widget = GTK_WIDGET (entry);
@@ -1870,11 +1954,17 @@ gtk_entry_get_cursor_locations (GtkEntry *entry,
gint *weak_x)
{
PangoLayout *layout = gtk_entry_get_layout (entry, TRUE);
- gint index = g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text;
-
+ const gchar *text;
PangoRectangle strong_pos, weak_pos;
+ gint index;
+
+ text = pango_layout_get_text (layout);
- index += entry->preedit_cursor;
+ index =
+ g_utf8_offset_to_pointer (text,
+ entry->current_pos +
+ entry->preedit_cursor) - text;
+
pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
g_object_unref (G_OBJECT (layout));
@@ -1978,8 +2068,11 @@ gtk_entry_move_visually (GtkEntry *entry,
{
gint index;
PangoLayout *layout = gtk_entry_get_layout (entry, FALSE);
+ const gchar *text;
- index = g_utf8_offset_to_pointer (entry->text, start) - entry->text;
+ text = pango_layout_get_text (layout);
+
+ index = g_utf8_offset_to_pointer (text, start) - text;
while (count != 0)
{
@@ -2007,7 +2100,7 @@ gtk_entry_move_visually (GtkEntry *entry,
g_object_unref (G_OBJECT (layout));
- return g_utf8_pointer_to_offset (entry->text, entry->text + index);
+ return g_utf8_pointer_to_offset (text, text + index);
}
static gint
@@ -2324,6 +2417,20 @@ gtk_entry_set_visibility (GtkEntry *entry,
}
void
+gtk_entry_set_invisible_char (GtkEntry *entry,
+ gunichar ch)
+{
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (ch == entry->invisible_char)
+ return;
+
+ entry->invisible_char = ch;
+
+ gtk_entry_recompute (entry);
+}
+
+void
gtk_entry_set_editable(GtkEntry *entry,
gboolean editable)
{