summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/common.vcxproj2
-rw-r--r--src/common/dcc.c3
-rw-r--r--src/common/hexchat-plugin.h50
-rw-r--r--src/common/make-te.vcxproj2
-rw-r--r--src/common/outbound.c2
-rw-r--r--src/common/plugin.c144
-rw-r--r--src/common/plugin.h25
-rw-r--r--src/common/proto-irc.c21
-rw-r--r--src/common/servlist.c7
-rw-r--r--src/common/text.c12
-rw-r--r--src/common/text.h3
-rw-r--r--src/common/url.c7
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj2
-rw-r--r--src/fe-gtk/menu.c2
-rw-r--r--src/fe-text/fe-text.vcxproj2
-rw-r--r--src/pixmaps/pixmaps.vcxproj2
-rw-r--r--src/version-script5
-rw-r--r--src/version/version.vcxproj2
18 files changed, 237 insertions, 56 deletions
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index c71d6ced..5568409e 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -119,7 +119,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -137,7 +136,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

diff --git a/src/common/dcc.c b/src/common/dcc.c
index c0527510..1137c444 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -548,7 +548,8 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	for (i = 5; i < PDIWORDS; i++)
 		word[i] = "\000";
 
-	ret = plugin_emit_print (sess, word);
+	ret = plugin_emit_print (sess, word) 
+		+ plugin_emit_print_attrs (sess, word, 0);
 
 	/* did the plugin close it? */
 	if (!g_slist_find (dcc_list, dcc))
diff --git a/src/common/hexchat-plugin.h b/src/common/hexchat-plugin.h
index 36dc544f..61597181 100644
--- a/src/common/hexchat-plugin.h
+++ b/src/common/hexchat-plugin.h
@@ -49,6 +49,10 @@ typedef struct _hexchat_hook hexchat_hook;
 #ifndef PLUGIN_C
 typedef struct _hexchat_context hexchat_context;
 #endif
+typedef struct
+{
+	time_t server_time_utc; /* 0 if not used */
+} hexchat_event_attrs;
 
 #ifndef PLUGIN_C
 struct _hexchat_plugin
@@ -164,6 +168,23 @@ struct _hexchat_plugin
 		const char *var);
 	int (*hexchat_pluginpref_list) (hexchat_plugin *ph,
 		char *dest);
+	hexchat_hook *(*hexchat_hook_server_attrs) (hexchat_plugin *ph,
+		   const char *name,
+		   int pri,
+		   int (*callback) (char *word[], char *word_eol[],
+							hexchat_event_attrs *attrs, void *user_data),
+		   void *userdata);
+	hexchat_hook *(*hexchat_hook_print_attrs) (hexchat_plugin *ph,
+		  const char *name,
+		  int pri,
+		  int (*callback) (char *word[], hexchat_event_attrs *attrs,
+						   void *user_data),
+		  void *userdata);
+	int (*hexchat_emit_print_attrs) (hexchat_plugin *ph, hexchat_event_attrs *attrs,
+									 const char *event_name, ...);
+	hexchat_event_attrs *(*hexchat_event_attrs_create) (hexchat_plugin *ph);
+	void (*hexchat_event_attrs_free) (hexchat_plugin *ph,
+									  hexchat_event_attrs *attrs);
 };
 #endif
 
@@ -176,6 +197,10 @@ hexchat_hook_command (hexchat_plugin *ph,
 		    const char *help_text,
 		    void *userdata);
 
