summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/chanopt.c2
-rw-r--r--src/common/common.vcxproj2
-rw-r--r--src/common/dcc.c8
-rw-r--r--src/common/dcc.h2
-rw-r--r--src/common/hexchat.c1
-rw-r--r--src/common/hexchat.h14
-rw-r--r--src/common/inbound.c36
-rw-r--r--src/common/inbound.h2
-rw-r--r--src/common/meson.build5
-rw-r--r--src/common/modes.c4
-rw-r--r--src/common/outbound.c2
-rw-r--r--src/common/plugin.c119
-rw-r--r--src/common/proto-irc.c65
-rw-r--r--src/common/proto-irc.h6
-rw-r--r--src/common/server.c56
-rw-r--r--src/common/servlist.c61
-rw-r--r--src/common/text.c7
-rw-r--r--src/common/textevents.in6
-rw-r--r--src/common/url.c2
-rw-r--r--src/common/userlist.c17
-rw-r--r--src/fe-gtk/fe-gtk.c4
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj2
-rw-r--r--src/fe-gtk/joind.c2
-rw-r--r--src/fe-gtk/maingui.c30
-rw-r--r--src/fe-gtk/menu.c20
-rw-r--r--src/fe-gtk/meson.build13
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj126
-rw-r--r--src/fe-gtk/pixmaps.c22
-rw-r--r--src/fe-gtk/plugin-notification.c40
-rw-r--r--src/fe-gtk/xtext.c18
-rw-r--r--src/fe-text/fe-text.c2
-rw-r--r--src/fe-text/fe-text.vcxproj2
-rw-r--r--src/htm/Properties/Resources.Designer.cs2
-rw-r--r--src/htm/Properties/Settings.Designer.cs2
-rw-r--r--src/htm/app.config2
-rw-r--r--src/htm/htm.csproj2
-rw-r--r--src/libenchant_win8/libenchant_win8.vcxproj2
37 files changed, 494 insertions, 214 deletions
diff --git a/src/common/chanopt.c b/src/common/chanopt.c
index 1870c99c..67cb46cf 100644
--- a/src/common/chanopt.c
+++ b/src/common/chanopt.c
@@ -58,6 +58,7 @@ typedef struct
 
 static const channel_options chanopt[] =
 {
+	{"alert_balloon", NULL, S_F(alert_balloon)},
 	{"alert_beep", "BEEP", S_F(alert_beep)},
 	{"alert_taskbar", NULL, S_F(alert_taskbar)},
 	{"alert_tray", "TRAY", S_F(alert_tray)},
@@ -182,6 +183,7 @@ typedef struct
 {
 	/* Per-Channel Alerts */
 	/* use a byte, because we need a pointer to each element */
+	guint8 alert_balloon;
 	guint8 alert_beep;
 	guint8 alert_taskbar;
 	guint8 alert_tray;
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 33a883bf..bc191f43 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>

 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

-    <PlatformToolset>v140</PlatformToolset>

+    <PlatformToolset>v142</PlatformToolset>

     <ConfigurationType>StaticLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

diff --git a/src/common/dcc.c b/src/common/dcc.c
index 51f6d661..df129e68 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -1618,13 +1618,13 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 }
 
 guint32
-dcc_get_my_address (void)	/* the address we'll tell the other person */
+dcc_get_my_address (session *sess)	/* the address we'll tell the other person */
 {
 	struct hostent *dns_query;
 	guint32 addr = 0;
 
-	if (prefs.hex_dcc_ip_from_server && prefs.dcc_ip)
-		addr = prefs.dcc_ip;
+	if (prefs.hex_dcc_ip_from_server && sess->server->dcc_ip)
+		addr = sess->server->dcc_ip;
 	else if (prefs.hex_dcc_ip[0])
 	{
 	   dns_query = gethostbyname ((const char *) prefs.hex_dcc_ip);
@@ -1710,7 +1710,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
 	/*if we have a dcc_ip, we use that, so the remote client can connect*/
 	/*else we try to take an address from hex_dcc_ip*/
 	/*if something goes wrong we tell the client to connect to our LAN ip*/
-	dcc->addr = dcc_get_my_address ();
+	dcc->addr = dcc_get_my_address (sess);
 
 	/*if nothing else worked we use the address we bound to*/
 	if (dcc->addr == 0)
diff --git a/src/common/dcc.h b/src/common/dcc.h
index 379385e6..74028205 100644
--- a/src/common/dcc.h
+++ b/src/common/dcc.h
@@ -124,7 +124,7 @@ void dcc_chat (session *sess, char *nick, int passive);
 void handle_dcc (session *sess, char *nick, char *word[], char *word_eol[],
 					  const message_tags_data *tags_data);
 void dcc_show_list (session *sess);
-guint32 dcc_get_my_address (void);
+guint32 dcc_get_my_address (session *sess);
 void dcc_get_with_destfile (struct DCC *dcc, char *utf8file);
 
 #endif
diff --git a/src/common/hexchat.c b/src/common/hexchat.c
index 347cf1ce..9be2e56d 100644
--- a/src/common/hexchat.c
+++ b/src/common/hexchat.c
@@ -493,6 +493,7 @@ session_new (server *serv, char *from, int type, int focus)
 	sess->logfd = -1;
 	sess->type = type;
 
+	sess->alert_balloon = SET_DEFAULT;
 	sess->alert_beep = SET_DEFAULT;
 	sess->alert_taskbar = SET_DEFAULT;
 	sess->alert_tray = SET_DEFAULT;
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index 8c4a6a41..d8effa1f 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -75,7 +75,7 @@
 #define DOMAINLEN	100
 #define NICKLEN		64				/* including the NULL, so 63 really */
 #define CHANLEN		300
-#define PDIWORDS		32
+#define PDIWORDS	32
 #define USERNAMELEN 10
 #define HIDDEN_CHAR	8			/* invisible character for xtext */
 
@@ -301,8 +301,8 @@ struct hexchatprefs
 	char hex_irc_user_name[127];
 	char hex_net_bind_host[127];
 	char hex_net_proxy_host[64];
-	char hex_net_proxy_pass[32];
-	char hex_net_proxy_user[32];
+	char hex_net_proxy_pass[256];
+	char hex_net_proxy_user[256];
 	char hex_stamp_log_format[64];
 	char hex_stamp_text_format[64];
 	char hex_text_background[PATHLEN + 1];
@@ -313,7 +313,6 @@ struct hexchatprefs
 
 	/* these are the private variables */
 	guint32 local_ip;
-	guint32 dcc_ip;
 
 	unsigned int wait_on_exit;	/* wait for logs to be flushed to disk IF we're connected */
 
@@ -364,6 +363,7 @@ typedef struct session
 {
 	/* Per-Channel Alerts */
 	/* use a byte, because we need a pointer to each element */
+	guint8 alert_balloon;
 	guint8 alert_beep;
 	guint8 alert_taskbar;
 	guint8 alert_tray;
@@ -482,6 +482,10 @@ typedef struct server
 	int proxy_sok4;
 	int proxy_sok6;
 	int id;					/* unique ID number (for plugin API) */
+
+	/* dcc_ip moved from hexchatprefs to make it per-server */
+	guint32 dcc_ip;
+
 #ifdef USE_OPENSSL
 	SSL_CTX *ctx;
 	SSL *ssl;
@@ -566,6 +570,7 @@ typedef struct server
 	unsigned int have_idmsg:1;		/* freenode's IDENTIFY-MSG */
 	unsigned int have_accnotify:1; /* cap account-notify */
 	unsigned int have_extjoin:1;	/* cap extended-join */
+	unsigned int have_account_tag:1;	/* cap account-tag */
 	unsigned int have_server_time:1;	/* cap server-time */
 	unsigned int have_sasl:1;		/* SASL capability */
 	unsigned int have_except:1;	/* ban exemptions +e */
@@ -575,6 +580,7 @@ typedef struct server
 	unsigned int sasl_mech;			/* mechanism for sasl auth */
 	unsigned int sent_capend:1;	/* have sent CAP END yet */
 	unsigned int waiting_on_cap:1;	/* waiting on another line of CAP LS */
+	unsigned int waiting_on_sasl:1; /* waiting on sasl */
 #ifdef USE_OPENSSL
 	unsigned int use_ssl:1;				  /* is server SSL capable? */
 	unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */
diff --git a/src/common/inbound.c b/src/common/inbound.c
index fb8eb511..7175b2ae 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -815,7 +815,9 @@ inbound_topictime (server *serv, char *chan, char *nick, time_t stamp,
 	if (!sess)
 		sess = serv->server_session;
 
-	tim[24] = 0;	/* get rid of the \n */
+	if (tim != NULL)
+		tim[24] = 0;	/* get rid of the \n */
+
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_TOPICDATE, sess, chan, nick, tim, NULL, 0,
 								  tags_data->timestamp);
 }
@@ -1420,7 +1422,7 @@ inbound_foundip (session *sess, char *ip, const message_tags_data *tags_data)
 	HostAddr = gethostbyname (ip);
 	if (HostAddr)
 	{
-		prefs.dcc_ip = ((struct in_addr *) HostAddr->h_addr)->s_addr;
+		sess->server->dcc_ip = ((struct in_addr *) HostAddr->h_addr)->s_addr;
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_FOUNDIP, sess->server->server_session,
 									  inet_ntoa (*((struct in_addr *) HostAddr->h_addr)),
 									  NULL, NULL, NULL, 0, tags_data->timestamp);
@@ -1489,7 +1491,7 @@ inbound_banlist (session *sess, time_t stamp, char *chan, char *mask,
 	server *serv = sess->server;
 	char *nl;
 
-	if (stamp <= 0)
+	if (stamp <= 0 || time_str == NULL)
 	{
 		time_str = "";
 	}
@@ -1669,6 +1671,8 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
 			serv->have_server_time = enable;
 		else if (!strcmp (extension, "away-notify"))
 			serv->have_awaynotify = enable;
+		else if (!strcmp (extension, "account-tag"))
+			serv->have_account_tag = enable;
 		else if (!strcmp (extension, "sasl"))
 		{
 			serv->have_sasl = enable;
@@ -1722,6 +1726,9 @@ static const char * const supported_caps[] = {
 	"userhost-in-names",
 	"cap-notify",
 	"chghost",
+	"setname",
+	"invite-notify",
+	"account-tag",
 
 	/* ZNC */
 	"znc.in/server-time-iso",
@@ -1768,7 +1775,6 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 {
 	char buffer[500];	/* buffer for requesting capabilities and emitting the signal */
 	gboolean want_cap = FALSE; /* format the CAP REQ string based on previous capabilities being requested or not */
-	gboolean want_sasl = FALSE; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
 	char **extensions;
 	int i;
 
@@ -1806,7 +1812,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 		/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
 		if (!g_strcmp0 (extension, "sasl") &&
 			((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
-				|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
+				|| serv->loginmethod == LOGIN_SASLEXTERNAL))
 		{
 			if (value)
 			{
@@ -1816,7 +1822,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 				serv->sasl_mech = sasl_mech;
 			}
 			want_cap = TRUE;
-			want_sasl = TRUE;
+			serv->waiting_on_sasl = TRUE;
 			g_strlcat (buffer, "sasl ", sizeof(buffer));
 			continue;
 		}
@@ -1842,7 +1848,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 									  tags_data->timestamp);
 		tcp_sendf (serv, "%s\r\n", g_strchomp (buffer));
 	}
-	if (!want_sasl && !serv->waiting_on_cap)
+	if (!serv->waiting_on_sasl && !serv->waiting_on_cap)
 	{
 		/* if we use SASL, CAP END is dealt via raw numerics */
 		serv->sent_capend = TRUE;
@@ -1851,13 +1857,25 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 }
 
 void
-inbound_cap_nak (server *serv, const message_tags_data *tags_data)
+inbound_cap_nak (server *serv, char *extensions_str, const message_tags_data *tags_data)
 {
-	if (!serv->waiting_on_cap && !serv->sent_capend)
+	char **extensions;
+	int i;
+
+	extensions = g_strsplit (extensions_str, " ", 0);
+	for (i=0; extensions[i]; i++)
+	{
+		if (!g_strcmp0 (extensions[i], "sasl"))
+			serv->waiting_on_sasl = FALSE;
+	}
+
+	if (!serv->waiting_on_cap && !serv->waiting_on_sasl && !serv->sent_capend)
 	{
 		serv->sent_capend = TRUE;
 		tcp_send_len (serv, "CAP END\r\n", 9);
 	}
+
+	g_strfreev (extensions);
 }
 
 void
diff --git a/src/common/inbound.h b/src/common/inbound.h
index 83e78d5d..6e7c171f 100644
--- a/src/common/inbound.h
+++ b/src/common/inbound.h
@@ -92,7 +92,7 @@ void inbound_cap_ack (server *serv, char *nick, char *extensions,
 							 const message_tags_data *tags_data);
 void inbound_cap_ls (server *serv, char *nick, char *extensions,
 							const message_tags_data *tags_data);
-void inbound_cap_nak (server *serv, const message_tags_data *tags_data);
+void inbound_cap_nak (server *serv, char *extensions, const message_tags_data *tags_data);
 void inbound_cap_list (server *serv, char *nick, char *extensions,
 							  const message_tags_data *tags_data);
 void inbound_cap_del (server *serv, char *nick, char *extensions,
diff --git a/src/common/meson.build b/src/common/meson.build
index a0d6ce2b..492227b2 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -93,10 +93,6 @@ endif
 
 if get_option('with-plugin')
   common_deps += libgmodule_dep
-  common_cflags += '-DHEXCHATLIBDIR="@0@"'.format(join_paths(get_option('prefix'),
-                                                  get_option('libdir'),
-                                                  'hexchat/plugins'))
-
   install_headers('hexchat-plugin.h')
 endif
 
@@ -109,6 +105,7 @@ hexchat_common = static_library('hexchatcommon',
 )
 
 hexchat_common_dep = declare_dependency(
+  sources: [textevents] + marshal,
   link_with: hexchat_common,
   include_directories: common_includes,
   compile_args: common_cflags,
diff --git a/src/common/modes.c b/src/common/modes.c
index c65bf279..3c0ac8ab 100644
--- a/src/common/modes.c
+++ b/src/common/modes.c
@@ -735,6 +735,8 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 		if (!(*word[i + offset]))
 			break;
 		num_args++;
+		if (word[i + offset][0] == ':')
+			break;
 	}
 
 	/* count the number of modes (without the -/+ chars */
@@ -765,7 +767,7 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args + 1))
 			{
 				arg++;
-				argstr = word[arg + offset];
+				argstr = STRIP_COLON(word, word_eol, arg+offset);
 			}
 			handle_single_mode (&mr, sign, *modes, nick, chan,
 									  argstr, numeric_324 || prefs.hex_irc_raw_modes,
diff --git a/src/common/outbound.c b/src/common/outbound.c
index 96fb7fe4..614aad38 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -3287,7 +3287,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[2][0])
 		return FALSE;
 
-	addr = dcc_get_my_address ();
+	addr = dcc_get_my_address (sess);
 	if (addr == 0)
 	{
 		/* use the one from our connected server socket */
diff --git a/src/common/plugin.c b/src/common/plugin.c
index 0aa8859d..d3f3b7ca 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -115,6 +115,34 @@ enum
 	HOOK_DELETED      = 1 << 7  /* marked for deletion */
 };
 
+enum
+{
+	CHANNEL_FLAG_CONNECTED             = 1 << 0,
+	CHANNEL_FLAG_CONNECING             = 1 << 1,
+	CHANNEL_FLAG_AWAY                  = 1 << 2,
+	CHANNEL_FLAG_END_OF_MOTD           = 1 << 3,
+	CHANNEL_FLAG_HAS_WHOX              = 1 << 4,
+	CHANNEL_FLAG_HAS_IDMSG             = 1 << 5,
+	CHANNEL_FLAG_HIDE_JOIN_PARTS       = 1 << 6,
+	CHANNEL_FLAG_HIDE_JOIN_PARTS_UNSET = 1 << 7,
+	CHANNEL_FLAG_BEEP                  = 1 << 8,
+	CHANNEL_FLAG_BEEP_UNSET            = 1 << 9,
+	CHANNEL_FLAG_UNUSED                = 1 << 10,
+	CHANNEL_FLAG_LOGGING               = 1 << 11,
+	CHANNEL_FLAG_LOGGING_UNSET         = 1 << 12,
+	CHANNEL_FLAG_SCROLLBACK            = 1 << 13,
+	CHANNEL_FLAG_SCROLLBACK_UNSET      = 1 << 14,
+	CHANNEL_FLAG_STRIP_COLORS          = 1 << 15,
+	CHANNEL_FLAG_STRIP_COLORS_UNSET    = 1 << 16,
+	CHANNEL_FLAG_TRAY                  = 1 << 17,
+	CHANNEL_FLAG_TRAY_UNSET            = 1 << 18,
+	CHANNEL_FLAG_TASKBAR               = 1 << 19,
+	CHANNEL_FLAG_TASKBAR_UNSET         = 1 << 20,
+	CHANNEL_FLAG_BALLOON               = 1 << 21,
+	CHANNEL_FLAG_BALLOON_UNSET         = 1 << 22,
+	CHANNEL_FLAG_COUNT                 = 23
+};
+
 GSList *plugin_list = NULL;	/* export for plugingui.c */
 static GSList *hook_list = NULL;
 
@@ -355,7 +383,8 @@ plugin_kill_all (void)
 	}
 }
 
-#ifdef USE_PLUGIN
+#if defined(USE_PLUGIN) || defined(WIN32)
+/* used for loading plugins, and in fe-gtk/notifications/notification-windows.c */
 
 GModule *
 module_load (char *filename)
@@ -384,6 +413,10 @@ module_load (char *filename)
 	return handle;
 }
 
+#endif
+
+#ifdef USE_PLUGIN
+
 /* load a plugin from a filename. Returns: NULL-success or an error string */
 
 char *
@@ -676,11 +709,11 @@ check_and_invalidate(void *plug_, void *killsess_)
 int
 plugin_emit_dummy_print (session *sess, char *name)
 {
-	char *word[32];
+	char *word[PDIWORDS];
 	int i;
 
 	word[0] = name;
-	for (i = 1; i < 32; i++)
+	for (i = 1; i < PDIWORDS; i++)
 		word[i] = "\000";
 
 	i = plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT);
@@ -1544,7 +1577,11 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 {
 	guint32 hash = str_hash (name);
 	gpointer data = ph->context;
-	int tmp = 0;
+
+	int channel_flag;
+	int channel_flags[CHANNEL_FLAG_COUNT];
+	int channel_flags_used = 0;
+
 	int type = LIST_CHANNELS;
 
 	/* a NULL xlist is a shortcut to current "channels" context */
@@ -1605,48 +1642,38 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 		case 0xd1b:	/* id */
 			return ((struct session *)data)->server->id;
 		case 0x5cfee87:	/* flags */
-			/* used if alert_taskbar is unset */                 /* 20 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->alert_taskbar;      /* 19 */
-			tmp <<= 1;
-			/* used if alert_tray is unset */                    /* 18 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->alert_tray;         /* 17 */
-			tmp <<= 1;
-			/* used if text_strip is unset */                    /* 16 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->text_strip;          /* 15 */
-			tmp <<= 1;
-			/* used if text_scrollback is unset */               /* 14 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->text_scrollback;    /* 13 */
-			tmp <<= 1;
-			/* used if text_logging is unset */                  /* 12 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->text_logging;       /* 11 */
-			tmp <<= 1;
-			/* unused for historical reasons */                  /* 10 */
-			tmp <<= 1;
-			/* used if alert_beep is unset */                    /* 9 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->alert_beep;         /* 8 */
-			tmp <<= 1;
-			/* used if text_hidejoinpart is unset */              /* 7 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->text_hidejoinpart;   /* 6 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->have_idmsg; /* 5 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->have_whox;  /* 4 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->end_of_motd;/* 3 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->is_away;    /* 2 */
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->connecting; /* 1 */ 
-			tmp <<= 1;
-			tmp |= ((struct session *)data)->server->connected;  /* 0 */
-			return tmp;
+			channel_flags[0] = ((struct session *)data)->server->connected;
+			channel_flags[1] = ((struct session *)data)->server->connecting;
+			channel_flags[2] = ((struct session *)data)->server->is_away;
+			channel_flags[3] = ((struct session *)data)->server->end_of_motd;
+			channel_flags[4] = ((struct session *)data)->server->have_whox;
+			channel_flags[5] = ((struct session *)data)->server->have_idmsg;
+			channel_flags[6] = ((struct session *)data)->text_hidejoinpart;
+			channel_flags[7] = ((struct session *)data)->text_hidejoinpart == SET_DEFAULT;
+			channel_flags[8] = ((struct session *)data)->alert_beep;
+			channel_flags[9] = ((struct session *)data)->alert_beep == SET_DEFAULT;
+			channel_flags[10] = 0; /* unused for historical reasons */
+			channel_flags[11] = ((struct session *)data)->text_logging;
+			channel_flags[12] = ((struct session *)data)->text_logging == SET_DEFAULT;
+			channel_flags[13] = ((struct session *)data)->text_scrollback;
+			channel_flags[14] = ((struct session *)data)->text_scrollback == SET_DEFAULT;
+			channel_flags[15] = ((struct session *)data)->text_strip;
+			channel_flags[16] = ((struct session *)data)->text_strip == SET_DEFAULT;
+			channel_flags[17] = ((struct session *)data)->alert_tray;
+			channel_flags[18] = ((struct session *)data)->alert_tray == SET_DEFAULT;
+			channel_flags[19] = ((struct session *)data)->alert_taskbar;
+			channel_flags[20] = ((struct session *)data)->alert_taskbar == SET_DEFAULT;
+			channel_flags[21] = ((struct session *)data)->alert_balloon;
+			channel_flags[22] = ((struct session *)data)->alert_balloon == SET_DEFAULT;
+
+			/* Set flags */
+			for (channel_flag = 0; channel_flag < CHANNEL_FLAG_COUNT; ++channel_flag) {
+				if (channel_flags[channel_flag]) {
+					channel_flags_used |= 1 << channel_flag;
+				}
+			}
+
+			return channel_flags_used;
 		case 0x1a192: /* lag */
 			return ((struct session *)data)->server->lag;
 		case 0x1916144c: /* maxmodes */
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 776d1434..c8e44b62 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -60,8 +60,8 @@ irc_login (server *serv, char *user, char *realname)
 
 	tcp_sendf (serv,
 				  "NICK %s\r\n"
-				  "USER %s %s %s :%s\r\n",
-				  serv->nick, user, user, serv->servername, realname);
+				  "USER %s 0 * :%s\r\n",
+				  serv->nick, user, realname);
 }
 
 static void
@@ -454,7 +454,8 @@ channel_date (session *sess, char *chan, char *timestr,
 {
 	time_t timestamp = (time_t) atol (timestr);
 	char *tim = ctime (&timestamp);
-	tim[24] = 0;	/* get rid of the \n */
+	if (tim != NULL)
+		tim[24] = 0;	/* get rid of the \n */
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDATE, sess, chan, tim, NULL, NULL, 0,
 								  tags_data->timestamp);
 }
@@ -602,7 +603,8 @@ process_numeric (session * sess, int n,
 			else
 			{
 				tim = ctime (&timestamp);
-				tim[19] = 0; 	/* get rid of the \n */
+				if (tim != NULL)
+					tim[19] = 0; 	/* get rid of the \n */
 				EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS4T, whois_sess, word[4],
 											  outbuf, tim, NULL, 0, tags_data->timestamp);
 			}
@@ -621,7 +623,7 @@ process_numeric (session * sess, int n,
 	case 319:
 		if (!serv->skip_next_whois)
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS2, whois_sess, word[4],
-										  word_eol[5] + 1, NULL, NULL, 0,
+										  word_eol[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], NULL, NULL, 0,
 										  tags_data->timestamp);
 		break;
 
@@ -714,7 +716,7 @@ process_numeric (session * sess, int n,
 		break;
 
 	case 333:
-		inbound_topictime (serv, word[4], word[5], atol (word[6]), tags_data);
+		inbound_topictime (serv, word[4], word[5], atol (STRIP_COLON(word, word_eol, 6)), tags_data);
 		break;
 
 #if 0
@@ -726,7 +728,7 @@ process_numeric (session * sess, int n,
 #endif
 
 	case 341:						  /* INVITE ACK */
-		EMIT_SIGNAL_TIMESTAMP (XP_TE_UINVITE, sess, word[4], word[5],
+		EMIT_SIGNAL_TIMESTAMP (XP_TE_UINVITE, sess, word[4], STRIP_COLON(word, word_eol, 5),
 									  serv->servername, NULL, 0, tags_data->timestamp);
 		break;
 
@@ -957,6 +959,7 @@ process_numeric (session * sess, int n,
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_SASLRESPONSE, serv->server_session, word[1],
 									  word[2], word[3], ++word_eol[4], 0,
 									  tags_data->timestamp);
+		serv->waiting_on_sasl = FALSE;
 		if (!serv->sent_capend)
 		{
 			serv->sent_capend = TRUE;
@@ -1007,6 +1010,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 						 const message_tags_data *tags_data)
 {
 	server *serv = sess->server;
+	char *account;
 	char ip[128], nick[NICKLEN];
 	char *text, *ex;
 	int len = strlen (type);
@@ -1025,6 +1029,14 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 		ex[0] = '!';
 	}
 
+
+	/** Update the account for this message's source. */
+	if (serv->have_account_tag)
+	{
+		account = tags_data->account && *tags_data->account ? tags_data->account : "*";
+		inbound_account (serv, nick, account, tags_data);
+	}
+
 	if (len == 4)
 	{
 		guint32 t;
@@ -1142,7 +1154,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 		{
 
 		case WORDL('A','C','C','O'):
-			inbound_account (serv, nick, word[3], tags_data);
+			inbound_account (serv, nick, STRIP_COLON(word, word_eol, 3), tags_data);
 			return;
 
 		case WORDL('A', 'U', 'T', 'H'):
@@ -1150,20 +1162,26 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 			return;
 
 		case WORDL('C', 'H', 'G', 'H'):
-			inbound_user_info (sess, NULL, word[3], word[4], NULL, nick, NULL,
+			inbound_user_info (sess, NULL, word[3], STRIP_COLON(word, word_eol, 4), NULL, nick, NULL,
+							   NULL, 0xff, tags_data);
+			return;
+
+		case WORDL('S', 'E', 'T', 'N'):
+			inbound_user_info (sess, NULL, NULL, NULL, NULL, nick, STRIP_COLON(word, word_eol, 3),
 							   NULL, 0xff, tags_data);
 			return;
 
 		case WORDL('I','N','V','I'):
 			if (ignore_check (word[1], IG_INVI))
 				return;
-			
-			if (word[4][0] == ':')
-				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4] + 1, nick,
-											  serv->servername, NULL, 0,
+
+			text = STRIP_COLON(word, word_eol, 4);
+			if (serv->p_cmp (word[3], serv->nick))
+				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITEDOTHER, sess, text, nick,
+											  word[3], serv->servername, 0,
 											  tags_data->timestamp);
 			else
-				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4], nick,
+				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, text, nick,
 											  serv->servername, NULL, 0,
 											  tags_data->timestamp);
 				
@@ -1241,10 +1259,13 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 							text++;
 					}
 					len = strlen (text);
-					if (text[0] == 1 && text[len - 1] == 1)	/* ctcp */
+					if (text[0] == 1)	/* ctcp */
 					{
 						char *new_pdibuf = NULL;
-						text[len - 1] = 0;
+						if (text[len - 1] == 1)
+						{
+							text[len - 1] = 0;
+						}
 						text++;
 						if (g_ascii_strncasecmp (text, "ACTION", 6) != 0)
 							flood_check (nick, ip, serv, sess, 0);
@@ -1330,7 +1351,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 				}
 				else if (strncasecmp (word[4], "NAK", 3) == 0)
 				{
-					inbound_cap_nak (serv, tags_data);
+					inbound_cap_nak (serv, word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], tags_data);
 				}
 				else if (strncasecmp (word[4], "LIST", 4) == 0)	
 				{
@@ -1513,6 +1534,9 @@ handle_message_tags (server *serv, const char *tags_str,
 		*value = '\0';
 		value++;
 
+		if (serv->have_account_tag && !strcmp (key, "account"))
+			tags_data->account = g_strdup (value);
+
 		if (serv->have_server_time && !strcmp (key, "time"))
 			handle_message_tag_time (value, tags_data);
 	}
@@ -1610,10 +1634,17 @@ irc_inline (server *serv, char *buf, int len)
 	}
 
 xit:
+	message_tags_data_free (&tags_data);
 	g_free (pdibuf);
 }
 
 void
