qulogic/pidgin

Merged release-2.x.y into default

2017-11-03, Gary Kramlich
17f8a2a8ccba
Merged release-2.x.y into default
--- a/COPYRIGHT Fri Nov 03 04:29:05 2017 +0000
+++ b/COPYRIGHT Fri Nov 03 01:22:04 2017 -0500
@@ -292,6 +292,7 @@
F.W. Kong
Konstantin Korikov
Cole Kowalski
+Daniel Kamil Kozar
Nikita Kozlov
Matt Kramer
Gary Kramlich
@@ -628,6 +629,7 @@
Kevin Wu Won
Pui Lam Wong
Justin Wood
+David Woodhouse
Ximian
Ma Xuan
Yonas Yanfa
--- a/ChangeLog Fri Nov 03 04:29:05 2017 +0000
+++ b/ChangeLog Fri Nov 03 01:22:04 2017 -0500
@@ -104,12 +104,22 @@
* A single jabber plugin provides XMPP, GTalk and Facebook protocols.
* A single yahoo plugin provides both Yahoo and Yahoo JAPAN protocols.
-version 2.12.1 (??/??/????):
+version 2.13.0 (??/??/????):
libpurple:
* Unified string comparison. (PR #186) (Arkadiy Illarionov)
+ * Properlly shell escape URI's when opening them. (PR #271 Daniel Kamil Kozar)
+
+ libgnt:
+ * Fixed build against curses 6.0 with opaque structs set. (#16764 dimstar)
+ (PR #268 Daniel Kamil Kozar)
+ * Fixed a crash when resizing the window. (#16680 marcus) (PR #269 Daniel Kamil Kozar)
+
+ General:
+ * Fixed bashism in autotools. (#16836 lameventanas) (PR #267 Daniel Kamil Kozar)
XMPP:
* Show XEP-0066 OOB URLs in any message, not just headlines
+ * Fix a user after free (#17200 debarshiray) (PR #266 Ethan Blanton)
IRC:
* Fix "Registration timeout" on SASL auth with InspIRCd servers
@@ -117,6 +127,14 @@
* Fix issues with plugins that modify outgoing messages
(such as the custom PART/QUIT feature of the IRC More plugin)
+ Pidgin:
+ * Better support for dark themes. (#12572 Alyssa Rosenzweig and Gary Kramlich)
+ * Fixed IPv6 links by not escaping []'s. (#16391 cyisfor) (PR #270 Daniel Kamil Kozar)
+ * Only write buddy icons to the cache if they're not already cached. (PR #276 David Woodhouse)
+
+ Finch:
+ * Fix handling of search results (#17238 David Woodhouse)
+
version 2.12.0 (03/09/2017):
libpurple:
* Fix an out of bounds memory write in purple_markup_unescape_entity.
--- a/ChangeLog.API Fri Nov 03 04:29:05 2017 +0000
+++ b/ChangeLog.API Fri Nov 03 01:22:04 2017 -0500
@@ -611,6 +611,11 @@
* _GntTreeColumnFlag
* _GntWidgetFlags
+version 2.13.0:
+ libpurple:
+ Added:
+ * purple_uri_escape_for_open
+
version 2.12.0:
libpurple:
Added:
--- a/finch/gntnotify.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/gntnotify.c Fri Nov 03 01:22:04 2017 -0500
@@ -385,11 +385,12 @@
finch_notify_sr_new_rows(PurpleConnection *gc,
PurpleNotifySearchResults *results, void *data)
{
- GntTree *tree = GNT_TREE(data);
+ GntWindow *window = GNT_WINDOW(data);
+ GntTree *tree = GNT_TREE(g_object_get_data(G_OBJECT(window), "tree-widget"));
GList *o;
GntTreeRow *prev = NULL;
- /* XXX: Do I need to empty the tree here? */
+ gnt_tree_remove_all(GNT_TREE(tree));
for (o = results->rows; o; o = o->next)
{
@@ -493,12 +494,16 @@
g_signal_connect(G_OBJECT(tree), "destroy",
G_CALLBACK(notify_sr_destroy_cb), NULL);
- finch_notify_sr_new_rows(gc, results, tree);
+ g_object_set_data(G_OBJECT(window), "tree-widget", tree);
+ finch_notify_sr_new_rows(gc, results, window);
+
+ g_signal_connect(G_OBJECT(window), "destroy",
+ G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(PURPLE_NOTIFY_SEARCHRESULTS));
gnt_widget_show(window);
g_object_set_data(G_OBJECT(window), "notify-results", results);
- return tree;
+ return window;
}
static void *
--- a/finch/libgnt/gntmain.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/libgnt/gntmain.c Fri Nov 03 01:22:04 2017 -0500
@@ -551,10 +551,11 @@
#ifdef SIGWINCH
static void (*org_winch_handler)(int);
+static void (*org_winch_handler_sa)(int, siginfo_t *, void *);
#endif
static void
-sighandler(int sig)
+sighandler(int sig, siginfo_t *info, void *data)
{
switch (sig) {
#ifdef SIGWINCH
@@ -563,18 +564,17 @@
g_idle_add((GSourceFunc)refresh_screen, NULL);
if (org_winch_handler)
org_winch_handler(sig);
- signal(SIGWINCH, sighandler);
+ if (org_winch_handler_sa)
+ org_winch_handler_sa(sig, info, data);
break;
#endif
#ifndef _WIN32
case SIGCHLD:
clean_pid();
- signal(SIGCHLD, sighandler);
break;
#endif
case SIGINT:
ask_before_exit();
- signal(SIGINT, sighandler);
break;
}
}
@@ -602,6 +602,10 @@
{
char *filename;
const char *locale;
+ struct sigaction act;
+#ifdef SIGWINCH
+ struct sigaction oact;
+#endif
if (channel)
return;
@@ -654,14 +658,26 @@
werase(stdscr);
wrefresh(stdscr);
+ act.sa_sigaction = sighandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+
#ifdef SIGWINCH
- org_winch_handler = signal(SIGWINCH, sighandler);
+ org_winch_handler = NULL;
+ org_winch_handler_sa = NULL;
+ sigaction(SIGWINCH, &act, &oact);
+ if (oact.sa_flags & SA_SIGINFO)
+ {
+ org_winch_handler_sa = oact.sa_sigaction;
+ }
+ else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN)
+ {
+ org_winch_handler = oact.sa_handler;
+ }
#endif
-#ifndef _WIN32
- signal(SIGCHLD, sighandler);
+ sigaction(SIGCHLD, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
signal(SIGPIPE, SIG_IGN);
-#endif
- signal(SIGINT, sighandler);
#if !GLIB_CHECK_VERSION(2, 36, 0)
/* GLib type system is automaticaly initialized since 2.36. */
--- a/finch/libgnt/gntwm.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/libgnt/gntwm.c Fri Nov 03 01:22:04 2017 -0500
@@ -166,37 +166,37 @@
cchar_t ch;
PANEL *below = panel;
- sx = panel->win->_begx;
- ex = panel->win->_maxx + sx;
- sy = panel->win->_begy;
- ey = panel->win->_maxy + sy;
+ sx = getbegx(panel->win);
+ ex = getmaxx(panel->win) + sx;
+ sy = getbegy(panel->win);
+ ey = getmaxy(panel->win) + sy;
while ((below = panel_below(below)) != NULL) {
- if (sy > below->win->_begy + below->win->_maxy ||
- ey < below->win->_begy)
+ if (sy > getbegy(below->win) + getmaxy(below->win) ||
+ ey < getbegy(below->win))
continue;
- if (sx > below->win->_begx + below->win->_maxx ||
- ex < below->win->_begx)
+ if (sx > getbegx(below->win) + getmaxx(below->win) ||
+ ex < getbegx(below->win))
continue;
- for (y = MAX(sy, below->win->_begy); y <= MIN(ey, below->win->_begy + below->win->_maxy); y++) {
- if (mvwin_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch) != OK)
+ for (y = MAX(sy, getbegy(below->win)); y <= MIN(ey, getbegy(below->win) + getmaxy(below->win)); y++) {
+ if (mvwin_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch) != OK)
goto right;
w = widestringwidth(ch.chars);
if (w > 1 && (ch.attr & 1)) {
ch.chars[0] = ' ';
ch.attr &= ~ A_CHARTEXT;
- mvwadd_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch);
- touchline(below->win, y - below->win->_begy, 1);
+ mvwadd_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch);
+ touchline(below->win, y - getbegy(below->win), 1);
}
right:
- if (mvwin_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch) != OK)
+ if (mvwin_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch) != OK)
continue;
w = widestringwidth(ch.chars);
if (w > 1 && !(ch.attr & 1)) {
ch.chars[0] = ' ';
ch.attr &= ~ A_CHARTEXT;
- mvwadd_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch);
- touchline(below->win, y - below->win->_begy, 1);
+ mvwadd_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch);
+ touchline(below->win, y - getbegy(below->win), 1);
}
}
}
--- a/libpurple/buddyicon.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/buddyicon.c Fri Nov 03 01:22:04 2017 -0500
@@ -176,6 +176,7 @@
if (!purple_image_save(img, path))
purple_debug_error("buddyicon", "failed to save icon %s", path);
+
g_free(path);
}
--- a/libpurple/media.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/media.c Fri Nov 03 01:22:04 2017 -0500
@@ -1458,20 +1458,12 @@
gchar dtmf, guint8 volume, guint16 duration)
{
#ifdef USE_VV
- PurpleAccount *account = NULL;
- PurpleConnection *gc = NULL;
- PurpleProtocol *protocol = NULL;
PurpleMediaBackendIface *backend_iface = NULL;
if (media)
{
- account = purple_media_get_account(media);
backend_iface = PURPLE_MEDIA_BACKEND_GET_INTERFACE(media->priv->backend);
}
- if (account)
- gc = purple_account_get_connection(account);
- if (gc)
- protocol = purple_connection_get_protocol(gc);
if (dtmf == 'a')
dtmf = 'A';
@@ -1484,11 +1476,7 @@
g_return_val_if_fail(strchr("0123456789ABCD#*", dtmf), FALSE);
- if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, MEDIA_IFACE, send_dtmf)
- && purple_protocol_media_iface_send_dtmf(protocol, media, dtmf, volume, duration))
- {
- return TRUE;
- } else if (backend_iface && backend_iface->send_dtmf
+ if (backend_iface && backend_iface->send_dtmf
&& backend_iface->send_dtmf(media->priv->backend,
session_id, dtmf, volume, duration))
{
--- a/libpurple/media/backend-fs2.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/media/backend-fs2.c Fri Nov 03 01:22:04 2017 -0500
@@ -1059,7 +1059,7 @@
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
PurpleMediaBackendFs2Stream *media_stream;
- gchar *name;
+ const gchar *name;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
@@ -1073,8 +1073,7 @@
local_candidate->foundation);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
+ name = g_object_get_data(G_OBJECT(participant), "purple-name");
media_stream = get_stream(self, session->id, name);
media_stream->local_candidates = g_list_append(
@@ -1085,24 +1084,25 @@
g_signal_emit_by_name(self, "new-candidate",
session->id, name, candidate);
g_object_unref(candidate);
+ g_object_unref(participant);
} else if (gst_structure_has_name(structure,
"farstream-local-candidates-prepared")) {
const GValue *value;
FsStream *stream;
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
- gchar *name;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
session = get_session_from_fs_stream(self, stream);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
g_signal_emit_by_name(self, "candidates-prepared",
- session->id, name);
+ session->id,
+ g_object_get_data(G_OBJECT(participant), "purple-name"));
+
+ g_object_unref(participant);
} else if (gst_structure_has_name(structure,
"farstream-new-active-candidate-pair")) {
const GValue *value;
@@ -1112,7 +1112,6 @@
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
PurpleMediaCandidate *lcandidate, *rcandidate;
- gchar *name;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
@@ -1122,8 +1121,6 @@
remote_candidate = g_value_get_boxed(value);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
session = get_session_from_fs_stream(self, stream);
@@ -1131,8 +1128,11 @@
rcandidate = candidate_from_fs(remote_candidate);
g_signal_emit_by_name(self, "active-candidate-pair",
- session->id, name, lcandidate, rcandidate);
-
+ session->id,
+ g_object_get_data(G_OBJECT(participant), "purple-name"),
+ lcandidate, rcandidate);
+
+ g_object_unref(participant);
g_object_unref(lcandidate);
g_object_unref(rcandidate);
} else if (gst_structure_has_name(structure,
--- a/libpurple/protocols/gg/blist.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/protocols/gg/blist.c Fri Nov 03 01:22:04 2017 -0500
@@ -125,7 +125,7 @@
g = g_strdup("Gadu-Gadu");
- if ('\0' != data_tbl[F_GROUP]) {
+ if ('\0' != *(data_tbl[F_GROUP])) {
/* XXX: Probably buddy should be added to all the groups. */
/* Hard limit to at most 50 groups */
gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
--- a/libpurple/protocols/jabber/jingle/rtp.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c Fri Nov 03 01:22:04 2017 -0500
@@ -819,6 +819,7 @@
JingleTransport *transport;
JabberBuddy *jb;
JabberBuddyResource *jbr;
+ gboolean ret = FALSE;
const gchar *transport_type;
gchar *resource = NULL, *me = NULL, *sid = NULL;
@@ -827,16 +828,15 @@
jb = jabber_buddy_find(js, who, FALSE);
if (!jb) {
purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n");
- return FALSE;
+ goto out;
}
resource = jabber_get_resource(who);
jbr = jabber_buddy_find_resource(jb, resource);
- g_free(resource);
if (!jbr) {
purple_debug_error("jingle-rtp", "Could not find buddy's resource - %s\n", resource);
- return FALSE;
+ goto out;
}
if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_ICEUDP)) {
@@ -848,7 +848,7 @@
} else {
purple_debug_error("jingle-rtp", "Resource doesn't support "
"the same transport types\n");
- return FALSE;
+ goto out;
}
/* set ourselves as initiator */
@@ -856,7 +856,6 @@
sid = jabber_get_next_id(js);
session = jingle_session_create(js, sid, me, who, TRUE);
- g_free(sid);
if (type & PURPLE_MEDIA_AUDIO) {
@@ -878,13 +877,17 @@
g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
}
- g_free(me);
-
if (jingle_rtp_get_media(session) == NULL) {
- return FALSE;
+ goto out;
}
- return TRUE;
+ ret = TRUE;
+
+out:
+ g_free(me);
+ g_free(resource);
+ g_free(sid);
+ return ret;
}
void
--- a/libpurple/tests/test_util.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/tests/test_util.c Fri Nov 03 01:22:04 2017 -0500
@@ -523,6 +523,30 @@
}
/******************************************************************************
+ * URI Escaping
+ *****************************************************************************/
+static void
+test_uri_escape_for_open(void) {
+ /* make sure shell stuff is escaped... */
+ gchar *result = purple_uri_escape_for_open("https://$(xterm)");
+ g_assert_cmpstr("https://%24%28xterm%29", ==, result);
+ g_free(result);
+
+ result = purple_uri_escape_for_open("https://`xterm`");
+ g_assert_cmpstr("https://%60xterm%60", ==, result);
+ g_free(result);
+
+ result = purple_uri_escape_for_open("https://$((25 + 13))");
+ g_assert_cmpstr("https://%24%28%2825%20+%2013%29%29", ==, result);
+ g_free(result);
+
+ /* ...but keep brackets so that ipv6 links can be opened. */
+ result = purple_uri_escape_for_open("https://[123:4567:89a::::]");
+ g_assert_cmpstr("https://[123:4567:89a::::]", ==, result);
+ g_free(result);
+}
+
+/******************************************************************************
* MANE
*****************************************************************************/
gint
@@ -570,5 +594,8 @@
g_test_add_func("/util/test_strdup_withhtml",
test_util_strdup_withhtml);
+ g_test_add_func("/util/test_uri_escape_for_open",
+ test_uri_escape_for_open);
+
return g_test_run();
}
--- a/libpurple/util.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/util.c Fri Nov 03 01:22:04 2017 -0500
@@ -1472,7 +1472,7 @@
pln = "\302\256"; /* or use g_unichar_to_utf8(0xae); */
else if(IS_ENTITY("&apos;"))
pln = "\'";
- else if(text[1] == '#' && g_ascii_isxdigit(text[2])) {
+ else if(text[1] == '#' && (g_ascii_isxdigit(text[2]) || text[2] == 'x')) {
static char buf[7];
const char *start = text + 2;
char *end;
@@ -4271,6 +4271,17 @@
return result;
}
+char *
+purple_uri_escape_for_open(const char *unescaped)
+{
+ /* Replace some special characters like $ with their percent-encoded value.
+ * This shouldn't be necessary because we shell-escape the entire arg before
+ * exec'ing the browser, however, we had a report that a URL containing
+ * $(xterm) was causing xterm to start on his system. This is obviously a
+ * bug on his system, but it's pretty easy for us to protect against it. */
+ return g_uri_escape_string(unescaped, "[]:;/%#,+?=&@", FALSE);
+}
+
/**************************************************************************
* UTF8 String Functions
**************************************************************************/
--- a/libpurple/util.h Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/util.h Fri Nov 03 01:22:04 2017 -0500
@@ -1329,6 +1329,17 @@
*/
GList *purple_uri_list_extract_filenames(const gchar *uri_list);
+/**
+ * This function escapes any characters that might be interpreted by the shell
+ * when executing a program to open a URI on some systems.
+ *
+ * @param unescaped The unescaped URI.
+ *
+ * @return A newly allocated string with any shell metacharacters replaced with
+ * their escaped equivalents.
+ */
+char *purple_uri_escape_for_open(const char *unescaped);
+
/**************************************************************************
* UTF8 String Functions
**************************************************************************/
--- a/libpurple/win32/libc_interface.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/win32/libc_interface.c Fri Nov 03 01:22:04 2017 -0500
@@ -33,6 +33,7 @@
#include <glib.h>
#include "debug.h"
#include "libc_internal.h"
+#include "util.h"
#include <glib/gstdio.h>
#include "util.h"
--- a/pidgin/Makefile.am Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/Makefile.am Fri Nov 03 01:22:04 2017 -0500
@@ -79,6 +79,7 @@
gtksound.c \
gtkstatus-icon-theme.c \
gtkstatusbox.c \
+ gtkstyle.c \
gtkutils.c \
gtkwebview.c \
gtkwebviewtoolbar.c \
@@ -128,6 +129,7 @@
gtksound.h \
gtkstatus-icon-theme.h \
gtkstatusbox.h \
+ gtkstyle.h \
pidginstock.h \
gtkutils.h \
gtkwebview.h \
--- a/pidgin/gtkblist.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtkblist.c Fri Nov 03 01:22:04 2017 -0500
@@ -55,6 +55,7 @@
#include "gtkstatusbox.h"
#include "gtkscrollbook.h"
#include "gtksmiley-manager.h"
+#include "gtkstyle.h"
#include "gtkblist-theme.h"
#include "gtkblist-theme-loader.h"
#include "gtkutils.h"
@@ -4251,7 +4252,7 @@
gchar *
pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased)
{
- const char *name, *name_color, *name_font, *status_color, *status_font;
+ const char *name, *name_color, *name_font, *status_color, *status_font, *dim_grey;
char *text = NULL;
PurpleProtocol *protocol = NULL;
PurpleContact *contact;
@@ -4354,13 +4355,15 @@
theme = pidgin_blist_get_theme();
name_color = NULL;
+ dim_grey = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey";
+
if (theme) {
if (purple_presence_is_idle(presence)) {
namefont = statusfont = pidgin_blist_theme_get_idle_text_info(theme);
- name_color = "dim grey";
+ name_color = dim_grey;
} else if (!purple_presence_is_online(presence)) {
namefont = pidgin_blist_theme_get_offline_text_info(theme);
- name_color = "dim grey";
+ name_color = dim_grey;
statusfont = pidgin_blist_theme_get_status_text_info(theme);
} else if (purple_presence_is_available(presence)) {
namefont = pidgin_blist_theme_get_online_text_info(theme);
@@ -4374,14 +4377,14 @@
&& (purple_presence_is_idle(presence)
|| !purple_presence_is_online(presence)))
{
- name_color = "dim grey";
+ name_color = dim_grey;
}
}
name_color = theme_font_get_color_default(namefont, name_color);
name_font = theme_font_get_face_default(namefont, "");
- status_color = theme_font_get_color_default(statusfont, "dim grey");
+ status_color = theme_font_get_color_default(statusfont, dim_grey);
status_font = theme_font_get_face_default(statusfont, "");
if (aliased && selected) {
@@ -6554,7 +6557,7 @@
textcolor = pidgin_theme_font_get_color_describe(pair);
else
/* If no theme them default to making idle buddy names grey */
- textcolor = "dim grey";
+ textcolor = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey";
if (textcolor) {
idle = g_strdup_printf("<span color='%s' font_desc='%s'>%d:%02d</span>",
--- a/pidgin/gtkconv.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtkconv.c Fri Nov 03 01:22:04 2017 -0500
@@ -61,6 +61,7 @@
#include "gtkpounce.h"
#include "gtkprefs.h"
#include "gtkprivacy.h"
+#include "gtkstyle.h"
#include "gtkutils.h"
#include "gtkwebview.h"
#include "pidginstock.h"
@@ -8940,6 +8941,57 @@
e2ee_stock = NULL;
}
+/* Invalidate the first tab color set */
+static gboolean tab_color_fuse = TRUE;
+
+static void
+pidgin_conversations_set_tab_colors(void)
+{
+ /* Set default tab colors */
+ GString *str = g_string_new(NULL);
+ GtkSettings *settings = gtk_settings_get_default();
+ GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now;
+ struct {
+ const char *stylename;
+ const char *labelname;
+ const char *color;
+ } styles[] = {
+ {"pidgin_tab_label_typing_default", "tab-label-typing", "#4e9a06"},
+ {"pidgin_tab_label_typed_default", "tab-label-typed", "#c4a000"},
+ {"pidgin_tab_label_attention_default", "tab-label-attention", "#006aff"},
+ {"pidgin_tab_label_unreadchat_default", "tab-label-unreadchat", "#cc0000"},
+ {"pidgin_tab_label_event_default", "tab-label-event", "#888a85"},
+ {NULL, NULL, NULL}
+ };
+ int iter;
+
+ if(tab_color_fuse) {
+ tab_color_fuse = FALSE;
+ return;
+ }
+
+ for (iter = 0; styles[iter].stylename; iter++) {
+ now = gtk_rc_get_style_by_paths(settings, styles[iter].labelname, NULL, G_TYPE_NONE);
+ if (parent == now ||
+ (parent && now && parent->rc_style == now->rc_style)) {
+ GdkColor color;
+ gdk_color_parse(styles[iter].color, &color);
+ pidgin_style_adjust_contrast(gtk_widget_get_default_style(), &color);
+
+ g_string_append_printf(str, "style \"%s\" {\n"
+ "fg[ACTIVE] = \"%s\"\n"
+ "}\n"
+ "widget \"*%s\" style \"%s\"\n",
+ styles[iter].stylename,
+ gdk_color_to_string(&color),
+ styles[iter].labelname, styles[iter].stylename);
+ }
+ }
+ gtk_rc_parse_string(str->str);
+ g_string_free(str, TRUE);
+ gtk_rc_reset_styles(settings);
+}
+
void
pidgin_conversations_uninit(void)
{
@@ -10247,6 +10299,9 @@
purple_signal_emit(pidgin_conversations_get_handle(),
"conversation-window-created", win);
+ /* Fix colours */
+ pidgin_conversations_set_tab_colors();
+
return win;
}
@@ -11210,6 +11265,9 @@
gdk_rgba_parse(&nick_highlight, DEFAULT_HIGHLIGHT_COLOR);
gdk_rgba_parse(&send_color, DEFAULT_SEND_COLOR);
+ pidgin_style_adjust_contrast(NULL, &nick_highlight);
+ pidgin_style_adjust_contrast(NULL, &send_color);
+
srand(background.red * 65535 + background.green * 65535 + background.blue * 65535 + 1);
breakout_time = time(NULL) + 3;
--- a/pidgin/gtknotify.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtknotify.c Fri Nov 03 01:22:04 2017 -0500
@@ -1336,13 +1336,7 @@
GSList *argv = NULL, *argv_remote = NULL;
gchar **usercmd_argv = NULL;
- /* Replace some special characters like $ with their percent-encoded
- value. This shouldn't be necessary because we shell-escape the entire
- arg before exec'ing the browser, however, we had a report that a URL
- containing $(xterm) was causing xterm to start on his system. This is
- obviously a bug on his system, but it's pretty easy for us to protect
- against it. */
- uri_escaped = g_uri_escape_string(uri, ":;/%#,+?=&@", FALSE);
+ uri_escaped = purple_uri_escape_for_open(uri);
web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT
"/browsers/browser");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkstyle.c Fri Nov 03 01:22:04 2017 -0500
@@ -0,0 +1,70 @@
+/*
+ * @file gtkstyle.c GTK+ Style utility functions
+ * @ingroup pidgin
+ */
+
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ */
+#include "gtkstyle.h"
+
+/* Assume light mode */
+static gboolean dark_mode_cache = FALSE;
+
+gboolean
+pidgin_style_is_dark(GtkStyle *style) {
+ GdkColor bg;
+
+ if (!style) {
+ return dark_mode_cache;
+ }
+
+ bg = style->base[GTK_STATE_NORMAL];
+
+ if (bg.red != 0xFFFF || bg.green != 0xFFFF || bg.blue != 0xFFFF) {
+ dark_mode_cache = ((int) bg.red + (int) bg.green + (int) bg.blue) < (65536 * 3 / 2);
+ }
+
+ return dark_mode_cache;
+}
+
+void
+pidgin_style_adjust_contrast(GtkStyle *style, GdkColor *color) {
+ if (pidgin_style_is_dark(style)) {
+ gdouble r, g, b, h, s, v;
+
+ r = ((gdouble) color->red) / 65535.0;
+ g = ((gdouble) color->green) / 65535.0;
+ b = ((gdouble) color->blue) / 65535.0;
+
+ gtk_rgb_to_hsv(r, g, b, &h, &s, &v);
+
+ v += 0.3;
+ v = v > 1.0 ? 1.0 : v;
+ s = 0.7;
+
+ gtk_hsv_to_rgb(h, s, v, &r, &g, &b);
+
+ color->red = (guint16) (r * 65535.0);
+ color->green = (guint16) (g * 65535.0);
+ color->blue = (guint16) (b * 65535.0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkstyle.h Fri Nov 03 01:22:04 2017 -0500
@@ -0,0 +1,59 @@
+/**
+ * @file gtkstyle.h GTK+ Style utility functions
+ * @ingroup pidgin
+ */
+
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+#ifndef _PIDGINSTYLE_H_
+#define _PIDGINSTYLE_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/*@{*/
+
+/**
+ * Returns TRUE if dark mode is enabled and foreground colours should be invertred
+ *
+ * @param style The GtkStyle in use, or NULL to use a cached version.
+ *
+ * @return @c TRUE if dark mode, @c FALSE otherwise
+ */
+
+gboolean pidgin_style_is_dark(GtkStyle *style);
+
+/**
+ * Lighten a color if dark mode is enabled.
+ *
+ * @param style The GtkStyle in use.
+ *
+ * @param color Color to be lightened. Transformed color will be written here.
+ */
+
+void pidgin_style_adjust_contrast(GtkStyle *style, GdkColor *color);
+
+/*@}*/
+
+G_END_DECLS
+
+#endif /* _PIDGINSTYLE_H_ */
--- a/pidgin/meson.build Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/meson.build Fri Nov 03 01:22:04 2017 -0500
@@ -35,6 +35,7 @@
'gtksound.c',
'gtkstatus-icon-theme.c',
'gtkstatusbox.c',
+ 'gtkstyle.c',
'gtkutils.c',
'gtkwebview.c',
'gtkwebviewtoolbar.c',
@@ -84,6 +85,7 @@
'gtksound.h',
'gtkstatus-icon-theme.h',
'gtkstatusbox.h',
+ 'gtkstyle.h',
'pidginstock.h',
'gtkutils.h',
'gtkwebview.h',