pidgin-latex plugin
Florian Schmidt
mista.tapas at gmx.net
Tue Apr 10 20:34:04 EDT 2007
Hi,
with the help of the #pidgin irc channel i have tried to write a pidgin latex
plugin [1][2], because the olde one wouldn't compile for me. I have mostly
succeeded, but there's some problems left..
The plugin (or some part of pidgin) segfaults with bigger equations like i.e.
$$ \begin{pmatrix} \num{0,88} & \num{0,15} & \num{0,06} \\
\num{0,06} & \num{0,80} & \num{0,04} \\ \num{0,06} & \num{0,05} &
\num{0,90} \end{pmatrix}^2 \cdot \begin{pmatrix} 100 \\ 0 \\ 0\\
\end{pmatrix} = \begin{pmatrix} \num{78.7}\\ \num{10.32}\\
\num{10.98}\end{pmatrix}$$
Similar to the kopete plugin i use latex and imagemagick to produce the output
graphics and then use gaim_imgstore_add () to add the produced image so it's
available in the gtkconv window (i need to filter some "<br>"s and "amp;"s
from the input buffer provided by pidgin too with the help of sed in the
shell script).
I'm not 100% sure i have got the search and replace right (C - not the best
language for text processing). My debugging skills are limited with gtk apps
(i use the ubuntu gtk/gaim/etc packages, so they kinda lack symbols, too)..
So if someone would like to look it over (it's only a few pages of C
altogether)..
As the segfaults seem to depend on the size of the rendered math i am kinda
stumped though..
Another problem is that right now the pid is not postfixed to the tempfile
names, so different users on the same machine might conflict (they also need
to get deleted after being loaded)
It would be nice to have a config dialog, etc.. Patches welcome :)
A cosmetic thing would be to have the latex code get into the clipboard when
selecting the image in the msg window.. Any hints?
Thanks for any tips and regards,
Flo
[1] http://tapas.affenbande.org/wordpress/?page_id=70
[2] http://tapas.affenbande.org/pidgin-latex.tgz
Here's the [short] code for reference:
/*
Copyright (C) 2004 Florian Schmidt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define GAIM_PLUGINS
#include <glib.h>
#include "notify.h"
#include "plugin.h"
#include "version.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int latex_to_image_id (gchar *text)
{
//printf("latex_to_image %s\n", text);
gint stdin, stdout, stderr;
GPid pid;
gchar *argv[2];
gchar *argv0 = "pidgin-latex-convert.sh";
gchar *argv1 = 0;
GError *error = 0;
argv[0] = argv0;
argv[1] = argv1;
if (!g_spawn_async_with_pipes ("/", argv, 0, G_SPAWN_DO_NOT_REAP_CHILD|
G_SPAWN_SEARCH_PATH, 0, 0, &pid, &stdin, &stdout, &stderr, &error))
{
gaim_notify_error (NULL, NULL, "error executing script", NULL);
return -1;
}
char *filedata;
size_t size;
int id;
write (stdin, text, strlen(text));
close (stdin);
waitpid (pid, 0, 0);
//sleep (1);
g_spawn_close_pid(pid);
if (!g_file_get_contents("/tmp/pidgin-latex-tmp.jpg", &filedata,
&size, &error)) {
gaim_notify_error(NULL, NULL, error->message, NULL);
g_error_free(error);
return -1;
}
id = gaim_imgstore_add(filedata, size, "pidgin-latex-tmp.jpg");
return id;
}
static gboolean displaying_msg_cb (GaimAccount *account, const char *who, char
**buffer, GaimConversation *conv, GaimMessageFlags flags, void *data)
{
// the plan:
// 1] iterate over the message to find $$[text]$$ combinations
//printf ("%s\n", *buffer);
// 2] for each of these produce an image [by calling pidgin-latex-convert.sh
// and feeding teh latex code as stdin. it will write a file
// /tmp/pidgin-latex-tmp.jpg
// 3] load image and aquire index
// 4] replace occurence in text with <IMG ID=..> tag
// 5] profit
gchar *newbuffer = malloc(1);
strcpy (newbuffer, "");
gchar *tmpbuffer;
int length = strlen (*buffer);
gchar *pos = *buffer;
gchar *dollarpos1 = *buffer;
gchar *dollarpos2 = *buffer;
while (1)
{
// find first $$ in rest of string
dollarpos1 = g_strstr_len (pos, strlen(pos), "$$");
if (dollarpos1 == NULL)
{
//printf ("no dollar\n");
// copy rest of buffer to new buffer and be done
tmpbuffer = newbuffer;
newbuffer = g_strconcat (newbuffer, pos, 0);
free (tmpbuffer);
//printf("newbuffer: %s\n", newbuffer);
break;
}
else // a "$$" ha been found
{
//printf ("dollar %s\n", dollarpos1);
// find second $$
dollarpos2 = g_strstr_len (dollarpos1 + 2, strlen(dollarpos1 + 2), "$$");
if (dollarpos2 == NULL) // no match
{
//printf ("no second dollar\n");
// copy string and be done
tmpbuffer = newbuffer;
newbuffer = g_strconcat (newbuffer, pos, 0);
free(tmpbuffer);
//printf("newbuffer: %s\n", newbuffer);
break;
}
else //match
{
//printf ("second dollar\n");
gchar *tmpbuffer2 = (gchar *)malloc(1 + dollarpos1 - pos);
strncpy (tmpbuffer2, pos, dollarpos1 - pos);
tmpbuffer2[dollarpos1 - pos] = 0;
tmpbuffer = newbuffer;
newbuffer = g_strconcat (newbuffer, tmpbuffer2, 0);
free(tmpbuffer);
free(tmpbuffer2);
//printf("newbuffer: %s\n", newbuffer);
tmpbuffer = (gchar*)malloc(1 + dollarpos2 - dollarpos1);
strncpy (tmpbuffer, dollarpos1, 2 + dollarpos2 - dollarpos1);
tmpbuffer[2 + dollarpos2 - dollarpos1] = 0;
int id = latex_to_image_id (tmpbuffer);
if (id == -1)
{
//printf("Something went wrong creating the image\n");
// oh oh, need to cleanup, not leak memory ;)
return FALSE;
}
free(tmpbuffer);
// ok we have the id now. so let's replace the text by concatenating our
new buffer with "<IMG ID=" the id and ">"
gchar *tagbuffer = malloc(100);
sprintf (tagbuffer, "<IMG ID=%i>", id);
tmpbuffer = newbuffer;
newbuffer = g_strconcat (newbuffer, tagbuffer, 0);
//printf("newbuffer: %s\n", newbuffer);
free (tmpbuffer);
free (tagbuffer);
pos = dollarpos2 + 2;
}
}
}
tmpbuffer = *buffer;
*buffer = newbuffer;
free (tmpbuffer);
return FALSE;
}
static gboolean
plugin_load(GaimPlugin *plugin)
{
void *conversation = (void *)gaim_gtk_conversations_get_handle();
gaim_signal_connect(conversation, "displaying-im-msg", plugin,
GAIM_CALLBACK(displaying_msg_cb), NULL);
gaim_signal_connect(conversation, "displaying-chat-msg", plugin,
GAIM_CALLBACK(displaying_msg_cb), NULL);
return TRUE;
}
//struct GaimGtkPluginUiInfo ui_info;
static GaimPluginInfo info =
{
GAIM_PLUGIN_MAGIC,
GAIM_MAJOR_VERSION,
GAIM_MINOR_VERSION,
GAIM_PLUGIN_STANDARD,
NULL,
0,
NULL,
GAIM_PRIORITY_DEFAULT,
"pidgin-latex",
"LaTeX",
"1.0",
"Pidgin LaTeX Plugin",
"A simple plugin for displaying latex math in the chat window",
"Florian Paul Schmidt (mista.tapas at gmx.net)",
"http://tapas.affenbande.org",
plugin_load,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void init_plugin(GaimPlugin *plugin)
{
}
GAIM_INIT_PLUGIN(hello_world, init_plugin, info);
--
Palimm Palimm!
http://tapas.affenbande.org
More information about the Devel
mailing list