changeset 12061:29dc8fc0dd6c

[gaim-migrate @ 14356] SF Patch #1351190 from Michael Hearn "This allows Linux binaries of Gaim to operate even when GTKspell is not available at runtime. Useful for the autopackages." I made a number of changes to this, so blame me first if it's busted. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Sun, 13 Nov 2005 00:19:12 +0000
parents f7d2f637ff03
children 4ccd528ffe6e
files COPYRIGHT ChangeLog configure.ac plugins/ChangeLog.API src/Makefile.am src/gtkconv.c src/gtkdialogs.c src/gtkprefs.c src/gtkrequest.c src/gtkutils.c src/gtkutils.h
diffstat 11 files changed, 134 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Nov 13 00:05:44 2005 +0000
+++ b/COPYRIGHT	Sun Nov 13 00:19:12 2005 +0000
@@ -103,6 +103,7 @@
 Andrew Hart (arhart)
 G. Sumner Hayes
 Michael R. Head
+Michael Hearn
 Mike Heffner
 Benjamin Herrenschmidt
 Fernando Herrera
--- a/ChangeLog	Sun Nov 13 00:05:44 2005 +0000
+++ b/ChangeLog	Sun Nov 13 00:19:12 2005 +0000
@@ -110,6 +110,7 @@
 	* GNOME users can open received files by clicking on "Open" in the
 	  file transfer window
 	* Mouse-over hyperlink coloring is now themeable
+	* GtkSpell is now loaded dynamically at runtime (Michael Hearn)
 
 	Preference Changes:
 	* Preferences have been substantially reorganized and cleaned up
--- a/configure.ac	Sun Nov 13 00:05:44 2005 +0000
+++ b/configure.ac	Sun Nov 13 00:19:12 2005 +0000
@@ -1280,7 +1280,6 @@
 	PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, , enable_gtkspell=no)
 	if test "$enable_gtkspell" = "yes" ; then
 		AC_SUBST(GTKSPELL_CFLAGS)
-		AC_SUBST(GTKSPELL_LIBS)
 		AC_DEFINE(USE_GTKSPELL,,[do we have gtkspell?])
 	fi
 fi
--- a/plugins/ChangeLog.API	Sun Nov 13 00:05:44 2005 +0000
+++ b/plugins/ChangeLog.API	Sun Nov 13 00:19:12 2005 +0000
@@ -143,6 +143,8 @@
 	  a visibility manager - see the docs for more information
 	* gaim_gtk_conversations_get_first_unseen() to find the first conv
 	  with an "unseen" state >= to the specified state
+	* gaim_gtk_gtkspell_is_available()
+	* gaim_gtk_gtkspell_unsetup()
 
 	Signals - Changed:
 	* "received-im-msg" and "received-chat-msg" to match, both now pass a
--- a/src/Makefile.am	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/Makefile.am	Sun Nov 13 00:19:12 2005 +0000
@@ -352,7 +352,6 @@
 	$(XSS_LIBS) \
 	$(SM_LIBS) \
 	$(INTLLIBS) \
-	$(GTKSPELL_LIBS) \
 	$(STARTUP_NOTIFICATION_LIBS) \
 	$(VV_LIBS) \
 	$(MS_LIBS)
--- a/src/gtkconv.c	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkconv.c	Sun Nov 13 00:19:12 2005 +0000
@@ -5425,11 +5425,9 @@
 		gtkconv = GAIM_GTK_CONVERSATION(conv);
 
 		if (value)
-			gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(gtkconv->entry));
-		else {
-			spell = gtkspell_get_from_text_view(GTK_TEXT_VIEW(gtkconv->entry));
-			gtkspell_detach(spell);
-		}
+			gaim_gtk_gtkspell_setup(GTK_TEXT_VIEW(gtkconv->entry));
+		else
+			gaim_gtk_gtkspell_unsetup(GTK_TEXT_VIEW(gtkconv->entry));
 	}
 #endif
 }
--- a/src/gtkdialogs.c	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkdialogs.c	Sun Nov 13 00:19:12 2005 +0000
@@ -370,9 +370,12 @@
 #endif
 
 #ifdef USE_GTKSPELL
