diff options
| author | Adam Schreiber <sadam@gnome.org> | 2010-01-25 02:22:24 (GMT) |
|---|---|---|
| committer | Adam Schreiber <sadam@gnome.org> | 2010-01-25 02:22:24 (GMT) |
| commit | ed6f046ff86e34925acb8ec045b150d26137d472 (patch) | |
| tree | d76200f9b1c4795962b88bc9fd22d40fcd4c67ff | |
| parent | aab8e97abe9bd9f4bb2bb2b0acb9f6ca49722bb2 (diff) | |
| download | seahorse-plugins-ed6f046ff86e34925acb8ec045b150d26137d472.zip seahorse-plugins-ed6f046ff86e34925acb8ec045b150d26137d472.tar.xz | |
Use GTK+ GtkEntryBuffer for secure password entry.
Remove our own copy of GtkEntry, and use the new GtkEntryBuffer
in GTK+ 2.18. Bump requred GTK+ version. These changes are copied
from seahorse an modified slightly. The author of
seahorse-secure-buffer.[ch] is Stef Walter.
| -rw-r--r-- | libseahorse/Makefile.am | 2 | ||||
| -rw-r--r-- | libseahorse/seahorse-passphrase.c | 31 | ||||
| -rw-r--r-- | libseahorse/seahorse-prefs.c | 2 | ||||
| -rw-r--r-- | libseahorse/seahorse-secure-buffer.c | 196 | ||||
| -rw-r--r-- | libseahorse/seahorse-secure-buffer.h | 57 | ||||
| -rw-r--r-- | libseahorse/seahorse-secure-entry.c | 2987 | ||||
| -rw-r--r-- | libseahorse/seahorse-secure-entry.h | 187 |
7 files changed, 273 insertions, 3189 deletions
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am index ce76704..e0ae1b4 100644 --- a/libseahorse/Makefile.am +++ b/libseahorse/Makefile.am @@ -43,7 +43,7 @@ libseahorse_a_SOURCES = \ seahorse-gconf.c seahorse-gconf.h \ seahorse-gtkstock.c seahorse-gtkstock.h \ seahorse-secure-memory.c seahorse-secure-memory.h \ - seahorse-secure-entry.c seahorse-secure-entry.h \ + seahorse-secure-buffer.c seahorse-secure-buffer.h \ seahorse-algo.c seahorse-algo.h \ seahorse-unix-signal.c seahorse-unix-signal.h \ $(BUILT_SOURCES) \ diff --git a/libseahorse/seahorse-passphrase.c b/libseahorse/seahorse-passphrase.c index b9feb0b..5d738d6 100644 --- a/libseahorse/seahorse-passphrase.c +++ b/libseahorse/seahorse-passphrase.c @@ -46,7 +46,7 @@ #include "seahorse-widget.h" #include "seahorse-util.h" #include "seahorse-passphrase.h" -#include "seahorse-secure-entry.h" +#include "seahorse-secure-buffer.h" #include "seahorse-gpg-options.h" #include "agent/seahorse-agent.h" @@ -122,7 +122,7 @@ static void confirm_callback (GtkWidget *widget, GtkDialog *dialog) { GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "secure-entry")); - g_assert (SEAHORSE_IS_SECURE_ENTRY (entry)); + g_assert (GTK_IS_ENTRY (entry)); gtk_widget_grab_focus (entry); } @@ -136,14 +136,14 @@ enter_callback (GtkWidget *widget, GtkDialog *dialog) static void entry_changed (GtkEditable *editable, GtkDialog *dialog) { - SeahorseSecureEntry *entry, *confirm; + GtkEntry *entry, *confirm; - entry = SEAHORSE_SECURE_ENTRY (g_object_get_data (G_OBJECT (dialog), "secure-entry")); - confirm = SEAHORSE_SECURE_ENTRY (g_object_get_data (G_OBJECT (dialog), "confirm-entry")); + entry = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "secure-entry")); + confirm = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "confirm-entry")); gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_ACCEPT, - strcmp (seahorse_secure_entry_get_text (entry), - seahorse_secure_entry_get_text (confirm)) == 0); + strcmp (gtk_entry_get_text (entry), + gtk_entry_get_text (confirm)) == 0); } static gboolean @@ -185,7 +185,8 @@ seahorse_passphrase_prompt_show (const gchar *title, const gchar *description, const gchar *prompt, const gchar *check, gboolean confirm) { - SeahorseSecureEntry *entry; + GtkEntryBuffer *buffer; + GtkEntry *entry; GtkDialog *dialog; GtkWidget *w; GtkWidget *box; @@ -251,7 +252,9 @@ seahorse_passphrase_prompt_show (const gchar *title, const gchar *description, g_free (msg); gtk_table_attach (table, w, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - entry = SEAHORSE_SECURE_ENTRY (seahorse_secure_entry_new ()); + buffer = seahorse_secure_buffer_new (); + entry = GTK_ENTRY (gtk_entry_new_with_buffer (buffer)); + g_object_unref (buffer); gtk_widget_set_size_request (GTK_WIDGET (entry), 200, -1); g_object_set_data (G_OBJECT (dialog), "confirm-entry", entry); g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (confirm_callback), dialog); @@ -267,7 +270,9 @@ seahorse_passphrase_prompt_show (const gchar *title, const gchar *description, g_free (msg); gtk_table_attach (table, w, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - entry = SEAHORSE_SECURE_ENTRY (seahorse_secure_entry_new ()); + buffer = seahorse_secure_buffer_new (); + entry = GTK_ENTRY (gtk_entry_new_with_buffer (buffer)); + g_object_unref (buffer); gtk_widget_set_size_request (GTK_WIDGET (entry), 200, -1); g_object_set_data (G_OBJECT (dialog), "secure-entry", entry); g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (enter_callback), dialog); @@ -315,10 +320,10 @@ seahorse_passphrase_prompt_show (const gchar *title, const gchar *description, const gchar* seahorse_passphrase_prompt_get (GtkDialog *dialog) { - SeahorseSecureEntry *entry; + GtkEntry *entry; - entry = SEAHORSE_SECURE_ENTRY (g_object_get_data (G_OBJECT (dialog), "secure-entry")); - return seahorse_secure_entry_get_text (entry); + entry = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "secure-entry")); + return gtk_entry_get_text (entry); } gboolean diff --git a/libseahorse/seahorse-prefs.c b/libseahorse/seahorse-prefs.c index eab846d..44ea4e9 100644 --- a/libseahorse/seahorse-prefs.c +++ b/libseahorse/seahorse-prefs.c @@ -32,7 +32,7 @@ #include "seahorse-check-button-control.h" #include "seahorse-gconf.h" #include "seahorse-gtkstock.h" -#include "seahorse-secure-entry.h" +#include "seahorse-secure-buffer.h" #include "seahorse-widget.h" /* From seahorse-prefs-cache.c */ diff --git a/libseahorse/seahorse-secure-buffer.c b/libseahorse/seahorse-secure-buffer.c new file mode 100644 index 0000000..8db74f0 --- /dev/null +++ b/libseahorse/seahorse-secure-buffer.c @@ -0,0 +1,196 @@ +/* + * Seahorse + * + * Copyright (C) 2010 Stefan Walter + * + * This program 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.1 of + * the License, or (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include "seahorse-secure-buffer.h" +#include <gnome-keyring-memory.h> + +#include <string.h> + +/* Initial size of buffer, in bytes */ +#define MIN_SIZE 16 + +struct _SeahorseSecureBufferPrivate +{ + gchar *text; + gsize text_size; + gsize text_bytes; + guint text_chars; +}; + +G_DEFINE_TYPE (SeahorseSecureBuffer, seahorse_secure_buffer, GTK_TYPE_ENTRY_BUFFER); + +/* -------------------------------------------------------------------------------- + * SECURE IMPLEMENTATIONS OF TEXT BUFFER + */ + +static const gchar* +seahorse_secure_buffer_real_get_text (GtkEntryBuffer *buffer, gsize *n_bytes) +{ + SeahorseSecureBuffer *self = SEAHORSE_SECURE_BUFFER (buffer); + if (n_bytes) + *n_bytes = self->priv->text_bytes; + if (!self->priv->text) + return ""; + return self->priv->text; +} + +static guint +seahorse_secure_buffer_real_get_length (GtkEntryBuffer *buffer) +{ + SeahorseSecureBuffer *self = SEAHORSE_SECURE_BUFFER (buffer); + return self->priv->text_chars; +} + +static guint +seahorse_secure_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position, + const gchar *chars, guint n_chars) +{ + SeahorseSecureBuffer *self = SEAHORSE_SECURE_BUFFER (buffer); + SeahorseSecureBufferPrivate *pv = self->priv; + gsize n_bytes; + gsize at; + + n_bytes = g_utf8_offset_to_pointer (chars, n_chars) - chars; + + /* Need more memory */ + if (n_bytes + pv->text_bytes + 1 > pv->text_size) { + + /* Calculate our new buffer size */ + while (n_bytes + pv->text_bytes + 1 > pv->text_size) { + if (pv->text_size == 0) { + pv->text_size = MIN_SIZE; + } else { + if (2 * pv->text_size < GTK_ENTRY_BUFFER_MAX_SIZE) { + pv->text_size *= 2; + } else { + pv->text_size = GTK_ENTRY_BUFFER_MAX_SIZE; + if (n_bytes > pv->text_size - pv->text_bytes - 1) { + n_bytes = pv->text_size - pv->text_bytes - 1; + n_bytes = g_utf8_find_prev_char (chars, chars + n_bytes + 1) - chars; + n_chars = g_utf8_strlen (chars, n_bytes); + } + break; + } + } + } + + pv->text = gnome_keyring_memory_realloc (pv->text, pv->text_size); + } + + /* Actual text insertion */ + at = g_utf8_offset_to_pointer (pv->text, position) - pv->text; + g_memmove (pv->text + at + n_bytes, pv->text + at, pv->text_bytes - at); + memcpy (pv->text + at, chars, n_bytes); + + /* Book keeping */ + pv->text_bytes += n_bytes; + pv->text_chars += n_chars; + pv->text[pv->text_bytes] = '\0'; + + gtk_entry_buffer_emit_inserted_text (buffer, position, chars, n_chars); + return n_chars; +} + +static guint +seahorse_secure_buffer_real_delete_text (GtkEntryBuffer *buffer, guint position, guint n_chars) +{ + SeahorseSecureBuffer *self = SEAHORSE_SECURE_BUFFER (buffer); + SeahorseSecureBufferPrivate *pv = self->priv; + gsize start, end; + + if (position > pv->text_chars) + position = pv->text_chars; + if (position + n_chars > pv->text_chars) + n_chars = pv->text_chars - position; + + if (n_chars > 0) { + start = g_utf8_offset_to_pointer (pv->text, position) - pv->text; + end = g_utf8_offset_to_pointer (pv->text, position + n_chars) - pv->text; + + g_memmove (pv->text + start, pv->text + end, pv->text_bytes + 1 - end); + pv->text_chars -= n_chars; + pv->text_bytes -= (end - start); + + gtk_entry_buffer_emit_deleted_text (buffer, position, n_chars); + } + + return n_chars; +} + +/* -------------------------------------------------------------------------------- + * + */ + +static void +seahorse_secure_buffer_init (SeahorseSecureBuffer *self) +{ + SeahorseSecureBufferPrivate *pv; + pv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_SECURE_BUFFER, SeahorseSecureBufferPrivate); + + pv->text = NULL; + pv->text_chars = 0; + pv->text_bytes = 0; + pv->text_size = 0; +} + +static void +seahorse_secure_buffer_finalize (GObject *obj) +{ + SeahorseSecureBuffer *self = SEAHORSE_SECURE_BUFFER (obj); + SeahorseSecureBufferPrivate *pv = self->priv; + + if (pv->text) { + gnome_keyring_memory_free (pv->text); + pv->text = NULL; + pv->text_bytes = pv->text_size = 0; + pv->text_chars = 0; + } + + G_OBJECT_CLASS (seahorse_secure_buffer_parent_class)->finalize (obj); +} + +static void +seahorse_secure_buffer_class_init (SeahorseSecureBufferClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkEntryBufferClass *buffer_class = GTK_ENTRY_BUFFER_CLASS (klass); + + gobject_class->finalize = seahorse_secure_buffer_finalize; + + buffer_class->get_text = seahorse_secure_buffer_real_get_text; + buffer_class->get_length = seahorse_secure_buffer_real_get_length; + buffer_class->insert_text = seahorse_secure_buffer_real_insert_text; + buffer_class->delete_text = seahorse_secure_buffer_real_delete_text; + + g_type_class_add_private (gobject_class, sizeof (SeahorseSecureBufferPrivate)); +} + +/* -------------------------------------------------------------------------------- + * + */ + +GtkEntryBuffer* +seahorse_secure_buffer_new (void) +{ + return g_object_new (SEAHORSE_TYPE_SECURE_BUFFER, NULL); +} diff --git a/libseahorse/seahorse-secure-buffer.h b/libseahorse/seahorse-secure-buffer.h new file mode 100644 index 0000000..7c94f8a --- /dev/null +++ b/libseahorse/seahorse-secure-buffer.h @@ -0,0 +1,57 @@ +/* + * Seahorse + * + * Copyright (C) 2010 Stefan Walter + * + * This program 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.1 of + * the License, or (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef __SEAHORSE_SECURE_BUFFER_H__ +#define __SEAHORSE_SECURE_BUFFER_H__ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define SEAHORSE_TYPE_SECURE_BUFFER (seahorse_secure_buffer_get_type ()) +#define SEAHORSE_SECURE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SECURE_BUFFER, SeahorseSecureBuffer)) +#define SEAHORSE_SECURE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SECURE_BUFFER, SeahorseSecureBufferClass)) +#define SEAHORSE_IS_SECURE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SECURE_BUFFER)) +#define SEAHORSE_IS_SECURE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SECURE_BUFFER)) +#define SEAHORSE_SECURE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SECURE_BUFFER, SeahorseSecureBufferClass)) + +typedef struct _SeahorseSecureBuffer SeahorseSecureBuffer; +typedef struct _SeahorseSecureBufferClass SeahorseSecureBufferClass; +typedef struct _SeahorseSecureBufferPrivate SeahorseSecureBufferPrivate; + +struct _SeahorseSecureBuffer +{ + GtkEntryBuffer parent; + SeahorseSecureBufferPrivate *priv; +}; + +struct _SeahorseSecureBufferClass +{ + GtkEntryBufferClass parent_class; +}; + +GType seahorse_secure_buffer_get_type (void) G_GNUC_CONST; + +GtkEntryBuffer* seahorse_secure_buffer_new (void); + +G_END_DECLS + +#endif /* __SEAHORSE_SECURE_BUFFER_H__ */ diff --git a/libseahorse/seahorse-secure-entry.c b/libseahorse/seahorse-secure-entry.c deleted file mode 100644 index 22a3f9f..0000000 --- a/libseahorse/seahorse-secure-entry.c +++ /dev/null @@ -1,2987 +0,0 @@ -/* - * GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * 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. - * - * (C) by Albrecht Dreß 2004 unter the terms of the GNU Lesser General - * Public License. - * - * The entry is invisible by default, uses secure memory methods to - * allocate the text memory, and all potentially dangerous methods - * (copy & paste, popup, etc.) have been removed. - */ - -/* - * Modified for inclusion into seahorse by Stef Walter - */ - -#include <stdlib.h> -#include <string.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include "seahorse-secure-entry.h" -#include "seahorse-secure-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, - PROP_VISIBILITY -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* GObject, GtkObject methods */ -static void seahorse_secure_entry_class_init (SeahorseSecureEntryClass *klass); -static void seahorse_secure_entry_editable_init (GtkEditableClass *iface); -static void seahorse_secure_entry_cell_editable_init (GtkCellEditableIface *iface); -static void seahorse_secure_entry_init (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void seahorse_secure_entry_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); -static void seahorse_secure_entry_finalize (GObject *object); - -/* GtkWidget methods */ -static void seahorse_secure_entry_realize (GtkWidget *widget); -static void seahorse_secure_entry_unrealize (GtkWidget *widget); -static void seahorse_secure_entry_size_request (GtkWidget *widget, GtkRequisition *requisition); -static void seahorse_secure_entry_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static void seahorse_secure_entry_draw_frame (GtkWidget *widget); -static gint seahorse_secure_entry_expose (GtkWidget *widget, GdkEventExpose *event); -static gint seahorse_secure_entry_button_press (GtkWidget *widget, GdkEventButton *event); -static gint seahorse_secure_entry_button_release (GtkWidget *widget, GdkEventButton *event); -static gint seahorse_secure_entry_motion_notify (GtkWidget *widget, GdkEventMotion *event); -static gint seahorse_secure_entry_key_press (GtkWidget *widget, GdkEventKey *event); -static gint seahorse_secure_entry_key_release (GtkWidget *widget, GdkEventKey *event); -static gint seahorse_secure_entry_focus_in (GtkWidget *widget, GdkEventFocus *event); -static gint seahorse_secure_entry_focus_out (GtkWidget *widget, GdkEventFocus *event); -static void seahorse_secure_entry_grab_focus (GtkWidget *widget); -static void seahorse_secure_entry_style_set (GtkWidget *widget, GtkStyle *previous_style); -static void seahorse_secure_entry_direction_changed (GtkWidget *widget, GtkTextDirection previous_dir); -static void seahorse_secure_entry_state_changed (GtkWidget *widget, GtkStateType previous_state); -static void seahorse_secure_entry_screen_changed (GtkWidget *widget, GdkScreen *old_screen); - -/* GtkEditable method implementations */ -static void seahorse_secure_entry_insert_text (GtkEditable *editable, const gchar *new_text, - gint new_text_length, gint *position); -static void seahorse_secure_entry_delete_text (GtkEditable *editable, gint start_pos, gint end_pos); -static void seahorse_secure_entry_real_set_position (GtkEditable *editable, gint position); -static gint seahorse_secure_entry_get_position (GtkEditable *editable); -static void seahorse_secure_entry_set_selection_bounds (GtkEditable *editable, gint start, gint end); -static gboolean seahorse_secure_entry_get_selection_bounds (GtkEditable *editable, gint *start, gint *end); - -/* GtkCellEditable method implementations */ -static void seahorse_secure_entry_start_editing (GtkCellEditable *cell_editable, GdkEvent *event); - -/* Default signal handlers */ -static void seahorse_secure_entry_real_insert_text (GtkEditable *editable, const gchar *new_text, - gint new_text_length, gint *position); -static void seahorse_secure_entry_real_delete_text (GtkEditable *editable, gint start_pos, gint end_pos); -static void seahorse_secure_entry_move_cursor (SeahorseSecureEntry *entry, GtkMovementStep step, - gint count, gboolean extend_selection); -static void seahorse_secure_entry_insert_at_cursor (SeahorseSecureEntry *entry, const gchar *str); -static void seahorse_secure_entry_delete_from_cursor (SeahorseSecureEntry *entry, GtkDeleteType type, gint count); -static void seahorse_secure_entry_real_activate (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_keymap_direction_changed (GdkKeymap *keymap, SeahorseSecureEntry *entry); - -/* IM Context Callbacks */ -static void seahorse_secure_entry_commit_cb(GtkIMContext *context, const gchar *str, SeahorseSecureEntry *entry); -static void seahorse_secure_entry_preedit_changed_cb (GtkIMContext * context, SeahorseSecureEntry *entry); -static gboolean seahorse_secure_entry_retrieve_surrounding_cb (GtkIMContext *context, SeahorseSecureEntry *entry); -static gboolean seahorse_secure_entry_delete_surrounding_cb (GtkIMContext *context, gint offset, - gint n_chars, SeahorseSecureEntry *entry); - -/* Internal routines */ -static void seahorse_secure_entry_enter_text (SeahorseSecureEntry *entry, const gchar *str); -static void seahorse_secure_entry_set_positions (SeahorseSecureEntry *entry, gint current_pos, gint selection_bound); -static void seahorse_secure_entry_draw_text (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_draw_cursor (SeahorseSecureEntry *entry); -static PangoLayout *seahorse_secure_entry_ensure_layout(SeahorseSecureEntry *entry, gboolean include_preedit); -static void seahorse_secure_entry_reset_layout (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_queue_draw (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_reset_im_context (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_recompute (SeahorseSecureEntry *entry); -static gint seahorse_secure_entry_find_position (SeahorseSecureEntry *entry, gint x); -static void seahorse_secure_entry_get_cursor_locations (SeahorseSecureEntry *entry, gint *strong_x, gint *weak_x); -static void seahorse_secure_entry_adjust_scroll (SeahorseSecureEntry *entry); -static gint seahorse_secure_entry_move_visually (SeahorseSecureEntry *editable, gint start, gint count); -static gint seahorse_secure_entry_move_logically (SeahorseSecureEntry *entry, gint start, gint count); -static gboolean seahorse_secure_entry_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); -static void seahorse_secure_entry_state_changed (GtkWidget *widget, GtkStateType previous_state); -static void seahorse_secure_entry_check_cursor_blink (SeahorseSecureEntry *entry); -static void seahorse_secure_entry_pend_cursor_blink (SeahorseSecureEntry *entry); -static void get_text_area_size (SeahorseSecureEntry *entry, gint *x, gint *y, gint *width, gint *height); -static void get_widget_window_size (SeahorseSecureEntry *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; - -GType -seahorse_secure_entry_get_type(void) -{ - static GType entry_type = 0; - - if (!entry_type) { - static const GTypeInfo entry_info = { - sizeof(SeahorseSecureEntryClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) seahorse_secure_entry_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(SeahorseSecureEntry), - 0, /* n_preallocs */ - (GInstanceInitFunc) seahorse_secure_entry_init, - }; - - static const GInterfaceInfo editable_info = { - (GInterfaceInitFunc) seahorse_secure_entry_editable_init, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - static const GInterfaceInfo cell_editable_info = { - (GInterfaceInitFunc) seahorse_secure_entry_cell_editable_init, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - entry_type = g_type_register_static(GTK_TYPE_WIDGET, "SeahorseSecureEntry", &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 -seahorse_secure_entry_class_init(SeahorseSecureEntryClass *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 = seahorse_secure_entry_finalize; - gobject_class->set_property = seahorse_secure_entry_set_property; - gobject_class->get_property = seahorse_secure_entry_get_property; - - widget_class->realize = seahorse_secure_entry_realize; - widget_class->unrealize = seahorse_secure_entry_unrealize; - widget_class->size_request = seahorse_secure_entry_size_request; - widget_class->size_allocate = seahorse_secure_entry_size_allocate; - widget_class->expose_event = seahorse_secure_entry_expose; - widget_class->button_press_event = seahorse_secure_entry_button_press; - widget_class->button_release_event = seahorse_secure_entry_button_release; - widget_class->motion_notify_event = seahorse_secure_entry_motion_notify; - widget_class->key_press_event = seahorse_secure_entry_key_press; - widget_class->key_release_event = seahorse_secure_entry_key_release; - widget_class->focus_in_event = seahorse_secure_entry_focus_in; - widget_class->focus_out_event = seahorse_secure_entry_focus_out; - widget_class->grab_focus = seahorse_secure_entry_grab_focus; - widget_class->style_set = seahorse_secure_entry_style_set; - widget_class->direction_changed = seahorse_secure_entry_direction_changed; - widget_class->state_changed = seahorse_secure_entry_state_changed; - widget_class->screen_changed = seahorse_secure_entry_screen_changed; - widget_class->mnemonic_activate = seahorse_secure_entry_mnemonic_activate; - - class->move_cursor = seahorse_secure_entry_move_cursor; - class->insert_at_cursor = seahorse_secure_entry_insert_at_cursor; - class->delete_from_cursor = seahorse_secure_entry_delete_from_cursor; - class->activate = seahorse_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)); - - g_object_class_install_property (gobject_class, PROP_VISIBILITY, - g_param_spec_boolean ("visibility", "Visibility", "Whether contents are drawn using invisible character", - FALSE, G_PARAM_READWRITE)); - - /* Action signals */ - - signals[ACTIVATE] = g_signal_new ("activate", G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (SeahorseSecureEntryClass, 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 (SeahorseSecureEntryClass, 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 (SeahorseSecureEntryClass, 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 (SeahorseSecureEntryClass, 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 -seahorse_secure_entry_editable_init (GtkEditableClass *iface) -{ - iface->do_insert_text = seahorse_secure_entry_insert_text; - iface->do_delete_text = seahorse_secure_entry_delete_text; - iface->insert_text = seahorse_secure_entry_real_insert_text; - iface->delete_text = seahorse_secure_entry_real_delete_text; - iface->set_selection_bounds = seahorse_secure_entry_set_selection_bounds; - iface->get_selection_bounds = seahorse_secure_entry_get_selection_bounds; - iface->set_position = seahorse_secure_entry_real_set_position; - iface->get_position = seahorse_secure_entry_get_position; -} - -static void -seahorse_secure_entry_cell_editable_init (GtkCellEditableIface * iface) -{ - iface->start_editing = seahorse_secure_entry_start_editing; -} - -static void -seahorse_secure_entry_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY(object); - - switch (prop_id) { - case PROP_MAX_LENGTH: - seahorse_secure_entry_set_max_length(entry, g_value_get_int(value)); - break; - - case PROP_HAS_FRAME: - seahorse_secure_entry_set_has_frame(entry, g_value_get_boolean(value)); - break; - - case PROP_INVISIBLE_CHAR: - seahorse_secure_entry_set_invisible_char(entry, g_value_get_uint(value)); - break; - - case PROP_ACTIVATES_DEFAULT: - seahorse_secure_entry_set_activates_default(entry, g_value_get_boolean(value)); - break; - - case PROP_WIDTH_CHARS: - seahorse_secure_entry_set_width_chars(entry, g_value_get_int(value)); - break; - - case PROP_TEXT: - seahorse_secure_entry_set_text(entry, g_value_get_string(value)); - break; - - case PROP_VISIBILITY: - seahorse_secure_entry_set_visibility (entry, g_value_get_boolean (value)); - break; - - case PROP_SCROLL_OFFSET: - case PROP_CURSOR_POSITION: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -seahorse_secure_entry_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - SeahorseSecureEntry *entry = SEAHORSE_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, seahorse_secure_entry_get_text(entry)); - break; - case PROP_VISIBILITY: - g_value_set_boolean (value, seahorse_secure_entry_get_visibility (entry)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -seahorse_secure_entry_init (SeahorseSecureEntry *entry) -{ - GtkStyle *style; - GtkWidget *tempent; - - GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS); - - /* Get the RC style for a normal GtkEntry */ - style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (GTK_WIDGET (entry)), - NULL, NULL, GTK_TYPE_ENTRY); - gtk_widget_set_style (GTK_WIDGET (entry), style); - - entry->text_size = MIN_SIZE; - WITH_SECURE_MEM (entry->text = g_malloc(entry->text_size + 1)); - entry->text[0] = '\0'; - - entry->visibility = FALSE; - entry->width_chars = -1; - entry->is_cell_renderer = FALSE; - entry->editing_canceled = FALSE; - entry->has_frame = TRUE; - - /* Use the invisible_char from GtkEntry */ - tempent = gtk_entry_new (); - entry->invisible_char = gtk_entry_get_invisible_char (GTK_ENTRY (tempent)); - g_object_ref_sink (tempent); - g_object_unref (tempent); - - /* - * 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 (seahorse_secure_entry_commit_cb), entry); - g_signal_connect (entry->im_context, "preedit_changed", - G_CALLBACK(seahorse_secure_entry_preedit_changed_cb), entry); - g_signal_connect (entry->im_context, "retrieve_surrounding", - G_CALLBACK(seahorse_secure_entry_retrieve_surrounding_cb), entry); - g_signal_connect (entry->im_context, "delete_surrounding", - G_CALLBACK(seahorse_secure_entry_delete_surrounding_cb), entry); -} - -static void -seahorse_secure_entry_finalize (GObject *object) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 -seahorse_secure_entry_realize (GtkWidget *widget) -{ - SeahorseSecureEntry *entry; - GtkEditable *editable; - GdkWindowAttr attributes; - gint attributes_mask; - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - entry = SEAHORSE_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; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (widget->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 (widget->window, &attributes, attributes_mask); - gdk_window_set_user_data (entry->text_area, entry); - - gdk_cursor_unref (attributes.cursor); - - widget->style = gtk_style_attach (widget->style, widget->window); - - gdk_window_set_background (widget->window, - &widget->style->base[GTK_WIDGET_STATE (widget)]); - gdk_window_set_background (entry->text_area, - &widget->style->base[GTK_WIDGET_STATE (widget)]); - - gdk_window_show (entry->text_area); - - gtk_im_context_set_client_window (entry->im_context, entry->text_area); - - seahorse_secure_entry_adjust_scroll (entry); -} - -static void -seahorse_secure_entry_unrealize (GtkWidget *widget) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - seahorse_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 (SeahorseSecureEntry *entry, gint *xborder, gint *yborder) -{ - GtkWidget *widget = GTK_WIDGET (entry); - gint focus_width; - gboolean interior_focus; - - gtk_widget_style_get (widget, "interior-focus", &interior_focus, - "focus-line-width", &focus_width, NULL); - - if (entry->has_frame) { - *xborder = widget->style->xthickness; - *yborder = widget->style->ythickness; - } else { - *xborder = 0; - *yborder = 0; - } - - if (!interior_focus) { - *xborder += focus_width; - *yborder += focus_width; - } -} - -static void -seahorse_secure_entry_size_request (GtkWidget *widget, GtkRequisition *requisition) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - PangoFontMetrics *metrics; - gint xborder, yborder; - PangoContext *context; - - context = gtk_widget_get_pango_context (widget); - metrics = pango_context_get_metrics (context, widget->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(SeahorseSecureEntry *entry, gint *x, gint *y, gint *width, gint *height) -{ - gint xborder, yborder; - GtkRequisition requisition; - GtkWidget *widget = GTK_WIDGET (entry); - - gtk_widget_get_child_requisition (widget, &requisition); - - get_borders (entry, &xborder, &yborder); - - if (x) - *x = xborder; - - if (y) - *y = yborder; - - if (width) - *width = GTK_WIDGET (entry)->allocation.width - xborder * 2; - - if (height) - *height = requisition.height - yborder * 2; -} - -static void -get_widget_window_size (SeahorseSecureEntry *entry, gint *x, gint *y, gint *width, gint *height) -{ - GtkRequisition requisition; - GtkWidget *widget = GTK_WIDGET (entry); - - gtk_widget_get_child_requisition (widget, &requisition); - - if (x) - *x = widget->allocation.x; - - if (y) { - if (entry->is_cell_renderer) - *y = widget->allocation.y; - else - *y = widget->allocation.y + (widget->allocation.height - - requisition.height) / 2; - } - - if (width) - *width = widget->allocation.width; - - if (height) { - if (entry->is_cell_renderer) - *height = widget->allocation.height; - else - *height = requisition.height; - } -} - -static void -seahorse_secure_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY(widget); - - widget->allocation = *allocation; - - if (GTK_WIDGET_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 (widget->window, x, y, width, height); - - get_text_area_size (entry, &x, &y, &width, &height); - - gdk_window_move_resize (entry->text_area, x, y, width, height); - - seahorse_secure_entry_recompute (entry); - } -} - -static void -seahorse_secure_entry_draw_frame (GtkWidget *widget) -{ - 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); - - gdk_drawable_get_size (widget->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; - } - - gtk_paint_shadow (widget->style, widget->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(widget->style, widget->window, GTK_WIDGET_STATE (widget), - NULL, widget, "entry", 0, 0, width, height); - } -} - -static gint -seahorse_secure_entry_expose(GtkWidget *widget, GdkEventExpose *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY(widget); - - if (widget->window == event->window) - seahorse_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); - - gtk_paint_flat_box(widget->style, entry->text_area, GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE, - NULL, widget, "entry_bg", 0, 0, area_width, area_height); - - if ((entry->invisible_char != 0) && GTK_WIDGET_HAS_FOCUS (widget) && - entry->selection_bound == entry->current_pos && entry->cursor_visible) - seahorse_secure_entry_draw_cursor (SEAHORSE_SECURE_ENTRY (widget)); - - seahorse_secure_entry_draw_text (SEAHORSE_SECURE_ENTRY (widget)); - } - - return FALSE; -} - -static gint -seahorse_secure_entry_button_press(GtkWidget *widget, GdkEventButton *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 = seahorse_secure_entry_find_position (entry, event->x + entry->scroll_offset); - - if (event->button == 1) { - switch (event->type) { - case GDK_BUTTON_PRESS: - seahorse_secure_entry_set_positions(entry, tmp_pos, tmp_pos); - break; - default: - break; - } - - return TRUE; - } - - return FALSE; -} - -static gint -seahorse_secure_entry_button_release(GtkWidget *widget, GdkEventButton *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY(widget); - - if (event->window != entry->text_area || entry->button != event->button) - return FALSE; - - entry->button = 0; - return TRUE; -} - -static gint -seahorse_secure_entry_motion_notify(GtkWidget *widget, GdkEventMotion *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 = seahorse_secure_entry_find_position (entry, - event->x + entry->scroll_offset); - - seahorse_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 -seahorse_secure_entry_obscure_mouse_cursor (SeahorseSecureEntry * entry) -{ - if (entry->mouse_cursor_obscured) - return; - - set_invisible_cursor (entry->text_area); - - entry->mouse_cursor_obscured = TRUE; -} - -static gint -seahorse_secure_entry_key_press (GtkWidget *widget, GdkEventKey *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - seahorse_secure_entry_pend_cursor_blink (entry); - - if (gtk_im_context_filter_keypress (entry->im_context, event)) { - seahorse_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 -seahorse_secure_entry_key_release (GtkWidget *widget, GdkEventKey *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 -seahorse_secure_entry_focus_in (GtkWidget *widget, GdkEventFocus *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 (seahorse_secure_entry_keymap_direction_changed), entry); - - seahorse_secure_entry_check_cursor_blink (entry); - - return FALSE; -} - -static gint -seahorse_secure_entry_focus_out (GtkWidget *widget, GdkEventFocus *event) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - gtk_widget_queue_draw (widget); - - entry->need_im_reset = TRUE; - gtk_im_context_focus_out (entry->im_context); - - seahorse_secure_entry_check_cursor_blink (entry); - - g_signal_handlers_disconnect_by_func (gdk_keymap_get_for_display (gtk_widget_get_display (widget)), - seahorse_secure_entry_keymap_direction_changed, entry); - - return FALSE; -} - -static void -seahorse_secure_entry_grab_focus (GtkWidget *widget) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - GtkSettings *settings = gtk_widget_get_settings (widget); - gboolean select_on_focus = FALSE; - - GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT); - GTK_WIDGET_CLASS (parent_class)->grab_focus(widget); - - /* Some versions of GTK don't have this property */ - if (g_object_class_find_property (G_OBJECT_CLASS (GTK_SETTINGS_GET_CLASS (settings)), - "gtk-entry-select-on-focus")) - g_object_get (settings, "gtk-entry-select-on-focus", &select_on_focus, NULL); - - if (select_on_focus && !entry->in_click) - gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); -} - -static void -seahorse_secure_entry_direction_changed(GtkWidget *widget, GtkTextDirection previous_dir) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - seahorse_secure_entry_recompute (entry); - - GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir); -} - -static void -seahorse_secure_entry_state_changed (GtkWidget *widget, GtkStateType previous_state) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - if (GTK_WIDGET_REALIZED (widget)) { - gdk_window_set_background (widget->window, - &widget->style->base[GTK_WIDGET_STATE(widget)]); - gdk_window_set_background (entry->text_area, - &widget->style->base[GTK_WIDGET_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 -seahorse_secure_entry_screen_changed (GtkWidget *widget, GdkScreen *old_screen) -{ - seahorse_secure_entry_recompute (SEAHORSE_SECURE_ENTRY (widget)); -} - -/* GtkEditable method implementations */ - -static void -seahorse_secure_entry_insert_text (GtkEditable *editable, const gchar *new_text, - gint new_text_length, gint * position) -{ - SeahorseSecureEntry *entry = SEAHORSE_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)); - - strncpy (text, new_text, new_text_length); - text[new_text_length] = '\0'; - - 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 -seahorse_secure_entry_delete_text (GtkEditable* editable, gint start_pos, - gint end_pos) -{ - SeahorseSecureEntry *entry = SEAHORSE_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 -seahorse_secure_entry_set_position_internal (SeahorseSecureEntry *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) - seahorse_secure_entry_reset_im_context (entry); - seahorse_secure_entry_set_positions (entry, position, position); - } -} - -static void -seahorse_secure_entry_real_set_position (GtkEditable *editable, gint position) -{ - seahorse_secure_entry_set_position_internal (SEAHORSE_SECURE_ENTRY (editable), - position, TRUE); -} - -static gint -seahorse_secure_entry_get_position (GtkEditable *editable) -{ - return SEAHORSE_SECURE_ENTRY (editable)->current_pos; -} - -static void -seahorse_secure_entry_set_selection_bounds (GtkEditable *editable, - gint start, gint end) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (editable); - - if (start < 0) - start = entry->text_length; - if (end < 0) - end = entry->text_length; - - seahorse_secure_entry_reset_im_context (entry); - - seahorse_secure_entry_set_positions (entry, MIN (end, entry->text_length), - MIN (start, entry->text_length)); -} - -static gboolean -seahorse_secure_entry_get_selection_bounds (GtkEditable *editable, - gint *start, gint *end) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (editable); - - *start = entry->selection_bound; - *end = entry->current_pos; - - return (entry->selection_bound != entry->current_pos); -} - -static void -seahorse_secure_entry_style_set (GtkWidget *widget, GtkStyle *previous_style) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY (widget); - - seahorse_secure_entry_recompute (entry); - - if (previous_style && GTK_WIDGET_REALIZED (widget)) { - gdk_window_set_background (widget->window, - &widget->style->base[GTK_WIDGET_STATE (widget)]); - gdk_window_set_background (entry->text_area, - &widget->style-> base[GTK_WIDGET_STATE (widget)]); - } -} - -/* GtkCellEditable method implementations - */ -static void -gtk_cell_editable_secure_entry_activated (SeahorseSecureEntry *entry, gpointer data) -{ - 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 (SeahorseSecureEntry *entry, GdkEventKey *key_event, - gpointer data) -{ - 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 -seahorse_secure_entry_start_editing (GtkCellEditable *cell_editable, - GdkEvent *event) -{ - SEAHORSE_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 -seahorse_secure_entry_real_insert_text (GtkEditable *editable, const gchar *new_text, - gint new_text_length, gint *position) -{ - gint _index; - gint n_chars; - - SeahorseSecureEntry *entry = SEAHORSE_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 + 1)); - } - - _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; - - seahorse_secure_entry_recompute (entry); - - entry->changed = TRUE; - g_signal_emit_by_name (editable, "changed"); - g_object_notify (G_OBJECT (editable), "text"); -} - -static void -seahorse_secure_entry_real_delete_text (GtkEditable *editable, gint start_pos, - gint end_pos) -{ - SeahorseSecureEntry *entry = SEAHORSE_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; - - seahorse_secure_entry_set_positions(entry, current_pos, selection_bound); - - seahorse_secure_entry_recompute (entry); - - entry->changed = TRUE; - 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 (SeahorseSecureEntry *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 = seahorse_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 -seahorse_secure_entry_move_cursor (SeahorseSecureEntry *entry, GtkMovementStep step, - gint count, gboolean extend_selection) -{ - gint new_pos = entry->current_pos; - - seahorse_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 = seahorse_secure_entry_move_logically (entry, new_pos, count); - break; - case GTK_MOVEMENT_VISUAL_POSITIONS: - new_pos = seahorse_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); - - seahorse_secure_entry_pend_cursor_blink (entry); -} - -static void -seahorse_secure_entry_insert_at_cursor(SeahorseSecureEntry *entry, const gchar *str) -{ - GtkEditable *editable = GTK_EDITABLE (entry); - gint pos = entry->current_pos; - - seahorse_secure_entry_reset_im_context (entry); - - gtk_editable_insert_text (editable, str, -1, &pos); - gtk_editable_set_position (editable, pos); -} - -static void -seahorse_secure_entry_delete_from_cursor (SeahorseSecureEntry *entry, GtkDeleteType type, - gint count) -{ - GtkEditable *editable = GTK_EDITABLE (entry); - gint start_pos = entry->current_pos; - gint end_pos = entry->current_pos; - - seahorse_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 = seahorse_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; - } - - seahorse_secure_entry_pend_cursor_blink (entry); -} - -#if UNUSED -static void -seahorse_secure_entry_delete_cb (SeahorseSecureEntry *entry) -{ - GtkEditable *editable = GTK_EDITABLE (entry); - gint start, end; - - if (gtk_editable_get_selection_bounds (editable, &start, &end)) - gtk_editable_delete_text (editable, start, end); -} - - -static void -seahorse_secure_entry_toggle_overwrite (SeahorseSecureEntry *entry) -{ - entry->overwrite_mode = !entry->overwrite_mode; -} -#endif - -static void -seahorse_secure_entry_real_activate (SeahorseSecureEntry *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)) { - window = GTK_WINDOW(toplevel); - - if (window && widget != window->default_widget && - !(widget == window->focus_widget && - (!window->default_widget || !GTK_WIDGET_SENSITIVE(window->default_widget)))) - gtk_window_activate_default(window); - } - } -} - -static void -seahorse_secure_entry_keymap_direction_changed (GdkKeymap *keymap, SeahorseSecureEntry *entry) -{ - seahorse_secure_entry_recompute (entry); -} - -/* IM Context Callbacks */ - -static void -seahorse_secure_entry_commit_cb (GtkIMContext *context, const gchar *str, - SeahorseSecureEntry *entry) -{ - seahorse_secure_entry_enter_text (entry, str); -} - -static void -seahorse_secure_entry_preedit_changed_cb (GtkIMContext *context, SeahorseSecureEntry *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); - - seahorse_secure_entry_recompute (entry); -} - -static gboolean -seahorse_secure_entry_retrieve_surrounding_cb (GtkIMContext *context, SeahorseSecureEntry *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 -seahorse_secure_entry_delete_surrounding_cb (GtkIMContext *slave, gint offset, gint n_chars, - SeahorseSecureEntry *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 -seahorse_secure_entry_enter_text (SeahorseSecureEntry *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) - seahorse_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); - seahorse_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 -seahorse_secure_entry_set_positions (SeahorseSecureEntry *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) - seahorse_secure_entry_recompute (entry); -} - -static void -seahorse_secure_entry_reset_layout (SeahorseSecureEntry *entry) -{ - if (entry->cached_layout) { - g_object_unref (entry->cached_layout); - entry->cached_layout = NULL; - } -} - -static void -update_im_cursor_location (SeahorseSecureEntry *entry) -{ - GdkRectangle area; - gint strong_x; - gint strong_xoffset; - gint area_width, area_height; - - seahorse_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) -{ - SeahorseSecureEntry *entry; - - GDK_THREADS_ENTER (); - - entry = SEAHORSE_SECURE_ENTRY (data); - - entry->recompute_idle = 0; - - if (gtk_widget_has_screen (GTK_WIDGET (entry))) { - seahorse_secure_entry_adjust_scroll (entry); - seahorse_secure_entry_queue_draw (entry); - - update_im_cursor_location (entry); - } - - GDK_THREADS_LEAVE (); - - return FALSE; -} - -static void -seahorse_secure_entry_recompute (SeahorseSecureEntry *entry) -{ - seahorse_secure_entry_reset_layout (entry); - seahorse_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 gunichar -build_string (SeahorseSecureEntry *entry, GString *str, gint extra) -{ - gint i, count, char_len; - gunichar invisible_char; - gchar buf[7]; - - if (entry->visibility) { - g_string_append_len (str, entry->text, entry->n_bytes); - return 0; - - } else { - - if (entry->invisible_char != 0) - invisible_char = entry->invisible_char; - else - invisible_char = ' '; /* just pick a char */ - - count = g_utf8_strlen (entry->text, entry->n_bytes) + extra; - - char_len = g_unichar_to_utf8 (entry->invisible_char, buf); - for (i = 0; i < count; i++) - g_string_append_len(str, buf, char_len); - - return invisible_char; - } -} - -static PangoLayout * -seahorse_secure_entry_create_layout (SeahorseSecureEntry * 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 preedit_len_chars; - gunichar invisible_char; - - preedit_len_chars = g_utf8_strlen (preedit_string, -1); - invisible_char = build_string (entry, tmp_string, preedit_len_chars); - - /* - * 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); - build_string (entry, str, 0); - 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 * -seahorse_secure_entry_ensure_layout (SeahorseSecureEntry *entry, gboolean include_preedit) -{ - if (entry->preedit_length > 0 && !include_preedit != !entry->cache_includes_preedit) - seahorse_secure_entry_reset_layout (entry); - - if (!entry->cached_layout) { - entry->cached_layout = seahorse_secure_entry_create_layout (entry, include_preedit); - entry->cache_includes_preedit = include_preedit; - } - - return entry->cached_layout; -} - -static void -get_layout_position (SeahorseSecureEntry *entry, gint *x, gint *y) -{ - PangoLayout *layout; - PangoRectangle logical_rect; - gint area_width, area_height; - gint y_pos; - PangoLayoutLine *line; - - layout = seahorse_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 -seahorse_secure_entry_draw_text(SeahorseSecureEntry *entry) -{ - GtkWidget *widget; - PangoLayoutLine *line; - - if (entry->invisible_char == 0) - return; - - if (GTK_WIDGET_DRAWABLE (entry)) { - PangoLayout *layout = seahorse_secure_entry_ensure_layout (entry, TRUE); - gint x, y; - gint start_pos, end_pos; - - widget = GTK_WIDGET(entry); - - get_layout_position(entry, &x, &y); - - gdk_draw_layout(entry->text_area, widget->style->text_gc[widget->state], 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; - GdkRegion *clip_region = gdk_region_new (); - 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(entry)) { - selection_gc = widget->style->base_gc[GTK_STATE_SELECTED]; - text_gc = widget->style->text_gc[GTK_STATE_SELECTED]; - } else { - selection_gc = widget->style->base_gc[GTK_STATE_ACTIVE]; - text_gc = widget->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); - - gdk_region_union_with_rect(clip_region, &rect); - } - - 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); - - gdk_region_destroy(clip_region); - g_free(ranges); - } - } -} - -static void -draw_insertion_cursor (SeahorseSecureEntry *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 -seahorse_secure_entry_draw_cursor (SeahorseSecureEntry * entry) -{ - GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET(entry))); - PangoDirection keymap_direction = gdk_keymap_get_direction (keymap); - - if (GTK_WIDGET_DRAWABLE (entry)) { - GtkWidget *widget = GTK_WIDGET(entry); - 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); - - seahorse_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 -seahorse_secure_entry_queue_draw (SeahorseSecureEntry *entry) -{ - if (GTK_WIDGET_REALIZED (entry)) - gdk_window_invalidate_rect (entry->text_area, NULL, FALSE); -} - -static void -seahorse_secure_entry_reset_im_context (SeahorseSecureEntry *entry) -{ - if (entry->need_im_reset) { - entry->need_im_reset = 0; - gtk_im_context_reset (entry->im_context); - } -} - -static gint -seahorse_secure_entry_find_position (SeahorseSecureEntry *entry, gint x) -{ - PangoLayout *layout; - PangoLayoutLine *line; - gint _index; - gint pos; - gboolean trailing; - const gchar *text; - gint cursor_index; - - layout = seahorse_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 -seahorse_secure_entry_get_cursor_locations (SeahorseSecureEntry *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 = seahorse_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 -seahorse_secure_entry_adjust_scroll (SeahorseSecureEntry *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_REALIZED(entry)) - return; - - gdk_drawable_get_size (entry->text_area, &text_area_width, NULL); - text_area_width -= 2 * INNER_BORDER; - - layout = seahorse_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. - */ - - seahorse_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 -seahorse_secure_entry_move_visually (SeahorseSecureEntry * entry, - gint start, gint count) -{ - gint _index; - PangoLayout *layout = seahorse_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 -seahorse_secure_entry_move_logically (SeahorseSecureEntry *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 * -seahorse_secure_entry_new (void) -{ - return g_object_new (SEAHORSE_TYPE_SECURE_ENTRY, NULL); -} - -/** - * seahorse_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 #SeahorseSecureEntry 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 seahorse_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 #SeahorseSecureEntry. - **/ -GtkWidget * -seahorse_secure_entry_new_with_max_length (gint max) -{ - SeahorseSecureEntry *entry; - - max = CLAMP (max, 0, MAX_SIZE); - - entry = g_object_new (SEAHORSE_TYPE_SECURE_ENTRY, NULL); - entry->text_max_length = max; - - return GTK_WIDGET (entry); -} - -void -seahorse_secure_entry_set_text (SeahorseSecureEntry *entry, const gchar *text) -{ - gint tmp_pos; - - g_return_if_fail (SEAHORSE_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); -} - -void -seahorse_secure_entry_append_text (SeahorseSecureEntry *entry, const gchar *text) -{ - gint tmp_pos; - - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - g_return_if_fail (text != NULL); - - tmp_pos = entry->text_length; - gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos); -} - -void -seahorse_secure_entry_prepend_text (SeahorseSecureEntry *entry, const gchar *text) -{ - gint tmp_pos; - - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - g_return_if_fail (text != NULL); - - tmp_pos = 0; - gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos); -} - -void -seahorse_secure_entry_set_position(SeahorseSecureEntry *entry, gint position) -{ - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - - gtk_editable_set_position (GTK_EDITABLE (entry), position); -} - -void -seahorse_secure_entry_reset_changed (SeahorseSecureEntry *entry) -{ - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - entry->changed = FALSE; -} - -gboolean -seahorse_secure_entry_get_changed (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), FALSE); - return entry->changed; -} - -void -seahorse_secure_entry_set_visibility (SeahorseSecureEntry *entry, gboolean setting) -{ - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - - if (setting == entry->visibility) - return; - - entry->visibility = setting; - g_object_notify (G_OBJECT (entry), "visibility"); - seahorse_secure_entry_recompute (entry); -} - -gboolean -seahorse_secure_entry_get_visibility (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), FALSE); - return entry->visibility; -} - - -/** - * seahorse_secure_entry_set_invisible_char: - * @entry: a #SeahorseSecureEntry - * @ch: a Unicode character - * - * Sets the character to use in place of the actual text when - * seahorse_secure_entry_set_visibility() has been called to set text - * 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 -seahorse_secure_entry_set_invisible_char (SeahorseSecureEntry *entry, gunichar ch) -{ - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - - if (ch == entry->invisible_char) - return; - - entry->invisible_char = ch; - g_object_notify (G_OBJECT (entry), "invisible_char"); - seahorse_secure_entry_recompute (entry); -} - -/** - * seahorse_secure_entry_get_invisible_char: - * @entry: a #SeahorseSecureEntry - * - * Retrieves the character displayed in place of the real characters - * for entries with visisbility set to false. See seahorse_secure_entry_set_invisible_char(). - * - * Return value: the current invisible char, or 0, if the entry does not - * show invisible text at all. - **/ -gunichar -seahorse_secure_entry_get_invisible_char (SeahorseSecureEntry * entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), 0); - - return entry->invisible_char; -} - -/** - * seahorse_secure_entry_get_text: - * @entry: a #SeahorseSecureEntry - * - * 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* -seahorse_secure_entry_get_text (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), NULL); - - return entry->text; -} - -void -seahorse_secure_entry_select_region (SeahorseSecureEntry *entry, - gint start, gint end) -{ - gtk_editable_select_region (GTK_EDITABLE (entry), start, end); -} - -/** - * seahorse_secure_entry_set_max_length: - * @entry: a #SeahorseSecureEntry. - * @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 -seahorse_secure_entry_set_max_length(SeahorseSecureEntry *entry, gint max) -{ - g_return_if_fail (SEAHORSE_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"); -} - -/** - * seahorse_secure_entry_get_max_length: - * @entry: a #SeahorseSecureEntry - * - * Retrieves the maximum allowed length of the text in - * @entry. See seahorse_secure_entry_set_max_length(). - * - * Return value: the maximum allowed number of characters - * in #SeahorseSecureEntry, or 0 if there is no maximum. - **/ -gint -seahorse_secure_entry_get_max_length (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), 0); - return entry->text_max_length; -} - -/** - * seahorse_secure_entry_set_activates_default: - * @entry: a #SeahorseSecureEntry - * @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 -seahorse_secure_entry_set_activates_default (SeahorseSecureEntry *entry, - gboolean setting) -{ - g_return_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry)); - setting = setting != FALSE; - - if (setting != entry->activates_default) { - entry->activates_default = setting; - g_object_notify (G_OBJECT (entry), "activates_default"); - } -} - -/** - * seahorse_secure_entry_get_activates_default: - * @entry: a #SeahorseSecureEntry - * - * Retrieves the value set by seahorse_secure_entry_set_activates_default(). - * - * Return value: %TRUE if the entry will activate the default widget - **/ -gboolean -seahorse_secure_entry_get_activates_default (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), FALSE); - return entry->activates_default; -} - -/** - * seahorse_secure_entry_set_width_chars: - * @entry: a #SeahorseSecureEntry - * @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 -seahorse_secure_entry_set_width_chars (SeahorseSecureEntry *entry, gint n_chars) -{ - g_return_if_fail (SEAHORSE_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)); - } -} - -/** - * seahorse_secure_entry_get_width_chars: - * @entry: a #SeahorseSecureEntry - * - * Gets the value set by seahorse_secure_entry_set_width_chars(). - * - * Return value: number of chars to request space for, or negative if unset - **/ -gint -seahorse_secure_entry_get_width_chars (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), 0); - return entry->width_chars; -} - -/** - * seahorse_secure_entry_set_has_frame: - * @entry: a #SeahorseSecureEntry - * @setting: new value - * - * Sets whether the entry has a beveled frame around it. - **/ -void -seahorse_secure_entry_set_has_frame (SeahorseSecureEntry *entry, gboolean setting) -{ - g_return_if_fail (SEAHORSE_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"); -} - -/** - * seahorse_secure_entry_get_has_frame: - * @entry: a #SeahorseSecureEntry - * - * Gets the value set by seahorse_secure_entry_set_has_frame(). - * - * Return value: whether the entry has a beveled frame - **/ -gboolean -seahorse_secure_entry_get_has_frame (SeahorseSecureEntry *entry) -{ - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), FALSE); - return entry->has_frame; -} - - -/** - * seahorse_secure_entry_get_layout: - * @entry: a #SeahorseSecureEntry - * - * Gets the #PangoLayout used to display the entry. - * The layout is useful to e.g. convert text positions to - * pixel positions, in combination with seahorse_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 - * seahorse_secure_entry_layout_index_to_text_index() and - * seahorse_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 * -seahorse_secure_entry_get_layout (SeahorseSecureEntry *entry) -{ - PangoLayout *layout; - - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), NULL); - - layout = seahorse_secure_entry_ensure_layout (entry, TRUE); - - return layout; -} - - -/** - * seahorse_secure_entry_layout_index_to_text_index: - * @entry: a #SeahorseSecureEntry - * @layout_index: byte index into the entry layout text - * - * Converts from a position in the entry contents (returned - * by seahorse_secure_entry_get_text()) to a position in the - * entry's #PangoLayout (returned by seahorse_secure_entry_get_layout(), - * with text retrieved via pango_layout_get_text()). - * - * Return value: byte index into the entry contents - **/ -gint -seahorse_secure_entry_layout_index_to_text_index (SeahorseSecureEntry * entry, - gint layout_index) -{ - PangoLayout *layout; - const gchar *text; - gint cursor_index; - - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), 0); - - layout = seahorse_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; -} - -/** - * seahorse_secure_entry_text_index_to_layout_index: - * @entry: a #SeahorseSecureEntry - * @text_index: byte index into the entry contents - * - * Converts from a position in the entry's #PangoLayout(returned by - * seahorse_secure_entry_get_layout()) to a position in the entry contents - * (returned by seahorse_secure_entry_get_text()). - * - * Return value: byte index into the entry layout text - **/ -gint -seahorse_secure_entry_text_index_to_layout_index (SeahorseSecureEntry *entry, - gint text_index) -{ - PangoLayout *layout; - const gchar *text; - gint cursor_index; - g_return_val_if_fail (SEAHORSE_IS_SECURE_ENTRY (entry), 0); - - layout = seahorse_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; -} - -/** - * seahorse_secure_entry_get_layout_offsets: - * @entry: a #SeahorseSecureEntry - * @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 - * seahorse_secure_entry_layout_index_to_text_index() and - * seahorse_secure_entry_text_index_to_layout_index() are needed to convert byte - * indices in the layout to byte indices in the entry contents. - * - **/ -void -seahorse_secure_entry_get_layout_offsets (SeahorseSecureEntry *entry, - gint *x, gint *y) -{ - gint text_area_x, text_area_y; - - g_return_if_fail (SEAHORSE_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; -} - -#if UNUSED -/* Quick hack of a popup menu - */ -static void -activate_cb (GtkWidget *menuitem, SeahorseSecureEntry *entry) -{ - const gchar *signal = g_object_get_data(G_OBJECT(menuitem), "gtk-signal"); - g_signal_emit_by_name(entry, signal); -} -#endif - -static gboolean -seahorse_secure_entry_mnemonic_activate (GtkWidget *widget, gboolean group_cycling) -{ - gtk_widget_grab_focus (widget); - return TRUE; -} - -#if UNUSED -static void -unichar_chosen_func(const char *text, gpointer data) -{ - SeahorseSecureEntry *entry = SEAHORSE_SECURE_ENTRY(data); - seahorse_secure_entry_enter_text (entry, text); -} -#endif - -/* 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 (SeahorseSecureEntry *entry) -{ - GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry)); - gboolean blink; - - if (GTK_WIDGET_HAS_FOCUS (entry) && - 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 (SeahorseSecureEntry *entry) -{ - GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry)); - gint time; - - g_object_get (settings, "gtk-cursor-blink-time", &time, NULL); - - return time; -} - -static void -show_cursor (SeahorseSecureEntry *entry) -{ - if (!entry->cursor_visible) { - entry->cursor_visible = TRUE; - - if (GTK_WIDGET_HAS_FOCUS (entry) && - entry->selection_bound == entry->current_pos) - gtk_widget_queue_draw (GTK_WIDGET (entry)); - } -} - -static void -hide_cursor(SeahorseSecureEntry * entry) -{ - if (entry->cursor_visible) { - entry->cursor_visible = FALSE; - - if (GTK_WIDGET_HAS_FOCUS (entry) && - entry->selection_bound == entry->current_pos) - gtk_widget_queue_draw (GTK_WIDGET (entry)); - } -} - -/* - * Blink! - */ -static gint -blink_cb (gpointer data) -{ - SeahorseSecureEntry *entry; - - GDK_THREADS_ENTER (); - - entry = SEAHORSE_SECURE_ENTRY (data); - - if (!GTK_WIDGET_HAS_FOCUS (entry)) { - g_warning ("SeahorseSecureEntry - 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 (entry)); - 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 -seahorse_secure_entry_check_cursor_blink (SeahorseSecureEntry *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 -seahorse_secure_entry_pend_cursor_blink (SeahorseSecureEntry *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, - guint n_param_values, const GValue * param_values, - gpointer invocation_hint, 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, - guint n_param_values, const GValue * param_values, - gpointer invocation_hint, 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); -} diff --git a/libseahorse/seahorse-secure-entry.h b/libseahorse/seahorse-secure-entry.h deleted file mode 100644 index 2b87d93..0000000 --- a/libseahorse/seahorse-secure-entry.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * 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. - * - * (C) by Albrecht Dreß 2004 unter the terms of the GNU Lesser General - * Public License. - * - * 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. - */ - -#ifndef __SEAHORSE_SECURE_ENTRY_H__ -#define __SEAHORSE_SECURE_ENTRY_H__ - - -#include <gtk/gtk.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define SEAHORSE_TYPE_SECURE_ENTRY (seahorse_secure_entry_get_type ()) -#define SEAHORSE_SECURE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SECURE_ENTRY, SeahorseSecureEntry)) -#define SEAHORSE_SECURE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SECURE_ENTRY, SeahorseSecureEntryClass)) -#define SEAHORSE_IS_SECURE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SECURE_ENTRY)) -#define SEAHORSE_IS_SECURE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SECURE_ENTRY)) -#define SEAHORSE_SECURE_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SECURE_ENTRY, SeahorseSecureEntryClass)) - -typedef struct _SeahorseSecureEntry SeahorseSecureEntry; -typedef struct _SeahorseSecureEntryClass SeahorseSecureEntryClass; - -struct _SeahorseSecureEntry { - GtkWidget widget; - - gchar *text; - - guint overwrite_mode : 1; - - /* length in use, in chars */ - guint16 text_length; - guint16 text_max_length; - - /*< private > */ - GdkWindow *text_area; - GtkIMContext *im_context; - - gint current_pos; - gint selection_bound; - - PangoLayout *cached_layout; - guint cache_includes_preedit : 1; - - guint need_im_reset : 1; - - guint has_frame : 1; - - guint activates_default : 1; - - guint cursor_visible : 1; - - /* Flag so we don't select all when clicking in entry to focus in */ - guint in_click : 1; - - /* Only used by GtkCellRendererText */ - guint is_cell_renderer : 1; - guint editing_canceled : 1; - - guint mouse_cursor_obscured : 1; - - /* PangoDirection */ - guint resolved_dir : 4; - - guint button; - guint blink_timeout; - guint recompute_idle; - gint scroll_offset; - gint ascent; /* font ascent, in pango units */ - gint descent; /* font descent, in pango units */ - - guint16 text_size; /* allocated size, in bytes */ - guint16 n_bytes; /* length in use, in bytes */ - - guint16 preedit_length; /* length of preedit string, in bytes */ - guint16 preedit_cursor; /* offset of cursor within preedit string, in chars */ - - gunichar invisible_char; - gint width_chars; - - gboolean visibility; - - /* Keeps track of whether changed between resets */ - gboolean changed; -}; - -struct _SeahorseSecureEntryClass { - GtkWidgetClass parent_class; - - /* Action signals */ - void (*activate) (SeahorseSecureEntry *entry); - void (*move_cursor) (SeahorseSecureEntry *entry, GtkMovementStep step, - gint count, gboolean extend_selection); - void (*insert_at_cursor) (SeahorseSecureEntry *entry, const gchar *str); - void (*delete_from_cursor) (SeahorseSecureEntry *entry, GtkDeleteType type, gint count); - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - -GType seahorse_secure_entry_get_type (void) G_GNUC_CONST; - -GtkWidget* seahorse_secure_entry_new (void); - -void seahorse_secure_entry_reset_changed (SeahorseSecureEntry *entry); - -gboolean seahorse_secure_entry_get_changed (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_set_visibility (SeahorseSecureEntry *entry, gboolean setting); - -gboolean seahorse_secure_entry_get_visibility (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_set_invisible_char (SeahorseSecureEntry *entry, gunichar ch); - -gunichar seahorse_secure_entry_get_invisible_char (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_set_has_frame (SeahorseSecureEntry *entry, gboolean setting); - -gboolean seahorse_secure_entry_get_has_frame (SeahorseSecureEntry *entry); - -/* text is truncated if needed */ -void seahorse_secure_entry_set_max_length (SeahorseSecureEntry *entry, gint max); - -gint seahorse_secure_entry_get_max_length (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_set_activates_default (SeahorseSecureEntry *entry, gboolean setting); - -gboolean seahorse_secure_entry_get_activates_default (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_set_width_chars (SeahorseSecureEntry *entry, gint n_chars); - -gint seahorse_secure_entry_get_width_chars (SeahorseSecureEntry *entry); - -/* Somewhat more convenient than the GtkEditable generic functions */ -void seahorse_secure_entry_set_text (SeahorseSecureEntry *entry, const gchar *text); - -/* returns a reference to the text */ -const gchar* seahorse_secure_entry_get_text (SeahorseSecureEntry *entry); - -PangoLayout* seahorse_secure_entry_get_layout (SeahorseSecureEntry *entry); - -void seahorse_secure_entry_get_layout_offsets (SeahorseSecureEntry *entry, gint *x, gint *y); - -#ifdef __cplusplus -} -#endif - -#endif /*__SEAHORSE_SECURE_ENTRY_H__ */ |