aboutsummaryrefslogtreecommitdiff
path: root/gtksecentry/gtksecentry.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtksecentry/gtksecentry.c')
-rw-r--r--gtksecentry/gtksecentry.c3364
1 files changed, 0 insertions, 3364 deletions
diff --git a/gtksecentry/gtksecentry.c b/gtksecentry/gtksecentry.c
deleted file mode 100644
index f68f094..0000000
--- a/gtksecentry/gtksecentry.c
+++ /dev/null
@@ -1,3364 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 2004 Albrecht Dreß
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GTK+ Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * Heavily stripped down for use in pinentry-gtk-2 by Albrecht Dreß
- * <albrecht.dress@arcor.de> Feb. 2004:
- *
- * The entry is now always invisible, uses secure memory methods to
- * allocate the text memory, and all potentially dangerous methods
- * (copy & paste, popup, etc.) have been removed.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include "gtksecentry.h"
-#include "memory.h"
-
-#define MIN_SECURE_ENTRY_WIDTH 150
-#define DRAW_TIMEOUT 20
-#define INNER_BORDER 2
-
-/* Initial size of buffer, in bytes */
-#define MIN_SIZE 16
-
-/* Maximum size of text buffer, in bytes */
-#define MAX_SIZE G_MAXUSHORT
-
-enum {
- ACTIVATE,
- MOVE_CURSOR,
- INSERT_AT_CURSOR,
- DELETE_FROM_CURSOR,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_CURSOR_POSITION,
- PROP_SELECTION_BOUND,
- PROP_MAX_LENGTH,
- PROP_HAS_FRAME,
- PROP_INVISIBLE_CHAR,
- PROP_ACTIVATES_DEFAULT,
- PROP_WIDTH_CHARS,
- PROP_SCROLL_OFFSET,
- PROP_TEXT
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* GObject, GtkObject methods
- */
-static void gtk_secure_entry_class_init(GtkSecureEntryClass * klass);
-static void gtk_secure_entry_editable_init(GtkEditableClass * iface);
-static void gtk_secure_entry_cell_editable_init(GtkCellEditableIface *
- iface);
-static void gtk_secure_entry_init(GtkSecureEntry * entry);
-static void gtk_secure_entry_set_property(GObject * object,
- guint prop_id,
- const GValue * value,
- GParamSpec * pspec);
-static void gtk_secure_entry_get_property(GObject * object,
- guint prop_id,
- GValue * value,
- GParamSpec * pspec);
-static void gtk_secure_entry_finalize(GObject * object);
-
-/* GtkWidget methods
- */
-static void gtk_secure_entry_realize(GtkWidget * widget);
-static void gtk_secure_entry_unrealize(GtkWidget * widget);
-static void gtk_secure_entry_size_request(GtkWidget * widget,
- GtkRequisition * requisition);
-static void gtk_secure_entry_size_allocate(GtkWidget * widget,
- GtkAllocation * allocation);
-static void gtk_secure_entry_draw_frame(GtkWidget * widget);
-static gint gtk_secure_entry_expose(GtkWidget * widget,
- GdkEventExpose * event);
-static gint gtk_secure_entry_button_press(GtkWidget * widget,
- GdkEventButton * event);
-static gint gtk_secure_entry_button_release(GtkWidget * widget,
- GdkEventButton * event);
-static gint gtk_secure_entry_motion_notify(GtkWidget * widget,
- GdkEventMotion * event);
-static gint gtk_secure_entry_key_press(GtkWidget * widget,
- GdkEventKey * event);
-static gint gtk_secure_entry_key_release(GtkWidget * widget,
- GdkEventKey * event);
-static gint gtk_secure_entry_focus_in(GtkWidget * widget,
- GdkEventFocus * event);
-static gint gtk_secure_entry_focus_out(GtkWidget * widget,
- GdkEventFocus * event);
-static void gtk_secure_entry_grab_focus(GtkWidget * widget);
-static void gtk_secure_entry_style_set(GtkWidget * widget,
- GtkStyle * previous_style);
-static void gtk_secure_entry_direction_changed(GtkWidget * widget,
- GtkTextDirection
- previous_dir);
-static void gtk_secure_entry_state_changed(GtkWidget * widget,
- GtkStateType previous_state);
-static void gtk_secure_entry_screen_changed(GtkWidget * widget,
- GdkScreen * old_screen);
-
-/* GtkEditable method implementations
- */
-static void gtk_secure_entry_insert_text(GtkEditable * editable,
- const gchar * new_text,
- gint new_text_length,
- gint * position);
-static void gtk_secure_entry_delete_text(GtkEditable * editable,
- gint start_pos, gint end_pos);
-static void gtk_secure_entry_real_set_position(GtkEditable * editable,
- gint position);
-static gint gtk_secure_entry_get_position(GtkEditable * editable);
-static void gtk_secure_entry_set_selection_bounds(GtkEditable * editable,
- gint start, gint end);
-static gboolean gtk_secure_entry_get_selection_bounds(GtkEditable *
- editable,
- gint * start,
- gint * end);
-
-/* GtkCellEditable method implementations
- */
-static void gtk_secure_entry_start_editing(GtkCellEditable * cell_editable,
- GdkEvent * event);
-
-/* Default signal handlers
- */
-static void gtk_secure_entry_real_insert_text(GtkEditable * editable,
- const gchar * new_text,
- gint new_text_length,
- gint * position);
-static void gtk_secure_entry_real_delete_text(GtkEditable * editable,
- gint start_pos,
- gint end_pos);
-static void gtk_secure_entry_move_cursor(GtkSecureEntry * entry,
- GtkMovementStep step,
- gint count,
- gboolean extend_selection);
-static void gtk_secure_entry_insert_at_cursor(GtkSecureEntry * entry,
- const gchar * str);
-static void gtk_secure_entry_delete_from_cursor(GtkSecureEntry * entry,
- GtkDeleteType type,
- gint count);
-static void gtk_secure_entry_real_activate(GtkSecureEntry * entry);
-
-static void gtk_secure_entry_keymap_direction_changed(GdkKeymap * keymap,
- GtkSecureEntry *
- entry);
-/* IM Context Callbacks
- */
-static void gtk_secure_entry_commit_cb(GtkIMContext * context,
- const gchar * str,
- GtkSecureEntry * entry);
-static void gtk_secure_entry_preedit_changed_cb(GtkIMContext * context,
- GtkSecureEntry * entry);
-static gboolean gtk_secure_entry_retrieve_surrounding_cb(GtkIMContext *
- context,
- GtkSecureEntry *
- entry);
-static gboolean gtk_secure_entry_delete_surrounding_cb(GtkIMContext *
- context,
- gint offset,
- gint n_chars,
- GtkSecureEntry *
- entry);
-
-/* Internal routines
- */
-static void gtk_secure_entry_enter_text(GtkSecureEntry * entry,
- const gchar * str);
-static void gtk_secure_entry_set_positions(GtkSecureEntry * entry,
- gint current_pos,
- gint selection_bound);
-static void gtk_secure_entry_draw_text(GtkSecureEntry * entry);
-static void gtk_secure_entry_draw_cursor(GtkSecureEntry * entry);
-static PangoLayout *gtk_secure_entry_ensure_layout(GtkSecureEntry * entry,
- gboolean
- include_preedit);
-static void gtk_secure_entry_reset_layout(GtkSecureEntry * entry);
-static void gtk_secure_entry_queue_draw(GtkSecureEntry * entry);
-static void gtk_secure_entry_reset_im_context(GtkSecureEntry * entry);
-static void gtk_secure_entry_recompute(GtkSecureEntry * entry);
-static gint gtk_secure_entry_find_position(GtkSecureEntry * entry, gint x);
-static void gtk_secure_entry_get_cursor_locations(GtkSecureEntry * entry,
- gint * strong_x,
- gint * weak_x);
-static void gtk_secure_entry_adjust_scroll(GtkSecureEntry * entry);
-static gint gtk_secure_entry_move_visually(GtkSecureEntry * editable,
- gint start, gint count);
-static gint gtk_secure_entry_move_logically(GtkSecureEntry * entry,
- gint start, gint count);
-static gboolean gtk_secure_entry_mnemonic_activate(GtkWidget * widget,
- gboolean group_cycling);
-static void gtk_secure_entry_check_cursor_blink(GtkSecureEntry * entry);
-static void gtk_secure_entry_pend_cursor_blink(GtkSecureEntry * entry);
-static void get_text_area_size(GtkSecureEntry * entry,
- gint * x,
- gint * y, gint * width, gint * height);
-static void get_widget_window_size(GtkSecureEntry * entry,
- gint * x,
- gint * y, gint * width, gint * height);
-
-
-
-#define _gtk_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
-#define _gtk_marshal_VOID__STRING g_cclosure_marshal_VOID__STRING
-static void _gtk_marshal_VOID__ENUM_INT_BOOLEAN(GClosure * closure,
- GValue * return_value,
- guint n_param_values,
- const GValue *
- param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-static void _gtk_marshal_VOID__ENUM_INT(GClosure * closure,
- GValue * return_value,
- guint n_param_values,
- const GValue * param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-
-static GtkWidgetClass *parent_class = NULL;
-
-gboolean g_use_secure_mem = FALSE;
-
-# define g_sec_new(type, count) \
- ((type *) g_sec_malloc ((unsigned) sizeof (type) * (count)))
-
-#define WITH_SECURE_MEM(EXP) do { \
- gboolean tmp = g_use_secure_mem; \
- g_use_secure_mem = TRUE; \
- EXP; \
- g_use_secure_mem = tmp; \
- } while(0)
-
-
-gpointer
-g_malloc(gsize size)
-{
- gpointer p;
-
- if (size == 0)
- return NULL;
-
- if (g_use_secure_mem)
- p = (gpointer) secmem_malloc(size);
- else
- p = (gpointer) malloc(size);
- if (!p)
- g_error("could not allocate %"G_GSIZE_FORMAT" bytes", size);
-
- return p;
-}
-
-gpointer
-g_malloc0(gsize size)
-{
- gpointer p;
-
- if (size == 0)
- return NULL;
-
- if (g_use_secure_mem) {
- p = (gpointer) secmem_malloc(size);
- if (p)
- memset(p, 0, size);
- } else
- p = (gpointer) calloc(size, 1);
- if (!p)
- g_error("could not allocate %"G_GSIZE_FORMAT" bytes", size);
-
- return p;
-}
-
-gpointer
-g_realloc(gpointer mem, gsize size)
-{
- gpointer p;
-
- if (size == 0) {
- g_free(mem);
-
- return NULL;
- }
-
- if (!mem) {
- if (g_use_secure_mem)
- p = (gpointer) secmem_malloc(size);
- else
- p = (gpointer) malloc(size);
- } else {
- if (g_use_secure_mem) {
- g_assert(m_is_secure(mem));
- p = (gpointer) secmem_realloc(mem, size);
- } else
- p = (gpointer) realloc(mem, size);
- }
-
- if (!p)
- g_error("could not reallocate %lu bytes", (gulong) size);
-
- return p;
-}
-
-void
-g_free(gpointer mem)
-{
- if (mem) {
- if (m_is_secure(mem))
- secmem_free(mem);
- else
- free(mem);
- }
-}
-
-GType
-gtk_secure_entry_get_type(void)
-{
- static GType entry_type = 0;
-
- if (!entry_type) {
- static const GTypeInfo entry_info = {
- sizeof(GtkSecureEntryClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_secure_entry_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(GtkSecureEntry),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gtk_secure_entry_init,
- NULL,
- };
-
- static const GInterfaceInfo editable_info = {
- (GInterfaceInitFunc) gtk_secure_entry_editable_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
- static const GInterfaceInfo cell_editable_info = {
- (GInterfaceInitFunc) gtk_secure_entry_cell_editable_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
- entry_type =
- g_type_register_static(GTK_TYPE_WIDGET, "GtkSecureEntry",
- &entry_info, 0);
-
- g_type_add_interface_static(entry_type,
- GTK_TYPE_EDITABLE, &editable_info);
- g_type_add_interface_static(entry_type,
- GTK_TYPE_CELL_EDITABLE,
- &cell_editable_info);
- }
-
- return entry_type;
-}
-
-static void
-add_move_binding(GtkBindingSet * binding_set,
- guint keyval,
- guint modmask, GtkMovementStep step, gint count)
-{
- g_return_if_fail((modmask & GDK_SHIFT_MASK) == 0);
-
- gtk_binding_entry_add_signal(binding_set, keyval, modmask,
- "move_cursor", 3,
- G_TYPE_ENUM, step,
- G_TYPE_INT, count, G_TYPE_BOOLEAN, FALSE);
-
- /* Selection-extending version */
- gtk_binding_entry_add_signal(binding_set, keyval,
- modmask | GDK_SHIFT_MASK, "move_cursor",
- 3, G_TYPE_ENUM, step, G_TYPE_INT, count,
- G_TYPE_BOOLEAN, TRUE);
-}
-
-static void
-gtk_secure_entry_class_init(GtkSecureEntryClass * class)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(class);
- GtkWidgetClass *widget_class;
- GtkBindingSet *binding_set;
-
- widget_class = (GtkWidgetClass *) class;
- parent_class = g_type_class_peek_parent(class);
-
- gobject_class->finalize = gtk_secure_entry_finalize;
- gobject_class->set_property = gtk_secure_entry_set_property;
- gobject_class->get_property = gtk_secure_entry_get_property;
-
- widget_class->realize = gtk_secure_entry_realize;
- widget_class->unrealize = gtk_secure_entry_unrealize;
- widget_class->size_request = gtk_secure_entry_size_request;
- widget_class->size_allocate = gtk_secure_entry_size_allocate;
- widget_class->expose_event = gtk_secure_entry_expose;
- widget_class->button_press_event = gtk_secure_entry_button_press;
- widget_class->button_release_event = gtk_secure_entry_button_release;
- widget_class->motion_notify_event = gtk_secure_entry_motion_notify;
- widget_class->key_press_event = gtk_secure_entry_key_press;
- widget_class->key_release_event = gtk_secure_entry_key_release;
- widget_class->focus_in_event = gtk_secure_entry_focus_in;
- widget_class->focus_out_event = gtk_secure_entry_focus_out;
- widget_class->grab_focus = gtk_secure_entry_grab_focus;
- widget_class->style_set = gtk_secure_entry_style_set;
- widget_class->direction_changed = gtk_secure_entry_direction_changed;
- widget_class->state_changed = gtk_secure_entry_state_changed;
- widget_class->screen_changed = gtk_secure_entry_screen_changed;
- widget_class->mnemonic_activate = gtk_secure_entry_mnemonic_activate;
-
- class->move_cursor = gtk_secure_entry_move_cursor;
- class->insert_at_cursor = gtk_secure_entry_insert_at_cursor;
- class->delete_from_cursor = gtk_secure_entry_delete_from_cursor;
- class->activate = gtk_secure_entry_real_activate;
-
- g_object_class_install_property(gobject_class,
- PROP_CURSOR_POSITION,
- g_param_spec_int("cursor_position",
- "Cursor Position",
- "The current position of the insertion cursor in chars",
- 0, MAX_SIZE, 0,
- G_PARAM_READABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_SELECTION_BOUND,
- g_param_spec_int("selection_bound",
- "Selection Bound",
- "The position of the opposite end of the selection from the cursor in chars",
- 0, MAX_SIZE, 0,
- G_PARAM_READABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_MAX_LENGTH,
- g_param_spec_int("max_length",
- "Maximum length",
- "Maximum number of characters for this entry. Zero if no maximum",
- 0, MAX_SIZE, 0,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_HAS_FRAME,
- g_param_spec_boolean("has_frame",
- "Has Frame",
- "FALSE removes outside bevel from entry",
- TRUE,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_INVISIBLE_CHAR,
- g_param_spec_unichar("invisible_char",
- "Invisible character",
- "The character to use when masking entry contents (in \"password mode\")",
- '*',
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_ACTIVATES_DEFAULT,
- g_param_spec_boolean
- ("activates_default",
- "Activates default",
- "Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed",
- FALSE,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
- g_object_class_install_property(gobject_class, PROP_WIDTH_CHARS,
- g_param_spec_int("width_chars",
- "Width in chars",
- "Number of characters to leave space for in the entry",
- -1, G_MAXINT, -1,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_SCROLL_OFFSET,
- g_param_spec_int("scroll_offset",
- "Scroll offset",
- "Number of pixels of the entry scrolled off the screen to the left",
- 0, G_MAXINT, 0,
- G_PARAM_READABLE));
-
- g_object_class_install_property(gobject_class,
- PROP_TEXT,
- g_param_spec_string("text",
- "Text",
- "The contents of the entry",
- "",
- G_PARAM_READABLE |
- G_PARAM_WRITABLE));
-
- /* Action signals */
-
- signals[ACTIVATE] =
- g_signal_new("activate",
- G_OBJECT_CLASS_TYPE(gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkSecureEntryClass, activate),
- NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0);
- widget_class->activate_signal = signals[ACTIVATE];
-
- signals[MOVE_CURSOR] =
- g_signal_new("move_cursor",
- G_OBJECT_CLASS_TYPE(gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkSecureEntryClass, move_cursor),
- NULL, NULL,
- _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
- G_TYPE_NONE, 3,
- GTK_TYPE_MOVEMENT_STEP, G_TYPE_INT, G_TYPE_BOOLEAN);
-
- signals[INSERT_AT_CURSOR] =
- g_signal_new("insert_at_cursor",
- G_OBJECT_CLASS_TYPE(gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkSecureEntryClass,
- insert_at_cursor), NULL, NULL,
- _gtk_marshal_VOID__STRING, G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- signals[DELETE_FROM_CURSOR] =
- g_signal_new("delete_from_cursor",
- G_OBJECT_CLASS_TYPE(gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET(GtkSecureEntryClass,
- delete_from_cursor), NULL, NULL,
- _gtk_marshal_VOID__ENUM_INT, G_TYPE_NONE, 2,
- GTK_TYPE_DELETE_TYPE, G_TYPE_INT);
-
- /*
- * Key bindings
- */
-
- binding_set = gtk_binding_set_by_class(class);
-
- /* Moving the insertion point */
- add_move_binding(binding_set, GDK_Right, 0,
- GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-
- add_move_binding(binding_set, GDK_Left, 0,
- GTK_MOVEMENT_VISUAL_POSITIONS, -1);
-
- add_move_binding(binding_set, GDK_KP_Right, 0,
- GTK_MOVEMENT_VISUAL_POSITIONS, 1);
-
- add_move_binding(binding_set, GDK_KP_Left, 0,
- GTK_MOVEMENT_VISUAL_POSITIONS, -1);
-
- add_move_binding(binding_set, GDK_Right, GDK_CONTROL_MASK,
- GTK_MOVEMENT_WORDS, 1);
-
- add_move_binding(binding_set, GDK_Left, GDK_CONTROL_MASK,
- GTK_MOVEMENT_WORDS, -1);
-
- add_move_binding(binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
- GTK_MOVEMENT_WORDS, 1);
-
- add_move_binding(binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
- GTK_MOVEMENT_WORDS, -1);
-
- add_move_binding(binding_set, GDK_Home, 0,
- GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
-
- add_move_binding(binding_set, GDK_End, 0,
- GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
-
- add_move_binding(binding_set, GDK_KP_Home, 0,
- GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
-
- add_move_binding(binding_set, GDK_KP_End, 0,
- GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
-
- add_move_binding(binding_set, GDK_Home, GDK_CONTROL_MASK,
- GTK_MOVEMENT_BUFFER_ENDS, -1);
-
- add_move_binding(binding_set, GDK_End, GDK_CONTROL_MASK,
- GTK_MOVEMENT_BUFFER_ENDS, 1);
-
- add_move_binding(binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
- GTK_MOVEMENT_BUFFER_ENDS, -1);
-
- add_move_binding(binding_set, GDK_KP_End, GDK_CONTROL_MASK,
- GTK_MOVEMENT_BUFFER_ENDS, 1);
-
- /* Select all
- */
- gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
- "move_cursor", 3,
- GTK_TYPE_MOVEMENT_STEP,
- GTK_MOVEMENT_BUFFER_ENDS, G_TYPE_INT, -1,
- G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
- "move_cursor", 3, GTK_TYPE_MOVEMENT_STEP,
- GTK_MOVEMENT_BUFFER_ENDS, G_TYPE_INT, 1,
- G_TYPE_BOOLEAN, TRUE);
-
-
- /* Activate
- */
- gtk_binding_entry_add_signal(binding_set, GDK_Return, 0,
- "activate", 0);
- gtk_binding_entry_add_signal(binding_set, GDK_KP_Enter, 0,
- "activate", 0);
-
- /* Deleting text */
- gtk_binding_entry_add_signal(binding_set, GDK_Delete, 0,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal(binding_set, GDK_KP_Delete, 0,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal(binding_set, GDK_BackSpace, 0,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS,
- G_TYPE_INT, -1);
-
- /* Make this do the same as Backspace, to help with mis-typing */
- gtk_binding_entry_add_signal(binding_set, GDK_BackSpace,
- GDK_SHIFT_MASK, "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_CHARS, G_TYPE_INT,
- -1);
-
- gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_CONTROL_MASK,
- "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal(binding_set, GDK_KP_Delete,
- GDK_CONTROL_MASK, "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
- G_TYPE_INT, 1);
-
- gtk_binding_entry_add_signal(binding_set, GDK_BackSpace,
- GDK_CONTROL_MASK, "delete_from_cursor", 2,
- G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
- G_TYPE_INT, -1);
-}
-
-static void
-gtk_secure_entry_editable_init(GtkEditableClass * iface)
-{
- iface->do_insert_text = gtk_secure_entry_insert_text;
- iface->do_delete_text = gtk_secure_entry_delete_text;
- iface->insert_text = gtk_secure_entry_real_insert_text;
- iface->delete_text = gtk_secure_entry_real_delete_text;
- iface->set_selection_bounds = gtk_secure_entry_set_selection_bounds;
- iface->get_selection_bounds = gtk_secure_entry_get_selection_bounds;
- iface->set_position = gtk_secure_entry_real_set_position;
- iface->get_position = gtk_secure_entry_get_position;
-}
-
-static void
-gtk_secure_entry_cell_editable_init(GtkCellEditableIface * iface)
-{
- iface->start_editing = gtk_secure_entry_start_editing;
-}
-
-static void
-gtk_secure_entry_set_property(GObject * object,
- guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(object);
-
- switch (prop_id) {
- case PROP_MAX_LENGTH:
- gtk_secure_entry_set_max_length(entry, g_value_get_int(value));
- break;
-
- case PROP_HAS_FRAME:
- gtk_secure_entry_set_has_frame(entry, g_value_get_boolean(value));
- break;
-
- case PROP_INVISIBLE_CHAR:
- gtk_secure_entry_set_invisible_char(entry,
- g_value_get_uint(value));
- break;
-
- case PROP_ACTIVATES_DEFAULT:
- gtk_secure_entry_set_activates_default(entry,
- g_value_get_boolean(value));
- break;
-
- case PROP_WIDTH_CHARS:
- gtk_secure_entry_set_width_chars(entry, g_value_get_int(value));
- break;
-
- case PROP_TEXT:
- gtk_secure_entry_set_text(entry, g_value_get_string(value));
- break;
-
- case PROP_SCROLL_OFFSET:
- case PROP_CURSOR_POSITION:
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_secure_entry_get_property(GObject * object,
- guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(object);
-
- switch (prop_id) {
- case PROP_CURSOR_POSITION:
- g_value_set_int(value, entry->current_pos);
- break;
- case PROP_SELECTION_BOUND:
- g_value_set_int(value, entry->selection_bound);
- break;
- case PROP_MAX_LENGTH:
- g_value_set_int(value, entry->text_max_length);
- break;
- case PROP_HAS_FRAME:
- g_value_set_boolean(value, entry->has_frame);
- break;
- case PROP_INVISIBLE_CHAR:
- g_value_set_uint(value, entry->invisible_char);
- break;
- case PROP_ACTIVATES_DEFAULT:
- g_value_set_boolean(value, entry->activates_default);
- break;
- case PROP_WIDTH_CHARS:
- g_value_set_int(value, entry->width_chars);
- break;
- case PROP_SCROLL_OFFSET:
- g_value_set_int(value, entry->scroll_offset);
- break;
- case PROP_TEXT:
- g_value_set_string(value, gtk_secure_entry_get_text(entry));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_secure_entry_init(GtkSecureEntry * entry)
-{
- gtk_widget_set_can_focus (GTK_WIDGET(entry), TRUE);
-
- entry->text_size = MIN_SIZE;
- WITH_SECURE_MEM(entry->text = g_malloc(entry->text_size));
- entry->text[0] = '\0';
-
- entry->invisible_char = '*';
- entry->width_chars = -1;
- entry->is_cell_renderer = FALSE;
- entry->editing_canceled = FALSE;
- entry->has_frame = TRUE;
-
- /* This object is completely private. No external entity can gain a reference
- * to it; so we create it here and destroy it in finalize().
- */
- entry->im_context = gtk_im_multicontext_new();
-
- g_signal_connect(entry->im_context, "commit",
- G_CALLBACK(gtk_secure_entry_commit_cb), entry);
- g_signal_connect(entry->im_context, "preedit_changed",
- G_CALLBACK(gtk_secure_entry_preedit_changed_cb),
- entry);
- g_signal_connect(entry->im_context, "retrieve_surrounding",
- G_CALLBACK(gtk_secure_entry_retrieve_surrounding_cb),
- entry);
- g_signal_connect(entry->im_context, "delete_surrounding",
- G_CALLBACK(gtk_secure_entry_delete_surrounding_cb),
- entry);
-}
-
-static void
-gtk_secure_entry_finalize(GObject * object)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(object);
-
- if (entry->cached_layout)
- g_object_unref(entry->cached_layout);
-
- g_object_unref(entry->im_context);
-
- if (entry->blink_timeout)
- g_source_remove(entry->blink_timeout);
-
- if (entry->recompute_idle)
- g_source_remove(entry->recompute_idle);
-
- entry->text_size = 0;
-
- if (entry->text)
- WITH_SECURE_MEM(g_free(entry->text));
- entry->text = NULL;
-
- G_OBJECT_CLASS(parent_class)->finalize(object);
-}
-
-static void
-gtk_secure_entry_realize(GtkWidget * widget)
-{
- GtkSecureEntry *entry;
- GtkEditable *editable;
- GdkWindow *window;
- GtkStyle *style;
- GdkWindowAttr attributes;
- gint attributes_mask;
-
- gtk_widget_set_realized (widget, TRUE);
-
- entry = GTK_SECURE_ENTRY(widget);
- editable = GTK_EDITABLE(widget);
-
- attributes.window_type = GDK_WINDOW_CHILD;
-
- get_widget_window_size(entry, &attributes.x, &attributes.y,
- &attributes.width, &attributes.height);
-
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual(widget);
- attributes.colormap = gtk_widget_get_colormap(widget);
- attributes.event_mask = gtk_widget_get_events(widget);
- attributes.event_mask |= (GDK_EXPOSURE_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_BUTTON1_MOTION_MASK |
- GDK_BUTTON3_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK);
- attributes_mask =
- GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
- window = gdk_window_new(gtk_widget_get_parent_window(widget),
- &attributes, attributes_mask);
- gtk_widget_set_window (widget, window);
- gdk_window_set_user_data(window, entry);
-
- get_text_area_size(entry, &attributes.x, &attributes.y,
- &attributes.width, &attributes.height);
-
- attributes.cursor =
- gdk_cursor_new_for_display(gtk_widget_get_display(widget),
- GDK_XTERM);
- attributes_mask |= GDK_WA_CURSOR;
-
- entry->text_area =
- gdk_window_new(window, &attributes, attributes_mask);
- gdk_window_set_user_data(entry->text_area, entry);
-
- gdk_cursor_unref(attributes.cursor);
-
- style = gtk_widget_get_style (widget);
- style = gtk_style_attach(style, window);
- gtk_widget_set_style (widget, style);
-
- gdk_window_set_background(window,
- &style->base[gtk_widget_get_state (widget)]);
- gdk_window_set_background(entry->text_area,
- &style->base[gtk_widget_get_state (widget)]);
-
- gdk_window_show(entry->text_area);
-
- gtk_im_context_set_client_window(entry->im_context, entry->text_area);
-
- gtk_secure_entry_adjust_scroll(entry);
-}
-
-static void
-gtk_secure_entry_unrealize(GtkWidget * widget)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_secure_entry_reset_layout(entry);
-
- gtk_im_context_set_client_window(entry->im_context, NULL);
-
- if (entry->text_area) {
- gdk_window_set_user_data(entry->text_area, NULL);
- gdk_window_destroy(entry->text_area);
- entry->text_area = NULL;
- }
-
- if (GTK_WIDGET_CLASS(parent_class)->unrealize)
- (*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget);
-}
-
-static void
-get_borders(GtkSecureEntry * entry, gint * xborder, gint * yborder)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
- GtkStyle *style;
- gint focus_width;
- gboolean interior_focus;
-
- gtk_widget_style_get(widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width, NULL);
-
- style = gtk_widget_get_style (widget);
- if (entry->has_frame) {
- *xborder = style->xthickness;
- *yborder = style->ythickness;
- } else {
- *xborder = 0;
- *yborder = 0;
- }
-
- if (!interior_focus) {
- *xborder += focus_width;
- *yborder += focus_width;
- }
-}
-
-static void
-gtk_secure_entry_size_request(GtkWidget * widget,
- GtkRequisition * requisition)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- GtkStyle *style;
- PangoFontMetrics *metrics;
- gint xborder, yborder;
- PangoContext *context;
-
- style = gtk_widget_get_style (widget);
- context = gtk_widget_get_pango_context(widget);
- metrics = pango_context_get_metrics(context,
- style->font_desc,
- pango_context_get_language
- (context));
-
- entry->ascent = pango_font_metrics_get_ascent(metrics);
- entry->descent = pango_font_metrics_get_descent(metrics);
-
- get_borders(entry, &xborder, &yborder);
-
- xborder += INNER_BORDER;
- yborder += INNER_BORDER;
-
- if (entry->width_chars < 0)
- requisition->width = MIN_SECURE_ENTRY_WIDTH + xborder * 2;
- 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->height =
- PANGO_PIXELS(entry->ascent + entry->descent) + yborder * 2;
-
- pango_font_metrics_unref(metrics);
-}
-
-static void
-get_text_area_size(GtkSecureEntry * entry,
- gint * x, gint * y, gint * width, gint * height)
-{
- gint xborder, yborder;
- GtkRequisition requisition;
- GtkWidget *widget = GTK_WIDGET(entry);
- GtkAllocation allocation;
-
- gtk_widget_get_child_requisition(widget, &requisition);
- gtk_widget_get_allocation (GTK_WIDGET(entry), &allocation);
-
- get_borders(entry, &xborder, &yborder);
-
- if (x)
- *x = xborder;
-
- if (y)
- *y = yborder;
-
- if (width)
- *width = allocation.width - xborder * 2;
-
- if (height)
- *height = requisition.height - yborder * 2;
-}
-
-static void
-get_widget_window_size(GtkSecureEntry * entry,
- gint * x, gint * y, gint * width, gint * height)
-{
- GtkRequisition requisition;
- GtkWidget *widget = GTK_WIDGET(entry);
- GtkAllocation allocation;
-
- gtk_widget_get_child_requisition(widget, &requisition);
- gtk_widget_get_allocation (GTK_WIDGET(entry), &allocation);
-
- if (x)
- *x = allocation.x;
-
- if (y) {
- if (entry->is_cell_renderer)
- *y = allocation.y;
- else
- *y = allocation.y + (allocation.height -
- requisition.height) / 2;
- }
-
- if (width)
- *width = allocation.width;
-
- if (height) {
- if (entry->is_cell_renderer)
- *height = allocation.height;
- else
- *height = requisition.height;
- }
-}
-
-static void
-gtk_secure_entry_size_allocate(GtkWidget * widget,
- GtkAllocation * allocation)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_widget_set_allocation (widget, allocation);
-
- if (gtk_widget_get_realized (widget)) {
- /* We call gtk_widget_get_child_requisition, since we want (for
- * backwards compatibility reasons) the realization here to
- * be affected by the usize of the entry, if set
- */
- gint x, y, width, height;
-
- get_widget_window_size(entry, &x, &y, &width, &height);
-
- gdk_window_move_resize(gtk_widget_get_window (widget),
- x, y, width, height);
-
- get_text_area_size(entry, &x, &y, &width, &height);
-
- gdk_window_move_resize(entry->text_area, x, y, width, height);
-
- gtk_secure_entry_recompute(entry);
- }
-}
-
-static void
-gtk_secure_entry_draw_frame(GtkWidget * widget)
-{
- GtkStyle *style;
- GdkWindow *window;
- gint x = 0, y = 0;
- gint width, height;
- gboolean interior_focus;
- gint focus_width;
-
- gtk_widget_style_get(widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width, NULL);
-
- window = gtk_widget_get_window (widget);
- gdk_drawable_get_size(window, &width, &height);
-
- if (gtk_widget_has_focus (widget) && !interior_focus) {
- x += focus_width;
- y += focus_width;
- width -= 2 * focus_width;
- height -= 2 * focus_width;
- }
-
- style = gtk_widget_get_style (widget);
- gtk_paint_shadow(style, window,
- GTK_STATE_NORMAL, GTK_SHADOW_IN,
- NULL, widget, "entry", x, y, width, height);
-
- if (gtk_widget_has_focus (widget) && !interior_focus) {
- x -= focus_width;
- y -= focus_width;
- width += 2 * focus_width;
- height += 2 * focus_width;
-
- gtk_paint_focus(style, window,
- gtk_widget_get_state (widget), NULL, widget, "entry", 0,
- 0, width, height);
- }
-}
-
-static gint
-gtk_secure_entry_expose(GtkWidget * widget, GdkEventExpose * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- GtkStyle *style;
-
- if (gtk_widget_get_window (widget) == event->window)
- gtk_secure_entry_draw_frame(widget);
- else if (entry->text_area == event->window) {
- gint area_width, area_height;
-
- get_text_area_size(entry, NULL, NULL, &area_width, &area_height);
-
-
- style = gtk_widget_get_style (widget);
- gtk_paint_flat_box(style, entry->text_area,
- gtk_widget_get_state (widget), GTK_SHADOW_NONE,
- NULL, widget, "entry_bg",
- 0, 0, area_width, area_height);
-
- if ((entry->invisible_char != 0) &&
- gtk_widget_has_focus (widget) &&
- entry->selection_bound == entry->current_pos
- && entry->cursor_visible)
- gtk_secure_entry_draw_cursor(GTK_SECURE_ENTRY(widget));
-
- gtk_secure_entry_draw_text(GTK_SECURE_ENTRY(widget));
- }
-
- return FALSE;
-}
-
-static gint
-gtk_secure_entry_button_press(GtkWidget * widget, GdkEventButton * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- gint tmp_pos;
-
- if (event->window != entry->text_area ||
- (entry->button && event->button != entry->button))
- 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;
- }
-
- tmp_pos =
- gtk_secure_entry_find_position(entry,
- event->x + entry->scroll_offset);
-
- if (event->button == 1) {
- switch (event->type) {
- case GDK_BUTTON_PRESS:
- gtk_secure_entry_set_positions(entry, tmp_pos, tmp_pos);
- break;
-
- default:
- break;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gint
-gtk_secure_entry_button_release(GtkWidget * widget, GdkEventButton * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- if (event->window != entry->text_area
- || entry->button != event->button)
- return FALSE;
-
- entry->button = 0;
-
- return TRUE;
-}
-
-static gint
-gtk_secure_entry_motion_notify(GtkWidget * widget, GdkEventMotion * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- gint tmp_pos;
-
- if (entry->mouse_cursor_obscured) {
- GdkCursor *cursor;
-
- cursor =
- gdk_cursor_new_for_display(gtk_widget_get_display(widget),
- GDK_XTERM);
- gdk_window_set_cursor(entry->text_area, cursor);
- gdk_cursor_unref(cursor);
- entry->mouse_cursor_obscured = FALSE;
- }
-
- if (event->window != entry->text_area || entry->button != 1)
- return FALSE;
-
- if (event->is_hint || (entry->text_area != event->window))
- gdk_window_get_pointer(entry->text_area, NULL, NULL, NULL);
-
- {
- gint height;
- gdk_drawable_get_size(entry->text_area, NULL, &height);
-
- if (event->y < 0)
- tmp_pos = 0;
- else if (event->y >= height)
- tmp_pos = entry->text_length;
- else
- tmp_pos =
- gtk_secure_entry_find_position(entry,
- event->x +
- entry->scroll_offset);
-
- gtk_secure_entry_set_positions(entry, tmp_pos, -1);
- }
-
- return TRUE;
-}
-
-static void
-set_invisible_cursor(GdkWindow * window)
-{
- GdkBitmap *empty_bitmap;
- GdkCursor *cursor;
- GdkColor useless;
- char invisible_cursor_bits[] = { 0x0 };
-
- useless.red = useless.green = useless.blue = 0;
- useless.pixel = 0;
-
- empty_bitmap = gdk_bitmap_create_from_data(window,
- invisible_cursor_bits, 1,
- 1);
-
- cursor = gdk_cursor_new_from_pixmap(empty_bitmap,
- empty_bitmap,
- &useless, &useless, 0, 0);
-
- gdk_window_set_cursor(window, cursor);
-
- gdk_cursor_unref(cursor);
-
- g_object_unref(empty_bitmap);
-}
-
-static void
-gtk_secure_entry_obscure_mouse_cursor(GtkSecureEntry * entry)
-{
- if (entry->mouse_cursor_obscured)
- return;
-
- set_invisible_cursor(entry->text_area);
-
- entry->mouse_cursor_obscured = TRUE;
-}
-
-static gint
-gtk_secure_entry_key_press(GtkWidget * widget, GdkEventKey * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_secure_entry_pend_cursor_blink(entry);
-
- if (gtk_im_context_filter_keypress(entry->im_context, event)) {
- gtk_secure_entry_obscure_mouse_cursor(entry);
- entry->need_im_reset = TRUE;
- return TRUE;
- }
-
- if (GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event))
- /* Activate key bindings
- */
- return TRUE;
-
- return FALSE;
-}
-
-static gint
-gtk_secure_entry_key_release(GtkWidget * widget, GdkEventKey * event)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- if (gtk_im_context_filter_keypress(entry->im_context, event)) {
- entry->need_im_reset = TRUE;
- return TRUE;
- }
-
- return GTK_WIDGET_CLASS(parent_class)->key_release_event(widget,
- event);
-}
-
-static gint
-gtk_secure_entry_focus_in(GtkWidget * widget,
- GdkEventFocus * event G_GNUC_UNUSED)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_widget_queue_draw(widget);
-
- entry->need_im_reset = TRUE;
- gtk_im_context_focus_in(entry->im_context);
-
- g_signal_connect(gdk_keymap_get_for_display
- (gtk_widget_get_display(widget)), "direction_changed",
- G_CALLBACK(gtk_secure_entry_keymap_direction_changed),
- entry);
-
- gtk_secure_entry_check_cursor_blink(entry);
-
- return FALSE;
-}
-
-static gint
-gtk_secure_entry_focus_out(GtkWidget * widget,
- GdkEventFocus * event G_GNUC_UNUSED)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_widget_queue_draw(widget);
-
- entry->need_im_reset = TRUE;
- gtk_im_context_focus_out(entry->im_context);
-
- gtk_secure_entry_check_cursor_blink(entry);
-
- g_signal_handlers_disconnect_by_func(gdk_keymap_get_for_display
- (gtk_widget_get_display(widget)),
- gtk_secure_entry_keymap_direction_changed,
- entry);
-
- return FALSE;
-}
-
-static void
-gtk_secure_entry_grab_focus(GtkWidget * widget)
-{
- GtkWidget *tmp;
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- gboolean select_on_focus;
-
- gtk_widget_set_can_default (widget, TRUE);
- GTK_WIDGET_CLASS(parent_class)->grab_focus(widget);
-
- /* read current select on focus setting from GtkEntry */
- tmp = gtk_entry_new ();
- g_object_get(gtk_widget_get_settings(tmp),
- "gtk-entry-select-on-focus", &select_on_focus, NULL);
- gtk_widget_destroy (tmp);
-
- if (select_on_focus && !entry->in_click)
- gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
-}
-
-static void
-gtk_secure_entry_direction_changed(GtkWidget * widget,
- GtkTextDirection previous_dir)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
-
- gtk_secure_entry_recompute(entry);
-
- GTK_WIDGET_CLASS(parent_class)->direction_changed(widget,
- previous_dir);
-}
-
-static void
-gtk_secure_entry_state_changed(GtkWidget * widget,
- GtkStateType previous_state G_GNUC_UNUSED)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- GtkStyle *style;
-
- style = gtk_widget_get_style (widget);
- if (gtk_widget_get_realized (widget)) {
- gdk_window_set_background(gtk_widget_get_window(widget),
- &style->base[gtk_widget_get_state (widget)]);
- gdk_window_set_background(entry->text_area,
- &style->base[gtk_widget_get_state (widget)]);
- }
-
- if (!gtk_widget_is_sensitive (widget)) {
- /* Clear any selection */
- gtk_editable_select_region(GTK_EDITABLE(entry), entry->current_pos,
- entry->current_pos);
- }
-
- gtk_widget_queue_draw(widget);
-}
-
-static void
-gtk_secure_entry_screen_changed(GtkWidget * widget,
- GdkScreen * old_screen G_GNUC_UNUSED)
-{
- gtk_secure_entry_recompute(GTK_SECURE_ENTRY(widget));
-}
-
-/* GtkEditable method implementations
- */
-static void
-gtk_secure_entry_insert_text(GtkEditable * editable,
- const gchar * new_text,
- gint new_text_length, gint * position)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
- gchar *text;
-
- if (*position < 0 || *position > entry->text_length)
- *position = entry->text_length;
-
- g_object_ref(editable);
-
- WITH_SECURE_MEM(text = g_new(gchar, new_text_length + 1));
-
- text[new_text_length] = '\0';
- strncpy(text, new_text, new_text_length);
-
- g_signal_emit_by_name(editable, "insert_text", text, new_text_length,
- position);
-
- WITH_SECURE_MEM(g_free(text));
-
- g_object_unref(editable);
-}
-
-static void
-gtk_secure_entry_delete_text(GtkEditable * editable,
- gint start_pos, gint end_pos)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
-
- if (end_pos < 0 || end_pos > entry->text_length)
- end_pos = entry->text_length;
- if (start_pos < 0)
- start_pos = 0;
- if (start_pos > end_pos)
- start_pos = end_pos;
-
- g_object_ref(editable);
-
- g_signal_emit_by_name(editable, "delete_text", start_pos, end_pos);
-
- g_object_unref(editable);
-}
-
-static void
-gtk_secure_entry_set_position_internal(GtkSecureEntry * entry,
- gint position, gboolean reset_im)
-{
- if (position < 0 || position > entry->text_length)
- position = entry->text_length;
-
- if (position != entry->current_pos ||
- position != entry->selection_bound) {
- if (reset_im)
- gtk_secure_entry_reset_im_context(entry);
- gtk_secure_entry_set_positions(entry, position, position);
- }
-}
-
-static void
-gtk_secure_entry_real_set_position(GtkEditable * editable, gint position)
-{
- gtk_secure_entry_set_position_internal(GTK_SECURE_ENTRY(editable),
- position, TRUE);
-}
-
-static gint
-gtk_secure_entry_get_position(GtkEditable * editable)
-{
- return GTK_SECURE_ENTRY(editable)->current_pos;
-}
-
-static void
-gtk_secure_entry_set_selection_bounds(GtkEditable * editable,
- gint start, gint end)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
-
- if (start < 0)
- start = entry->text_length;
- if (end < 0)
- end = entry->text_length;
-
- gtk_secure_entry_reset_im_context(entry);
-
- gtk_secure_entry_set_positions(entry,
- MIN(end, entry->text_length),
- MIN(start, entry->text_length));
-}
-
-static gboolean
-gtk_secure_entry_get_selection_bounds(GtkEditable * editable,
- gint * start, gint * end)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
-
- *start = entry->selection_bound;
- *end = entry->current_pos;
-
- return (entry->selection_bound != entry->current_pos);
-}
-
-static void
-gtk_secure_entry_style_set(GtkWidget * widget, GtkStyle * previous_style)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(widget);
- GtkStyle *style;
-
- gtk_secure_entry_recompute(entry);
-
- style = gtk_widget_get_style (widget);
- if (previous_style && gtk_widget_get_realized (widget)) {
- gdk_window_set_background(gtk_widget_get_window (widget),
- &style->base[gtk_widget_get_state (widget)]);
- gdk_window_set_background(entry->text_area,
- &style->base[gtk_widget_get_state (widget)]);
- }
-}
-
-/* GtkCellEditable method implementations
- */
-static void
-gtk_cell_editable_secure_entry_activated(GtkSecureEntry * entry,
- gpointer data G_GNUC_UNUSED)
-{
- gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry));
- gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry));
-}
-
-static gboolean
-gtk_cell_editable_key_press_event(GtkSecureEntry * entry,
- GdkEventKey * key_event,
- gpointer data G_GNUC_UNUSED)
-{
- if (key_event->keyval == GDK_Escape) {
- entry->editing_canceled = TRUE;
- gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry));
- gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry));
-
- return TRUE;
- }
-
- /* override focus */
- if (key_event->keyval == GDK_Up || key_event->keyval == GDK_Down) {
- gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry));
- gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry));
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-gtk_secure_entry_start_editing(GtkCellEditable * cell_editable,
- GdkEvent * event G_GNUC_UNUSED)
-{
- GTK_SECURE_ENTRY(cell_editable)->is_cell_renderer = TRUE;
-
- g_signal_connect(cell_editable, "activate",
- G_CALLBACK(gtk_cell_editable_secure_entry_activated), NULL);
- g_signal_connect(cell_editable, "key_press_event",
- G_CALLBACK(gtk_cell_editable_key_press_event), NULL);
-}
-
-/* Default signal handlers
- */
-static void
-gtk_secure_entry_real_insert_text(GtkEditable * editable,
- const gchar * new_text,
- gint new_text_length, gint * position)
-{
- gint _index;
- gint n_chars;
-
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
-
- if (new_text_length < 0)
- new_text_length = strlen(new_text);
-
- n_chars = g_utf8_strlen(new_text, new_text_length);
- 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)));
- n_chars = entry->text_max_length - entry->text_length;
- new_text_length =
- g_utf8_offset_to_pointer(new_text, n_chars) - new_text;
- }
-
- if (new_text_length + entry->n_bytes + 1 > entry->text_size) {
- while (new_text_length + entry->n_bytes + 1 > entry->text_size) {
- if (entry->text_size == 0)
- entry->text_size = MIN_SIZE;
- else {
- if (2 * (guint) entry->text_size < MAX_SIZE &&
- 2 * (guint) entry->text_size > entry->text_size)
- entry->text_size *= 2;
- else {
- entry->text_size = MAX_SIZE;
- if (new_text_length >
- (gint) entry->text_size - (gint) entry->n_bytes -
- 1) {
- new_text_length =
- (gint) entry->text_size -
- (gint) entry->n_bytes - 1;
- new_text_length =
- g_utf8_find_prev_char(new_text,
- new_text +
- new_text_length + 1) -
- new_text;
- n_chars = g_utf8_strlen(new_text, new_text_length);
- }
- break;
- }
- }
- }
-
- WITH_SECURE_MEM(entry->text =
- g_realloc(entry->text, entry->text_size));
- }
-
- _index = g_utf8_offset_to_pointer(entry->text, *position) - entry->text;
-
- g_memmove(entry->text + _index + new_text_length, entry->text + _index,
- entry->n_bytes - _index);
- memcpy(entry->text + _index, new_text, new_text_length);
-
- entry->n_bytes += new_text_length;
- entry->text_length += n_chars;
-
- /* NUL terminate for safety and convenience */
- entry->text[entry->n_bytes] = '\0';
-
- if (entry->current_pos > *position)
- entry->current_pos += n_chars;
-
- if (entry->selection_bound > *position)
- entry->selection_bound += n_chars;
-
- *position += n_chars;
-
- gtk_secure_entry_recompute(entry);
-
- g_signal_emit_by_name(editable, "changed");
- g_object_notify(G_OBJECT(editable), "text");
-}
-
-static void
-gtk_secure_entry_real_delete_text(GtkEditable * editable,
- gint start_pos, gint end_pos)
-{
- GtkSecureEntry *entry = GTK_SECURE_ENTRY(editable);
-
- if (start_pos < 0)
- start_pos = 0;
- if (end_pos < 0 || end_pos > entry->text_length)
- end_pos = entry->text_length;
-
- if (start_pos < end_pos) {
- gint start_index =
- g_utf8_offset_to_pointer(entry->text, start_pos) - entry->text;
- gint end_index =
- g_utf8_offset_to_pointer(entry->text, end_pos) - entry->text;
- gint current_pos;
- gint selection_bound;
-
- g_memmove(entry->text + start_index, entry->text + end_index,
- entry->n_bytes + 1 - end_index);
- entry->text_length -= (end_pos - start_pos);
- entry->n_bytes -= (end_index - start_index);
-
- current_pos = entry->current_pos;
- if (current_pos > start_pos)
- current_pos -= MIN(current_pos, end_pos) - start_pos;
-
- selection_bound = entry->selection_bound;
- if (selection_bound > start_pos)
- selection_bound -= MIN(selection_bound, end_pos) - start_pos;
-
- gtk_secure_entry_set_positions(entry, current_pos,
- selection_bound);
-
- gtk_secure_entry_recompute(entry);
-
- g_signal_emit_by_name(editable, "changed");
- g_object_notify(G_OBJECT(editable), "text");
- }
-}
-
-/* Compute the X position for an offset that corresponds to the "more important
- * cursor position for that offset. We use this when trying to guess to which
- * end of the selection we should go to when the user hits the left or
- * right arrow key.
- */
-static gint
-get_better_cursor_x(GtkSecureEntry * entry, gint offset)
-{
- GdkKeymap *keymap =
- gdk_keymap_get_for_display(gtk_widget_get_display
- (GTK_WIDGET(entry)));
- PangoDirection keymap_direction = gdk_keymap_get_direction(keymap);
- gboolean split_cursor;
-
- PangoLayout *layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- const gchar *text = pango_layout_get_text(layout);
- gint _index = g_utf8_offset_to_pointer(text, offset) - text;
-
- PangoRectangle strong_pos, weak_pos;
-
- g_object_get(gtk_widget_get_settings(GTK_WIDGET(entry)),
- "gtk-split-cursor", &split_cursor, NULL);
-
- pango_layout_get_cursor_pos(layout, _index, &strong_pos, &weak_pos);
-
- if (split_cursor)
- return strong_pos.x / PANGO_SCALE;
- else
- return (keymap_direction ==
- entry->resolved_dir) ? strong_pos.x /
- PANGO_SCALE : weak_pos.x / PANGO_SCALE;
-}
-
-static void
-gtk_secure_entry_move_cursor(GtkSecureEntry * entry,
- GtkMovementStep step,
- gint count, gboolean extend_selection)
-{
- gint new_pos = entry->current_pos;
-
- gtk_secure_entry_reset_im_context(entry);
-
- if (entry->current_pos != entry->selection_bound && !extend_selection) {
- /* If we have a current selection and aren't extending it, move to the
- * start/or end of the selection as appropriate
- */
- switch (step) {
- case GTK_MOVEMENT_VISUAL_POSITIONS:
- {
- gint current_x =
- get_better_cursor_x(entry, entry->current_pos);
- gint bound_x =
- get_better_cursor_x(entry, entry->selection_bound);
-
- if (count < 0)
- new_pos =
- current_x <
- bound_x ? entry->current_pos : entry->
- selection_bound;
- else
- new_pos =
- current_x >
- bound_x ? entry->current_pos : entry->
- selection_bound;
-
- break;
- }
- case GTK_MOVEMENT_LOGICAL_POSITIONS:
- case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
- case GTK_MOVEMENT_PARAGRAPH_ENDS:
- case GTK_MOVEMENT_BUFFER_ENDS:
- new_pos = count < 0 ? 0 : entry->text_length;
- break;
- case GTK_MOVEMENT_WORDS:
- case GTK_MOVEMENT_DISPLAY_LINES:
- case GTK_MOVEMENT_PARAGRAPHS:
- case GTK_MOVEMENT_PAGES:
- case GTK_MOVEMENT_HORIZONTAL_PAGES:
- break;
- }
- } else {
- switch (step) {
- case GTK_MOVEMENT_LOGICAL_POSITIONS:
- new_pos =
- gtk_secure_entry_move_logically(entry, new_pos, count);
- break;
- case GTK_MOVEMENT_VISUAL_POSITIONS:
- new_pos =
- gtk_secure_entry_move_visually(entry, new_pos, count);
- break;
- case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
- case GTK_MOVEMENT_PARAGRAPH_ENDS:
- case GTK_MOVEMENT_BUFFER_ENDS:
- new_pos = count < 0 ? 0 : entry->text_length;
- break;
- case GTK_MOVEMENT_WORDS:
- case GTK_MOVEMENT_DISPLAY_LINES:
- case GTK_MOVEMENT_PARAGRAPHS:
- case GTK_MOVEMENT_PAGES:
- case GTK_MOVEMENT_HORIZONTAL_PAGES:
- break;
- }
- }
-
- if (extend_selection)
- gtk_editable_select_region(GTK_EDITABLE(entry),
- entry->selection_bound, new_pos);
- else
- gtk_editable_set_position(GTK_EDITABLE(entry), new_pos);
-
- gtk_secure_entry_pend_cursor_blink(entry);
-}
-
-static void
-gtk_secure_entry_insert_at_cursor(GtkSecureEntry * entry,
- const gchar * str)
-{
- GtkEditable *editable = GTK_EDITABLE(entry);
- gint pos = entry->current_pos;
-
- gtk_secure_entry_reset_im_context(entry);
-
- gtk_editable_insert_text(editable, str, -1, &pos);
- gtk_editable_set_position(editable, pos);
-}
-
-static void
-gtk_secure_entry_delete_from_cursor(GtkSecureEntry * entry,
- GtkDeleteType type, gint count)
-{
- GtkEditable *editable = GTK_EDITABLE(entry);
- gint start_pos = entry->current_pos;
- gint end_pos = entry->current_pos;
-
- gtk_secure_entry_reset_im_context(entry);
-
- if (entry->selection_bound != entry->current_pos) {
- gtk_editable_delete_selection(editable);
- return;
- }
-
- switch (type) {
- case GTK_DELETE_CHARS:
- end_pos =
- gtk_secure_entry_move_logically(entry, entry->current_pos,
- count);
- gtk_editable_delete_text(editable, MIN(start_pos, end_pos),
- MAX(start_pos, end_pos));
- break;
- case GTK_DELETE_DISPLAY_LINE_ENDS:
- case GTK_DELETE_PARAGRAPH_ENDS:
- if (count < 0)
- gtk_editable_delete_text(editable, 0, entry->current_pos);
- else
- gtk_editable_delete_text(editable, entry->current_pos, -1);
- break;
- case GTK_DELETE_DISPLAY_LINES:
- case GTK_DELETE_PARAGRAPHS:
- gtk_editable_delete_text(editable, 0, -1);
- break;
- default:
- break;
- }
-
- gtk_secure_entry_pend_cursor_blink(entry);
-}
-
-static void
-gtk_secure_entry_real_activate(GtkSecureEntry * entry)
-{
- GtkWindow *window;
- GtkWidget *toplevel;
- GtkWidget *widget;
-
- widget = GTK_WIDGET(entry);
-
- if (entry->activates_default) {
- toplevel = gtk_widget_get_toplevel(widget);
- if (GTK_IS_WINDOW(toplevel)) {
- GtkWidget *default_widget;
-
- window = GTK_WINDOW(toplevel);
- if (window)
- default_widget = gtk_window_get_default_widget (window);
- else
- return;
-
- if (widget != default_widget &&
- !(widget == gtk_window_get_focus (window) &&
- (!default_widget
- || !gtk_widget_get_sensitive (default_widget))))
- gtk_window_activate_default(window);
- }
- }
-}
-
-static void
-gtk_secure_entry_keymap_direction_changed(GdkKeymap * keymap G_GNUC_UNUSED,
- GtkSecureEntry * entry)
-{
- gtk_secure_entry_recompute(entry);
-}
-
-/* IM Context Callbacks
- */
-
-static void
-gtk_secure_entry_commit_cb(GtkIMContext * context G_GNUC_UNUSED,
- const gchar * str, GtkSecureEntry * entry)
-{
- gtk_secure_entry_enter_text(entry, str);
-}
-
-static void
-gtk_secure_entry_preedit_changed_cb(GtkIMContext * context G_GNUC_UNUSED,
- GtkSecureEntry * entry)
-{
- gchar *preedit_string;
- gint cursor_pos;
-
- gtk_im_context_get_preedit_string(entry->im_context,
- &preedit_string, NULL, &cursor_pos);
- entry->preedit_length = strlen(preedit_string);
- cursor_pos = CLAMP(cursor_pos, 0, g_utf8_strlen(preedit_string, -1));
- entry->preedit_cursor = cursor_pos;
- g_free(preedit_string);
-
- gtk_secure_entry_recompute(entry);
-}
-
-static gboolean
-gtk_secure_entry_retrieve_surrounding_cb(GtkIMContext * context,
- GtkSecureEntry * entry)
-{
- gtk_im_context_set_surrounding(context,
- entry->text,
- entry->n_bytes,
- g_utf8_offset_to_pointer(entry->text,
- entry->
- current_pos) -
- entry->text);
-
- return TRUE;
-}
-
-static gboolean
-gtk_secure_entry_delete_surrounding_cb(GtkIMContext * slave G_GNUC_UNUSED,
- gint offset,
- gint n_chars,
- GtkSecureEntry * entry)
-{
- gtk_editable_delete_text(GTK_EDITABLE(entry),
- entry->current_pos + offset,
- entry->current_pos + offset + n_chars);
-
- return TRUE;
-}
-
-/* Internal functions
- */
-
-/* Used for im_commit_cb and inserting Unicode chars */
-static void
-gtk_secure_entry_enter_text(GtkSecureEntry * entry, const gchar * str)
-{
- GtkEditable *editable = GTK_EDITABLE(entry);
- gint tmp_pos;
-
- if (gtk_editable_get_selection_bounds(editable, NULL, NULL))
- gtk_editable_delete_selection(editable);
- else {
- if (entry->overwrite_mode)
- gtk_secure_entry_delete_from_cursor(entry, GTK_DELETE_CHARS,
- 1);
- }
-
- tmp_pos = entry->current_pos;
- gtk_editable_insert_text(editable, str, strlen(str), &tmp_pos);
- gtk_secure_entry_set_position_internal(entry, tmp_pos, FALSE);
-}
-
-/* All changes to entry->current_pos and entry->selection_bound
- * should go through this function.
- */
-static void
-gtk_secure_entry_set_positions(GtkSecureEntry * entry,
- gint current_pos, gint selection_bound)
-{
- gboolean changed = FALSE;
-
- g_object_freeze_notify(G_OBJECT(entry));
-
- if (current_pos != -1 && entry->current_pos != current_pos) {
- entry->current_pos = current_pos;
- changed = TRUE;
-
- g_object_notify(G_OBJECT(entry), "cursor_position");
- }
-
- if (selection_bound != -1 && entry->selection_bound != selection_bound) {
- entry->selection_bound = selection_bound;
- changed = TRUE;
-
- g_object_notify(G_OBJECT(entry), "selection_bound");
- }
-
- g_object_thaw_notify(G_OBJECT(entry));
-
- if (changed)
- gtk_secure_entry_recompute(entry);
-}
-
-static void
-gtk_secure_entry_reset_layout(GtkSecureEntry * entry)
-{
- if (entry->cached_layout) {
- g_object_unref(entry->cached_layout);
- entry->cached_layout = NULL;
- }
-}
-
-static void
-update_im_cursor_location(GtkSecureEntry * entry)
-{
- GdkRectangle area;
- gint strong_x;
- gint strong_xoffset;
- gint area_width, area_height;
-
- gtk_secure_entry_get_cursor_locations(entry, &strong_x, NULL);
- get_text_area_size(entry, NULL, NULL, &area_width, &area_height);
-
- strong_xoffset = strong_x - entry->scroll_offset;
- if (strong_xoffset < 0) {
- strong_xoffset = 0;
- } else if (strong_xoffset > area_width) {
- strong_xoffset = area_width;
- }
- area.x = strong_xoffset;
- area.y = 0;
- area.width = 0;
- area.height = area_height;
-
- gtk_im_context_set_cursor_location(entry->im_context, &area);
-}
-
-static gboolean
-recompute_idle_func(gpointer data)
-{
- GtkSecureEntry *entry;
-
- GDK_THREADS_ENTER();
-
- entry = GTK_SECURE_ENTRY(data);
-
- entry->recompute_idle = 0;
-
- if (gtk_widget_has_screen(GTK_WIDGET(entry))) {
- gtk_secure_entry_adjust_scroll(entry);
- gtk_secure_entry_queue_draw(entry);
-
- update_im_cursor_location(entry);
- }
-
- GDK_THREADS_LEAVE();
-
- return FALSE;
-}
-
-static void
-gtk_secure_entry_recompute(GtkSecureEntry * entry)
-{
- gtk_secure_entry_reset_layout(entry);
- gtk_secure_entry_check_cursor_blink(entry);
-
- if (!entry->recompute_idle) {
- entry->recompute_idle = g_idle_add_full(G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */
- recompute_idle_func, entry,
- NULL);
- }
-}
-
-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_secure_entry_create_layout(GtkSecureEntry * entry,
- gboolean include_preedit)
-{
- GtkWidget *widget = GTK_WIDGET(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;
-
- pango_layout_set_single_paragraph_mode(layout, TRUE);
-
- if (include_preedit) {
- gtk_im_context_get_preedit_string(entry->im_context,
- &preedit_string, &preedit_attrs,
- NULL);
- preedit_length = entry->preedit_length;
- }
-
- if (preedit_length) {
- GString *tmp_string = g_string_new(NULL);
-
- gint cursor_index = g_utf8_offset_to_pointer(entry->text,
- entry->current_pos) -
- entry->text;
-
- 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, preedit_length);
-
- g_string_free(tmp_string, TRUE);
- } else {
- PangoDirection pango_dir;
-
- pango_dir = pango_find_base_dir(entry->text, entry->n_bytes);
- if (pango_dir == PANGO_DIRECTION_NEUTRAL) {
- if (gtk_widget_has_focus (widget)) {
- GdkDisplay *display = gtk_widget_get_display(widget);
- GdkKeymap *keymap = gdk_keymap_get_for_display(display);
- pango_dir = gdk_keymap_get_direction(keymap);
- } else {
- if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_LTR)
- pango_dir = PANGO_DIRECTION_LTR;
- else
- pango_dir = PANGO_DIRECTION_RTL;
- }
- }
-
- pango_context_set_base_dir(gtk_widget_get_pango_context(widget),
- pango_dir);
-
- pango_layout_set_alignment(layout, pango_dir);
-
- entry->resolved_dir = pango_dir;
-
- {
- 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)
- g_free(preedit_string);
- if (preedit_attrs)
- pango_attr_list_unref(preedit_attrs);
-
- pango_attr_list_unref(tmp_attrs);
-
- return layout;
-}
-
-static PangoLayout *
-gtk_secure_entry_ensure_layout(GtkSecureEntry * entry,
- gboolean include_preedit)
-{
- if (entry->preedit_length > 0 &&
- !include_preedit != !entry->cache_includes_preedit)
- gtk_secure_entry_reset_layout(entry);
-
- if (!entry->cached_layout) {
- entry->cached_layout =
- gtk_secure_entry_create_layout(entry, include_preedit);
- entry->cache_includes_preedit = include_preedit;
- }
-
- return entry->cached_layout;
-}
-
-static void
-get_layout_position(GtkSecureEntry * entry, gint * x, gint * y)
-{
- PangoLayout *layout;
- PangoRectangle logical_rect;
- gint area_width, area_height;
- gint y_pos;
- PangoLayoutLine *line;
-
- layout = gtk_secure_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);
-
- line = pango_layout_get_lines(layout)->data;
- pango_layout_line_get_extents(line, NULL, &logical_rect);
-
- /* Align primarily for locale's ascent/descent */
- y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
- entry->ascent + logical_rect.y);
-
- /* Now see if we need to adjust to fit in actual drawn string */
- if (logical_rect.height > area_height)
- y_pos = (area_height - logical_rect.height) / 2;
- else if (y_pos < 0)
- y_pos = 0;
- else if (y_pos + logical_rect.height > area_height)
- y_pos = area_height - logical_rect.height;
-
- y_pos = INNER_BORDER + y_pos / PANGO_SCALE;
-
- if (x)
- *x = INNER_BORDER - entry->scroll_offset;
-
- if (y)
- *y = y_pos;
-}
-
-static void
-gtk_secure_entry_draw_text(GtkSecureEntry * entry)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
- PangoLayoutLine *line;
- GtkStyle *style;
-
- if (entry->invisible_char == 0)
- return;
-
- if (gtk_widget_is_drawable (widget)) {
- PangoLayout *layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- gint x, y;
- gint start_pos, end_pos;
-
- get_layout_position(entry, &x, &y);
-
- style = gtk_widget_get_style (widget);
- gdk_draw_layout(entry->text_area,
- style->text_gc[gtk_widget_get_state (widget)],
- x, y, layout);
-
- if (gtk_editable_get_selection_bounds
- (GTK_EDITABLE(entry), &start_pos, &end_pos)) {
- gint *ranges;
- gint n_ranges, i;
- PangoRectangle logical_rect;
- const gchar *text = pango_layout_get_text(layout);
- gint start_index =
- g_utf8_offset_to_pointer(text, start_pos) - text;
- gint end_index =
- g_utf8_offset_to_pointer(text, end_pos) - text;
-#if GTK_CHECK_VERSION(2, 90, 5)
- cairo_region_t *clip_region = cairo_region_create();
-#else
- GdkRegion *clip_region = gdk_region_new();
-#endif
- GdkGC *text_gc;
- GdkGC *selection_gc;
-
- line = pango_layout_get_lines(layout)->data;
-
- pango_layout_line_get_x_ranges(line, start_index, end_index,
- &ranges, &n_ranges);
-
- pango_layout_get_extents(layout, NULL, &logical_rect);
-
- if (gtk_widget_has_focus (widget)) {
- selection_gc = style->base_gc[GTK_STATE_SELECTED];
- text_gc = style->text_gc[GTK_STATE_SELECTED];
- } else {
- selection_gc = style->base_gc[GTK_STATE_ACTIVE];
- text_gc = style->text_gc[GTK_STATE_ACTIVE];
- }
-
- for (i = 0; i < n_ranges; i++) {
- GdkRectangle rect;
-
- rect.x =
- INNER_BORDER - entry->scroll_offset +
- ranges[2 * i] / PANGO_SCALE;
- rect.y = y;
- rect.width =
- (ranges[2 * i + 1] - ranges[2 * i]) / PANGO_SCALE;
- rect.height = logical_rect.height / PANGO_SCALE;
-
- gdk_draw_rectangle(entry->text_area, selection_gc, TRUE,
- rect.x, rect.y, rect.width,
- rect.height);
-#if GTK_CHECK_VERSION(2, 90, 5)
- cairo_region_union_rectangle (clip_region, &rect);
-#else
- gdk_region_union_with_rect(clip_region, &rect);
-#endif
- }
-
- gdk_gc_set_clip_region(text_gc, clip_region);
- gdk_draw_layout(entry->text_area, text_gc, x, y, layout);
- gdk_gc_set_clip_region(text_gc, NULL);
-
-#if GTK_CHECK_VERSION(2, 90, 5)
- cairo_region_destroy(clip_region);
-#else
- gdk_region_destroy(clip_region);
-#endif
- g_free(ranges);
- }
- }
-}
-
-static void
-draw_insertion_cursor(GtkSecureEntry * entry,
- GdkRectangle * cursor_location,
- gboolean is_primary,
- PangoDirection direction, gboolean draw_arrow)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
- GtkTextDirection text_dir;
-
- if (direction == PANGO_DIRECTION_LTR)
- text_dir = GTK_TEXT_DIR_LTR;
- else
- text_dir = GTK_TEXT_DIR_RTL;
-
- gtk_draw_insertion_cursor(widget, entry->text_area, NULL,
- cursor_location,
- is_primary, text_dir, draw_arrow);
-}
-
-static void
-gtk_secure_entry_draw_cursor(GtkSecureEntry * entry)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
- GdkKeymap *keymap =
- gdk_keymap_get_for_display(gtk_widget_get_display
- (widget));
- PangoDirection keymap_direction = gdk_keymap_get_direction(keymap);
-
- if (gtk_widget_is_drawable (widget)) {
- GdkRectangle cursor_location;
- gboolean split_cursor;
-
- gint xoffset = INNER_BORDER - entry->scroll_offset;
- gint strong_x, weak_x;
- gint text_area_height;
- PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
- PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
- gint x1 = 0;
- gint x2 = 0;
-
- gdk_drawable_get_size(entry->text_area, NULL, &text_area_height);
-
- gtk_secure_entry_get_cursor_locations(entry, &strong_x, &weak_x);
-
- g_object_get(gtk_widget_get_settings(widget),
- "gtk-split-cursor", &split_cursor, NULL);
-
- dir1 = entry->resolved_dir;
-
- if (split_cursor) {
- x1 = strong_x;
-
- if (weak_x != strong_x) {
- dir2 =
- (entry->resolved_dir ==
- PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL :
- PANGO_DIRECTION_LTR;
- x2 = weak_x;
- }
- } else {
- if (keymap_direction == entry->resolved_dir)
- x1 = strong_x;
- else
- x1 = weak_x;
- }
-
- cursor_location.x = xoffset + x1;
- cursor_location.y = INNER_BORDER;
- cursor_location.width = 0;
- cursor_location.height = text_area_height - 2 * INNER_BORDER;
-
- draw_insertion_cursor(entry,
- &cursor_location, TRUE, dir1,
- dir2 != PANGO_DIRECTION_NEUTRAL);
-
- if (dir2 != PANGO_DIRECTION_NEUTRAL) {
- cursor_location.x = xoffset + x2;
- draw_insertion_cursor(entry,
- &cursor_location, FALSE, dir2, TRUE);
- }
- }
-}
-
-static void
-gtk_secure_entry_queue_draw(GtkSecureEntry * entry)
-{
- if (gtk_widget_get_realized (GTK_WIDGET(entry)))
- gdk_window_invalidate_rect(entry->text_area, NULL, FALSE);
-}
-
-static void
-gtk_secure_entry_reset_im_context(GtkSecureEntry * entry)
-{
- if (entry->need_im_reset) {
- entry->need_im_reset = 0;
- gtk_im_context_reset(entry->im_context);
- }
-}
-
-static gint
-gtk_secure_entry_find_position(GtkSecureEntry * entry, gint x)
-{
- PangoLayout *layout;
- PangoLayoutLine *line;
- gint _index;
- gint pos;
- gboolean trailing;
- const gchar *text;
- gint cursor_index;
-
- layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- text = pango_layout_get_text(layout);
- cursor_index =
- g_utf8_offset_to_pointer(text, entry->current_pos) - text;
-
- line = pango_layout_get_lines(layout)->data;
- pango_layout_line_x_to_index(line, x * PANGO_SCALE, &_index, &trailing);
-
- if (_index >= cursor_index && entry->preedit_length) {
- if (_index >= cursor_index + entry->preedit_length)
- _index -= entry->preedit_length;
- else {
- _index = cursor_index;
- trailing = 0;
- }
- }
-
- pos = g_utf8_pointer_to_offset(text, text + _index);
- pos += trailing;
-
- return pos;
-}
-
-static void
-gtk_secure_entry_get_cursor_locations(GtkSecureEntry * entry,
- gint * strong_x, gint * weak_x)
-{
- if (!entry->invisible_char) {
- if (strong_x)
- *strong_x = 0;
-
- if (weak_x)
- *weak_x = 0;
- } else {
- PangoLayout *layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- const gchar *text = pango_layout_get_text(layout);
- PangoRectangle strong_pos, weak_pos;
- gint _index;
-
- _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);
-
- if (strong_x)
- *strong_x = strong_pos.x / PANGO_SCALE;
-
- if (weak_x)
- *weak_x = weak_pos.x / PANGO_SCALE;
- }
-}
-
-static void
-gtk_secure_entry_adjust_scroll(GtkSecureEntry * entry)
-{
- gint min_offset, max_offset;
- gint text_area_width, text_width;
- gint strong_x, weak_x;
- gint strong_xoffset, weak_xoffset;
- PangoLayout *layout;
- PangoLayoutLine *line;
- PangoRectangle logical_rect;
-
- if (!gtk_widget_get_realized (GTK_WIDGET(entry)))
- return;
-
- gdk_drawable_get_size(entry->text_area, &text_area_width, NULL);
- text_area_width -= 2 * INNER_BORDER;
-
- layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- line = pango_layout_get_lines(layout)->data;
-
- pango_layout_line_get_extents(line, NULL, &logical_rect);
-
- /* Display as much text as we can */
-
- text_width = PANGO_PIXELS(logical_rect.width);
-
- if (text_width > text_area_width) {
- min_offset = 0;
- max_offset = text_width - text_area_width;
- } else {
- min_offset = 0;
- max_offset = min_offset;
- }
-
- 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
- * 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 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
- * small-screen-real-estate display.
- *
- * We always make sure that the strong cursor is on screen, and
- * put the weak cursor on screen if possible.
- */
-
- gtk_secure_entry_get_cursor_locations(entry, &strong_x, &weak_x);
-
- strong_xoffset = strong_x - entry->scroll_offset;
-
- if (strong_xoffset < 0) {
- entry->scroll_offset += strong_xoffset;
- strong_xoffset = 0;
- } else if (strong_xoffset > text_area_width) {
- entry->scroll_offset += strong_xoffset - text_area_width;
- strong_xoffset = text_area_width;
- }
-
- weak_xoffset = weak_x - entry->scroll_offset;
-
- if (weak_xoffset < 0
- && strong_xoffset - weak_xoffset <= text_area_width) {
- entry->scroll_offset += weak_xoffset;
- } else if (weak_xoffset > text_area_width &&
- strong_xoffset - (weak_xoffset - text_area_width) >= 0) {
- entry->scroll_offset += weak_xoffset - text_area_width;
- }
-
- g_object_notify(G_OBJECT(entry), "scroll_offset");
-}
-
-static gint
-gtk_secure_entry_move_visually(GtkSecureEntry * entry,
- gint start, gint count)
-{
- gint _index;
- PangoLayout *layout = gtk_secure_entry_ensure_layout(entry, FALSE);
- const gchar *text;
-
- text = pango_layout_get_text(layout);
-
- _index = g_utf8_offset_to_pointer(text, start) - text;
-
- while (count != 0) {
- int new_index, new_trailing;
- gboolean split_cursor;
- gboolean strong;
-
- g_object_get(gtk_widget_get_settings(GTK_WIDGET(entry)),
- "gtk-split-cursor", &split_cursor, NULL);
-
- if (split_cursor)
- strong = TRUE;
- else {
- GdkKeymap *keymap =
- gdk_keymap_get_for_display(gtk_widget_get_display
- (GTK_WIDGET(entry)));
- PangoDirection keymap_direction =
- gdk_keymap_get_direction(keymap);
-
- strong = keymap_direction == entry->resolved_dir;
- }
-
- if (count > 0) {
- pango_layout_move_cursor_visually(layout, strong, _index, 0, 1,
- &new_index, &new_trailing);
- count--;
- } else {
- pango_layout_move_cursor_visually(layout, strong, _index, 0, -1,
- &new_index, &new_trailing);
- count++;
- }
-
- if (new_index < 0 || new_index == G_MAXINT)
- break;
-
- _index = new_index;
-
- while (new_trailing--)
- _index = g_utf8_next_char(text + new_index) - text;
- }
-
- return g_utf8_pointer_to_offset(text, text + _index);
-}
-
-static gint
-gtk_secure_entry_move_logically(GtkSecureEntry * entry,
- gint start, gint count)
-{
- gint new_pos = start;
-
- /* Prevent any leak of information */
- new_pos = CLAMP(start + count, 0, entry->text_length);
-
- return new_pos;
-}
-
-/* Public API
- */
-
-GtkWidget *
-gtk_secure_entry_new(void)
-{
- return g_object_new(GTK_TYPE_SECURE_ENTRY, NULL);
-}
-
-/**
- * gtk_secure_entry_new_with_max_length:
- * @max: the maximum length of the entry, or 0 for no maximum.
- * (other than the maximum length of entries.) The value passed in will
- * be clamped to the range 0-65536.
- *
- * Creates a new #GtkSecureEntry widget with the given maximum length.
- *
- * Note: the existence of this function is inconsistent
- * with the rest of the GTK+ API. The normal setup would
- * be to just require the user to make an extra call
- * to gtk_secure_entry_set_max_length() instead. It is not
- * expected that this function will be removed, but
- * it would be better practice not to use it.
- *
- * Return value: a new #GtkSecureEntry.
- **/
-GtkWidget *
-gtk_secure_entry_new_with_max_length(gint max)
-{
- GtkSecureEntry *entry;
-
- max = CLAMP(max, 0, MAX_SIZE);
-
- entry = g_object_new(GTK_TYPE_SECURE_ENTRY, NULL);
- entry->text_max_length = max;
-
- return GTK_WIDGET(entry);
-}
-
-void
-gtk_secure_entry_set_text(GtkSecureEntry * entry, const gchar * text)
-{
- gint tmp_pos;
-
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
- g_return_if_fail(text != NULL);
-
- /* Actually setting the text will affect the cursor and selection;
- * if the contents don't actually change, this will look odd to the user.
- */
- if (strcmp(entry->text, text) == 0)
- return;
-
- gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1);
-
- tmp_pos = 0;
- gtk_editable_insert_text(GTK_EDITABLE(entry), text, strlen(text),
- &tmp_pos);
-}
-
-/**
- * gtk_secure_entry_set_invisible_char:
- * @entry: a #GtkSecureEntry
- * @ch: a Unicode character
- *
- * Sets the character to use in place of the actual text when
- * gtk_secure_entry_set_visibility() has been called to set text visibility
- * to %FALSE. i.e. this is the character used in "password mode" to
- * show the user how many characters have been typed. The default
- * invisible char is an asterisk ('*'). If you set the invisible char
- * to 0, then the user will get no feedback at all; there will be
- * no text on the screen as they type.
- *
- **/
-void
-gtk_secure_entry_set_invisible_char(GtkSecureEntry * entry, gunichar ch)
-{
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
-
- if (ch == entry->invisible_char)
- return;
-
- entry->invisible_char = ch;
- g_object_notify(G_OBJECT(entry), "invisible_char");
- gtk_secure_entry_recompute(entry);
-}
-
-/**
- * gtk_secure_entry_get_invisible_char:
- * @entry: a #GtkSecureEntry
- *
- * Retrieves the character displayed in place of the real characters
- * for entries with visisbility set to false. See gtk_secure_entry_set_invisible_char().
- *
- * Return value: the current invisible char, or 0, if the entry does not
- * show invisible text at all.
- **/
-gunichar
-gtk_secure_entry_get_invisible_char(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), 0);
-
- return entry->invisible_char;
-}
-
-/**
- * gtk_secure_entry_get_text:
- * @entry: a #GtkSecureEntry
- *
- * Retrieves the contents of the entry widget.
- * See also gtk_editable_get_chars().
- *
- * Return value: a pointer to the contents of the widget as a
- * string. This string points to internally allocated
- * storage in the widget and must not be freed, modified or
- * stored.
- **/
-G_CONST_RETURN gchar *
-gtk_secure_entry_get_text(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), NULL);
-
- return entry->text;
-}
-
-/**
- * gtk_secure_entry_set_max_length:
- * @entry: a #GtkSecureEntry.
- * @max: the maximum length of the entry, or 0 for no maximum.
- * (other than the maximum length of entries.) The value passed in will
- * be clamped to the range 0-65536.
- *
- * Sets the maximum allowed length of the contents of the widget. If
- * the current contents are longer than the given length, then they
- * will be truncated to fit.
- **/
-void
-gtk_secure_entry_set_max_length(GtkSecureEntry * entry, gint max)
-{
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
-
- max = CLAMP(max, 0, MAX_SIZE);
-
- if (max > 0 && entry->text_length > max)
- gtk_editable_delete_text(GTK_EDITABLE(entry), max, -1);
-
- entry->text_max_length = max;
- g_object_notify(G_OBJECT(entry), "max_length");
-}
-
-/**
- * gtk_secure_entry_get_max_length:
- * @entry: a #GtkSecureEntry
- *
- * Retrieves the maximum allowed length of the text in
- * @entry. See gtk_secure_entry_set_max_length().
- *
- * Return value: the maximum allowed number of characters
- * in #GtkSecureEntry, or 0 if there is no maximum.
- **/
-gint
-gtk_secure_entry_get_max_length(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), 0);
-
- return entry->text_max_length;
-}
-
-/**
- * gtk_secure_entry_set_activates_default:
- * @entry: a #GtkSecureEntry
- * @setting: %TRUE to activate window's default widget on Enter keypress
- *
- * If @setting is %TRUE, pressing Enter in the @entry will activate the default
- * widget for the window containing the entry. This usually means that
- * the dialog box containing the entry will be closed, since the default
- * widget is usually one of the dialog buttons.
- *
- * (For experts: if @setting is %TRUE, the entry calls
- * gtk_window_activate_default() on the window containing the entry, in
- * the default handler for the "activate" signal.)
- *
- **/
-void
-gtk_secure_entry_set_activates_default(GtkSecureEntry * entry,
- gboolean setting)
-{
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
- setting = setting != FALSE;
-
- if (setting != entry->activates_default) {
- entry->activates_default = setting;
- g_object_notify(G_OBJECT(entry), "activates_default");
- }
-}
-
-/**
- * gtk_secure_entry_get_activates_default:
- * @entry: a #GtkSecureEntry
- *
- * Retrieves the value set by gtk_secure_entry_set_activates_default().
- *
- * Return value: %TRUE if the entry will activate the default widget
- **/
-gboolean
-gtk_secure_entry_get_activates_default(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), FALSE);
-
- return entry->activates_default;
-}
-
-/**
- * gtk_secure_entry_set_width_chars:
- * @entry: a #GtkSecureEntry
- * @n_chars: width in chars
- *
- * Changes the size request of the entry to be about the right size
- * for @n_chars characters. Note that it changes the size
- * <emphasis>request</emphasis>, the size can still be affected by
- * how you pack the widget into containers. If @n_chars is -1, the
- * size reverts to the default entry size.
- *
- **/
-void
-gtk_secure_entry_set_width_chars(GtkSecureEntry * entry, gint n_chars)
-{
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
-
- if (entry->width_chars != n_chars) {
- entry->width_chars = n_chars;
- g_object_notify(G_OBJECT(entry), "width_chars");
- gtk_widget_queue_resize(GTK_WIDGET(entry));
- }
-}
-
-/**
- * gtk_secure_entry_get_width_chars:
- * @entry: a #GtkSecureEntry
- *
- * Gets the value set by gtk_secure_entry_set_width_chars().
- *
- * Return value: number of chars to request space for, or negative if unset
- **/
-gint
-gtk_secure_entry_get_width_chars(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), 0);
-
- return entry->width_chars;
-}
-
-/**
- * gtk_secure_entry_set_has_frame:
- * @entry: a #GtkSecureEntry
- * @setting: new value
- *
- * Sets whether the entry has a beveled frame around it.
- **/
-void
-gtk_secure_entry_set_has_frame(GtkSecureEntry * entry, gboolean setting)
-{
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
-
- setting = (setting != FALSE);
-
- if (entry->has_frame == setting)
- return;
-
- gtk_widget_queue_resize(GTK_WIDGET(entry));
- entry->has_frame = setting;
- g_object_notify(G_OBJECT(entry), "has_frame");
-}
-
-/**
- * gtk_secure_entry_get_has_frame:
- * @entry: a #GtkSecureEntry
- *
- * Gets the value set by gtk_secure_entry_set_has_frame().
- *
- * Return value: whether the entry has a beveled frame
- **/
-gboolean
-gtk_secure_entry_get_has_frame(GtkSecureEntry * entry)
-{
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), FALSE);
-
- return entry->has_frame;
-}
-
-
-/**
- * gtk_secure_entry_get_layout:
- * @entry: a #GtkSecureEntry
- *
- * Gets the #PangoLayout used to display the entry.
- * The layout is useful to e.g. convert text positions to
- * pixel positions, in combination with gtk_secure_entry_get_layout_offsets().
- * The returned layout is owned by the entry so need not be
- * freed by the caller.
- *
- * Keep in mind that the layout text may contain a preedit string, so
- * gtk_secure_entry_layout_index_to_text_index() and
- * gtk_secure_entry_text_index_to_layout_index() are needed to convert byte
- * indices in the layout to byte indices in the entry contents.
- *
- * Return value: the #PangoLayout for this entry
- **/
-PangoLayout *
-gtk_secure_entry_get_layout(GtkSecureEntry * entry)
-{
- PangoLayout *layout;
-
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), NULL);
-
- layout = gtk_secure_entry_ensure_layout(entry, TRUE);
-
- return layout;
-}
-
-
-/**
- * gtk_secure_entry_layout_index_to_text_index:
- * @entry: a #GtkSecureEntry
- * @layout_index: byte index into the entry layout text
- *
- * Converts from a position in the entry contents (returned
- * by gtk_secure_entry_get_text()) to a position in the
- * entry's #PangoLayout (returned by gtk_secure_entry_get_layout(),
- * with text retrieved via pango_layout_get_text()).
- *
- * Return value: byte index into the entry contents
- **/
-gint
-gtk_secure_entry_layout_index_to_text_index(GtkSecureEntry * entry,
- gint layout_index)
-{
- PangoLayout *layout;
- const gchar *text;
- gint cursor_index;
-
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), 0);
-
- layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- text = pango_layout_get_text(layout);
- cursor_index =
- g_utf8_offset_to_pointer(text, entry->current_pos) - text;
-
- if (layout_index >= cursor_index && entry->preedit_length) {
- if (layout_index >= cursor_index + entry->preedit_length)
- layout_index -= entry->preedit_length;
- else
- layout_index = cursor_index;
- }
-
- return layout_index;
-}
-
-/**
- * gtk_secure_entry_text_index_to_layout_index:
- * @entry: a #GtkSecureEntry
- * @text_index: byte index into the entry contents
- *
- * Converts from a position in the entry's #PangoLayout(returned by
- * gtk_secure_entry_get_layout()) to a position in the entry contents
- * (returned by gtk_secure_entry_get_text()).
- *
- * Return value: byte index into the entry layout text
- **/
-gint
-gtk_secure_entry_text_index_to_layout_index(GtkSecureEntry * entry,
- gint text_index)
-{
- PangoLayout *layout;
- const gchar *text;
- gint cursor_index;
- g_return_val_if_fail(GTK_IS_SECURE_ENTRY(entry), 0);
-
- layout = gtk_secure_entry_ensure_layout(entry, TRUE);
- text = pango_layout_get_text(layout);
- cursor_index =
- g_utf8_offset_to_pointer(text, entry->current_pos) - text;
-
- if (text_index > cursor_index)
- text_index += entry->preedit_length;
-
- return text_index;
-}
-
-/**
- * gtk_secure_entry_get_layout_offsets:
- * @entry: a #GtkSecureEntry
- * @x: location to store X offset of layout, or %NULL
- * @y: location to store Y offset of layout, or %NULL
- *
- *
- * Obtains the position of the #PangoLayout used to render text
- * in the entry, in widget coordinates. Useful if you want to line
- * up the text in an entry with some other text, e.g. when using the
- * entry to implement editable cells in a sheet widget.
- *
- * Also useful to convert mouse events into coordinates inside the
- * #PangoLayout, e.g. to take some action if some part of the entry text
- * is clicked.
- *
- * Note that as the user scrolls around in the entry the offsets will
- * change; you'll need to connect to the "notify::scroll_offset"
- * signal to track this. Remember when using the #PangoLayout
- * functions you need to convert to and from pixels using
- * PANGO_PIXELS() or #PANGO_SCALE.
- *
- * Keep in mind that the layout text may contain a preedit string, so
- * gtk_secure_entry_layout_index_to_text_index() and
- * gtk_secure_entry_text_index_to_layout_index() are needed to convert byte
- * indices in the layout to byte indices in the entry contents.
- *
- **/
-void
-gtk_secure_entry_get_layout_offsets(GtkSecureEntry * entry,
- gint * x, gint * y)
-{
- gint text_area_x, text_area_y;
-
- g_return_if_fail(GTK_IS_SECURE_ENTRY(entry));
-
- /* this gets coords relative to text area */
- get_layout_position(entry, x, y);
-
- /* convert to widget coords */
- get_text_area_size(entry, &text_area_x, &text_area_y, NULL, NULL);
-
- if (x)
- *x += text_area_x;
-
- if (y)
- *y += text_area_y;
-}
-
-static gboolean
-gtk_secure_entry_mnemonic_activate(GtkWidget * widget,
- gboolean group_cycling G_GNUC_UNUSED)
-{
- gtk_widget_grab_focus(widget);
- return TRUE;
-}
-
-/* We display the cursor when
- *
- * - the selection is empty, AND
- * - the widget has focus
- */
-
-#define CURSOR_ON_MULTIPLIER 0.66
-#define CURSOR_OFF_MULTIPLIER 0.34
-#define CURSOR_PEND_MULTIPLIER 1.0
-
-static gboolean
-cursor_blinks(GtkSecureEntry * entry)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
- GtkSettings *settings = gtk_widget_get_settings(widget);
- gboolean blink;
-
- if (gtk_widget_has_focus (widget) &&
- entry->selection_bound == entry->current_pos) {
- g_object_get(settings, "gtk-cursor-blink", &blink, NULL);
- return blink;
- } else
- return FALSE;
-}
-
-static gint
-get_cursor_time(GtkSecureEntry * entry)
-{
- GtkSettings *settings = gtk_widget_get_settings(GTK_WIDGET(entry));
- gint blinktime;
-
- g_object_get(settings, "gtk-cursor-blink-time", &blinktime, NULL);
-
- return blinktime;
-}
-
-static void
-show_cursor(GtkSecureEntry * entry)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
-
- if (!entry->cursor_visible) {
- entry->cursor_visible = TRUE;
-
- if (gtk_widget_has_focus (widget)
- && entry->selection_bound == entry->current_pos)
- gtk_widget_queue_draw(widget);
- }
-}
-
-static void
-hide_cursor(GtkSecureEntry * entry)
-{
- GtkWidget *widget = GTK_WIDGET(entry);
-
- if (entry->cursor_visible) {
- entry->cursor_visible = FALSE;
-
- if (gtk_widget_has_focus (widget)
- && entry->selection_bound == entry->current_pos)
- gtk_widget_queue_draw(widget);
- }
-}
-
-/*
- * Blink!
- */
-static gint
-blink_cb(gpointer data)
-{
- GtkSecureEntry *entry;
- GtkWidget *widget;
-
- GDK_THREADS_ENTER();
-
- entry = GTK_SECURE_ENTRY(data);
- widget = GTK_WIDGET (entry);
-
- if (!gtk_widget_has_focus (widget)) {
- g_warning
- ("GtkSecureEntry - did not receive focus-out-event. If you\n"
- "connect a handler to this signal, it must return\n"
- "FALSE so the entry gets the event as well");
- }
-
- g_assert(gtk_widget_has_focus (widget));
- g_assert(entry->selection_bound == entry->current_pos);
-
- if (entry->cursor_visible) {
- hide_cursor(entry);
- entry->blink_timeout =
- g_timeout_add(get_cursor_time(entry) * CURSOR_OFF_MULTIPLIER,
- blink_cb, entry);
- } else {
- show_cursor(entry);
- entry->blink_timeout =
- g_timeout_add(get_cursor_time(entry) * CURSOR_ON_MULTIPLIER,
- blink_cb, entry);
- }
-
- GDK_THREADS_LEAVE();
-
- /* Remove ourselves */
- return FALSE;
-}
-
-static void
-gtk_secure_entry_check_cursor_blink(GtkSecureEntry * entry)
-{
- if (cursor_blinks(entry)) {
- if (!entry->blink_timeout) {
- entry->blink_timeout =
- g_timeout_add(get_cursor_time(entry) *
- CURSOR_ON_MULTIPLIER, blink_cb, entry);
- show_cursor(entry);
- }
- } else {
- if (entry->blink_timeout) {
- g_source_remove(entry->blink_timeout);
- entry->blink_timeout = 0;
- }
-
- entry->cursor_visible = TRUE;
- }
-
-}
-
-static void
-gtk_secure_entry_pend_cursor_blink(GtkSecureEntry * entry)
-{
- if (cursor_blinks(entry)) {
- if (entry->blink_timeout != 0)
- g_source_remove(entry->blink_timeout);
-
- entry->blink_timeout =
- g_timeout_add(get_cursor_time(entry) * CURSOR_PEND_MULTIPLIER,
- blink_cb, entry);
- show_cursor(entry);
- }
-}
-
-static inline gboolean
-keyval_is_cursor_move(guint keyval)
-{
- if (keyval == GDK_Up || keyval == GDK_KP_Up)
- return TRUE;
-
- if (keyval == GDK_Down || keyval == GDK_KP_Down)
- return TRUE;
-
- if (keyval == GDK_Page_Up)
- return TRUE;
-
- if (keyval == GDK_Page_Down)
- return TRUE;
-
- return FALSE;
-}
-
-/* stolen from gtkmarshalers.c */
-
-#define g_marshal_value_peek_enum(v) (v)->data[0].v_int
-#define g_marshal_value_peek_int(v) (v)->data[0].v_int
-#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
-
-/* VOID:ENUM,INT,BOOLEAN (gtkmarshalers.list:64) */
-static void
-_gtk_marshal_VOID__ENUM_INT_BOOLEAN(GClosure * closure,
- GValue * return_value G_GNUC_UNUSED,
- guint n_param_values,
- const GValue * param_values,
- gpointer invocation_hint G_GNUC_UNUSED,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__ENUM_INT_BOOLEAN) (gpointer data1,
- gint arg_1,
- gint arg_2,
- gboolean arg_3,
- gpointer data2);
- register GMarshalFunc_VOID__ENUM_INT_BOOLEAN callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
-
- g_return_if_fail(n_param_values == 4);
-
- if (G_CCLOSURE_SWAP_DATA(closure)) {
- data1 = closure->data;
- data2 = g_value_peek_pointer(param_values + 0);
- } else {
- data1 = g_value_peek_pointer(param_values + 0);
- data2 = closure->data;
- }
- callback =
- (GMarshalFunc_VOID__ENUM_INT_BOOLEAN) (marshal_data ? marshal_data
- : cc->callback);
-
- callback(data1,
- g_marshal_value_peek_enum(param_values + 1),
- g_marshal_value_peek_int(param_values + 2),
- g_marshal_value_peek_boolean(param_values + 3), data2);
-}
-
-static void
-_gtk_marshal_VOID__ENUM_INT(GClosure * closure,
- GValue * return_value G_GNUC_UNUSED,
- guint n_param_values,
- const GValue * param_values,
- gpointer invocation_hint G_GNUC_UNUSED,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__ENUM_INT) (gpointer data1,
- gint arg_1,
- gint arg_2,
- gpointer data2);
- register GMarshalFunc_VOID__ENUM_INT callback;
- register GCClosure *cc = (GCClosure *) closure;
- register gpointer data1, data2;
-
- g_return_if_fail(n_param_values == 3);
-
- if (G_CCLOSURE_SWAP_DATA(closure)) {
- data1 = closure->data;
- data2 = g_value_peek_pointer(param_values + 0);
- } else {
- data1 = g_value_peek_pointer(param_values + 0);
- data2 = closure->data;
- }
- callback =
- (GMarshalFunc_VOID__ENUM_INT) (marshal_data ? marshal_data : cc->
- callback);
-
- callback(data1,
- g_marshal_value_peek_enum(param_values + 1),
- g_marshal_value_peek_int(param_values + 2), data2);
-}
bgstack15