-	g_string_append(str, "    <b>GtkSpell:</b> Enabled<br/>");
+	if (gaim_gtk_gtkspell_is_available())
+		g_string_append(str, "    <b>GtkSpell:</b> Enabled<br/>");
+	else
+		g_string_append(str, "    <b>GtkSpell:</b> Disabled (Library Not Found)<br/>");
 #else
-	g_string_append(str, "    <b>GtkSpell:</b> Disabled<br/>");
+	g_string_append(str, "    <b>GtkSpell:</b> Disabled (Not Compiled)<br/>");
 #endif
 
 #ifdef HAVE_GNUTLS
--- a/src/gtkprefs.c	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkprefs.c	Sun Nov 13 00:19:12 2005 +0000
@@ -798,6 +798,7 @@
 	GtkWidget *vbox2;
 	GtkWidget *iconpref1;
 	GtkWidget *iconpref2;
+	GtkWidget *spellpref;
 
 	ret = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
 	gtk_container_set_border_width(GTK_CONTAINER(ret), GAIM_HIG_BORDER);
@@ -820,10 +821,21 @@
 
 	gaim_gtk_prefs_checkbox(_("_Notify buddies that you are typing to them"),
 			"/core/conversations/im/send_typing", vbox);
-#ifdef USE_GTKSPELL
-	gaim_gtk_prefs_checkbox(_("_Highlight misspelled words"),
-			"/gaim/gtk/conversations/spellcheck", vbox);
-#endif
+	
+	spellpref = gaim_gtk_prefs_checkbox(_("_Highlight misspelled words"),
+					    "/gaim/gtk/conversations/spellcheck", vbox);
+	
+	if (!gaim_gtk_gtkspell_is_available())
+	{
+		gboolean gtkspell_enabled = gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck");
+
+		gtk_widget_set_sensitive(spellpref, FALSE);
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spellpref), FALSE);
+
+		/* Preserve the preference. If the user had it enabled, we want it to
+		 * stay enabled if they install gtkspell again. */
+		gaim_prefs_set_bool("/gaim/gtk/conversations/spellcheck", gtkspell_enabled);
+	}
 
 	frame = gaim_gtk_create_imhtml(TRUE, &imhtml, &toolbar);
 	gtk_widget_set_name(imhtml, "gaim_gtkprefs_font_imhtml");
--- a/src/gtkrequest.c	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkrequest.c	Sun Nov 13 00:19:12 2005 +0000
@@ -398,7 +398,7 @@
 			gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
 
 			if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck"))
-				gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(entry));
+				gaim_gtk_gtkspell_setup(GTK_TEXT_VIEW(entry));
 
 			gtk_container_add(GTK_CONTAINER(sw), entry);
 		}
@@ -1085,7 +1085,7 @@
 									GTK_WRAP_WORD_CHAR);
 
 		if (gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck"))
-			gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(textview));
+			gaim_gtk_gtkspell_setup(GTK_TEXT_VIEW(textview));
 
 		gtk_container_add(GTK_CONTAINER(widget), textview);
 		gtk_widget_show(textview);
--- a/src/gtkutils.c	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkutils.c	Sun Nov 13 00:19:12 2005 +0000
@@ -147,7 +147,7 @@
 	gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), GTK_IMHTML_ALL ^ GTK_IMHTML_IMAGE);
 	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR);
 	if (editable && gaim_prefs_get_bool("/gaim/gtk/conversations/spellcheck"))
-		gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(imhtml));
+		gaim_gtk_gtkspell_setup(GTK_TEXT_VIEW(imhtml));
 	gtk_widget_show(imhtml);
 
 	if (editable) {
@@ -897,25 +897,102 @@
 	return buf;
 }
 
