SF.net SVN: geany-plugins: [90] trunk/spellcheck
eht16 at users.sourceforge.net
eht16 at xxxxx
Sat Jun 28 16:20:37 UTC 2008
Revision: 90
http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=90&view=rev
Author: eht16
Date: 2008-06-28 09:20:36 -0700 (Sat, 28 Jun 2008)
Log Message:
-----------
Use "populate-edit-menu" signal to add a "Spell Check" menu item to the editing menu and provide a submenu with suggestions for misspelled words and allow to add the word to the personal dictionary.
Modified Paths:
--------------
trunk/spellcheck/ChangeLog
trunk/spellcheck/src/spellcheck.c
Modified: trunk/spellcheck/ChangeLog
===================================================================
--- trunk/spellcheck/ChangeLog 2008-06-28 08:19:15 UTC (rev 89)
+++ trunk/spellcheck/ChangeLog 2008-06-28 16:20:36 UTC (rev 90)
@@ -1,3 +1,12 @@
+2008-06-28 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+
+ * src/spellcheck.c:
+ Use "populate-edit-menu" signal to add a "Spell Check" menu item to
+ the editing menu and provide a submenu with suggestions for
+ misspelled words and allow to add the word to the personal
+ dictionary.
+
+
2008-06-19 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* README, configure.in, src/Makefile.am, src/spellcheck.c:
Modified: trunk/spellcheck/src/spellcheck.c
===================================================================
--- trunk/spellcheck/src/spellcheck.c 2008-06-28 08:19:15 UTC (rev 89)
+++ trunk/spellcheck/src/spellcheck.c 2008-06-28 16:20:36 UTC (rev 90)
@@ -54,7 +54,7 @@
GeanyFunctions *geany_functions;
-PLUGIN_VERSION_CHECK(71)
+PLUGIN_VERSION_CHECK(72)
PLUGIN_SET_INFO(_("Spell Check"), _("Checks the spelling of the current document."), "0.2",
_("The Geany developer team"))
@@ -66,12 +66,28 @@
gboolean check_while_typing;
gulong signal_id;
GPtrArray *dicts;
+ GtkWidget *edit_menu;
+ GtkWidget *edit_menu_sep;
+ GtkWidget *edit_menu_sub;
EnchantBroker *broker;
EnchantDict *dict;
} SpellCheck;
static SpellCheck *sc;
+#define MAX_MENU_SUGGESTIONS 10
+typedef struct
+{
+ gint pos;
+ GeanyDocument *doc;
+ gchar *suggs[MAX_MENU_SUGGESTIONS];
+ gchar *word;
+} SpellClickInfo;
+static SpellClickInfo clickinfo;
+
+static void on_populate_edit_menu(GObject *obj, const gchar *word, gint pos,
+ GeanyDocument *doc, gpointer user_data);
+
/* Keybinding(s) */
enum
{
@@ -82,6 +98,13 @@
+PluginCallback plugin_callbacks[] =
+{
+ { "populate-edit-menu", (GCallback) &on_populate_edit_menu, FALSE, NULL },
+ { NULL, NULL, FALSE, NULL }
+};
+
+
/* currently unused */
#ifdef G_OS_WIN32
#warning TODO check Windows support
@@ -105,6 +128,140 @@
#endif
+static void clear_indicators_on_range(GeanyDocument *doc, gint start, gint len)
+{
+ g_return_if_fail(doc != NULL);
+
+ if (len > 0)
+ {
+ p_sci->send_message(doc->sci, SCI_STARTSTYLING, start, INDIC2_MASK);
+ p_sci->send_message(doc->sci, SCI_SETSTYLING, len, 0);
+ }
+}
+
+
+static void clear_indicators_on_line(GeanyDocument *doc, gint line_number)
+{
+ gint start_pos, length;
+
+ g_return_if_fail(doc != NULL);
+
+ start_pos = p_sci->get_position_from_line(doc->sci, line_number);
+ length = p_sci->get_line_length(doc->sci, line_number);
+
+ clear_indicators_on_range(doc, start_pos, length);
+}
+
+
+
+static void on_menu_suggestion_item_activate(GtkMenuItem *menuitem, gpointer gdata)
+{
+ gchar *sugg = gdata;
+ gint startword, endword;
+
+ if (clickinfo.doc == NULL || clickinfo.pos == -1)
+ {
+ g_free(sugg);
+ return;
+ }
+
+ startword = p_sci->send_message(clickinfo.doc->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
+ endword = p_sci->send_message(clickinfo.doc->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
+
+ if (startword != endword)
+ {
+ p_sci->set_selection_start(clickinfo.doc->sci, startword);
+ p_sci->set_selection_end(clickinfo.doc->sci, endword);
+ p_sci->replace_sel(clickinfo.doc->sci, sugg);
+
+ clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
+ }
+}
+
+
+static void on_menu_addword_item_activate(GtkMenuItem *menuitem, gpointer gdata)
+{
+ gint startword, endword;
+
+ if (clickinfo.doc == NULL || clickinfo.word == NULL || clickinfo.pos == -1)
+ return;
+
+ enchant_dict_add_to_pwl(sc->dict, clickinfo.word, -1);
+
+ startword = p_sci->send_message(clickinfo.doc->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
+ endword = p_sci->send_message(clickinfo.doc->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
+ if (startword != endword)
+ {
+ clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
+ }
+}
+
+
+static void on_populate_edit_menu(GObject *obj, const gchar *word, gint pos,
+ GeanyDocument *doc, gpointer user_data)
+{
+ gsize n_suggs, i;
+ gchar **tmp_suggs;
+
+ if (! NZV(word) || enchant_dict_check(sc->dict, word, -1) == 0)
+ {
+ gtk_widget_hide(sc->edit_menu);
+ gtk_widget_hide(sc->edit_menu_sep);
+ return;
+ }
+
+ tmp_suggs = enchant_dict_suggest(sc->dict, word, -1, &n_suggs);
+
+ if (tmp_suggs != NULL)
+ {
+ GtkWidget *menu_item, *image;
+ gchar *label;
+
+ clickinfo.pos = pos;
+ clickinfo.doc = doc;
+ setptr(clickinfo.word, g_strdup(word));
+
+ if (GTK_IS_WIDGET(sc->edit_menu_sub))
+ gtk_widget_destroy(sc->edit_menu_sub);
+
+ sc->edit_menu_sub = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(sc->edit_menu), sc->edit_menu_sub);
+
+ /* TODO do we need more than 10 suggestions? gtkspell offers additional suggestions
+ * in another sub menu, should we too? */
+ for (i = 0; i < MIN(n_suggs, 10); i++)
+ {
+ /* keep the suggestions in a static array for the callback function */
+ g_free(clickinfo.suggs[i]);
+ clickinfo.suggs[i] = g_strdup(tmp_suggs[i]);
+
+ menu_item = gtk_menu_item_new_with_label(clickinfo.suggs[i]);
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+ g_signal_connect((gpointer) menu_item, "activate",
+ G_CALLBACK(on_menu_suggestion_item_activate), clickinfo.suggs[i]);
+ }
+ menu_item = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+
+ image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+
+ label = g_strdup_printf(_("Add \"%s\" to Dictionary"), word);
+ menu_item = gtk_image_menu_item_new_with_label(label);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+ g_signal_connect((gpointer) menu_item, "activate",
+ G_CALLBACK(on_menu_addword_item_activate), NULL);
+
+ gtk_widget_show(sc->edit_menu);
+ gtk_widget_show(sc->edit_menu_sep);
+ gtk_widget_show_all(sc->edit_menu_sub);
+
+ enchant_dict_free_string_list(sc->dict, tmp_suggs);
+ g_free(label);
+ }
+}
+
+
static void dict_describe(const gchar* const lang, const gchar* const name,
const gchar* const desc, const gchar* const file, void *target)
{
@@ -248,22 +405,6 @@
}
-static void clear_indicators_on_line(GeanyDocument *doc, gint line_number)
-{
- glong start_pos, length;
-
- g_return_if_fail(doc != NULL);
-
- start_pos = p_sci->get_position_from_line(doc->sci, line_number);
- length = p_sci->get_line_length(doc->sci, line_number);
- if (length > 0)
- {
- p_sci->send_message(doc->sci, SCI_STARTSTYLING, start_pos, INDIC2_MASK);
- p_sci->send_message(doc->sci, SCI_SETSTYLING, length, 0);
- }
-}
-
-
/* Checks only the last word before the current cursor position -> check as you type. */
static gboolean on_key_release(GtkWidget *widget, GdkEventKey *ev, gpointer user_data)
{
@@ -458,6 +599,20 @@
}
+static void create_edit_menu()
+{
+ sc->edit_menu = gtk_image_menu_item_new_from_stock(GTK_STOCK_SPELL_CHECK, NULL);
+ gtk_container_add(GTK_CONTAINER(main_widgets->editor_menu), sc->edit_menu);
+ gtk_menu_reorder_child(GTK_MENU(main_widgets->editor_menu), sc->edit_menu, 0);
+
+ sc->edit_menu_sep = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(main_widgets->editor_menu), sc->edit_menu_sep);
+ gtk_menu_reorder_child(GTK_MENU(main_widgets->editor_menu), sc->edit_menu_sep, 1);
+
+ gtk_widget_show_all(sc->edit_menu);
+}
+
+
static GtkWidget *create_menu()
{
GtkWidget *sp_item, *menu, *subitem;
@@ -494,6 +649,7 @@
{
GtkWidget *sp_item;
GKeyFile *config = g_key_file_new();
+ guint i;
sc = g_new0(SpellCheck, 1);
@@ -517,8 +673,15 @@
return;
}
+ for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
+ {
+ clickinfo.suggs[i] = NULL;
+ }
+ clickinfo.word = NULL;
+
create_dicts_array();
+ create_edit_menu();
sp_item = create_menu();
gtk_widget_show_all(sp_item);
@@ -578,6 +741,11 @@
void plugin_cleanup(void)
{
guint i;
+ for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
+ {
+ clickinfo.suggs[i] = NULL;
+ }
+ g_free(clickinfo.word);
for (i = 0; i < sc->dicts->len; i++)
{
g_free(g_ptr_array_index(sc->dicts, i));
@@ -586,6 +754,9 @@
g_signal_handler_disconnect(main_widgets->window, sc->signal_id);
+ gtk_widget_destroy(sc->edit_menu);
+ gtk_widget_destroy(sc->edit_menu_sep);
+
enchant_broker_free_dict(sc->broker, sc->dict);
enchant_broker_free(sc->broker);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Plugins-Commits
mailing list