/* X-Chat * Copyright (C) 2002 Peter Zelezny. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #ifdef WIN32 #include #else #include #endif #include "hexchat.h" #include "fe.h" #include "util.h" #include "outbound.h" #include "cfgfiles.h" #include "ignore.h" #include "server.h" #include "servlist.h" #include "modes.h" #include "notify.h" #include "text.h" #define PLUGIN_C typedef struct session hexchat_context; #include "hexchat-plugin.h" #include "plugin.h" #include "typedef.h" #include "hexchatc.h" /* the USE_PLUGIN define only removes libdl stuff */ #ifdef USE_PLUGIN #ifdef USE_GMODULE #include #else #include #endif #endif #define DEBUG(x) {x;} /* crafted to be an even 32 bytes */ struct _hexchat_hook { hexchat_plugin *pl; /* the plugin to which it belongs */ char *name; /* "xdcc" */ void *callback; /* pointer to xdcc_callback */ char *help_text; /* help_text for commands only */ void *userdata; /* passed to the callback */ int tag; /* for timers & FDs only */ int type; /* HOOK_* */ int pri; /* fd */ /* priority / fd for HOOK_FD only */ }; struct _hexchat_list { int type; /* LIST_* */ GSList *pos; /* current pos */ GSList *next; /* next pos */ GSList *head; /* for LIST_USERS only */ struct notify_per_server *notifyps; /* notify_per_server * */ }; typedef int (hexchat_cmd_cb) (char *word[], char *word_eol[], void *user_data); typedef int (hexchat_serv_cb) (char *word[], char *word_eol[], void *user_data); typedef int (hexchat_print_cb) (char *word[], void *user_data); typedef int (hexchat_fd_cb) (int fd, int flags, void *user_data); typedef int (hexchat_timer_cb) (void *user_data); typedef int (hexchat_init_func) (hexchat_plugin *, char **, char **, char **, char *); typedef int (hexchat_deinit_func) (hexchat_plugin *); enum { LIST_CHANNELS, LIST_DCC, LIST_IGNORE, LIST_NOTIFY, LIST_USERS }; enum { HOOK_COMMAND, /* /command */ HOOK_SERVER, /* PRIVMSG, NOTICE, numerics */ HOOK_PRINT, /* All print events */ HOOK_TIMER, /* timeouts */ HOOK_FD, /* sockets & fds */ HOOK_DELETED /* marked for deletion */ }; GSList *plugin_list = NULL; /* export for plugingui.c */ static GSList *hook_list = NULL; extern const struct prefs vars[]; /* cfgfiles.c */ /* unload a plugin and remove it from our linked list */ static int plugin_free (hexchat_plugin *pl, int do_deinit, int allow_refuse) { GSList *list, *next; hexchat_hook *hook; hexchat_deinit_func *deinit_func; /* fake plugin added by hexchat_plugingui_add() */ if (pl->fake) goto xit; /* run the plugin's deinit routine, if any */ if (do_deinit && pl->deinit_callback != NULL) { deinit_func = pl->deinit_callback; if (!deinit_func (pl) && allow_refuse) return FALSE; } /* remove all of this plugin's hooks */ list = hook_list; while (list) { hook = list->data; next = list->next; if (hook->pl == pl) hexchat_unhook (NULL, hook); list = next; } #ifdef USE_PLUGIN if (pl->handle) #ifdef USE_GMODULE g_module_close (pl->handle); #else dlclose (pl->handle); #endif #endif xit: if (pl->free_strings) { if (pl->name) free (pl->name); if (pl->desc) free (pl->desc); if (pl->version) free (pl->version); } if (pl->filename) free ((char *)pl->filename); free (pl); plugin_list = g_slist_remove (plugin_list, pl); #ifdef USE_PLUGIN fe_pluginlist_update (); #endif return TRUE; } static hexchat_plugin * plugin_list_add (hexchat_context *ctx, char *filename, const char *name, const char *desc, const char *version, void *handle, void *deinit_func, int fake, int free_strings) { hexchat_plugin *pl; pl = malloc (sizeof (hexchat_plugin)); pl->handle = handle; pl->filename = filename; pl->context = ctx; pl->name = (char *)name; pl->desc = (char *)desc; pl->version = (char *)version; pl->deinit_callback = deinit_func; pl->fake = fake; pl->free_strings = free_strings; /* free() name,desc,version? */ plugin_list = g_slist_prepend (plugin_list, pl); return pl; } static void * hexchat_dummy (hexchat_plugin *ph) { return NULL; } #ifdef WIN32 static int hexchat_read_fd (hexchat_plugin *ph, GIOChannel *source, char *buf, int *len) { GError *error = NULL; g_io_channel_set_buffered (source, FALSE); g_io_channel_set_encoding (source, NULL, &error); if (g_io_channel_read_chars (source, buf, *len, (gsize*)len, &error) == G_IO_STATUS_NORMAL) { return 0; } else { return -1; } } #endif /* Load a static plugin */ void plugin_add (session *sess, char *filename, void *handle, void *init_func, void *deinit_func, char *arg, int fake) { hexchat_plugin *pl; char *file; file = NULL; if (filename) file = strdup (filename); pl = plugin_list_add (sess, file, file, NULL, NULL, handle, deinit_func, fake, FALSE); if (!fake) { /* win32 uses these because it doesn't have --export-dynamic! */ pl->hexchat_hook_command = hexchat_hook_command; pl->hexchat_hook_server = hexchat_hook_server; pl->hexchat_hook_print = hexchat_hook_print; pl->hexchat_hook_timer = hexchat_hook_timer; pl->hexchat_hook_fd = hexchat_hook_fd; pl->hexchat_unhook = hexchat_unhook; pl->hexchat_print = hexchat_print; pl->hexchat_printf = hexchat_printf; pl->hexchat_command = hexchat_command; pl->hexchat_commandf = hexchat_commandf; pl->hexchat_nickcmp = hexchat_nickcmp; pl->hexchat_set_context = hexchat_set_context; pl->hexchat_find_context = hexchat_find_context; pl->hexchat_get_context = hexchat_get_context; pl->hexchat_get_info = hexchat_get_info; pl->hexchat_get_prefs = hexchat_get_prefs; pl->hexchat_list_get = hexchat_list_get; pl->hexchat_list_free = hexchat_list_free; pl->hexchat_list_fields = hexchat_list_fields; pl->hexchat_list_str = hexchat_list_str; pl->hexchat_list_next = hexchat_list_next; pl->hexchat_list_int = hexchat_list_int; pl->hexchat_plugingui_add = hexchat_plugingui_add; pl->hexchat_plugingui_remove = hexchat_plugingui_remove; pl->hexchat_emit_print = hexchat_emit_print; #ifdef WIN32 pl->hexchat_read_fd = (void *) hexchat_read_fd; #else pl->hexchat_read_fd = hexchat_dummy; #endif pl->hexchat_list_time = hexchat_list_time; pl->hexchat_gettext = hexchat_gettext; pl->hexchat_send_modes = hexchat_send_modes; pl->hexchat_strip = hexchat_strip; pl->hexchat_free = hexchat_free; pl->hexchat_pluginpref_set_str = hexchat_pluginpref_set_str; pl->hexchat_pluginpref_get_str = hexchat_pluginpref_get_str; pl->hexchat_pluginpref_set_int = hexchat_pluginpref_set_int; pl->hexchat_pluginpref_get_int = hexchat_pluginpref_get_int; pl->hexchat_pluginpref_delete = hexchat_pluginpref_delete; pl->hexchat_pluginpref_list = hexchat_pluginpref_list; /* incase new plugins are loaded on older HexChat */ pl->hexchat_dummy4 = hexchat_dummy; pl->hexchat_dummy3 = hexchat_dummy; pl->hexchat_dummy2 = hexchat_dummy; pl->hexchat_dummy1 = hexchat_dummy; /* run hexchat_plugin_init, if it returns 0, close the plugin */ if (((hexchat_init_func *)init_func) (pl, &pl->name, &pl->desc, &pl->version, arg) == 0) { plugin_free (pl, FALSE, FALSE); return; } } #ifdef USE_PLUGIN fe_pluginlist_update (); #endif } /* kill any plugin by the given (file) name (used by /unload) */ int plugin_kill (char *name, int by_filename) { GSList *list; hexchat_plugin *pl; list = plugin_list; while (list) { pl = list->data; /* static-plugins (plugin-timer.c) have a NULL filename */ if ((by_filename && pl->filename && g_ascii_strcasecmp (name, pl->filename) == 0) || (by_filename && pl->filename && g_ascii_strcasecmp (name, file_part (pl->filename)) == 0) || (!by_filename && g_ascii_strcasecmp (name, pl->name) == 0)) { /* statically linked plugins have a NULL filename */ if (pl->filename != NULL && !pl->fake) { if (plugin_free (pl, TRUE, TRUE)) return 1; return 2; } } list = list->next; } return 0; } /* kill all running plugins (at shutdown) */ void plugin_kill_all (void) { GSList *list, *next; hexchat_plugin *pl; list = plugin_list; while (list) { pl = list->data; next = list->next; if (!pl->fake) plugin_free (list->data, TRUE, FALSE); list = next; } } #ifdef USE_PLUGIN /* load a plugin from a filename. Returns: NULL-success or an error string */ char * plugin_load (session *sess, char *filename, char *arg) { void *handle; hexchat_init_func *init_func; hexchat_deinit_func *deinit_func; #ifdef USE_GMODULE /* load the plugin */ handle = g_module_open (filename, 0); if (handle == NULL) return (char *)g_module_error (); /* find the init routine hexchat_plugin_init */ if (!g_module_symbol (handle, "hexchat_plugin_init", (gpointer *)&init_func)) { g_module_close (handle); return _("No hexchat_plugin_init symbol; is this really a HexChat plugin?"); } /* find the plugin's deinit routine, if any */ if (!g_module_symbol (handle, "hexchat_plugin_deinit", (gpointer *)&deinit_func)) deinit_func = NULL; #else char *error; char *filepart; /* OpenBSD lacks this! */ #ifndef RTLD_GLOBAL #define RTLD_GLOBAL 0 #endif #ifndef RTLD_NOW #define RTLD_NOW 0 #endif /* get the filename without path */ filepart = file_part (filename); /* load the plugin */ if (filepart && /* xsys draws in libgtk-1.2, causing crashes, so force RTLD_LOCAL */ (strstr (filepart, "local") || strncmp (filepart, "libxsys-1", 9) == 0) ) handle = dlopen (filename, RTLD_NOW); else handle = dlopen (filename, RTLD_GLOBAL | RTLD_NOW); if (handle == NULL) return (char *)dlerror (); dlerror (); /* Clear any existing error */ /* find the init routine hexchat_plugin_init */ init_func = dlsym (handle, "hexchat_plugin_init"); error = (char *)dlerror (); if (error != NULL) { dlclose (handle); return _("No hexchat_plugin_init symbol; is this really a HexChat plugin?"); } /* find the plugin's deinit routine, if any */ deinit_func = dlsym (handle, "hexchat_plugin_deinit"); error = (char *)dlerror (); #endif /* add it to our linked list */ plugin_add (sess, filename, handle, init_func, deinit_func, arg, FALSE); return NULL; } static session *ps; static void plugin_auto_load_cb (char *filename) { char *pMsg; #ifndef WIN32 /* black listed */ if (!strcmp (file_part (filename), "dbus.so")) return; #endif pMsg = plugin_load (ps, filename, NULL); if (pMsg) { PrintTextf (ps, "AutoLoad failed for: %s\n", filename); PrintText (ps, pMsg); } } void plugin_auto_load (session *sess) { char *sub_dir; ps = sess; sub_dir = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "addons", get_xdir ()); #ifdef WIN32 /* a long list of bundled plugins that should be loaded automati
/* X-Chat
 * Copyright (C) 1998 Peter Zelezny.
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#include "fe-gtk.h"
#include "palette.h"

#include "../common/hexchat.h"
#include "../common/util.h"
#include "../common/cfgfiles.h"
#include "../common/typedef.h"


GdkColor colors[] = {
	/* colors for xtext */
	{0, 0xd3d3, 0xd7d7, 0xcfcf}, /* 16 white */
	{0, 0x2e2e, 0x3434, 0x3636}, /* 17 black */
	{0, 0x3434, 0x6565, 0xa4a4}, /* 18 blue */
	{0, 0x4e4e, 0x9a9a, 0x0606}, /* 19 green */
	{0, 0xcccc, 0x0000, 0x0000}, /* 20 red */
	{0, 0x8f8f, 0x3939, 0x0202}, /* 21 light red */
	{0, 0x5c5c, 0x3535, 0x6666}, /* 22 purple */
	{0, 0xcece, 0x5c5c, 0x0000}, /* 23 orange */
	{0, 0xc4c4, 0xa0a0, 0x0000}, /* 24 yellow */
	{0, 0x7373, 0xd2d2, 0x1616}, /* 25 green */
	{0, 0x1111, 0xa8a8, 0x7979}, /* 26 aqua */
	{0, 0x5858, 0xa1a1, 0x9d9d}, /* 27 light aqua */
	{0, 0x5757, 0x7979, 0x9e9e}, /* 28 blue */
	{0, 0xa0d0, 0x42d4, 0x6562}, /* 29 light purple */
	{0, 0x5555, 0x5757, 0x5353}, /* 30 grey */
	{0, 0x8888, 0x8a8a, 0x8585}, /* 31 light grey */

	{0, 0xd3d3, 0xd7d7, 0xcfcf}, /* 16 white */
	{0, 0x2e2e, 0x3434, 0x3636}, /* 17 black */
	{0, 0x3434, 0x6565, 0xa4a4}, /* 18 blue */
	{0, 0x4e4e, 0x9a9a, 0x0606}, /* 19 green */
	{0, 0xcccc, 0x0000, 0x0000}, /* 20 red */
	{0, 0x8f8f, 0x3939, 0x0202}, /* 21 light red */
	{0, 0x5c5c, 0x3535, 0x6666}, /* 22 purple */
	{0, 0xcece, 0x5c5c, 0x0000}, /* 23 orange */
	{0, 0xc4c4, 0xa0a0, 0x0000}, /* 24 yellow */
	{0, 0x7373, 0xd2d2, 0x1616}, /* 25 green */
	{0, 0x1111, 0xa8a8, 0x7979}, /* 26 aqua */
	{0, 0x5858, 0xa1a1, 0x9d9d}, /* 27 light aqua */
	{0, 0x5757, 0x7979, 0x9e9e}, /* 28 blue */
	{0, 0xa0d0, 0x42d4, 0x6562}, /* 29 light purple */
	{0, 0x5555, 0x5757, 0x5353}, /* 30 grey */
	{0, 0x8888, 0x8a8a, 0x8585}, /* 31 light grey */

	{0, 0xd3d3, 0xd7d7, 0xcfcf}, /* 32 marktext Fore (white) */
	{0, 0x2020, 0x4a4a, 0x8787}, /* 33 marktext Back (blue) */
	{0, 0x2512, 0x29e8, 0x2b85}, /* 34 foreground (black) */
	{0, 0xfae0, 0xfae0, 0xf8c4}, /* 35 background (white) */
	{0, 0x8f8f, 0x3939, 0x0202}, /* 36 marker line (red) */

	/* colors for GUI */
	{0, 0x3434, 0x6565, 0xa4a4}, /* 37 tab New Data (dark red) */
	{0, 0x4e4e, 0x9a9a, 0x0606}, /* 38 tab Nick Mentioned (blue) */
	{0, 0xcece, 0x5c5c, 0x0000}, /* 39 tab New Message (red) */
	{0, 0x8888, 0x8a8a, 0x8585}, /* 40 away user (grey) */
	{0, 0xa4a4, 0x0000, 0x0000}, /* 41 spell checker color (red) */
};
#define MAX_COL 41


void
palette_alloc (GtkWidget * widget)
{
	int i;
	static int done_alloc = FALSE;
	GdkColormap *cmap;

	if (!done_alloc)		  /* don't do it again */
	{
		done_alloc = TRUE;
		cmap = gtk_widget_get_colormap (widget);
		for (i = MAX_COL; i >= 0; i--)
			gdk_colormap_alloc_color (cmap, &colors[i], FALSE, TRUE);
	}
}

/* maps HexChat 2.0.x colors to current */
static const int remap[] =
{
	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
	33,	/* 16:marktextback */
	32,	/* 17:marktextfore */
	34,	/* 18: fg */
	35,	/* 19: bg */
	37,	/* 20: newdata */
	38,	/* 21: blue */
	39,	/* 22: newmsg */
	40		/* 23: away */
};

void
palette_load (void)
{
	int i, j, l, fh, res;
	char prefname[256];
	struct stat st;
	char *