+hexchat_event_attrs *hexchat_event_attrs_create (hexchat_plugin *ph);
+
+void hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *attrs);
+
 hexchat_hook *
 hexchat_hook_server (hexchat_plugin *ph,
 		   const char *name,
@@ -184,6 +209,14 @@ hexchat_hook_server (hexchat_plugin *ph,
 		   void *userdata);
 
 hexchat_hook *
+hexchat_hook_server_attrs (hexchat_plugin *ph,
+		   const char *name,
+		   int pri,
+		   int (*callback) (char *word[], char *word_eol[],
+							hexchat_event_attrs *attrs, void *user_data),
+		   void *userdata);
+
+hexchat_hook *
 hexchat_hook_print (hexchat_plugin *ph,
 		  const char *name,
 		  int pri,
@@ -191,6 +224,14 @@ hexchat_hook_print (hexchat_plugin *ph,
 		  void *userdata);
 
 hexchat_hook *
+hexchat_hook_print_attrs (hexchat_plugin *ph,
+		  const char *name,
+		  int pri,
+		  int (*callback) (char *word[], hexchat_event_attrs *attrs,
+						   void *user_data),
+		  void *userdata);
+
+hexchat_hook *
 hexchat_hook_timer (hexchat_plugin *ph,
 		  int timeout,
 		  int (*callback) (void *user_data),
@@ -297,6 +338,10 @@ int
 hexchat_emit_print (hexchat_plugin *ph,
 		  const char *event_name, ...);
 
+int 
+hexchat_emit_print_attrs (hexchat_plugin *ph, hexchat_event_attrs *attrs,
+						  const char *event_name, ...);
+
 char *
 hexchat_gettext (hexchat_plugin *ph,
 	       const char *msgid);
@@ -350,8 +395,12 @@ hexchat_pluginpref_list (hexchat_plugin *ph,
 #define HEXCHAT_PLUGIN_HANDLE (ph)
 #endif
 #define hexchat_hook_command ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_command)
+#define hexchat_event_attrs_create ((HEXCHAT_PLUGIN_HANDLE)->hexchat_event_attrs_create)
+#define hexchat_event_attrs_free ((HEXCHAT_PLUGIN_HANDLE)->hexchat_event_attrs_free)
 #define hexchat_hook_server ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_server)
+#define hexchat_hook_server_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_server_attrs)
 #define hexchat_hook_print ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_print)
+#define hexchat_hook_print_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_print_attrs)
 #define hexchat_hook_timer ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_timer)
 #define hexchat_hook_fd ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_fd)
 #define hexchat_unhook ((HEXCHAT_PLUGIN_HANDLE)->hexchat_unhook)
@@ -374,6 +423,7 @@ hexchat_pluginpref_list (hexchat_plugin *ph,
 #define hexchat_plugingui_add ((HEXCHAT_PLUGIN_HANDLE)->hexchat_plugingui_add)
 #define hexchat_plugingui_remove ((HEXCHAT_PLUGIN_HANDLE)->hexchat_plugingui_remove)
 #define hexchat_emit_print ((HEXCHAT_PLUGIN_HANDLE)->hexchat_emit_print)
+#define hexchat_emit_print_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_emit_print_attrs)
 #define hexchat_list_time ((HEXCHAT_PLUGIN_HANDLE)->hexchat_list_time)
 #define hexchat_gettext ((HEXCHAT_PLUGIN_HANDLE)->hexchat_gettext)
 #define hexchat_send_modes ((HEXCHAT_PLUGIN_HANDLE)->hexchat_send_modes)
diff --git a/src/common/make-te.vcxproj b/src/common/make-te.vcxproj
index 07bb5ca4..b9f0f11f 100644
--- a/src/common/make-te.vcxproj
+++ b/src/common/make-te.vcxproj
@@ -57,7 +57,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -77,7 +76,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

diff --git a/src/common/outbound.c b/src/common/outbound.c
index 6beaa2cc..9ddacb75 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -3877,7 +3877,7 @@ const struct commands xc_cmds[] = {
 	{"ME", cmd_me, 0, 0, 1,
 	 N_("ME <action>, sends the action to the current channel (actions are written in the 3rd person, like /me jumps)")},
 	{"MENU", cmd_menu, 0, 0, 1, "MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-r<X,group>] [-tX] {ADD|DEL} <path> [command] [unselect command]\n"
-										 "       See http://docs.hexchat.org/en/latest/plugins.html#controlling-the-gui for more details."},
+										 "       See http://hexchat.readthedocs.org/en/latest/plugins.html#controlling-the-gui for more details."},
 	{"MKICK", cmd_mkick, 1, 1, 1,
 	 N_("MKICK, Mass kicks everyone except you in the current channel (needs chanop)")},
 	{"MODE", cmd_mode, 1, 0, 1, 0},
diff --git a/src/common/plugin.c b/src/common/plugin.c
index 5a6a42a6..50157ea1 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -86,6 +86,8 @@ struct _hexchat_list
 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_serv_attrs_cb) (char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *user_data);
+typedef int (hexchat_print_attrs_cb) (char *word[], hexchat_event_attrs *attrs, 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 *);
@@ -102,12 +104,14 @@ enum
 
 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 */
+	HOOK_COMMAND,      /* /command */
+	HOOK_SERVER,       /* PRIVMSG, NOTICE, numerics */
+	HOOK_SERVER_ATTRS, /* same as above, with attributes */
+	HOOK_PRINT,        /* All print events */
+	HOOK_PRINT_ATTRS,  /* same as above, with attributes */
+	HOOK_TIMER,        /* timeouts */
+	HOOK_FD,           /* sockets & fds */
+	HOOK_DELETED       /* marked for deletion */
 };
 
 GSList *plugin_list = NULL;	/* export for plugingui.c */
@@ -289,12 +293,11 @@ plugin_add (session *sess, char *filename, void *handle, void *init_func,
 		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;
+		pl->hexchat_hook_server_attrs = hexchat_hook_server_attrs;
+		pl->hexchat_hook_print_attrs = hexchat_hook_print_attrs;
+		pl->hexchat_emit_print_attrs = hexchat_emit_print_attrs;
+		pl->hexchat_event_attrs_create = hexchat_event_attrs_create;
+		pl->hexchat_event_attrs_free = hexchat_event_attrs_free;
 
 		/* 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)
@@ -519,7 +522,7 @@ plugin_hook_find (GSList *list, int type, char *name)
 	while (list)
 	{
 		hook = list->data;
-		if (hook->type == type)
+		if (hook && hook->type == type)
 		{
 			if (g_ascii_strcasecmp (hook->name, name) == 0)
 				return list;
@@ -539,7 +542,8 @@ plugin_hook_find (GSList *list, int type, char *name)
 /* check for plugin hooks and run them */
 
 static int
-plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], int type)
+plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[],
+				 hexchat_event_attrs *attrs, int type)
 {
 	GSList *list, *next;
 	hexchat_hook *hook;
@@ -562,9 +566,15 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], int
 		case HOOK_COMMAND:
 			ret = ((hexchat_cmd_cb *)hook->callback) (word, word_eol, hook->userdata);
 			break;
+		case HOOK_PRINT_ATTRS:
+			ret = ((hexchat_print_attrs_cb *)hook->callback) (word, attrs, hook->userdata);
+			break;
 		case HOOK_SERVER:
 			ret = ((hexchat_serv_cb *)hook->callback) (word, word_eol, hook->userdata);
 			break;
+		case HOOK_SERVER_ATTRS:
+			ret = ((hexchat_serv_attrs_cb *)hook->callback) (word, word_eol, attrs, hook->userdata);
+			break;
 		default: /*case HOOK_PRINT:*/
 			ret = ((hexchat_print_cb *)hook->callback) (word, hook->userdata);
 			break;
@@ -590,7 +600,7 @@ xit:
 	{
 		hook = list->data;
 		next = list->next;
-		if (hook->type == HOOK_DELETED)
+		if (!hook || hook->type == HOOK_DELETED)
 		{
 			hook_list = g_slist_remove (hook_list, hook);
 			free (hook);
@@ -606,15 +616,43 @@ xit:
 int
 plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[])
 {
-	return plugin_hook_run (sess, name, word, word_eol, HOOK_COMMAND);
+	return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_COMMAND);
 }
 
-/* got a server PRIVMSG, NOTICE, numeric etc... */
+hexchat_event_attrs *
+hexchat_event_attrs_create (hexchat_plugin *ph)
+{
+	hexchat_event_attrs *attrs;
+
+	attrs = g_malloc (sizeof (*attrs));
 
+	attrs->server_time_utc = (time_t) 0;
+
+	return attrs;
+}
+
+void
+hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *attrs)
+{
+	g_free (attrs);
+}
+
+/* got a server PRIVMSG, NOTICE, numeric etc... */
 int
 plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[])
 {
-	return plugin_hook_run (sess, name, word, word_eol, HOOK_SERVER);
+	return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_SERVER);
+}
+
+int
+plugin_emit_server_attrs (session *sess, char *name, char *word[], char *word_eol[],
+						  time_t server_time)
+{
+	hexchat_event_attrs attrs;
+
+	attrs.server_time_utc = server_time;
+
+	return plugin_hook_run (sess, name, word, word_eol, &attrs, HOOK_SERVER_ATTRS);
 }
 
 /* see if any plugins are interested in this print event */
