+} // namespace
+
+/*
+ *-------------------------------------------------------------------
+ * init
+ *-------------------------------------------------------------------
+ */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+void bar_pane_keywords_close_unused(GtkWidget *bar)
+{
+ PaneKeywordsData *pkd;
+
+ pkd = static_cast<PaneKeywordsData *>(g_object_get_data(G_OBJECT(bar), "pane_data"));
+ if (!pkd) return;
+
+ g_free(pkd->pane.id);
+ g_object_unref(pkd->widget);
+}
+#pragma GCC diagnostic pop
+
+GtkWidget *bar_pane_keywords_new_from_config(const gchar **attribute_names, const gchar **attribute_values)
+{
+ gchar *id = g_strdup("keywords");
+ gchar *title = nullptr;
+ gchar *key = g_strdup(COMMENT_KEY);
+ gboolean expanded = TRUE;
+ gint height = 200;
+ GtkWidget *ret;
+
+ while (*attribute_names)
+ {
+ const gchar *option = *attribute_names++;
+ const gchar *value = *attribute_values++;
+
+ if (READ_CHAR_FULL("id", id)) continue;
+ if (READ_CHAR_FULL("title", title)) continue;
+ if (READ_CHAR_FULL("key", key)) continue;
+ if (READ_BOOL_FULL("expanded", expanded)) continue;
+ if (READ_INT_FULL("height", height)) continue;
+
+
+ log_printf("unknown attribute %s = %s\n", option, value);
+ }
+
+ options->info_keywords.height = height;
+ bar_pane_translate_title(PANE_KEYWORDS, id, &title);
+ ret = bar_pane_keywords_new(id, title, key, expanded, height);
+ g_free(id);
+ g_free(title);
+ g_free(key);
+ return ret;
+}
+
+void bar_pane_keywords_update_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values)
+{
+ PaneKeywordsData *pkd;
+
+ pkd = static_cast<PaneKeywordsData *>(g_object_get_data(G_OBJECT(pane), "pane_data"));
+ if (!pkd) return;
+
+ gchar *title = nullptr;
+
+ while (*attribute_names)
+ {
+ const gchar *option = *attribute_names++;
+ const gchar *value = *attribute_values++;
+
+ if (READ_CHAR_FULL("title", title)) continue;
+ if (READ_CHAR_FULL("key", pkd->key)) continue;
+ if (READ_BOOL_FULL("expanded", pkd->pane.expanded)) continue;
+ if (READ_CHAR_FULL("id", pkd->pane.id)) continue;
+
+
+ log_printf("unknown attribute %s = %s\n", option, value);
+ }
+
+ if (title)
+ {
+ bar_pane_translate_title(PANE_KEYWORDS, pkd->pane.id, &title);
+ gtk_label_set_text(GTK_LABEL(pkd->pane.title), title);
+ g_free(title);
+ }
+
+ bar_update_expander(pane);
+ bar_pane_keywords_update(pkd);
+}
+
+
+void bar_pane_keywords_entry_add_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values)
+{
+ PaneKeywordsData *pkd;
+ gchar *path = nullptr;
+ GtkTreePath *tree_path;
+
+ pkd = static_cast<PaneKeywordsData *>(g_object_get_data(G_OBJECT(pane), "pane_data"));
+ if (!pkd) return;
+
+ while (*attribute_names)
+ {
+ const gchar *option = *attribute_names++;
+ const gchar *value = *attribute_values++;
+
+ if (READ_CHAR_FULL("path", path))
+ {
+ tree_path = gtk_tree_path_new_from_string(path);
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(pkd->keyword_treeview), tree_path);
+ gtk_tree_path_free(tree_path);
+ pkd->expanded_rows = g_list_append(pkd->expanded_rows, g_strdup(path));
+ continue;
+ }
+ log_printf("unknown attribute %s = %s\n", option, value);
+ }
+}
+
+/*
+ *-------------------------------------------------------------------
+ * keyword / comment utils
+ *-------------------------------------------------------------------
+ */
+
+GList *keyword_list_pull(GtkWidget *text_widget)
+{
+ GList *list;
+ gchar *text;
+
+ text = text_widget_text_pull(text_widget);
+ list = string_to_keywords_list(text);
+
+ g_free(text);
+
+ return list;
+}
+