|
Packit |
aa0600 |
/*
|
|
Packit |
aa0600 |
* This file is part of gspell, a spell-checking library.
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* Copyright 2016 - Sébastien Wilmet
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
aa0600 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
aa0600 |
* License as published by the Free Software Foundation; either
|
|
Packit |
aa0600 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
aa0600 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aa0600 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aa0600 |
* Lesser General Public License for more details.
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aa0600 |
* along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
aa0600 |
*/
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
aa0600 |
#include <config.h>
|
|
Packit |
aa0600 |
#endif
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
#include "gspell-context-menu.h"
|
|
Packit |
aa0600 |
#include <glib/gi18n-lib.h>
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
#define LANGUAGE_DATA_KEY "gspell-language-data-key"
|
|
Packit |
aa0600 |
#define SUGGESTION_DATA_KEY "gspell-suggestion-data-key"
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
typedef struct _LanguageData LanguageData;
|
|
Packit |
aa0600 |
typedef struct _SuggestionData SuggestionData;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
struct _LanguageData
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
const GspellLanguage *lang;
|
|
Packit |
aa0600 |
GspellLanguageActivatedCallback callback;
|
|
Packit |
aa0600 |
gpointer user_data;
|
|
Packit |
aa0600 |
};
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
struct _SuggestionData
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GspellChecker *checker;
|
|
Packit |
aa0600 |
gchar *misspelled_word;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
gchar *suggested_word;
|
|
Packit |
aa0600 |
GspellSuggestionActivatedCallback callback;
|
|
Packit |
aa0600 |
gpointer user_data;
|
|
Packit |
aa0600 |
};
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static void
|
|
Packit |
aa0600 |
suggestion_data_free (gpointer data)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
SuggestionData *suggestion_data = data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (suggestion_data != NULL)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
g_clear_object (&suggestion_data->checker);
|
|
Packit |
aa0600 |
g_free (suggestion_data->misspelled_word);
|
|
Packit |
aa0600 |
g_free (suggestion_data->suggested_word);
|
|
Packit |
aa0600 |
g_free (suggestion_data);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static void
|
|
Packit |
aa0600 |
activate_language_cb (GtkWidget *menu_item)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
LanguageData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_object_get_data (G_OBJECT (menu_item), LANGUAGE_DATA_KEY);
|
|
Packit |
aa0600 |
g_return_if_fail (data != NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (data->callback != NULL)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
data->callback (data->lang, data->user_data);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static GtkWidget *
|
|
Packit |
aa0600 |
get_language_menu (const GspellLanguage *current_language,
|
|
Packit |
aa0600 |
GspellLanguageActivatedCallback callback,
|
|
Packit |
aa0600 |
gpointer user_data)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GtkWidget *menu;
|
|
Packit |
aa0600 |
const GList *languages;
|
|
Packit |
aa0600 |
const GList *l;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu = gtk_menu_new ();
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
languages = gspell_language_get_available ();
|
|
Packit |
aa0600 |
for (l = languages; l != NULL; l = l->next)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
const GspellLanguage *lang = l->data;
|
|
Packit |
aa0600 |
const gchar *lang_name;
|
|
Packit |
aa0600 |
GtkWidget *menu_item;
|
|
Packit |
aa0600 |
LanguageData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
lang_name = gspell_language_get_name (lang);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (lang == current_language)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
/* Do not create a group. Just mark the current language
|
|
Packit |
aa0600 |
* as active.
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* With a group, the first language in the list gets
|
|
Packit |
aa0600 |
* activated, which changes the GspellChecker language
|
|
Packit |
aa0600 |
* before we arrive to the current_language.
|
|
Packit |
aa0600 |
*
|
|
Packit |
aa0600 |
* Also, having a bullet only for the current_language is
|
|
Packit |
aa0600 |
* sufficient (to be like in Firefox), the menu is
|
|
Packit |
aa0600 |
* anyway ephemeral. No need to have an empty bullet for
|
|
Packit |
aa0600 |
* all the other languages.
|
|
Packit |
aa0600 |
*/
|
|
Packit |
aa0600 |
menu_item = gtk_radio_menu_item_new_with_label (NULL, lang_name);
|
|
Packit |
aa0600 |
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
else
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new_with_label (lang_name);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_new0 (LanguageData, 1);
|
|
Packit |
aa0600 |
data->lang = lang;
|
|
Packit |
aa0600 |
data->callback = callback;
|
|
Packit |
aa0600 |
data->user_data = user_data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_object_set_data_full (G_OBJECT (menu_item),
|
|
Packit |
aa0600 |
LANGUAGE_DATA_KEY,
|
|
Packit |
aa0600 |
data,
|
|
Packit |
aa0600 |
g_free);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_signal_connect (menu_item,
|
|
Packit |
aa0600 |
"activate",
|
|
Packit |
aa0600 |
G_CALLBACK (activate_language_cb),
|
|
Packit |
aa0600 |
NULL);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
return menu;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
GtkMenuItem *
|
|
Packit |
aa0600 |
_gspell_context_menu_get_language_menu_item (const GspellLanguage *current_language,
|
|
Packit |
aa0600 |
GspellLanguageActivatedCallback callback,
|
|
Packit |
aa0600 |
gpointer user_data)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GtkWidget *lang_menu;
|
|
Packit |
aa0600 |
GtkMenuItem *menu_item;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
lang_menu = get_language_menu (current_language, callback, user_data);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Language")));
|
|
Packit |
aa0600 |
gtk_menu_item_set_submenu (menu_item, lang_menu);
|
|
Packit |
aa0600 |
gtk_widget_show_all (GTK_WIDGET (menu_item));
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
return menu_item;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static void
|
|
Packit |
aa0600 |
activate_suggestion_cb (GtkWidget *menu_item)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
SuggestionData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
|
|
Packit |
aa0600 |
g_return_if_fail (data != NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (data->callback != NULL)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
data->callback (data->suggested_word, data->user_data);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static void
|
|
Packit |
aa0600 |
ignore_all_cb (GtkWidget *menu_item)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
SuggestionData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
|
|
Packit |
aa0600 |
g_return_if_fail (data != NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
gspell_checker_add_word_to_session (data->checker,
|
|
Packit |
aa0600 |
data->misspelled_word,
|
|
Packit |
aa0600 |
-1);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static void
|
|
Packit |
aa0600 |
add_to_dictionary_cb (GtkWidget *menu_item)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
SuggestionData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
|
|
Packit |
aa0600 |
g_return_if_fail (data != NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
gspell_checker_add_word_to_personal (data->checker,
|
|
Packit |
aa0600 |
data->misspelled_word,
|
|
Packit |
aa0600 |
-1);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
static GtkWidget *
|
|
Packit |
aa0600 |
get_suggestion_menu (GspellChecker *checker,
|
|
Packit |
aa0600 |
const gchar *misspelled_word,
|
|
Packit |
aa0600 |
GspellSuggestionActivatedCallback callback,
|
|
Packit |
aa0600 |
gpointer user_data)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GtkWidget *top_menu;
|
|
Packit |
aa0600 |
GtkWidget *menu_item;
|
|
Packit |
aa0600 |
GSList *suggestions = NULL;
|
|
Packit |
aa0600 |
SuggestionData *data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
top_menu = gtk_menu_new ();
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
suggestions = gspell_checker_get_suggestions (checker, misspelled_word, -1);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (suggestions == NULL)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
/* No suggestions. Put something in the menu anyway... */
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new_with_label (_("(no suggested words)"));
|
|
Packit |
aa0600 |
gtk_widget_set_sensitive (menu_item, FALSE);
|
|
Packit |
aa0600 |
gtk_menu_shell_prepend (GTK_MENU_SHELL (top_menu), menu_item);
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
else
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GtkWidget *menu = top_menu;
|
|
Packit |
aa0600 |
gint count = 0;
|
|
Packit |
aa0600 |
GSList *l;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
/* Build a set of menus with suggestions. */
|
|
Packit |
aa0600 |
for (l = suggestions; l != NULL; l = l->next)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
gchar *suggested_word = l->data;
|
|
Packit |
aa0600 |
GtkWidget *label;
|
|
Packit |
aa0600 |
gchar *label_text;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
if (count == 10)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
/* Separator */
|
|
Packit |
aa0600 |
menu_item = gtk_separator_menu_item_new ();
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new_with_mnemonic (_("_More…"));
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu = gtk_menu_new ();
|
|
Packit |
aa0600 |
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
|
|
Packit |
aa0600 |
count = 0;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
label_text = g_strdup_printf ("%s", suggested_word);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
label = gtk_label_new (label_text);
|
|
Packit |
aa0600 |
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
|
Packit |
aa0600 |
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new ();
|
|
Packit |
aa0600 |
gtk_container_add (GTK_CONTAINER (menu_item), label);
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_new0 (SuggestionData, 1);
|
|
Packit |
aa0600 |
data->suggested_word = g_strdup (suggested_word);
|
|
Packit |
aa0600 |
data->callback = callback;
|
|
Packit |
aa0600 |
data->user_data = user_data;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_object_set_data_full (G_OBJECT (menu_item),
|
|
Packit |
aa0600 |
SUGGESTION_DATA_KEY,
|
|
Packit |
aa0600 |
data,
|
|
Packit |
aa0600 |
suggestion_data_free);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_signal_connect (menu_item,
|
|
Packit |
aa0600 |
"activate",
|
|
Packit |
aa0600 |
G_CALLBACK (activate_suggestion_cb),
|
|
Packit |
aa0600 |
NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_free (label_text);
|
|
Packit |
aa0600 |
count++;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_slist_free_full (suggestions, g_free);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
/* Separator */
|
|
Packit |
aa0600 |
menu_item = gtk_separator_menu_item_new ();
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
/* Ignore all */
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new_with_mnemonic (_("_Ignore All"));
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_new0 (SuggestionData, 1);
|
|
Packit |
aa0600 |
data->checker = g_object_ref (checker);
|
|
Packit |
aa0600 |
data->misspelled_word = g_strdup (misspelled_word);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_object_set_data_full (G_OBJECT (menu_item),
|
|
Packit |
aa0600 |
SUGGESTION_DATA_KEY,
|
|
Packit |
aa0600 |
data,
|
|
Packit |
aa0600 |
suggestion_data_free);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_signal_connect (menu_item,
|
|
Packit |
aa0600 |
"activate",
|
|
Packit |
aa0600 |
G_CALLBACK (ignore_all_cb),
|
|
Packit |
aa0600 |
NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
/* Add to Dictionary */
|
|
Packit |
aa0600 |
menu_item = gtk_menu_item_new_with_mnemonic (_("_Add"));
|
|
Packit |
aa0600 |
gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
data = g_new0 (SuggestionData, 1);
|
|
Packit |
aa0600 |
data->checker = g_object_ref (checker);
|
|
Packit |
aa0600 |
data->misspelled_word = g_strdup (misspelled_word);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_object_set_data_full (G_OBJECT (menu_item),
|
|
Packit |
aa0600 |
SUGGESTION_DATA_KEY,
|
|
Packit |
aa0600 |
data,
|
|
Packit |
aa0600 |
suggestion_data_free);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_signal_connect (menu_item,
|
|
Packit |
aa0600 |
"activate",
|
|
Packit |
aa0600 |
G_CALLBACK (add_to_dictionary_cb),
|
|
Packit |
aa0600 |
NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
return top_menu;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
GtkMenuItem *
|
|
Packit |
aa0600 |
_gspell_context_menu_get_suggestions_menu_item (GspellChecker *checker,
|
|
Packit |
aa0600 |
const gchar *misspelled_word,
|
|
Packit |
aa0600 |
GspellSuggestionActivatedCallback callback,
|
|
Packit |
aa0600 |
gpointer user_data)
|
|
Packit |
aa0600 |
{
|
|
Packit |
aa0600 |
GtkWidget *suggestion_menu;
|
|
Packit |
aa0600 |
GtkMenuItem *menu_item;
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
g_return_val_if_fail (GSPELL_IS_CHECKER (checker), NULL);
|
|
Packit |
aa0600 |
g_return_val_if_fail (misspelled_word != NULL, NULL);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
suggestion_menu = get_suggestion_menu (checker,
|
|
Packit |
aa0600 |
misspelled_word,
|
|
Packit |
aa0600 |
callback,
|
|
Packit |
aa0600 |
user_data);
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
menu_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions…")));
|
|
Packit |
aa0600 |
gtk_menu_item_set_submenu (menu_item, suggestion_menu);
|
|
Packit |
aa0600 |
gtk_widget_show_all (GTK_WIDGET (menu_item));
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
return menu_item;
|
|
Packit |
aa0600 |
}
|
|
Packit |
aa0600 |
|
|
Packit |
aa0600 |
/* ex:set ts=8 noet: */
|