@@ -622,7 +660,17 @@ plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[])
 int
 plugin_emit_print (session *sess, char *word[])
 {
-	return plugin_hook_run (sess, word[0], word, NULL, HOOK_PRINT);
+	return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT);
+}
+
+int
+plugin_emit_print_attrs (session *sess, char *word[], time_t server_time)
+{
+	hexchat_event_attrs attrs;
+
+	attrs.server_time_utc = server_time;
+
+	return plugin_hook_run (sess, word[0], word, NULL, &attrs, HOOK_PRINT_ATTRS);
 }
 
 int
@@ -635,7 +683,7 @@ plugin_emit_dummy_print (session *sess, char *name)
 	for (i = 1; i < 32; i++)
 		word[i] = "\000";
 
-	return plugin_hook_run (sess, name, word, NULL, HOOK_PRINT);
+	return plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT);
 }
 
 int
@@ -663,7 +711,7 @@ plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval,
 	for (i = 5; i < PDIWORDS; i++)
 		word[i] = "\000";
 
-	return plugin_hook_run (sess, word[0], word, NULL, HOOK_PRINT);
+	return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT);
 }
 
 static int
@@ -702,7 +750,7 @@ plugin_insert_hook (hexchat_hook *new_hook)
 	while (list)
 	{
 		hook = list->data;
-		if (hook->type == new_hook->type && hook->pri <= new_hook->pri)
+		if (hook && hook->type == new_hook->type && hook->pri <= new_hook->pri)
 		{
 			hook_list = g_slist_insert_before (hook_list, list, new_hook);
 			return;
@@ -780,7 +828,7 @@ plugin_command_list(GList *tmp_list)
 	while (list)
 	{
 		hook = list->data;
-		if (hook->type == HOOK_COMMAND)
+		if (hook && hook->type == HOOK_COMMAND)
 			tmp_list = g_list_prepend(tmp_list, hook->name);
 		list = list->next;
 	}
@@ -798,7 +846,7 @@ plugin_command_foreach (session *sess, void *userdata,
 	while (list)
 	{
 		hook = list->data;
-		if (hook->type == HOOK_COMMAND && hook->name[0])
+		if (hook && hook->type == HOOK_COMMAND && hook->name[0])
 		{
 			cb (sess, userdata, hook->name, hook->help_text);
 		}
@@ -869,6 +917,14 @@ hexchat_hook_server (hexchat_plugin *ph, const char *name, int pri,
 }
 
 hexchat_hook *
+hexchat_hook_server_attrs (hexchat_plugin *ph, const char *name, int pri,
+						   hexchat_serv_attrs_cb *callb, void *userdata)
+{
+	return plugin_add_hook (ph, HOOK_SERVER_ATTRS, pri, name, 0, callb, 0,
+							userdata);
+}
+
+hexchat_hook *
 hexchat_hook_print (hexchat_plugin *ph, const char *name, int pri,
 						hexchat_print_cb *callb, void *userdata)
 {
@@ -876,6 +932,14 @@ hexchat_hook_print (hexchat_plugin *ph, const char *name, int pri,
 }
 
 hexchat_hook *
+hexchat_hook_print_attrs (hexchat_plugin *ph, const char *name, int pri,
+						  hexchat_print_attrs_cb *callb, void *userdata)
+{
+	return plugin_add_hook (ph, HOOK_PRINT_ATTRS, pri, name, 0, callb, 0,
+							userdata);
+}
+
+hexchat_hook *
 hexchat_hook_timer (hexchat_plugin *ph, int timeout, hexchat_timer_cb *callb,
 					   void *userdata)
 {
@@ -1598,8 +1662,36 @@ hexchat_emit_print (hexchat_plugin *ph, const char *event_name, ...)
 			break;
 	}
 
-	i = text_emit_by_name ((char *)event_name, ph->context, argv[0], argv[1],
-								  argv[2], argv[3]);
+	i = text_emit_by_name ((char *)event_name, ph->context, (time_t) 0,
+						   argv[0], argv[1], argv[2], argv[3]);
+	va_end (args);
+
+	return i;
+}
+
+int
+hexchat_emit_print_attrs (hexchat_plugin *ph, hexchat_event_attrs *attrs,
+						  const char *event_name, ...)
+{
+	va_list args;
+	/* currently only 4 because no events use more than 4.
+		This can be easily expanded without breaking the API. */
+	char *argv[4] = {NULL, NULL, NULL, NULL};
+	int i = 0;
+
+	va_start (args, event_name);
+	while (1)
+	{
+		argv[i] = va_arg (args, char *);
+		if (!argv[i])
+			break;
+		i++;
+		if (i >= 4)
+			break;
+	}
+
+	i = text_emit_by_name ((char *)event_name, ph->context, attrs->server_time_utc,
+						   argv[0], argv[1], argv[2], argv[3]);
 	va_end (args);
 
 	return i;
diff --git a/src/common/plugin.h b/src/common/plugin.h
index dd878895..f75639e9 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -132,10 +132,24 @@ struct _hexchat_plugin
 		const char *var);
 	int (*hexchat_pluginpref_list) (hexchat_plugin *ph,
 		char *dest);
-	void *(*hexchat_dummy4) (hexchat_plugin *ph);
-	void *(*hexchat_dummy3) (hexchat_plugin *ph);
-	void *(*hexchat_dummy2) (hexchat_plugin *ph);
-	void *(*hexchat_dummy1) (hexchat_plugin *ph);
+	hexchat_hook *(*hexchat_hook_server_attrs) (hexchat_plugin *ph,
+		   const char *name,
+		   int pri,
+		   int (*callback) (char *word[], char *word_eol[],
+							hexchat_event_attrs *attrs, void *user_data),
+		   void *userdata);
+	hexchat_hook *(*hexchat_hook_print_attrs) (hexchat_plugin *ph,
+		  const char *name,
+		  int pri,
+		  int (*callback) (char *word[], hexchat_event_attrs *attrs,
+						   void *user_data),
+		  void *userdata);
+	int (*hexchat_emit_print_attrs) (hexchat_plugin *ph, hexchat_event_attrs *attrs,
+									 const char *event_name, ...);
+	hexchat_event_attrs *(*hexchat_event_attrs_create) (hexchat_plugin *ph);
+	void (*hexchat_event_attrs_free) (hexchat_plugin *ph,
+									  hexchat_event_attrs *attrs);
+
 	/* PRIVATE FIELDS! */
 	void *handle;		/* from dlopen */
 	char *filename;	/* loaded from */
@@ -156,7 +170,10 @@ void plugin_kill_all (void);
 void plugin_auto_load (session *sess);
 int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[]);
 int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]);
+int plugin_emit_server_attrs (session *sess, char *name, char *word[],
+							  char *word_eol[], time_t server_time);
 int plugin_emit_print (session *sess, char *word[]);
+int plugin_emit_print_attrs (session *sess, char *word[], time_t server_time);
 int plugin_emit_dummy_print (session *sess, char *name);
 int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, int len, char *string);
 GList* plugin_command_list(GList *tmp_list);
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index bea9f6f7..128c0c85 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -1493,6 +1493,9 @@ irc_inline (server *serv, char *buf, int len)
 
 	if (buf[0] == ':')
 	{
+		int eat1;
+		int eat2;
+
 		/* find a context for this message */
 		if (is_channel (serv, word[3]))
 		{
@@ -1506,15 +1509,29 @@ irc_inline (server *serv, char *buf, int len)
 
 		word[0] = type;
 		word_eol[1] = buf;	/* keep the ":" for plugins */
-		if (plugin_emit_server (sess, type, word, word_eol))
+
+		eat1 = plugin_emit_server (sess, type, word, word_eol);
+		eat2 = plugin_emit_server_attrs (sess, type, word, word_eol, 
+										 tags_data.timestamp);
+
+		if (eat1 || eat2)
 			goto xit;
+
 		word[1]++;
 		word_eol[1] = buf + 1;	/* but not for HexChat internally */
 
 	} else
 	{
+		int eat1;
+		int eat2;
+
 		word[0] = type = word[1];
-		if (plugin_emit_server (sess, type, word, word_eol))
+
+		eat1 = plugin_emit_server (sess, type, word, word_eol);
+		eat2 = plugin_emit_server_attrs (sess, type, word, word_eol,
+										 tags_data.timestamp);
+
+		if (eat1 || eat2)
 			goto xit;
 	}
 
diff --git a/src/common/servlist.c b/src/common/servlist.c
index 1e06acd4..ceee3455 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -207,7 +207,7 @@ static const struct defaultserver def[] =
 	{"EnterTheGame",	0},
 	{0,			"IRC.EnterTheGame.Com"},
 
-	{"EntropyNet",	0},
+	{"EntropyNet",	0, 0, 0, LOGIN_SASL},
 #ifdef USE_OPENSSL
 	{0,			"irc.entropynet.net/+6697"},
 #endif
@@ -510,7 +510,7 @@ static const struct defaultserver def[] =
 	{0,			"moo.slashnet.org"},
 	{0,			"radon.slashnet.org"},
 
-	{"Snoonet", 0},
+	{"Snoonet", 0, 0, 0, LOGIN_SASL},
 #ifdef USE_OPENSSL
 	{0,			"irc.snoonet.org/+6697"},
 #endif
@@ -550,6 +550,9 @@ static const struct defaultserver def[] =
 	{0,			"tahoma.starchat.net"},
 	{0,			"neo.starchat.net"},
 
+	{"StaticBox", 0, 0, 0, LOGIN_SASL},
+	{0,			"irc.staticbox.net"},
+
 	{"Station51", 0},
 #ifdef USE_OPENSSL
 	{0,			"irc.station51.net/+6697"},
diff --git a/src/common/text.c b/src/common/text.c
index a0e860ce..b825faba 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -2070,6 +2070,8 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 	int i;
 	unsigned int stripcolor_args = (chanopt_is_set (prefs.hex_text_stripcolor_msg, sess->text_strip) ? 0xFFFFFFFF : 0);
 	char tbuf[NICKLEN + 4];
+	int eat1;
+	int eat2;
 
 	if (prefs.hex_text_color_nicks && (index == XP_TE_CHANACTION || index == XP_TE_CHANMSG))
 	{
@@ -2086,7 +2088,10 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 	for (i = 5; i < PDIWORDS; i++)
 		word[i] = "\000";
 
-	if (plugin_emit_print (sess, word))
+	eat1 = plugin_emit_print (sess, word);
+	eat2 = plugin_emit_print_attrs (sess, word, timestamp);
+
+	if (eat1 || eat2)
 		return;
 
 	/* If a plugin's callback executes "/close", 'sess' may be invalid */
@@ -2158,14 +2163,15 @@ text_find_format_string (char *name)
 }
 
 int
-text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d)
+text_emit_by_name (char *name, session *sess, time_t timestamp,
+				   char *a, char *b, char *c, char *d)
 {
 	int i = 0;
 
 	i = pevent_find (name, &i);
 	if (i >= 0)
 	{
-		text_emit (i, sess, a, b, c, d, 0);
+		text_emit (i, sess, a, b, c, d, timestamp);
 		return 1;
 	}
 
diff --git a/src/common/text.h b/src/common/text.h
index 5a51c894..a9fd9d4e 100644
--- a/src/common/text.h
+++ b/src/common/text.h
@@ -55,7 +55,8 @@ void pevent_make_pntevts (void);
 int text_color_of (char *name);
 void text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 		time_t timestamp);