+message_tags_data_free (message_tags_data *tags_data)
+{
+	g_clear_pointer (&tags_data->account, g_free);
+}
+
+void
 proto_fill_her_up (server *serv)
 {
 	serv->p_inline = irc_inline;
diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h
index a7b4029c..0f72c644 100644
--- a/src/common/proto-irc.h
+++ b/src/common/proto-irc.h
@@ -25,18 +25,24 @@
 
 #define MESSAGE_TAGS_DATA_INIT			\
 	{									\
+		NULL, /* account name */		\
 		(time_t)0, /* timestamp */		\
 	}
 
+#define STRIP_COLON(word, word_eol, idx) (word)[(idx)][0] == ':' ? (word_eol)[(idx)]+1 : (word)[(idx)]
+
 /* Message tag information that might be passed along with a server message
  *
  * See http://ircv3.atheme.org/specification/capability-negotiation-3.1
  */
 typedef struct 
 {
+	char *account;
 	time_t timestamp;
 } message_tags_data;
 
+void message_tags_data_free (message_tags_data *tags_data);
+
 void proto_fill_her_up (server *serv);
 
 #endif
diff --git a/src/common/server.c b/src/common/server.c
index 3db0a963..5c645eb5 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -200,13 +200,35 @@ tcp_send_len (server *serv, char *buf, int len)
 	}
 	else
 	{
-		/* WHO/MODE get the lowest priority */
-		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0 ||
-		/* but only MODE queries, not changes */
-			(g_ascii_strncasecmp (dbuf + 1, "MODE", 4) == 0 &&
-			 strchr (dbuf, '-') == NULL &&
-			 strchr (dbuf, '+') == NULL))
+		/* WHO gets the lowest priority */
+		if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0)
 			dbuf[0] = 0;
