[gtk/wip/compose-parser: 3/3] composetable: Rewrite Compose files if necessary
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/compose-parser: 3/3] composetable: Rewrite Compose files if necessary
- Date: Thu, 15 Jul 2021 13:30:58 +0000 (UTC)
commit 87e2a02e0c69cec7c04a48265761da13b99c9a2b
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Jul 14 07:38:32 2021 -0400
composetable: Rewrite Compose files if necessary
Apply heuristics to avoid breaking users existing configurations
with the change to not always add the default sequences.
If we find a cache that was generated before 4.4, and the Compose
file does not have an include, and doesn't contain so many sequences
that it is probably a copy of the system one, we take steps to keep
things working, and thell the user about it.
gtk/compose/compose-parse.c | 2 +-
gtk/gtkcomposetable.c | 122 +++++++++++++++++++++++++++++++++++++++----
gtk/gtkcomposetable.h | 3 +-
testsuite/gtk/composetable.c | 10 ++--
4 files changed, 119 insertions(+), 18 deletions(-)
---
diff --git a/gtk/compose/compose-parse.c b/gtk/compose/compose-parse.c
index 55e9331f3e..e80b270453 100644
--- a/gtk/compose/compose-parse.c
+++ b/gtk/compose/compose-parse.c
@@ -26,7 +26,7 @@ main (int argc, char *argv[])
exit (1);
}
- table = gtk_compose_table_parse (argv[1]);
+ table = gtk_compose_table_parse (argv[1], NULL);
if (!table)
g_error ("Failed to parse %s", argv[1]);
diff --git a/gtk/gtkcomposetable.c b/gtk/gtkcomposetable.c
index 39ca2e3e92..c95b153e6f 100644
--- a/gtk/gtkcomposetable.c
+++ b/gtk/gtkcomposetable.c
@@ -83,6 +83,7 @@ typedef struct {
GHashTable *sequences;
GList *files;
const char *compose_file;
+ gboolean found_include;
} GtkComposeParser;
static GtkComposeParser *
@@ -95,6 +96,7 @@ parser_new (void)
parser->sequences = g_hash_table_new_full (sequence_hash, sequence_equal, g_free, g_free);
parser->files = NULL;
parser->compose_file = NULL;
+ parser->found_include = FALSE;
return parser;
}
@@ -357,6 +359,8 @@ parser_handle_include (GtkComposeParser *parser,
const char *start, *end;
char *path;
+ parser->found_include = TRUE;
+
p = line + strlen ("include ");
while (g_ascii_isspace (*p))
@@ -719,7 +723,8 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
}
static GtkComposeTable *
-gtk_compose_table_load_cache (const char *compose_file)
+gtk_compose_table_load_cache (const char *compose_file,
+ gboolean *found_old_cache)
{
guint32 hash;
char *path = NULL;
@@ -740,6 +745,8 @@ gtk_compose_table_load_cache (const char *compose_file)
char *char_data = NULL;
GtkComposeTable *retval;
+ *found_old_cache = FALSE;
+
hash = g_str_hash (compose_file);
if ((path = gtk_compose_hash_get_cache_path (hash)) == NULL)
return NULL;
@@ -780,8 +787,8 @@ gtk_compose_table_load_cache (const char *compose_file)
GET_GUINT16 (version);
if (version != GTK_COMPOSE_TABLE_VERSION)
{
- g_warning ("cache version is different %u != %u",
- version, GTK_COMPOSE_TABLE_VERSION);
+ if (version < GTK_COMPOSE_TABLE_VERSION)
+ *found_old_cache = TRUE;
goto out_load_cache;
}
@@ -993,15 +1000,15 @@ parser_get_compose_table (GtkComposeParser *parser)
}
static char *
-canonicalize_filename (GtkComposeParser *parser,
- const char *path)
+canonicalize_filename (const char *parent_path,
+ const char *path)
{
GFile *file;
char *retval;
- if (path[0] != '/' && parser->compose_file)
+ if (path[0] != '/' && parent_path)
{
- GFile *orig = g_file_new_for_path (parser->compose_file);
+ GFile *orig = g_file_new_for_path (parent_path);
GFile *parent = g_file_get_parent (orig);
file = g_file_resolve_relative_path (parent, path);
g_object_unref (parent);
@@ -1029,7 +1036,7 @@ parser_parse_file (GtkComposeParser *parser,
if (parser->compose_file == NULL)
parser->compose_file = compose_file;
- path = canonicalize_filename (parser, compose_file);
+ path = canonicalize_filename (parser->compose_file, compose_file);
if (g_list_find_custom (parser->files, path, (GCompareFunc)strcmp))
{
@@ -1046,7 +1053,8 @@ parser_parse_file (GtkComposeParser *parser,
}
GtkComposeTable *
-gtk_compose_table_parse (const char *compose_file)
+gtk_compose_table_parse (const char *compose_file,
+ gboolean *found_include)
{
GtkComposeParser *parser;
GtkComposeTable *compose_table;
@@ -1054,23 +1062,115 @@ gtk_compose_table_parse (const char *compose_file)
parser = parser_new ();
parser_parse_file (parser, compose_file);
compose_table = parser_get_compose_table (parser);
+ if (found_include)
+ *found_include = parser->found_include;
parser_free (parser);
return compose_table;
}
+static const char *prefix =
+ "# GTK has rewritten this file to add the line:\n"
+ "\n"
+ "include \"%L\"\n"
+ "\n"
+ "# This is necessary to add your own Compose sequences\n"
+ "# in addition to the builtin sequences of GTK. If this\n"
+ "# is not what you want, just remove that line.\n"
+ "#\n"
+ "# A backup of the previous file contents has been made.\n"
+ "\n"
+ "\n";
+
+static gboolean
+rewrite_compose_file (const char *compose_file)
+{
+ char *path = NULL;
+ char *content = NULL;
+ gsize content_len;
+ GFile *file = NULL;
+ GOutputStream *stream = NULL;
+ gboolean ret = FALSE;
+
+ path = canonicalize_filename (NULL, compose_file);
+
+ if (!g_file_get_contents (path, &content, &content_len, NULL))
+ goto out;
+
+ file = g_file_new_for_path (path);
+ stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, TRUE, 0, NULL, NULL));
+
+ if (stream == NULL)
+ goto out;
+
+ if (!g_output_stream_write (stream, prefix, strlen (prefix), NULL, NULL))
+ goto out;
+
+ if (!g_output_stream_write (stream, content, content_len, NULL, NULL))
+ goto out;
+
+ if (!g_output_stream_close (stream, NULL, NULL))
+ goto out;
+
+ ret = TRUE;
+
+out:
+ g_clear_object (&stream);
+ g_clear_object (&file);
+ g_clear_pointer (&path, g_free);
+ g_clear_pointer (&content, g_free);
+
+ return ret;
+}
+
GtkComposeTable *
gtk_compose_table_new_with_file (const char *compose_file)
{
GtkComposeTable *compose_table;
+ gboolean found_old_cache = FALSE;
+ gboolean found_include = FALSE;
g_assert (compose_file != NULL);
- compose_table = gtk_compose_table_load_cache (compose_file);
+ compose_table = gtk_compose_table_load_cache (compose_file, &found_old_cache);
if (compose_table != NULL)
return compose_table;
- compose_table = gtk_compose_table_parse (compose_file);
+parse:
+ compose_table = gtk_compose_table_parse (compose_file, &found_include);
+
+ /* This is where we apply heuristics to avoid breaking users existing configurations
+ * with the change to not always add the default sequences.
+ *
+ * If we find a cache that was generated before 4.4, and the Compose file
+ * does not have an include, and doesn't contain so many sequences that it
+ * is probably a copy of the system one, we take steps to keep things working,
+ * and thell the user about it.
+ */
+ if (found_old_cache && !found_include && compose_table->n_sequences < 100)
+ {
+ if (rewrite_compose_file (compose_file))
+ {
+ g_warning ("\nSince GTK 4.4, Compose files replace the builtin\n"
+ "compose sequences. To keep them and add your own\n"
+ "sequences on top, the line:\n"
+ "\n"
+ " include \"%%L\"\n"
+ "\n"
+ "has been added to the Compose file\n%s.\n", compose_file);
+ goto parse;
+ }
+ else
+ {
+ g_warning ("\nSince GTK 4.4, Compose files replace the builtin\n"
+ "compose sequences. To keep them and add your own\n"
+ "sequences on top, you need to add the line:\n"
+ "\n"
+ " include \"%%L\"\n"
+ "\n"
+ "to the Compose file\n%s.\n", compose_file);
+ }
+ }
if (compose_table != NULL)
gtk_compose_table_save_cache (compose_table);
diff --git a/gtk/gtkcomposetable.h b/gtk/gtkcomposetable.h
index 7a4c952f33..1398559a66 100644
--- a/gtk/gtkcomposetable.h
+++ b/gtk/gtkcomposetable.h
@@ -58,7 +58,8 @@ struct _GtkComposeTable
};
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
-GtkComposeTable * gtk_compose_table_parse (const char *compose_file);
+GtkComposeTable * gtk_compose_table_parse (const char *compose_file,
+ gboolean *found_include);
GtkComposeTable * gtk_compose_table_new_with_data (const guint16 *data,
int max_seq_len,
int n_seqs);
diff --git a/testsuite/gtk/composetable.c b/testsuite/gtk/composetable.c
index 9c3a4a6142..1a77e5bc93 100644
--- a/testsuite/gtk/composetable.c
+++ b/testsuite/gtk/composetable.c
@@ -84,7 +84,7 @@ generate_output (const char *file)
GtkComposeTable *table;
char *output;
- table = gtk_compose_table_parse (file);
+ table = gtk_compose_table_parse (file, NULL);
output = gtk_compose_table_print (table);
g_print ("%s", output);
@@ -104,7 +104,7 @@ compose_table_compare (gconstpointer data)
file = g_test_build_filename (G_TEST_DIST, "compose", basename, NULL);
expected = g_strconcat (file, ".expected", NULL);
- table = gtk_compose_table_parse (file);
+ table = gtk_compose_table_parse (file, NULL);
output = gtk_compose_table_print (table);
diff = diff_with_file (expected, output, -1, &error);
@@ -131,7 +131,7 @@ compose_table_cycle (void)
file = g_test_build_filename (G_TEST_DIST, "compose", "cycle", NULL);
- table = gtk_compose_table_parse (file);
+ table = gtk_compose_table_parse (file, NULL);
g_assert_nonnull (table);
g_free (file);
@@ -153,7 +153,7 @@ compose_table_nofile (void)
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "nofile", NULL);
- table = gtk_compose_table_parse (file);
+ table = gtk_compose_table_parse (file, NULL);
g_assert_nonnull (table);
g_free (file);
@@ -179,7 +179,7 @@ compose_table_match (void)
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "match", NULL);
- table = gtk_compose_table_parse (file);
+ table = gtk_compose_table_parse (file, NULL);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]