Bug 796761 - Control characters can be pasted in register fields

If copied text includes control characters they are inserted when
pasted which can cause alignment issues. This commit filters the
clipboard text for control characters before it is pasted.
This commit is contained in:
Robert Fewell 2021-04-05 14:32:48 +01:00
parent ec9cdd151d
commit d55060c0fc
3 changed files with 111 additions and 1 deletions

View File

@ -40,6 +40,7 @@
#include "gnucash-sheetP.h"
#include "gnucash-style.h"
#include "gnc-ui-util.h"
/* The arguments we take */
enum
@ -398,7 +399,43 @@ gnc_item_edit_copy_clipboard (GncItemEdit *item_edit)
void
gnc_item_edit_paste_clipboard (GncItemEdit *item_edit)
{
gtk_editable_paste_clipboard(GTK_EDITABLE(item_edit->editor));
GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET(item_edit->editor),
GDK_SELECTION_CLIPBOARD);
gchar *text = gtk_clipboard_wait_for_text (clipboard);
gchar *filtered_text;
gint start_pos, end_pos;
gint position;
if (!text)
return;
filtered_text = gnc_filter_text_for_control_chars (text);
if (!filtered_text)
{
g_free (text);
return;
}
position = gtk_editable_get_position (GTK_EDITABLE(item_edit->editor));
if (gtk_editable_get_selection_bounds (GTK_EDITABLE(item_edit->editor),
&start_pos, &end_pos))
{
position = start_pos;
gtk_editable_delete_selection (GTK_EDITABLE(item_edit->editor));
gtk_editable_insert_text (GTK_EDITABLE(item_edit->editor),
filtered_text, -1, &position);
}
else
gtk_editable_insert_text (GTK_EDITABLE(item_edit->editor),
filtered_text, -1, &position);
gtk_editable_set_position (GTK_EDITABLE(item_edit->editor), position);
g_free (text);
g_free (filtered_text);
}

View File

@ -2663,3 +2663,67 @@ gnc_ui_util_remove_registered_prefs (void)
GNC_PREF_AUTO_DECIMAL_PLACES,
gnc_set_auto_decimal_places, NULL);
}
static gboolean
unichar_is_cntrl (gunichar uc)
{
if (uc < 0x20 || (uc > 0x7e && uc < 0xa0))
return TRUE;
else
return FALSE;
}
gchar *
gnc_filter_text_for_control_chars (const gchar *text)
{
gchar *normal_text, *nt;
GString *filtered;
gboolean cntrl = FALSE;
gboolean text_found = FALSE;
if (!text)
return NULL;
if (!g_utf8_validate (text, -1, NULL))
return NULL;
normal_text = g_utf8_normalize (text, -1, G_NORMALIZE_ALL_COMPOSE);
filtered = g_string_sized_new (strlen (normal_text) + 1);
nt = normal_text;
while (*nt)
{
gunichar uc = g_utf8_get_char (nt);
// check for starting with control characters
if (unichar_is_cntrl (uc) && !text_found)
{
nt = g_utf8_next_char (nt);
continue;
}
// check for alpha, num and punctuation
if (!unichar_is_cntrl (uc))
{
filtered = g_string_append_unichar (filtered, uc);
text_found = TRUE;
}
// check for control characters after text
if (unichar_is_cntrl (uc))
cntrl = TRUE;
nt = g_utf8_next_char (nt);
if (cntrl) // if control characters in text replace with space
{
gunichar uc2 = g_utf8_get_char (nt);
if (!unichar_is_cntrl (uc2))
filtered = g_string_append_unichar (filtered, ' ');
}
cntrl = FALSE;
}
g_free (normal_text);
return g_string_free (filtered, FALSE);
}

View File

@ -397,6 +397,15 @@ void gnc_ui_util_init (void);
void gnc_ui_util_remove_registered_prefs (void);
/** Returns the incoming text removed of control characters
*
* @param incoming_text The text to filter
*
* @return The incoming text filtered of control characters to be
* freed by the caller.
*/
gchar * gnc_filter_text_for_control_chars (const gchar *incoming_text);
#endif
/** @} */
/** @} */