+		/* as do MODE queries (but not changes) */
+		else if (g_ascii_strncasecmp (dbuf + 1, "MODE ", 5) == 0)
+		{
+			char *mode_str, *mode_str_end, *loc;
+			/* skip spaces before channel/nickname */
+			for (mode_str = dbuf + 5; *mode_str == ' '; ++mode_str);
+			/* skip over channel/nickname */
+			mode_str = strchr (mode_str, ' ');
+			if (mode_str)
+			{
+				/* skip spaces before mode string */
+				for (; *mode_str == ' '; ++mode_str);
+				/* find spaces after end of mode string */
+				mode_str_end = strchr (mode_str, ' ');
+				/* look for +/- within the mode string */
+				loc = strchr (mode_str, '-');
+				if (loc && (!mode_str_end || loc < mode_str_end))
+					goto keep_priority;
+				loc = strchr (mode_str, '+');
+				if (loc && (!mode_str_end || loc < mode_str_end))
+					goto keep_priority;
+			}
+			dbuf[0] = 0;
+keep_priority:
+			;
+		}
 	}
 
 	serv->outbound_queue = g_slist_append (serv->outbound_queue, dbuf);
@@ -1094,6 +1116,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 	if (auth)
 	{
 		int len_u=0, len_p=0;
+		unsigned char *u_p_buf;
 
 		/* authentication sub-negotiation (RFC1929) */
 		if (buf[1] != 2)  /* UPA not supported by server */
@@ -1102,18 +1125,22 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 			return 1;
 		}
 