-int text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d);
+int text_emit_by_name (char *name, session *sess, time_t timestamp,
+					   char *a, char *b, char *c, char *d);
 char *text_validate (char **text, int *len);
 int get_stamp_str (char *fmt, time_t tim, char **ret);
 void format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args);
diff --git a/src/common/url.c b/src/common/url.c
index 10479127..892441c8 100644
--- a/src/common/url.c
+++ b/src/common/url.c
@@ -350,8 +350,8 @@ do_an_re(const char *word, int *start, int *end, int *type)
 }
 
 /*	Miscellaneous description --- */
-#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*\\."
-#define TLD "[a-z][-a-z0-9]*[a-z]"
+#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*"
+#define TLD "\\.[a-z][-a-z0-9]*[a-z]"
 #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
 #define IPV6GROUP "([0-9a-f]{0,4})"
 #define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})"	\
@@ -359,6 +359,7 @@ do_an_re(const char *word, int *start, int *end, int *type)
 #define HOST "(" DOMAIN TLD "|" IPADDR "|" IPV6ADDR ")"
 /* In urls the IPv6 must be enclosed in square brackets */
 #define HOST_URL "(" DOMAIN TLD "|" IPADDR "|" "\\[" IPV6ADDR "\\]" ")"
+#define HOST_URL_OPT_TLD "(" DOMAIN "|" HOST_URL ")"
 #define PORT "(:[1-9][0-9]{0,4})"
 #define OPT_PORT "(" PORT ")?"
 
