pidgin/purple-plugin-pack

Bump versions version for release
pp_2_8_0
2020-08-06, Gary Kramlich
1e6de767dd01
Bump versions version for release
/*
* Switchspell - Switch spelling language during run time.
* Copyright (C) 2007-2008
*
* 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 Street, Fifth Floor, Boston, MA
* 02111-1301, USA.
*/
/* If you can't figure out what this line is for, DON'T TOUCH IT. */
#include "../common/pp_internal.h"
#define PLUGIN_ID "gtk-plugin_pack-switchspell"
#define PLUGIN_STATIC_NAME "switchspell"
#define PLUGIN_AUTHOR "Alfredo Raul Pena (arpena)\n" \
"Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
/* Purple headers */
#include <conversation.h>
#include <debug.h>
#include <plugin.h>
/* Pidgin headers */
#include <gtkconv.h>
#include <gtkplugin.h>
#ifdef HAVE_ENCHANT
#include <enchant.h>
#else
#include <aspell.h>
#endif
#include <gtkspell/gtkspell.h>
#include <string.h>
#define PROP_LANG "switchspell::language"
static PurpleBlistNode *
blist_node_for_conv(PurpleConversation *conv)
{
PurpleBlistNode *node = NULL;
PurpleAccount *account = purple_conversation_get_account(conv);
const char *name = purple_conversation_get_name(conv);
switch (purple_conversation_get_type(conv)) {
case PURPLE_CONV_TYPE_IM:
{
PurpleBuddy *buddy = purple_find_buddy(account, name);
if (buddy)
node = (PurpleBlistNode *)purple_buddy_get_contact(buddy);
break;
}
case PURPLE_CONV_TYPE_CHAT:
node = (PurpleBlistNode *)purple_blist_find_chat(account, name);
break;
default:
break;
}
return node;
}
static void
spell_set_language(PidginConversation *gtkconv, gchar *lang)
{
GtkSpell *spell;
GError *error = NULL;
spell = gtkspell_get_from_text_view(GTK_TEXT_VIEW(gtkconv->entry));
if (spell != NULL) {
if (!gtkspell_set_language(spell, lang, &error)) {
purple_debug_error("switchspell", "failed to set language %s: %s\n", lang, error->message);
g_error_free(error);
}
}
}
static void
menu_conv_use_dict_cb(GObject *m, gpointer data)
{
PidginWindow *win = g_object_get_data(m, "user_data");
gchar *lang = g_object_get_data(m, "lang");
PurpleConversation *conv;
PidginConversation *gtkconv;
PurpleBlistNode *node;
if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(m)))
return;
conv = pidgin_conv_window_get_active_conversation(win);
gtkconv = PIDGIN_CONVERSATION(conv);
spell_set_language(gtkconv, lang);
g_object_set_data(G_OBJECT(gtkconv->entry), PROP_LANG, lang);
node = blist_node_for_conv(gtkconv->active_conv);
if (node)
purple_blist_node_set_string(node, "switchspell", lang);
}
#ifdef HAVE_ENCHANT
struct nufan
{
GSList *group;
GtkWidget *menu;
PidginWindow *win;
};
static void
enchant_dict_desc_cb(const char * const lang_tag, const char * const provider_name,
const char * const provider_desc, const char * const provider_file,
void *user_data)
{
GtkWidget *menu = ((struct nufan *)user_data)->menu;
PidginWindow *win = ((struct nufan *)user_data)->win;
GtkWidget *menuitem = gtk_radio_menu_item_new_with_label(((struct nufan *)user_data)->group, lang_tag);
((struct nufan *)user_data)->group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
g_object_set_data(G_OBJECT(menuitem), "user_data", win);
g_object_set_data_full(G_OBJECT(menuitem), "lang", g_strdup(lang_tag), g_free);
g_signal_connect(G_OBJECT(menuitem), "activate",
G_CALLBACK(menu_conv_use_dict_cb), NULL);
gtk_widget_show(menuitem);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
}
#endif
static void
regenerate_switchspell_menu(PidginConversation *gtkconv)
{
PidginWindow *win;
GtkWidget *menu;
GtkWidget *mitem;
#ifdef HAVE_ENCHANT
struct nufan user_data;
EnchantBroker *eb;
#else
GSList *group = NULL;
AspellConfig *config;
AspellDictInfoList *dlist;
AspellDictInfoEnumeration *dels;
const AspellDictInfo *entry;
#endif
if (gtkconv == NULL)
return;
win = pidgin_conv_get_window(gtkconv);
if (win == NULL)
return;
mitem = g_object_get_data(G_OBJECT(win->window), PROP_LANG);
if (mitem == NULL) {
mitem = gtk_menu_item_new_with_mnemonic(_("Spe_ll Check"));
gtk_menu_shell_insert(GTK_MENU_SHELL(win->menu.menubar), mitem, 3);
g_object_set_data(G_OBJECT(win->window), PROP_LANG, mitem);
gtk_widget_show(mitem);
}
else
return;
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), menu);
#ifdef HAVE_ENCHANT
user_data.group = NULL;
user_data.menu = menu;
user_data.win = win;
eb = enchant_broker_init();
enchant_broker_list_dicts(eb, enchant_dict_desc_cb, &user_data);
enchant_broker_free(eb);
#else
config = new_aspell_config();
dlist = get_aspell_dict_info_list(config);
delete_aspell_config(config);
dels = aspell_dict_info_list_elements(dlist);
aspell_dict_info_list_empty(dlist);
while ((entry = aspell_dict_info_enumeration_next(dels)) != 0) {
GtkWidget *menuitem = gtk_radio_menu_item_new_with_label(group, entry->name);
group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
g_object_set_data(G_OBJECT(menuitem), "user_data", win);
g_object_set_data_full(G_OBJECT(menuitem), "lang", g_strdup((gchar *)entry->name), g_free);
g_signal_connect(G_OBJECT(menuitem), "activate",
G_CALLBACK(menu_conv_use_dict_cb), NULL);
gtk_widget_show(menuitem);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
}
delete_aspell_dict_info_enumeration(dels);
#endif
gtk_widget_show_all(menu);
}
static void
update_switchspell_selection(PidginConversation *gtkconv)
{
PidginWindow *win;
GtkWidget *menu;
GList *item, *items;
char *curlang;
if (gtkconv == NULL)
return;
win = pidgin_conv_get_window(gtkconv);
if (win == NULL)
return;
/* Leave the menu alone if the tab is not the active conversation */
if (pidgin_conv_window_get_active_gtkconv(win) != gtkconv)
return;
menu = g_object_get_data(G_OBJECT(win->window), PROP_LANG);
if (menu == NULL)
return;
menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
curlang = g_strdup(g_object_get_data(G_OBJECT(gtkconv->entry), PROP_LANG));
items = gtk_container_get_children(GTK_CONTAINER(menu));
for (item = items; item; item = item->next) {
const char *lang = g_object_get_data(G_OBJECT(item->data), "lang");
if (lang && curlang && strcmp(lang, curlang) == 0) {
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item->data)))
// If menu item already selected just set current speller language
spell_set_language(gtkconv, curlang);
else
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->data), TRUE);
break;
}
}
g_list_free(items);
g_free(curlang);
}
static gboolean make_sure_gtkconv(PurpleConversation *conv);
static void
conversation_switched_cb(PurpleConversation *conv)
{
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
if (!g_object_get_data(G_OBJECT(gtkconv->entry), PROP_LANG))
make_sure_gtkconv(conv);
regenerate_switchspell_menu(gtkconv);
update_switchspell_selection(gtkconv);
}
static gboolean
make_sure_gtkconv(PurpleConversation *conv)
{
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
const char *lang = NULL;
PurpleBlistNode *node;
if (gtkconv == NULL)
return TRUE;
node = blist_node_for_conv(conv);
if (node)
lang = purple_blist_node_get_string(node, "switchspell");
g_object_set_data(G_OBJECT(gtkconv->entry), PROP_LANG, lang ? (char *)lang : getenv("LANG"));
update_switchspell_selection(gtkconv);
return FALSE;
}
static void
conversation_created_cb(PurpleConversation *conv)
{
/* Read all about it (and more!) in xmmsremote */
g_timeout_add(500, (GSourceFunc)make_sure_gtkconv, conv);
}
static void attach_switchspell_menu(gpointer data, gpointer dontcare)
{
PidginWindow *win = data;
PidginConversation *gtkconv;
gtkconv = pidgin_conv_window_get_active_gtkconv(win);
regenerate_switchspell_menu(gtkconv);
update_switchspell_selection(gtkconv);
}
static gboolean plugin_load(PurplePlugin *plugin)
{
void *conv_handle = purple_conversations_get_handle();
purple_signal_connect(conv_handle, "conversation-created", plugin,
PURPLE_CALLBACK(conversation_created_cb), NULL);
purple_signal_connect(pidgin_conversations_get_handle(), "conversation-switched",
plugin, PURPLE_CALLBACK(conversation_switched_cb), NULL);
g_list_foreach(pidgin_conv_windows_get_list(), attach_switchspell_menu, NULL);
return TRUE;
}
static void remove_switchspell_menu(gpointer data, gpointer dontcare)
{
PidginWindow *win = data;
GtkWidget *menu;
menu = g_object_get_data(G_OBJECT(win->window), PROP_LANG);
if (menu) {
gtk_widget_destroy(menu);
g_object_set_data(G_OBJECT(win->window), PROP_LANG, NULL);
}
}
static gboolean plugin_unload(PurplePlugin *plugin)
{
purple_prefs_disconnect_by_handle(plugin);
g_list_foreach(pidgin_conv_windows_get_list(), remove_switchspell_menu, NULL);
return TRUE;
}
static PurplePluginInfo info = {
PURPLE_PLUGIN_MAGIC, /* Magic */
PURPLE_MAJOR_VERSION, /* Purple Major Version */
PURPLE_MINOR_VERSION, /* Purple Minor Version */
PURPLE_PLUGIN_STANDARD, /* plugin type */
PIDGIN_PLUGIN_TYPE, /* ui requirement */
0, /* flags */
NULL, /* dependencies */
PURPLE_PRIORITY_DEFAULT, /* priority */
PLUGIN_ID, /* plugin id */
NULL, /* name */
PP_VERSION, /* version */
NULL, /* summary */
NULL, /* description */
PLUGIN_AUTHOR, /* author */
PP_WEBSITE, /* website */
plugin_load, /* load */
plugin_unload, /* unload */
NULL, /* destroy */
NULL, /* ui_info */
NULL, /* extra_info */
NULL, /* prefs_info */
NULL, /* actions */
NULL, /* reserved 1 */
NULL, /* reserved 2 */
NULL, /* reserved 3 */
NULL /* reserved 4 */
};
static void init_plugin(PurplePlugin *plugin)
{
#ifdef ENABLE_NLS
bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
#endif /* ENABLE_NLS */
info.name = _("Switch Spell");
info.summary = _("Switch Spell Checker Language");
info.description = _("Switch Spell Checker Language");
}
PURPLE_INIT_PLUGIN(switchspell, init_plugin, info)