From ef9294aae23c3f791e1bbd8354d3006ad353d936 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 00:00:51 -0800 Subject: [PATCH 01/18] Pull upstream fixes for gtk and gtksourceview changes * fix errors in xed-metadata-manager * upstream changes for file loading and saving * modernize some code in xed-document Closes https://github.com/linuxmint/xed/issues/146 --- configure.ac | 4 +- xed/Makefile.am | 11 +- xed/xed-close-confirmation-dialog.c | 5 +- xed/xed-commands-file.c | 588 +++++++++++------- xed/xed-commands.h | 2 + xed/xed-document-private.h | 21 + xed/xed-document.c | 895 +++++++++++++++------------- xed/xed-document.h | 41 +- xed/xed-metadata-manager.c | 608 +++++++++---------- xed/xed-metadata-manager.h | 2 +- xed/xed-tab.c | 30 +- xed/xed-window.c | 2 + 12 files changed, 1200 insertions(+), 1009 deletions(-) create mode 100644 xed/xed-document-private.h diff --git a/configure.ac b/configure.ac index fe8d570..90d461b 100644 --- a/configure.ac +++ b/configure.ac @@ -149,8 +149,8 @@ PKG_CHECK_MODULES(XED, [ $GMODULE_ADD gthread-2.0 >= 2.13.0 gio-2.0 >= 2.40.0 - gtk+-3.0 >= 3.18.0 - gtksourceview-3.0 >= 3.18.0 + gtk+-3.0 >= 3.19.3 + gtksourceview-3.0 >= 3.19.0 libpeas-1.0 >= 1.12.0 libpeas-gtk-1.0 >= 1.12.0 ]) diff --git a/xed/Makefile.am b/xed/Makefile.am index bbaec9c..763df73 100644 --- a/xed/Makefile.am +++ b/xed/Makefile.am @@ -40,10 +40,12 @@ NOINST_H_FILES = \ xed-close-button.h \ xed-close-confirmation-dialog.h \ xed-dirs.h \ + xed-document-private.h \ xed-documents-panel.h \ xed-encodings-dialog.h \ xed-history-entry.h \ xed-io-error-info-bar.h \ + xed-metadata-manager.h \ xed-paned.h \ xed-plugins-engine.h \ xed-preferences-dialog.h \ @@ -80,10 +82,6 @@ INST_H_FILES = \ xed-window.h \ xed-window-activatable.h -if !ENABLE_GVFS_METADATA -NOINST_H_FILES += xed-metadata-manager.h -endif - headerdir = $(prefix)/include/xed header_DATA = \ @@ -119,6 +117,7 @@ libxed_c_files = \ xed-message-bus.c \ xed-message-type.c \ xed-message.c \ + xed-metadata-manager.c \ xed-notebook.c \ xed-paned.c \ xed-panel.c \ @@ -146,10 +145,6 @@ libxed_la_SOURCES = \ $(NOINST_H_FILES) \ $(INST_H_FILES) -if !ENABLE_GVFS_METADATA -libxed_la_SOURCES += xed-metadata-manager.c -endif - xed-enum-types.h: xed-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS) $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xed-enum-types.h.template $(INST_H_FILES)) > $@ diff --git a/xed/xed-close-confirmation-dialog.c b/xed/xed-close-confirmation-dialog.c index e667ad5..b72f16e 100755 --- a/xed/xed-close-confirmation-dialog.c +++ b/xed/xed-close-confirmation-dialog.c @@ -32,10 +32,13 @@ #include #endif +#include "xed-close-confirmation-dialog.h" + #include -#include "xed-close-confirmation-dialog.h" #include +#include +#include #include #include diff --git a/xed/xed-commands-file.c b/xed/xed-commands-file.c index 2323cab..098dcb4 100644 --- a/xed/xed-commands-file.c +++ b/xed/xed-commands-file.c @@ -38,31 +38,27 @@ #include #include +#include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-commands.h" #include "xed-window.h" #include "xed-window-private.h" #include "xed-statusbar.h" -#include "xed-debug.h" #include "xed-utils.h" #include "xed-file-chooser-dialog.h" #include "xed-close-confirmation-dialog.h" /* Defined constants */ #define XED_OPEN_DIALOG_KEY "xed-open-dialog-key" -#define XED_TAB_TO_SAVE_AS "xed-tab-to-save-as" -#define XED_LIST_OF_TABS_TO_SAVE_AS "xed-list-of-tabs-to-save-as" #define XED_IS_CLOSING_ALL "xed-is-closing-all" #define XED_IS_QUITTING "xed-is-quitting" -#define XED_IS_CLOSING_TAB "xed-is-closing-tab" #define XED_IS_QUITTING_ALL "xed-is-quitting-all" static void tab_state_changed_while_saving (XedTab *tab, GParamSpec *pspec, XedWindow *window); -static void save_as_tab (XedTab *tab, - XedWindow *window); - void _xed_cmd_file_new (GtkAction *action, XedWindow *window) @@ -521,110 +517,73 @@ replace_read_only_file (GtkWindow *parent, } static void -save_finish_cb (XedTab *tab, - GAsyncResult *result, - gpointer user_data) +tab_save_as_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) { - _xed_tab_save_finish (tab, result); + gboolean success = _xed_tab_save_finish (tab, result); + g_task_return_boolean (task, success); + g_object_unref (task); } static void save_dialog_response_cb (XedFileChooserDialog *dialog, gint response_id, - XedWindow *window) + GTask *task) { XedTab *tab; - gpointer data; - GSList *tabs_to_save_as; + XedWindow *window; + XedDocument *doc; + GtkSourceFile *file; + GFile *location; + gchar *parse_name; + GtkSourceNewlineType newline_type; + const GtkSourceEncoding *encoding; xed_debug (DEBUG_COMMANDS); - tab = XED_TAB (g_object_get_data (G_OBJECT (dialog), XED_TAB_TO_SAVE_AS)); + tab = g_task_get_source_object (task); + window = g_task_get_task_data (task); if (response_id != GTK_RESPONSE_OK) { gtk_widget_destroy (GTK_WIDGET (dialog)); - goto save_next_tab; - } - - if (tab != NULL) - { - GFile *location; - XedDocument *doc; - gchar *parse_name; - GtkSourceNewlineType newline_type; - const GtkSourceEncoding *encoding; - - doc = xed_tab_get_document (tab); - - location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); - g_return_if_fail (location != NULL); - - encoding = xed_file_chooser_dialog_get_encoding (dialog); - newline_type = xed_file_chooser_dialog_get_newline_type (dialog); - - gtk_widget_destroy (GTK_WIDGET (dialog)); - - doc = xed_tab_get_document (tab); - g_return_if_fail (XED_IS_DOCUMENT (doc)); - - parse_name = g_file_get_parse_name (location); - - xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), - window->priv->generic_message_cid, - _("Saving file '%s'\342\200\246"), - parse_name); - - g_free (parse_name); - - /* let's remember the dir we navigated too, - * even if the saving fails... */ - _xed_window_set_default_location (window, location); - - _xed_tab_save_as_async (tab, - location, - encoding, - newline_type, - NULL, - (GAsyncReadyCallback) save_finish_cb, - NULL); - - g_object_unref (location); - } - -save_next_tab: - - data = g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS); - if (data == NULL) - { + g_task_return_boolean (task, FALSE); + g_object_unref (task); return; } - /* Save As the next tab of the list (we are Saving All files) */ - tabs_to_save_as = (GSList *)data; - g_return_if_fail (tab == XED_TAB (tabs_to_save_as->data)); + doc = xed_tab_get_document (tab); + location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); + g_return_if_fail (location != NULL); - /* Remove the first item of the list */ - tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, tabs_to_save_as); + encoding = xed_file_chooser_dialog_get_encoding (dialog); + newline_type = xed_file_chooser_dialog_get_newline_type (dialog); - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); + gtk_widget_destroy (GTK_WIDGET (dialog)); - if (tabs_to_save_as != NULL) - { - tab = XED_TAB (tabs_to_save_as->data); + parse_name = g_file_get_parse_name (location); - if (GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (tab), XED_IS_CLOSING_TAB)) == TRUE) - { - g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL); + xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Saving file '%s'\342\200\246"), + parse_name); - /* Trace tab state changes */ - g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window); - } + g_free (parse_name); - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); - } + /* let's remember the dir we navigated too, even if the saving fails... */ + _xed_window_set_default_location (window, location); + + _xed_tab_save_as_async (tab, + location, + encoding, + newline_type, + g_task_get_cancellable (task), + (GAsyncReadyCallback) tab_save_as_ready_cb, + task); + + g_object_unref (location); } static GtkFileChooserConfirmation @@ -663,16 +622,20 @@ confirm_overwrite_callback (GtkFileChooser *dialog, return res; } +/* Call save_as_tab_finish() in @callback. */ static void -save_as_tab (XedTab *tab, - XedWindow *window) +save_as_tab_async (XedTab *tab, + XedWindow *window, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + GTask *task; GtkWidget *save_dialog; GtkWindowGroup *wg; XedDocument *doc; GtkSourceFile *file; GFile *location; - gboolean uri_set = FALSE; const GtkSourceEncoding *encoding; GtkSourceNewlineType newline_type; @@ -681,6 +644,9 @@ save_as_tab (XedTab *tab, xed_debug (DEBUG_COMMANDS); + task = g_task_new (tab, cancellable, callback, user_data); + g_task_set_task_data (task, g_object_ref (window), g_object_unref); + save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"), GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_SAVE, @@ -706,11 +672,11 @@ save_as_tab (XedTab *tab, if (location != NULL) { - uri_set = gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL); + gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL); } - if (!uri_set) + else { GFile *default_path; gchar *docname; @@ -734,7 +700,7 @@ save_as_tab (XedTab *tab, g_free (docname); } - /* Set suggested encoding */ + /* Set suggested encoding and newline type */ encoding = gtk_source_file_get_encoding (file); if (encoding == NULL) @@ -748,39 +714,94 @@ save_as_tab (XedTab *tab, xed_file_chooser_dialog_set_newline_type (XED_FILE_CHOOSER_DIALOG (save_dialog), newline_type); - g_object_set_data (G_OBJECT (save_dialog), XED_TAB_TO_SAVE_AS, tab); - - g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), window); + g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), task); gtk_widget_show (save_dialog); } -static void -save_tab (XedTab *tab, - XedWindow *window) +static gboolean +save_as_tab_finish (XedTab *tab, + GAsyncResult *result) { - XedDocument *doc; + g_return_val_if_fail (g_task_is_valid (result, tab), FALSE); + + return g_task_propagate_boolean (G_TASK (result), NULL); +} + +static void +save_as_tab_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) +{ + gboolean success = save_as_tab_finish (tab, result); + + g_task_return_boolean (task, success); + g_object_unref (task); +} + +static void +tab_save_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) +{ + gboolean success = _xed_tab_save_finish (tab, result); + + g_task_return_boolean (task, success); + g_object_unref (task); +} + +/** + * xed_commands_save_document_async: + * @document: the #XedDocument to save. + * @window: a #XedWindow. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the operation + * is finished. + * @user_data: (closure): the data to pass to the @callback function. + * + * Asynchronously save the @document. @document must belong to @window. The + * source object of the async task is @document (which will be the first + * parameter of the #GAsyncReadyCallback). + * + * When the operation is finished, @callback will be called. You can then call + * xed_commands_save_document_finish() to get the result of the operation. + */ +void +xed_commands_save_document_async (XedDocument *document, + XedWindow *window, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + XedTab *tab; gchar *uri_for_display; xed_debug (DEBUG_COMMANDS); - g_return_if_fail (XED_IS_TAB (tab)); + g_return_if_fail (XED_IS_DOCUMENT (document)); g_return_if_fail (XED_IS_WINDOW (window)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); - doc = xed_tab_get_document (tab); - g_return_if_fail (XED_IS_DOCUMENT (doc)); + task = g_task_new (document, cancellable, callback, user_data); - if (xed_document_is_untitled (doc) || - xed_document_get_readonly (doc)) + tab = xed_tab_get_from_document (document); + + if (xed_document_is_untitled (document) || + xed_document_get_readonly (document)) { xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly"); - save_as_tab (tab, window); + save_as_tab_async (tab, + window, + cancellable, + (GAsyncReadyCallback) save_as_tab_ready_cb, + task); return; } - uri_for_display = xed_document_get_uri_for_display (doc); + uri_for_display = xed_document_get_uri_for_display (document); xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), window->priv->generic_message_cid, _("Saving file '%s'\342\200\246"), @@ -789,9 +810,53 @@ save_tab (XedTab *tab, g_free (uri_for_display); _xed_tab_save_async (tab, - NULL, - (GAsyncReadyCallback) save_finish_cb, - NULL); + cancellable, + (GAsyncReadyCallback) tab_save_ready_cb, + task); +} + +/** + * xed_commands_save_document_finish: + * @document: a #XedDocument. + * @result: a #GAsyncResult. + * + * Finishes an asynchronous document saving operation started with + * xed_commands_save_document_async(). + * + * Note that there is no error parameter because the errors are already handled + * by xed. + * + * Returns: %TRUE if the document has been correctly saved, %FALSE otherwise. + */ +gboolean +xed_commands_save_document_finish (XedDocument *document, + GAsyncResult *result) +{ + g_return_val_if_fail (g_task_is_valid (result, document), FALSE); + + return g_task_propagate_boolean (G_TASK (result), NULL); +} + +static void +save_tab_ready_cb (XedDocument *doc, + GAsyncResult *result, + gpointer user_data) +{ + xed_commands_save_document_finish (doc, result); +} + +/* Save tab asynchronously, but without results. */ +static void +save_tab (XedTab *tab, + XedWindow *window) +{ + XedDocument *doc = xed_tab_get_document (tab); + + xed_commands_save_document_async (doc, + window, + NULL, + (GAsyncReadyCallback) save_tab_ready_cb, + NULL); } void @@ -803,12 +868,18 @@ _xed_cmd_file_save (GtkAction *action, xed_debug (DEBUG_COMMANDS); tab = xed_window_get_active_tab (window); - if (tab == NULL) + if (tab != NULL) { - return; + save_tab (tab, window); } +} - save_tab (tab, window); +static void +_xed_cmd_file_save_as_cb (XedTab *tab, + GAsyncResult *result, + gpointer user_data) +{ + save_as_tab_finish (tab, result); } void @@ -820,12 +891,149 @@ _xed_cmd_file_save_as (GtkAction *action, xed_debug (DEBUG_COMMANDS); tab = xed_window_get_active_tab (window); - if (tab == NULL) + if (tab != NULL) + { + save_as_tab_async (tab, + window, + NULL, + (GAsyncReadyCallback) _xed_cmd_file_save_as_cb, + NULL); + } +} + +static void +quit_if_needed (XedWindow *window) +{ + gboolean is_quitting; + gboolean is_quitting_all; + + is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING)); + + is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING_ALL)); + + if (is_quitting) + { + gtk_widget_destroy (GTK_WIDGET (window)); + } + + if (is_quitting_all) + { + GtkApplication *app; + + app = GTK_APPLICATION (g_application_get_default ()); + + if (gtk_application_get_windows (app) == NULL) + { + g_application_quit (G_APPLICATION (app)); + } + } +} + +static gboolean +really_close_tab (XedTab *tab) +{ + GtkWidget *toplevel; + XedWindow *window; + + xed_debug (DEBUG_COMMANDS); + + g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab)); + g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE); + + window = XED_WINDOW (toplevel); + + xed_window_close_tab (window, tab); + + if (xed_window_get_active_tab (window) == NULL) + { + quit_if_needed (window); + } + + return FALSE; +} + +static void +close_tab (XedTab *tab) +{ + XedDocument *doc; + + doc = xed_tab_get_document (tab); + g_return_if_fail (doc != NULL); + + /* If the user has modified again the document, do not close the tab. */ + if (_xed_document_needs_saving (doc)) { return; } - save_as_tab (tab, window); + /* Close the document only if it has been succesfully saved. + * Tab state is set to CLOSING (it is a state without exiting + * transitions) and the tab is closed in an idle handler. + */ + _xed_tab_mark_for_closing (tab); + + g_idle_add_full (G_PRIORITY_HIGH_IDLE, + (GSourceFunc) really_close_tab, + tab, + NULL); +} + +typedef struct _SaveAsData SaveAsData; + +struct _SaveAsData +{ + /* Reffed */ + XedWindow *window; + + /* List of reffed GeditTab's */ + GSList *tabs_to_save_as; + + guint close_tabs : 1; +}; + +static void save_as_documents_list (SaveAsData *data); + +static void +save_as_documents_list_cb (XedTab *tab, + GAsyncResult *result, + SaveAsData *data) +{ + gboolean saved = save_as_tab_finish (tab, result); + + if (saved && data->close_tabs) + { + close_tab (tab); + } + + g_return_if_fail (tab == XED_TAB (data->tabs_to_save_as->data)); + g_object_unref (data->tabs_to_save_as->data); + data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as, data->tabs_to_save_as); + + if (data->tabs_to_save_as != NULL) + { + save_as_documents_list (data); + } + else + { + g_object_unref (data->window); + g_slice_free (SaveAsData, data); + } +} + +static void +save_as_documents_list (SaveAsData *data) +{ + XedTab *next_tab = XED_TAB (data->tabs_to_save_as->data); + + xed_window_set_active_tab (data->window, next_tab); + + save_as_tab_async (next_tab, + data->window, + NULL, + (GAsyncReadyCallback) save_as_documents_list_cb, + data); } /* @@ -835,8 +1043,8 @@ static void save_documents_list (XedWindow *window, GList *docs) { + SaveAsData *data = NULL; GList *l; - GSList *tabs_to_save_as = NULL; xed_debug (DEBUG_COMMANDS); @@ -868,9 +1076,17 @@ save_documents_list (XedWindow *window, if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) { if (_xed_document_needs_saving (doc)) + { + if (data == NULL) { - tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); + data = g_slice_new (SaveAsData); + data->window = g_object_ref (window); + data->tabs_to_save_as = NULL; + data->close_tabs = FALSE; } + + data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t)); + } } else { @@ -913,23 +1129,21 @@ save_documents_list (XedWindow *window, l = g_list_next (l); } - if (tabs_to_save_as != NULL) + if (data != NULL) { - XedTab *tab; - - tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); - - g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL); - - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); - - tab = XED_TAB (tabs_to_save_as->data); - - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); + data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as); + save_as_documents_list (data); } } +/** + * xed_commands_save_all_documents: + * @window: a #XedWindow. + * + * Asynchronously save all documents belonging to @window. The result of the + * operation is not available, so it's difficult to know whether all the + * documents are correctly saved. + */ void xed_commands_save_all_documents (XedWindow *window) { @@ -953,6 +1167,14 @@ _xed_cmd_file_save_all (GtkAction *action, xed_commands_save_all_documents (window); } +/** + * xed_commands_save_document: + * @window: a #XedWindow. + * @document: the #XedDocument to save. + * + * Asynchronously save @document. @document must belong to @window. If you need + * the result of the operation, use xed_commands_save_document_async(). + */ void xed_commands_save_document (XedWindow *window, XedDocument *document) @@ -1161,39 +1383,6 @@ _xed_cmd_file_revert (GtkAction *action, gtk_widget_show (dialog); } -/* Close tab */ -static gboolean -really_close_tab (XedTab *tab) -{ - GtkWidget *toplevel; - XedWindow *window; - - xed_debug (DEBUG_COMMANDS); - - g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE); - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab)); - g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE); - - window = XED_WINDOW (toplevel); - - xed_window_close_tab (window, tab); - - if (xed_window_get_active_tab (window) == NULL) - { - gboolean is_quitting; - - is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING)); - - if (is_quitting) - { - gtk_widget_destroy (GTK_WIDGET (window)); - } - } - - return FALSE; -} - static void tab_state_changed_while_saving (XedTab *tab, GParamSpec *pspec, @@ -1209,26 +1398,9 @@ tab_state_changed_while_saving (XedTab *tab, finished */ if (ts == XED_TAB_STATE_NORMAL) { - XedDocument *doc; - g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window); - doc = xed_tab_get_document (tab); - g_return_if_fail (doc != NULL); - - /* If the saving operation failed or was interrupted, then the - document is still "modified" -> do not close the tab */ - if (_xed_document_needs_saving (doc)) - { - return; - } - - /* Close the document only if it has been succesfully saved. - Tab state is set to CLOSING (it is a state without exiting - transitions) and the tab is closed in a idle handler */ - _xed_tab_mark_for_closing (tab); - - g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)really_close_tab, tab, NULL); + close_tab (tab); } } @@ -1244,21 +1416,6 @@ save_and_close (XedTab *tab, save_tab (tab, window); } -static void -save_as_and_close (XedTab *tab, - XedWindow *window) -{ - xed_debug (DEBUG_COMMANDS); - - g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL); - - /* Trace tab state changes */ - g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window); - - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); -} - static void save_and_close_all_documents (const GList *docs, XedWindow *window) @@ -1266,9 +1423,9 @@ save_and_close_all_documents (const GList *docs, GList *tabs; GList *l; GSList *sl; - GSList *tabs_to_save_as; - GSList *tabs_to_save_and_close; - GList *tabs_to_close; + SaveAsData *data = NULL; + GSList *tabs_to_save_and_close = NULL; + GList *tabs_to_close = NULL; xed_debug (DEBUG_COMMANDS); @@ -1276,19 +1433,13 @@ save_and_close_all_documents (const GList *docs, tabs = gtk_container_get_children (GTK_CONTAINER (_xed_window_get_notebook (window))); - tabs_to_save_as = NULL; - tabs_to_save_and_close = NULL; - tabs_to_close = NULL; - l = tabs; while (l != NULL) { - XedTab *t; + XedTab *t = XED_TAB (l->data);; XedTabState state; XedDocument *doc; - t = XED_TAB (l->data); - state = xed_tab_get_state (t); doc = xed_tab_get_document (t); @@ -1337,9 +1488,15 @@ save_and_close_all_documents (const GList *docs, user is running xed - Paolo (Dec. 8, 2005) */ if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) { - g_object_set_data (G_OBJECT (t), XED_IS_CLOSING_TAB, GBOOLEAN_TO_POINTER (TRUE)); + if (data == NULL) + { + data = g_slice_new (SaveAsData); + data->window = g_object_ref (window); + data->tabs_to_save_as = NULL; + data->close_tabs = TRUE; + } - tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); + data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t)); } else { @@ -1371,20 +1528,11 @@ save_and_close_all_documents (const GList *docs, } g_slist_free (tabs_to_save_and_close); - /* Save As and close all the files in tabs_to_save_as */ - if (tabs_to_save_as != NULL) + /* Save As and close all the files in data->tabs_to_save_as. */ + if (data != NULL) { - XedTab *tab; - - tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); - - g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL); - - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); - - tab = XED_TAB (tabs_to_save_as->data); - - save_as_and_close (tab, window); + data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as); + save_as_documents_list (data); } } diff --git a/xed/xed-commands.h b/xed/xed-commands.h index 1ff5ae9..679bc1e 100644 --- a/xed/xed-commands.h +++ b/xed/xed-commands.h @@ -12,6 +12,8 @@ void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSo /* Ignore non-existing URIs */ GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos); void xed_commands_save_document (XedWindow *window, XedDocument *document); +void xed_commands_save_document_async (XedDocument *document, XedWindow *window, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +gboolean xed_commands_save_document_finish (XedDocument *document, GAsyncResult *result); void xed_commands_save_all_documents (XedWindow *window); /* diff --git a/xed/xed-document-private.h b/xed/xed-document-private.h new file mode 100644 index 0000000..9693eb9 --- /dev/null +++ b/xed/xed-document-private.h @@ -0,0 +1,21 @@ +#ifndef __XED_DOCUMENT_PRIVATE_H__ +#define __XED_DOCUMENT_PRIVATE_H__ + +#include "xed-document.h" + +G_BEGIN_DECLS + +glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc); + +gboolean _xed_document_needs_saving (XedDocument *doc); + +gboolean _xed_document_get_empty_search (XedDocument *doc); + +void _xed_document_set_create (XedDocument *doc, + gboolean create); + +gboolean _xed_document_get_create (XedDocument *doc); + +G_END_DECLS + +#endif /* __XED_DOCUMENT_PRIVATE_H__ */ diff --git a/xed/xed-document.c b/xed/xed-document.c index 44f27f3..470e831 100644 --- a/xed/xed-document.c +++ b/xed/xed-document.c @@ -41,26 +41,20 @@ #include #include "xed-document.h" +#include "xed-document-private.h" #include "xed-settings.h" #include "xed-debug.h" #include "xed-utils.h" -#include "xed-marshal.h" -#include "xed-enum-types.h" - -#ifndef ENABLE_GVFS_METADATA #include "xed-metadata-manager.h" -#else + #define METADATA_QUERY "metadata::*" -#endif #define NO_LANGUAGE_NAME "_NORMAL_" -#define XED_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_DOCUMENT, XedDocumentPrivate)) - static void xed_document_loaded_real (XedDocument *doc); static void xed_document_saved_real (XedDocument *doc); -struct _XedDocumentPrivate +typedef struct { GtkSourceFile *file; @@ -73,24 +67,22 @@ struct _XedDocumentPrivate gchar *content_type; - GTimeVal mtime; GTimeVal time_of_last_save_or_load; GtkSourceSearchContext *search_context; - guint readonly : 1; - guint externally_modified : 1; - guint deleted : 1; + guint user_action; + guint last_save_was_manually : 1; guint language_set_by_user : 1; guint stop_cursor_moved_emission : 1; - guint mtime_set : 1; + guint use_gvfs_metadata : 1; /* Create file if location points to a non existing file (for example * when opened from the command line). */ guint create : 1; -}; +} XedDocumentPrivate; enum { @@ -98,9 +90,13 @@ enum PROP_SHORTNAME, PROP_CONTENT_TYPE, PROP_MIME_TYPE, - PROP_READ_ONLY + PROP_READ_ONLY, + PROP_USE_GVFS_METADATA, + LAST_PROP }; +static GParamSpec *properties[LAST_PROP]; + enum { CURSOR_MOVED, @@ -111,11 +107,11 @@ enum LAST_SIGNAL }; -static guint document_signals[LAST_SIGNAL] = { 0 }; +static guint document_signals[LAST_SIGNAL]; static GHashTable *allocated_untitled_numbers = NULL; -G_DEFINE_TYPE(XedDocument, xed_document, GTK_SOURCE_TYPE_BUFFER) +G_DEFINE_TYPE_WITH_PRIVATE (XedDocument, xed_document, GTK_SOURCE_TYPE_BUFFER) static gint get_untitled_number (void) @@ -161,11 +157,13 @@ get_language_string (XedDocument *doc) static void save_metadata (XedDocument *doc) { + XedDocumentPrivate *priv; const gchar *language = NULL; GtkTextIter iter; gchar *position; - if (doc->priv->language_set_by_user) + priv = xed_document_get_instance_private (doc); + if (priv->language_set_by_user) { language = get_language_string (doc); } @@ -196,24 +194,26 @@ save_metadata (XedDocument *doc) static void xed_document_dispose (GObject *object) { - XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (XED_DOCUMENT (object)); + /* Metadata must be saved here and not in finalize because the language * is gone by the time finalize runs. */ - if (doc->priv->file != NULL) + if (priv->file != NULL) { - save_metadata (doc); + save_metadata (XED_DOCUMENT (object)); - g_object_unref (doc->priv->file); - doc->priv->file = NULL; + g_object_unref (priv->file); + priv->file = NULL; } - g_clear_object (&doc->priv->editor_settings); - g_clear_object (&doc->priv->metadata_info); - g_clear_object (&doc->priv->search_context); + g_clear_object (&priv->editor_settings); + g_clear_object (&priv->metadata_info); + g_clear_object (&priv->search_context); G_OBJECT_CLASS (xed_document_parent_class)->dispose (object); } @@ -221,17 +221,19 @@ xed_document_dispose (GObject *object) static void xed_document_finalize (GObject *object) { - XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); - if (doc->priv->untitled_number > 0) + priv = xed_document_get_instance_private (XED_DOCUMENT (object)); + + if (priv->untitled_number > 0) { - release_untitled_number (doc->priv->untitled_number); + release_untitled_number (priv->untitled_number); } - g_free (doc->priv->content_type); - g_free (doc->priv->short_name); + g_free (priv->content_type); + g_free (priv->short_name); G_OBJECT_CLASS (xed_document_parent_class)->finalize (object); } @@ -243,6 +245,9 @@ xed_document_get_property (GObject *object, GParamSpec *pspec) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); switch (prop_id) { @@ -256,7 +261,10 @@ xed_document_get_property (GObject *object, g_value_take_string (value, xed_document_get_mime_type (doc)); break; case PROP_READ_ONLY: - g_value_set_boolean (value, doc->priv->readonly); + g_value_set_boolean (value, gtk_source_file_is_readonly (priv->file)); + break; + case PROP_USE_GVFS_METADATA: + g_value_set_boolean (value, priv->use_gvfs_metadata); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -271,6 +279,9 @@ xed_document_set_property (GObject *object, GParamSpec *pspec) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); switch (prop_id) { @@ -280,16 +291,53 @@ xed_document_set_property (GObject *object, case PROP_CONTENT_TYPE: xed_document_set_content_type (doc, g_value_get_string (value)); break; + case PROP_USE_GVFS_METADATA: + priv->use_gvfs_metadata = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +xed_document_begin_user_action (GtkTextBuffer *buffer) +{ + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (XED_DOCUMENT (buffer)); + + ++priv->user_action; + + if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action != NULL) + { + GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action (buffer); + } +} + +static void +xed_document_end_user_action (GtkTextBuffer *buffer) +{ + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (XED_DOCUMENT (buffer)); + + --priv->user_action; + + if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action != NULL) + { + GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action (buffer); + } +} + static void emit_cursor_moved (XedDocument *doc) { - if (!doc->priv->stop_cursor_moved_emission) + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); + + if (!priv->stop_cursor_moved_emission) { g_signal_emit (doc, document_signals[CURSOR_MOVED], 0); } @@ -301,13 +349,16 @@ xed_document_mark_set (GtkTextBuffer *buffer, GtkTextMark *mark) { XedDocument *doc = XED_DOCUMENT (buffer); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set != NULL) { GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set (buffer, iter, mark); } - if (mark == gtk_text_buffer_get_insert (buffer)) + if (mark == gtk_text_buffer_get_insert (buffer) && (priv->user_action == 0)) { emit_cursor_moved (doc); } @@ -325,8 +376,11 @@ static void xed_document_constructed (GObject *object) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; - g_settings_bind (doc->priv->editor_settings, + priv = xed_document_get_instance_private (doc); + + g_settings_bind (priv->editor_settings, XED_SETTINGS_ENSURE_TRAILING_NEWLINE, doc, "implicit-trailing-newline", @@ -347,43 +401,77 @@ xed_document_class_init (XedDocumentClass *klass) object_class->set_property = xed_document_set_property; object_class->constructed = xed_document_constructed; + buf_class->begin_user_action = xed_document_begin_user_action; + buf_class->end_user_action = xed_document_end_user_action; buf_class->mark_set = xed_document_mark_set; buf_class->changed = xed_document_changed; klass->loaded = xed_document_loaded_real; klass->saved = xed_document_saved_real; - g_object_class_install_property (object_class, PROP_SHORTNAME, - g_param_spec_string ("shortname", - "Short Name", - "The document's short name", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:shortname: + * + * The documents short name. + */ + properties[PROP_SHORTNAME] = + g_param_spec_string ("shortname", + "Short Name", + "The documents short name", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CONTENT_TYPE, - g_param_spec_string ("content-type", - "Content Type", - "The document's Content Type", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:content-type: + * + * The documents content type. + */ + properties[PROP_CONTENT_TYPE] = + g_param_spec_string ("content-type", + "Content Type", + "The documents content type", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MIME_TYPE, - g_param_spec_string ("mime-type", - "MIME Type", - "The document's MIME Type", - "text/plain", - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:mime-type: + * + * The documents MIME type. + */ + properties[PROP_MIME_TYPE] = + g_param_spec_string ("mime-type", + "MIME Type", + "The documents MIME type", + "text/plain", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_READ_ONLY, - g_param_spec_boolean ("read-only", - "Read Only", - "Whether the document is read only or not", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + properties[PROP_READ_ONLY] = + g_param_spec_boolean ("read-only", + "Read Only", + "Whether the document is read-only or not", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * XedDocument:use-gvfs-metadata: + * + * Whether to use GVFS metadata. If %FALSE, use the xed metadata + * manager that stores the metadata in an XML file in the user cache + * directory. + * + * + * The property is used internally by xed. It must not be used in a + * xed plugin. The property can be modified or removed at any time. + * + */ + properties[PROP_USE_GVFS_METADATA] = + g_param_spec_boolean ("use-gvfs-metadata", + "Use GVFS metadata", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, LAST_PROP, properties); /* This signal is used to update the cursor position is the statusbar, * it's emitted either when the insert mark is moved explicitely or @@ -396,8 +484,7 @@ xed_document_class_init (XedDocumentClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (XedDocumentClass, cursor_moved), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -424,7 +511,7 @@ xed_document_class_init (XedDocumentClass *klass) document_signals[LOADED] = g_signal_new ("loaded", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (XedDocumentClass, loaded), NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -452,12 +539,10 @@ xed_document_class_init (XedDocumentClass *klass) document_signals[SAVED] = g_signal_new ("saved", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (XedDocumentClass, saved), NULL, NULL, NULL, G_TYPE_NONE, 0); - - g_type_class_add_private (object_class, sizeof (XedDocumentPrivate)); } static void @@ -465,10 +550,13 @@ set_language (XedDocument *doc, GtkSourceLanguage *lang, gboolean set_by_user) { + XedDocumentPrivate *priv; GtkSourceLanguage *old_lang; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + old_lang = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc)); if (old_lang == lang) @@ -478,19 +566,6 @@ set_language (XedDocument *doc, gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), lang); - if (lang != NULL) - { - gboolean syntax_hl; - - syntax_hl = g_settings_get_boolean (doc->priv->editor_settings, - XED_SETTINGS_SYNTAX_HIGHLIGHTING); - gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), syntax_hl); - } - else - { - gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), FALSE); - } - if (set_by_user) { const gchar *language = get_language_string (doc); @@ -498,18 +573,21 @@ set_language (XedDocument *doc, xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE, language, NULL); } - doc->priv->language_set_by_user = set_by_user; + priv->language_set_by_user = set_by_user; } static void save_encoding_metadata (XedDocument *doc) { + XedDocumentPrivate *priv; const GtkSourceEncoding *encoding; const gchar *charset; xed_debug (DEBUG_DOCUMENT); - encoding = gtk_source_file_get_encoding (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + encoding = gtk_source_file_get_encoding (priv->file); if (encoding == NULL) { @@ -551,10 +629,13 @@ get_default_style_scheme (GSettings *editor_settings) static GtkSourceLanguage * guess_language (XedDocument *doc) { + XedDocumentPrivate *priv; gchar *data; GtkSourceLanguageManager *manager = gtk_source_language_manager_get_default (); GtkSourceLanguage *language = NULL; + priv = xed_document_get_instance_private (doc); + data = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE); if (data != NULL) @@ -573,19 +654,19 @@ guess_language (XedDocument *doc) GFile *location; gchar *basename = NULL; - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); xed_debug_message (DEBUG_DOCUMENT, "Sniffing Language"); if (location != NULL) { basename = g_file_get_basename (location); } - else if (doc->priv->short_name != NULL) + else if (priv->short_name != NULL) { - basename = g_strdup (doc->priv->short_name); + basename = g_strdup (priv->short_name); } - language = gtk_source_language_manager_guess_language (manager, basename, doc->priv->content_type); + language = gtk_source_language_manager_guess_language (manager, basename, priv->content_type); g_free (basename); } @@ -598,7 +679,11 @@ on_content_type_changed (XedDocument *doc, GParamSpec *pspec, gpointer useless) { - if (!doc->priv->language_set_by_user) + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); + + if (!priv->language_set_by_user) { GtkSourceLanguage *language = guess_language (doc); @@ -620,61 +705,74 @@ on_location_changed (GtkSourceFile *file, GParamSpec *pspec, XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + location = gtk_source_file_get_location (file); - if (location != NULL && doc->priv->untitled_number > 0) + if (location != NULL && priv->untitled_number > 0) { - release_untitled_number (doc->priv->untitled_number); - doc->priv->untitled_number = 0; + release_untitled_number (priv->untitled_number); + priv->untitled_number = 0; } - if (doc->priv->short_name == NULL) + if (priv->short_name == NULL) { - g_object_notify (G_OBJECT (doc), "shortname"); + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]); } -#ifdef ENABLE_GVFS_METADATA - - /* load metadata for this location: we load sync since metadata is - * always local so it should be fast and we need the information - * right after the location was set. - */ - if (location != NULL) + /* Load metadata for this location: we load sync since metadata is + * always local so it should be fast and we need the information + * right after the location was set. + */ + if (priv->use_gvfs_metadata && location != NULL) { GError *error = NULL; - if (doc->priv->metadata_info != NULL) + if (priv->metadata_info != NULL) { - g_object_unref (doc->priv->metadata_info); + g_object_unref (priv->metadata_info); } - doc->priv->metadata_info = g_file_query_info (location, - METADATA_QUERY, - G_FILE_QUERY_INFO_NONE, - NULL, - &error); + priv->metadata_info = g_file_query_info (location, + METADATA_QUERY, + G_FILE_QUERY_INFO_NONE, + NULL, + &error); if (error != NULL) { - /* TODO document why the warning is not displayed in - * certain cases. + /* Do not complain about metadata if we are opening a + * non existing file. */ - if (error->domain != G_FILE_ERROR || - (error->code != G_FILE_ERROR_ISDIR && - error->code != G_FILE_ERROR_NOTDIR && - error->code != G_FILE_ERROR_NOENT)) + if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) && + !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) && + !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_warning ("%s", error->message); } g_error_free (error); } + + if (priv->metadata_info == NULL) + { + priv->metadata_info = g_file_info_new (); + } } -#endif +} + +static void +on_readonly_changed (GtkSourceFile *file, + GParamSpec *pspec, + XedDocument *doc) +{ + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_READ_ONLY]); } static void @@ -685,40 +783,43 @@ xed_document_init (XedDocument *doc) xed_debug (DEBUG_DOCUMENT); - doc->priv = XED_DOCUMENT_GET_PRIVATE (doc); - priv = doc->priv; + priv = xed_document_get_instance_private (doc); priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor"); - priv->untitled_number = get_untitled_number (); - priv->content_type = get_default_content_type (); - - priv->readonly = FALSE; - priv->stop_cursor_moved_emission = FALSE; - priv->last_save_was_manually = TRUE; priv->language_set_by_user = FALSE; - g_get_current_time (&doc->priv->time_of_last_save_or_load); + g_get_current_time (&priv->time_of_last_save_or_load); priv->file = gtk_source_file_new (); + priv->metadata_info = g_file_info_new (); g_signal_connect_object (priv->file, "notify::location", G_CALLBACK (on_location_changed), doc, 0); + g_signal_connect_object (priv->file, "notify::read-only", + G_CALLBACK (on_readonly_changed), doc, 0); + + g_settings_bind (priv->editor_settings, + XED_SETTINGS_SYNTAX_HIGHLIGHTING, + doc, + "highlight-syntax", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + g_settings_bind (priv->editor_settings, XED_SETTINGS_MAX_UNDO_ACTIONS, doc, "max-undo-levels", - G_SETTINGS_BIND_GET); + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); g_settings_bind (priv->editor_settings, XED_SETTINGS_BRACKET_MATCHING, doc, "highlight-matching-brackets", - G_SETTINGS_BIND_GET); + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); style_scheme = get_default_style_scheme (priv->editor_settings); if (style_scheme != NULL) @@ -732,34 +833,46 @@ xed_document_init (XedDocument *doc) XedDocument * xed_document_new (void) { - return g_object_new (XED_TYPE_DOCUMENT, NULL); + gboolean use_gvfs_metadata; + +#ifdef ENABLE_GVFS_METADATA + use_gvfs_metadata = TRUE; +#else + use_gvfs_metadata = FALSE; +#endif + + return g_object_new (XED_TYPE_DOCUMENT, + "use-gvfs-metadata", use_gvfs_metadata, + NULL); } static void set_content_type_no_guess (XedDocument *doc, const gchar *content_type) { + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); - if (doc->priv->content_type != NULL && - content_type != NULL && - g_str_equal (doc->priv->content_type, content_type)) + priv = xed_document_get_instance_private (doc); + + if (priv->content_type != NULL && content_type != NULL && + g_str_equal (priv->content_type, content_type)) { return; } - g_free (doc->priv->content_type); + g_free (priv->content_type); if (content_type == NULL || g_content_type_is_unknown (content_type)) { - doc->priv->content_type = get_default_content_type (); + priv->content_type = get_default_content_type (); } else { - doc->priv->content_type = g_strdup (content_type); + priv->content_type = g_strdup (content_type); } - g_object_notify (G_OBJECT (doc), "content-type"); + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_CONTENT_TYPE]); } /** @@ -771,17 +884,21 @@ void xed_document_set_content_type (XedDocument *doc, const gchar *content_type) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + if (content_type == NULL) { GFile *location; gchar *guessed_type = NULL; /* If content type is null, we guess from the filename */ - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { gchar *basename; @@ -810,11 +927,14 @@ xed_document_set_content_type (XedDocument *doc, GFile * xed_document_get_location (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; + priv = xed_document_get_instance_private (doc); + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); return location != NULL ? g_object_ref (location) : NULL; } @@ -823,10 +943,12 @@ void xed_document_set_location (XedDocument *doc, GFile *location) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (G_IS_FILE (location)); - gtk_source_file_set_location (doc->priv->file, location); + gtk_source_file_set_location (priv->file, location); xed_document_set_content_type (doc, NULL); } @@ -839,15 +961,18 @@ xed_document_set_location (XedDocument *doc, gchar * xed_document_get_uri_for_display (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("")); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); if (location == NULL) { - return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); + return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number); } else { @@ -864,19 +989,22 @@ xed_document_get_uri_for_display (XedDocument *doc) gchar * xed_document_get_short_name_for_display (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("")); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); - if (doc->priv->short_name != NULL) + location = gtk_source_file_get_location (priv->file); + + if (priv->short_name != NULL) { - return g_strdup (doc->priv->short_name); + return g_strdup (priv->short_name); } else if (location == NULL) { - return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); + return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number); } else { @@ -893,20 +1021,28 @@ void xed_document_set_short_name_for_display (XedDocument *doc, const gchar *short_name) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - g_free (doc->priv->short_name); - doc->priv->short_name = g_strdup (short_name); + priv = xed_document_get_instance_private (doc); - g_object_notify (G_OBJECT (doc), "shortname"); + g_free (priv->short_name); + priv->short_name = g_strdup (short_name); + + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]); } gchar * xed_document_get_content_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return g_strdup (doc->priv->content_type); + priv = xed_document_get_instance_private (doc); + + return g_strdup (priv->content_type); } /** @@ -918,40 +1054,31 @@ xed_document_get_content_type (XedDocument *doc) gchar * xed_document_get_mime_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("text/plain")); - if (doc->priv->content_type != NULL && - !g_content_type_is_unknown (doc->priv->content_type)) + priv = xed_document_get_instance_private (doc); + + if (priv->content_type != NULL && + !g_content_type_is_unknown (priv->content_type)) { - return g_content_type_get_mime_type (doc->priv->content_type); + return g_content_type_get_mime_type (priv->content_type); } return g_strdup ("text/plain"); } -static void -set_readonly (XedDocument *doc, - gboolean readonly) -{ - xed_debug (DEBUG_DOCUMENT); - - g_return_if_fail (XED_IS_DOCUMENT (doc)); - - readonly = readonly != FALSE; - - if (doc->priv->readonly != readonly) - { - doc->priv->readonly = readonly; - g_object_notify (G_OBJECT (doc), "read-only"); - } -} - gboolean xed_document_get_readonly (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - return doc->priv->readonly; + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_is_readonly (priv->file); } static void @@ -978,33 +1105,17 @@ loaded_query_info_cb (GFile *location, error = NULL; } - if (info != NULL) + if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) { - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) - { - const gchar *content_type; + const gchar *content_type; - content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); - xed_document_set_content_type (doc, content_type); - } + content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) - { - gboolean read_only; - - read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); - set_readonly (doc, read_only); - } - - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED)) - { - g_file_info_get_modification_time (info, &doc->priv->mtime); - doc->priv->mtime_set = TRUE; - } - - g_object_unref (info); + xed_document_set_content_type (doc, content_type); } + g_clear_object (&info); + /* Async operation finished. */ g_object_unref (doc); } @@ -1012,9 +1123,12 @@ loaded_query_info_cb (GFile *location, static void xed_document_loaded_real (XedDocument *doc) { - GFile *location; + XedDocumentPrivate *priv; + GFile *location; - if (!doc->priv->language_set_by_user) + priv = xed_document_get_instance_private (doc); + + if (!priv->language_set_by_user) { GtkSourceLanguage *language = guess_language (doc); @@ -1024,17 +1138,11 @@ xed_document_loaded_real (XedDocument *doc) set_language (doc, language, FALSE); } - doc->priv->mtime_set = FALSE; - doc->priv->externally_modified = FALSE; - doc->priv->deleted = FALSE; - - g_get_current_time (&doc->priv->time_of_last_save_or_load); - - set_readonly (doc, FALSE); + g_get_current_time (&priv->time_of_last_save_or_load); xed_document_set_content_type (doc, NULL); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { @@ -1043,8 +1151,7 @@ xed_document_loaded_real (XedDocument *doc) g_file_query_info_async (location, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, @@ -1058,10 +1165,13 @@ saved_query_info_cb (GFile *location, GAsyncResult *result, XedDocument *doc) { + XedDocumentPrivate *priv; GFileInfo *info; const gchar *content_type = NULL; GError *error = NULL; + priv = xed_document_get_instance_private (doc); + info = g_file_query_info_finish (location, result, &error); if (error != NULL) @@ -1071,20 +1181,9 @@ saved_query_info_cb (GFile *location, error = NULL; } - doc->priv->mtime_set = FALSE; - - if (info != NULL) + if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) { - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) - { - content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); - } - - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED)) - { - g_file_info_get_modification_time (info, &doc->priv->mtime); - doc->priv->mtime_set = TRUE; - } + content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); } xed_document_set_content_type (doc, content_type); @@ -1094,15 +1193,9 @@ saved_query_info_cb (GFile *location, g_object_unref (info); } - g_get_current_time (&doc->priv->time_of_last_save_or_load); + g_get_current_time (&priv->time_of_last_save_or_load); - doc->priv->externally_modified = FALSE; - doc->priv->deleted = FALSE; - doc->priv->create = FALSE; - - set_readonly (doc, FALSE); - - gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE); + priv->create = FALSE; save_encoding_metadata (doc); @@ -1113,14 +1206,18 @@ saved_query_info_cb (GFile *location, static void xed_document_saved_real (XedDocument *doc) { - GFile *location = gtk_source_file_get_location (doc->priv->file); + XedDocumentPrivate *priv; + GFile *location; + + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); /* Keep the doc alive during the async operation. */ g_object_ref (doc); g_file_query_info_async (location, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, @@ -1131,11 +1228,14 @@ xed_document_saved_real (XedDocument *doc) gboolean xed_document_is_untouched (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; + priv = xed_document_get_instance_private (doc); + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); return location == NULL && !gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)); } @@ -1143,107 +1243,37 @@ xed_document_is_untouched (XedDocument *doc) gboolean xed_document_is_untitled (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - return gtk_source_file_get_location (doc->priv->file) == NULL; + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_get_location (priv->file) == NULL; } gboolean xed_document_is_local (XedDocument *doc) { - GFile *location; + XedDocumentPrivate *priv; g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); - if (location == NULL) - { - return FALSE; - } - - return g_file_has_uri_scheme (location, "file"); -} - -static void -check_file_on_disk (XedDocument *doc) -{ - GFile *location; - GFileInfo *info; - - location = gtk_source_file_get_location (doc->priv->file); - - if (location == NULL) - { - return; - } - - info = g_file_query_info (location, - G_FILE_ATTRIBUTE_TIME_MODIFIED "," \ - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, - G_FILE_QUERY_INFO_NONE, - NULL, NULL); - - if (info != NULL) - { - /* While at it also check if permissions changed */ - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) - { - gboolean read_only; - - read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); - - set_readonly (doc, read_only); - } - - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED) && doc->priv->mtime_set) - { - GTimeVal timeval; - - g_file_info_get_modification_time (info, &timeval); - - /* Note that mtime can even go backwards if the - * user is copying over a file with an old mtime - */ - if (timeval.tv_sec != doc->priv->mtime.tv_sec || - timeval.tv_usec != doc->priv->mtime.tv_usec) - { - doc->priv->externally_modified = TRUE; - } - } - - g_object_unref (info); - } - else - { - doc->priv->deleted = TRUE; - } -} - -gboolean -_xed_document_check_externally_modified (XedDocument *doc) -{ - g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - - if (!doc->priv->externally_modified) - { - check_file_on_disk (doc); - } - - return doc->priv->externally_modified; + return gtk_source_file_is_local (priv->file); } gboolean xed_document_get_deleted (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - if (!doc->priv->deleted) - { - check_file_on_disk (doc); - } + priv = xed_document_get_instance_private (doc); - return doc->priv->deleted; + return gtk_source_file_is_deleted (priv->file); } /* @@ -1252,29 +1282,27 @@ xed_document_get_deleted (XedDocument *doc) gboolean _xed_document_needs_saving (XedDocument *doc) { + XedDocumentPrivate *priv; + gboolean externally_modified = FALSE; + gboolean deleted = FALSE; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + priv = xed_document_get_instance_private (doc); + if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))) { return TRUE; } - if (doc->priv->externally_modified || doc->priv->deleted) + if (gtk_source_file_is_local (priv->file)) { - return TRUE; + gtk_source_file_check_file_on_disk (priv->file); + externally_modified = gtk_source_file_is_externally_modified (priv->file); + deleted = gtk_source_file_is_deleted (priv->file); } - if (xed_document_is_local (doc)) - { - check_file_on_disk (doc); - - if (doc->priv->externally_modified || doc->priv->deleted) - { - return TRUE; - } - } - - return FALSE; + return (externally_modified || deleted) && !priv->create; } /* @@ -1285,8 +1313,6 @@ gboolean xed_document_goto_line (XedDocument *doc, gint line) { - gboolean ret = TRUE; - guint line_count; GtkTextIter iter; xed_debug (DEBUG_DOCUMENT); @@ -1294,21 +1320,11 @@ xed_document_goto_line (XedDocument *doc, g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (line >= -1, FALSE); - line_count = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc)); - - if (line >= line_count) - { - ret = FALSE; - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); - } - else - { - gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); - } + gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); - return ret; + return gtk_text_iter_get_line (&iter) == line; } gboolean @@ -1316,29 +1332,17 @@ xed_document_goto_line_offset (XedDocument *doc, gint line, gint line_offset) { - gboolean ret = TRUE; - guint offset_count; GtkTextIter iter; g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (line >= -1, FALSE); g_return_val_if_fail (line_offset >= -1, FALSE); - gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); - - offset_count = gtk_text_iter_get_chars_in_line (&iter); - if (line_offset > offset_count) - { - ret = FALSE; - } - else - { - gtk_text_iter_set_line_offset (&iter, line_offset); - } + gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc), &iter, line, line_offset); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); - return ret; + return (gtk_text_iter_get_line (&iter) == line && gtk_text_iter_get_line_offset (&iter) == line_offset); } /** @@ -1372,44 +1376,54 @@ xed_document_get_language (XedDocument *doc) const GtkSourceEncoding * xed_document_get_encoding (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return gtk_source_file_get_encoding (doc->priv->file); + xed_document_get_instance_private (doc); + + return gtk_source_file_get_encoding (priv->file); } glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc) { + XedDocumentPrivate *priv; GTimeVal current_time; xed_debug (DEBUG_DOCUMENT); g_return_val_if_fail (XED_IS_DOCUMENT (doc), -1); + priv = xed_document_get_instance_private (doc); + g_get_current_time (¤t_time); - return (current_time.tv_sec - doc->priv->time_of_last_save_or_load.tv_sec); + return (current_time.tv_sec - priv->time_of_last_save_or_load.tv_sec); } GtkSourceNewlineType xed_document_get_newline_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), 0); - return gtk_source_file_get_newline_type (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_get_newline_type (priv->file); } -#ifndef ENABLE_GVFS_METADATA -gchar * -xed_document_get_metadata (XedDocument *doc, - const gchar *key) +static gchar * +get_metadata_from_metadata_manager (XedDocument *doc, + const gchar *key) { + XedDocumentPrivate *priv; GFile *location; - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - g_return_val_if_fail (key != NULL, NULL); + priv = xed_document_get_instance_private (doc); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { @@ -1419,40 +1433,41 @@ xed_document_get_metadata (XedDocument *doc, return NULL; } -void -xed_document_set_metadata (XedDocument *doc, - const gchar *first_key, - ...) +static gchar * +get_metadata_from_gvfs (XedDocument *doc, + const gchar *key) { - GFile *location; - const gchar *key; - const gchar *value; - va_list var_args; + XedDocumentPrivate *priv; - g_return_if_fail (XED_IS_DOCUMENT (doc)); - g_return_if_fail (first_key != NULL); + priv = xed_document_get_instance_private (doc); - location = gtk_source_file_get_location (doc->priv->file); - - if (location == NULL) + if (priv->metadata_info != NULL && + g_file_info_has_attribute (priv->metadata_info, key) && + g_file_info_get_attribute_type (priv->metadata_info, key) == G_FILE_ATTRIBUTE_TYPE_STRING) { - /* Can't set metadata for untitled documents */ - return; + return g_strdup (g_file_info_get_attribute_string (priv->metadata_info, key)); } - va_start (var_args, first_key); - - for (key = first_key; key; key = va_arg (var_args, const gchar *)) - { - value = va_arg (var_args, const gchar *); - - xed_metadata_manager_set (location, key, value); - } - - va_end (var_args); + return NULL; } -#else +static void +set_gvfs_metadata (GFileInfo *info, + const gchar *key, + const gchar *value) +{ + g_return_if_fail (G_IS_FILE_INFO (info)); + + if (value != NULL) + { + g_file_info_set_attribute_string (info, key, value); + } + else + { + /* Unset the key */ + g_file_info_set_attribute (info, key, G_FILE_ATTRIBUTE_TYPE_INVALID, NULL); + } +} /** * xed_document_get_metadata: @@ -1467,15 +1482,19 @@ gchar * xed_document_get_metadata (XedDocument *doc, const gchar *key) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); g_return_val_if_fail (key != NULL, NULL); - if (doc->priv->metadata_info && g_file_info_has_attribute (doc->priv->metadata_info, key)) + priv = xed_document_get_instance_private (doc); + + if (priv->use_gvfs_metadata) { - return g_strdup (g_file_info_get_attribute_string (doc->priv->metadata_info, key)); + return get_metadata_from_gvfs (doc, key); } - return NULL; + return get_metadata_from_metadata_manager (doc, key); } static void @@ -1507,44 +1526,57 @@ xed_document_set_metadata (XedDocument *doc, const gchar *first_key, ...) { - const gchar *key; - const gchar *value; - va_list var_args; - GFileInfo *info; + XedDocumentPrivate *priv; GFile *location; + const gchar *key; + va_list var_args; + GFileInfo *info = NULL; g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (first_key != NULL); - info = g_file_info_new (); + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); + + /* With the metadata manager, can't set metadata for untitled documents. + * With GVFS metadata, if the location is NULL the metadata is stored in + * priv->metadata_info, so that it can be saved later if the document is + * saved. + */ + + if (!priv->use_gvfs_metadata && location == NULL) + { + return; + } + + if (priv->use_gvfs_metadata) + { + info = g_file_info_new (); + } va_start (var_args, first_key); for (key = first_key; key; key = va_arg (var_args, const gchar *)) { - value = va_arg (var_args, const gchar *); + const gchar *value = va_arg (var_args, const gchar *); - if (value != NULL) + if (priv->use_gvfs_metadata) { - g_file_info_set_attribute_string (info, key, value); + /* Collect the metadata into @info. */ + set_gvfs_metadata (info, key, value); + set_gvfs_metadata (priv->metadata_info, key, value); } else { /* Unset the key */ - g_file_info_remove_attribute (info, key); + xed_metadata_manager_set (location, key, value); } } va_end (var_args); - if (doc->priv->metadata_info != NULL) - { - g_file_info_copy_into (info, doc->priv->metadata_info); - } - - location = gtk_source_file_get_location (doc->priv->file); - - if (location != NULL) + if (priv->use_gvfs_metadata && location != NULL) { g_file_set_attributes_async (location, info, @@ -1555,9 +1587,8 @@ xed_document_set_metadata (XedDocument *doc, NULL); } - g_object_unref (info); + g_clear_object (&info); } -#endif /** * xed_document_set_search_context: @@ -1570,19 +1601,23 @@ void xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext *search_context) { - g_return_if_fail (XED_IS_DOCUMENT (doc)); + XedDocumentPrivate *priv; - g_clear_object (&doc->priv->search_context); - doc->priv->search_context = search_context; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - if (search_context != NULL) - { - gboolean highlight = g_settings_get_boolean (doc->priv->editor_settings, XED_SETTINGS_SEARCH_HIGHLIGHTING); + priv = xed_document_get_instance_private (doc); + + g_clear_object (&priv->search_context); + priv->search_context = search_context; + + if (search_context != NULL) + { + gboolean highlight = g_settings_get_boolean (priv->editor_settings, XED_SETTINGS_SEARCH_HIGHLIGHTING); gtk_source_search_context_set_highlight (search_context, highlight); g_object_ref (search_context); - } + } } /** @@ -1595,9 +1630,13 @@ xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext * xed_document_get_search_context (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return doc->priv->search_context; + priv = xed_document_get_instance_private (doc); + + return priv->search_context; } /** @@ -1618,24 +1657,36 @@ xed_document_get_search_context (XedDocument *doc) GtkSourceFile * xed_document_get_file (XedDocument *doc) { - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); + XedDocumentPrivate *priv; - return doc->priv->file; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); + + priv = xed_document_get_instance_private (doc); + + return priv->file; } void _xed_document_set_create (XedDocument *doc, gboolean create) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - doc->priv->create = create != FALSE; + priv = xed_document_get_instance_private (doc); + + priv->create = create != FALSE; } gboolean _xed_document_get_create (XedDocument *doc) { - g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + XedDocumentPrivate *priv; - return doc->priv->create; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + + priv = xed_document_get_instance_private (doc); + + return priv->create; } diff --git a/xed/xed-document.h b/xed/xed-document.h index f8bb270..a1fbf6d 100644 --- a/xed/xed-document.h +++ b/xed/xed-document.h @@ -37,29 +37,14 @@ G_BEGIN_DECLS -#define XED_TYPE_DOCUMENT (xed_document_get_type()) -#define XED_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT, XedDocument)) -#define XED_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT, XedDocumentClass)) -#define XED_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_DOCUMENT)) -#define XED_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT)) -#define XED_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT, XedDocumentClass)) +#define XED_TYPE_DOCUMENT (xed_document_get_type()) + +G_DECLARE_DERIVABLE_TYPE (XedDocument, xed_document, XED, DOCUMENT, GtkSourceBuffer) #define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position" #define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding" #define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language" -typedef struct _XedDocument XedDocument; -typedef struct _XedDocumentPrivate XedDocumentPrivate; -typedef struct _XedDocumentClass XedDocumentClass; - -struct _XedDocument -{ - GtkSourceBuffer buffer; - - /*< private > */ - XedDocumentPrivate *priv; -}; - struct _XedDocumentClass { GtkSourceBufferClass parent_class; @@ -77,8 +62,6 @@ struct _XedDocumentClass void (* saved) (XedDocument *document); }; -GType xed_document_get_type (void) G_GNUC_CONST; - XedDocument *xed_document_new (void); GtkSourceFile *xed_document_get_file (XedDocument *doc); @@ -138,24 +121,6 @@ void xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext *xed_document_get_search_context (XedDocument *doc); -/* Non exported functions */ - -glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc); - -void _xed_document_apply_error_style (XedDocument *doc, - GtkTextIter *start, - GtkTextIter *end); - -/* Note: this is a sync stat: use only on local files */ -gboolean _xed_document_check_externally_modified (XedDocument *doc); - -gboolean _xed_document_needs_saving (XedDocument *doc); - -void _xed_document_set_create (XedDocument *doc, - gboolean create); - -gboolean _xed_document_get_create (XedDocument *doc); - G_END_DECLS #endif /* __XED_DOCUMENT_H__ */ diff --git a/xed/xed-metadata-manager.c b/xed/xed-metadata-manager.c index 01d491e..d92ff87 100644 --- a/xed/xed-metadata-manager.c +++ b/xed/xed-metadata-manager.c @@ -21,23 +21,15 @@ * Boston, MA 02110-1301, USA. */ -/* - * Modified by the xed Team, 2003-2007. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#include -#include #include #include "xed-metadata-manager.h" #include "xed-debug.h" /* -#define XED_METADATA_VERBOSE_DEBUG 1 +#define XED_METADATA_VERBOSE_DEBUG 1 */ -#define MAX_ITEMS 50 +#define MAX_ITEMS 50 typedef struct _XedMetadataManager XedMetadataManager; @@ -45,21 +37,21 @@ typedef struct _Item Item; struct _Item { - time_t atime; /* time of last access */ + gint64 atime; /* time of last access in seconds since January 1, 1970 UTC */ - GHashTable *values; + GHashTable *values; }; struct _XedMetadataManager { - gboolean values_loaded; /* It is true if the file - has been read */ + gboolean values_loaded; /* It is true if the file + has been read */ - guint timeout_id; + guint timeout_id; - GHashTable *items; + GHashTable *items; - gchar *metadata_filename; + gchar *metadata_filename; }; static gboolean xed_metadata_manager_save (gpointer data); @@ -70,34 +62,34 @@ static XedMetadataManager *xed_metadata_manager = NULL; static void item_free (gpointer data) { - Item *item; + Item *item; - g_return_if_fail (data != NULL); + g_return_if_fail (data != NULL); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - item = (Item *)data; + item = (Item *)data; - if (item->values != NULL) - g_hash_table_destroy (item->values); + if (item->values != NULL) + g_hash_table_destroy (item->values); - g_free (item); + g_free (item); } static void xed_metadata_manager_arm_timeout (void) { - if (xed_metadata_manager->timeout_id == 0) - { - xed_metadata_manager->timeout_id = - g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, - 2, - (GSourceFunc)xed_metadata_manager_save, - NULL, - NULL); - } + if (xed_metadata_manager->timeout_id == 0) + { + xed_metadata_manager->timeout_id = + g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, + 2, + (GSourceFunc)xed_metadata_manager_save, + NULL, + NULL); + } } /** @@ -110,22 +102,22 @@ xed_metadata_manager_arm_timeout (void) void xed_metadata_manager_init (const gchar *metadata_filename) { - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - if (xed_metadata_manager != NULL) - return; + if (xed_metadata_manager != NULL) + return; - xed_metadata_manager = g_new0 (XedMetadataManager, 1); + xed_metadata_manager = g_new0 (XedMetadataManager, 1); - xed_metadata_manager->values_loaded = FALSE; + xed_metadata_manager->values_loaded = FALSE; - xed_metadata_manager->items = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - item_free); + xed_metadata_manager->items = + g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + item_free); - xed_metadata_manager->metadata_filename = g_strdup (metadata_filename); + xed_metadata_manager->metadata_filename = g_strdup (metadata_filename); return; } @@ -139,154 +131,159 @@ xed_metadata_manager_init (const gchar *metadata_filename) void xed_metadata_manager_shutdown (void) { - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - if (xed_metadata_manager == NULL) - return; + if (xed_metadata_manager == NULL) + return; - if (xed_metadata_manager->timeout_id) - { - g_source_remove (xed_metadata_manager->timeout_id); - xed_metadata_manager->timeout_id = 0; - xed_metadata_manager_save (NULL); - } + if (xed_metadata_manager->timeout_id) + { + g_source_remove (xed_metadata_manager->timeout_id); + xed_metadata_manager->timeout_id = 0; + xed_metadata_manager_save (NULL); + } - if (xed_metadata_manager->items != NULL) - g_hash_table_destroy (xed_metadata_manager->items); + if (xed_metadata_manager->items != NULL) + g_hash_table_destroy (xed_metadata_manager->items); - g_free (gedit_metadata_manager->metadata_filename); - g_free (xed_metadata_manager); - xed_metadata_manager = NULL; + g_free (xed_metadata_manager->metadata_filename); + g_free (xed_metadata_manager); + xed_metadata_manager = NULL; } static void parseItem (xmlDocPtr doc, xmlNodePtr cur) { - Item *item; + Item *item; - xmlChar *uri; - xmlChar *atime; + xmlChar *uri; + xmlChar *atime; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) - return; + if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) + return; - uri = xmlGetProp (cur, (const xmlChar *)"uri"); - if (uri == NULL) - return; + uri = xmlGetProp (cur, (const xmlChar *)"uri"); + if (uri == NULL) + return; - atime = xmlGetProp (cur, (const xmlChar *)"atime"); - if (atime == NULL) - { - xmlFree (uri); - return; - } + atime = xmlGetProp (cur, (const xmlChar *)"atime"); + if (atime == NULL) + { + xmlFree (uri); + return; + } - item = g_new0 (Item, 1); + item = g_new0 (Item, 1); - item->atime = g_ascii_strtoull ((char *)atime, NULL, 0); + item->atime = g_ascii_strtoll ((char *)atime, NULL, 0); - item->values = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); + item->values = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); - cur = cur->xmlChildrenNode; + cur = cur->xmlChildrenNode; - while (cur != NULL) - { - if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) - { - xmlChar *key; - xmlChar *value; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) + { + xmlChar *key; + xmlChar *value; - key = xmlGetProp (cur, (const xmlChar *)"key"); - value = xmlGetProp (cur, (const xmlChar *)"value"); + key = xmlGetProp (cur, (const xmlChar *)"key"); + value = xmlGetProp (cur, (const xmlChar *)"value"); - if ((key != NULL) && (value != NULL)) - g_hash_table_insert (item->values, - g_strdup ((gchar *)key), - g_strdup ((gchar *)value)); + if ((key != NULL) && (value != NULL)) + g_hash_table_insert (item->values, + g_strdup ((gchar *)key), + g_strdup ((gchar *)value)); - if (key != NULL) - xmlFree (key); - if (value != NULL) - xmlFree (value); - } + if (key != NULL) + xmlFree (key); + if (value != NULL) + xmlFree (value); + } - cur = cur->next; - } + cur = cur->next; + } - g_hash_table_insert (xed_metadata_manager->items, - g_strdup ((gchar *)uri), - item); + g_hash_table_insert (xed_metadata_manager->items, + g_strdup ((gchar *)uri), + item); - xmlFree (uri); - xmlFree (atime); + xmlFree (uri); + xmlFree (atime); } static gboolean load_values (void) { - xmlDocPtr doc; - xmlNodePtr cur; + xmlDocPtr doc; + xmlNodePtr cur; - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - g_return_val_if_fail (xed_metadata_manager != NULL, FALSE); - g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE); + g_return_val_if_fail (xed_metadata_manager != NULL, FALSE); + g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE); - xed_metadata_manager->values_loaded = TRUE; + xed_metadata_manager->values_loaded = TRUE; - xmlKeepBlanksDefault (0); + xmlKeepBlanksDefault (0); - /* FIXME: file locking - Paolo */ - if ((xed_metadata_manager->metadata_filename == NULL) || - (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))) - { - return FALSE; - } + /* FIXME: file locking - Paolo */ + if (xed_metadata_manager->metadata_filename == NULL) + { + return FALSE; + } - doc = xmlParseFile (xed_metadata_manager->metadata_filename); + /* TODO: avoid races */ + if (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS)) + { + return TRUE; + } - if (doc == NULL) - { - return FALSE; - } + doc = xmlParseFile (xed_metadata_manager->metadata_filename); - cur = xmlDocGetRootElement (doc); - if (cur == NULL) - { - g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); - xmlFreeDoc (doc); + if (doc == NULL) + { + return FALSE; + } - return FALSE; - } + cur = xmlDocGetRootElement (doc); + if (cur == NULL) + { + g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); + xmlFreeDoc (doc); - if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) - { - g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename)); - xmlFreeDoc (doc); + return TRUE; + } - return FALSE; - } + if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) + { + g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename)); + xmlFreeDoc (doc); - cur = xmlDocGetRootElement (doc); - cur = cur->xmlChildrenNode; + return FALSE; + } - while (cur != NULL) - { - parseItem (doc, cur); + cur = xmlDocGetRootElement (doc); + cur = cur->xmlChildrenNode; - cur = cur->next; - } + while (cur != NULL) + { + parseItem (doc, cur); - xmlFreeDoc (doc); + cur = cur->next; + } - return TRUE; + xmlFreeDoc (doc); + + return TRUE; } /** @@ -298,48 +295,51 @@ load_values (void) */ gchar * xed_metadata_manager_get (GFile *location, - const gchar *key) + const gchar *key) { - Item *item; - gchar *value; - gchar *uri; + Item *item; + gchar *value; + gchar *uri; - g_return_val_if_fail (G_IS_FILE (location), NULL); - g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (G_IS_FILE (location), NULL); + g_return_val_if_fail (key != NULL, NULL); - uri = g_file_get_uri (location); + uri = g_file_get_uri (location); - xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key ); + xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key ); - if (!xed_metadata_manager->values_loaded) - { - gboolean res; + if (!xed_metadata_manager->values_loaded) + { + gboolean res; - res = load_values (); + res = load_values (); - if (!res) - return NULL; - } + if (!res) + { + g_free (uri); + return NULL; + } + } - item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, - uri); + item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, + uri); - g_free (uri); + g_free (uri); - if (item == NULL) - return NULL; + if (item == NULL) + return NULL; - item->atime = time (NULL); + item->atime = g_get_real_time () / 1000; - if (item->values == NULL) - return NULL; + if (item->values == NULL) + return NULL; - value = g_hash_table_lookup (item->values, key); + value = g_hash_table_lookup (item->values, key); - if (value == NULL) - return NULL; - else - return g_strdup (value); + if (value == NULL) + return NULL; + else + return g_strdup (value); } /** @@ -352,219 +352,221 @@ xed_metadata_manager_get (GFile *location, */ void xed_metadata_manager_set (GFile *location, - const gchar *key, - const gchar *value) + const gchar *key, + const gchar *value) { - Item *item; - gchar *uri; + Item *item; + gchar *uri; - g_return_if_fail (G_IS_FILE (location)); - g_return_if_fail (key != NULL); + g_return_if_fail (G_IS_FILE (location)); + g_return_if_fail (key != NULL); - uri = g_file_get_uri (location); + uri = g_file_get_uri (location); - xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value); + xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value); - if (!xed_metadata_manager->values_loaded) - { - gboolean res; + if (!xed_metadata_manager->values_loaded) + { + gboolean ok; - res = load_values (); + ok = load_values (); - if (!res) - return; - } + if (!ok) + { + g_free (uri); + return; + } + } - item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, - uri); + item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, + uri); - if (item == NULL) - { - item = g_new0 (Item, 1); + if (item == NULL) + { + item = g_new0 (Item, 1); - g_hash_table_insert (xed_metadata_manager->items, - g_strdup (uri), - item); - } + g_hash_table_insert (xed_metadata_manager->items, + g_strdup (uri), + item); + } - if (item->values == NULL) - item->values = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - if (value != NULL) - g_hash_table_insert (item->values, - g_strdup (key), - g_strdup (value)); - else - g_hash_table_remove (item->values, - key); + if (item->values == NULL) + item->values = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + if (value != NULL) + g_hash_table_insert (item->values, + g_strdup (key), + g_strdup (value)); + else + g_hash_table_remove (item->values, + key); - item->atime = time (NULL); + item->atime = g_get_real_time () / 1000; - g_free (uri); + g_free (uri); - xed_metadata_manager_arm_timeout (); + xed_metadata_manager_arm_timeout (); } static void save_values (const gchar *key, const gchar *value, xmlNodePtr parent) { - xmlNodePtr xml_node; + xmlNodePtr xml_node; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - g_return_if_fail (key != NULL); + g_return_if_fail (key != NULL); - if (value == NULL) - return; + if (value == NULL) + return; - xml_node = xmlNewChild (parent, - NULL, - (const xmlChar *)"entry", - NULL); + xml_node = xmlNewChild (parent, + NULL, + (const xmlChar *)"entry", + NULL); - xmlSetProp (xml_node, - (const xmlChar *)"key", - (const xmlChar *)key); - xmlSetProp (xml_node, - (const xmlChar *)"value", - (const xmlChar *)value); + xmlSetProp (xml_node, + (const xmlChar *)"key", + (const xmlChar *)key); + xmlSetProp (xml_node, + (const xmlChar *)"value", + (const xmlChar *)value); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); + xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); #endif } static void save_item (const gchar *key, const gpointer *data, xmlNodePtr parent) { - xmlNodePtr xml_node; - const Item *item = (const Item *)data; - gchar *atime; + xmlNodePtr xml_node; + const Item *item = (const Item *)data; + gchar *atime; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - g_return_if_fail (key != NULL); + g_return_if_fail (key != NULL); - if (item == NULL) - return; + if (item == NULL) + return; - xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL); + xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL); - xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key); + xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "uri: %s", key); + xed_debug_message (DEBUG_METADATA, "uri: %s", key); #endif - atime = g_strdup_printf ("%ld", item->atime); - xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); + atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime); + xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "atime: %s", atime); + xed_debug_message (DEBUG_METADATA, "atime: %s", atime); #endif - g_free (atime); + g_free (atime); - g_hash_table_foreach (item->values, - (GHFunc)save_values, - xml_node); + g_hash_table_foreach (item->values, + (GHFunc)save_values, + xml_node); } static void get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove) { - const Item *item = (const Item *)value; + const Item *item = (const Item *)value; - if (*key_to_remove == NULL) - { - *key_to_remove = key; - } - else - { - const Item *item_to_remove = - g_hash_table_lookup (xed_metadata_manager->items, - *key_to_remove); + if (*key_to_remove == NULL) + { + *key_to_remove = key; + } + else + { + const Item *item_to_remove = + g_hash_table_lookup (xed_metadata_manager->items, + *key_to_remove); - g_return_if_fail (item_to_remove != NULL); + g_return_if_fail (item_to_remove != NULL); - if (item->atime < item_to_remove->atime) - { - *key_to_remove = key; - } - } + if (item->atime < item_to_remove->atime) + { + *key_to_remove = key; + } + } } static void resize_items (void) { - while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS) - { - gpointer key_to_remove = NULL; + while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS) + { + gpointer key_to_remove = NULL; - g_hash_table_foreach (xed_metadata_manager->items, - (GHFunc)get_oldest, - &key_to_remove); + g_hash_table_foreach (xed_metadata_manager->items, + (GHFunc)get_oldest, + &key_to_remove); - g_return_if_fail (key_to_remove != NULL); + g_return_if_fail (key_to_remove != NULL); - g_hash_table_remove (xed_metadata_manager->items, - key_to_remove); - } + g_hash_table_remove (xed_metadata_manager->items, + key_to_remove); + } } static gboolean xed_metadata_manager_save (gpointer data) { - xmlDocPtr doc; - xmlNodePtr root; + xmlDocPtr doc; + xmlNodePtr root; - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - xed_metadata_manager->timeout_id = 0; + xed_metadata_manager->timeout_id = 0; - resize_items (); + resize_items (); - xmlIndentTreeOutput = TRUE; + xmlIndentTreeOutput = TRUE; - doc = xmlNewDoc ((const xmlChar *)"1.0"); - if (doc == NULL) - return TRUE; + doc = xmlNewDoc ((const xmlChar *)"1.0"); + if (doc == NULL) + return TRUE; - /* Create metadata root */ - root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL); - xmlDocSetRootElement (doc, root); + /* Create metadata root */ + root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL); + xmlDocSetRootElement (doc, root); - g_hash_table_foreach (xed_metadata_manager->items, - (GHFunc)save_item, - root); + g_hash_table_foreach (xed_metadata_manager->items, + (GHFunc)save_item, + root); - /* FIXME: lock file - Paolo */ - if (xed_metadata_manager->metadata_filename != NULL) - { - gchar *cache_dir; - int res; + /* FIXME: lock file - Paolo */ + if (xed_metadata_manager->metadata_filename != NULL) + { + gchar *cache_dir; + int res; - /* make sure the cache dir exists */ - cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename); - res = g_mkdir_with_parents (cache_dir, 0755); - if (res != -1) - { - xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1); - } + /* make sure the cache dir exists */ + cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename); + res = g_mkdir_with_parents (cache_dir, 0755); + if (res != -1) + { + xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1); + } - g_free (cache_dir); - } + g_free (cache_dir); + } - xmlFreeDoc (doc); + xmlFreeDoc (doc); - xed_debug_message (DEBUG_METADATA, "DONE"); + xed_debug_message (DEBUG_METADATA, "DONE"); - return FALSE; + return FALSE; } - diff --git a/xed/xed-metadata-manager.h b/xed/xed-metadata-manager.h index dd682f7..c794a2a 100644 --- a/xed/xed-metadata-manager.h +++ b/xed/xed-metadata-manager.h @@ -30,7 +30,7 @@ #ifndef __XED_METADATA_MANAGER_H__ #define __XED_METADATA_MANAGER_H__ -#include +#include G_BEGIN_DECLS diff --git a/xed/xed-tab.c b/xed/xed-tab.c index 5c89645..7dc4986 100644 --- a/xed/xed-tab.c +++ b/xed/xed-tab.c @@ -43,6 +43,8 @@ #include "xed-print-preview.h" #include "xed-progress-info-bar.h" #include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-enum-types.h" #include "xed-settings.h" #include "xed-view-frame.h" @@ -1112,39 +1114,39 @@ view_focused_in (GtkWidget *widget, XedTab *tab) { XedDocument *doc; + GtkSourceFile *file; g_return_val_if_fail (XED_IS_TAB (tab), FALSE); /* we try to detect file changes only in the normal state */ if (tab->priv->state != XED_TAB_STATE_NORMAL) { - return FALSE; + return GDK_EVENT_PROPAGATE; } /* we already asked, don't bug the user again */ if (!tab->priv->ask_if_externally_modified) { - return FALSE; + return GDK_EVENT_PROPAGATE; } doc = xed_tab_get_document (tab); + file = xed_document_get_file (doc); /* If file was never saved or is remote we do not check */ - if (!xed_document_is_local (doc)) + if (gtk_source_file_is_local (file)) { - return FALSE; + gtk_source_file_check_file_on_disk (file); + + if (gtk_source_file_is_externally_modified (file)) + { + xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION); + + display_externally_modified_notification (tab); + } } - if (_xed_document_check_externally_modified (doc)) - { - xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION); - - display_externally_modified_notification (tab); - - return FALSE; - } - - return FALSE; + return GDK_EVENT_PROPAGATE; } static void diff --git a/xed/xed-window.c b/xed/xed-window.c index 9d8e369..7227c1a 100644 --- a/xed/xed-window.c +++ b/xed/xed-window.c @@ -20,6 +20,8 @@ #include "xed-utils.h" #include "xed-commands.h" #include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-panel.h" #include "xed-documents-panel.h" #include "xed-plugins-engine.h" From bc18f166a3301eac6cf3f9c101e71b0c95889abc Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 00:25:34 -0800 Subject: [PATCH 02/18] preferences-dialog: Complete revamp Use the new XApps preferences window as the base for a total redesign of the new dialog. While at it port to GtkSourceStyleSchemeChooserWidget. --- configure.ac | 1 + debian/control | 3 +- xed/resources/ui/xed-preferences-dialog.ui | 1999 +++++++++----------- xed/xed-preferences-dialog.c | 1136 +++++------ xed/xed-preferences-dialog.h | 59 +- 5 files changed, 1340 insertions(+), 1858 deletions(-) diff --git a/configure.ac b/configure.ac index 90d461b..aaf0017 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,7 @@ PKG_CHECK_MODULES(XED, [ gtksourceview-3.0 >= 3.19.0 libpeas-1.0 >= 1.12.0 libpeas-gtk-1.0 >= 1.12.0 + xapp ]) PKG_CHECK_MODULES(X11, [x11]) diff --git a/debian/control b/debian/control index b7544aa..493e733 100644 --- a/debian/control +++ b/debian/control @@ -14,6 +14,7 @@ Build-Depends: autotools-dev, libgtk-3-dev, libgtksourceview-3.0-dev, libpeas-dev, + libxapp-dev, libsm-dev, libx11-dev, libxml2-dev, @@ -145,4 +146,4 @@ Description: Text editor (documentation files) includes support for spell checking, comparing files, viewing CVS ChangeLogs, and adjusting indentation levels. . - This package contains the documentation files. \ No newline at end of file + This package contains the documentation files. diff --git a/xed/resources/ui/xed-preferences-dialog.ui b/xed/resources/ui/xed-preferences-dialog.ui index 5975d36..00bf20d 100755 --- a/xed/resources/ui/xed-preferences-dialog.ui +++ b/xed/resources/ui/xed-preferences-dialog.ui @@ -1,260 +1,121 @@ - + + - 1 - 160 - 80 - 1 - 10 - - 1 24 - 8 + 4 1 4 - + 1 - 100 - 8 + 160 + 120 1 10 - + + True False - gtk-add - - - False - Preferences - False - True - dialog - - + vertical + + True - False - vertical - - + True + never + + True False - end - - gtk-help - True - True - True - False - True - - - False - False - 0 - - - - - gtk-close - True - True - True - False - True - - - False - False - 1 - - - - - False - False - end - 0 - - - - - True - True - 6 - - + True False 12 - 18 + vertical + 6 - + True False - 6 - - - True - False - Text Wrapping - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - Enable text _wrapping - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - Do not _split words over two lines - True - True - False - True - 0.5 - True - - - False - False - 1 - - - - - True - True - 1 - - - - - True - True - 1 - - + Font + 0 + + + + - True + False True 0 - + True False - 6 + 32 + 32 + vertical - - True - False - Line Numbers - 0 - - - - - - False - False - 0 - - - - + True False - + True False - + Use the system fixed width font (%s) + 0 False - False + True 0 - + True - False - 6 - - - _Display line numbers - True - True - False - True - 0.5 - True - - - False - False - 0 - - + True - True + False True + end 1 - True + False + True + 0 + + + + + True + False + 175 + True + + + True + True + True + 6 + Sans 12 + + + + + + False True 1 @@ -262,304 +123,63 @@ False - False + True 1 - + True False - 6 - - - True - False - Current Line - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - Highlight current _line - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - True - 1 - - - - - True - True - 1 - - - - - False - True - 2 - - - - - True - False - 6 - - - True - False - Right Margin - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - Display right _margin - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - False - 6 - - - True - False - _Right margin at column: - True - right_margin_position_spinbutton - 0 - - - False - False - 0 - - - - - True - True - adjustment1 - 1 - True - True - - - False - False - 1 - - - - - False - False - 1 - - - - - True - True - 1 - - - - - True - True - 1 - - + Display + 0 + + + + False False - 3 - - - - - True - False - 6 - - - True - False - Bracket Matching - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - Highlight matching _bracket - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - True - 1 - - - - - True - True - 1 - - - - - True - True - 4 + 2 True False + 32 + 32 vertical - 6 - + True False - Overview Map - 0 - - - + + + True + False + Display line numbers + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + False @@ -568,14 +188,223 @@ - - Display overview map + True - True - False - 12 - 0 - True + False + 6 + + + True + False + Display overview map + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 1 + + + + + True + False + 6 + + + True + False + Display right margin + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 2 + + + + + True + False + 175 + + + True + False + 6 + + + True + False + Right margin at column + 0 + + + False + True + 0 + + + + + True + True + 4 + adjustment2 + 4 + + + False + True + end + 1 + + + + + + + False + True + 3 + + + + + False + True + 3 + + + + + True + False + Highlighting + 0 + + + + + + + False + False + 4 + + + + + True + False + 32 + 32 + vertical + 6 + + + True + False + + + True + False + Highlight the current line + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 0 + + + + + True + False + + + True + False + Highlight matching brackets + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + False @@ -585,371 +414,70 @@ - True + False True 5 - - - - - True - False - View - - - False - - - - - True - False - 12 - 18 - + True False - 6 - - - True - False - Tab Stops - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - True - False - 6 - - - True - False - _Tab width: - True - center - tabs_width_spinbutton - - - False - False - 0 - - - - - True - True - adjustment2 - 1 - True - - - False - False - 1 - - - - - True - True - 0 - - - - - Insert _spaces instead of tabs - True - True - False - True - 0.5 - True - - - False - False - 1 - - - - - False - False - 1 - - - - - False - False - 1 - - + Indentation + 0 + + + + False False - 0 + 6 - - True - False - 6 - - - True - False - Automatic Indentation - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - _Enable automatic indentation - True - True - False - True - 0.5 - True - - - False - False - 1 - - - - - False - False - 1 - - - - - False - False - 1 - - - - - True - False - 6 - - - True - False - File Saving - 0 - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - Create a _backup copy of files before saving - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - False - 6 - - - _Autosave files every - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - True - adjustment3 - 1 - True - - - False - False - 1 - - - - - True - False - _minutes - True - center - auto_save_spinbutton - - - False - False - 2 - - - - - True - True - 1 - - - - - False - False - 1 - - - - - True - True - 1 - - - - - False - False - 2 - - - - + True False + 32 + 32 vertical 6 - + True False - Tab Scrolling - 0 - - - + + + True + False + Tab width + 0 + + + False + True + 0 + + + + + True + True + adjustment1 + + + False + True + end + 1 + + False - False + True 0 @@ -958,10 +486,11 @@ True False - + True False - + Use spaces instead of tabs + 0 False @@ -970,172 +499,282 @@ - - Allow mouse wheel scrolling to change tabs + True True - False - 0 - True False True + end 1 False - False + True + 1 + + + + + True + False + + + True + False + Automatic indentation + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 2 + + + + + False + True + 7 + + + + + True + False + Word wrap + 0 + + + + + + + False + True + 8 + + + + + True + False + 32 + 32 + vertical + 6 + + + True + False + + + True + False + Word wrap + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 0 + + + + + True + False + 175 + True + + + True + False + + + True + False + Split words over two lines + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + + + False + True 1 - True + False True - 3 + 9 - - - 1 - - - - - True - False - Editor - - - 1 - False - - - - - True - False - 12 - 18 - + True False - 6 + Tab scrolling + 0 + + + + + + + False + True + 10 + + + + + True + False + 32 + 32 - + True False - Font + Allow mouse wheel scrolling to change tabs 0 - - - False - False + True 0 - + True - False - - - True - False - - - - False - False - 0 - - - - - True - False - 6 - - - _Use the system fixed width font (%s) - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - False - 12 - - - True - False - Editor _font: - True - center - font_button - 0 - - - False - False - 0 - - - - - True - True - False - Sans 12 - Pick the editor font - True - - - True - True - 1 - - - - - False - False - 1 - - - - - True - True - 1 - - + True - True + False True + end 1 + + False + True + 11 + + + + + + + + + True + True + 0 + + + + + 100 + 1 + 10 + + + True + False + vertical + + + True + True + never + + + True + False + + + True + False + 12 + vertical + 6 + + + True + False + File saving + 0 + + + + + False False @@ -1143,188 +782,232 @@ - + True False + 32 + 32 + vertical 6 - - True - False - Color Scheme - 0 - - - - - - False - False - 0 - - - - - Use dark theme variant (if available) - True - True - False - 12 - 0 - True - - - False - False - 1 - - - - + True False - + True False - + Create a backup copy of files before saving + 0 False - False + True 0 - + True - False - 6 - - - True - True - etched-in - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - - - - - True - True - 0 - - - - - True - False - 6 - end - - - _Add... - True - True - False - install_scheme_image - True - - - False - False - 0 - - - - - gtk-remove - True - True - False - True - - - False - False - 1 - - - - - False - True - 1 - - + True - True + False True + end 1 - True + False + True + 0 + + + + + True + False + + + True + False + Autosave files + 0 + + + False + True + 0 + + + + + True + True + + + False + True + end + 1 + + + + + False + True + 1 + + + + + True + False + 175 + True + + + True + False + + + True + False + Minutes between saving + 0 + + + False + True + 0 + + + + + True + True + adjustment3 + 1 + True + + + False + True + end + 1 + + + + + + + False True 2 - True + False True 1 - - - 2 - - - - - True - False - Font & Colors - - - 2 - False - - - - - True - False - 12 - - 3 - - - + + + + + True + True + 0 + + + + + True + False + vertical + + + True + False + 12 + vertical + + + + + + True + True + 0 + + + + + True + False + vertical + + + True + False + 12 + vertical + 6 + + + True + False + Dark theme + 0 + + + + + + + False + False + 0 + + + + + True + False + 32 + 32 + + True False - Plugins + Use dark theme variant (if available) + 0 - 3 - False + False + True + 0 + + + + + True + True + + + False + True + end + 1 @@ -1334,11 +1017,135 @@ 1 + + + True + False + Style scheme + 0 + + + + + + + False + False + 2 + + + + + True + False + 32 + 32 + vertical + + + True + True + never + in + + + True + False + + + True + False + + + + + + + True + True + 0 + + + + + True + False + + + True + False + 6 + + + True + True + True + Install scheme + + + True + False + list-add-symbolic + + + + + False + True + 0 + + + + + True + True + True + Remove scheme + + + True + False + list-remove-symbolic + + + + + False + True + 1 + + + + + False + True + end + 0 + + + + + + False + True + 1 + + + + + True + True + 3 + + + + True + True + 1 + - - helpbutton1 - closebutton1 - diff --git a/xed/xed-preferences-dialog.c b/xed/xed-preferences-dialog.c index 2e3ad43..32faf6f 100755 --- a/xed/xed-preferences-dialog.c +++ b/xed/xed-preferences-dialog.c @@ -62,95 +62,86 @@ static GtkWidget *preferences_dialog = NULL; -enum +#define XED_TYPE_PREFERENCES_DIALOG (xed_preferences_dialog_get_type ()) + +G_DECLARE_FINAL_TYPE (XedPreferencesDialog, xed_preferences_dialog, XED, PREFERENCES_DIALOG, XAppPreferencesWindow) + +struct _XedPreferencesDialog { - ID_COLUMN = 0, - NAME_COLUMN, - DESC_COLUMN, - NUM_COLUMNS -}; + XAppPreferencesWindow parent_instance; + GSettings *editor_settings; + GSettings *ui_settings; -#define XED_PREFERENCES_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ - XED_TYPE_PREFERENCES_DIALOG, \ - XedPreferencesDialogPrivate)) - -struct _XedPreferencesDialogPrivate -{ - GSettings *editor; - GSettings *ui; - - GtkWidget *notebook; - - /* Font */ - GtkWidget *default_font_checkbutton; - GtkWidget *font_button; - GtkWidget *font_hbox; - - /* Style Scheme */ - GtkWidget *prefer_dark_theme_checkbutton; - GtkListStore *schemes_treeview_model; - GtkWidget *schemes_treeview; - GtkWidget *install_scheme_button; - GtkWidget *uninstall_scheme_button; - - GtkWidget *install_scheme_file_schooser; - - /* Tabs */ - GtkWidget *tabs_width_spinbutton; - GtkWidget *insert_spaces_checkbutton; - GtkWidget *tabs_width_hbox; - - /* Auto indentation */ - GtkWidget *auto_indent_checkbutton; - - /* Text Wrapping */ - GtkWidget *wrap_text_checkbutton; - GtkWidget *split_checkbutton; + /* Main pages */ + GtkWidget *editor_page; + GtkWidget *save_page; + GtkWidget *theme_page; + GtkWidget *plugins_page; /* File Saving */ - GtkWidget *backup_copy_checkbutton; - GtkWidget *auto_save_checkbutton; - GtkWidget *auto_save_spinbutton; - GtkWidget *autosave_hbox; + GtkWidget *backup_copy_switch; + GtkWidget *auto_save_switch; + GtkWidget *auto_save_spin; + GtkWidget *auto_save_revealer; - /* Line numbers */ - GtkWidget *display_line_numbers_checkbutton; + /* Font */ + GtkWidget *fixed_width_font_label; + GtkWidget *fixed_width_font_switch; + GtkWidget *font_button_revealer; + GtkWidget *font_button; - /* Highlight current line */ - GtkWidget *highlight_current_line_checkbutton; - - /* Highlight matching bracket */ - GtkWidget *bracket_matching_checkbutton; + /* Display */ + GtkWidget *display_line_numbers_switch; /* Minimap */ - GtkWidget *mini_map_checkbutton; + GtkWidget *minimap_switch; /* Right margin */ - GtkWidget *right_margin_checkbutton; - GtkWidget *right_margin_position_spinbutton; - GtkWidget *right_margin_position_hbox; + GtkWidget *display_right_margin_switch; + GtkWidget *right_margin_spin; + GtkWidget *right_margin_revealer; + + /* Highlight current line */ + GtkWidget *highlight_current_line_switch; + + /* Highlight matching bracket */ + GtkWidget *highlight_matching_bracket_switch; + + /* Tabs */ + GtkWidget *tab_width_spin; + GtkWidget *use_spaces_switch; + GtkWidget *automatic_indentation_switch; + + /* Word wrap */ + GtkWidget *word_wrap_switch; + GtkWidget *split_words_revealer; + GtkWidget *split_words_switch; /* Tab scrolling */ - GtkWidget *tab_scrolling_checkbutton; + GtkWidget *tab_scrolling_switch; + + /* Style scheme */ + GtkWidget *prefer_dark_theme_switch; + GtkWidget *schemes_list; + GtkWidget *install_scheme_button; + GtkWidget *uninstall_scheme_button; + GtkWidget *install_scheme_file_schooser; /* Plugins manager */ - GtkWidget *plugin_manager_place_holder; - - /* Style Scheme editor dialog */ - GtkWidget *style_scheme_dialog; + GtkWidget *plugin_manager_place_holder; }; -G_DEFINE_TYPE(XedPreferencesDialog, xed_preferences_dialog, GTK_TYPE_DIALOG) +G_DEFINE_TYPE(XedPreferencesDialog, xed_preferences_dialog, XAPP_TYPE_PREFERENCES_WINDOW) static void xed_preferences_dialog_dispose (GObject *object) { XedPreferencesDialog *dlg = XED_PREFERENCES_DIALOG (object); - g_clear_object (&dlg->priv->editor); - g_clear_object (&dlg->priv->ui); + g_clear_object (&dlg->editor_settings); + g_clear_object (&dlg->ui_settings); G_OBJECT_CLASS (xed_preferences_dialog_parent_class)->dispose (object); } @@ -159,291 +150,302 @@ static void xed_preferences_dialog_class_init (XedPreferencesDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = xed_preferences_dialog_dispose; - g_type_class_add_private (object_class, sizeof (XedPreferencesDialogPrivate)); + gtk_widget_class_set_template_from_resource (widget_class, "/org/x/editor/ui/xed-preferences-dialog.ui"); + + /* Pages */ + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, editor_page); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, save_page); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, theme_page); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, plugins_page); + + /* Editor Page widgets */ + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, fixed_width_font_label); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, fixed_width_font_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, font_button_revealer); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, font_button); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, display_line_numbers_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, minimap_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, display_right_margin_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, right_margin_spin); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, right_margin_revealer); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, highlight_current_line_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, highlight_matching_bracket_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, tab_width_spin); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, use_spaces_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, automatic_indentation_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, word_wrap_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, split_words_revealer); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, split_words_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, tab_scrolling_switch); + + /* Save page widgets */ + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, backup_copy_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, auto_save_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, auto_save_spin); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, auto_save_revealer); + + /* Theme page widgets */ + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, prefer_dark_theme_switch); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, schemes_list); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, install_scheme_button); + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, uninstall_scheme_button); + + /* Plugin page widgets */ + gtk_widget_class_bind_template_child (widget_class, XedPreferencesDialog, plugin_manager_place_holder); } static void -dialog_response_handler (GtkDialog *dlg, - gint res_id) +close_button_clicked (GtkButton *button, + gpointer data) { + XedPreferencesDialog *dlg = XED_PREFERENCES_DIALOG (data); + xed_debug (DEBUG_PREFS); - switch (res_id) + gtk_widget_destroy (GTK_WIDGET (dlg)); +} + +static void +help_button_clicked (GtkButton *button, + gpointer data) +{ + XedPreferencesDialog *dlg = XED_PREFERENCES_DIALOG (data); + + xed_debug (DEBUG_PREFS); + + xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-prefs"); +} + +static void +word_wrap_switch_toggled (GObject *toggle_switch, + GParamSpec *pspec, + gpointer data) +{ + XedPreferencesDialog *dlg = XED_PREFERENCES_DIALOG (data); + GtkWrapMode mode; + + if (!gtk_switch_get_active (GTK_SWITCH (dlg->word_wrap_switch))) { - case GTK_RESPONSE_HELP: - xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-prefs"); - g_signal_stop_emission_by_name (dlg, "response"); - break; - default: - gtk_widget_destroy (GTK_WIDGET (dlg)); + mode = GTK_WRAP_NONE; + + gtk_revealer_set_reveal_child (GTK_REVEALER (dlg->split_words_revealer), FALSE); } -} + else + { + gtk_revealer_set_reveal_child (GTK_REVEALER (dlg->split_words_revealer), TRUE); -static void -on_auto_save_changed (GSettings *settings, - const gchar *key, - XedPreferencesDialog *dlg) -{ - gboolean value; + if (gtk_switch_get_active (GTK_SWITCH (dlg->split_words_switch))) + { + mode = GTK_WRAP_CHAR; + } + else + { + mode = GTK_WRAP_WORD; + } + } - xed_debug (DEBUG_PREFS); - - value = g_settings_get_boolean (settings, key); - - gtk_widget_set_sensitive (dlg->priv->auto_save_spinbutton, value); + g_settings_set_enum (dlg->editor_settings, XED_SETTINGS_WRAP_MODE, mode); } static void setup_editor_page (XedPreferencesDialog *dlg) { - gboolean auto_save; - - xed_debug (DEBUG_PREFS); - - /* Get values */ - auto_save = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_AUTO_SAVE); - - /* Set widget sensitivity */ - gtk_widget_set_sensitive (dlg->priv->auto_save_spinbutton, auto_save); - - /* Connect signal */ - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_TABS_SIZE, - dlg->priv->tabs_width_spinbutton, - "value", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_INSERT_SPACES, - dlg->priv->insert_spaces_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_AUTO_INDENT, - dlg->priv->auto_indent_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_CREATE_BACKUP_COPY, - dlg->priv->backup_copy_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_BRACKET_MATCHING, - dlg->priv->bracket_matching_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_AUTO_SAVE_INTERVAL, - dlg->priv->auto_save_spinbutton, - "value", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_signal_connect (dlg->priv->editor, "changed::auto_save", - G_CALLBACK (on_auto_save_changed), dlg); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_AUTO_SAVE, - dlg->priv->auto_save_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->ui, - XED_SETTINGS_ENABLE_TAB_SCROLLING, - dlg->priv->tab_scrolling_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); -} - -static gboolean split_button_state = TRUE; - -static void -wrap_mode_checkbutton_toggled (GtkToggleButton *button, - XedPreferencesDialog *dlg) -{ - GtkWrapMode mode; - - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton))) - { - mode = GTK_WRAP_NONE; - - gtk_widget_set_sensitive (dlg->priv->split_checkbutton, FALSE); - gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); - } - else - { - gtk_widget_set_sensitive (dlg->priv->split_checkbutton, TRUE); - gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), FALSE); - - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton))) - { - split_button_state = TRUE; - mode = GTK_WRAP_WORD; - } - else - { - split_button_state = FALSE; - mode = GTK_WRAP_CHAR; - } - } - - g_settings_set_enum (dlg->priv->editor, XED_SETTINGS_WRAP_MODE, mode); -} - -static void -right_margin_checkbutton_toggled (GtkToggleButton *button, - XedPreferencesDialog *dlg) -{ - gboolean active; - - g_return_if_fail (button == GTK_TOGGLE_BUTTON (dlg->priv->right_margin_checkbutton)); - - active = gtk_toggle_button_get_active (button); - - g_settings_set_boolean (dlg->priv->editor, XED_SETTINGS_DISPLAY_RIGHT_MARGIN, active); - - gtk_widget_set_sensitive (dlg->priv->right_margin_position_hbox, active); -} - -static void -setup_view_page (XedPreferencesDialog *dlg) -{ + XedSettings *settings; + gchar *system_font = NULL; + gchar *label_text; GtkWrapMode wrap_mode; - gboolean display_right_margin; xed_debug (DEBUG_PREFS); - /* Get values */ - display_right_margin = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_DISPLAY_RIGHT_MARGIN); + /* Fonts */ + settings = _xed_app_get_settings (XED_APP (g_application_get_default ())); + system_font = xed_settings_get_system_font (settings); - /* Set initial state */ - wrap_mode = g_settings_get_enum (dlg->priv->editor, XED_SETTINGS_WRAP_MODE); + label_text = g_strdup_printf(_("Use the system fixed width font (%s)"), system_font); + gtk_label_set_text (GTK_LABEL (dlg->fixed_width_font_label), label_text); + g_free (system_font); + g_free (label_text); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_USE_DEFAULT_FONT, + dlg->fixed_width_font_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_object_bind_property (dlg->fixed_width_font_switch, + "active", + dlg->font_button_revealer, + "reveal-child", + G_BINDING_SYNC_CREATE | G_BINDING_DEFAULT | G_BINDING_INVERT_BOOLEAN); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_EDITOR_FONT, + dlg->font_button, + "font-name", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + /* Display */ + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_DISPLAY_RIGHT_MARGIN, + dlg->display_right_margin_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_object_bind_property (dlg->display_right_margin_switch, + "active", + dlg->right_margin_revealer, + "reveal-child", + G_BINDING_SYNC_CREATE | G_BINDING_DEFAULT); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_DISPLAY_LINE_NUMBERS, + dlg->display_line_numbers_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_settings_bind (dlg->ui_settings, + XED_SETTINGS_MINIMAP_VISIBLE, + dlg->minimap_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_RIGHT_MARGIN_POSITION, + dlg->right_margin_spin, + "value", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + /* Highlighting */ + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_HIGHLIGHT_CURRENT_LINE, + dlg->highlight_current_line_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_BRACKET_MATCHING, + dlg->highlight_matching_bracket_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + /* Indentation */ + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_TABS_SIZE, + dlg->tab_width_spin, + "value", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_INSERT_SPACES, + dlg->use_spaces_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_AUTO_INDENT, + dlg->automatic_indentation_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + /* Word wrap */ + wrap_mode = g_settings_get_enum (dlg->editor_settings, XED_SETTINGS_WRAP_MODE); switch (wrap_mode) { case GTK_WRAP_WORD: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); + gtk_switch_set_active (GTK_SWITCH (dlg->word_wrap_switch), TRUE); + gtk_revealer_set_reveal_child (GTK_REVEALER (dlg->split_words_revealer), TRUE); + gtk_switch_set_active (GTK_SWITCH (dlg->split_words_switch), FALSE); break; case GTK_WRAP_CHAR: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), FALSE); + gtk_switch_set_active (GTK_SWITCH (dlg->word_wrap_switch), TRUE); + gtk_revealer_set_reveal_child (GTK_REVEALER (dlg->split_words_revealer), TRUE); + gtk_switch_set_active (GTK_SWITCH (dlg->split_words_switch), TRUE); break; default: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->wrap_text_checkbutton), FALSE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), split_button_state); - gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (dlg->priv->split_checkbutton), TRUE); - + gtk_switch_set_active (GTK_SWITCH (dlg->word_wrap_switch), FALSE); + gtk_revealer_set_reveal_child (GTK_REVEALER (dlg->split_words_revealer), FALSE); } - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->right_margin_checkbutton), display_right_margin); + g_signal_connect (dlg->word_wrap_switch, "notify::active", + G_CALLBACK (word_wrap_switch_toggled), dlg); + g_signal_connect (dlg->split_words_switch, "notify::active", + G_CALLBACK (word_wrap_switch_toggled), dlg); - /* Set widgets sensitivity */ - gtk_widget_set_sensitive (dlg->priv->split_checkbutton, (wrap_mode != GTK_WRAP_NONE)); - gtk_widget_set_sensitive (dlg->priv->right_margin_position_hbox, display_right_margin); - - /* Connect signals */ - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_DISPLAY_LINE_NUMBERS, - dlg->priv->display_line_numbers_checkbutton, + /* Tab scrolling */ + g_settings_bind (dlg->ui_settings, + XED_SETTINGS_ENABLE_TAB_SCROLLING, + dlg->tab_scrolling_switch, "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_HIGHLIGHT_CURRENT_LINE, - dlg->priv->highlight_current_line_checkbutton, + + xapp_preferences_window_add_page (XAPP_PREFERENCES_WINDOW (dlg), dlg->editor_page, "editor", _("Editor")); +} + +static void +setup_save_page (XedPreferencesDialog *dlg) +{ + xed_debug (DEBUG_PREFS); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_CREATE_BACKUP_COPY, + dlg->backup_copy_switch, "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_RIGHT_MARGIN_POSITION, - dlg->priv->right_margin_position_spinbutton, + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_AUTO_SAVE, + dlg->auto_save_switch, + "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + g_object_bind_property (dlg->auto_save_switch, + "active", + dlg->auto_save_revealer, + "reveal-child", + G_BINDING_SYNC_CREATE | G_BINDING_DEFAULT); + + g_settings_bind (dlg->editor_settings, + XED_SETTINGS_AUTO_SAVE_INTERVAL, + dlg->auto_save_spin, "value", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->ui, - XED_SETTINGS_MINIMAP_VISIBLE, - dlg->priv->mini_map_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_signal_connect (dlg->priv->wrap_text_checkbutton, "toggled", - G_CALLBACK (wrap_mode_checkbutton_toggled), dlg); - g_signal_connect (dlg->priv->split_checkbutton, "toggled", - G_CALLBACK (wrap_mode_checkbutton_toggled), dlg); - g_signal_connect (dlg->priv->right_margin_checkbutton, "toggled", - G_CALLBACK (right_margin_checkbutton_toggled), dlg); + + xapp_preferences_window_add_page (XAPP_PREFERENCES_WINDOW (dlg), dlg->save_page, "save", _("Save")); } -static void -on_use_default_font_changed (GSettings *settings, - const gchar *key, - XedPreferencesDialog *dlg) -{ - gboolean value; - - xed_debug (DEBUG_PREFS); - - value = g_settings_get_boolean (settings, key); - gtk_widget_set_sensitive (dlg->priv->font_hbox, !value); -} - -static void -setup_font_colors_page_font_section (XedPreferencesDialog *dlg) -{ - GObject *settings; - gboolean use_default_font; - gchar *system_font = NULL; - gchar *label; - - xed_debug (DEBUG_PREFS); - - gtk_widget_set_tooltip_text (dlg->priv->font_button, - _("Click on this button to select the font to be used by the editor")); - - xed_utils_set_atk_relation (dlg->priv->font_button, - dlg->priv->default_font_checkbutton, - ATK_RELATION_CONTROLLED_BY); - xed_utils_set_atk_relation (dlg->priv->default_font_checkbutton, - dlg->priv->font_button, - ATK_RELATION_CONTROLLER_FOR); - - /* Get values */ - settings = _xed_app_get_settings (XED_APP (g_application_get_default ())); - system_font = xed_settings_get_system_font (XED_SETTINGS (settings)); - use_default_font = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_USE_DEFAULT_FONT); - - label = g_strdup_printf(_("_Use the system fixed width font (%s)"), system_font); - gtk_button_set_label (GTK_BUTTON (dlg->priv->default_font_checkbutton), label); - g_free (system_font); - g_free (label); - - /* read current config and setup initial state */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->priv->default_font_checkbutton), use_default_font); - - /* Connect signals */ - g_signal_connect (dlg->priv->editor, "changed::use-default-font", - G_CALLBACK (on_use_default_font_changed), dlg); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_USE_DEFAULT_FONT, - dlg->priv->default_font_checkbutton, - "active", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - g_settings_bind (dlg->priv->editor, - XED_SETTINGS_EDITOR_FONT, - dlg->priv->font_button, - "font-name", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); - - /* Set initial widget sensitivity */ - gtk_widget_set_sensitive (dlg->priv->font_hbox, !use_default_font); -} - -static gboolean -is_xed_user_style_scheme (const gchar *scheme_id) +static GtkSourceStyleScheme * +get_default_color_scheme (XedPreferencesDialog *dlg) { GtkSourceStyleSchemeManager *manager; - GtkSourceStyleScheme *scheme; - gboolean res = FALSE; + GtkSourceStyleScheme *scheme = NULL; + gchar *pref_id; manager = gtk_source_style_scheme_manager_get_default (); - scheme = gtk_source_style_scheme_manager_get_scheme (manager, scheme_id); + pref_id = g_settings_get_string (dlg->editor_settings, XED_SETTINGS_SCHEME); + scheme = gtk_source_style_scheme_manager_get_scheme (manager, pref_id); + + g_free (pref_id); + + if (scheme == NULL) + { + /* Fallback to classic style scheme */ + scheme = gtk_source_style_scheme_manager_get_scheme (manager, "classic"); + } + + return scheme; +} + +static void +set_buttons_sensisitivity_according_to_scheme (XedPreferencesDialog *dlg, + GtkSourceStyleScheme *scheme) +{ + gboolean editable = FALSE; + if (scheme != NULL) { const gchar *filename; @@ -451,135 +453,26 @@ is_xed_user_style_scheme (const gchar *scheme_id) filename = gtk_source_style_scheme_get_filename (scheme); if (filename != NULL) { - res = g_str_has_prefix (filename, xed_dirs_get_user_styles_dir ()); + editable = g_str_has_prefix (filename, xed_dirs_get_user_styles_dir ()); } } - return res; + gtk_widget_set_sensitive (dlg->uninstall_scheme_button, editable); } static void -set_buttons_sensisitivity_according_to_scheme (XedPreferencesDialog *dlg, - const gchar *scheme_id) +style_scheme_changed (GtkSourceStyleSchemeChooser *chooser, + GParamSpec *pspec, + XedPreferencesDialog *dlg) { - gboolean editable; + GtkSourceStyleScheme *scheme; + const gchar *id; - editable = ((scheme_id != NULL) && is_xed_user_style_scheme (scheme_id)); + scheme = gtk_source_style_scheme_chooser_get_style_scheme (chooser); + id = gtk_source_style_scheme_get_id (scheme); - gtk_widget_set_sensitive (dlg->priv->uninstall_scheme_button, editable); -} - -static void -style_scheme_changed (GtkWidget *treeview, - XedPreferencesDialog *dlg) -{ - GtkTreePath *path; - - gtk_tree_view_get_cursor (GTK_TREE_VIEW (dlg->priv->schemes_treeview), &path, NULL); - - if (path != NULL) - { - GtkTreeIter iter; - gchar *id; - - gtk_tree_model_get_iter (GTK_TREE_MODEL (dlg->priv->schemes_treeview_model), &iter, path); - gtk_tree_path_free (path); - gtk_tree_model_get (GTK_TREE_MODEL (dlg->priv->schemes_treeview_model), &iter, ID_COLUMN, &id, -1); - - g_settings_set_string (dlg->priv->editor, XED_SETTINGS_SCHEME, id); - - set_buttons_sensisitivity_according_to_scheme (dlg, id); - - g_free (id); - } -} - -static const gchar * -ensure_color_scheme_id (XedPreferencesDialog *dlg, - const gchar *id) -{ - GtkSourceStyleSchemeManager *manager; - GtkSourceStyleScheme *scheme = NULL; - - manager = gtk_source_style_scheme_manager_get_default (); - if (id == NULL) - { - gchar *pref_id; - - pref_id = g_settings_get_string (dlg->priv->editor, XED_SETTINGS_SCHEME); - scheme = gtk_source_style_scheme_manager_get_scheme (manager, pref_id); - g_free (pref_id); - } - else - { - scheme = gtk_source_style_scheme_manager_get_scheme (manager, id); - } - - if (scheme == NULL) - { - /* Fall-back to classic style scheme */ - scheme = gtk_source_style_scheme_manager_get_scheme (manager, "classic"); - } - - if (scheme == NULL) - { - /* Cannot determine default style scheme -> broken GtkSourceView installation */ - return NULL; - } - - return gtk_source_style_scheme_get_id (scheme); -} - -static const gchar * -populate_color_scheme_list (XedPreferencesDialog *dlg, - const gchar *def_id) -{ - GtkSourceStyleSchemeManager *manager; - const gchar * const *ids; - gint i; - - gtk_list_store_clear (dlg->priv->schemes_treeview_model); - - def_id = ensure_color_scheme_id (dlg, def_id); - if (def_id == NULL) - { - g_warning ("Cannot build the list of available color schemes.\n" - "Please check your GtkSourceView installation."); - return NULL; - } - - manager = gtk_source_style_scheme_manager_get_default (); - ids = gtk_source_style_scheme_manager_get_scheme_ids (manager); - for (i = 0; ids[i] != NULL; i++) - { - GtkSourceStyleScheme *scheme; - const gchar *name; - const gchar *description; - GtkTreeIter iter; - - scheme = gtk_source_style_scheme_manager_get_scheme (manager, ids[i]); - name = gtk_source_style_scheme_get_name (scheme); - description = gtk_source_style_scheme_get_description (scheme); - - gtk_list_store_append (dlg->priv->schemes_treeview_model, &iter); - gtk_list_store_set (dlg->priv->schemes_treeview_model, - &iter, - ID_COLUMN, ids[i], - NAME_COLUMN, name, - DESC_COLUMN, description, - -1); - - g_return_val_if_fail (def_id != NULL, NULL); - if (strcmp (ids[i], def_id) == 0) - { - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->schemes_treeview)); - gtk_tree_selection_select_iter (selection, &iter); - } - } - - return def_id; + g_settings_set_string (dlg->editor_settings, XED_SETTINGS_SCHEME, id); + set_buttons_sensisitivity_according_to_scheme (dlg, scheme); } /* @@ -654,6 +547,7 @@ file_copy (const gchar *name, if (!g_file_set_contents (dest_name, contents, length, error)) { + g_free (contents); return FALSE; } @@ -677,7 +571,7 @@ file_copy (const gchar *name, * * Return value: the id of the installed scheme, %NULL otherwise. */ -static const gchar * +static GtkSourceStyleScheme * install_style_scheme (const gchar *fname) { GtkSourceStyleSchemeManager *manager; @@ -686,7 +580,7 @@ install_style_scheme (const gchar *fname) const gchar *styles_dir; GError *error = NULL; gboolean copied = FALSE; - const gchar* const *ids; + const gchar * const *ids; g_return_val_if_fail (fname != NULL, NULL); @@ -703,13 +597,16 @@ install_style_scheme (const gchar *fname) new_file_name = g_build_filename (styles_dir, basename, NULL); g_free (basename); - /* Copy the style scheme file into GEDIT_STYLES_DIR */ + /* Copy the style scheme file into XED_STYLES_DIR */ if (!file_copy (fname, new_file_name, &error)) { g_free (new_file_name); + g_free (dirname); g_message ("Cannot install style scheme:\n%s", error->message); + g_error_free (error); + return NULL; } @@ -742,7 +639,7 @@ install_style_scheme (const gchar *fname) /* The style scheme has been correctly installed */ g_free (new_file_name); - return gtk_source_style_scheme_get_id (scheme); + return scheme; } ++ids; } @@ -758,59 +655,13 @@ install_style_scheme (const gchar *fname) return NULL; } -/** - * uninstall_style_scheme: - * @manager: a #GtkSourceStyleSchemeManager - * @id: the id of the style scheme to be uninstalled - * - * Uninstall a user scheme. - * - * If the call was succesful, it returns %TRUE - * otherwise %FALSE. - * - * Return value: %TRUE on success, %FALSE otherwise. - */ -static gboolean -uninstall_style_scheme (const gchar *id) -{ - GtkSourceStyleSchemeManager *manager; - GtkSourceStyleScheme *scheme; - const gchar *filename; - - g_return_val_if_fail (id != NULL, FALSE); - - manager = gtk_source_style_scheme_manager_get_default (); - - scheme = gtk_source_style_scheme_manager_get_scheme (manager, id); - if (scheme == NULL) - { - return FALSE; - } - - filename = gtk_source_style_scheme_get_filename (scheme); - if (filename == NULL) - { - return FALSE; - } - - if (g_unlink (filename) == -1) - { - return FALSE; - } - - /* Reload the available style schemes */ - gtk_source_style_scheme_manager_force_rescan (manager); - - return TRUE; -} - static void add_scheme_chooser_response_cb (GtkDialog *chooser, gint res_id, XedPreferencesDialog *dlg) { gchar* filename; - const gchar *scheme_id; + GtkSourceStyleScheme *scheme; if (res_id != GTK_RESPONSE_ACCEPT) { @@ -826,20 +677,18 @@ add_scheme_chooser_response_cb (GtkDialog *chooser, gtk_widget_hide (GTK_WIDGET (chooser)); - scheme_id = install_style_scheme (filename); + scheme = install_style_scheme (filename); g_free (filename); - if (scheme_id == NULL) + if (scheme == NULL) { xed_warning (GTK_WINDOW (dlg), _("The selected color scheme cannot be installed.")); return; } - g_settings_set_string (dlg->priv->editor, XED_SETTINGS_SCHEME, scheme_id); + g_settings_set_string (dlg->editor_settings, XED_SETTINGS_SCHEME, gtk_source_style_scheme_get_id (scheme)); - scheme_id = populate_color_scheme_list (dlg, scheme_id); - - set_buttons_sensisitivity_according_to_scheme (dlg, scheme_id); + set_buttons_sensisitivity_according_to_scheme (dlg, scheme); } static void @@ -849,10 +698,10 @@ install_scheme_clicked (GtkButton *button, GtkWidget *chooser; GtkFileFilter *filter; - if (dlg->priv->install_scheme_file_schooser != NULL) + if (dlg->install_scheme_file_schooser != NULL) { - gtk_window_present (GTK_WINDOW (dlg->priv->install_scheme_file_schooser)); - gtk_widget_grab_focus (dlg->priv->install_scheme_file_schooser); + gtk_window_present (GTK_WINDOW (dlg->install_scheme_file_schooser)); + gtk_widget_grab_focus (dlg->install_scheme_file_schooser); return; } @@ -884,191 +733,95 @@ install_scheme_clicked (GtkButton *button, g_signal_connect (chooser, "response", G_CALLBACK (add_scheme_chooser_response_cb), dlg); - dlg->priv->install_scheme_file_schooser = chooser; + dlg->install_scheme_file_schooser = chooser; - g_object_add_weak_pointer (G_OBJECT (chooser), (gpointer) &dlg->priv->install_scheme_file_schooser); + g_object_add_weak_pointer (G_OBJECT (chooser), (gpointer) &dlg->install_scheme_file_schooser); gtk_widget_show (chooser); } +/** + * uninstall_style_scheme: + * @manager: a #GtkSourceStyleSchemeManager + * @scheme: a #GtkSourceStyleScheme + * + * Uninstall a user scheme. + * + * If the call was succesful, it returns %TRUE + * otherwise %FALSE. + * + * Return value: %TRUE on success, %FALSE otherwise. + */ +static gboolean +uninstall_style_scheme (GtkSourceStyleScheme *scheme) +{ + GtkSourceStyleSchemeManager *manager; + const gchar *filename; + + g_return_val_if_fail (GTK_SOURCE_IS_STYLE_SCHEME (scheme), FALSE); + + manager = gtk_source_style_scheme_manager_get_default (); + + filename = gtk_source_style_scheme_get_filename (scheme); + if (filename == NULL) + { + return FALSE; + } + + if (g_unlink (filename) == -1) + { + return FALSE; + } + + /* Reload the available style schemes */ + gtk_source_style_scheme_manager_force_rescan (manager); + + return TRUE; +} + static void uninstall_scheme_clicked (GtkButton *button, XedPreferencesDialog *dlg) { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; + GtkSourceStyleScheme *scheme; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->schemes_treeview)); - model = GTK_TREE_MODEL (dlg->priv->schemes_treeview_model); + scheme = gtk_source_style_scheme_chooser_get_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) + if (!uninstall_style_scheme (scheme)) { - gchar *id; - gchar *name; - - gtk_tree_model_get (model, &iter, ID_COLUMN, &id, NAME_COLUMN, &name, -1); - - if (!uninstall_style_scheme (id)) - { - xed_warning (GTK_WINDOW (dlg), _("Could not remove color scheme \"%s\"."), name); - } - else - { - const gchar *real_new_id; - gchar *new_id = NULL; - GtkTreePath *path; - GtkTreeIter new_iter; - gboolean new_iter_set = FALSE; - - /* If the removed style scheme is the last of the list, - * set as new default style scheme the previous one, - * otherwise set the next one. - * To make this possible, we need to get the id of the - * new default style scheme before re-populating the list. - * Fall back to "classic" if it is not possible to get - * the id - */ - path = gtk_tree_model_get_path (model, &iter); - - /* Try to move to the next path */ - gtk_tree_path_next (path); - if (!gtk_tree_model_get_iter (model, &new_iter, path)) - { - /* It seems the removed style scheme was the - * last of the list. Try to move to the - * previous one */ - gtk_tree_path_free (path); - - path = gtk_tree_model_get_path (model, &iter); - - gtk_tree_path_prev (path); - if (gtk_tree_model_get_iter (model, &new_iter, path)) - { - new_iter_set = TRUE; - } - } - else - { - new_iter_set = TRUE; - } - - gtk_tree_path_free (path); - - if (new_iter_set) - { - gtk_tree_model_get (model, &new_iter, ID_COLUMN, &new_id, -1); - } - - real_new_id = populate_color_scheme_list (dlg, new_id); - g_free (new_id); - - set_buttons_sensisitivity_according_to_scheme (dlg, real_new_id); - - if (real_new_id != NULL) - { - g_settings_set_string (dlg->priv->editor, XED_SETTINGS_SCHEME, real_new_id); - } - } - - g_free (id); - g_free (name); + xed_warning (GTK_WINDOW (dlg), _("Could not remove color scheme \"%s\"."), + gtk_source_style_scheme_get_name (scheme)); } } static void -scheme_description_cell_data_func (GtkTreeViewColumn *column, - GtkCellRenderer *renderer, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data) +setup_theme_page (XedPreferencesDialog *dlg) { - gchar *name; - gchar *desc; - gchar *text; - - gtk_tree_model_get (model, iter, NAME_COLUMN, &name, DESC_COLUMN, &desc, -1); - - if (desc != NULL) - { - text = g_markup_printf_escaped ("%s - %s", name, desc); - } - else - { - text = g_markup_printf_escaped ("%s", name); - } - - g_free (name); - g_free (desc); - - g_object_set (G_OBJECT (renderer), "markup", text, NULL); - - g_free (text); -} - -static void -setup_font_colors_page_style_scheme_section (XedPreferencesDialog *dlg) -{ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *selection; - const gchar *def_id; + GtkSourceStyleScheme *scheme; xed_debug (DEBUG_PREFS); - /* Create GtkListStore for styles & setup treeview. */ - dlg->priv->schemes_treeview_model = gtk_list_store_new (NUM_COLUMNS, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dlg->priv->schemes_treeview_model), - 0, GTK_SORT_ASCENDING); - gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->schemes_treeview), - GTK_TREE_MODEL (dlg->priv->schemes_treeview_model)); - - column = gtk_tree_view_column_new (); - - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - gtk_tree_view_column_set_cell_data_func (column, - renderer, - scheme_description_cell_data_func, - dlg, - NULL); - - gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->schemes_treeview), column); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->schemes_treeview)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - - def_id = populate_color_scheme_list (dlg, NULL); - - /* Connect signals */ - g_signal_connect (dlg->priv->schemes_treeview, "cursor-changed", - G_CALLBACK (style_scheme_changed), dlg); - g_signal_connect (dlg->priv->install_scheme_button, "clicked", - G_CALLBACK (install_scheme_clicked), dlg); - g_signal_connect (dlg->priv->uninstall_scheme_button, "clicked", - G_CALLBACK (uninstall_scheme_clicked), dlg); - - /* Set initial widget sensitivity */ - set_buttons_sensisitivity_according_to_scheme (dlg, def_id); -} - -static void -setup_font_colors_page (XedPreferencesDialog *dlg) -{ - setup_font_colors_page_font_section (dlg); - setup_font_colors_page_style_scheme_section (dlg); - - g_settings_bind (dlg->priv->editor, + /* Prefer dark theme */ + g_settings_bind (dlg->editor_settings, XED_SETTINGS_PREFER_DARK_THEME, - dlg->priv->prefer_dark_theme_checkbutton, + dlg->prefer_dark_theme_switch, "active", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET); + + /* Style scheme */ + scheme = get_default_color_scheme (dlg); + + g_signal_connect (dlg->schemes_list, "notify::style-scheme", + G_CALLBACK (style_scheme_changed), dlg); + g_signal_connect (dlg->install_scheme_button, "clicked", + G_CALLBACK (install_scheme_clicked), dlg); + g_signal_connect (dlg->uninstall_scheme_button, "clicked", + G_CALLBACK (uninstall_scheme_clicked), dlg); + + gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list), scheme); + set_buttons_sensisitivity_according_to_scheme (dlg, scheme); + + xapp_preferences_window_add_page (XAPP_PREFERENCES_WINDOW (dlg), dlg->theme_page, "theme", _("Theme")); } static void @@ -1081,87 +834,48 @@ setup_plugins_page (XedPreferencesDialog *dlg) page_content = peas_gtk_plugin_manager_new (NULL); g_return_if_fail (page_content != NULL); - gtk_box_pack_start (GTK_BOX (dlg->priv->plugin_manager_place_holder), page_content, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (dlg->plugin_manager_place_holder), page_content, TRUE, TRUE, 0); gtk_widget_show_all (page_content); + + xapp_preferences_window_add_page (XAPP_PREFERENCES_WINDOW (dlg), dlg->plugins_page, "plugins", _("Plugins")); +} + +static void +setup_buttons (XedPreferencesDialog *dlg) +{ + GtkWidget *button; + + button = gtk_button_new_with_label (_("Help")); + xapp_preferences_window_add_button (XAPP_PREFERENCES_WINDOW (dlg), button, GTK_PACK_START); + g_signal_connect (button, "clicked", + G_CALLBACK (help_button_clicked), dlg); + + button = gtk_button_new_with_label (_("Close")); + xapp_preferences_window_add_button (XAPP_PREFERENCES_WINDOW (dlg), button, GTK_PACK_END); + g_signal_connect (button, "clicked", + G_CALLBACK (close_button_clicked), dlg); } static void xed_preferences_dialog_init (XedPreferencesDialog *dlg) { - GtkBuilder *builder; - gchar *root_objects[] = { - "notebook", - "adjustment1", - "adjustment2", - "adjustment3", - NULL - }; - xed_debug (DEBUG_PREFS); - dlg->priv = XED_PREFERENCES_DIALOG_GET_PRIVATE (dlg); - dlg->priv->editor = g_settings_new ("org.x.editor.preferences.editor"); - dlg->priv->ui = g_settings_new ("org.x.editor.preferences.ui"); - - gtk_dialog_add_buttons (GTK_DIALOG (dlg), - _("Close"), GTK_RESPONSE_CLOSE, - _("Help"), GTK_RESPONSE_HELP, - NULL); + dlg->editor_settings = g_settings_new ("org.x.editor.preferences.editor"); + dlg->ui_settings = g_settings_new ("org.x.editor.preferences.ui"); gtk_window_set_title (GTK_WINDOW (dlg), _("Xed Preferences")); - gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); - /* HIG defaults */ - gtk_container_set_border_width (GTK_CONTAINER (dlg), 5); - gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 2); /* 2 * 5 + 2 = 12 */ - gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 5); - gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6); + gtk_widget_init_template (GTK_WIDGET (dlg)); - g_signal_connect (dlg, "response", - G_CALLBACK (dialog_response_handler), NULL); - - builder = gtk_builder_new (); - gtk_builder_add_objects_from_resource (builder, "/org/x/editor/ui/xed-preferences-dialog.ui", root_objects, NULL); - dlg->priv->notebook = GTK_WIDGET (gtk_builder_get_object (builder, "notebook")); - g_object_ref (dlg->priv->notebook); - dlg->priv->display_line_numbers_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "display_line_numbers_checkbutton")); - dlg->priv->highlight_current_line_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "highlight_current_line_checkbutton")); - dlg->priv->bracket_matching_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "bracket_matching_checkbutton")); - dlg->priv->mini_map_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "mini_map_checkbutton")); - dlg->priv->wrap_text_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "wrap_text_checkbutton")); - dlg->priv->split_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "split_checkbutton")); - dlg->priv->right_margin_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "right_margin_checkbutton")); - dlg->priv->right_margin_position_spinbutton = GTK_WIDGET (gtk_builder_get_object (builder, "right_margin_position_spinbutton")); - dlg->priv->right_margin_position_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "right_margin_position_hbox")); - dlg->priv->tabs_width_spinbutton = GTK_WIDGET (gtk_builder_get_object (builder, "tabs_width_spinbutton")); - dlg->priv->tabs_width_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "tabs_width_hbox")); - dlg->priv->insert_spaces_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "insert_spaces_checkbutton")); - dlg->priv->auto_indent_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "auto_indent_checkbutton")); - dlg->priv->autosave_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "autosave_hbox")); - dlg->priv->backup_copy_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "backup_copy_checkbutton")); - dlg->priv->auto_save_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "auto_save_checkbutton")); - dlg->priv->auto_save_spinbutton = GTK_WIDGET (gtk_builder_get_object (builder, "auto_save_spinbutton")); - dlg->priv->tab_scrolling_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "tab_scrolling_checkbutton")); - dlg->priv->default_font_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "default_font_checkbutton")); - dlg->priv->font_button = GTK_WIDGET (gtk_builder_get_object (builder, "font_button")); - dlg->priv->font_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "font_hbox")); - dlg->priv->prefer_dark_theme_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "prefer_dark_theme_checkbutton")); - dlg->priv->schemes_treeview = GTK_WIDGET (gtk_builder_get_object (builder, "schemes_treeview")); - dlg->priv->install_scheme_button = GTK_WIDGET (gtk_builder_get_object (builder, "install_scheme_button")); - dlg->priv->uninstall_scheme_button = GTK_WIDGET (gtk_builder_get_object (builder, "uninstall_scheme_button")); - dlg->priv->plugin_manager_place_holder = GTK_WIDGET (gtk_builder_get_object (builder, "plugin_manager_place_holder")); - g_object_unref (builder); - - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), dlg->priv->notebook, FALSE, FALSE, 0); - g_object_unref (dlg->priv->notebook); - gtk_container_set_border_width (GTK_CONTAINER (dlg->priv->notebook), 5); + setup_buttons (dlg); setup_editor_page (dlg); - setup_view_page (dlg); - setup_font_colors_page (dlg); + setup_save_page (dlg); + setup_theme_page (dlg); setup_plugins_page (dlg); + gtk_widget_show_all (GTK_WIDGET (dlg)); } void diff --git a/xed/xed-preferences-dialog.h b/xed/xed-preferences-dialog.h index 40cc03e..f7e8685 100755 --- a/xed/xed-preferences-dialog.h +++ b/xed/xed-preferences-dialog.h @@ -3,7 +3,7 @@ * xed-preferences-dialog.c * This file is part of xed * - * Copyright (C) 2001-2005 Paolo Maggi + * Copyright (C) 2001-2005 Paolo Maggi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,14 +17,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /* - * Modified by the xed Team, 2003. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. + * Modified by the xed Team, 2003. See the AUTHORS file for a + * list of people on the xed Team. + * See the ChangeLog files for a list of changes. * * $Id$ */ @@ -32,54 +32,13 @@ #ifndef __XED_PREFERENCES_DIALOG_H__ #define __XED_PREFERENCES_DIALOG_H__ +#include + #include "xed-window.h" G_BEGIN_DECLS -/* - * Type checking and casting macros - */ -#define XED_TYPE_PREFERENCES_DIALOG (xed_preferences_dialog_get_type()) -#define XED_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog)) -#define XED_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog const)) -#define XED_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass)) -#define XED_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_PREFERENCES_DIALOG)) -#define XED_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_PREFERENCES_DIALOG)) -#define XED_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass)) - - -/* Private structure type */ -typedef struct _XedPreferencesDialogPrivate XedPreferencesDialogPrivate; - -/* - * Main object structure - */ -typedef struct _XedPreferencesDialog XedPreferencesDialog; - -struct _XedPreferencesDialog -{ - GtkDialog dialog; - - /*< private > */ - XedPreferencesDialogPrivate *priv; -}; - -/* - * Class definition - */ -typedef struct _XedPreferencesDialogClass XedPreferencesDialogClass; - -struct _XedPreferencesDialogClass -{ - GtkDialogClass parent_class; -}; - -/* - * Public methods - */ -GType xed_preferences_dialog_get_type (void) G_GNUC_CONST; - -void xed_show_preferences_dialog (XedWindow *parent); +void xed_show_preferences_dialog (XedWindow *parent); G_END_DECLS From 78ca6d13e0c19d0908462607e9b568409bc895bd Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 00:46:02 -0800 Subject: [PATCH 03/18] xed-window: Rework the fullscreen toolbar The animation used for hiding/showing the fullscreen toolbar is totally broken under HiDPI. Port to GtkRevealer and GtkEventBox to get the proper behaviour. --- xed/xed-window-private.h | 6 +- xed/xed-window.c | 206 ++++++++------------------------------- 2 files changed, 44 insertions(+), 168 deletions(-) diff --git a/xed/xed-window-private.h b/xed/xed-window-private.h index 2e3b5c1..691779c 100644 --- a/xed/xed-window-private.h +++ b/xed/xed-window-private.h @@ -66,9 +66,9 @@ struct _XedWindowPrivate /* Widgets for fullscreen mode */ GtkWidget *fullscreen_controls; - GtkWidget *fullscreen_controls_container; - guint fullscreen_animation_timeout_id; - gboolean fullscreen_animation_enter; + GtkWidget *fullscreen_overlay; + GtkWidget *fullscreen_eventbox; + GtkWidget *fullscreen_revealer; /* statusbar and context ids for statusbar messages */ GtkWidget *statusbar; diff --git a/xed/xed-window.c b/xed/xed-window.c index 7227c1a..16fa803 100644 --- a/xed/xed-window.c +++ b/xed/xed-window.c @@ -35,8 +35,6 @@ #define TAB_WIDTH_DATA "XedWindowTabWidthData" #define LANGUAGE_DATA "XedWindowLanguageData" -#define FULLSCREEN_ANIMATION_SPEED 4 - #define XED_WINDOW_DEFAULT_WIDTH 650 #define XED_WINDOW_DEFAULT_HEIGHT 500 @@ -207,18 +205,6 @@ xed_window_dispose (GObject *object) window->priv->dispose_has_run = TRUE; } - if (window->priv->fullscreen_animation_timeout_id != 0) - { - g_source_remove (window->priv->fullscreen_animation_timeout_id); - window->priv->fullscreen_animation_timeout_id = 0; - } - - if (window->priv->fullscreen_controls != NULL) - { - gtk_widget_destroy (window->priv->fullscreen_controls); - window->priv->fullscreen_controls = NULL; - } - if (window->priv->recents_handler_id != 0) { GtkRecentManager *recent_manager; @@ -2636,143 +2622,22 @@ drop_uris_cb (GtkWidget *widget, load_uris_from_drop (window, uri_list); } -static void -fullscreen_controls_show (XedWindow *window) -{ - GdkScreen *screen; - GdkRectangle fs_rect; - gint min_h, nat_h; - - screen = gtk_window_get_screen (GTK_WINDOW (window)); - gdk_screen_get_monitor_geometry ( - screen, gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))), - &fs_rect); - - gtk_widget_get_preferred_height (window->priv->fullscreen_controls_container, &min_h, &nat_h); - gtk_window_resize (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.width, nat_h); - gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - nat_h + 1); - - gtk_widget_show_all (window->priv->fullscreen_controls); -} - static gboolean -run_fullscreen_animation (gpointer data) -{ - XedWindow *window = XED_WINDOW(data); - GdkScreen *screen; - GdkRectangle fs_rect; - gint x, y; - - screen = gtk_window_get_screen (GTK_WINDOW(window)); - gdk_screen_get_monitor_geometry (screen, - gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))), - &fs_rect); - - gtk_window_get_position (GTK_WINDOW(window->priv->fullscreen_controls), &x, &y); - - if (window->priv->fullscreen_animation_enter) - { - if (y == fs_rect.y) - { - window->priv->fullscreen_animation_timeout_id = 0; - return FALSE; - } - else - { - gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y + 1); - return TRUE; - } - } - else - { - gint w, h; - gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h); - if (y == fs_rect.y - h + 1) - { - window->priv->fullscreen_animation_timeout_id = 0; - return FALSE; - } - else - { - gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y - 1); - return TRUE; - } - } -} - -static void -show_hide_fullscreen_toolbar (XedWindow *window, - gboolean show, - gint height) -{ - GtkSettings *settings; - gboolean enable_animations; - - settings = gtk_widget_get_settings (GTK_WIDGET(window)); - g_object_get (G_OBJECT(settings), "gtk-enable-animations", &enable_animations, NULL); - - if (enable_animations) - { - window->priv->fullscreen_animation_enter = show; - if (window->priv->fullscreen_animation_timeout_id == 0) - { - window->priv->fullscreen_animation_timeout_id = g_timeout_add (FULLSCREEN_ANIMATION_SPEED, - (GSourceFunc) run_fullscreen_animation, window); - } - } - else - { - GdkRectangle fs_rect; - GdkScreen *screen; - screen = gtk_window_get_screen (GTK_WINDOW(window)); - gdk_screen_get_monitor_geometry (screen, - gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))), - &fs_rect); - - if (show) - { - gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y); - } - else - { - gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - height + 1); - } - } - -} - -static gboolean -on_fullscreen_controls_enter_notify_event (GtkWidget *widget, +on_fullscreen_controls_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, - XedWindow *window) + XedWindow *window) { - show_hide_fullscreen_toolbar (window, TRUE, 0); + gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE); + return FALSE; } static gboolean -on_fullscreen_controls_leave_notify_event (GtkWidget *widget, +on_fullscreen_controls_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event, - XedWindow *window) + XedWindow *window) { - GdkDisplay *display; - GdkScreen *screen; - gint w, h; - gint x, y; - - display = gdk_display_get_default (); - screen = gtk_window_get_screen (GTK_WINDOW(window)); - - gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h); - gdk_display_get_pointer (display, &screen, &x, &y, NULL); - - /* gtk seems to emit leave notify when clicking on tool items, - * work around it by checking the coordinates - */ - if (y >= h) - { - show_hide_fullscreen_toolbar (window, FALSE, h); - } + gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE); return FALSE; } @@ -2783,6 +2648,9 @@ fullscreen_controls_build (XedWindow *window) XedWindowPrivate *priv = window->priv; GtkAction *action; GtkWidget *box; + GtkWidget *toolbar; + GtkWidget *toolitem; + GtkWidget *toolbox; GtkWidget *fullscreen_btn; GtkWidget *separator; GtkWidget *button; @@ -2792,17 +2660,23 @@ fullscreen_controls_build (XedWindow *window) return; } - priv->fullscreen_controls = gtk_window_new (GTK_WINDOW_POPUP); + priv->fullscreen_controls = gtk_revealer_new (); + gtk_widget_set_valign (priv->fullscreen_controls, GTK_ALIGN_START); + gtk_container_add (GTK_CONTAINER (priv->fullscreen_eventbox), priv->fullscreen_controls); - gtk_window_set_transient_for (GTK_WINDOW (priv->fullscreen_controls), GTK_WINDOW (&window->window)); + toolbar = gtk_toolbar_new (); + toolitem = gtk_tool_item_new (); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (toolitem), 0); - window->priv->fullscreen_controls_container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_container_set_border_width (GTK_CONTAINER (window->priv->fullscreen_controls_container), 6); - gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), window->priv->fullscreen_controls_container); + toolbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "primary-toolbar"); + gtk_container_add (GTK_CONTAINER (toolitem), toolbox); + gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), toolbar); box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_vexpand (box, FALSE); - gtk_box_pack_start (GTK_BOX (window->priv->fullscreen_controls_container), box, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (toolbox), box, FALSE, FALSE, 0); action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew"); button = create_toolbar_button (action); @@ -2858,13 +2732,15 @@ fullscreen_controls_build (XedWindow *window) fullscreen_btn = create_toolbar_button (action); gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0); - gtk_widget_show_all (window->priv->fullscreen_controls_container); + gtk_widget_show_all (toolbox); - g_signal_connect(priv->fullscreen_controls, "enter-notify-event", - G_CALLBACK (on_fullscreen_controls_enter_notify_event), window); + g_signal_connect (priv->fullscreen_eventbox, "enter-notify-event", + G_CALLBACK (on_fullscreen_controls_enter_notify_event), window); - g_signal_connect(priv->fullscreen_controls, "leave-notify-event", - G_CALLBACK (on_fullscreen_controls_leave_notify_event), window); + g_signal_connect (priv->fullscreen_eventbox, "leave-notify-event", + G_CALLBACK (on_fullscreen_controls_leave_notify_event), window); + + gtk_widget_set_size_request (priv->fullscreen_eventbox, -1, 1); } static void @@ -3531,14 +3407,7 @@ check_window_is_active (XedWindow *window, { if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN) { - if (gtk_window_is_active (GTK_WINDOW(window))) - { - gtk_widget_show (window->priv->fullscreen_controls); - } - else - { - gtk_widget_hide (window->priv->fullscreen_controls); - } + gtk_widget_set_visible (window->priv->fullscreen_eventbox, gtk_window_is_active (GTK_WINDOW (window))); } } @@ -3606,7 +3475,6 @@ xed_window_init (XedWindow *window) window->priv->inhibition_cookie = 0; window->priv->dispose_has_run = FALSE; window->priv->fullscreen_controls = NULL; - window->priv->fullscreen_animation_timeout_id = 0; window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor"); window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui"); @@ -3623,9 +3491,16 @@ xed_window_init (XedWindow *window) gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window"); main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_container_add (GTK_CONTAINER (window), main_box); + window->priv->fullscreen_overlay = gtk_overlay_new (); + gtk_container_add (GTK_CONTAINER (window->priv->fullscreen_overlay), main_box); + gtk_container_add (GTK_CONTAINER (window), window->priv->fullscreen_overlay); + gtk_widget_show (window->priv->fullscreen_overlay); gtk_widget_show (main_box); + window->priv->fullscreen_eventbox = gtk_event_box_new (); + gtk_widget_set_valign (window->priv->fullscreen_eventbox, GTK_ALIGN_START); + gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fullscreen_overlay), window->priv->fullscreen_eventbox); + /* Add menu bar and toolbar bar */ create_menu_bar_and_toolbar (window, main_box); @@ -4324,7 +4199,8 @@ _xed_window_fullscreen (XedWindow *window) gtk_widget_hide (window->priv->statusbar); fullscreen_controls_build (window); - fullscreen_controls_show (window); + + gtk_widget_show_all (window->priv->fullscreen_eventbox); } void @@ -4361,7 +4237,7 @@ _xed_window_unfullscreen (XedWindow *window) } g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window); - gtk_widget_hide (window->priv->fullscreen_controls); + gtk_widget_hide (window->priv->fullscreen_eventbox); } gboolean From 561c94e71a685741e65db33b8f77c7da382022c3 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 01:03:23 -0800 Subject: [PATCH 04/18] xed-status-combo-box: Remove some deprecated css functionality This stuff is deprecated and just spams warnings so clean it up. --- xed/xed-status-combo-box.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/xed/xed-status-combo-box.c b/xed/xed-status-combo-box.c index 9d45981..ea195cc 100644 --- a/xed/xed-status-combo-box.c +++ b/xed/xed-status-combo-box.c @@ -141,18 +141,14 @@ xed_status_combo_box_changed (XedStatusComboBox *combo, static void xed_status_combo_box_class_init (XedStatusComboBoxClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); static const gchar style[] = "* {\n" - "-GtkButton-default-border : 0;\n" - "-GtkButton-default-outside-border : 0;\n" - "-GtkButton-inner-border: 0;\n" - "-GtkWidget-focus-line-width : 0;\n" - "-GtkWidget-focus-padding : 0;\n" "padding: 2px;\n" "}"; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + object_class->finalize = xed_status_combo_box_finalize; object_class->get_property = xed_status_combo_box_get_property; object_class->set_property = xed_status_combo_box_set_property; From c269c57777a231e816eb4f6cddb70d9b43adc4ac Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 01:18:56 -0800 Subject: [PATCH 05/18] xed-view-frame: Fix the css for the minimap frame This makes it work in gtk3.20+ --- xed/resources/css/xed-style.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xed/resources/css/xed-style.css b/xed/resources/css/xed-style.css index 984ca8a..a910576 100644 --- a/xed/resources/css/xed-style.css +++ b/xed/resources/css/xed-style.css @@ -1,7 +1,7 @@ -.xed-map-frame:dir(ltr) { +.xed-map-frame:dir(ltr) border { border-width: 0 0 0 1px; } -.xed-map-frame:dir(rtl) { +.xed-map-frame:dir(rtl) border { border-width: 0 1px 0 0; -} \ No newline at end of file +} From 6383f71fa060bee8a83774155614d7ac7262b644 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 01:31:43 -0800 Subject: [PATCH 06/18] xed-notebook: Clean up some gtk3.20+ conditionals Since we are moving to gtk3.22 we can clean these up. --- xed/xed-notebook.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xed/xed-notebook.c b/xed/xed-notebook.c index 481afa5..6e13d4b 100644 --- a/xed/xed-notebook.c +++ b/xed/xed-notebook.c @@ -714,11 +714,9 @@ xed_notebook_init (XedNotebook *notebook) notebook->priv->tab_scrolling_enabled = g_settings_get_boolean (notebook->priv->ui_settings, "enable-tab-scrolling"); gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); - -#if GTK_CHECK_VERSION (3, 20, 0) - gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); -#endif + gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (notebook), 0); g_signal_connect (notebook, "button-press-event", (GCallback)button_press_cb, NULL); From 6159ad5be20ac5a1fc8f35514c19afe85ee2c41f Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 03:22:03 -0800 Subject: [PATCH 07/18] Add a shortcuts window --- xed/resources/ui/xed-shortcuts.ui | 330 ++++++++++++++++++++++++++++++ xed/resources/ui/xed-ui.xml | 2 + xed/resources/xed.gresource.xml | 3 +- xed/xed-commands-help.c | 32 ++- xed/xed-commands.h | 1 + xed/xed-ui.h | 2 + 6 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 xed/resources/ui/xed-shortcuts.ui diff --git a/xed/resources/ui/xed-shortcuts.ui b/xed/resources/ui/xed-shortcuts.ui new file mode 100644 index 0000000..bd9b628 --- /dev/null +++ b/xed/resources/ui/xed-shortcuts.ui @@ -0,0 +1,330 @@ + + + + + 1 + + + 1 + shortcuts + 12 + + + 1 + Documents + + + 1 + <ctrl>N + Create a new document + + + + + 1 + <ctrl>O + Open a document + + + + + 1 + <ctrl>S + Save the document + + + + + 1 + <ctrl><shift>S + Save the document with a new filename + + + + + 1 + <ctrl><shift>L + Save all the documents + + + + + 1 + <ctrl>W + Close the document + + + + + 1 + <ctrl><shift>W + Close all the documents + + + + + 1 + <ctrl><Alt>Page_Down + Switch to the next document + + + + + 1 + <ctrl><Alt>Page_Up + Switch to the previous document + + + + + 1 + <Alt>1...9 + Switch to the first - ninth document + + + + + + + 1 + Windows and Panes + + + 1 + F9 + Show side pane + + + + + 1 + <ctrl>F9 + Show bottom pane + + + + + 1 + F11 + Fullscreen on / off + + + + + 1 + <ctrl>Q + Quit the application + + + + + + + 1 + Find and Replace + + + 1 + <ctrl>F + Find + + + + + 1 + <ctrl>G + Find the next match + + + + + 1 + <ctrl><Shift>G + Find the previous match + + + + + 1 + <ctrl>H + Find and Replace + + + + + 1 + <ctrl>I + Go to line + + + + + + + 1 + Copy and Paste + + + 1 + <ctrl>C + Copy selected text to clipboard + + + + + 1 + <ctrl>X + Cut selected text to clipboard + + + + + 1 + <ctrl>V + Paste text from clipboard + + + + + + + 1 + Undo and Redo + + + 1 + <ctrl>Z + Undo previous command + + + + + 1 + <ctrl>Y + Redo previous command + + + + + + + 1 + Selection + + + 1 + <ctrl>A + Select all text + + + + + + + 1 + Editing + + + 1 + Insert + Toggle insert / overwrite + + + + + 1 + <ctrl>D + Delete current line + + + + + 1 + <alt>Up + Move current line up + + + + + 1 + <alt>Down + Move current line down + + + + + 1 + <alt>Left + Move current word left + + + + + 1 + <alt>Right + Move current word right + + + + + + 1 + <ctrl><shift>a + Increment number at cursor + + + + + 1 + <ctrl><shift>x + Decrement number at cursor + + + + + + + 1 + Tools + + + 1 + <shift>F7 + Check spelling + + + + + 1 + <ctrl>P + Print the document + + + + + + + + diff --git a/xed/resources/ui/xed-ui.xml b/xed/resources/ui/xed-ui.xml index 10d48bf..91a01ba 100644 --- a/xed/resources/ui/xed-ui.xml +++ b/xed/resources/ui/xed-ui.xml @@ -123,6 +123,8 @@ + + diff --git a/xed/resources/xed.gresource.xml b/xed/resources/xed.gresource.xml index b02bde6..0a55cb5 100644 --- a/xed/resources/xed.gresource.xml +++ b/xed/resources/xed.gresource.xml @@ -6,7 +6,8 @@ ui/xed-preferences-dialog.ui ui/xed-print-preferences.ui ui/xed-searchbar.ui + ui/xed-shortcuts.ui ui/xed-view-frame.ui css/xed-style.css - \ No newline at end of file + diff --git a/xed/xed-commands-help.c b/xed/xed-commands-help.c index b031339..769ddc2 100644 --- a/xed/xed-commands-help.c +++ b/xed/xed-commands-help.c @@ -46,7 +46,7 @@ void _xed_cmd_help_contents (GtkAction *action, XedWindow *window) { - xed_debug(DEBUG_COMMANDS); + xed_debug (DEBUG_COMMANDS); xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (window), NULL, NULL); } @@ -67,3 +67,33 @@ void _xed_cmd_help_about (GtkAction *action, "website", "http://github.com/linuxmint/xed", NULL); } + +void +_xed_cmd_help_keyboard_shortcuts (GtkAction *action, + XedWindow *window) +{ + static GtkWidget *shortcuts_window; + + xed_debug (DEBUG_COMMANDS); + + if (shortcuts_window == NULL) + { + GtkBuilder *builder; + + builder = gtk_builder_new_from_resource ("/org/x/editor/ui/xed-shortcuts.ui"); + shortcuts_window = GTK_WIDGET (gtk_builder_get_object (builder, "shortcuts-xed")); + + g_signal_connect (shortcuts_window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &shortcuts_window); + + g_object_unref (builder); + } + + if (GTK_WINDOW (window) != gtk_window_get_transient_for (GTK_WINDOW (shortcuts_window))) + { + gtk_window_set_transient_for (GTK_WINDOW (shortcuts_window), GTK_WINDOW (window)); + } + + gtk_widget_show_all (shortcuts_window); + gtk_window_present (GTK_WINDOW (shortcuts_window)); +} diff --git a/xed/xed-commands.h b/xed/xed-commands.h index 679bc1e..005e64a 100644 --- a/xed/xed-commands.h +++ b/xed/xed-commands.h @@ -66,6 +66,7 @@ void _xed_cmd_documents_move_to_new_window (GtkAction *action, XedWindow *window void _xed_cmd_help_contents (GtkAction *action, XedWindow *window); void _xed_cmd_help_about (GtkAction *action, XedWindow *window); +void _xed_cmd_help_keyboard_shortcuts (GtkAction *action, XedWindow *window); void _xed_cmd_file_close_tab (XedTab *tab, XedWindow *window); diff --git a/xed/xed-ui.h b/xed/xed-ui.h index 24e97b5..5f32f9f 100644 --- a/xed/xed-ui.h +++ b/xed/xed-ui.h @@ -67,6 +67,8 @@ static const GtkActionEntry xed_always_sensitive_menu_entries[] = N_("Open the xed manual"), G_CALLBACK (_xed_cmd_help_contents) }, { "HelpAbout", "help-about-symbolic", N_("_About"), NULL, N_("About this application"), G_CALLBACK (_xed_cmd_help_about) }, + { "HelpShortcuts", NULL, N_("_Keyboard Shortcuts"), NULL, + N_("Show the keyboard shortcuts dialog"), G_CALLBACK (_xed_cmd_help_keyboard_shortcuts) }, /* Fullscreen toolbar */ { "LeaveFullscreen", "view-restore-symbolic", NULL, From ddaf70747c712792598c9dbce2812b247991fafd Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 12:12:48 -0800 Subject: [PATCH 08/18] xed-view: Add shortcuts for change case Closes https://github.com/linuxmint/xed/issues/154 --- xed/resources/ui/xed-shortcuts.ui | 49 +++++++++++++++++-------------- xed/xed-view.c | 32 ++++++++++++++++++-- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/xed/resources/ui/xed-shortcuts.ui b/xed/resources/ui/xed-shortcuts.ui index bd9b628..ad6ae4d 100644 --- a/xed/resources/ui/xed-shortcuts.ui +++ b/xed/resources/ui/xed-shortcuts.ui @@ -219,6 +219,26 @@ + + + 1 + Tools + + + 1 + <shift>F7 + Check spelling + + + + + 1 + <ctrl>P + Print the document + + + + 1 @@ -265,7 +285,6 @@ Move current word right - 1 @@ -304,26 +329,6 @@ - - - 1 - Tools - - - 1 - <shift>F7 - Check spelling - - - - - 1 - <ctrl>P - Print the document - - - - diff --git a/xed/xed-view.c b/xed/xed-view.c index 0099553..0a60133 100644 --- a/xed/xed-view.c +++ b/xed/xed-view.c @@ -607,8 +607,36 @@ xed_view_class_init (XedViewClass *klass) binding_set = gtk_binding_set_by_class (klass); - gtk_binding_entry_add_signal (binding_set, GDK_KEY_d, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, - GTK_DELETE_PARAGRAPHS, G_TYPE_INT, 1); + gtk_binding_entry_add_signal (binding_set, + GDK_KEY_d, + GDK_CONTROL_MASK, + "delete_from_cursor", 2, + G_TYPE_ENUM, GTK_DELETE_PARAGRAPHS, + G_TYPE_INT, 1); + + gtk_binding_entry_add_signal (binding_set, + GDK_KEY_u, + GDK_CONTROL_MASK, + "change_case", 1, + G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_UPPER); + + gtk_binding_entry_add_signal (binding_set, + GDK_KEY_l, + GDK_CONTROL_MASK, + "change_case", 1, + G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_LOWER); + + gtk_binding_entry_add_signal (binding_set, + GDK_KEY_asciitilde, + GDK_CONTROL_MASK, + "change_case", 1, + G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TOGGLE); + + gtk_binding_entry_add_signal (binding_set, + GDK_KEY_t, + GDK_CONTROL_MASK, + "change_case", 1, + G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TITLE); } /** From d86c906848f354c2f5242e4458b4fb450df889e4 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 4 Dec 2017 22:39:28 -0800 Subject: [PATCH 09/18] debian: Add --enable-silent-rules to debian/rules --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index b6118b3..529c008 100755 --- a/debian/rules +++ b/debian/rules @@ -14,7 +14,7 @@ override_dh_auto_configure: # upstream tarball is without configure. autogen.sh will create it NOCONFIGURE=1 ./autogen.sh dh_auto_configure $(DHFLAGS) -- \ - --disable-silent-rules \ + --enable-silent-rules \ --libexecdir=/usr/lib/ \ --enable-gtk-doc From 100428eaf9a38f3e02c4f6fb95bb83567346ad96 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Tue, 5 Dec 2017 00:10:49 -0800 Subject: [PATCH 10/18] css: Add support for Adwaita --- xed/resources/css/xed.adwaita.css | 17 +++++++++++ xed/resources/xed.gresource.xml | 1 + xed/xed-app.c | 50 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 xed/resources/css/xed.adwaita.css diff --git a/xed/resources/css/xed.adwaita.css b/xed/resources/css/xed.adwaita.css new file mode 100644 index 0000000..600a9d2 --- /dev/null +++ b/xed/resources/css/xed.adwaita.css @@ -0,0 +1,17 @@ +.xed-window .primary-toolbar { + border: 0px solid @borders; + border-bottom-width: 1px; +} + +.xed-statusbar { + border: 0px solid @borders; + border-top-width: 1px; +} + +.xed-searchbar { + box-shadow: inset 0 1px @borders; +} + +.xed-statusbar button { + padding: 0 4px; +} diff --git a/xed/resources/xed.gresource.xml b/xed/resources/xed.gresource.xml index 0a55cb5..29a9aed 100644 --- a/xed/resources/xed.gresource.xml +++ b/xed/resources/xed.gresource.xml @@ -9,5 +9,6 @@ ui/xed-shortcuts.ui ui/xed-view-frame.ui css/xed-style.css + css/xed.adwaita.css diff --git a/xed/xed-app.c b/xed/xed-app.c index 785e162..ef0f169 100644 --- a/xed/xed-app.c +++ b/xed/xed-app.c @@ -223,6 +223,54 @@ set_initial_theme_style (XedApp *app) } } +static void +theme_changed (GtkSettings *settings, + GParamSpec *pspec, + gpointer data) +{ + static GtkCssProvider *provider; + gchar *theme; + GdkScreen *screen; + + g_object_get (settings, "gtk-theme-name", &theme, NULL); + screen = gdk_screen_get_default (); + + if (g_str_equal (theme, "Adwaita")) + { + if (provider == NULL) + { + GFile *file; + + provider = gtk_css_provider_new (); + file = g_file_new_for_uri ("resource:///org/x/editor/css/xed.adwaita.css"); + gtk_css_provider_load_from_file (provider, file, NULL); + g_object_unref (file); + } + + gtk_style_context_add_provider_for_screen (screen, + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + else if (provider != NULL) + { + gtk_style_context_remove_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider)); + g_clear_object (&provider); + } + + g_free (theme); +} + +static void +setup_theme_extensions (void) +{ + GtkSettings *settings; + + settings = gtk_settings_get_default (); + g_signal_connect (settings, "notify::gtk-theme-name", + G_CALLBACK (theme_changed), NULL); + theme_changed (settings, NULL, NULL); +} + static void xed_app_startup (GApplication *application) { @@ -251,6 +299,8 @@ xed_app_startup (GApplication *application) gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir); g_free (icon_dir); + setup_theme_extensions (); + #ifndef ENABLE_GVFS_METADATA /* Setup metadata-manager */ cache_dir = xed_dirs_get_user_cache_dir (); From a13a57322818b040f990970d545d288b5784eaae Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Sat, 9 Dec 2017 01:06:28 -0800 Subject: [PATCH 11/18] xed-searchbar: Fix the size of the searchbar close button The theming for this changed in gtk3.20+. Get it back to the proper size and theme it in xed-style.css instead of hard coding it. --- xed/resources/css/xed-style.css | 6 ++++++ xed/xed-searchbar.c | 8 +------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/xed/resources/css/xed-style.css b/xed/resources/css/xed-style.css index a910576..1807e87 100644 --- a/xed/resources/css/xed-style.css +++ b/xed/resources/css/xed-style.css @@ -5,3 +5,9 @@ .xed-map-frame:dir(rtl) border { border-width: 0 1px 0 0; } + +.xed-searchbar .close-button { + padding: 0; + min-height: 0; + min-width: 0; +} diff --git a/xed/xed-searchbar.c b/xed/xed-searchbar.c index 94b33c2..9d705a6 100755 --- a/xed/xed-searchbar.c +++ b/xed/xed-searchbar.c @@ -659,11 +659,8 @@ xed_searchbar_init (XedSearchbar *searchbar) { GtkWidget *content; GtkSizeGroup *size_group; - GtkStyleContext *context; - GtkCssProvider *provider; GtkBuilder *builder; gchar *root_objects[] = { "searchbar_content", NULL }; - const gchar *data = ".button {padding: 0;}"; searchbar->priv = XED_SEARCHBAR_GET_PRIVATE (searchbar); @@ -709,10 +706,7 @@ xed_searchbar_init (XedSearchbar *searchbar) gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->search_label), searchbar->priv->search_entry); gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->replace_label), searchbar->priv->replace_entry); - provider = gtk_css_provider_new (); - context = gtk_widget_get_style_context (searchbar->priv->close_button); - gtk_css_provider_load_from_data (provider, data, -1, NULL); - gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk_style_context_add_class (gtk_widget_get_style_context (searchbar->priv->close_button), "close-button"); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget (size_group, GTK_WIDGET (searchbar->priv->find_button)); From a5af28a95d614c26c9f749296950f068d67fe3da Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Sun, 10 Dec 2017 15:23:37 -0800 Subject: [PATCH 12/18] xed-spell-checker.c: Clean up the code formatting --- plugins/spell/xed-spell-checker.c | 644 ++++++++++++++++-------------- 1 file changed, 344 insertions(+), 300 deletions(-) diff --git a/plugins/spell/xed-spell-checker.c b/plugins/spell/xed-spell-checker.c index b158bd8..e45e926 100644 --- a/plugins/spell/xed-spell-checker.c +++ b/plugins/spell/xed-spell-checker.c @@ -44,27 +44,27 @@ struct _XedSpellChecker { - GObject parent_instance; + GObject parent_instance; - EnchantDict *dict; - EnchantBroker *broker; - const XedSpellCheckerLanguage *active_lang; + EnchantDict *dict; + EnchantBroker *broker; + const XedSpellCheckerLanguage *active_lang; }; /* GObject properties */ enum { - PROP_0 = 0, - PROP_LANGUAGE, - LAST_PROP + PROP_0 = 0, + PROP_LANGUAGE, + LAST_PROP }; /* Signals */ enum { - ADD_WORD_TO_PERSONAL = 0, - ADD_WORD_TO_SESSION, - SET_LANGUAGE, - CLEAR_SESSION, - LAST_SIGNAL + ADD_WORD_TO_PERSONAL = 0, + ADD_WORD_TO_SESSION, + SET_LANGUAGE, + CLEAR_SESSION, + LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -72,415 +72,453 @@ static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE(XedSpellChecker, xed_spell_checker, G_TYPE_OBJECT) static void -xed_spell_checker_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +xed_spell_checker_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - /* - XedSpellChecker *spell = XED_SPELL_CHECKER (object); - */ + /* + XedSpellChecker *spell = XED_SPELL_CHECKER (object); + */ - switch (prop_id) - { - case PROP_LANGUAGE: - /* TODO */ - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } + switch (prop_id) + { + case PROP_LANGUAGE: + /* TODO */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void -xed_spell_checker_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +xed_spell_checker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - /* - XedSpellChecker *spell = XED_SPELL_CHECKER (object); - */ + /* + XedSpellChecker *spell = XED_SPELL_CHECKER (object); + */ - switch (prop_id) - { - case PROP_LANGUAGE: - /* TODO */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } + switch (prop_id) + { + case PROP_LANGUAGE: + /* TODO */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void xed_spell_checker_finalize (GObject *object) { - XedSpellChecker *spell_checker; + XedSpellChecker *spell_checker; - g_return_if_fail (XED_IS_SPELL_CHECKER (object)); + g_return_if_fail (XED_IS_SPELL_CHECKER (object)); - spell_checker = XED_SPELL_CHECKER (object); + spell_checker = XED_SPELL_CHECKER (object); - if (spell_checker->dict != NULL) - enchant_broker_free_dict (spell_checker->broker, spell_checker->dict); + if (spell_checker->dict != NULL) + { + enchant_broker_free_dict (spell_checker->broker, spell_checker->dict); + } - if (spell_checker->broker != NULL) - enchant_broker_free (spell_checker->broker); + if (spell_checker->broker != NULL) + { + enchant_broker_free (spell_checker->broker); + } - G_OBJECT_CLASS (xed_spell_checker_parent_class)->finalize (object); + G_OBJECT_CLASS (xed_spell_checker_parent_class)->finalize (object); } static void -xed_spell_checker_class_init (XedSpellCheckerClass * klass) +xed_spell_checker_class_init (XedSpellCheckerClass *klass) { - GObjectClass *object_class; + GObjectClass *object_class; - object_class = G_OBJECT_CLASS (klass); + object_class = G_OBJECT_CLASS (klass); - object_class->set_property = xed_spell_checker_set_property; - object_class->get_property = xed_spell_checker_get_property; + object_class->set_property = xed_spell_checker_set_property; + object_class->get_property = xed_spell_checker_get_property; - object_class->finalize = xed_spell_checker_finalize; + object_class->finalize = xed_spell_checker_finalize; - g_object_class_install_property (object_class, - PROP_LANGUAGE, - g_param_spec_pointer ("language", - "Language", - "The language used by the spell checker", - G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_LANGUAGE, + g_param_spec_pointer ("language", + "Language", + "The language used by the spell checker", + G_PARAM_READWRITE)); - signals[ADD_WORD_TO_PERSONAL] = - g_signal_new ("add_word_to_personal", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_personal), - NULL, NULL, - xed_marshal_VOID__STRING_INT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_INT); + signals[ADD_WORD_TO_PERSONAL] = + g_signal_new ("add_word_to_personal", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_personal), + NULL, NULL, + xed_marshal_VOID__STRING_INT, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_INT); - signals[ADD_WORD_TO_SESSION] = - g_signal_new ("add_word_to_session", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_session), - NULL, NULL, - xed_marshal_VOID__STRING_INT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_INT); + signals[ADD_WORD_TO_SESSION] = + g_signal_new ("add_word_to_session", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_session), + NULL, NULL, + xed_marshal_VOID__STRING_INT, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_INT); - signals[SET_LANGUAGE] = - g_signal_new ("set_language", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, set_language), - NULL, NULL, - xed_marshal_VOID__POINTER, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); + signals[SET_LANGUAGE] = + g_signal_new ("set_language", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (XedSpellCheckerClass, set_language), + NULL, NULL, + xed_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); - signals[CLEAR_SESSION] = - g_signal_new ("clear_session", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, clear_session), - NULL, NULL, - xed_marshal_VOID__VOID, - G_TYPE_NONE, - 0); + signals[CLEAR_SESSION] = + g_signal_new ("clear_session", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (XedSpellCheckerClass, clear_session), + NULL, NULL, + xed_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } static void xed_spell_checker_init (XedSpellChecker *spell_checker) { - spell_checker->broker = enchant_broker_init (); - spell_checker->dict = NULL; - spell_checker->active_lang = NULL; + spell_checker->broker = enchant_broker_init (); + spell_checker->dict = NULL; + spell_checker->active_lang = NULL; } XedSpellChecker * -xed_spell_checker_new (void) +xed_spell_checker_new (void) { - XedSpellChecker *spell; + XedSpellChecker *spell; - spell = XED_SPELL_CHECKER ( - g_object_new (XED_TYPE_SPELL_CHECKER, NULL)); + spell = XED_SPELL_CHECKER (g_object_new (XED_TYPE_SPELL_CHECKER, NULL)); - g_return_val_if_fail (spell != NULL, NULL); + g_return_val_if_fail (spell != NULL, NULL); - return spell; + return spell; } static gboolean lazy_init (XedSpellChecker *spell, - const XedSpellCheckerLanguage *language) + const XedSpellCheckerLanguage *language) { - if (spell->dict != NULL) - return TRUE; + if (spell->dict != NULL) + { + return TRUE; + } - g_return_val_if_fail (spell->broker != NULL, FALSE); + g_return_val_if_fail (spell->broker != NULL, FALSE); - spell->active_lang = NULL; + spell->active_lang = NULL; - if (language != NULL) - { - spell->active_lang = language; - } - else - { - /* First try to get a default language */ - const XedSpellCheckerLanguage *l; - gint i = 0; - const gchar * const *lang_tags = g_get_language_names (); + if (language != NULL) + { + spell->active_lang = language; + } + else + { + /* First try to get a default language */ + const XedSpellCheckerLanguage *l; + gint i = 0; + const gchar * const *lang_tags = g_get_language_names (); - while (lang_tags [i]) - { - l = xed_spell_checker_language_from_key (lang_tags [i]); + while (lang_tags [i]) + { + l = xed_spell_checker_language_from_key (lang_tags [i]); - if (l != NULL) - { - spell->active_lang = l; - break; - } + if (l != NULL) + { + spell->active_lang = l; + break; + } - i++; - } - } + i++; + } + } - /* Second try to get a default language */ - if (spell->active_lang == NULL) - spell->active_lang = xed_spell_checker_language_from_key ("en_US"); + /* Second try to get a default language */ + if (spell->active_lang == NULL) + { + spell->active_lang = xed_spell_checker_language_from_key ("en_US"); + } - /* Last try to get a default language */ - if (spell->active_lang == NULL) - { - const GSList *langs; - langs = xed_spell_checker_get_available_languages (); - if (langs != NULL) - spell->active_lang = (const XedSpellCheckerLanguage *)langs->data; - } + /* Last try to get a default language */ + if (spell->active_lang == NULL) + { + const GSList *langs; + langs = xed_spell_checker_get_available_languages (); + if (langs != NULL) + { + spell->active_lang = (const XedSpellCheckerLanguage *)langs->data; + } + } - if (spell->active_lang != NULL) - { - const gchar *key; + if (spell->active_lang != NULL) + { + const gchar *key; - key = xed_spell_checker_language_to_key (spell->active_lang); + key = xed_spell_checker_language_to_key (spell->active_lang); - spell->dict = enchant_broker_request_dict (spell->broker, - key); - } + spell->dict = enchant_broker_request_dict (spell->broker, key); + } - if (spell->dict == NULL) - { - spell->active_lang = NULL; + if (spell->dict == NULL) + { + spell->active_lang = NULL; - if (language != NULL) - g_warning ("Spell checker plugin: cannot select a default language."); + if (language != NULL) + { + g_warning ("Spell checker plugin: cannot select a default language."); + } - return FALSE; - } + return FALSE; + } - return TRUE; + return TRUE; } gboolean xed_spell_checker_set_language (XedSpellChecker *spell, - const XedSpellCheckerLanguage *language) + const XedSpellCheckerLanguage *language) { - gboolean ret; + gboolean ret; - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - if (spell->dict != NULL) - { - enchant_broker_free_dict (spell->broker, spell->dict); - spell->dict = NULL; - } + if (spell->dict != NULL) + { + enchant_broker_free_dict (spell->broker, spell->dict); + spell->dict = NULL; + } - ret = lazy_init (spell, language); + ret = lazy_init (spell, language); - if (ret) - g_signal_emit (G_OBJECT (spell), signals[SET_LANGUAGE], 0, language); - else - g_warning ("Spell checker plugin: cannot use language %s.", - xed_spell_checker_language_to_string (language)); - - return ret; + if (ret) + { + g_signal_emit (G_OBJECT (spell), signals[SET_LANGUAGE], 0, language); + } + else + { + g_warning ("Spell checker plugin: cannot use language %s.", xed_spell_checker_language_to_string (language)); + } + + return ret; } const XedSpellCheckerLanguage * xed_spell_checker_get_language (XedSpellChecker *spell) { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); - if (!lazy_init (spell, spell->active_lang)) - return NULL; + if (!lazy_init (spell, spell->active_lang)) + { + return NULL; + } - return spell->active_lang; + return spell->active_lang; } gboolean xed_spell_checker_check_word (XedSpellChecker *spell, - const gchar *word, - gssize len) + const gchar *word, + gssize len) { - gint enchant_result; - gboolean res = FALSE; + gint enchant_result; + gboolean res = FALSE; - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (word != NULL, FALSE); - if (!lazy_init (spell, spell->active_lang)) - return FALSE; + if (!lazy_init (spell, spell->active_lang)) + { + return FALSE; + } - if (len < 0) - len = strlen (word); + if (len < 0) + { + len = strlen (word); + } - if (strcmp (word, "xed") == 0) - return TRUE; + if (strcmp (word, "xed") == 0) + { + return TRUE; + } - if (xed_spell_utils_is_digit (word, len)) - return TRUE; + if (xed_spell_utils_is_digit (word, len)) + { + return TRUE; + } - g_return_val_if_fail (spell->dict != NULL, FALSE); - enchant_result = enchant_dict_check (spell->dict, word, len); + g_return_val_if_fail (spell->dict != NULL, FALSE); + enchant_result = enchant_dict_check (spell->dict, word, len); - switch (enchant_result) - { - case -1: - /* error */ - res = FALSE; + switch (enchant_result) + { + case -1: + /* error */ + res = FALSE; - g_warning ("Spell checker plugin: error checking word '%s' (%s).", - word, enchant_dict_get_error (spell->dict)); + g_warning ("Spell checker plugin: error checking word '%s' (%s).", + word, enchant_dict_get_error (spell->dict)); - break; - case 1: - /* it is not in the directory */ - res = FALSE; - break; - case 0: - /* is is in the directory */ - res = TRUE; - break; - default: - g_return_val_if_reached (FALSE); - } + break; + case 1: + /* it is not in the directory */ + res = FALSE; + break; + case 0: + /* is is in the directory */ + res = TRUE; + break; + default: + g_return_val_if_reached (FALSE); + } - return res; + return res; } /* return NULL on error or if no suggestions are found */ GSList * xed_spell_checker_get_suggestions (XedSpellChecker *spell, - const gchar *word, - gssize len) + const gchar *word, + gssize len) { - gchar **suggestions; - size_t n_suggestions = 0; - GSList *suggestions_list = NULL; - gint i; + gchar **suggestions; + size_t n_suggestions = 0; + GSList *suggestions_list = NULL; + gint i; - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); - g_return_val_if_fail (word != NULL, NULL); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); + g_return_val_if_fail (word != NULL, NULL); - if (!lazy_init (spell, spell->active_lang)) - return NULL; + if (!lazy_init (spell, spell->active_lang)) + { + return NULL; + } - g_return_val_if_fail (spell->dict != NULL, NULL); + g_return_val_if_fail (spell->dict != NULL, NULL); - if (len < 0) - len = strlen (word); + if (len < 0) + { + len = strlen (word); + } - suggestions = enchant_dict_suggest (spell->dict, word, len, &n_suggestions); + suggestions = enchant_dict_suggest (spell->dict, word, len, &n_suggestions); - if (n_suggestions == 0) - return NULL; + if (n_suggestions == 0) + { + return NULL; + } - g_return_val_if_fail (suggestions != NULL, NULL); + g_return_val_if_fail (suggestions != NULL, NULL); - for (i = 0; i < (gint)n_suggestions; i++) - { - suggestions_list = g_slist_prepend (suggestions_list, - suggestions[i]); - } + for (i = 0; i < (gint)n_suggestions; i++) + { + suggestions_list = g_slist_prepend (suggestions_list, suggestions[i]); + } - /* The single suggestions will be freed by the caller */ - g_free (suggestions); + /* The single suggestions will be freed by the caller */ + g_free (suggestions); - suggestions_list = g_slist_reverse (suggestions_list); + suggestions_list = g_slist_reverse (suggestions_list); - return suggestions_list; + return suggestions_list; } gboolean xed_spell_checker_add_word_to_personal (XedSpellChecker *spell, - const gchar *word, - gssize len) + const gchar *word, + gssize len) { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (word != NULL, FALSE); - if (!lazy_init (spell, spell->active_lang)) - return FALSE; + if (!lazy_init (spell, spell->active_lang)) + { + return FALSE; + } - g_return_val_if_fail (spell->dict != NULL, FALSE); + g_return_val_if_fail (spell->dict != NULL, FALSE); - if (len < 0) - len = strlen (word); + if (len < 0) + { + len = strlen (word); + } - enchant_dict_add_to_pwl (spell->dict, word, len); + enchant_dict_add_to_pwl (spell->dict, word, len); - g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len); + g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len); - return TRUE; + return TRUE; } gboolean xed_spell_checker_add_word_to_session (XedSpellChecker *spell, - const gchar *word, - gssize len) + const gchar *word, + gssize len) { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (word != NULL, FALSE); - if (!lazy_init (spell, spell->active_lang)) - return FALSE; + if (!lazy_init (spell, spell->active_lang)) + { + return FALSE; + } - g_return_val_if_fail (spell->dict != NULL, FALSE); + g_return_val_if_fail (spell->dict != NULL, FALSE); - if (len < 0) - len = strlen (word); + if (len < 0) + { + len = strlen (word); + } - enchant_dict_add_to_session (spell->dict, word, len); + enchant_dict_add_to_session (spell->dict, word, len); - g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_SESSION], 0, word, len); + g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_SESSION], 0, word, len); - return TRUE; + return TRUE; } gboolean xed_spell_checker_clear_session (XedSpellChecker *spell) { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - /* free and re-request dictionary */ - if (spell->dict != NULL) - { - enchant_broker_free_dict (spell->broker, spell->dict); - spell->dict = NULL; - } + /* free and re-request dictionary */ + if (spell->dict != NULL) + { + enchant_broker_free_dict (spell->broker, spell->dict); + spell->dict = NULL; + } - if (!lazy_init (spell, spell->active_lang)) - return FALSE; + if (!lazy_init (spell, spell->active_lang)) + { + return FALSE; + } - g_signal_emit (G_OBJECT (spell), signals[CLEAR_SESSION], 0); + g_signal_emit (G_OBJECT (spell), signals[CLEAR_SESSION], 0); - return TRUE; + return TRUE; } /* @@ -489,32 +527,38 @@ xed_spell_checker_clear_session (XedSpellChecker *spell) */ gboolean xed_spell_checker_set_correction (XedSpellChecker *spell, - const gchar *word, - gssize w_len, - const gchar *replacement, - gssize r_len) + const gchar *word, + gssize w_len, + const gchar *replacement, + gssize r_len) { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); - g_return_val_if_fail (replacement != NULL, FALSE); + g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); + g_return_val_if_fail (word != NULL, FALSE); + g_return_val_if_fail (replacement != NULL, FALSE); - if (!lazy_init (spell, spell->active_lang)) - return FALSE; + if (!lazy_init (spell, spell->active_lang)) + { + return FALSE; + } - g_return_val_if_fail (spell->dict != NULL, FALSE); + g_return_val_if_fail (spell->dict != NULL, FALSE); - if (w_len < 0) - w_len = strlen (word); + if (w_len < 0) + { + w_len = strlen (word); + } - if (r_len < 0) - r_len = strlen (replacement); + if (r_len < 0) + { + r_len = strlen (replacement); + } - enchant_dict_store_replacement (spell->dict, - word, - w_len, - replacement, - r_len); + enchant_dict_store_replacement (spell->dict, + word, + w_len, + replacement, + r_len); - return TRUE; + return TRUE; } From 0a2560088375358ef72faf5c7228ac1854cc0a9d Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Sun, 10 Dec 2017 15:38:15 -0800 Subject: [PATCH 13/18] spell-plugin: Update for removal of some deprecated functionality enchant_dict_add_to_pwl () was removed from libenchant. Use it's replacement, enchant_dict_add () instead and bump our required version of libenchant. Closes https://github.com/linuxmint/xed/issues/198 --- configure.ac | 2 +- plugins/spell/xed-spell-checker.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index aaf0017..e282b07 100644 --- a/configure.ac +++ b/configure.ac @@ -94,7 +94,7 @@ dnl ================================================================ dnl spell plugins checks: enchant and iso-codes dnl ================================================================ -ENCHANT_REQUIRED=1.2.0 +ENCHANT_REQUIRED=1.6.0 ISO_CODES_REQUIRED=0.35 AC_ARG_ENABLE([spell], diff --git a/plugins/spell/xed-spell-checker.c b/plugins/spell/xed-spell-checker.c index e45e926..65d55fa 100644 --- a/plugins/spell/xed-spell-checker.c +++ b/plugins/spell/xed-spell-checker.c @@ -465,7 +465,7 @@ xed_spell_checker_add_word_to_personal (XedSpellChecker *spell, len = strlen (word); } - enchant_dict_add_to_pwl (spell->dict, word, len); + enchant_dict_add (spell->dict, word, len); g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len); From 6c7e40c3ba072da5e5809f84b0c3759fb751c032 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Tue, 12 Dec 2017 18:42:51 -0800 Subject: [PATCH 14/18] xed-notebook: Allow changing tabs with mouse back/forward buttons While at it, fix the direction for switching tabs when scrolling with the mouse wheel. Closes https://github.com/linuxmint/xed/issues/115 --- xed/xed-notebook.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/xed/xed-notebook.c b/xed/xed-notebook.c index 6e13d4b..8dceee0 100644 --- a/xed/xed-notebook.c +++ b/xed/xed-notebook.c @@ -543,6 +543,8 @@ button_release_cb (XedNotebook *notebook, GdkEventButton *event, gpointer data) { + gboolean ret_val = FALSE; + if (notebook->priv->drag_in_progress) { gint cur_page_num; @@ -566,11 +568,23 @@ button_release_cb (XedNotebook *notebook, } gtk_grab_remove (GTK_WIDGET (notebook)); } + else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 8)) + { + gtk_notebook_prev_page (GTK_NOTEBOOK (notebook)); + + ret_val = TRUE; + } + else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 9)) + { + gtk_notebook_next_page (GTK_NOTEBOOK (notebook)); + + ret_val = TRUE; + } /* This must be called even if a drag isn't happening */ drag_stop (notebook); - return FALSE; + return ret_val; } static gboolean @@ -638,13 +652,13 @@ notebook_scroll_event_cb (XedNotebook *notebook, switch (event->direction) { case GDK_SCROLL_DOWN: - case GDK_SCROLL_RIGHT: - gtk_notebook_next_page (GTK_NOTEBOOK (notebook)); - break; - case GDK_SCROLL_UP: case GDK_SCROLL_LEFT: gtk_notebook_prev_page (GTK_NOTEBOOK (notebook)); break; + case GDK_SCROLL_UP: + case GDK_SCROLL_RIGHT: + gtk_notebook_next_page (GTK_NOTEBOOK (notebook)); + break; default: break; } From 39dcfcab0b947968efd803197c5f6eb543d49959 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Sun, 28 Jan 2018 01:56:46 -0800 Subject: [PATCH 15/18] Fix a couple of issues turned up by Codacy --- xed/xed-commands-file.c | 2 -- xed/xed-document.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xed/xed-commands-file.c b/xed/xed-commands-file.c index 098dcb4..a6893bc 100644 --- a/xed/xed-commands-file.c +++ b/xed/xed-commands-file.c @@ -533,7 +533,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog, { XedTab *tab; XedWindow *window; - XedDocument *doc; GtkSourceFile *file; GFile *location; gchar *parse_name; @@ -554,7 +553,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog, return; } - doc = xed_tab_get_document (tab); location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); g_return_if_fail (location != NULL); diff --git a/xed/xed-document.c b/xed/xed-document.c index 470e831..b8d9bfe 100644 --- a/xed/xed-document.c +++ b/xed/xed-document.c @@ -948,6 +948,8 @@ xed_document_set_location (XedDocument *doc, g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (G_IS_FILE (location)); + priv = xed_document_get_instance_private (doc); + gtk_source_file_set_location (priv->file, location); xed_document_set_content_type (doc, NULL); } @@ -1380,7 +1382,7 @@ xed_document_get_encoding (XedDocument *doc) g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - xed_document_get_instance_private (doc); + priv = xed_document_get_instance_private (doc); return gtk_source_file_get_encoding (priv->file); } From 19354f86c1cf42a2f42a20447dbe228d4abd3024 Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Mon, 5 Feb 2018 01:48:10 -0800 Subject: [PATCH 16/18] Clean up a few build warnings Mostly just missing casts and removing a couple now unused functions and variables. --- xed/xed-commands-file.c | 1 - xed/xed-settings.c | 20 -------------------- xed/xed-view-gutter-renderer.c | 1 - xed/xed-window.c | 26 ++++++++------------------ 4 files changed, 8 insertions(+), 40 deletions(-) diff --git a/xed/xed-commands-file.c b/xed/xed-commands-file.c index a6893bc..e126006 100644 --- a/xed/xed-commands-file.c +++ b/xed/xed-commands-file.c @@ -533,7 +533,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog, { XedTab *tab; XedWindow *window; - GtkSourceFile *file; GFile *location; gchar *parse_name; GtkSourceNewlineType newline_type; diff --git a/xed/xed-settings.c b/xed/xed-settings.c index 3a1d02d..6f9d5ff 100644 --- a/xed/xed-settings.c +++ b/xed/xed-settings.c @@ -282,26 +282,6 @@ on_auto_save_interval_changed (GSettings *settings, g_list_free (docs); } -static void -on_wrap_mode_changed (GSettings *settings, - const gchar *key, - XedSettings *xs) -{ - GtkWrapMode wrap_mode; - GList *views, *l; - - wrap_mode = g_settings_get_enum (settings, key); - - views = xed_app_get_views (XED_APP (g_application_get_default ())); - - for (l = views; l != NULL; l = g_list_next (l)) - { - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (l->data), wrap_mode); - } - - g_list_free (views); -} - static void on_syntax_highlighting_changed (GSettings *settings, const gchar *key, diff --git a/xed/xed-view-gutter-renderer.c b/xed/xed-view-gutter-renderer.c index f516543..b6b3362 100644 --- a/xed/xed-view-gutter-renderer.c +++ b/xed/xed-view-gutter-renderer.c @@ -7,7 +7,6 @@ G_DEFINE_TYPE (XedViewGutterRenderer, xed_view_gutter_renderer, GTK_SOURCE_TYPE_ static void xed_view_gutter_renderer_class_init (XedViewGutterRendererClass *klass) { - GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass); } static void diff --git a/xed/xed-window.c b/xed/xed-window.c index 16fa803..84bd94a 100644 --- a/xed/xed-window.c +++ b/xed/xed-window.c @@ -1197,7 +1197,6 @@ create_menu_bar_and_toolbar (XedWindow *window, GtkUIManager *manager; GtkRecentManager *recent_manager; GError *error = NULL; - gchar *ui_file; GtkWidget *tool_item; GtkWidget *tool_box; GtkWidget *box; @@ -2170,7 +2169,7 @@ show_overview_map_changed (GObject *object, map_frame = GTK_FRAME (object); action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap"); - if (gtk_widget_get_visible (map_frame)) + if (gtk_widget_get_visible (GTK_WIDGET (map_frame))) { overveiw_map_visible = TRUE; } @@ -2223,7 +2222,7 @@ notebook_switch_page (GtkNotebook *book, if (window->priv->show_overview_map_id) { - g_signal_handler_disconnect (xed_view_frame_get_map_frame (_xed_tab_get_view_frame (window->priv->active_tab)), window->priv->show_overview_map_id); + g_signal_handler_disconnect (xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (window->priv->active_tab))), window->priv->show_overview_map_id); window->priv->show_overview_map_id = 0; } } @@ -2253,7 +2252,7 @@ notebook_switch_page (GtkNotebook *book, update_languages_menu (window); view = xed_tab_get_view (tab); - map_frame = xed_view_frame_get_map_frame (_xed_tab_get_view_frame (tab)); + map_frame = xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (tab))); /* sync the statusbar */ update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window); @@ -2360,15 +2359,6 @@ set_sensitivity_according_to_window_state (XedWindow *window) } } -static void -update_tab_autosave (GtkWidget *widget, - gpointer data) -{ - XedTab *tab = XED_TAB(widget); - gboolean *enabled = (gboolean *) data; - xed_tab_set_auto_save_enabled (tab, *enabled); -} - static void analyze_tab_state (XedTab *tab, XedWindow *window) @@ -2444,7 +2434,7 @@ update_can_close (XedWindow *window) GList *l; gboolean can_close = TRUE; - tabs = xed_notebook_get_all_tabs (priv->notebook); + tabs = xed_notebook_get_all_tabs (XED_NOTEBOOK (priv->notebook)); for (l = tabs; l != NULL; l = g_list_next (l)) { @@ -2947,7 +2937,7 @@ notebook_tab_removed (XedNotebook *notebook, --window->priv->num_tabs; view = xed_tab_get_view (tab); - frame = _xed_tab_get_view_frame (tab); + frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab)); doc = xed_tab_get_document (tab); g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window); @@ -3150,7 +3140,7 @@ side_panel_size_allocate (GtkWidget *widget, GtkAllocation *allocation, XedWindow *window) { - if (!xed_paned_get_is_animating (window->priv->hpaned)) + if (!xed_paned_get_is_animating (XED_PANED (window->priv->hpaned))) { window->priv->side_panel_size = allocation->width; } @@ -3161,7 +3151,7 @@ bottom_panel_size_allocate (GtkWidget *widget, GtkAllocation *allocation, XedWindow *window) { - if (!xed_paned_get_is_animating (window->priv->vpaned)) + if (!xed_paned_get_is_animating (XED_PANED (window->priv->vpaned))) { window->priv->bottom_panel_size = allocation->height; } @@ -3282,7 +3272,7 @@ bottom_panel_item_removed (XedPanel *panel, { GtkAction *action; - xed_paned_close (window->priv->vpaned, 2); + xed_paned_close (XED_PANED (window->priv->vpaned), 2); gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE); action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane"); gtk_action_set_sensitive (action, FALSE); From bd32e81f1393b901781b654070606a81e5cb0fed Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Thu, 8 Feb 2018 23:26:23 -0800 Subject: [PATCH 17/18] spell-plugin: Port to gspell --- configure.ac | 46 +- debian/control | 3 +- plugins/Makefile.am | 2 +- plugins/spell/Makefile.am | 18 +- plugins/spell/languages-dialog.ui | 140 --- plugins/spell/spell-checker.ui | 369 ------ plugins/spell/xed-automatic-spell-checker.c | 967 --------------- plugins/spell/xed-automatic-spell-checker.h | 67 - plugins/spell/xed-spell-checker-dialog.c | 726 ----------- plugins/spell/xed-spell-checker-dialog.h | 92 -- plugins/spell/xed-spell-checker-language.c | 439 ------- plugins/spell/xed-spell-checker-language.h | 51 - plugins/spell/xed-spell-checker.c | 564 --------- plugins/spell/xed-spell-checker.h | 109 -- plugins/spell/xed-spell-language-dialog.c | 284 ----- plugins/spell/xed-spell-language-dialog.h | 65 - plugins/spell/xed-spell-plugin.c | 1216 ++++++------------- plugins/spell/xed-spell-utils.c | 94 -- plugins/spell/xed-spell-utils.h | 37 - 19 files changed, 365 insertions(+), 4924 deletions(-) delete mode 100644 plugins/spell/languages-dialog.ui delete mode 100644 plugins/spell/spell-checker.ui delete mode 100644 plugins/spell/xed-automatic-spell-checker.c delete mode 100644 plugins/spell/xed-automatic-spell-checker.h delete mode 100644 plugins/spell/xed-spell-checker-dialog.c delete mode 100644 plugins/spell/xed-spell-checker-dialog.h delete mode 100644 plugins/spell/xed-spell-checker-language.c delete mode 100644 plugins/spell/xed-spell-checker-language.h delete mode 100644 plugins/spell/xed-spell-checker.c delete mode 100644 plugins/spell/xed-spell-checker.h delete mode 100644 plugins/spell/xed-spell-language-dialog.c delete mode 100644 plugins/spell/xed-spell-language-dialog.h delete mode 100644 plugins/spell/xed-spell-utils.c delete mode 100644 plugins/spell/xed-spell-utils.h diff --git a/configure.ac b/configure.ac index e282b07..ee138fc 100644 --- a/configure.ac +++ b/configure.ac @@ -94,49 +94,25 @@ dnl ================================================================ dnl spell plugins checks: enchant and iso-codes dnl ================================================================ -ENCHANT_REQUIRED=1.6.0 -ISO_CODES_REQUIRED=0.35 +GSPELL_REQUIRED=0.2.5 AC_ARG_ENABLE([spell], AS_HELP_STRING([--disable-spell],[Disable spell plugin (default: enabled)]), - [enable_enchant=$enableval], - [enable_enchant=yes]) + [enable_spell=$enableval], + [enable_spell=yes]) -if test "x$enable_enchant" = "xyes" ; then +if test "x$enable_spell" = "xyes" ; then - PKG_CHECK_MODULES(ENCHANT, enchant >= $ENCHANT_REQUIRED, \ - have_enchant=yes, have_enchant=no) + PKG_CHECK_MODULES(GSPELL, gspell-1 >= $GSPELL_REQUIRED, \ + have_gspell=yes, have_gspell=no) - if test "x$have_enchant" = "xyes"; then - - PKG_CHECK_EXISTS([iso-codes >= $ISO_CODES_REQUIRED], - [have_iso_codes=yes],[have_iso_codes=no]) - - if test "x$have_iso_codes" = "xyes"; then - AC_MSG_CHECKING([whether iso-codes has iso-639 and iso-3166 domains]) - if $PKG_CONFIG --variable=domains iso-codes | grep 639 > /dev/null && \ - $PKG_CONFIG --variable=domains iso-codes | grep 3166 > /dev/null ; then - result=yes - else - result=no - have_iso_codes=no - fi - AC_MSG_RESULT([$result]) - fi - - if test "x$have_iso_codes" = "xyes"; then - AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix]) - AC_DEFINE([HAVE_ISO_CODES],[1],[Define if you have the iso-codes package]) - else - AC_MSG_ERROR([iso-codes is required to build the spell plugin. Use --disable-spell to build without spell plugin.]) - fi - else - enable_enchant=no - AC_MSG_ERROR([Enchant library not found or too old. Use --disable-spell to build without spell plugin.]) + if test "x$have_gspell" = "xno"; then + enable_spell=no + AC_MSG_ERROR([gspell library not found or too old. Use --disable-spell to build without spell plugin.]) fi fi -AM_CONDITIONAL(ENABLE_ENCHANT, test x"$enable_enchant" = "xyes") +AM_CONDITIONAL(ENABLE_SPELL, test x"$enable_spell" = "xyes") dnl ================================================================ dnl Start of pkg-config checks @@ -255,7 +231,7 @@ Configuration: Source code location: ${srcdir} Compiler: ${CC} - Spell Plugin enabled: $enable_enchant + Spell Plugin enabled: $enable_spell Gvfs metadata enabled: $enable_gvfs_metadata GObject Introspection: ${enable_introspection} " diff --git a/debian/control b/debian/control index 493e733..8d7e25e 100644 --- a/debian/control +++ b/debian/control @@ -7,10 +7,9 @@ Build-Depends: autotools-dev, gobject-introspection, gtk-doc-tools, intltool, - iso-codes, - libenchant-dev, libgirepository1.0-dev, libglib2.0-dev, + libgspell-1-dev, libgtk-3-dev, libgtksourceview-3.0-dev, libpeas-dev, diff --git a/plugins/Makefile.am b/plugins/Makefile.am index e6e56c7..846c57c 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -19,7 +19,7 @@ SUBDIRS = \ time \ trailsave -if ENABLE_ENCHANT +if ENABLE_SPELL SUBDIRS += spell endif diff --git a/plugins/spell/Makefile.am b/plugins/spell/Makefile.am index 1afd0d3..504a4f0 100644 --- a/plugins/spell/Makefile.am +++ b/plugins/spell/Makefile.am @@ -4,7 +4,7 @@ plugindir = $(XED_PLUGINS_LIBS_DIR) AM_CPPFLAGS = \ -I$(top_srcdir) \ $(XED_CFLAGS) \ - $(ENCHANT_CFLAGS) \ + $(GSPELL_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) @@ -17,25 +17,13 @@ plugin_LTLIBRARIES = libspell.la libspell_la_SOURCES = \ xed-spell-plugin.c \ xed-spell-plugin.h \ - xed-spell-checker.c \ - xed-spell-checker.h \ - xed-spell-checker-dialog.c \ - xed-spell-checker-dialog.h \ - xed-spell-checker-language.c \ - xed-spell-checker-language.h \ - xed-spell-language-dialog.c \ - xed-spell-language-dialog.h \ - xed-automatic-spell-checker.c \ - xed-automatic-spell-checker.h \ - xed-spell-utils.c \ - xed-spell-utils.h \ $(BUILT_SOURCES) libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) -libspell_la_LIBADD = $(XED_LIBS) $(ENCHANT_LIBS) +libspell_la_LIBADD = $(XED_LIBS) $(GSPELL_LIBS) uidir = $(XED_PLUGINS_DATA_DIR)/spell -ui_DATA = spell-checker.ui languages-dialog.ui xed-spell-setup-dialog.ui +ui_DATA = xed-spell-setup-dialog.ui xed-spell-marshal.h: xed-spell-marshal.list $(GLIB_GENMARSHAL) $(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=xed_marshal > $@ diff --git a/plugins/spell/languages-dialog.ui b/plugins/spell/languages-dialog.ui deleted file mode 100644 index 28ec4fb..0000000 --- a/plugins/spell/languages-dialog.ui +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - False - 5 - Set language - True - True - dialog - - - True - False - 2 - - - True - False - end - - - gtk-help - True - True - True - False - True - - - True - True - 0 - - - - - gtk-cancel - True - True - True - False - True - - - True - True - 1 - - - - - gtk-ok - True - True - True - False - True - - - True - True - 2 - - - - - False - True - end - 0 - - - - - True - False - True - True - 5 - vertical - 11 - - - True - False - Select the _language of the current document. - True - True - languages_treeview - 0 - - - False - False - 0 - - - - - 180 - True - True - etched-in - - - 180 - True - True - False - - - - - - - - True - True - 1 - - - - - False - True - 0 - - - - - - helpbutton1 - closebutton1 - button1 - - - diff --git a/plugins/spell/spell-checker.ui b/plugins/spell/spell-checker.ui deleted file mode 100644 index f5f8a30..0000000 --- a/plugins/spell/spell-checker.ui +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - False - False - True - dialog - True - Check spelling - - - True - False - 12 - vertical - 6 - - - True - False - True - 6 - 12 - - - True - False - Misspelled word: - 0 - - - 0 - 0 - - - - - True - False - word - True - center - 0 - - - 1 - 0 - - - - - True - False - Change _to: - True - 0 - - - 0 - 1 - - - - - True - False - True - 12 - - - True - True - True - - - False - True - 0 - - - - - Check _Word - True - True - True - True - - - False - True - 1 - - - - - 1 - 1 - - - - - False - True - 0 - - - - - True - False - 6 - 12 - - - True - False - _Suggestions: - True - 0 - - - 0 - 0 - - - - - True - True - True - True - in - - - True - True - False - - - - - - - - 0 - 1 - - - - - True - False - 6 - vertical - 12 - - - True - False - 12 - 12 - - - _Ignore - True - True - True - True - - - 0 - 0 - - - - - Ignore _All - True - True - True - True - - - 1 - 0 - - - - - Cha_nge - True - True - True - True - - - 0 - 1 - - - - - Change A_ll - True - True - True - True - - - 1 - 1 - - - - - False - True - 0 - - - - - True - False - vertical - 11 - - - True - False - User dictionary: - True - 0 - - - False - True - 0 - - - - - True - False - 6 - True - - - Add w_ord - True - True - True - True - - - False - True - 0 - - - - - False - True - 2 - - - - - False - True - 1 - - - - - 1 - 1 - - - - - True - False - 12 - - - True - False - Language: - - - False - True - 0 - - - - - True - False - Language - True - - - False - True - 1 - - - - - 0 - 2 - - - - - True - False - True - end - - - _Close - True - True - True - end - True - - - - True - True - 0 - - - - - 1 - 3 - - - - - - - - - - - - - - True - True - 1 - - - - - - diff --git a/plugins/spell/xed-automatic-spell-checker.c b/plugins/spell/xed-automatic-spell-checker.c deleted file mode 100644 index 1202920..0000000 --- a/plugins/spell/xed-automatic-spell-checker.c +++ /dev/null @@ -1,967 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-automatic-spell-checker.c - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -/* This is a modified version of gtkspell 2.0.5 (gtkspell.sf.net) */ -/* gtkspell - a spell-checking addon for GTK's TextView widget - * Copyright (c) 2002 Evan Martin. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include "xed-automatic-spell-checker.h" -#include "xed-spell-utils.h" - -struct _XedAutomaticSpellChecker -{ - XedDocument *doc; - GSList *views; - - GtkTextMark *mark_insert_start; - GtkTextMark *mark_insert_end; - gboolean deferred_check; - - GtkTextTag *tag_highlight; - GtkTextMark *mark_click; - - XedSpellChecker *spell_checker; -}; - -static GQuark automatic_spell_checker_id = 0; -static GQuark suggestion_id = 0; - -static void xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell); - -static void -view_destroy (XedView *view, - XedAutomaticSpellChecker *spell) -{ - xed_automatic_spell_checker_detach_view (spell, view); -} - -static void -check_word (XedAutomaticSpellChecker *spell, - GtkTextIter *start, - GtkTextIter *end) -{ - gchar *word; - - word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), start, end, FALSE); - - /* - g_print ("Check word: %s [%d - %d]\n", word, gtk_text_iter_get_offset (start), - gtk_text_iter_get_offset (end)); - */ - - if (!xed_spell_checker_check_word (spell->spell_checker, word, -1)) - { - /* - g_print ("Apply tag: [%d - %d]\n", gtk_text_iter_get_offset (start), - gtk_text_iter_get_offset (end)); - */ - gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, start, end); - } - - g_free (word); -} - -static void -check_range (XedAutomaticSpellChecker *spell, - GtkTextIter start, - GtkTextIter end, - gboolean force_all) -{ - /* we need to "split" on word boundaries. - * luckily, Pango knows what "words" are - * so we don't have to figure it out. */ - - GtkTextIter wstart; - GtkTextIter wend; - GtkTextIter cursor; - GtkTextIter precursor; - gboolean highlight; - - /* - g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start), - gtk_text_iter_get_offset (&end)); - */ - - if (gtk_text_iter_inside_word (&end)) - { - gtk_text_iter_forward_word_end (&end); - } - - if (!gtk_text_iter_starts_word (&start)) - { - if (gtk_text_iter_inside_word (&start) || gtk_text_iter_ends_word (&start)) - { - gtk_text_iter_backward_word_start (&start); - } - else - { - /* if we're neither at the beginning nor inside a word, - * me must be in some spaces. - * skip forward to the beginning of the next word. */ - - if (gtk_text_iter_forward_word_end (&start)) - { - gtk_text_iter_backward_word_start (&start); - } - } - } - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), - &cursor, - gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc))); - - precursor = cursor; - gtk_text_iter_backward_char (&precursor); - - highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) || - gtk_text_iter_has_tag (&precursor, spell->tag_highlight); - - gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end); - - /* Fix a corner case when replacement occurs at beginning of buffer: - * An iter at offset 0 seems to always be inside a word, - * even if it's not. Possibly a pango bug. - */ - if (gtk_text_iter_get_offset (&start) == 0) - { - gtk_text_iter_forward_word_end(&start); - gtk_text_iter_backward_word_start(&start); - } - - wstart = start; - - while (xed_spell_utils_skip_no_spell_check (&wstart, &end) && gtk_text_iter_compare (&wstart, &end) < 0) - { - gboolean inword; - - /* move wend to the end of the current word. */ - wend = wstart; - - gtk_text_iter_forward_word_end (&wend); - - inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) && (gtk_text_iter_compare (&cursor, &wend) <= 0); - - if (inword && !force_all) - { - /* this word is being actively edited, - * only check if it's already highligted, - * otherwise defer this check until later. */ - if (highlight) - { - check_word (spell, &wstart, &wend); - } - else - { - spell->deferred_check = TRUE; - } - } - else - { - check_word (spell, &wstart, &wend); - spell->deferred_check = FALSE; - } - - /* now move wend to the beginning of the next word, */ - gtk_text_iter_forward_word_end (&wend); - gtk_text_iter_backward_word_start (&wend); - - /* make sure we've actually advanced - * (we don't advance in some corner cases), */ - if (gtk_text_iter_equal (&wstart, &wend)) - { - break; /* we're done in these cases.. */ - } - - /* and then pick this as the new next word beginning. */ - wstart = wend; - } -} - -static void -check_deferred_range (XedAutomaticSpellChecker *spell, - gboolean force_all) -{ - GtkTextIter start, end; - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &start, spell->mark_insert_start); - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &end, spell->mark_insert_end); - - check_range (spell, start, end, force_all); -} - -/* insertion works like this: - * - before the text is inserted, we mark the position in the buffer. - * - after the text is inserted, we see where our mark is and use that and - * the current position to check the entire range of inserted text. - * - * this may be overkill for the common case (inserting one character). */ - -static void -insert_text_before (GtkTextBuffer *buffer, - GtkTextIter *iter, - gchar *text, - gint len, - XedAutomaticSpellChecker *spell) -{ - gtk_text_buffer_move_mark (buffer, spell->mark_insert_start, iter); -} - -static void -insert_text_after (GtkTextBuffer *buffer, - GtkTextIter *iter, - gchar *text, - gint len, - XedAutomaticSpellChecker *spell) -{ - GtkTextIter start; - - /* we need to check a range of text. */ - gtk_text_buffer_get_iter_at_mark (buffer, &start, spell->mark_insert_start); - - check_range (spell, start, *iter, FALSE); - - gtk_text_buffer_move_mark (buffer, spell->mark_insert_end, iter); -} - -/* deleting is more simple: we're given the range of deleted text. - * after deletion, the start and end iters should be at the same position - * (because all of the text between them was deleted!). - * this means we only really check the words immediately bounding the - * deletion. - */ - -static void -delete_range_after (GtkTextBuffer *buffer, - GtkTextIter *start, - GtkTextIter *end, - XedAutomaticSpellChecker *spell) -{ - check_range (spell, *start, *end, FALSE); -} - -static void -mark_set (GtkTextBuffer *buffer, - GtkTextIter *iter, - GtkTextMark *mark, - XedAutomaticSpellChecker *spell) -{ - /* if the cursor has moved and there is a deferred check so handle it now */ - if ((mark == gtk_text_buffer_get_insert (buffer)) && spell->deferred_check) - { - check_deferred_range (spell, FALSE); - } -} - -static void -get_word_extents_from_mark (GtkTextBuffer *buffer, - GtkTextIter *start, - GtkTextIter *end, - GtkTextMark *mark) -{ - gtk_text_buffer_get_iter_at_mark(buffer, start, mark); - - if (!gtk_text_iter_starts_word (start)) - { - gtk_text_iter_backward_word_start (start); - } - - *end = *start; - - if (gtk_text_iter_inside_word (end)) - { - gtk_text_iter_forward_word_end (end); - } -} - -static void -remove_tag_to_word (XedAutomaticSpellChecker *spell, - const gchar *word) -{ - GtkTextIter iter; - GtkTextIter match_start, match_end; - - gboolean found; - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (spell->doc), &iter, 0); - - found = TRUE; - - while (found) - { - found = gtk_text_iter_forward_search (&iter, - word, - GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY, - &match_start, - &match_end, - NULL); - - if (found) - { - if (gtk_text_iter_starts_word (&match_start) && gtk_text_iter_ends_word (&match_end)) - { - gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), - spell->tag_highlight, - &match_start, - &match_end); - } - - iter = match_end; - } - } -} - -static void -add_to_dictionary (GtkWidget *menuitem, - XedAutomaticSpellChecker *spell) -{ - gchar *word; - - GtkTextIter start, end; - - get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click); - - word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE); - - xed_spell_checker_add_word_to_personal (spell->spell_checker, word, -1); - - g_free (word); -} - -static void -ignore_all (GtkWidget *menuitem, - XedAutomaticSpellChecker *spell) -{ - gchar *word; - - GtkTextIter start, end; - - get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click); - - word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE); - - xed_spell_checker_add_word_to_session (spell->spell_checker, word, -1); - - g_free (word); -} - -static void -replace_word (GtkWidget *menuitem, - XedAutomaticSpellChecker *spell) -{ - gchar *oldword; - const gchar *newword; - - GtkTextIter start, end; - - get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click); - - oldword = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE); - - newword = g_object_get_qdata (G_OBJECT (menuitem), suggestion_id); - g_return_if_fail (newword != NULL); - - gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (spell->doc)); - - gtk_text_buffer_delete (GTK_TEXT_BUFFER (spell->doc), &start, &end); - gtk_text_buffer_insert (GTK_TEXT_BUFFER (spell->doc), &start, newword, -1); - - gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (spell->doc)); - - xed_spell_checker_set_correction (spell->spell_checker, - oldword, strlen (oldword), - newword, strlen (newword)); - - g_free (oldword); -} - -static GtkWidget * -build_suggestion_menu (XedAutomaticSpellChecker *spell, - const gchar *word) -{ - GtkWidget *topmenu, *menu; - GtkWidget *mi; - GSList *suggestions; - GSList *list; - gchar *label_text; - - topmenu = menu = gtk_menu_new(); - - suggestions = xed_spell_checker_get_suggestions (spell->spell_checker, word, -1); - - list = suggestions; - - if (suggestions == NULL) - { - /* no suggestions. put something in the menu anyway... */ - GtkWidget *label; - /* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions for the current misspelled word */ - label = gtk_label_new (_("(no suggested words)")); - - mi = gtk_menu_item_new (); - gtk_widget_set_sensitive (mi, FALSE); - gtk_container_add (GTK_CONTAINER(mi), label); - gtk_widget_show_all (mi); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); - } - else - { - gint count = 0; - - /* build a set of menus with suggestions. */ - while (suggestions != NULL) - { - GtkWidget *label; - - if (count == 10) - { - /* Separator */ - mi = gtk_menu_item_new (); - gtk_widget_show (mi); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - - mi = gtk_menu_item_new_with_mnemonic (_("_More...")); - gtk_widget_show (mi); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - - menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu); - count = 0; - } - - label_text = g_strdup_printf ("%s", (gchar*) suggestions->data); - - label = gtk_label_new (label_text); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - gtk_widget_set_halign (label, GTK_ALIGN_START); - - mi = gtk_menu_item_new (); - gtk_container_add (GTK_CONTAINER (mi), label); - - gtk_widget_show_all (mi); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - - g_object_set_qdata_full (G_OBJECT (mi), - suggestion_id, - g_strdup (suggestions->data), - (GDestroyNotify)g_free); - - g_free (label_text); - g_signal_connect (mi, "activate", - G_CALLBACK (replace_word), spell); - - count++; - - suggestions = g_slist_next (suggestions); - } - } - - /* free the suggestion list */ - suggestions = list; - - while (list) - { - g_free (list->data); - list = g_slist_next (list); - } - - g_slist_free (suggestions); - - /* Separator */ - mi = gtk_menu_item_new (); - gtk_widget_show (mi); - gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi); - - /* Ignore all */ - mi = gtk_menu_item_new_with_mnemonic (_("_Ignore All")); - - g_signal_connect (mi, "activate", - G_CALLBACK(ignore_all), spell); - - gtk_widget_show_all (mi); - - gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi); - - /* + Add to Dictionary */ - mi = gtk_menu_item_new_with_mnemonic (_("_Add")); - - g_signal_connect (mi, "activate", - G_CALLBACK (add_to_dictionary), spell); - - gtk_widget_show_all (mi); - - gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi); - - return topmenu; -} - -static void -populate_popup (GtkTextView *textview, - GtkMenu *menu, - XedAutomaticSpellChecker *spell) -{ - GtkWidget *mi; - GtkTextIter start, end; - char *word; - - /* we need to figure out if they picked a misspelled word. */ - get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click); - - /* if our highlight algorithm ever messes up, - * this isn't correct, either. */ - if (!gtk_text_iter_has_tag (&start, spell->tag_highlight)) - { - return; /* word wasn't misspelled. */ - } - - /* menu separator comes first. */ - mi = gtk_menu_item_new (); - gtk_widget_show (mi); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); - - /* then, on top of it, the suggestions menu. */ - mi = gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions...")); - - word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), build_suggestion_menu (spell, word)); - g_free(word); - - gtk_widget_show_all (mi); - gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); -} - -void -xed_automatic_spell_checker_recheck_all (XedAutomaticSpellChecker *spell) -{ - GtkTextIter start, end; - - g_return_if_fail (spell != NULL); - - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end); - - check_range (spell, start, end, TRUE); -} - -static void -add_word_signal_cb (XedSpellChecker *checker, - const gchar *word, - gint len, - XedAutomaticSpellChecker *spell) -{ - gchar *w; - - if (len < 0) - { - w = g_strdup (word); - } - else - { - w = g_strndup (word, len); - } - - remove_tag_to_word (spell, w); - - g_free (w); -} - -static void -set_language_cb (XedSpellChecker *checker, - const XedSpellCheckerLanguage *lang, - XedAutomaticSpellChecker *spell) -{ - xed_automatic_spell_checker_recheck_all (spell); -} - -static void -clear_session_cb (XedSpellChecker *checker, - XedAutomaticSpellChecker *spell) -{ - xed_automatic_spell_checker_recheck_all (spell); -} - -/* When the user right-clicks on a word, they want to check that word. - * Here, we do NOT move the cursor to the location of the clicked-upon word - * since that prevents the use of edit functions on the context menu. - */ -static gboolean -button_press_event (GtkTextView *view, - GdkEventButton *event, - XedAutomaticSpellChecker *spell) -{ - if (event->button == 3) - { - gint x, y; - GtkTextIter iter; - - GtkTextBuffer *buffer = gtk_text_view_get_buffer (view); - - /* handle deferred check if it exists */ - if (spell->deferred_check) - { - check_deferred_range (spell, TRUE); - } - - gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_TEXT, event->x, event->y, &x, &y); - - gtk_text_view_get_iter_at_location (view, &iter, x, y); - - gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter); - } - - return FALSE; /* false: let gtk process this event, too. - we don't want to eat any events. */ -} - -/* Move the insert mark before popping up the menu, otherwise it - * will contain the wrong set of suggestions. - */ -static gboolean -popup_menu_event (GtkTextView *view, - XedAutomaticSpellChecker *spell) -{ - GtkTextIter iter; - GtkTextBuffer *buffer; - - buffer = gtk_text_view_get_buffer (view); - - /* handle deferred check if it exists */ - if (spell->deferred_check) - { - check_deferred_range (spell, TRUE); - } - - gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer)); - gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter); - - return FALSE; -} - -static void -tag_table_changed (GtkTextTagTable *table, - XedAutomaticSpellChecker *spell) -{ - g_return_if_fail (spell->tag_highlight != NULL); - - gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (table) - 1); -} - -static void -tag_added_or_removed (GtkTextTagTable *table, - GtkTextTag *tag, - XedAutomaticSpellChecker *spell) -{ - tag_table_changed (table, spell); -} - -static void -tag_changed (GtkTextTagTable *table, - GtkTextTag *tag, - gboolean size_changed, - XedAutomaticSpellChecker *spell) -{ - tag_table_changed (table, spell); -} - -static void -highlight_updated (GtkSourceBuffer *buffer, - GtkTextIter *start, - GtkTextIter *end, - XedAutomaticSpellChecker *spell) -{ - check_range (spell, *start, *end, FALSE); -} - -static void -spell_tag_destroyed (XedAutomaticSpellChecker *spell, - GObject *where_the_object_was) -{ - spell->tag_highlight = NULL; -} - -XedAutomaticSpellChecker * -xed_automatic_spell_checker_new (XedDocument *doc, - XedSpellChecker *checker) -{ - XedAutomaticSpellChecker *spell; - GtkTextTagTable *tag_table; - GtkTextIter start, end; - - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - g_return_val_if_fail (XED_IS_SPELL_CHECKER (checker), NULL); - g_return_val_if_fail ((spell = xed_automatic_spell_checker_get_from_document (doc)) == NULL, spell); - - /* attach to the widget */ - spell = g_new0 (XedAutomaticSpellChecker, 1); - - spell->doc = doc; - spell->spell_checker = g_object_ref (checker); - - if (automatic_spell_checker_id == 0) - { - automatic_spell_checker_id = g_quark_from_string ("XedAutomaticSpellCheckerID"); - } - if (suggestion_id == 0) - { - suggestion_id = g_quark_from_string ("XedAutoSuggestionID"); - } - - g_object_set_qdata_full (G_OBJECT (doc), automatic_spell_checker_id, - spell, (GDestroyNotify)xed_automatic_spell_checker_free_internal); - - g_signal_connect (doc, "insert-text", - G_CALLBACK (insert_text_before), spell); - g_signal_connect_after (doc, "insert-text", - G_CALLBACK (insert_text_after), spell); - g_signal_connect_after (doc, "delete-range", - G_CALLBACK (delete_range_after), spell); - g_signal_connect (doc, "mark-set", - G_CALLBACK (mark_set), spell); - - g_signal_connect (doc, "highlight-updated", - G_CALLBACK (highlight_updated), spell); - - g_signal_connect (spell->spell_checker, "add_word_to_session", - G_CALLBACK (add_word_signal_cb), spell); - g_signal_connect (spell->spell_checker, "add_word_to_personal", - G_CALLBACK (add_word_signal_cb), spell); - g_signal_connect (spell->spell_checker, "clear_session", - G_CALLBACK (clear_session_cb), spell); - g_signal_connect (spell->spell_checker, "set_language", - G_CALLBACK (set_language_cb), spell); - - spell->tag_highlight = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (doc), - "gtkspell-misspelled", - "underline", PANGO_UNDERLINE_ERROR, - NULL); - - g_object_weak_ref (G_OBJECT (spell->tag_highlight), (GWeakNotify)spell_tag_destroyed, spell); - - tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (doc)); - - gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (tag_table) - 1); - - g_signal_connect (tag_table, "tag-added", - G_CALLBACK (tag_added_or_removed), spell); - g_signal_connect (tag_table, "tag-removed", - G_CALLBACK (tag_added_or_removed), spell); - g_signal_connect (tag_table, "tag-changed", - G_CALLBACK (tag_changed), spell); - - /* we create the mark here, but we don't use it until text is - * inserted, so we don't really care where iter points. */ - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), &start, &end); - - spell->mark_insert_start = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-insert-start"); - - if (spell->mark_insert_start == NULL) - { - spell->mark_insert_start = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-insert-start", - &start, - TRUE); - } - else - { - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_start, &start); - } - - spell->mark_insert_end = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-insert-end"); - - if (spell->mark_insert_end == NULL) - { - spell->mark_insert_end = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-insert-end", - &start, - TRUE); - } - else - { - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_end, &start); - } - - spell->mark_click = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-click"); - - if (spell->mark_click == NULL) - { - spell->mark_click = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "xed-automatic-spell-checker-click", - &start, - TRUE); - } - else - { - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_click, &start); - } - - spell->deferred_check = FALSE; - - return spell; -} - -XedAutomaticSpellChecker * -xed_automatic_spell_checker_get_from_document (const XedDocument *doc) -{ - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - - if (automatic_spell_checker_id == 0) - { - return NULL; - } - - return g_object_get_qdata (G_OBJECT (doc), automatic_spell_checker_id); -} - -void -xed_automatic_spell_checker_free (XedAutomaticSpellChecker *spell) -{ - g_return_if_fail (spell != NULL); - g_return_if_fail (xed_automatic_spell_checker_get_from_document (spell->doc) == spell); - - if (automatic_spell_checker_id == 0) - { - return; - } - - g_object_set_qdata (G_OBJECT (spell->doc), automatic_spell_checker_id, NULL); -} - -static void -xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell) -{ - GtkTextTagTable *table; - GtkTextIter start, end; - GSList *list; - - g_return_if_fail (spell != NULL); - - table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (spell->doc)); - - if (table != NULL && spell->tag_highlight != NULL) - { - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end); - gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end); - - g_signal_handlers_disconnect_matched (G_OBJECT (table), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - gtk_text_tag_table_remove (table, spell->tag_highlight); - } - - g_signal_handlers_disconnect_matched (G_OBJECT (spell->doc), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - g_signal_handlers_disconnect_matched (G_OBJECT (spell->spell_checker), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - g_object_unref (spell->spell_checker); - - list = spell->views; - while (list != NULL) - { - XedView *view = XED_VIEW (list->data); - - g_signal_handlers_disconnect_matched (G_OBJECT (view), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - g_signal_handlers_disconnect_matched (G_OBJECT (view), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - list = g_slist_next (list); - } - - g_slist_free (spell->views); - - g_free (spell); -} - -void -xed_automatic_spell_checker_attach_view (XedAutomaticSpellChecker *spell, - XedView *view) -{ - g_return_if_fail (spell != NULL); - g_return_if_fail (XED_IS_VIEW (view)); - - g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc)); - - g_signal_connect (view, "button-press-event", - G_CALLBACK (button_press_event), spell); - g_signal_connect (view, "popup-menu", - G_CALLBACK (popup_menu_event), spell); - g_signal_connect (view, "populate-popup", - G_CALLBACK (populate_popup), spell); - g_signal_connect (view, "destroy", - G_CALLBACK (view_destroy), spell); - - spell->views = g_slist_prepend (spell->views, view); -} - -void -xed_automatic_spell_checker_detach_view (XedAutomaticSpellChecker *spell, - XedView *view) -{ - g_return_if_fail (spell != NULL); - g_return_if_fail (XED_IS_VIEW (view)); - - g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc)); - g_return_if_fail (spell->views != NULL); - - g_signal_handlers_disconnect_matched (G_OBJECT (view), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - g_signal_handlers_disconnect_matched (G_OBJECT (view), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - spell); - - spell->views = g_slist_remove (spell->views, view); -} - diff --git a/plugins/spell/xed-automatic-spell-checker.h b/plugins/spell/xed-automatic-spell-checker.h deleted file mode 100644 index b057a52..0000000 --- a/plugins/spell/xed-automatic-spell-checker.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-automatic-spell-checker.h - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -/* This is a modified version of gtkspell 2.0.2 (gtkspell.sf.net) */ -/* gtkspell - a spell-checking addon for GTK's TextView widget - * Copyright (c) 2002 Evan Martin. - */ - -#ifndef __XED_AUTOMATIC_SPELL_CHECKER_H__ -#define __XED_AUTOMATIC_SPELL_CHECKER_H__ - -#include -#include - -#include "xed-spell-checker.h" - -typedef struct _XedAutomaticSpellChecker XedAutomaticSpellChecker; - -XedAutomaticSpellChecker *xed_automatic_spell_checker_new ( - XedDocument *doc, - XedSpellChecker *checker); - -XedAutomaticSpellChecker *xed_automatic_spell_checker_get_from_document ( - const XedDocument *doc); - -void xed_automatic_spell_checker_free ( - XedAutomaticSpellChecker *spell); - -void xed_automatic_spell_checker_attach_view ( - XedAutomaticSpellChecker *spell, - XedView *view); - -void xed_automatic_spell_checker_detach_view ( - XedAutomaticSpellChecker *spell, - XedView *view); - -void xed_automatic_spell_checker_recheck_all ( - XedAutomaticSpellChecker *spell); - -#endif /* __XED_AUTOMATIC_SPELL_CHECKER_H__ */ - diff --git a/plugins/spell/xed-spell-checker-dialog.c b/plugins/spell/xed-spell-checker-dialog.c deleted file mode 100644 index 3fee5b7..0000000 --- a/plugins/spell/xed-spell-checker-dialog.c +++ /dev/null @@ -1,726 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker-dialog.c - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "xed-spell-checker-dialog.h" -#include "xed-spell-marshal.h" - -struct _XedSpellCheckerDialog -{ - GtkWindow parent_instance; - - XedSpellChecker *spell_checker; - - gchar *misspelled_word; - - GtkWidget *misspelled_word_label; - GtkWidget *word_entry; - GtkWidget *check_word_button; - GtkWidget *ignore_button; - GtkWidget *ignore_all_button; - GtkWidget *change_button; - GtkWidget *change_all_button; - GtkWidget *add_word_button; - GtkWidget *close_button; - GtkWidget *suggestions_list; - GtkWidget *language_label; - - GtkTreeModel *suggestions_list_model; -}; - -enum -{ - IGNORE, - IGNORE_ALL, - CHANGE, - CHANGE_ALL, - ADD_WORD_TO_PERSONAL, - LAST_SIGNAL -}; - -enum -{ - COLUMN_SUGGESTIONS, - NUM_COLUMNS -}; - -static void update_suggestions_list_model (XedSpellCheckerDialog *dlg, - GSList *suggestions); - -static void word_entry_changed_handler (GtkEditable *editable, - XedSpellCheckerDialog *dlg); -static void close_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void suggestions_list_selection_changed_handler (GtkTreeSelection *selection, - XedSpellCheckerDialog *dlg); -static void check_word_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void add_word_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void ignore_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void ignore_all_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void change_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void change_all_button_clicked_handler (GtkButton *button, - XedSpellCheckerDialog *dlg); -static void suggestions_list_row_activated_handler (GtkTreeView *view, - GtkTreePath *path, - GtkTreeViewColumn *column, - XedSpellCheckerDialog *dlg); - - -static guint signals [LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE(XedSpellCheckerDialog, xed_spell_checker_dialog, GTK_TYPE_WINDOW) - -static void -xed_spell_checker_dialog_dispose (GObject *object) -{ - XedSpellCheckerDialog *dlg = XED_SPELL_CHECKER_DIALOG (object); - - if (dlg->spell_checker != NULL) - { - g_object_unref (dlg->spell_checker); - dlg->spell_checker = NULL; - } - - if (dlg->misspelled_word != NULL) - { - g_free (dlg->misspelled_word); - dlg->misspelled_word = NULL; - } - - G_OBJECT_CLASS (xed_spell_checker_dialog_parent_class)->dispose (object); -} - -static void -xed_spell_checker_dialog_class_init (XedSpellCheckerDialogClass * klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = xed_spell_checker_dialog_dispose; - - signals[IGNORE] = - g_signal_new ("ignore", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore), - NULL, NULL, - xed_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); - - signals[IGNORE_ALL] = - g_signal_new ("ignore_all", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore_all), - NULL, NULL, - xed_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); - - signals[CHANGE] = - g_signal_new ("change", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change), - NULL, NULL, - xed_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - signals[CHANGE_ALL] = - g_signal_new ("change_all", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change_all), - NULL, NULL, - xed_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - signals[ADD_WORD_TO_PERSONAL] = - g_signal_new ("add_word_to_personal", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerDialogClass, add_word_to_personal), - NULL, NULL, - xed_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); -} - -static void -create_dialog (XedSpellCheckerDialog *dlg, - const gchar *data_dir) -{ - GtkWidget *error_widget; - GtkWidget *content; - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - GtkTreeSelection *selection; - gchar *root_objects[] = { - "content", - "check_word_image", - "add_word_image", - "ignore_image", - "change_image", - "ignore_all_image", - "change_all_image", - NULL - }; - gboolean ret; - gchar *ui_file; - - g_return_if_fail (dlg != NULL); - - dlg->spell_checker = NULL; - dlg->misspelled_word = NULL; - - ui_file = g_build_filename (data_dir, "spell-checker.ui", NULL); - ret = xed_utils_get_ui_objects (ui_file, - root_objects, - &error_widget, - - "content", &content, - "misspelled_word_label", &dlg->misspelled_word_label, - "word_entry", &dlg->word_entry, - "check_word_button", &dlg->check_word_button, - "ignore_button", &dlg->ignore_button, - "ignore_all_button", &dlg->ignore_all_button, - "change_button", &dlg->change_button, - "change_all_button", &dlg->change_all_button, - "add_word_button", &dlg->add_word_button, - "close_button", &dlg->close_button, - "suggestions_list", &dlg->suggestions_list, - "language_label", &dlg->language_label, - NULL); - g_free (ui_file); - - if (!ret) - { - gtk_widget_show (error_widget); - - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), - error_widget, TRUE, TRUE, 0); - - return; - } - - gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), ""); - gtk_widget_set_sensitive (dlg->word_entry, FALSE); - gtk_widget_set_sensitive (dlg->check_word_button, FALSE); - gtk_widget_set_sensitive (dlg->ignore_button, FALSE); - gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE); - gtk_widget_set_sensitive (dlg->change_button, FALSE); - gtk_widget_set_sensitive (dlg->change_all_button, FALSE); - gtk_widget_set_sensitive (dlg->add_word_button, FALSE); - - gtk_label_set_label (GTK_LABEL (dlg->language_label), ""); - - gtk_container_add (GTK_CONTAINER (dlg), content); - g_object_unref (content); - - gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE); - gtk_window_set_title (GTK_WINDOW (dlg), _("Check Spelling")); - - /* Suggestion list */ - dlg->suggestions_list_model = GTK_TREE_MODEL ( - gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING)); - - gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->suggestions_list), - dlg->suggestions_list_model); - - /* Add the suggestions column */ - cell = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Suggestions"), cell, - "text", COLUMN_SUGGESTIONS, NULL); - - gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->suggestions_list), column); - - gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->suggestions_list), - COLUMN_SUGGESTIONS); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list)); - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - /* Set default button */ - gtk_widget_set_can_default (dlg->change_button, TRUE); - gtk_widget_grab_default (dlg->change_button); - - gtk_entry_set_activates_default (GTK_ENTRY (dlg->word_entry), TRUE); - - /* Connect signals */ - g_signal_connect (dlg->word_entry, "changed", - G_CALLBACK (word_entry_changed_handler), dlg); - g_signal_connect (dlg->close_button, "clicked", - G_CALLBACK (close_button_clicked_handler), dlg); - g_signal_connect (selection, "changed", - G_CALLBACK (suggestions_list_selection_changed_handler), - dlg); - g_signal_connect (dlg->check_word_button, "clicked", - G_CALLBACK (check_word_button_clicked_handler), dlg); - g_signal_connect (dlg->add_word_button, "clicked", - G_CALLBACK (add_word_button_clicked_handler), dlg); - g_signal_connect (dlg->ignore_button, "clicked", - G_CALLBACK (ignore_button_clicked_handler), dlg); - g_signal_connect (dlg->ignore_all_button, "clicked", - G_CALLBACK (ignore_all_button_clicked_handler), dlg); - g_signal_connect (dlg->change_button, "clicked", - G_CALLBACK (change_button_clicked_handler), dlg); - g_signal_connect (dlg->change_all_button, "clicked", - G_CALLBACK (change_all_button_clicked_handler), dlg); - g_signal_connect (dlg->suggestions_list, "row-activated", - G_CALLBACK (suggestions_list_row_activated_handler), dlg); -} - -static void -xed_spell_checker_dialog_init (XedSpellCheckerDialog *dlg) -{ -} - -GtkWidget * -xed_spell_checker_dialog_new (const gchar *data_dir) -{ - XedSpellCheckerDialog *dlg; - - dlg = XED_SPELL_CHECKER_DIALOG ( - g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL)); - - g_return_val_if_fail (dlg != NULL, NULL); - - create_dialog (dlg, data_dir); - - return GTK_WIDGET (dlg); -} - -GtkWidget * -xed_spell_checker_dialog_new_from_spell_checker (XedSpellChecker *spell, - const gchar *data_dir) -{ - XedSpellCheckerDialog *dlg; - - g_return_val_if_fail (spell != NULL, NULL); - - dlg = XED_SPELL_CHECKER_DIALOG ( - g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL)); - - g_return_val_if_fail (dlg != NULL, NULL); - - create_dialog (dlg, data_dir); - - xed_spell_checker_dialog_set_spell_checker (dlg, spell); - - return GTK_WIDGET (dlg); -} - -void -xed_spell_checker_dialog_set_spell_checker (XedSpellCheckerDialog *dlg, XedSpellChecker *spell) -{ - const XedSpellCheckerLanguage* language; - const gchar *lang; - gchar *tmp; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (spell != NULL); - - if (dlg->spell_checker != NULL) - g_object_unref (dlg->spell_checker); - - dlg->spell_checker = spell; - g_object_ref (dlg->spell_checker); - - language = xed_spell_checker_get_language (dlg->spell_checker); - - lang = xed_spell_checker_language_to_string (language); - tmp = g_strdup_printf("%s", lang); - - gtk_label_set_label (GTK_LABEL (dlg->language_label), tmp); - g_free (tmp); - - if (dlg->misspelled_word != NULL) - xed_spell_checker_dialog_set_misspelled_word (dlg, dlg->misspelled_word, -1); - else - gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model)); - - /* TODO: reset all widgets */ -} - -void -xed_spell_checker_dialog_set_misspelled_word (XedSpellCheckerDialog *dlg, - const gchar *word, - gint len) -{ - gchar *tmp; - GSList *sug; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (word != NULL); - - g_return_if_fail (dlg->spell_checker != NULL); - g_return_if_fail (!xed_spell_checker_check_word (dlg->spell_checker, word, -1)); - - /* build_suggestions_list */ - if (dlg->misspelled_word != NULL) - g_free (dlg->misspelled_word); - - dlg->misspelled_word = g_strdup (word); - - tmp = g_strdup_printf("%s", word); - gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), tmp); - g_free (tmp); - - sug = xed_spell_checker_get_suggestions (dlg->spell_checker, - dlg->misspelled_word, - -1); - - update_suggestions_list_model (dlg, sug); - - /* free the suggestion list */ - g_slist_foreach (sug, (GFunc)g_free, NULL); - g_slist_free (sug); - - gtk_widget_set_sensitive (dlg->ignore_button, TRUE); - gtk_widget_set_sensitive (dlg->ignore_all_button, TRUE); - gtk_widget_set_sensitive (dlg->add_word_button, TRUE); -} - -static void -update_suggestions_list_model (XedSpellCheckerDialog *dlg, GSList *suggestions) -{ - GtkListStore *store; - GtkTreeIter iter; - GtkTreeSelection *sel; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (GTK_IS_LIST_STORE (dlg->suggestions_list_model)); - - store = GTK_LIST_STORE (dlg->suggestions_list_model); - gtk_list_store_clear (store); - - gtk_widget_set_sensitive (dlg->word_entry, TRUE); - - if (suggestions == NULL) - { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - /* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions - * for the current misspelled word */ - COLUMN_SUGGESTIONS, _("(no suggested words)"), - -1); - - gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), ""); - - gtk_widget_set_sensitive (dlg->suggestions_list, FALSE); - - return; - } - - gtk_widget_set_sensitive (dlg->suggestions_list, TRUE); - - gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), (gchar*)suggestions->data); - - while (suggestions != NULL) - { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - COLUMN_SUGGESTIONS, (gchar*)suggestions->data, - -1); - - suggestions = g_slist_next (suggestions); - } - - sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list)); - gtk_tree_model_get_iter_first (dlg->suggestions_list_model, &iter); - gtk_tree_selection_select_iter (sel, &iter); -} - -static void -word_entry_changed_handler (GtkEditable *editable, XedSpellCheckerDialog *dlg) -{ - const gchar *text; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)); - - if (g_utf8_strlen (text, -1) > 0) - { - gtk_widget_set_sensitive (dlg->check_word_button, TRUE); - gtk_widget_set_sensitive (dlg->change_button, TRUE); - gtk_widget_set_sensitive (dlg->change_all_button, TRUE); - } - else - { - gtk_widget_set_sensitive (dlg->check_word_button, FALSE); - gtk_widget_set_sensitive (dlg->change_button, FALSE); - gtk_widget_set_sensitive (dlg->change_all_button, FALSE); - } -} - -static void -close_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - gtk_widget_destroy (GTK_WIDGET (dlg)); -} - -static void -suggestions_list_selection_changed_handler (GtkTreeSelection *selection, - XedSpellCheckerDialog *dlg) -{ - GtkTreeIter iter; - GValue value = {0, }; - const gchar *text; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - if (! gtk_tree_selection_get_selected (selection, NULL, &iter)) - return; - - gtk_tree_model_get_value (dlg->suggestions_list_model, &iter, - COLUMN_SUGGESTIONS, - &value); - - text = g_value_get_string (&value); - - gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), text); - - g_value_unset (&value); -} - -static void -check_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - const gchar *word; - gssize len; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - word = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)); - len = strlen (word); - g_return_if_fail (len > 0); - - if (xed_spell_checker_check_word (dlg->spell_checker, word, len)) - { - GtkListStore *store; - GtkTreeIter iter; - - store = GTK_LIST_STORE (dlg->suggestions_list_model); - gtk_list_store_clear (store); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - /* Translators: Displayed in the "Check Spelling" dialog if the current word isn't misspelled */ - COLUMN_SUGGESTIONS, _("(correct spelling)"), - -1); - - gtk_widget_set_sensitive (dlg->suggestions_list, FALSE); - } - else - { - GSList *sug; - - sug = xed_spell_checker_get_suggestions (dlg->spell_checker, - word, - len); - - update_suggestions_list_model (dlg, sug); - - /* free the suggestion list */ - g_slist_foreach (sug, (GFunc)g_free, NULL); - g_slist_free (sug); - } -} - -static void -add_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - gchar *word; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (dlg->misspelled_word != NULL); - - xed_spell_checker_add_word_to_personal (dlg->spell_checker, - dlg->misspelled_word, - -1); - - word = g_strdup (dlg->misspelled_word); - - g_signal_emit (G_OBJECT (dlg), signals [ADD_WORD_TO_PERSONAL], 0, word); - - g_free (word); -} - -static void -ignore_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - gchar *word; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (dlg->misspelled_word != NULL); - - word = g_strdup (dlg->misspelled_word); - - g_signal_emit (G_OBJECT (dlg), signals [IGNORE], 0, word); - - g_free (word); -} - -static void -ignore_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - gchar *word; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (dlg->misspelled_word != NULL); - - xed_spell_checker_add_word_to_session (dlg->spell_checker, - dlg->misspelled_word, - -1); - - word = g_strdup (dlg->misspelled_word); - - g_signal_emit (G_OBJECT (dlg), signals [IGNORE_ALL], 0, word); - - g_free (word); -} - -static void -change_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - const gchar *entry_text; - gchar *change; - gchar *word; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (dlg->misspelled_word != NULL); - - entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)); - g_return_if_fail (entry_text != NULL); - g_return_if_fail (*entry_text != '\0'); - change = g_strdup (entry_text); - - xed_spell_checker_set_correction (dlg->spell_checker, - dlg->misspelled_word, -1, - change, -1); - - word = g_strdup (dlg->misspelled_word); - - g_signal_emit (G_OBJECT (dlg), signals [CHANGE], 0, word, change); - - g_free (word); - g_free (change); -} - -/* double click on one of the suggestions is like clicking on "change" */ -static void -suggestions_list_row_activated_handler (GtkTreeView *view, - GtkTreePath *path, - GtkTreeViewColumn *column, - XedSpellCheckerDialog *dlg) -{ - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - change_button_clicked_handler (GTK_BUTTON (dlg->change_button), dlg); -} - -static void -change_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg) -{ - const gchar *entry_text; - gchar *change; - gchar *word; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - g_return_if_fail (dlg->misspelled_word != NULL); - - entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)); - g_return_if_fail (entry_text != NULL); - g_return_if_fail (*entry_text != '\0'); - change = g_strdup (entry_text); - - xed_spell_checker_set_correction (dlg->spell_checker, - dlg->misspelled_word, -1, - change, -1); - - word = g_strdup (dlg->misspelled_word); - - g_signal_emit (G_OBJECT (dlg), signals [CHANGE_ALL], 0, word, change); - - g_free (word); - g_free (change); -} - -void -xed_spell_checker_dialog_set_completed (XedSpellCheckerDialog *dlg) -{ - gchar *tmp; - - g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg)); - - tmp = g_strdup_printf("%s", _("Completed spell checking")); - gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), - tmp); - g_free (tmp); - - gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model)); - gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), ""); - - gtk_widget_set_sensitive (dlg->word_entry, FALSE); - gtk_widget_set_sensitive (dlg->check_word_button, FALSE); - gtk_widget_set_sensitive (dlg->ignore_button, FALSE); - gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE); - gtk_widget_set_sensitive (dlg->change_button, FALSE); - gtk_widget_set_sensitive (dlg->change_all_button, FALSE); - gtk_widget_set_sensitive (dlg->add_word_button, FALSE); - gtk_widget_set_sensitive (dlg->suggestions_list, FALSE); -} - diff --git a/plugins/spell/xed-spell-checker-dialog.h b/plugins/spell/xed-spell-checker-dialog.h deleted file mode 100644 index ca5b9ef..0000000 --- a/plugins/spell/xed-spell-checker-dialog.h +++ /dev/null @@ -1,92 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker-dialog.h - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifndef __XED_SPELL_CHECKER_DIALOG_H__ -#define __XED_SPELL_CHECKER_DIALOG_H__ - -#include -#include "xed-spell-checker.h" - -G_BEGIN_DECLS - -#define XED_TYPE_SPELL_CHECKER_DIALOG (xed_spell_checker_dialog_get_type ()) -#define XED_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog)) -#define XED_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog)) -#define XED_IS_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER_DIALOG)) -#define XED_IS_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER_DIALOG)) -#define XED_SPELL_CHECKER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog)) - - -typedef struct _XedSpellCheckerDialog XedSpellCheckerDialog; - -typedef struct _XedSpellCheckerDialogClass XedSpellCheckerDialogClass; - -struct _XedSpellCheckerDialogClass -{ - GtkWindowClass parent_class; - - /* Signals */ - void (*ignore) (XedSpellCheckerDialog *dlg, - const gchar *word); - void (*ignore_all) (XedSpellCheckerDialog *dlg, - const gchar *word); - void (*change) (XedSpellCheckerDialog *dlg, - const gchar *word, - const gchar *change_to); - void (*change_all) (XedSpellCheckerDialog *dlg, - const gchar *word, - const gchar *change_to); - void (*add_word_to_personal) (XedSpellCheckerDialog *dlg, - const gchar *word); - -}; - -GType xed_spell_checker_dialog_get_type (void) G_GNUC_CONST; - -/* Constructors */ -GtkWidget *xed_spell_checker_dialog_new (const gchar *data_dir); -GtkWidget *xed_spell_checker_dialog_new_from_spell_checker - (XedSpellChecker *spell, - const gchar *data_dir); - -void xed_spell_checker_dialog_set_spell_checker - (XedSpellCheckerDialog *dlg, - XedSpellChecker *spell); -void xed_spell_checker_dialog_set_misspelled_word - (XedSpellCheckerDialog *dlg, - const gchar* word, - gint len); - -void xed_spell_checker_dialog_set_completed - (XedSpellCheckerDialog *dlg); - -G_END_DECLS - -#endif /* __XED_SPELL_CHECKER_DIALOG_H__ */ - diff --git a/plugins/spell/xed-spell-checker-language.c b/plugins/spell/xed-spell-checker-language.c deleted file mode 100644 index afaba78..0000000 --- a/plugins/spell/xed-spell-checker-language.c +++ /dev/null @@ -1,439 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker-language.c - * This file is part of xed - * - * Copyright (C) 2006 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2006. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -/* Part of the code taked from Epiphany. - * - * Copyright (C) 2003, 2004 Christian Persch - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include -#include - -#include "xed-spell-checker-language.h" - -#include - -#define ISO_639_DOMAIN "iso_639" -#define ISO_3166_DOMAIN "iso_3166" - -#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale" - -struct _XedSpellCheckerLanguage -{ - gchar *abrev; - gchar *name; -}; - -static gboolean available_languages_initialized = FALSE; -static GSList *available_languages = NULL; - -static GHashTable *iso_639_table = NULL; -static GHashTable *iso_3166_table = NULL; - -static void -bind_iso_domains (void) -{ - static gboolean bound = FALSE; - - if (bound == FALSE) - { - bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR); - bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8"); - - bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR); - bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8"); - - bound = TRUE; - } -} - -static void -read_iso_639_entry (xmlTextReaderPtr reader, - GHashTable *table) -{ - xmlChar *code, *name; - - code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code"); - name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name"); - - /* Get iso-639-2 code */ - if (code == NULL || code[0] == '\0') - { - xmlFree (code); - /* FIXME: use the 2T or 2B code? */ - code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code"); - } - - if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0') - { - g_hash_table_insert (table, code, name); - } - else - { - xmlFree (code); - xmlFree (name); - } -} - -static void -read_iso_3166_entry (xmlTextReaderPtr reader, - GHashTable *table) -{ - xmlChar *code, *name; - - code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code"); - name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name"); - - if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0') - { - char *lcode; - - lcode = g_ascii_strdown ((char *) code, -1); - xmlFree (code); - - /* g_print ("%s -> %s\n", lcode, name); */ - - g_hash_table_insert (table, lcode, name); - } - else - { - xmlFree (code); - xmlFree (name); - } -} - -typedef enum -{ - STATE_START, - STATE_STOP, - STATE_ENTRIES, -} ParserState; - -static void -load_iso_entries (int iso, - GFunc read_entry_func, - gpointer user_data) -{ - xmlTextReaderPtr reader; - ParserState state = STATE_START; - xmlChar iso_entries[32], iso_entry[32]; - char *filename; - int ret = -1; - - xed_debug_message (DEBUG_PLUGINS, "Loading ISO-%d codes", iso); - - filename = g_strdup_printf (ISO_CODES_PREFIX "/share/xml/iso-codes/iso_%d.xml", iso); - reader = xmlNewTextReaderFilename (filename); - if (reader == NULL) goto out; - - xmlStrPrintf (iso_entries, sizeof (iso_entries), (const xmlChar *)"iso_%d_entries", iso); - xmlStrPrintf (iso_entry, sizeof (iso_entry), (const xmlChar *)"iso_%d_entry", iso); - - ret = xmlTextReaderRead (reader); - - while (ret == 1) - { - const xmlChar *tag; - xmlReaderTypes type; - - tag = xmlTextReaderConstName (reader); - type = xmlTextReaderNodeType (reader); - - if (state == STATE_ENTRIES && - type == XML_READER_TYPE_ELEMENT && - xmlStrEqual (tag, iso_entry)) - { - read_entry_func (reader, user_data); - } - else if (state == STATE_START && - type == XML_READER_TYPE_ELEMENT && - xmlStrEqual (tag, iso_entries)) - { - state = STATE_ENTRIES; - } - else if (state == STATE_ENTRIES && - type == XML_READER_TYPE_END_ELEMENT && - xmlStrEqual (tag, iso_entries)) - { - state = STATE_STOP; - } - else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE || - type == XML_READER_TYPE_WHITESPACE || - type == XML_READER_TYPE_TEXT || - type == XML_READER_TYPE_COMMENT) - { - /* eat it */ - } - else - { - /* ignore it */ - } - - ret = xmlTextReaderRead (reader); - } - - xmlFreeTextReader (reader); - -out: - if (ret < 0 || state != STATE_STOP) - { - g_warning ("Failed to load ISO-%d codes from %s!\n", - iso, filename); - } - - g_free (filename); -} - -static GHashTable * -create_iso_639_table (void) -{ - GHashTable *table; - - bind_iso_domains (); - table = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) xmlFree, - (GDestroyNotify) xmlFree); - - load_iso_entries (639, (GFunc) read_iso_639_entry, table); - - return table; -} - -static GHashTable * -create_iso_3166_table (void) -{ - GHashTable *table; - - bind_iso_domains (); - table = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) xmlFree); - - load_iso_entries (3166, (GFunc) read_iso_3166_entry, table); - - return table; -} - -static char * -create_name_for_language (const char *code) -{ - char **str; - char *name = NULL; - const char *langname, *localename; - int len; - - g_return_val_if_fail (iso_639_table != NULL, NULL); - g_return_val_if_fail (iso_3166_table != NULL, NULL); - - str = g_strsplit (code, "_", -1); - len = g_strv_length (str); - g_return_val_if_fail (len != 0, NULL); - - langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]); - - if (len == 1 && langname != NULL) - { - name = g_strdup (dgettext (ISO_639_DOMAIN, langname)); - } - else if (len == 2 && langname != NULL) - { - gchar *locale_code = g_ascii_strdown (str[1], -1); - - localename = (const char *) g_hash_table_lookup (iso_3166_table, locale_code); - g_free (locale_code); - - if (localename != NULL) - { - /* Translators: the first %s is the language name, and - * the second %s is the locale name. Example: - * "French (France)" - */ - name = g_strdup_printf (C_("language", "%s (%s)"), - dgettext (ISO_639_DOMAIN, langname), - dgettext (ISO_3166_DOMAIN, localename)); - } - else - { - name = g_strdup_printf (C_("language", "%s (%s)"), - dgettext (ISO_639_DOMAIN, langname), str[1]); - } - } - else - { - /* Translators: this refers to an unknown language code - * (one which isn't in our built-in list). - */ - name = g_strdup_printf (C_("language", "Unknown (%s)"), code); - } - - g_strfreev (str); - - return name; -} - -static void -enumerate_dicts (const char * const lang_tag, - const char * const provider_name, - const char * const provider_desc, - const char * const provider_file, - void * user_data) -{ - gchar *lang_name; - - GTree *dicts = (GTree *)user_data; - - lang_name = create_name_for_language (lang_tag); - g_return_if_fail (lang_name != NULL); - - /* g_print ("%s - %s\n", lang_tag, lang_name); */ - - g_tree_replace (dicts, g_strdup (lang_tag), lang_name); -} - -static gint -key_cmp (gconstpointer a, gconstpointer b, gpointer user_data) -{ - return strcmp (a, b); -} - -static gint -lang_cmp (const XedSpellCheckerLanguage *a, - const XedSpellCheckerLanguage *b) -{ - return g_utf8_collate (a->name, b->name); -} - -static gboolean -build_langs_list (const gchar *key, - const gchar *value, - gpointer data) -{ - XedSpellCheckerLanguage *lang = g_new (XedSpellCheckerLanguage, 1); - - lang->abrev = g_strdup (key); - lang->name = g_strdup (value); - - available_languages = g_slist_insert_sorted (available_languages, - lang, - (GCompareFunc)lang_cmp); - - return FALSE; -} - -const GSList * -xed_spell_checker_get_available_languages (void) -{ - EnchantBroker *broker; - GTree *dicts; - - if (available_languages_initialized) - return available_languages; - - g_return_val_if_fail (available_languages == NULL, NULL); - - available_languages_initialized = TRUE; - - broker = enchant_broker_init (); - g_return_val_if_fail (broker != NULL, NULL); - - /* Use a GTree to efficiently remove duplicates while building the list */ - dicts = g_tree_new_full (key_cmp, - NULL, - (GDestroyNotify)g_free, - (GDestroyNotify)g_free); - - iso_639_table = create_iso_639_table (); - iso_3166_table = create_iso_3166_table (); - - enchant_broker_list_dicts (broker, enumerate_dicts, dicts); - - enchant_broker_free (broker); - - g_hash_table_destroy (iso_639_table); - g_hash_table_destroy (iso_3166_table); - - iso_639_table = NULL; - iso_3166_table = NULL; - - g_tree_foreach (dicts, (GTraverseFunc)build_langs_list, NULL); - - g_tree_destroy (dicts); - - return available_languages; -} - -const gchar * -xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang) -{ - if (lang == NULL) - /* Translators: this refers the Default language used by the - * spell checker - */ - return C_("language", "Default"); - - return lang->name; -} - -const gchar * -xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang) -{ - g_return_val_if_fail (lang != NULL, NULL); - - return lang->abrev; -} - -const XedSpellCheckerLanguage * -xed_spell_checker_language_from_key (const gchar *key) -{ - const GSList *langs; - - g_return_val_if_fail (key != NULL, NULL); - - langs = xed_spell_checker_get_available_languages (); - - while (langs != NULL) - { - const XedSpellCheckerLanguage *l = (const XedSpellCheckerLanguage *)langs->data; - - if (g_ascii_strcasecmp (key, l->abrev) == 0) - return l; - - langs = g_slist_next (langs); - } - - return NULL; -} diff --git a/plugins/spell/xed-spell-checker-language.h b/plugins/spell/xed-spell-checker-language.h deleted file mode 100644 index 1976eb8..0000000 --- a/plugins/spell/xed-spell-checker-language.h +++ /dev/null @@ -1,51 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker-language.h - * This file is part of xed - * - * Copyright (C) 2006 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2006. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifndef __XED_SPELL_CHECKER_LANGUAGE_H__ -#define __XED_SPELL_CHECKER_LANGUAGE_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _XedSpellCheckerLanguage XedSpellCheckerLanguage; - -const gchar *xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang); - -const gchar *xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang); - -const XedSpellCheckerLanguage *xed_spell_checker_language_from_key (const gchar *key); - -/* GSList contains "XedSpellCheckerLanguage*" items */ -const GSList *xed_spell_checker_get_available_languages - (void); - -G_END_DECLS - -#endif /* __XED_SPELL_CHECKER_LANGUAGE_H__ */ diff --git a/plugins/spell/xed-spell-checker.c b/plugins/spell/xed-spell-checker.c deleted file mode 100644 index 65d55fa..0000000 --- a/plugins/spell/xed-spell-checker.c +++ /dev/null @@ -1,564 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker.c - * This file is part of xed - * - * Copyright (C) 2002-2006 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002-2006. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include -#include - -#include "xed-spell-checker.h" -#include "xed-spell-utils.h" -#include "xed-spell-marshal.h" - -struct _XedSpellChecker -{ - GObject parent_instance; - - EnchantDict *dict; - EnchantBroker *broker; - const XedSpellCheckerLanguage *active_lang; -}; - -/* GObject properties */ -enum { - PROP_0 = 0, - PROP_LANGUAGE, - LAST_PROP -}; - -/* Signals */ -enum { - ADD_WORD_TO_PERSONAL = 0, - ADD_WORD_TO_SESSION, - SET_LANGUAGE, - CLEAR_SESSION, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE(XedSpellChecker, xed_spell_checker, G_TYPE_OBJECT) - -static void -xed_spell_checker_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - /* - XedSpellChecker *spell = XED_SPELL_CHECKER (object); - */ - - switch (prop_id) - { - case PROP_LANGUAGE: - /* TODO */ - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -xed_spell_checker_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - /* - XedSpellChecker *spell = XED_SPELL_CHECKER (object); - */ - - switch (prop_id) - { - case PROP_LANGUAGE: - /* TODO */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -xed_spell_checker_finalize (GObject *object) -{ - XedSpellChecker *spell_checker; - - g_return_if_fail (XED_IS_SPELL_CHECKER (object)); - - spell_checker = XED_SPELL_CHECKER (object); - - if (spell_checker->dict != NULL) - { - enchant_broker_free_dict (spell_checker->broker, spell_checker->dict); - } - - if (spell_checker->broker != NULL) - { - enchant_broker_free (spell_checker->broker); - } - - G_OBJECT_CLASS (xed_spell_checker_parent_class)->finalize (object); -} - -static void -xed_spell_checker_class_init (XedSpellCheckerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = xed_spell_checker_set_property; - object_class->get_property = xed_spell_checker_get_property; - - object_class->finalize = xed_spell_checker_finalize; - - g_object_class_install_property (object_class, - PROP_LANGUAGE, - g_param_spec_pointer ("language", - "Language", - "The language used by the spell checker", - G_PARAM_READWRITE)); - - signals[ADD_WORD_TO_PERSONAL] = - g_signal_new ("add_word_to_personal", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_personal), - NULL, NULL, - xed_marshal_VOID__STRING_INT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_INT); - - signals[ADD_WORD_TO_SESSION] = - g_signal_new ("add_word_to_session", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_session), - NULL, NULL, - xed_marshal_VOID__STRING_INT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_INT); - - signals[SET_LANGUAGE] = - g_signal_new ("set_language", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, set_language), - NULL, NULL, - xed_marshal_VOID__POINTER, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - - signals[CLEAR_SESSION] = - g_signal_new ("clear_session", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (XedSpellCheckerClass, clear_session), - NULL, NULL, - xed_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -} - -static void -xed_spell_checker_init (XedSpellChecker *spell_checker) -{ - spell_checker->broker = enchant_broker_init (); - spell_checker->dict = NULL; - spell_checker->active_lang = NULL; -} - -XedSpellChecker * -xed_spell_checker_new (void) -{ - XedSpellChecker *spell; - - spell = XED_SPELL_CHECKER (g_object_new (XED_TYPE_SPELL_CHECKER, NULL)); - - g_return_val_if_fail (spell != NULL, NULL); - - return spell; -} - -static gboolean -lazy_init (XedSpellChecker *spell, - const XedSpellCheckerLanguage *language) -{ - if (spell->dict != NULL) - { - return TRUE; - } - - g_return_val_if_fail (spell->broker != NULL, FALSE); - - spell->active_lang = NULL; - - if (language != NULL) - { - spell->active_lang = language; - } - else - { - /* First try to get a default language */ - const XedSpellCheckerLanguage *l; - gint i = 0; - const gchar * const *lang_tags = g_get_language_names (); - - while (lang_tags [i]) - { - l = xed_spell_checker_language_from_key (lang_tags [i]); - - if (l != NULL) - { - spell->active_lang = l; - break; - } - - i++; - } - } - - /* Second try to get a default language */ - if (spell->active_lang == NULL) - { - spell->active_lang = xed_spell_checker_language_from_key ("en_US"); - } - - /* Last try to get a default language */ - if (spell->active_lang == NULL) - { - const GSList *langs; - langs = xed_spell_checker_get_available_languages (); - if (langs != NULL) - { - spell->active_lang = (const XedSpellCheckerLanguage *)langs->data; - } - } - - if (spell->active_lang != NULL) - { - const gchar *key; - - key = xed_spell_checker_language_to_key (spell->active_lang); - - spell->dict = enchant_broker_request_dict (spell->broker, key); - } - - if (spell->dict == NULL) - { - spell->active_lang = NULL; - - if (language != NULL) - { - g_warning ("Spell checker plugin: cannot select a default language."); - } - - return FALSE; - } - - return TRUE; -} - -gboolean -xed_spell_checker_set_language (XedSpellChecker *spell, - const XedSpellCheckerLanguage *language) -{ - gboolean ret; - - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - - if (spell->dict != NULL) - { - enchant_broker_free_dict (spell->broker, spell->dict); - spell->dict = NULL; - } - - ret = lazy_init (spell, language); - - if (ret) - { - g_signal_emit (G_OBJECT (spell), signals[SET_LANGUAGE], 0, language); - } - else - { - g_warning ("Spell checker plugin: cannot use language %s.", xed_spell_checker_language_to_string (language)); - } - - return ret; -} - -const XedSpellCheckerLanguage * -xed_spell_checker_get_language (XedSpellChecker *spell) -{ - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); - - if (!lazy_init (spell, spell->active_lang)) - { - return NULL; - } - - return spell->active_lang; -} - -gboolean -xed_spell_checker_check_word (XedSpellChecker *spell, - const gchar *word, - gssize len) -{ - gint enchant_result; - gboolean res = FALSE; - - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); - - if (!lazy_init (spell, spell->active_lang)) - { - return FALSE; - } - - if (len < 0) - { - len = strlen (word); - } - - if (strcmp (word, "xed") == 0) - { - return TRUE; - } - - if (xed_spell_utils_is_digit (word, len)) - { - return TRUE; - } - - g_return_val_if_fail (spell->dict != NULL, FALSE); - enchant_result = enchant_dict_check (spell->dict, word, len); - - switch (enchant_result) - { - case -1: - /* error */ - res = FALSE; - - g_warning ("Spell checker plugin: error checking word '%s' (%s).", - word, enchant_dict_get_error (spell->dict)); - - break; - case 1: - /* it is not in the directory */ - res = FALSE; - break; - case 0: - /* is is in the directory */ - res = TRUE; - break; - default: - g_return_val_if_reached (FALSE); - } - - return res; -} - - -/* return NULL on error or if no suggestions are found */ -GSList * -xed_spell_checker_get_suggestions (XedSpellChecker *spell, - const gchar *word, - gssize len) -{ - gchar **suggestions; - size_t n_suggestions = 0; - GSList *suggestions_list = NULL; - gint i; - - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL); - g_return_val_if_fail (word != NULL, NULL); - - if (!lazy_init (spell, spell->active_lang)) - { - return NULL; - } - - g_return_val_if_fail (spell->dict != NULL, NULL); - - if (len < 0) - { - len = strlen (word); - } - - suggestions = enchant_dict_suggest (spell->dict, word, len, &n_suggestions); - - if (n_suggestions == 0) - { - return NULL; - } - - g_return_val_if_fail (suggestions != NULL, NULL); - - for (i = 0; i < (gint)n_suggestions; i++) - { - suggestions_list = g_slist_prepend (suggestions_list, suggestions[i]); - } - - /* The single suggestions will be freed by the caller */ - g_free (suggestions); - - suggestions_list = g_slist_reverse (suggestions_list); - - return suggestions_list; -} - -gboolean -xed_spell_checker_add_word_to_personal (XedSpellChecker *spell, - const gchar *word, - gssize len) -{ - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); - - if (!lazy_init (spell, spell->active_lang)) - { - return FALSE; - } - - g_return_val_if_fail (spell->dict != NULL, FALSE); - - if (len < 0) - { - len = strlen (word); - } - - enchant_dict_add (spell->dict, word, len); - - g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len); - - return TRUE; -} - -gboolean -xed_spell_checker_add_word_to_session (XedSpellChecker *spell, - const gchar *word, - gssize len) -{ - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); - - if (!lazy_init (spell, spell->active_lang)) - { - return FALSE; - } - - g_return_val_if_fail (spell->dict != NULL, FALSE); - - if (len < 0) - { - len = strlen (word); - } - - enchant_dict_add_to_session (spell->dict, word, len); - - g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_SESSION], 0, word, len); - - return TRUE; -} - -gboolean -xed_spell_checker_clear_session (XedSpellChecker *spell) -{ - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - - /* free and re-request dictionary */ - if (spell->dict != NULL) - { - enchant_broker_free_dict (spell->broker, spell->dict); - spell->dict = NULL; - } - - if (!lazy_init (spell, spell->active_lang)) - { - return FALSE; - } - - g_signal_emit (G_OBJECT (spell), signals[CLEAR_SESSION], 0); - - return TRUE; -} - -/* - * Informs dictionary, that word 'word' will be replaced/corrected by word - * 'replacement' - */ -gboolean -xed_spell_checker_set_correction (XedSpellChecker *spell, - const gchar *word, - gssize w_len, - const gchar *replacement, - gssize r_len) -{ - g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE); - g_return_val_if_fail (word != NULL, FALSE); - g_return_val_if_fail (replacement != NULL, FALSE); - - if (!lazy_init (spell, spell->active_lang)) - { - return FALSE; - } - - g_return_val_if_fail (spell->dict != NULL, FALSE); - - if (w_len < 0) - { - w_len = strlen (word); - } - - if (r_len < 0) - { - r_len = strlen (replacement); - } - - enchant_dict_store_replacement (spell->dict, - word, - w_len, - replacement, - r_len); - - return TRUE; -} - diff --git a/plugins/spell/xed-spell-checker.h b/plugins/spell/xed-spell-checker.h deleted file mode 100644 index 1e6ad50..0000000 --- a/plugins/spell/xed-spell-checker.h +++ /dev/null @@ -1,109 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-checker.h - * This file is part of xed - * - * Copyright (C) 2002-2006 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifndef __XED_SPELL_CHECKER_H__ -#define __XED_SPELL_CHECKER_H__ - -#include -#include - -#include "xed-spell-checker-language.h" - -G_BEGIN_DECLS - -#define XED_TYPE_SPELL_CHECKER (xed_spell_checker_get_type ()) -#define XED_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker)) -#define XED_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER, XedSpellChecker)) -#define XED_IS_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER)) -#define XED_IS_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER)) -#define XED_SPELL_CHECKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker)) - -typedef struct _XedSpellChecker XedSpellChecker; - -typedef struct _XedSpellCheckerClass XedSpellCheckerClass; - -struct _XedSpellCheckerClass -{ - GObjectClass parent_class; - - /* Signals */ - void (*add_word_to_personal) (XedSpellChecker *spell, - const gchar *word, - gint len); - - void (*add_word_to_session) (XedSpellChecker *spell, - const gchar *word, - gint len); - - void (*set_language) (XedSpellChecker *spell, - const XedSpellCheckerLanguage *lang); - - void (*clear_session) (XedSpellChecker *spell); -}; - - -GType xed_spell_checker_get_type (void) G_GNUC_CONST; - -/* Constructors */ -XedSpellChecker *xed_spell_checker_new (void); - -gboolean xed_spell_checker_set_language (XedSpellChecker *spell, - const XedSpellCheckerLanguage *lang); -const XedSpellCheckerLanguage - *xed_spell_checker_get_language (XedSpellChecker *spell); - -gboolean xed_spell_checker_check_word (XedSpellChecker *spell, - const gchar *word, - gssize len); - -GSList *xed_spell_checker_get_suggestions (XedSpellChecker *spell, - const gchar *word, - gssize len); - -gboolean xed_spell_checker_add_word_to_personal - (XedSpellChecker *spell, - const gchar *word, - gssize len); - -gboolean xed_spell_checker_add_word_to_session - (XedSpellChecker *spell, - const gchar *word, - gssize len); - -gboolean xed_spell_checker_clear_session (XedSpellChecker *spell); - -gboolean xed_spell_checker_set_correction (XedSpellChecker *spell, - const gchar *word, - gssize w_len, - const gchar *replacement, - gssize r_len); -G_END_DECLS - -#endif /* __XED_SPELL_CHECKER_H__ */ - diff --git a/plugins/spell/xed-spell-language-dialog.c b/plugins/spell/xed-spell-language-dialog.c deleted file mode 100644 index 452447a..0000000 --- a/plugins/spell/xed-spell-language-dialog.c +++ /dev/null @@ -1,284 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-language-dialog.c - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "xed-spell-language-dialog.h" -#include "xed-spell-checker-language.h" - - -enum -{ - COLUMN_LANGUAGE_NAME = 0, - COLUMN_LANGUAGE_POINTER, - ENCODING_NUM_COLS -}; - - -struct _XedSpellLanguageDialog -{ - GtkDialog dialog; - - GtkWidget *languages_treeview; - GtkTreeModel *model; -}; - -G_DEFINE_TYPE (XedSpellLanguageDialog, xed_spell_language_dialog, GTK_TYPE_DIALOG) - - -static void -xed_spell_language_dialog_class_init (XedSpellLanguageDialogClass *klass) -{ - /* GObjectClass *object_class = G_OBJECT_CLASS (klass); */ -} - -static void -dialog_response_handler (GtkDialog *dlg, - gint res_id) -{ - if (res_id == GTK_RESPONSE_HELP) - { - xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin"); - - g_signal_stop_emission_by_name (dlg, "response"); - } -} - -static void -scroll_to_selected (GtkTreeView *tree_view) -{ - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - - model = gtk_tree_view_get_model (tree_view); - g_return_if_fail (model != NULL); - - /* Scroll to selected */ - selection = gtk_tree_view_get_selection (tree_view); - g_return_if_fail (selection != NULL); - - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) - { - GtkTreePath* path; - - path = gtk_tree_model_get_path (model, &iter); - g_return_if_fail (path != NULL); - - gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 1.0, 0.0); - gtk_tree_path_free (path); - } -} - -static void -language_row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - XedSpellLanguageDialog *dialog) -{ - gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); -} - -static void -create_dialog (XedSpellLanguageDialog *dlg, - const gchar *data_dir) -{ - GtkWidget *error_widget; - GtkWidget *content; - gboolean ret; - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - gchar *ui_file; - gchar *root_objects[] = { - "content", - NULL - }; - - gtk_dialog_add_buttons (GTK_DIALOG (dlg), - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_OK"), GTK_RESPONSE_OK, - _("_Help"), GTK_RESPONSE_HELP, - NULL); - - gtk_window_set_title (GTK_WINDOW (dlg), _("Set language")); - gtk_window_set_modal (GTK_WINDOW (dlg), TRUE); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE); - - /* HIG defaults */ - gtk_container_set_border_width (GTK_CONTAINER (dlg), 5); - gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 2); - gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 5); - gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6); - - g_signal_connect (dlg, "response", - G_CALLBACK (dialog_response_handler), NULL); - - ui_file = g_build_filename (data_dir, "languages-dialog.ui", NULL); - ret = xed_utils_get_ui_objects (ui_file, - root_objects, - &error_widget, - "content", &content, - "languages_treeview", &dlg->languages_treeview, - NULL); - g_free (ui_file); - - if (!ret) - { - gtk_widget_show (error_widget); - - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), error_widget, TRUE, TRUE, 0); - - return; - } - - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), content, TRUE, TRUE, 0); - g_object_unref (content); - gtk_container_set_border_width (GTK_CONTAINER (content), 5); - - dlg->model = GTK_TREE_MODEL (gtk_list_store_new (ENCODING_NUM_COLS, G_TYPE_STRING, G_TYPE_POINTER)); - - gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->languages_treeview), dlg->model); - - g_object_unref (dlg->model); - - /* Add the encoding column */ - cell = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Languages"), - cell, - "text", - COLUMN_LANGUAGE_NAME, - NULL); - - gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->languages_treeview), column); - - gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->languages_treeview), COLUMN_LANGUAGE_NAME); - - g_signal_connect (dlg->languages_treeview, "realize", - G_CALLBACK (scroll_to_selected), dlg); - g_signal_connect (dlg->languages_treeview, "row-activated", - G_CALLBACK (language_row_activated), dlg); -} - -static void -xed_spell_language_dialog_init (XedSpellLanguageDialog *dlg) -{ - -} - -static void -populate_language_list (XedSpellLanguageDialog *dlg, - const XedSpellCheckerLanguage *cur_lang) -{ - GtkListStore *store; - GtkTreeIter iter; - - const GSList* langs; - - /* create list store */ - store = GTK_LIST_STORE (dlg->model); - - langs = xed_spell_checker_get_available_languages (); - - while (langs) - { - const gchar *name; - - name = xed_spell_checker_language_to_string ((const XedSpellCheckerLanguage*)langs->data); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - COLUMN_LANGUAGE_NAME, name, - COLUMN_LANGUAGE_POINTER, langs->data, - -1); - - if (langs->data == cur_lang) - { - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview)); - g_return_if_fail (selection != NULL); - - gtk_tree_selection_select_iter (selection, &iter); - } - - langs = g_slist_next (langs); - } -} - -GtkWidget * -xed_spell_language_dialog_new (GtkWindow *parent, - const XedSpellCheckerLanguage *cur_lang, - const gchar *data_dir) -{ - XedSpellLanguageDialog *dlg; - - g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL); - - dlg = g_object_new (XED_TYPE_SPELL_LANGUAGE_DIALOG, NULL); - - create_dialog (dlg, data_dir); - - populate_language_list (dlg, cur_lang); - - gtk_window_set_transient_for (GTK_WINDOW (dlg), parent); - gtk_widget_grab_focus (dlg->languages_treeview); - - return GTK_WIDGET (dlg); -} - -const XedSpellCheckerLanguage * -xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg) -{ - GValue value = {0, }; - const XedSpellCheckerLanguage* lang; - - GtkTreeIter iter; - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview)); - g_return_val_if_fail (selection != NULL, NULL); - - if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) - { - return NULL; - } - - gtk_tree_model_get_value (dlg->model, &iter, COLUMN_LANGUAGE_POINTER, &value); - - lang = (const XedSpellCheckerLanguage* ) g_value_get_pointer (&value); - - return lang; -} - diff --git a/plugins/spell/xed-spell-language-dialog.h b/plugins/spell/xed-spell-language-dialog.h deleted file mode 100644 index b11c454..0000000 --- a/plugins/spell/xed-spell-language-dialog.h +++ /dev/null @@ -1,65 +0,0 @@ -/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * xed-spell-language-dialog.h - * This file is part of xed - * - * Copyright (C) 2002 Paolo Maggi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Modified by the xed Team, 2002. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#ifndef __XED_SPELL_LANGUAGE_DIALOG_H__ -#define __XED_SPELL_LANGUAGE_DIALOG_H__ - -#include -#include "xed-spell-checker-language.h" - -G_BEGIN_DECLS - -#define XED_TYPE_SPELL_LANGUAGE_DIALOG (xed_spell_language_dialog_get_type()) -#define XED_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialog)) -#define XED_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass)) -#define XED_IS_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG)) -#define XED_IS_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG)) -#define XED_SPELL_LANGUAGE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass)) - - -typedef struct _XedSpellLanguageDialog XedSpellLanguageDialog; -typedef struct _XedSpellLanguageDialogClass XedSpellLanguageDialogClass; - -struct _XedSpellLanguageDialogClass -{ - GtkDialogClass parent_class; -}; - -GType xed_spell_language_dialog_get_type (void) G_GNUC_CONST; - -GtkWidget *xed_spell_language_dialog_new (GtkWindow *parent, - const XedSpellCheckerLanguage *cur_lang, - const gchar *data_dir); - -const XedSpellCheckerLanguage *xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg); - -G_END_DECLS - -#endif /* __XED_SPELL_LANGUAGE_DIALOG_H__ */ - diff --git a/plugins/spell/xed-spell-plugin.c b/plugins/spell/xed-spell-plugin.c index 5dd72f9..7c4efdc 100644 --- a/plugins/spell/xed-spell-plugin.c +++ b/plugins/spell/xed-spell-plugin.c @@ -18,41 +18,29 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H #include -#endif #include "xed-spell-plugin.h" -#include "xed-spell-utils.h" #include /* For strlen */ #include #include +#include #include #include #include -#include #include -#include - -#include "xed-spell-checker.h" -#include "xed-spell-checker-dialog.h" -#include "xed-spell-language-dialog.h" -#include "xed-automatic-spell-checker.h" +#include #define XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE "metadata::xed-spell-language" #define XED_METADATA_ATTRIBUTE_SPELL_ENABLED "metadata::xed-spell-enabled" -#define XED_AUTOMATIC_SPELL_VIEW "XedAutomaticSpellView" +#define SPELL_ENABLED_STR "1" #define MENU_PATH "/MenuBar/ToolsMenu/ToolsOps_1" -#define XED_SPELL_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \ - XED_TYPE_SPELL_PLUGIN, \ - XedSpellPluginPrivate)) - /* GSettings keys */ #define SPELL_SCHEMA "org.x.editor.plugins.spell" #define AUTOCHECK_TYPE_KEY "autocheck-type" @@ -60,53 +48,38 @@ static void xed_window_activatable_iface_init (XedWindowActivatableInterface *iface); static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface); -G_DEFINE_DYNAMIC_TYPE_EXTENDED (XedSpellPlugin, - xed_spell_plugin, - PEAS_TYPE_EXTENSION_BASE, - 0, - G_IMPLEMENT_INTERFACE_DYNAMIC (XED_TYPE_WINDOW_ACTIVATABLE, - xed_window_activatable_iface_init) - G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE, - peas_gtk_configurable_iface_init)) - struct _XedSpellPluginPrivate { XedWindow *window; GtkActionGroup *action_group; guint ui_id; - guint message_cid; - gulong tab_added_id; - gulong tab_removed_id; GSettings *settings; }; -typedef struct _CheckRange CheckRange; - -struct _CheckRange -{ - GtkTextMark *start_mark; - GtkTextMark *end_mark; - - gint mw_start; /* misspelled word start */ - gint mw_end; /* end */ - - GtkTextMark *current_mark; -}; - enum { PROP_0, PROP_WINDOW }; -static void spell_cb (GtkAction *action, - XedSpellPlugin *plugin); +G_DEFINE_DYNAMIC_TYPE_EXTENDED (XedSpellPlugin, + xed_spell_plugin, + PEAS_TYPE_EXTENSION_BASE, + 0, + G_IMPLEMENT_INTERFACE_DYNAMIC (XED_TYPE_WINDOW_ACTIVATABLE, + xed_window_activatable_iface_init) + G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE, + peas_gtk_configurable_iface_init) + G_ADD_PRIVATE_DYNAMIC (XedSpellPlugin)) + +static void check_spell_cb (GtkAction *action, + XedSpellPlugin *plugin); static void set_language_cb (GtkAction *action, XedSpellPlugin *plugin); -static void auto_spell_cb (GtkAction *action, - XedSpellPlugin *plugin); +static void inline_checker_cb (GtkAction *action, + XedSpellPlugin *plugin); /* UI actions. */ static const GtkActionEntry action_entries[] = @@ -116,7 +89,7 @@ static const GtkActionEntry action_entries[] = N_("_Check Spelling..."), "F7", N_("Check the current document for incorrect spelling"), - G_CALLBACK (spell_cb) + G_CALLBACK (check_spell_cb) }, { "ConfigSpell", @@ -130,12 +103,12 @@ static const GtkActionEntry action_entries[] = static const GtkToggleActionEntry toggle_action_entries[] = { - { "AutoSpell", + { "InlineSpellChecker", NULL, N_("_Autocheck Spelling"), NULL, N_("Automatically spell-check the current document"), - G_CALLBACK (auto_spell_cb), + G_CALLBACK (inline_checker_cb), FALSE } }; @@ -160,37 +133,6 @@ typedef enum AUTOCHECK_ALWAYS } XedSpellPluginAutocheckType; - - -static GQuark spell_checker_id = 0; -static GQuark check_range_id = 0; - -static void -xed_spell_plugin_init (XedSpellPlugin *plugin) -{ - xed_debug_message (DEBUG_PLUGINS, "XedSpellPlugin initializing"); - - plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin, XED_TYPE_SPELL_PLUGIN, XedSpellPluginPrivate); - - plugin->priv->settings = g_settings_new (SPELL_SCHEMA); -} - -static void -xed_spell_plugin_dispose (GObject *object) -{ - XedSpellPlugin *plugin = XED_SPELL_PLUGIN (object); - - xed_debug_message (DEBUG_PLUGINS, "XedSpellPlugin disposing"); - - g_clear_object (&plugin->priv->settings); - g_clear_object (&plugin->priv->window); - g_clear_object (&plugin->priv->action_group); - g_clear_object (&plugin->priv->settings); - - G_OBJECT_CLASS (xed_spell_plugin_parent_class)->dispose (object); -} - - static void xed_spell_plugin_set_property (GObject *object, guint prop_id, @@ -229,44 +171,94 @@ xed_spell_plugin_get_property (GObject *object, } } - static void -set_spell_language_cb (XedSpellChecker *spell, - const XedSpellCheckerLanguage *lang, - XedDocument *doc) +xed_spell_plugin_dispose (GObject *object) { - const gchar *key; + XedSpellPlugin *plugin = XED_SPELL_PLUGIN (object); - g_return_if_fail (XED_IS_DOCUMENT (doc)); - g_return_if_fail (lang != NULL); + xed_debug_message (DEBUG_PLUGINS, "XedSpellPlugin disposing"); - key = xed_spell_checker_language_to_key (lang); - g_return_if_fail (key != NULL); + g_clear_object (&plugin->priv->settings); + g_clear_object (&plugin->priv->window); + g_clear_object (&plugin->priv->action_group); + g_clear_object (&plugin->priv->settings); - xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE, key, NULL); + G_OBJECT_CLASS (xed_spell_plugin_parent_class)->dispose (object); } static void -set_language_from_metadata (XedSpellChecker *spell, - XedDocument *doc) +xed_spell_plugin_class_init (XedSpellPluginClass *klass) { - const XedSpellCheckerLanguage *lang = NULL; - gchar *value = NULL; + GObjectClass *object_class = G_OBJECT_CLASS (klass); - value = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE); + object_class->dispose = xed_spell_plugin_dispose; + object_class->set_property = xed_spell_plugin_set_property; + object_class->get_property = xed_spell_plugin_get_property; - if (value != NULL) + g_object_class_override_property (object_class, PROP_WINDOW, "window"); +} + +static void +xed_spell_plugin_class_finalize (XedSpellPluginClass *klass) +{ +} + +static void +xed_spell_plugin_init (XedSpellPlugin *plugin) +{ + xed_debug_message (DEBUG_PLUGINS, "XedSpellPlugin initializing"); + + plugin->priv = xed_spell_plugin_get_instance_private (plugin); + + plugin->priv->settings = g_settings_new (SPELL_SCHEMA); +} + +static GspellChecker * +get_spell_checker (XedDocument *doc) +{ + GspellTextBuffer *gspell_buffer; + + gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer (GTK_TEXT_BUFFER (doc)); + return gspell_text_buffer_get_spell_checker (gspell_buffer); +} + +static const GspellLanguage * +get_language_from_metadata (XedDocument *doc) +{ + const GspellLanguage *lang = NULL; + gchar *language_code = NULL; + + language_code = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE); + + if (language_code != NULL) { - lang = xed_spell_checker_language_from_key (value); - g_free (value); + lang = gspell_language_lookup (language_code); + g_free (language_code); } - if (lang != NULL) - { - g_signal_handlers_block_by_func (spell, set_spell_language_cb, doc); - xed_spell_checker_set_language (spell, lang); - g_signal_handlers_unblock_by_func (spell, set_spell_language_cb, doc); - } + return lang; +} + +static void +check_spell_cb (GtkAction *action, + XedSpellPlugin *plugin) +{ + XedSpellPluginPrivate *priv; + XedView *view; + GspellNavigator *navigator; + GtkWidget *dialog; + + xed_debug (DEBUG_PLUGINS); + + priv = plugin->priv; + + view = xed_window_get_active_view (priv->window); + g_return_if_fail (view != NULL); + + navigator = gspell_navigator_text_view_new (GTK_TEXT_VIEW (view)); + dialog = gspell_checker_dialog_new (GTK_WINDOW (priv->window), navigator); + + gtk_widget_show (dialog); } static XedSpellPluginAutocheckType @@ -291,507 +283,21 @@ set_autocheck_type (GSettings *settings, g_settings_set_enum (settings, AUTOCHECK_TYPE_KEY, autocheck_type); } -static XedSpellChecker * -get_spell_checker_from_document (XedDocument *doc) -{ - XedSpellChecker *spell; - gpointer data; - - xed_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (doc != NULL, NULL); - - data = g_object_get_qdata (G_OBJECT (doc), spell_checker_id); - - if (data == NULL) - { - spell = xed_spell_checker_new (); - - set_language_from_metadata (spell, doc); - - g_object_set_qdata_full (G_OBJECT (doc), - spell_checker_id, - spell, - (GDestroyNotify) g_object_unref); - - g_signal_connect (spell, "set_language", - G_CALLBACK (set_spell_language_cb), doc); - } - else - { - g_return_val_if_fail (XED_IS_SPELL_CHECKER (data), NULL); - spell = XED_SPELL_CHECKER (data); - } - - return spell; -} - -static CheckRange * -get_check_range (XedDocument *doc) -{ - CheckRange *range; - - xed_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (doc != NULL, NULL); - - range = (CheckRange *) g_object_get_qdata (G_OBJECT (doc), check_range_id); - - return range; -} - static void -update_current (XedDocument *doc, - gint current) +language_dialog_response_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) { - CheckRange *range; - GtkTextIter iter; - GtkTextIter end_iter; - - xed_debug (DEBUG_PLUGINS); - - g_return_if_fail (doc != NULL); - g_return_if_fail (current >= 0); - - range = get_check_range (doc); - g_return_if_fail (range != NULL); - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &iter, current); - - if (!gtk_text_iter_inside_word (&iter)) + if (response_id == GTK_RESPONSE_HELP) { - /* if we're not inside a word, - * we must be in some spaces. - * skip forward to the beginning of the next word. */ - if (!gtk_text_iter_is_end (&iter)) - { - gtk_text_iter_forward_word_end (&iter); - gtk_text_iter_backward_word_start (&iter); - } - } - else - { - if (!gtk_text_iter_starts_word (&iter)) - { - gtk_text_iter_backward_word_start (&iter); - } - } - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &end_iter, range->end_mark); - - if (gtk_text_iter_compare (&end_iter, &iter) < 0) - { - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, &end_iter); - } - else - { - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->current_mark, &iter); - } -} - -static void -set_check_range (XedDocument *doc, - GtkTextIter *start, - GtkTextIter *end) -{ - CheckRange *range; - GtkTextIter iter; - - xed_debug (DEBUG_PLUGINS); - - range = get_check_range (doc); - - if (range == NULL) - { - xed_debug_message (DEBUG_PLUGINS, "There was not a previous check range"); - - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); - - range = g_new0 (CheckRange, 1); - - range->start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "check_range_start_mark", &iter, TRUE); - - range->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "check_range_end_mark", &iter, FALSE); - - range->current_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc), - "check_range_current_mark", &iter, TRUE); - - g_object_set_qdata_full (G_OBJECT (doc), check_range_id, range, (GDestroyNotify)g_free); - } - - if (xed_spell_utils_skip_no_spell_check (start, end)) - { - if (!gtk_text_iter_inside_word (end)) - { - /* if we're neither inside a word, - * we must be in some spaces. - * skip backward to the end of the previous word. */ - if (!gtk_text_iter_is_end (end)) - { - gtk_text_iter_backward_word_start (end); - gtk_text_iter_forward_word_end (end); - } - } - else - { - if (!gtk_text_iter_ends_word (end)) - { - gtk_text_iter_forward_word_end (end); - } - } - } - else - { - /* no spell checking in the specified range */ - start = end; - } - - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->start_mark, start); - gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), range->end_mark, end); - - range->mw_start = -1; - range->mw_end = -1; - - update_current (doc, gtk_text_iter_get_offset (start)); -} - -static gchar * -get_current_word (XedDocument *doc, - gint *start, - gint *end) -{ - const CheckRange *range; - GtkTextIter end_iter; - GtkTextIter current_iter; - gint range_end; - - xed_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (doc != NULL, NULL); - g_return_val_if_fail (start != NULL, NULL); - g_return_val_if_fail (end != NULL, NULL); - - range = get_check_range (doc); - g_return_val_if_fail (range != NULL, NULL); - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), &end_iter, range->end_mark); - - range_end = gtk_text_iter_get_offset (&end_iter); - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), ¤t_iter, range->current_mark); - - end_iter = current_iter; - - if (!gtk_text_iter_is_end (&end_iter)) - { - xed_debug_message (DEBUG_PLUGINS, "Current is not end"); - - gtk_text_iter_forward_word_end (&end_iter); - } - - *start = gtk_text_iter_get_offset (¤t_iter); - *end = MIN (gtk_text_iter_get_offset (&end_iter), range_end); - - xed_debug_message (DEBUG_PLUGINS, "Current word extends [%d, %d]", *start, *end); - - if (!(*start < *end)) - { - return NULL; - } - - return gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), ¤t_iter, &end_iter, TRUE); -} - -static gboolean -goto_next_word (XedDocument *doc) -{ - CheckRange *range; - GtkTextIter current_iter; - GtkTextIter old_current_iter; - GtkTextIter end_iter; - - xed_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (doc != NULL, FALSE); - - range = get_check_range (doc); - g_return_val_if_fail (range != NULL, FALSE); - - gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc), ¤t_iter, range->current_mark); - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end_iter); - - old_current_iter = current_iter; - - gtk_text_iter_forward_word_ends (¤t_iter, 2); - gtk_text_iter_backward_word_start (¤t_iter); - - if (xed_spell_utils_skip_no_spell_check (¤t_iter, &end_iter) && - (gtk_text_iter_compare (&old_current_iter, ¤t_iter) < 0) && - (gtk_text_iter_compare (¤t_iter, &end_iter) < 0)) - { - update_current (doc, gtk_text_iter_get_offset (¤t_iter)); - return TRUE; - } - - return FALSE; -} - -static gchar * -get_next_misspelled_word (XedView *view) -{ - XedDocument *doc; - CheckRange *range; - gint start, end; - gchar *word; - XedSpellChecker *spell; - - g_return_val_if_fail (view != NULL, NULL); - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - g_return_val_if_fail (doc != NULL, NULL); - - range = get_check_range (doc); - g_return_val_if_fail (range != NULL, NULL); - - spell = get_spell_checker_from_document (doc); - g_return_val_if_fail (spell != NULL, NULL); - - word = get_current_word (doc, &start, &end); - if (word == NULL) - { - return NULL; - } - - xed_debug_message (DEBUG_PLUGINS, "Word to check: %s", word); - - while (xed_spell_checker_check_word (spell, word, -1)) - { - g_free (word); - - if (!goto_next_word (doc)) - { - return NULL; - } - - /* may return null if we reached the end of the selection */ - word = get_current_word (doc, &start, &end); - if (word == NULL) - { - return NULL; - } - - xed_debug_message (DEBUG_PLUGINS, "Word to check: %s", word); - } - - if (!goto_next_word (doc)) - { - update_current (doc, gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc))); - } - - if (word != NULL) - { - GtkTextIter s, e; - - range->mw_start = start; - range->mw_end = end; - - xed_debug_message (DEBUG_PLUGINS, "Select [%d, %d]", start, end); - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &s, start); - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &e, end); - - gtk_text_buffer_select_range (GTK_TEXT_BUFFER (doc), &s, &e); - - xed_view_scroll_to_cursor (view); - } - else - { - range->mw_start = -1; - range->mw_end = -1; - } - - return word; -} - -static void -ignore_cb (XedSpellCheckerDialog *dlg, - const gchar *w, - XedView *view) -{ - gchar *word = NULL; - - xed_debug (DEBUG_PLUGINS); - - g_return_if_fail (w != NULL); - g_return_if_fail (view != NULL); - - word = get_next_misspelled_word (view); - if (word == NULL) - { - xed_spell_checker_dialog_set_completed (dlg); - + xed_app_show_help (XED_APP (g_application_get_default ()), + GTK_WINDOW (dialog), + NULL, + "xed-spellcheck"); return; } - xed_spell_checker_dialog_set_misspelled_word (XED_SPELL_CHECKER_DIALOG (dlg), word, -1); - - g_free (word); -} - -static void -change_cb (XedSpellCheckerDialog *dlg, - const gchar *word, - const gchar *change, - XedView *view) -{ - XedDocument *doc; - CheckRange *range; - gchar *w = NULL; - GtkTextIter start, end; - - xed_debug (DEBUG_PLUGINS); - - g_return_if_fail (view != NULL); - g_return_if_fail (word != NULL); - g_return_if_fail (change != NULL); - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - g_return_if_fail (doc != NULL); - - range = get_check_range (doc); - g_return_if_fail (range != NULL); - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start); - if (range->mw_end < 0) - { - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); - } - else - { - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end); - } - - w = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE); - g_return_if_fail (w != NULL); - - if (strcmp (w, word) != 0) - { - g_free (w); - return; - } - - g_free (w); - - gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER(doc)); - - gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &start, &end); - gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &start, change, -1); - - gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER(doc)); - - update_current (doc, range->mw_start + g_utf8_strlen (change, -1)); - - /* go to next misspelled word */ - ignore_cb (dlg, word, view); -} - -static void -change_all_cb (XedSpellCheckerDialog *dlg, - const gchar *word, - const gchar *change, - XedView *view) -{ - XedDocument *doc; - CheckRange *range; - gchar *w = NULL; - GtkTextIter start, end; - GtkSourceSearchSettings *search_settings; - GtkSourceSearchContext *search_context; - - xed_debug (DEBUG_PLUGINS); - - g_return_if_fail (view != NULL); - g_return_if_fail (word != NULL); - g_return_if_fail (change != NULL); - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - g_return_if_fail (doc != NULL); - - range = get_check_range (doc); - g_return_if_fail (range != NULL); - - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start); - if (range->mw_end < 0) - { - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end); - } - else - { - gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end); - } - - w = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE); - g_return_if_fail (w != NULL); - - if (strcmp (w, word) != 0) - { - g_free (w); - return; - } - - g_free (w); - - search_settings = gtk_source_search_settings_new (); - gtk_source_search_settings_set_case_sensitive (search_settings, TRUE); - gtk_source_search_settings_set_at_word_boundaries (search_settings, TRUE); - gtk_source_search_settings_set_search_text (search_settings, word); - - search_context = gtk_source_search_context_new (GTK_SOURCE_BUFFER (doc), search_settings); - - gtk_source_search_context_set_highlight (search_context, FALSE); - - gtk_source_search_context_replace_all (search_context, change, -1, NULL); - - update_current (doc, range->mw_start + g_utf8_strlen (change, -1)); - - /* go to next misspelled word */ - ignore_cb (dlg, word, view); - - g_object_unref (search_settings); - g_object_unref (search_context); -} - -static void -add_word_cb (XedSpellCheckerDialog *dlg, - const gchar *word, - XedView *view) -{ - g_return_if_fail (view != NULL); - g_return_if_fail (word != NULL); - - /* go to next misspelled word */ - ignore_cb (dlg, word, view); -} - -static void -language_dialog_response (GtkDialog *dlg, - gint res_id, - XedSpellChecker *spell) -{ - if (res_id == GTK_RESPONSE_OK) - { - const XedSpellCheckerLanguage *lang; - - lang = xed_spell_language_get_selected_language (XED_SPELL_LANGUAGE_DIALOG (dlg)); - if (lang != NULL) - { - xed_spell_checker_set_language (spell, lang); - } - } - - gtk_widget_destroy (GTK_WIDGET (dlg)); + gtk_widget_destroy (GTK_WIDGET (dialog)); } static void @@ -899,11 +405,10 @@ set_language_cb (GtkAction *action, { XedSpellPluginPrivate *priv; XedDocument *doc; - XedSpellChecker *spell; - const XedSpellCheckerLanguage *lang; - GtkWidget *dlg; - GtkWindowGroup *wg; - gchar *data_dir; + GspellChecker *checker; + const GspellLanguage *lang; + GtkWidget *dialog; + GtkWindowGroup *window_group; xed_debug (DEBUG_PLUGINS); @@ -912,145 +417,38 @@ set_language_cb (GtkAction *action, doc = xed_window_get_active_document (priv->window); g_return_if_fail (doc != NULL); - spell = get_spell_checker_from_document (doc); - g_return_if_fail (spell != NULL); + checker = get_spell_checker (doc); + g_return_if_fail (checker != NULL); - lang = xed_spell_checker_get_language (spell); + lang = gspell_checker_get_language (checker); - data_dir = peas_extension_base_get_data_dir (PEAS_EXTENSION_BASE (plugin)); - dlg = xed_spell_language_dialog_new (GTK_WINDOW (priv->window), lang, data_dir); - g_free (data_dir); + dialog = gspell_language_chooser_dialog_new (GTK_WINDOW (priv->window), + lang, + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT); - wg = xed_window_get_group (priv->window); + g_object_bind_property (dialog, "language", + checker, "language", + G_BINDING_DEFAULT); - gtk_window_group_add_window (wg, GTK_WINDOW (dlg)); + window_group = xed_window_get_group (priv->window); - gtk_window_set_modal (GTK_WINDOW (dlg), TRUE); + gtk_window_group_add_window (window_group, GTK_WINDOW (dialog)); - g_signal_connect (dlg, "response", - G_CALLBACK (language_dialog_response), spell); + gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Help"), GTK_RESPONSE_HELP); - gtk_widget_show (dlg); + g_signal_connect (dialog, "response", + G_CALLBACK (language_dialog_response_cb), NULL); + + gtk_widget_show (dialog); } static void -spell_cb (GtkAction *action, - XedSpellPlugin *plugin) +inline_checker_cb (GtkAction *action, + XedSpellPlugin *plugin) { XedSpellPluginPrivate *priv; XedView *view; - XedDocument *doc; - XedSpellChecker *spell; - GtkWidget *dlg; - GtkTextIter start, end; - gchar *word; - gchar *data_dir; - - xed_debug (DEBUG_PLUGINS); - - priv = plugin->priv; - - view = xed_window_get_active_view (priv->window); - g_return_if_fail (view != NULL); - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - g_return_if_fail (doc != NULL); - - spell = get_spell_checker_from_document (doc); - g_return_if_fail (spell != NULL); - - if (gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc)) <= 0) - { - GtkWidget *statusbar; - - statusbar = xed_window_get_statusbar (priv->window); - xed_statusbar_flash_message (XED_STATUSBAR (statusbar), priv->message_cid, _("The document is empty.")); - - return; - } - - if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc), &start, &end)) - { - /* no selection, get the whole doc */ - gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), &start, &end); - } - - set_check_range (doc, &start, &end); - - word = get_next_misspelled_word (view); - if (word == NULL) - { - GtkWidget *statusbar; - - statusbar = xed_window_get_statusbar (priv->window); - xed_statusbar_flash_message (XED_STATUSBAR (statusbar), priv->message_cid, _("No misspelled words")); - - return; - } - - data_dir = peas_extension_base_get_data_dir (PEAS_EXTENSION_BASE (plugin)); - dlg = xed_spell_checker_dialog_new_from_spell_checker (spell, data_dir); - g_free (data_dir); - - gtk_window_set_modal (GTK_WINDOW (dlg), TRUE); - gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (priv->window)); - - g_signal_connect (dlg, "ignore", G_CALLBACK (ignore_cb), view); - g_signal_connect (dlg, "ignore_all", G_CALLBACK (ignore_cb), view); - - g_signal_connect (dlg, "change", G_CALLBACK (change_cb), view); - g_signal_connect (dlg, "change_all", G_CALLBACK (change_all_cb), view); - - g_signal_connect (dlg, "add_word_to_personal", G_CALLBACK (add_word_cb), view); - - xed_spell_checker_dialog_set_misspelled_word (XED_SPELL_CHECKER_DIALOG (dlg), word, -1); - - g_free (word); - - gtk_widget_show (dlg); -} - -static void -set_auto_spell (XedWindow *window, - XedView *view, - gboolean active) -{ - XedAutomaticSpellChecker *autospell; - XedSpellChecker *spell; - XedDocument *doc; - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - - spell = get_spell_checker_from_document (doc); - g_return_if_fail (spell != NULL); - - autospell = xed_automatic_spell_checker_get_from_document (doc); - - if (active) - { - if (autospell == NULL) - { - autospell = xed_automatic_spell_checker_new (doc, spell); - xed_automatic_spell_checker_attach_view (autospell, view); - xed_automatic_spell_checker_recheck_all (autospell); - } - } - else - { - if (autospell != NULL) - { - xed_automatic_spell_checker_free (autospell); - } - } -} - -static void -auto_spell_cb (GtkAction *action, - XedSpellPlugin *plugin) -{ - XedSpellPluginPrivate *priv; - XedDocument *doc; - XedView *view; gboolean active; xed_debug (DEBUG_PLUGINS); @@ -1058,24 +456,27 @@ auto_spell_cb (GtkAction *action, priv = plugin->priv; active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); - xed_debug_message (DEBUG_PLUGINS, active ? "Auto Spell activated" : "Auto Spell deactivated"); + xed_debug_message (DEBUG_PLUGINS, active ? "Inline Checker activated" : "Inline Checker deactivated"); view = xed_window_get_active_view (priv->window); - if (view == NULL) + if (view != NULL) { - return; + XedDocument *doc; + GspellTextView *gspell_view; + + doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + if (get_autocheck_type (plugin) == AUTOCHECK_DOCUMENT) + { + xed_document_set_metadata (doc, + XED_METADATA_ATTRIBUTE_SPELL_ENABLED, + active ? SPELL_ENABLED_STR : NULL, + NULL); + } + + gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view)); + gspell_text_view_set_inline_spell_checking (gspell_view, active); } - - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - - if (get_autocheck_type (plugin) == AUTOCHECK_DOCUMENT) - { - xed_document_set_metadata (doc, - XED_METADATA_ATTRIBUTE_SPELL_ENABLED, - active ? "1" : NULL, NULL); - } - - set_auto_spell (priv->window, view, active); } static void @@ -1088,30 +489,33 @@ update_ui (XedSpellPlugin *plugin) xed_debug (DEBUG_PLUGINS); priv = plugin->priv; + view = xed_window_get_active_view (priv->window); if (view != NULL) { - XedDocument *doc; XedTab *tab; - XedTabState state; - gboolean autospell; + GtkTextBuffer *buffer; - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); tab = xed_window_get_active_tab (priv->window); - state = xed_tab_get_state (tab); - autospell = (doc != NULL && xed_automatic_spell_checker_get_from_document (doc) != NULL); + g_return_if_fail (xed_tab_get_view (tab) == view); /* If the document is loading we can't get the metadata so we endup with an useless speller */ - if (state == XED_TAB_STATE_NORMAL) + if (xed_tab_get_state (tab) == XED_TAB_STATE_NORMAL) { - action = gtk_action_group_get_action (priv->action_group, "AutoSpell"); + GspellTextView *gspell_view; + gboolean inline_checking_enabled; - g_signal_handlers_block_by_func (action, auto_spell_cb, plugin); - set_auto_spell (priv->window, view, autospell); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), autospell); - g_signal_handlers_unblock_by_func (action, auto_spell_cb, plugin); + gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view)); + inline_checking_enabled = gspell_text_view_get_inline_spell_checking (gspell_view); + + action = gtk_action_group_get_action (priv->action_group, "InlineSpellChecker"); + + g_signal_handlers_block_by_func (action, inline_checker_cb, plugin); + gspell_text_view_set_inline_spell_checking (gspell_view, inline_checking_enabled); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), inline_checking_enabled); + g_signal_handlers_unblock_by_func (action, inline_checker_cb, plugin); } } @@ -1121,139 +525,239 @@ update_ui (XedSpellPlugin *plugin) } static void -set_auto_spell_from_metadata (XedSpellPlugin *plugin, - XedView *view, - GtkActionGroup *action_group) +setup_inline_checker_from_metadata (XedSpellPlugin *plugin, + XedView *view) { - gboolean active = FALSE; - gchar *active_str = NULL; - XedWindow *window; + XedSpellPluginPrivate *priv; XedDocument *doc; - XedDocument *active_doc; + gboolean enabled = FALSE; + gchar *enabled_str = NULL; + GspellTextView *gspell_view; + XedView *active_view; XedSpellPluginAutocheckType autocheck_type; - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + priv = plugin->priv; autocheck_type = get_autocheck_type (plugin); + doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + switch (autocheck_type) { case AUTOCHECK_ALWAYS: { - active = TRUE; + enabled = TRUE; break; } case AUTOCHECK_DOCUMENT: { - active_str = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_ENABLED); + enabled_str = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_ENABLED); break; } case AUTOCHECK_NEVER: default: - active = FALSE; + enabled = FALSE; break; } - if (active_str) + if (enabled_str != NULL) { - active = *active_str == '1'; - - g_free (active_str); + enabled = g_str_equal (enabled_str, SPELL_ENABLED_STR); + g_free (enabled_str); } - window = XED_WINDOW (plugin->priv->window); + gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view)); + gspell_text_view_set_inline_spell_checking (gspell_view, enabled); - set_auto_spell (window, view, active); + /* In case that the view is the active one we mark the spell action */ + active_view = xed_window_get_active_view (plugin->priv->window); - /* In case that the doc is the active one we mark the spell action */ - active_doc = xed_window_get_active_document (window); - - if (active_doc == doc && action_group != NULL) + if (active_view == view && priv->action_group != NULL) { GtkAction *action; - action = gtk_action_group_get_action (action_group, "AutoSpell"); + action = gtk_action_group_get_action (priv->action_group, "InlineSpellChecker"); - g_signal_handlers_block_by_func (action, auto_spell_cb, plugin); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); - g_signal_handlers_unblock_by_func (action, auto_spell_cb, plugin); + g_signal_handlers_block_by_func (action, inline_checker_cb, plugin); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), enabled); + g_signal_handlers_unblock_by_func (action, inline_checker_cb, plugin); } } +static void +language_notify_cb (GspellChecker *checker, + GParamSpec *pspec, + XedDocument *doc) +{ + const GspellLanguage *lang; + const gchar *language_code; + + g_return_if_fail (XED_IS_DOCUMENT (doc)); + + lang = gspell_checker_get_language (checker); + g_return_if_fail (lang != NULL); + + language_code = gspell_language_get_code (lang); + g_return_if_fail (language_code != NULL); + + xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE, language_code, NULL); +} + static void on_document_loaded (XedDocument *doc, XedSpellPlugin *plugin) { - XedSpellChecker *spell; + GspellChecker *checker; + XedTab *tab; XedView *view; - spell = XED_SPELL_CHECKER (g_object_get_qdata (G_OBJECT (doc), spell_checker_id)); - if (spell != NULL) + checker = get_spell_checker (doc); + + if (checker != NULL) { - set_language_from_metadata (spell, doc); + const GspellLanguage *lang; + + lang = get_language_from_metadata (doc); + + if (lang != NULL) + { + g_signal_handlers_block_by_func (checker, language_notify_cb, doc); + gspell_checker_set_language (checker, lang); + g_signal_handlers_unblock_by_func (checker, language_notify_cb, doc); + } } - view = XED_VIEW (g_object_get_data (G_OBJECT (doc), XED_AUTOMATIC_SPELL_VIEW)); - - set_auto_spell_from_metadata (plugin, view, plugin->priv->action_group); + tab = xed_tab_get_from_document (doc); + view = xed_tab_get_view (tab); + setup_inline_checker_from_metadata (plugin, view); } static void on_document_saved (XedDocument *doc, XedSpellPlugin *plugin) { - XedAutomaticSpellChecker *autospell; - XedSpellChecker *spell; - const gchar *key; + XedTab *tab; + XedView *view; + GspellChecker *checker; + const gchar *language_code = NULL; + GspellTextView *gspell_view; + gboolean inline_checking_enabled; /* Make sure to save the metadata here too */ - autospell = xed_automatic_spell_checker_get_from_document (doc); - spell = XED_SPELL_CHECKER (g_object_get_qdata (G_OBJECT (doc), spell_checker_id)); + checker = get_spell_checker (doc); - if (spell != NULL) + if (checker != NULL) { - key = xed_spell_checker_language_to_key (xed_spell_checker_get_language (spell)); - } - else - { - key = NULL; + const GspellLanguage *lang; + + lang = gspell_checker_get_language (checker); + if (lang != NULL) + { + language_code = gspell_language_get_code (lang); + } } + tab = xed_tab_get_from_document (doc); + view = xed_tab_get_view (tab); + + gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view)); + inline_checking_enabled = gspell_text_view_get_inline_spell_checking (gspell_view); + if (get_autocheck_type (plugin) == AUTOCHECK_DOCUMENT) { xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_ENABLED, - autospell != NULL ? "1" : NULL, + inline_checking_enabled ? SPELL_ENABLED_STR : NULL, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE, - key, + language_code, NULL); } else { - xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE, key, NULL); + xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_SPELL_LANGUAGE, language_code, NULL); } } +static void +activate_spell_checking_in_view (XedSpellPlugin *plugin, + XedView *view) +{ + XedDocument *doc; + + doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); + + /* It is possible that a GspellChecker has already been set, for example + * if a XedTab has moved to another window. + */ + if (get_spell_checker (doc) == NULL) + { + const GspellLanguage *lang; + GspellChecker *checker; + GspellTextBuffer *gspell_buffer; + + lang = get_language_from_metadata (doc); + checker = gspell_checker_new (lang); + + g_signal_connect_object (checker, "notify::language", + G_CALLBACK (language_notify_cb), doc, 0); + + gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer (GTK_TEXT_BUFFER (doc)); + gspell_text_buffer_set_spell_checker (gspell_buffer, checker); + g_object_unref (checker); + + setup_inline_checker_from_metadata (plugin, view); + } + + g_signal_connect_object (doc, "loaded", + G_CALLBACK (on_document_loaded), plugin, 0); + g_signal_connect_object (doc, "saved", + G_CALLBACK (on_document_saved), plugin, 0); +} + +static void +disconnect_view (XedSpellPlugin *plugin, + XedView *view) +{ + GtkTextBuffer *buffer; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + /* It should still be the same buffer as the one where the signal + * handlers were connected. If not, we assume that the old buffer is + * finalized. And it is anyway safe to call + * g_signal_handlers_disconnect_by_func() if no signal handlers are + * found. + */ + g_signal_handlers_disconnect_by_func (buffer, on_document_loaded, plugin); + g_signal_handlers_disconnect_by_func (buffer, on_document_saved, plugin); +} + +static void +deactivate_spell_checking_in_view (XedSpellPlugin *plugin, + XedView *view) +{ + GtkTextBuffer *gtk_buffer; + GspellTextBuffer *gspell_buffer; + GspellTextView *gspell_view; + + disconnect_view (plugin, view); + + gtk_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer (gtk_buffer); + gspell_text_buffer_set_spell_checker (gspell_buffer, NULL); + + gspell_view = gspell_text_view_get_from_gtk_text_view (GTK_TEXT_VIEW (view)); + gspell_text_view_set_inline_spell_checking (gspell_view, FALSE); +} + static void tab_added_cb (XedWindow *window, XedTab *tab, XedSpellPlugin *plugin) { - XedView *view; - XedDocument *doc; - - view = xed_tab_get_view (tab); - doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))); - - g_object_set_data (G_OBJECT (doc), XED_AUTOMATIC_SPELL_VIEW, view); - - g_signal_connect (doc, "loaded", - G_CALLBACK (on_document_loaded), plugin); - - g_signal_connect (doc, "saved", - G_CALLBACK (on_document_saved), plugin); + activate_spell_checking_in_view (plugin, xed_tab_get_view (tab)); } static void @@ -1261,25 +765,27 @@ tab_removed_cb (XedWindow *window, XedTab *tab, XedSpellPlugin *plugin) { - XedDocument *doc; - - doc = xed_tab_get_document (tab); - g_object_set_data (G_OBJECT (doc), XED_AUTOMATIC_SPELL_VIEW, NULL); - - g_signal_handlers_disconnect_by_func (doc, on_document_loaded, plugin); - g_signal_handlers_disconnect_by_func (doc, on_document_saved, plugin); + /* Don't deactivate completely the spell checking in @tab, since the tab + * can be moved to another window and we don't want to loose the spell + * checking settings (they are not saved in metadata for unsaved + * documents). + */ + disconnect_view (plugin, xed_tab_get_view (tab)); } static void xed_spell_plugin_activate (XedWindowActivatable *activatable) { + XedSpellPlugin *plugin; XedSpellPluginPrivate *priv; GtkUIManager *manager; - GList *views, *l; + GList *views; + GList *l; xed_debug (DEBUG_PLUGINS); - priv = XED_SPELL_PLUGIN (activatable)->priv; + plugin = XED_SPELL_PLUGIN (activatable); + priv = plugin->priv; manager = xed_window_get_ui_manager (priv->window); @@ -1298,9 +804,6 @@ xed_spell_plugin_activate (XedWindowActivatable *activatable) priv->ui_id = gtk_ui_manager_new_merge_id (manager); - priv->message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (xed_window_get_statusbar (priv->window)), - "spell_plugin_message"); - gtk_ui_manager_add_ui (manager, priv->ui_id, MENU_PATH, @@ -1312,8 +815,8 @@ xed_spell_plugin_activate (XedWindowActivatable *activatable) gtk_ui_manager_add_ui (manager, priv->ui_id, MENU_PATH, - "AutoSpell", - "AutoSpell", + "InlineSpellChecker", + "InlineSpellChecker", GTK_UI_MANAGER_MENUITEM, FALSE); @@ -1328,35 +831,43 @@ xed_spell_plugin_activate (XedWindowActivatable *activatable) update_ui (XED_SPELL_PLUGIN (activatable)); views = xed_window_get_views (priv->window); - for (l = views; l != NULL; l = g_list_next (l)) + for (l = views; l != NULL; l = l->next) { - XedView *view = XED_VIEW (l->data); - - set_auto_spell_from_metadata (XED_SPELL_PLUGIN (activatable), view, priv->action_group); + activate_spell_checking_in_view (plugin, XED_VIEW (l->data)); } - priv->tab_added_id = g_signal_connect (priv->window, "tab-added", - G_CALLBACK (tab_added_cb), activatable); - priv->tab_removed_id = g_signal_connect (priv->window, "tab-removed", - G_CALLBACK (tab_removed_cb), activatable); + g_signal_connect (priv->window, "tab-added", + G_CALLBACK (tab_added_cb), activatable); + g_signal_connect (priv->window, "tab-removed", + G_CALLBACK (tab_removed_cb), activatable); } static void xed_spell_plugin_deactivate (XedWindowActivatable *activatable) { + XedSpellPlugin *plugin; XedSpellPluginPrivate *priv; GtkUIManager *manager; + GList *views; + GList *l; xed_debug (DEBUG_PLUGINS); - priv = XED_SPELL_PLUGIN (activatable)->priv; + plugin = XED_SPELL_PLUGIN (activatable); + priv = plugin->priv; manager = xed_window_get_ui_manager (priv->window); gtk_ui_manager_remove_ui (manager, priv->ui_id); gtk_ui_manager_remove_action_group (manager, priv->action_group); - g_signal_handler_disconnect (priv->window, priv->tab_added_id); - g_signal_handler_disconnect (priv->window, priv->tab_removed_id); + g_signal_handlers_disconnect_by_func (priv->window, tab_added_cb, activatable); + g_signal_handlers_disconnect_by_func (priv->window, tab_removed_cb, activatable); + + views = xed_window_get_views (priv->window); + for (l = views; l != NULL; l = l->next) + { + deactivate_spell_checking_in_view (plugin, XED_VIEW (l->data)); + } } static void @@ -1377,35 +888,6 @@ xed_spell_plugin_create_configure_widget (PeasGtkConfigurable *configurable) return widget->content; } -static void -xed_spell_plugin_class_init (XedSpellPluginClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = xed_spell_plugin_dispose; - object_class->set_property = xed_spell_plugin_set_property; - object_class->get_property = xed_spell_plugin_get_property; - - if (spell_checker_id == 0) - { - spell_checker_id = g_quark_from_string ("XedSpellCheckerID"); - } - - if (check_range_id == 0) - { - check_range_id = g_quark_from_string ("CheckRangeID"); - } - - g_object_class_override_property (object_class, PROP_WINDOW, "window"); - - g_type_class_add_private (object_class, sizeof (XedSpellPluginPrivate)); -} - -static void -xed_spell_plugin_class_finalize (XedSpellPluginClass *klass) -{ -} - static void xed_window_activatable_iface_init (XedWindowActivatableInterface *iface) { diff --git a/plugins/spell/xed-spell-utils.c b/plugins/spell/xed-spell-utils.c deleted file mode 100644 index b36c736..0000000 --- a/plugins/spell/xed-spell-utils.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * xed-spell-utils.c - * This file is part of xed - * - * Copyright (C) 2010 - Jesse van den Kieboom - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include - -#include "xed-spell-utils.h" -#include - -gboolean -xed_spell_utils_is_digit (const char *text, gssize length) -{ - gunichar c; - const gchar *p; - const gchar *end; - - g_return_val_if_fail (text != NULL, FALSE); - - if (length < 0) - length = strlen (text); - - p = text; - end = text + length; - - while (p != end) { - const gchar *next; - next = g_utf8_next_char (p); - - c = g_utf8_get_char (p); - - if (!g_unichar_isdigit (c) && c != '.' && c != ',') - return FALSE; - - p = next; - } - - return TRUE; -} - -gboolean -xed_spell_utils_skip_no_spell_check (GtkTextIter *start, - GtkTextIter *end) -{ - GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (start)); - - while (gtk_source_buffer_iter_has_context_class (buffer, start, "no-spell-check")) - { - GtkTextIter last = *start; - - if (!gtk_source_buffer_iter_forward_to_context_class_toggle (buffer, start, "no-spell-check")) - { - return FALSE; - } - - if (gtk_text_iter_compare (start, &last) <= 0) - { - return FALSE; - } - - gtk_text_iter_forward_word_end (start); - gtk_text_iter_backward_word_start (start); - - if (gtk_text_iter_compare (start, &last) <= 0) - { - return FALSE; - } - - if (gtk_text_iter_compare (start, end) >= 0) - { - return FALSE; - } - } - - return TRUE; -} - diff --git a/plugins/spell/xed-spell-utils.h b/plugins/spell/xed-spell-utils.h deleted file mode 100644 index 263979c..0000000 --- a/plugins/spell/xed-spell-utils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * xed-spell-utils.h - * This file is part of xed - * - * Copyright (C) 2010 - Jesse van den Kieboom - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifndef __XED_SPELL_UTILS_H__ -#define __XED_SPELL_UTILS_H__ - -#include - -G_BEGIN_DECLS - -gboolean xed_spell_utils_is_digit (const char *text, gssize length); - -gboolean xed_spell_utils_skip_no_spell_check (GtkTextIter *start, GtkTextIter *end); - -G_END_DECLS - -#endif /* __XED_SPELL_UTILS_H__ */ - From a86c482308c9bd28e57e42330b2d848a22cd148a Mon Sep 17 00:00:00 2001 From: JosephMcc Date: Wed, 14 Feb 2018 10:37:36 -0800 Subject: [PATCH 18/18] spell-plugin: Fix a link to the help file --- plugins/spell/xed-spell-plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/spell/xed-spell-plugin.c b/plugins/spell/xed-spell-plugin.c index 7c4efdc..6e1aac1 100644 --- a/plugins/spell/xed-spell-plugin.c +++ b/plugins/spell/xed-spell-plugin.c @@ -293,7 +293,7 @@ language_dialog_response_cb (GtkDialog *dialog, xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dialog), NULL, - "xed-spellcheck"); + "xed-spell-checker-plugin"); return; }