@@ -517,7 +518,7 @@ re_url (void)
 			g_string_append (grist_gstr, USERINFO "?");
 
 		if (uri[i].flags & URI_AUTHORITY)
-			g_string_append (grist_gstr, HOST_URL OPT_PORT);
+			g_string_append (grist_gstr, HOST_URL_OPT_TLD OPT_PORT);
 		
 		if (uri[i].flags & URI_PATH)
 		{
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
index 0c149928..f8c6377a 100644
--- a/src/fe-gtk/fe-gtk.vcxproj
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -59,7 +59,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -81,7 +80,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index 1948348a..58c28e51 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -1545,7 +1545,7 @@ menu_ctcpguiopen (void)
 static void
 menu_docs (GtkWidget *wid, gpointer none)
 {
-	fe_open_url ("http://docs.hexchat.org/");
+	fe_open_url ("http://hexchat.readthedocs.org");
 }
 
 /*static void
diff --git a/src/fe-text/fe-text.vcxproj b/src/fe-text/fe-text.vcxproj
index 1c42c967..2a7c3742 100644
--- a/src/fe-text/fe-text.vcxproj
+++ b/src/fe-text/fe-text.vcxproj
@@ -59,7 +59,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -79,7 +78,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

diff --git a/src/pixmaps/pixmaps.vcxproj b/src/pixmaps/pixmaps.vcxproj
index dbb18520..a86a7e13 100644
--- a/src/pixmaps/pixmaps.vcxproj
+++ b/src/pixmaps/pixmaps.vcxproj
@@ -57,7 +57,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -76,7 +75,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

diff --git a/src/version-script b/src/version-script
index a98651db..a7ed1495 100644
--- a/src/version-script
+++ b/src/version-script
@@ -1,8 +1,12 @@
 EXPORTED {
 	global:
 		hexchat_hook_command;
+		hexchat_event_attrs_create;
+		hexchat_event_attrs_free;
 		hexchat_hook_server;
+		hexchat_hook_server_attrs;
 		hexchat_hook_print;
+		hexchat_hook_print_attrs;
 		hexchat_hook_timer;
 		hexchat_hook_fd;
 		hexchat_unhook;
@@ -25,6 +29,7 @@ EXPORTED {
 		hexchat_plugingui_add;
 		hexchat_plugingui_remove;
 		hexchat_emit_print;
+		hexchat_emit_print_attrs;
 		hexchat_list_time;
 		hexchat_gettext;
 		hexchat_send_modes;
diff --git a/src/version/version.vcxproj b/src/version/version.vcxproj
index ca429b08..f1520f73 100644
--- a/src/version/version.vcxproj
+++ b/src/version/version.vcxproj
@@ -57,7 +57,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

@@ -77,7 +76,6 @@
     <ClCompile>

       <PrecompiledHeader>

       </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>