-		memset (buf, 0, sizeof(buf));
-
 		/* form the UPA request */
 		len_u = strlen (prefs.hex_net_proxy_user);
 		len_p = strlen (prefs.hex_net_proxy_pass);
-		buf[0] = 1;
-		buf[1] = len_u;
-		memcpy (buf + 2, prefs.hex_net_proxy_user, len_u);
-		buf[2 + len_u] = len_p;
-		memcpy (buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p);
 
-		send (sok, buf, 3 + len_u + len_p, 0);
+        packetlen = 2 + len_u + 1 + len_p;
+		u_p_buf = g_malloc0 (packetlen);
+
+		u_p_buf[0] = 1;
+		u_p_buf[1] = len_u;
+		memcpy (u_p_buf + 2, prefs.hex_net_proxy_user, len_u);
+		u_p_buf[2 + len_u] = len_p;
+		memcpy (u_p_buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p);
+
+		send (sok, u_p_buf, packetlen, 0);
+		g_free(u_p_buf);
+
 		if ( recv (sok, buf, 2, 0) != 2 )
 			goto read_error;
 		if ( buf[1] != 0 )
@@ -1757,6 +1784,7 @@ server_set_defaults (server *serv)
 	serv->have_idmsg = FALSE;
 	serv->have_accnotify = FALSE;
 	serv->have_extjoin = FALSE;
