soc.2008.finch: 0b25c9dd: Added language switching context menu fo...
queueram at soc.pidgin.im
queueram at soc.pidgin.im
Thu Jun 5 04:05:39 EDT 2008
-----------------------------------------------------------------
Revision: 0b25c9dd3deaa5c16f7deff33c36af4812f2629a
Ancestor: 92a7c4f80e36250a33f90ff4a44cf0fb83941995
Author: queueram at soc.pidgin.im
Date: 2008-06-05T08:01:17
Branch: im.pidgin.soc.2008.finch
URL: http://d.pidgin.im/viewmtn/revision/info/0b25c9dd3deaa5c16f7deff33c36af4812f2629a
Modified files:
finch/libgnt/gntentry.c finch/libgnt/gntentry.h
ChangeLog:
Added language switching context menu for GntEntry spell checking.
Added public API for setting the spell checking language.
-------------- next part --------------
============================================================
--- finch/libgnt/gntentry.c a2c56a5d83f1b68e732f2a28fd938d491926ab87
+++ finch/libgnt/gntentry.c 46e5f2ae535628dfb6fdf2b465e5fbc173c6739b
@@ -31,6 +31,9 @@
#include "gntstyle.h"
#include "gnttree.h"
#include "gntutils.h"
+#include "gntmenu.h"
+#include "gntmenuitem.h"
+#include "gntmenuitemcheck.h"
#ifdef USE_ENCHANT
#include <enchant/enchant.h>
@@ -66,6 +69,7 @@ struct _GntEntrySpell
EnchantBroker *broker;
EnchantDict *dict;
#endif
+ char *lang;
gboolean enable;
};
@@ -1119,12 +1123,35 @@ new_killring(void)
return kr;
}
+#ifdef USE_ENCHANT
+static void
+set_spell_language(GntEntrySpell *spell, const char *lang)
+{
+ const char *err;
+
+ if(spell->broker) {
+ if(spell->dict)
+ enchant_broker_free_dict(spell->broker, spell->dict);
+
+ spell->dict = enchant_broker_request_dict(spell->broker, lang);
+
+ if (spell->dict == NULL) {
+ err = enchant_broker_get_error(spell->broker);
+ if(err != NULL) {
+ g_warning("GntEntry: couldn't get dictionary for %s: %s\n", lang, err);
+ } else {
+ g_warning("GntEntry: couldn't get dictionary for %s\n", lang);
+ }
+ }
+ }
+}
+#endif
+
static GntEntrySpell *
new_spell(void)
{
GntEntrySpell *sp = NULL;
#ifdef USE_ENCHANT
- const char *err;
const char *lang;
sp = g_new0(GntEntrySpell, 1);
@@ -1144,22 +1171,144 @@ new_spell(void)
lang = "en";
}
- sp->dict = enchant_broker_request_dict(sp->broker, lang);
-
- if (sp->dict == NULL) {
- err = enchant_broker_get_error(sp->broker);
- if(err != NULL) {
- g_warning("GntEntry: couldn't get dictionary for %s: %s\n", lang, err);
- } else {
- g_warning("GntEntry: couldn't get dictionary for %s\n", lang);
- }
- }
+ set_spell_language(sp, lang);
}
#endif
return sp;
}
+
+#ifdef USE_ENCHANT
+typedef struct {
+ GntEntry *entry;
+ GntMenu *sub;
+ char *lang;
+} SpellLangInfo;
+
static void
+destroy_spell_lang_info(GntWidget *widget, SpellLangInfo *sli)
+{
+ g_free(sli->lang);
+ g_free(sli);
+}
+
+static void
+context_menu_callback(GntMenuItem *item, gpointer data)
+{
+ SpellLangInfo *cur_info = (SpellLangInfo *)data;
+ if(cur_info->entry->spell) {
+ set_spell_language(cur_info->entry->spell, cur_info->lang);
+ entry_redraw(GNT_WIDGET(cur_info->entry));
+ }
+}
+
+/* callback called from enchant enchant_broker_list_dicts
+ * user_data is a (SpellLangInfo *) */
+static void
+add_lang_context(const char * const lang, const char * const name,
+ const char * const desc, const char * const file, void * user_data)
+{
+ SpellLangInfo *cur_info = (SpellLangInfo *)user_data;
+ GntMenuItem *item;
+ SpellLangInfo *spell_info = g_new(SpellLangInfo, 1);
+
+ spell_info->entry = cur_info->entry;
+ spell_info->sub = cur_info->sub;
+ spell_info->lang = g_strdup(lang);
+ /* this destroy callback will handle the spell_info and spell_info->lang frees */
+ g_signal_connect(G_OBJECT(cur_info->sub), "destroy", G_CALLBACK(destroy_spell_lang_info), spell_info);
+
+ item = gnt_menuitem_check_new(lang);
+ if(strcmp(lang, cur_info->lang) == 0)
+ gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), TRUE);
+ gnt_menu_add_item(GNT_MENU(spell_info->sub), GNT_MENU_ITEM(item));
+ gnt_menuitem_set_callback(item, context_menu_callback, (void*)spell_info);
+}
+
+/* callback called from enchant enchant_dict_describe
+ * user_data is a (char **)
+ * the ret_lang is freed in the create_spell_menu function */
+static void
+get_cur_lang(const char * const lang, const char * const name,
+ const char * const desc, const char * const file, void * user_data)
+{
+ char **ret_lang = (char **)user_data;
+ *ret_lang = g_strdup(lang);
+}
+
+static void
+create_spell_menu(GntMenu *menu, GntEntry *entry)
+{
+ GntMenuItem *item;
+ GntWidget *sub;
+ SpellLangInfo cur_info;
+
+ if(entry->spell && entry->spell->broker) {
+ /* create languages menu */
+ item = gnt_menuitem_new("Set Language");
+ gnt_menu_add_item(GNT_MENU(menu), GNT_MENU_ITEM(item));
+ sub = gnt_menu_new(GNT_MENU_POPUP);
+ gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+
+ cur_info.entry = entry;
+ cur_info.sub = GNT_MENU(sub);
+ /* get the current language */
+ if(entry->spell->dict)
+ enchant_dict_describe(entry->spell->dict, get_cur_lang, (void *)&(cur_info.lang));
+
+ enchant_broker_list_dicts(entry->spell->broker, add_lang_context, (void *)&cur_info);
+
+ g_free(cur_info.lang);
+ }
+}
+
+static void
+context_menu_destroyed(GntWidget *widget, GntEntry *entry)
+{
+ /* XXX: definite possible leak */
+ entry->context = NULL;
+}
+
+static void
+draw_context_menu(GntEntry *entry)
+{
+ GntWidget *context = NULL;
+ int x, y, width;
+
+ if (entry->context)
+ return;
+
+ entry->context = context = gnt_menu_new(GNT_MENU_POPUP);
+ /*
+ g_signal_connect(G_OBJECT(context), "destroy", G_CALLBACK(context_menu_destroyed), entry);
+ g_signal_connect(G_OBJECT(context), "hide", G_CALLBACK(gnt_widget_destroy), NULL);
+ */
+ g_signal_connect(G_OBJECT(context), "hide", G_CALLBACK(context_menu_destroyed), entry);
+
+ create_spell_menu(GNT_MENU(context), entry);
+
+ /* TODO: check if we are currently on a misspelled word and if so, generate a list of suggestions */
+
+ /* Set the position for the popup */
+ gnt_widget_get_position(GNT_WIDGET(entry), &x, &y);
+ gnt_widget_get_size(GNT_WIDGET(entry), &width, NULL);
+
+ x += entry->cursor - entry->scroll;
+ y += 1;
+
+ gnt_widget_set_position(context, x, y);
+ gnt_screen_menu_show(GNT_MENU(context));
+}
+
+static gboolean
+context_menu(GntWidget *widget, GntEntry *entry)
+{
+ draw_context_menu(entry);
+ return TRUE;
+}
+#endif
+
+static void
gnt_entry_init(GTypeInstance *instance, gpointer class)
{
GntWidget *widget = GNT_WIDGET(instance);
@@ -1184,6 +1333,10 @@ gnt_entry_init(GTypeInstance *instance,
widget->priv.minw = 3;
widget->priv.minh = 1;
+#ifdef USE_ENCHANT
+ g_signal_connect(G_OBJECT(entry), "context-menu", G_CALLBACK(context_menu), entry);
+#endif
+
GNTDEBUG;
}
@@ -1375,6 +1528,17 @@ void gnt_entry_set_spell_enable(GntEntry
}
}
+void gnt_entry_set_spell_lang(GntEntry *entry, const char *lang)
+{
+#ifdef USE_ENCHANT
+ if(entry->spell) {
+ if(strcmp(lang, entry->spell->lang) != 0) {
+ set_spell_language(entry->spell, lang);
+ }
+ }
+#endif
+}
+
void gnt_entry_add_suggest(GntEntry *entry, const char *text)
{
GList *find;
============================================================
--- finch/libgnt/gntentry.h 46cb5604468a05802f56d35525e1321d6a64a50e
+++ finch/libgnt/gntentry.h 53a6ca6b5281ca65251d575cce934d36a6ae6fb3
@@ -88,6 +88,7 @@ struct _GntEntry
GntWidget *ddown; /* The dropdown with the suggested list */
GntEntryKillRing *killring; /**< @since 2.3.0 */
GntEntrySpell *spell; /**< holds Enchant info for spell checking */
+ GntWidget *context; /**< Context menu for spelling */
};
struct _GntEntryClass
@@ -224,6 +225,14 @@ void gnt_entry_set_spell_enable(GntEntry
*/
void gnt_entry_set_spell_enable(GntEntry *entry, gboolean enable);
+/**
+ * Set the language to use for spell checking
+ *
+ * @param entry The entry box.
+ * @param lang The string-encoded language to use for spell checking
+ */
+void gnt_entry_set_spell_lang(GntEntry *entry, const char *lang);
+
G_END_DECLS
#endif /* GNT_ENTRY_H */
More information about the Commits
mailing list