+#ifdef USE_GTKSPELL
+static GtkSpell* (*gtkspell_get_from_text_view_ptr)(GtkTextView *view);
+static void (*gtkspell_detach_ptr)(GtkSpell *spell);
+static GtkSpell* (*gtkspell_new_attach_ptr)(GtkTextView *view, const gchar *lang, GError **error);
+static int gtkspell_available = -1; /* -1 unknown, 0 false, 1 true */
+
+static void
+setup_gtkspell()
+{
+#if GLIB_CHECK_VERSION(2,3,3)
+	GModule *handle = g_module_open("libgtkspell", G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+#else
+	GModule *handle = g_module_open("libgtkspell", G_MODULE_BIND_LAZY);
+#endif
+	if (handle != NULL)
+	{
+		gpointer ptr; /* squash GCC strict aliasing warnings */
+
+		g_module_symbol(handle, "gtkspell_new_attach", &ptr);
+		gtkspell_new_attach_ptr = ptr;
+
+		g_module_symbol(handle, "gtkspell_detach", &ptr);
+		gtkspell_detach_ptr = ptr;
+
+		g_module_symbol(handle, "gtkspell_get_from_text_view", &ptr);
+		gtkspell_get_from_text_view_ptr = ptr;
+
+		gtkspell_available = TRUE;
+	}
+	else
+	{
+		gaim_debug_warning("gtkspell", "Failed to load libgtkspell.so.0: %s\n", dlerror());
+		gtkspell_available = FALSE;
+	}
+}
+
+gboolean
+gaim_gtk_gtkspell_is_available()
+{
+	if (gtkspell_available == -1)
+		setup_gtkspell();
+
+	return gtkspell_available;
+}
+
 void
-gaim_gtk_setup_gtkspell(GtkTextView *textview)
+gaim_gtk_gtkspell_setup(GtkTextView *textview)
 {
-#ifdef USE_GTKSPELL
 	GError *error = NULL;
 	char *locale = NULL;
 
 	g_return_if_fail(textview != NULL);
 	g_return_if_fail(GTK_IS_TEXT_VIEW(textview));
 
-	if (gtkspell_new_attach(textview, locale, &error) == NULL && error)
+	if (!gaim_gtk_gtkspell_is_available())
+		return;
+
+	if (gtkspell_new_attach_ptr(textview, locale, &error) == NULL && error)
 	{
-		gaim_debug_warning("gtkspell", "Failed to setup GtkSpell: %s\n",
-						   error->message);
+		gaim_debug_warning("gtkspell", "Failed to setup GtkSpell: %s\n", error->message);
 		g_error_free(error);
 	}
-#endif /* USE_GTKSPELL */
+}
+
+void
+gaim_gtk_gtkspell_unsetup(GtkTextView *textview)
+{
+	GtkSpell *spell;
+
+	if (!gtkspell_available)
+		return;
+
+	spell = gtkspell_get_from_text_view_ptr(textview);
+	gtkspell_detach_ptr(spell);
 }
 
+#else  /* !USE_GTKSPELL */
+
+gboolean
+gaim_gtk_gtkspell_is_available()
+{
+	return FALSE;
+}
+
+void
+gaim_gtk_gtkspell_setup(GtkTextView *textview)
+{
+}
+
+void
+gaim_gtk_gtkspell_unsetup(GtkTextView *textview)
+{
+}
+
+#endif /* !USE_GTKSPELL */
+
 void
 gaim_gtk_save_accels_cb(GtkAccelGroup *accel_group, guint arg1,
 														 GdkModifierType arg2, GClosure *arg3,
--- a/src/gtkutils.h	Sun Nov 13 00:05:44 2005 +0000
+++ b/src/gtkutils.h	Sun Nov 13 00:19:12 2005 +0000
@@ -259,14 +259,32 @@
 gboolean gaim_gtk_check_if_dir(const char *path, GtkFileSelection *filesel);
 
 /**
+ * Returns @c TRUE if Gaim was compiled with GtkSpell support and the
+ * library is available at runtime.
+ */
+gboolean gaim_gtk_gtkspell_is_available();
+
+/**
  * Sets up GtkSpell for the given GtkTextView, reporting errors
  * if encountered.
  *
- * This does nothing if Gaim is not compiled with GtkSpell support.
+ * This does nothing if Gaim is not compiled with GtkSpell support, or
+ * the GtkSpell library cannot be located at runtime.
  *
  * @param textview The textview widget to setup spellchecking for.
  */
-void gaim_gtk_setup_gtkspell(GtkTextView *textview);
+void gaim_gtk_gtkspell_setup(GtkTextView *textview);
+
+/**
+ * Does the inverse of gaim_gtk_setup_gtkspell, detaching the spelling
+ * checker from the text view widget.
+ *
+ * This does nothing if Gaim is not compiled with GtkSpell support, or
+ * the GtkSpell library cannot be located at runtime.
+ *
+ * @param textview The textview widget to unsetup spellchecking for.
+ */
+void gaim_gtk_gtkspell_unsetup(GtkTextView *textview);
 
 /**
  * Stylizes the specified text using HTML, according to the current