+	serv->have_account_tag = FALSE;
 	serv->have_server_time = FALSE;
 	serv->have_sasl = FALSE;
 	serv->have_except = FALSE;
diff --git a/src/common/servlist.c b/src/common/servlist.c
index 449f982b..79a5694b 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -54,15 +54,13 @@ static const struct defaultserver def[] =
 	/* Invalid hostname in cert */
 	{0,			"irc.2600.net"},
 
-	{"2ch", 0, 0, "iso-2022-jp", 0, 0},
-	{0,			"irc.2ch.sc"},
-	{0,			"irc.nurs.or.jp"},
-	{0,			"irc.juggler.jp"},
-
 	{"AccessIRC",	0},
 	/* Self signed */
 	{0,			"irc.accessirc.net"},
 
+	{"ACN", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"global.acn.gr"},
+
 	{"AfterNET", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.afternet.org"},
 
@@ -125,6 +123,13 @@ static const struct defaultserver def[] =
 	{"DarkMyst", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.darkmyst.org"},
 
+#ifdef USE_OPENSSL
+	{"darkscience", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.darkscience.net"},
+	{0,			"irc.drk.sc"},
+	{0,			"irc.darkscience.ws"},
+#endif
+
 	{"Dark-Tou-Net",	0},
 	{0,			"irc.d-t-net.de"},
 
@@ -166,9 +171,6 @@ static const struct defaultserver def[] =
 	/* irc. points to chat. but many users and urls still reference it */
 	{0,				"irc.freenode.net"},
 
-	{"Furnet", 0, 0, 0, 0, 0, TRUE},
-	{0,			"irc.furnet.org"},
-
 	{"GalaxyNet",	0},
 	{0,			"irc.galaxynet.org"},
 
@@ -196,6 +198,12 @@ static const struct defaultserver def[] =
 #endif
 	{0,			"irc.globalgamers.net"},
 
+#ifdef USE_OPENSSL
+	{"hackint", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.hackint.org"},
+	{0,			"irc.eu.hackint.org"},
+#endif
+
 	{"Hashmark",	0},
 	{0,			"irc.hashmark.net"},
 
@@ -231,10 +239,18 @@ static const struct defaultserver def[] =
 	{"Krstarica", 0},
 	{0,			"irc.krstarica.com"},
 
+#ifdef USE_OPENSSL
+	{"LibertaCasa", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.liberta.casa"},
+#endif
+
 	{"LibraIRC", 0},
 	/* Self signed */
 	{0,			"irc.librairc.net"},
 
+	{"Libera.Chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.libera.chat"},
+
 #ifdef USE_OPENSSL
 	{"LinkNet",	0},
 	{0,			"irc.link-net.org/+7000"},
@@ -246,9 +262,6 @@ static const struct defaultserver def[] =
 	{"MIXXnet",		0},
 	{0,			"irc.mixxnet.net"},
 
-	{"Moznet", 0, 0, 0, 0, 0, TRUE},
-	{0,			"irc.mozilla.org"},
-	
 	{"ObsidianIRC",  0},
 	/* Self signed */
 	{0,      "irc.obsidianirc.net"}, 
@@ -273,9 +286,12 @@ static const struct defaultserver def[] =
 	{0,			"irc.ponychat.net"},
 
 	{"PTNet.org",	0},
-	/* Note that the network suggests ISO-8859-1 but most users ignore this */
+	{0,			"irc.ptnet.org"},
 	{0,			"uevora.ptnet.org"},
-	{0,			"vianetworks.ptnet.org"},
+	{0,			"claranet.ptnet.org"},
+	{0,			"sonaquela.ptnet.org"},
+	{0,			"uc.ptnet.org"},
+	{0,			"ipg.ptnet.org"},
 
 	{"QuakeNet", 0, 0, 0, LOGIN_CHALLENGEAUTH},
 	{0,			"irc.quakenet.org"},
@@ -299,6 +315,9 @@ static const struct defaultserver def[] =
 	{"Serenity-IRC",	0},
 	{0,			"irc.serenity-irc.net"},
 
+	{"SimosNap", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,            "irc.simosnap.com"},
+
 	{"SlashNET",	0},
 	/* Self signed */
 	{0,			"irc.slashnet.org"},
@@ -340,7 +359,18 @@ static const struct defaultserver def[] =
 
 	{"Techtronix",	0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.techtronix.net"},
+	
+	{"tilde.chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.tilde.chat"},
 
+#ifdef USE_OPENSSL
+	{"TripSit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.tripsit.me"},
+	{0,			"newirc.tripsit.me"},
+	{0,			"coconut.tripsit.me"},
+	{0,			"innsbruck.tripsit.me"},
+#endif	
+	
 	{"TURLINet", 0, 0, 0, 0, 0, TRUE},
 	/* Other servers use CP1251 and invalid certs */
 	{0,			"irc.servx.ru"},
@@ -358,6 +388,9 @@ static const struct defaultserver def[] =
 
 	{"Xertion", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.xertion.org"},
+	
+	{"DeltaPool", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.deltapool.net"},
 
 	{0,0}
 };
@@ -928,7 +961,7 @@ servlist_load_defaults (void)
 {
 	int i = 0, j = 0;
 	ircnet *net = NULL;
-	guint def_hash = g_str_hash ("freenode");
+	guint def_hash = g_str_hash ("Libera.Chat");
 
 	while (1)
 	{
diff --git a/src/common/text.c b/src/common/text.c
index 4a274f98..b0a90e03 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -1295,6 +1295,13 @@ static char * const pevt_invited_help[] = {
 	N_("Server Name"),
 };
 
+static char * const pevt_invitedother_help[] = {
+	N_("Channel Name"),
+	N_("Nick of person who sent the invite"),
+	N_("Nick of person who was invited"),
+	N_("Server Name"),
+};
+
 static char * const pevt_usersonchan_help[] = {
 	N_("Channel Name"),
 	N_("Users"),
diff --git a/src/common/textevents.in b/src/common/textevents.in
index 9790c18d..14bd4b06 100644
--- a/src/common/textevents.in
+++ b/src/common/textevents.in
@@ -496,6 +496,12 @@ pevt_invited_help
 %C24*%O$tYou have been invited to %C22$1%O by %C18$2%O (%C29$3%O)
 3
 
+Invited Other
+XP_TE_INVITEDOTHER
+pevt_invitedother_help
+%C24*%O$t%C26$3%C has been invited to %C22$1%O by %C18$2%O (%C29$4%O)
+4
+
 Join
 XP_TE_JOIN
 pevt_join_help
diff --git a/src/common/url.c b/src/common/url.c
index a741fb04..6a1d09e8 100644
--- a/src/common/url.c
+++ b/src/common/url.c
@@ -518,6 +518,8 @@ struct
 	{ "pop",       "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
 	{ "nfs",       "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
 	{ "smb",       "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
+	{ "gopher",    "/", URI_AUTHORITY | URI_PATH },
+	{ "gemini",    "/", URI_AUTHORITY | URI_PATH },
 	{ "ssh",       "",  URI_AUTHORITY | URI_OPT_USERINFO },
 	{ "sip",       "",  URI_AUTHORITY | URI_USERINFO },
 	{ "sips",      "",  URI_AUTHORITY | URI_USERINFO },
diff --git a/src/common/userlist.c b/src/common/userlist.c
index 0f28a000..5f2d67f2 100644
--- a/src/common/userlist.c
+++ b/src/common/userlist.c
@@ -101,13 +101,15 @@ userlist_set_account (struct session *sess, char *nick, char *account)
 	user = userlist_find (sess, nick);
 	if (user)
 	{
-		g_free (user->account);
-			
 		if (strcmp (account, "*") == 0)
-			user->account = NULL;
-		else
+		{
+			g_clear_pointer (&user->account, g_free);
+		} else if (g_strcmp0 (user->account, account))
+		{
+			g_free (user->account);
 			user->account = g_strdup (account);
-			
+		}
+
 		/* gui doesnt currently reflect login status, maybe later
 		fe_userlist_rehash (sess, user); */
 	}
@@ -130,8 +132,11 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
 			g_free (user->hostname);
 			user->hostname = g_strdup (hostname);
 		}
-		if (!user->realname && realname && *realname)
+		if (realname && *realname && g_strcmp0 (user->realname, realname) != 0)
+		{
+			g_free (user->realname);
 			user->realname = g_strdup (realname);
+		}
 		if (!user->servername && servername)
 			user->servername = g_strdup (servername);
 		if (!user->account && account && strcmp (account, "0") != 0)
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index 9d068a1b..ee3e847c 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -293,10 +293,10 @@ create_input_style (GtkStyle *style)
 		GtkSettings *settings = gtk_settings_get_default ();
 		char *theme_name;
 
-		/* gnome-themes-standard 3.20 relies on images to do theming
+		/* gnome-themes-standard 3.20+ relies on images to do theming
 		 * so we have to override that. */
 		g_object_get (settings, "gtk-theme-name", &theme_name, NULL);
-		if (g_str_has_prefix (theme_name, "Adwaita"))
+		if (g_str_has_prefix (theme_name, "Adwaita") || g_str_has_prefix (theme_name, "Yaru"))
 			gtk_rc_parse_string (adwaita_workaround_rc);
 		g_free (theme_name);
 
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
index 61d0a074..06df36dc 100644
--- a/src/fe-gtk/fe-gtk.vcxproj
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>

 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

-    <PlatformToolset>v140</PlatformToolset>

+    <PlatformToolset>v142</PlatformToolset>

     <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index f1d3da50..ce3cbcae 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -247,7 +247,7 @@ joind_show_dialog (server *serv)
 							G_CALLBACK (joind_ok_cb), serv);
 							
 	if (serv->network)
-		if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "freenode") == 0)
+		if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Libera.Chat") == 0)
 		{
 			gtk_entry_set_text (GTK_ENTRY (entry1), "#hexchat");
 		}
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index efeaaaeb..4e5baaa0 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -53,6 +53,10 @@
 #include "sexy-spell-entry.h"
 #include "gtkutil.h"
 
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+
 #define GUI_SPACING (3)
 #define GUI_BORDER (0)
 
@@ -1516,14 +1520,32 @@ static void
 mg_create_alertmenu (session *sess, GtkWidget *menu)
 {
 	GtkWidget *submenu;
+	int hex_balloon, hex_beep, hex_tray, hex_flash;
+
+
+	switch (sess->type) {
+		case SESS_DIALOG:
+			hex_balloon = prefs.hex_input_balloon_priv;
+			hex_beep = prefs.hex_input_beep_priv;
+			hex_tray = prefs.hex_input_tray_priv;
+			hex_flash = prefs.hex_input_flash_priv;
+			break;
+		default:
+			hex_balloon = prefs.hex_input_balloon_chans;
+			hex_beep = prefs.hex_input_beep_chans;
+			hex_tray = prefs.hex_input_tray_chans;
+			hex_flash = prefs.hex_input_flash_chans;
+	}
+
+	submenu = menu_quick_sub(_("_Extra Alerts"), menu, NULL, XCMENU_MNEMONIC, -1);
 
-	submenu = menu_quick_sub (_("_Extra Alerts"), menu, NULL, XCMENU_MNEMONIC, -1);
+	mg_perchan_menu_item(_("Show Notifications"), submenu, &sess->alert_balloon, hex_balloon);
 
-	mg_perchan_menu_item (_("Beep on _Message"), submenu, &sess->alert_beep, prefs.hex_input_beep_chans);
+	mg_perchan_menu_item(_("Beep on _Message"), submenu, &sess->alert_beep, hex_beep);
 
-	mg_perchan_menu_item (_("Blink Tray _Icon"), submenu, &sess->alert_tray, prefs.hex_input_tray_chans);
+	mg_perchan_menu_item(_("Blink Tray _Icon"), submenu, &sess->alert_tray, hex_tray);
 
-	mg_perchan_menu_item (_("Blink Task _Bar"), submenu, &sess->alert_taskbar, prefs.hex_input_flash_chans);
+	mg_perchan_menu_item(_("Blink Task _Bar"), submenu, &sess->alert_taskbar, hex_flash);
 }
 
 static void
diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c
index 097093b4..233715e5 100644
--- a/src/fe-gtk/menu.c
+++ b/src/fe-gtk/menu.c
@@ -1002,6 +1002,18 @@ menu_chan_part (GtkWidget * menu, char *chan)
 }
 
 static void
+menu_chan_focus (GtkWidget * menu, char *chan)
+{
+	char tbuf[256];
+
+	if (current_sess)
+	{
+		g_snprintf (tbuf, sizeof tbuf, "doat %s gui focus", chan);
+		handle_command (current_sess, tbuf, FALSE);
+	}
+}
+
+static void
 menu_chan_join (GtkWidget * menu, char *chan)
 {
 	char tbuf[256];
@@ -1018,8 +1030,11 @@ menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
 {
 	GtkWidget *menu;
 	int is_joined = FALSE;
+	session * chan_session;
+
+	chan_session = find_channel (sess->server, chan);
 
-	if (find_channel (sess->server, chan))
+	if (chan_session)
 		is_joined = TRUE;
 
 	g_free (str_copy);
@@ -1035,6 +1050,9 @@ menu_chanmenu (struct session *sess, GdkEventButton * event, char *chan)
 												 str_copy);
 	else
 	{
+		if (chan_session != current_sess)
+			menu_quick_item_with_callback (menu_chan_focus, _("Focus Channel"), menu,
+													 str_copy);
 		menu_quick_item_with_callback (menu_chan_part, _("Part Channel"), menu,
 												 str_copy);
 		menu_quick_item_with_callback (menu_chan_cycle, _("Cycle Channel"), menu,
diff --git a/src/fe-gtk/meson.build b/src/fe-gtk/meson.build
index f11580bb..3dfc7427 100644
--- a/src/fe-gtk/meson.build
+++ b/src/fe-gtk/meson.build
@@ -39,13 +39,9 @@ if gtk_dep.get_pkgconfig_variable('target') == 'x11'
   hexchat_gtk_deps += dependency('x11')
 endif
 
-hexchat_gtk_cflags = [
-  '-fPIE'
-]
+hexchat_gtk_cflags = []
 
-hexchat_gtk_ldflags = [
-  '-pie'
-]
+hexchat_gtk_ldflags = []
 
 if get_option('with-libnotify')
   hexchat_gtk_sources += 'notifications/notification-libnotify.c'
@@ -84,11 +80,16 @@ resources = gnome.compile_resources('resources',
   extra_args: ['--manual-register']
 )
 
+if host_machine.system() == 'windows'
+  hexchat_gtk_ldflags += '-Wl,-e,mainCRTStartup'
+endif
+
 executable('hexchat',
   sources:  resources + hexchat_gtk_sources,
   dependencies: hexchat_gtk_deps,
   c_args: hexchat_gtk_cflags,
   link_args: hexchat_gtk_ldflags,
+  pie: true,
   install: true,
   gui_app: true,
 )
diff --git a/src/fe-gtk/notifications/notifications-winrt.vcxproj b/src/fe-gtk/notifications/notifications-winrt.vcxproj
index 1f392b6b..2f6ffc99 100644
--- a/src/fe-gtk/notifications/notifications-winrt.vcxproj
+++ b/src/fe-gtk/notifications/notifications-winrt.vcxproj
@@ -1,62 +1,64 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="notification-winrt.cpp">

-      <CompileAsWinRT>true</CompileAsWinRT>

-    </ClCompile>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{C53145CC-D021-40C9-B97C-0249AB9A43C9}</ProjectGuid>

-    <Keyword>Win32Proj</Keyword>

-    <RootNamespace>notifications-winrt</RootNamespace>

-    <ProjectName>notifications-winrt</ProjectName>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Label="Configuration">

-    <PlatformToolset>v140</PlatformToolset>

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  <Import Project="..\..\..\win32\hexchat.props" />

-  <PropertyGroup>

-    <TargetName>hcnotifications-winrt</TargetName>

-    <OutDir>$(HexChatRel)plugins\</OutDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <SDLCheck>true</SDLCheck>

-      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <ClCompile>

-      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <SDLCheck>true</SDLCheck>

-      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

-    </ClCompile>

-    <Link>

-      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

-      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-    </Link>

-  </ItemDefinitionGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-</Project>

+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="notification-winrt.cpp">
+      <CompileAsWinRT>true</CompileAsWinRT>
+    </ClCompile>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C53145CC-D021-40C9-B97C-0249AB9A43C9}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>notifications-winrt</RootNamespace>
+    <ProjectName>notifications-winrt</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Label="Configuration">
+    <PlatformToolset>v142</PlatformToolset>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  <Import Project="..\..\..\win32\hexchat.props" />
+  <PropertyGroup>
+    <TargetName>hcnotifications-winrt</TargetName>
+    <OutDir>$(HexChatRel)plugins\</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalUsingDirectories>$(VC_LibraryPath_VC_x86_Store)\references;$(WindowsSDK_UnionMetadataPath);$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
+      <CompileAsWinRT>true</CompileAsWinRT>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>
+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalUsingDirectories>$(VC_LibraryPath_VC_x86_Store)\references;$(WindowsSDK_UnionMetadataPath);$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
+      <CompileAsWinRT>true</CompileAsWinRT>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>
+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
diff --git a/src/fe-gtk/pixmaps.c b/src/fe-gtk/pixmaps.c
index 6c6cfaeb..9bdf46fc 100644
--- a/src/fe-gtk/pixmaps.c
+++ b/src/fe-gtk/pixmaps.c
@@ -89,7 +89,9 @@ pixmap_load_from_file (char *filename)
 static GdkPixbuf *
 load_pixmap (const char *filename)
 {
-	GdkPixbuf *pixbuf;
+	GdkPixbuf *pixbuf, *scaledpixbuf;
+	const char *scale;
+	int iscale;
 
 	gchar *path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "icons" G_DIR_SEPARATOR_S "%s.png", get_xdir (), filename);
 	pixbuf = gdk_pixbuf_new_from_file (path, 0);
@@ -102,6 +104,24 @@ load_pixmap (const char *filename)
 		g_free (path);
 	}
 
+	// Hack to avoid unbearably tiny icons on HiDPI screens.
+	scale = g_getenv ("GDK_SCALE");
+	if (scale)
+	{
+		iscale = atoi (scale);
+		if (iscale > 0)
+		{
+			scaledpixbuf = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * iscale,
+				gdk_pixbuf_get_height (pixbuf) * iscale, GDK_INTERP_BILINEAR);
+
+			if (scaledpixbuf)
+			{
+				g_object_unref (pixbuf);
+				pixbuf = scaledpixbuf;
+			}
+		}
+	}
+
 	g_warn_if_fail (pixbuf != NULL);
 
 	return pixbuf;
diff --git a/src/fe-gtk/plugin-notification.c b/src/fe-gtk/plugin-notification.c
index 3ac89244..29478d7a 100644
--- a/src/fe-gtk/plugin-notification.c
+++ b/src/fe-gtk/plugin-notification.c
@@ -25,6 +25,9 @@
 
 static hexchat_plugin *ph;
 
+const int CHANNEL_FLAG_BALLOON       = 1 << 21;
+const int CHANNEL_FLAG_BALLOON_UNSET = 1 << 22;
+
 static gboolean
 should_alert (void)
 {
@@ -117,10 +120,24 @@ static int
 incoming_message_cb (char *word[], gpointer userdata)
 {
 	int message;
+	int flags;
+	int alert = 0;
+
+	flags = hexchat_list_int(ph, NULL, "flags");
+
+	/* Let sure that can alert */
+	if (should_alert()) {
+		/* Follow the channel rules if set */
+		if (!(flags & CHANNEL_FLAG_BALLOON_UNSET)) {
+			alert = (flags & CHANNEL_FLAG_BALLOON);
+		} else {
+			/* Else follow global environment */
+			alert = (hexchat_get_prefs(ph, "input_balloon_chans", NULL, &message) == 3 && message);
+		}
+	}
 
-	if (hexchat_get_prefs (ph, "input_balloon_chans", NULL, &message) == 3 && message && should_alert ())
-	{
-		show_notificationf (word[2], _("Channel message from: %s (%s)"), word[1], hexchat_get_info (ph, "channel"));
+	if (alert) {
+		show_notificationf(word[2], _("Channel message from: %s (%s)"), word[1], hexchat_get_info(ph, "channel"));
 	}
 	return HEXCHAT_EAT_NONE;
 }
@@ -129,8 +146,23 @@ static int
 incoming_priv_cb (char *word[], gpointer userdata)
 {
 	int priv;
+	int flags;
+	int alert = 0;
+
+	flags = hexchat_list_int(ph, NULL, "flags");
+
+	/* Let sure that can alert */
+	if (should_alert()) {
+		/* Follow the private rules if set */
+		if (!(flags & CHANNEL_FLAG_BALLOON_UNSET)) {
+			alert = (flags & CHANNEL_FLAG_BALLOON);
+		} else {
+			/* Else follow global environment */
+			alert = (hexchat_get_prefs(ph, "input_balloon_priv", NULL, &priv) == 3 && priv);
+		}
+	}
 
-	if (hexchat_get_prefs (ph, "input_balloon_priv", NULL, &priv) == 3 && priv && should_alert ())
+	if (alert)
 	{
 		const char *network = hexchat_get_info (ph, "network");
 		if (!network)
diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c
index fac0c4e6..418bb4da 100644
--- a/src/fe-gtk/xtext.c
+++ b/src/fe-gtk/xtext.c
@@ -283,8 +283,24 @@ backend_font_open (GtkXText *xtext, char *name)
 	metrics = pango_context_get_metrics (context, xtext->font->font, lang);
 	xtext->font->ascent = pango_font_metrics_get_ascent (metrics) / PANGO_SCALE;
 	xtext->font->descent = pango_font_metrics_get_descent (metrics) / PANGO_SCALE;
+
+	/*
+	 * In later versions of pango, a font's height should be calculated like
+	 * this to account for line gap; a typical symptom of not doing so is
+	 * cutting off the underscore on some fonts.
+	 */
+#if PANGO_VERSION_CHECK(1, 44, 0)
+	xtext->fontsize = pango_font_metrics_get_height (metrics) / PANGO_SCALE + 1;
+
+	if (xtext->fontsize == 0)
+		xtext->fontsize = xtext->font->ascent + xtext->font->descent;
+#else
+	xtext->fontsize = xtext->font->ascent + xtext->font->descent;
+#endif
+
 	pango_font_metrics_unref (metrics);
 }
+
 static int
 backend_get_text_width_emph (GtkXText *xtext, guchar *str, int len, int emphasis)
 {
@@ -3479,8 +3495,6 @@ gtk_xtext_set_font (GtkXText *xtext, char *name)
 	if (xtext->font == NULL)
 		return FALSE;
 
-	xtext->fontsize = xtext->font->ascent + xtext->font->descent;
-
 	{
 		char *time_str;
 		int stamp_size = xtext_get_stamp_str (time(0), &time_str);
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index ac190325..1d411ddf 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -837,7 +837,7 @@ fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
 	/* only one action type handled for now, but could add more */
 	switch (action)
 	{
-	/* gui focus is really the only case hexchat-text needs to wory about */
+	/* gui focus is really the only case hexchat-text needs to worry about */
 	case FE_GUI_FOCUS:
 		current_sess = sess;
 		current_tab = sess;
diff --git a/src/fe-text/fe-text.vcxproj b/src/fe-text/fe-text.vcxproj
index 6c7c25a8..75b64a12 100644
--- a/src/fe-text/fe-text.vcxproj
+++ b/src/fe-text/fe-text.vcxproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>

 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

-    <PlatformToolset>v140</PlatformToolset>

+    <PlatformToolset>v142</PlatformToolset>

     <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

diff --git a/src/htm/Properties/Resources.Designer.cs b/src/htm/Properties/Resources.Designer.cs
index 7627ee06..8e2cd74a 100644
--- a/src/htm/Properties/Resources.Designer.cs
+++ b/src/htm/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace thememan.Properties {
     // class via a tool like ResGen or Visual Studio.

     // To add or remove a member, edit your .ResX file then rerun ResGen

     // with the /str option, or rebuild your VS project.

-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]

+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]

     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

     internal class Resources {

diff --git a/src/htm/Properties/Settings.Designer.cs b/src/htm/Properties/Settings.Designer.cs
index cf679280..c8c467e8 100644
--- a/src/htm/Properties/Settings.Designer.cs
+++ b/src/htm/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace thememan.Properties {
     

     

     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]

+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]

     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

         

         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

diff --git a/src/htm/app.config b/src/htm/app.config
index ad1957f6..b33a2051 100644
--- a/src/htm/app.config
+++ b/src/htm/app.config
@@ -1,3 +1,3 @@
 <?xml version="1.0"?>

 <configuration>

-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>

+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup></configuration>

diff --git a/src/htm/htm.csproj b/src/htm/htm.csproj
index eaf57a0f..7c96d274 100644
--- a/src/htm/htm.csproj
+++ b/src/htm/htm.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>thememan</AssemblyName>

     <FileAlignment>512</FileAlignment>

     <IsWebBootstrapper>false</IsWebBootstrapper>

-    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>

+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>

     <TargetFrameworkProfile>

     </TargetFrameworkProfile>

     <PublishUrl>publish\</PublishUrl>

diff --git a/src/libenchant_win8/libenchant_win8.vcxproj b/src/libenchant_win8/libenchant_win8.vcxproj
index 3496f978..a6cbdad6 100644
--- a/src/libenchant_win8/libenchant_win8.vcxproj
+++ b/src/libenchant_win8/libenchant_win8.vcxproj
@@ -19,7 +19,7 @@
   <PropertyGroup Label="Configuration">

     <ConfigurationType>DynamicLibrary</ConfigurationType>

     <UseDebugLibraries>true</UseDebugLibraries>

-    <PlatformToolset>v140</PlatformToolset>

+    <PlatformToolset>v142</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <Import Project="..\..\win32\hexchat.props" />