summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Sales de Andrade <qulogic@pidgin.im>2012-01-04 02:37:25 +0000
committerElliott Sales de Andrade <qulogic@pidgin.im>2012-01-04 02:37:25 +0000
commitd37ef1e7fc266048d95ebcb16b9acdc49966f283 (patch)
treee27fb44fd8805a7999c0dfb8d6d9b6193c801473
parent669b95c40b4ed25e4f854288ebf551451d814d69 (diff)
parent6b02f78c6b5a13b9df1d49244d42b567497afd13 (diff)
downloadpidgin-d37ef1e7fc266048d95ebcb16b9acdc49966f283.tar.gz
propagate from branch 'im.pidgin.pidgin' (head 8b3b9ddcd0bd7144422bace37a221553a5fc68b2)
to branch 'im.pidgin.cpw.qulogic.gtk3' (head e3a2c79c88c5aa07e534bbbd6c9e80f44560c390)
-rw-r--r--finch/finch.c12
-rw-r--r--libpurple/account.h8
-rw-r--r--libpurple/accountopt.h9
-rw-r--r--libpurple/blist.h8
-rw-r--r--libpurple/buddyicon.h9
-rw-r--r--libpurple/certificate.h11
-rw-r--r--libpurple/circbuffer.h10
-rw-r--r--libpurple/cmds.h8
-rw-r--r--libpurple/connection.h8
-rw-r--r--libpurple/conversation.h8
-rw-r--r--libpurple/core.h8
-rw-r--r--libpurple/dbus-bindings.h8
-rw-r--r--libpurple/dbus-useful.h6
-rw-r--r--libpurple/debug.h8
-rw-r--r--libpurple/dnsquery.h8
-rw-r--r--libpurple/dnssrv.h10
-rw-r--r--libpurple/eventloop.h10
-rw-r--r--libpurple/ft.h8
-rw-r--r--libpurple/idle.h8
-rw-r--r--libpurple/imgstore.h8
-rw-r--r--libpurple/log.h8
-rw-r--r--libpurple/media-gst.h10
-rw-r--r--libpurple/media.h16
-rw-r--r--libpurple/mediamanager.h10
-rw-r--r--libpurple/mime.h10
-rw-r--r--libpurple/nat-pmp.h20
-rw-r--r--libpurple/network.h10
-rw-r--r--libpurple/notify.h8
-rw-r--r--libpurple/ntlm.h8
-rw-r--r--libpurple/plugin.h8
-rw-r--r--libpurple/pluginpref.h8
-rw-r--r--libpurple/pounce.h8
-rw-r--r--libpurple/prefs.h8
-rw-r--r--libpurple/privacy.h10
-rw-r--r--libpurple/protocols/jabber/auth_cyrus.c11
-rw-r--r--libpurple/proxy.h8
-rw-r--r--libpurple/prpl.h8
-rw-r--r--libpurple/request.h8
-rw-r--r--libpurple/roomlist.h8
-rw-r--r--libpurple/savedstatuses.h9
-rw-r--r--libpurple/server.h9
-rw-r--r--libpurple/signals.h9
-rw-r--r--libpurple/smiley.h8
-rw-r--r--libpurple/sound.h8
-rw-r--r--libpurple/sslconn.h8
-rw-r--r--libpurple/status.h9
-rw-r--r--libpurple/stringref.h10
-rw-r--r--libpurple/stun.h10
-rw-r--r--libpurple/upnp.h8
-rw-r--r--libpurple/util.h10
-rw-r--r--libpurple/value.h8
-rw-r--r--libpurple/whiteboard.h8
-rw-r--r--libpurple/xmlnode.h10
-rw-r--r--pidgin/gtkaccount.h4
-rw-r--r--pidgin/gtkblist-theme.h32
-rw-r--r--pidgin/gtkblist.h3
-rw-r--r--pidgin/gtkcellrendererexpander.h12
-rw-r--r--pidgin/gtkcertmgr.h4
-rw-r--r--pidgin/gtkconn.h4
-rw-r--r--pidgin/gtkconv-theme.c1
-rw-r--r--pidgin/gtkconv.c168
-rw-r--r--pidgin/gtkconv.h4
-rw-r--r--pidgin/gtkconvwin.h4
-rw-r--r--pidgin/gtkdebug.h4
-rw-r--r--pidgin/gtkdialogs.h4
-rw-r--r--pidgin/gtkdnd-hints.h4
-rw-r--r--pidgin/gtkdocklet.h4
-rw-r--r--pidgin/gtkeventloop.h4
-rw-r--r--pidgin/gtkft.h4
-rw-r--r--pidgin/gtkidle.h4
-rw-r--r--pidgin/gtkimhtml.h8
-rw-r--r--pidgin/gtkimhtmltoolbar.h8
-rw-r--r--pidgin/gtklog.h3
-rw-r--r--pidgin/gtkmain.c11
-rw-r--r--pidgin/gtknotify.h4
-rw-r--r--pidgin/gtkplugin.h4
-rw-r--r--pidgin/gtkpluginpref.h8
-rw-r--r--pidgin/gtkpounce.h4
-rw-r--r--pidgin/gtkprefs.h4
-rw-r--r--pidgin/gtkprivacy.h4
-rw-r--r--pidgin/gtkrequest.h4
-rw-r--r--pidgin/gtkroomlist.h4
-rw-r--r--pidgin/gtksavedstatuses.h4
-rw-r--r--pidgin/gtksession.h4
-rw-r--r--pidgin/gtksmiley.h4
-rw-r--r--pidgin/gtksound.h4
-rw-r--r--pidgin/gtksourceundomanager.h4
-rw-r--r--pidgin/gtkthemes.h4
-rw-r--r--pidgin/gtkutils.h8
-rw-r--r--pidgin/gtkwebview.c470
-rw-r--r--pidgin/gtkwebview.h65
-rw-r--r--pidgin/gtkwhiteboard.h8
-rw-r--r--pidgin/pidgintooltip.h4
-rw-r--r--pidgin/plugins/Makefile.am4
-rw-r--r--pidgin/plugins/markerline.c120
-rw-r--r--pidgin/smileyparser.h4
-rw-r--r--pidgin/themes/Template.html367
97 files changed, 1027 insertions, 859 deletions
diff --git a/finch/finch.c b/finch/finch.c
index 5157e8016c..1af4e87694 100644
--- a/finch/finch.c
+++ b/finch/finch.c
@@ -339,7 +339,17 @@ init_libpurple(int argc, char **argv)
/* set a user-specified config directory */
if (opt_config_dir_arg != NULL) {
- purple_util_set_user_dir(opt_config_dir_arg);
+ if (g_path_is_absolute(opt_config_dir_arg)) {
+ purple_util_set_user_dir(opt_config_dir_arg);
+ } else {
+ /* Make an absolute (if not canonical) path */
+ char *cwd = g_get_current_dir();
+ char *path = g_build_path(G_DIR_SEPARATOR_S, cwd, opt_config_dir_arg, NULL);
+ purple_util_set_user_dir(path);
+ g_free(path);
+ g_free(cwd);
+ }
+
g_free(opt_config_dir_arg);
}
diff --git a/libpurple/account.h b/libpurple/account.h
index 69fd16cbe9..70296b82d9 100644
--- a/libpurple/account.h
+++ b/libpurple/account.h
@@ -171,9 +171,7 @@ struct _PurpleAccount
PurpleConnectionErrorInfo *current_error; /**< Errors */
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Account API */
@@ -1191,8 +1189,6 @@ void purple_accounts_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_ACCOUNT_H_ */
diff --git a/libpurple/accountopt.h b/libpurple/accountopt.h
index b0b7d392ea..eed7b4f657 100644
--- a/libpurple/accountopt.h
+++ b/libpurple/accountopt.h
@@ -37,10 +37,7 @@ typedef struct _PurpleAccountOption PurpleAccountOption;
/** @copydoc _PurpleAccountUserSplit */
typedef struct _PurpleAccountUserSplit PurpleAccountUserSplit;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Account Option API */
@@ -353,8 +350,6 @@ void purple_account_user_split_set_reverse(PurpleAccountUserSplit *split, gboole
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_ACCOUNTOPT_H_ */
diff --git a/libpurple/blist.h b/libpurple/blist.h
index c7f9b636c5..881c3fa1b7 100644
--- a/libpurple/blist.h
+++ b/libpurple/blist.h
@@ -244,9 +244,7 @@ struct _PurpleBlistUiOps
void (*_purple_reserved1)(void);
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Buddy List API */
@@ -1202,8 +1200,6 @@ void purple_blist_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_BLIST_H_ */
diff --git a/libpurple/buddyicon.h b/libpurple/buddyicon.h
index 193277e3ed..873f828304 100644
--- a/libpurple/buddyicon.h
+++ b/libpurple/buddyicon.h
@@ -39,10 +39,7 @@ typedef struct _PurpleBuddyIcon PurpleBuddyIcon;
#include "prpl.h"
#include "util.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Buddy Icon API */
@@ -397,8 +394,6 @@ void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_BUDDYICON_H_ */
diff --git a/libpurple/certificate.h b/libpurple/certificate.h
index c13b38696d..bee2a0ffca 100644
--- a/libpurple/certificate.h
+++ b/libpurple/certificate.h
@@ -34,11 +34,6 @@
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
typedef enum
{
PURPLE_CERTIFICATE_INVALID = 0,
@@ -357,6 +352,8 @@ struct _PurpleCertificateVerificationRequest
gpointer cb_data;
};
+G_BEGIN_DECLS
+
/*****************************************************************************/
/** @name Certificate Verification Functions */
/*****************************************************************************/
@@ -833,8 +830,6 @@ purple_certificate_display_x509(PurpleCertificate *crt);
*/
void purple_certificate_add_ca_search_path(const char *path);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* _PURPLE_CERTIFICATE_H */
diff --git a/libpurple/circbuffer.h b/libpurple/circbuffer.h
index 77e7724161..7e9283404c 100644
--- a/libpurple/circbuffer.h
+++ b/libpurple/circbuffer.h
@@ -26,10 +26,6 @@
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
typedef struct _PurpleCircBuffer {
/** A pointer to the starting address of our chunk of memory. */
@@ -55,6 +51,8 @@ typedef struct _PurpleCircBuffer {
} PurpleCircBuffer;
+G_BEGIN_DECLS
+
/**
* Creates a new circular buffer. This will not allocate any memory for the
* actual buffer until data is appended to it.
@@ -111,8 +109,6 @@ gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf);
*/
gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _CIRCBUFFER_H */
diff --git a/libpurple/cmds.h b/libpurple/cmds.h
index 87fce8090d..80549afdf1 100644
--- a/libpurple/cmds.h
+++ b/libpurple/cmds.h
@@ -99,9 +99,7 @@ typedef enum {
/*@}*/
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Commands API */
@@ -240,8 +238,6 @@ void purple_cmds_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_CMDS_H_ */
diff --git a/libpurple/connection.h b/libpurple/connection.h
index 9ff72d4ed3..65c88d61b1 100644
--- a/libpurple/connection.h
+++ b/libpurple/connection.h
@@ -258,9 +258,7 @@ struct _PurpleConnection
prpl to avoid sending unneeded keepalives */
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Connection API */
@@ -543,8 +541,6 @@ void *purple_connections_get_handle(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_CONNECTION_H_ */
diff --git a/libpurple/conversation.h b/libpurple/conversation.h
index 32e992f352..80262ef809 100644
--- a/libpurple/conversation.h
+++ b/libpurple/conversation.h
@@ -249,9 +249,7 @@ struct _PurpleConversationUiOps
void (*_purple_reserved4)(void);
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Conversation API */
@@ -1402,8 +1400,6 @@ void purple_conversations_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_CONVERSATION_H_ */
diff --git a/libpurple/core.h b/libpurple/core.h
index 5c67e35dd6..19447b159f 100644
--- a/libpurple/core.h
+++ b/libpurple/core.h
@@ -76,9 +76,7 @@ typedef struct
void (*_purple_reserved3)(void);
} PurpleCoreUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Initializes the core of purple.
@@ -197,9 +195,7 @@ gboolean purple_core_ensure_single_instance(void);
*/
GHashTable* purple_core_get_ui_info(void);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_CORE_H_ */
diff --git a/libpurple/dbus-bindings.h b/libpurple/dbus-bindings.h
index 1d6f95875e..4bd7fa6f96 100644
--- a/libpurple/dbus-bindings.h
+++ b/libpurple/dbus-bindings.h
@@ -32,9 +32,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
gint purple_dbus_pointer_to_id(gconstpointer node);
gpointer purple_dbus_id_to_pointer(gint id, PurpleDBusType *type);
@@ -103,8 +101,6 @@ void purple_dbus_register_bindings(void *handle, PurpleDBusBinding *bindings);
DBusConnection *purple_dbus_get_connection(void);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif
diff --git a/libpurple/dbus-useful.h b/libpurple/dbus-useful.h
index 663c4c7a10..9d7b34dc5a 100644
--- a/libpurple/dbus-useful.h
+++ b/libpurple/dbus-useful.h
@@ -1,5 +1,7 @@
#include "conversation.h"
+G_BEGIN_DECLS
+
PurpleAccount *purple_accounts_find_ext(const char *name, const char *protocol_id,
gboolean (*account_test)(const PurpleAccount *account));
@@ -7,7 +9,5 @@ PurpleAccount *purple_accounts_find_any(const char *name, const char *protocol);
PurpleAccount *purple_accounts_find_connected(const char *name, const char *protocol);
-
-
-
+G_END_DECLS
diff --git a/libpurple/debug.h b/libpurple/debug.h
index 475df9f335..ba7cc92ef3 100644
--- a/libpurple/debug.h
+++ b/libpurple/debug.h
@@ -59,9 +59,7 @@ typedef struct
void (*_purple_reserved4)(void);
} PurpleDebugUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Debug API */
@@ -228,8 +226,6 @@ void purple_debug_init(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_DEBUG_H_ */
diff --git a/libpurple/dnsquery.h b/libpurple/dnsquery.h
index 84183f4383..9c811b684f 100644
--- a/libpurple/dnsquery.h
+++ b/libpurple/dnsquery.h
@@ -76,9 +76,7 @@ typedef struct
void (*_purple_reserved4)(void);
} PurpleDnsQueryUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name DNS query API */
@@ -154,8 +152,6 @@ void purple_dnsquery_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_DNSQUERY_H_ */
diff --git a/libpurple/dnssrv.h b/libpurple/dnssrv.h
index c0eb194c41..747d8bda17 100644
--- a/libpurple/dnssrv.h
+++ b/libpurple/dnssrv.h
@@ -24,10 +24,6 @@
#ifndef _PURPLE_DNSSRV_H
#define _PURPLE_DNSSRV_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
typedef struct _PurpleSrvTxtQueryData PurpleSrvTxtQueryData;
typedef struct _PurpleSrvResponse PurpleSrvResponse;
typedef struct _PurpleTxtResponse PurpleTxtResponse;
@@ -96,6 +92,8 @@ typedef void (*PurpleSrvCallback)(PurpleSrvResponse *resp, int results, gpointer
*/
typedef void (*PurpleTxtCallback)(GList *responses, gpointer data);
+G_BEGIN_DECLS
+
/**
* Queries an SRV record.
*
@@ -184,9 +182,7 @@ char *purple_srv_txt_query_get_query(PurpleSrvTxtQueryData *query_data);
*/
int purple_srv_txt_query_get_type(PurpleSrvTxtQueryData *query_data);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_DNSSRV_H */
diff --git a/libpurple/eventloop.h b/libpurple/eventloop.h
index 76448492ce..01465a150a 100644
--- a/libpurple/eventloop.h
+++ b/libpurple/eventloop.h
@@ -28,10 +28,6 @@
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**
* An input condition.
*/
@@ -154,6 +150,8 @@ struct _PurpleEventLoopUiOps
void (*_purple_reserved4)(void);
};
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name Event Loop API */
/**************************************************************************/
@@ -266,8 +264,6 @@ PurpleEventLoopUiOps *purple_eventloop_get_ui_ops(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_EVENTLOOP_H_ */
diff --git a/libpurple/ft.h b/libpurple/ft.h
index 8f18877d5c..0505db5841 100644
--- a/libpurple/ft.h
+++ b/libpurple/ft.h
@@ -184,9 +184,7 @@ struct _PurpleXfer
void *proto_data; /**< prpl-specific data. */
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name File Transfer API */
@@ -843,9 +841,7 @@ PurpleXferUiOps *purple_xfers_get_ui_ops(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_FT_H_ */
diff --git a/libpurple/idle.h b/libpurple/idle.h
index f01c75bc60..76c78d1258 100644
--- a/libpurple/idle.h
+++ b/libpurple/idle.h
@@ -41,9 +41,7 @@ typedef struct
void (*_purple_reserved4)(void);
} PurpleIdleUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Idle API */
@@ -97,8 +95,6 @@ void purple_idle_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_IDLE_H_ */
diff --git a/libpurple/imgstore.h b/libpurple/imgstore.h
index f647bf32e8..75e5fdb358 100644
--- a/libpurple/imgstore.h
+++ b/libpurple/imgstore.h
@@ -34,9 +34,7 @@
*/
typedef struct _PurpleStoredImage PurpleStoredImage;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Add an image to the store.
@@ -206,8 +204,6 @@ void purple_imgstore_init(void);
*/
void purple_imgstore_uninit(void);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_IMGSTORE_H_ */
diff --git a/libpurple/log.h b/libpurple/log.h
index e57e9f7487..1e12844d5a 100644
--- a/libpurple/log.h
+++ b/libpurple/log.h
@@ -181,9 +181,7 @@ struct _PurpleLogSet {
* IMPORTANT: Update that code if you add members here. */
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/***************************************/
/** @name Log Functions */
@@ -574,8 +572,6 @@ void purple_log_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_LOG_H_ */
diff --git a/libpurple/media-gst.h b/libpurple/media-gst.h
index 32d2b3c9d2..37581ec4f9 100644
--- a/libpurple/media-gst.h
+++ b/libpurple/media-gst.h
@@ -32,8 +32,6 @@
#include <gst/gst.h>
-G_BEGIN_DECLS
-
#define PURPLE_TYPE_MEDIA_ELEMENT_TYPE (purple_media_element_type_get_type())
#define PURPLE_TYPE_MEDIA_ELEMENT_INFO (purple_media_element_info_get_type())
#define PURPLE_MEDIA_ELEMENT_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_ELEMENT_INFO, PurpleMediaElementInfo))
@@ -73,9 +71,7 @@ typedef enum {
PURPLE_MEDIA_ELEMENT_SINK = 1 << 10, /** can be set as an active sink */
} PurpleMediaElementType;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Gets the element type's GType.
@@ -176,10 +172,6 @@ GstElement *purple_media_element_info_call_create(
PurpleMediaElementInfo *info, PurpleMedia *media,
const gchar *session_id, const gchar *participant);
-#ifdef __cplusplus
-}
-#endif
-
G_END_DECLS
#endif /* _PURPLE_MEDIA_GST_H_ */
diff --git a/libpurple/media.h b/libpurple/media.h
index ce23a98587..b55ed14f69 100644
--- a/libpurple/media.h
+++ b/libpurple/media.h
@@ -27,14 +27,12 @@
#ifndef _PURPLE_MEDIA_H_
#define _PURPLE_MEDIA_H_
-#include "media/candidate.h"
-#include "media/codec.h"
-#include "media/enum-types.h"
-
#include <glib.h>
#include <glib-object.h>
-G_BEGIN_DECLS
+#include "media/candidate.h"
+#include "media/codec.h"
+#include "media/enum-types.h"
#define PURPLE_TYPE_MEDIA (purple_media_get_type())
#define PURPLE_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA, PurpleMedia))
@@ -49,9 +47,7 @@ typedef struct _PurpleMedia PurpleMedia;
#include "signals.h"
#include "util.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Gets the media class's GType
@@ -379,10 +375,6 @@ gulong purple_media_set_output_window(PurpleMedia *media,
*/
void purple_media_remove_output_windows(PurpleMedia *media);
-#ifdef __cplusplus
-}
-#endif
-
G_END_DECLS
#endif /* _PURPLE_MEDIA_H_ */
diff --git a/libpurple/mediamanager.h b/libpurple/mediamanager.h
index 099972a4ac..b3d8f315d6 100644
--- a/libpurple/mediamanager.h
+++ b/libpurple/mediamanager.h
@@ -38,8 +38,6 @@ typedef struct _PurpleMediaManagerClass PurpleMediaManagerClass;
#include "account.h"
#include "media.h"
-G_BEGIN_DECLS
-
#define PURPLE_TYPE_MEDIA_MANAGER (purple_media_manager_get_type())
#define PURPLE_MEDIA_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManager))
#define PURPLE_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass))
@@ -47,9 +45,7 @@ G_BEGIN_DECLS
#define PURPLE_IS_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_MANAGER))
#define PURPLE_MEDIA_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass))
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Media Manager API */
@@ -209,10 +205,6 @@ GType purple_media_manager_get_backend_type(PurpleMediaManager *manager);
/*}@*/
-#ifdef __cplusplus
-}
-#endif
-
G_END_DECLS
#endif /* _PURPLE_MEDIA_MANAGER_H_ */
diff --git a/libpurple/mime.h b/libpurple/mime.h
index b568a49288..abf25d36b1 100644
--- a/libpurple/mime.h
+++ b/libpurple/mime.h
@@ -26,10 +26,6 @@
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**
* @file mime.h
* @ingroup core
@@ -48,6 +44,8 @@ typedef struct _PurpleMimeDocument PurpleMimeDocument;
*/
typedef struct _PurpleMimePart PurpleMimePart;
+G_BEGIN_DECLS
+
/**
* Allocate an empty MIME document.
*/
@@ -211,8 +209,6 @@ gsize purple_mime_part_get_length(PurpleMimePart *part);
void purple_mime_part_set_data(PurpleMimePart *part, const char *data);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif
diff --git a/libpurple/nat-pmp.h b/libpurple/nat-pmp.h
index 077c74c30c..44470c689b 100644
--- a/libpurple/nat-pmp.h
+++ b/libpurple/nat-pmp.h
@@ -41,6 +41,8 @@ typedef enum {
PURPLE_PMP_TYPE_TCP
} PurplePmpType;
+G_BEGIN_DECLS
+
/**
* Initialize nat-pmp
*/
@@ -54,24 +56,28 @@ char *purple_pmp_get_public_ip(void);
/**
* Remove the NAT-PMP mapping for a specified type on a specified port
*
- * @param type The PurplePmpType
+ * @param type The PurplePmpType
* @param privateport The private port on which we are listening locally
- * @param publicport The public port on which we are expecting a response
- * @param lifetime The lifetime of the mapping. It is recommended that this be PURPLE_PMP_LIFETIME.
+ * @param publicport The public port on which we are expecting a response
+ * @param lifetime The lifetime of the mapping. It is recommended that this
+ * be PURPLE_PMP_LIFETIME.
*
- * @returns TRUE if succesful; FALSE if unsuccessful
+ * @returns TRUE if successful; FALSE if unsuccessful
*/
-gboolean purple_pmp_create_map(PurplePmpType type, unsigned short privateport, unsigned short publicport, int lifetime);
+gboolean purple_pmp_create_map(PurplePmpType type, unsigned short privateport,
+ unsigned short publicport, int lifetime);
/**
* Remove the NAT-PMP mapping for a specified type on a specified port
*
- * @param type The PurplePmpType
+ * @param type The PurplePmpType
* @param privateport The private port on which the mapping was previously made
*
- * @returns TRUE if succesful; FALSE if unsuccessful
+ * @returns TRUE if successful; FALSE if unsuccessful
*/
gboolean purple_pmp_destroy_map(PurplePmpType type, unsigned short privateport);
+G_END_DECLS
+
#endif
diff --git a/libpurple/network.h b/libpurple/network.h
index 7686214906..788c487865 100644
--- a/libpurple/network.h
+++ b/libpurple/network.h
@@ -26,9 +26,9 @@
#ifndef _PURPLE_NETWORK_H_
#define _PURPLE_NETWORK_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <glib.h>
+
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Network API */
@@ -316,8 +316,6 @@ void purple_network_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_NETWORK_H_ */
diff --git a/libpurple/notify.h b/libpurple/notify.h
index ec4d34968f..ea7ab2b7c5 100644
--- a/libpurple/notify.h
+++ b/libpurple/notify.h
@@ -175,9 +175,7 @@ typedef struct
} PurpleNotifyUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
@@ -734,8 +732,6 @@ void purple_notify_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_NOTIFY_H_ */
diff --git a/libpurple/ntlm.h b/libpurple/ntlm.h
index e61a4f5f07..e67df3f828 100644
--- a/libpurple/ntlm.h
+++ b/libpurple/ntlm.h
@@ -27,9 +27,7 @@
#ifndef _PURPLE_NTLM_H
#define _PURPLE_NTLM_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Generates the base64 encoded type 1 message needed for NTLM authentication
@@ -66,8 +64,6 @@ guint8 *purple_ntlm_parse_type2(const gchar *type2, guint32 *flags);
*/
gchar *purple_ntlm_gen_type3(const gchar *username, const gchar *passw, const gchar *hostname, const gchar *domain, const guint8 *nonce, guint32 *flags);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_NTLM_H */
diff --git a/libpurple/plugin.h b/libpurple/plugin.h
index 5d6b48b663..c4ae3b889f 100644
--- a/libpurple/plugin.h
+++ b/libpurple/plugin.h
@@ -239,9 +239,7 @@ struct _PurplePluginAction {
#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Plugin API */
@@ -663,8 +661,6 @@ PurplePluginAction *purple_plugin_action_new(const char* label, void (*callback)
*/
void purple_plugin_action_free(PurplePluginAction *action);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_PLUGIN_H_ */
diff --git a/libpurple/pluginpref.h b/libpurple/pluginpref.h
index 6ce04ad9ab..85112321b7 100644
--- a/libpurple/pluginpref.h
+++ b/libpurple/pluginpref.h
@@ -50,9 +50,7 @@ typedef enum {
#include <glib.h>
#include "prefs.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Plugin Preference API */
@@ -262,8 +260,6 @@ PurpleStringFormatType purple_plugin_pref_get_format_type(PurplePluginPref *pref
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_PLUGINPREF_H_ */
diff --git a/libpurple/pounce.h b/libpurple/pounce.h
index 1b3a30cdc7..68a607876f 100644
--- a/libpurple/pounce.h
+++ b/libpurple/pounce.h
@@ -59,9 +59,7 @@ typedef enum
/** A pounce callback. */
typedef void (*PurplePounceCb)(PurplePounce *, PurplePounceEvent, void *);
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Buddy Pounce API */
@@ -354,8 +352,6 @@ void purple_pounces_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_POUNCE_H_ */
diff --git a/libpurple/prefs.h b/libpurple/prefs.h
index 42fc7687bb..ad8cdd5fc1 100644
--- a/libpurple/prefs.h
+++ b/libpurple/prefs.h
@@ -62,9 +62,7 @@ typedef enum
typedef void (*PurplePrefCallback) (const char *name, PurplePrefType type,
gconstpointer val, gpointer data);
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Prefs API
@@ -362,8 +360,6 @@ void purple_prefs_update_old(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_PREFS_H_ */
diff --git a/libpurple/privacy.h b/libpurple/privacy.h
index 7da35d4902..19ef9d6494 100644
--- a/libpurple/privacy.h
+++ b/libpurple/privacy.h
@@ -40,10 +40,6 @@ typedef enum
#include "account.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**
* Privacy core/UI operations.
*/
@@ -60,6 +56,8 @@ typedef struct
void (*_purple_reserved4)(void);
} PurplePrivacyUiOps;
+G_BEGIN_DECLS
+
/**
* Adds a user to the account's permit list.
*
@@ -187,8 +185,6 @@ PurplePrivacyUiOps *purple_privacy_get_ui_ops(void);
*/
void purple_privacy_init(void);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_PRIVACY_H_ */
diff --git a/libpurple/protocols/jabber/auth_cyrus.c b/libpurple/protocols/jabber/auth_cyrus.c
index 26a4cfdb32..f52e94bb86 100644
--- a/libpurple/protocols/jabber/auth_cyrus.c
+++ b/libpurple/protocols/jabber/auth_cyrus.c
@@ -167,7 +167,6 @@ static void
auth_no_pass_cb(PurpleConnection *gc, PurpleRequestFields *fields)
{
PurpleAccount *account;
- JabberStream *js;
/* The password prompt dialog doesn't get disposed if the account disconnects */
if (!PURPLE_CONNECTION_IS_VALID(gc))
@@ -361,30 +360,30 @@ jabber_sasl_build_callbacks(JabberStream *js)
id = 0;
js->sasl_cb[id].id = SASL_CB_GETREALM;
- js->sasl_cb[id].proc = jabber_sasl_cb_realm;
+ js->sasl_cb[id].proc = (void *)jabber_sasl_cb_realm;
js->sasl_cb[id].context = (void *)js;
id++;
js->sasl_cb[id].id = SASL_CB_AUTHNAME;
- js->sasl_cb[id].proc = jabber_sasl_cb_simple;
+ js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple;
js->sasl_cb[id].context = (void *)js;
id++;
js->sasl_cb[id].id = SASL_CB_USER;
- js->sasl_cb[id].proc = jabber_sasl_cb_simple;
+ js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple;
js->sasl_cb[id].context = (void *)js;
id++;
account = purple_connection_get_account(js->gc);
if (purple_account_get_password(account) != NULL ) {
js->sasl_cb[id].id = SASL_CB_PASS;
- js->sasl_cb[id].proc = jabber_sasl_cb_secret;
+ js->sasl_cb[id].proc = (void *)jabber_sasl_cb_secret;
js->sasl_cb[id].context = (void *)js;
id++;
}
js->sasl_cb[id].id = SASL_CB_LOG;
- js->sasl_cb[id].proc = jabber_sasl_cb_log;
+ js->sasl_cb[id].proc = (void *)jabber_sasl_cb_log;
js->sasl_cb[id].context = (void*)js;
id++;
diff --git a/libpurple/proxy.h b/libpurple/proxy.h
index e12e328bc2..fad49f3c50 100644
--- a/libpurple/proxy.h
+++ b/libpurple/proxy.h
@@ -56,9 +56,7 @@ typedef void (*PurpleProxyConnectFunction)(gpointer data, gint source, const gch
#include "account.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Proxy structure API */
@@ -326,8 +324,6 @@ void purple_proxy_connect_cancel_with_handle(void *handle);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_PROXY_H_ */
diff --git a/libpurple/prpl.h b/libpurple/prpl.h
index f20cfb2a25..635fcb47cb 100644
--- a/libpurple/prpl.h
+++ b/libpurple/prpl.h
@@ -621,9 +621,7 @@ struct _PurplePluginProtocolInfo
#define PURPLE_PLUGIN_PROTOCOL_INFO(plugin) \
((PurplePluginProtocolInfo *)(plugin)->info->extra_info)
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Attention Type API */
@@ -951,8 +949,6 @@ PurplePlugin *purple_find_prpl(const char *id);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PRPL_H_ */
diff --git a/libpurple/request.h b/libpurple/request.h
index 009c32bedb..b3fc852fe2 100644
--- a/libpurple/request.h
+++ b/libpurple/request.h
@@ -158,9 +158,7 @@ typedef void (*PurpleRequestChoiceCb)(void *, int);
typedef void (*PurpleRequestFieldsCb)(void *, PurpleRequestFields *fields);
typedef void (*PurpleRequestFileCb)(void *, const char *filename);
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Field List API */
@@ -1527,8 +1525,6 @@ PurpleRequestUiOps *purple_request_get_ui_ops(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_REQUEST_H_ */
diff --git a/libpurple/roomlist.h b/libpurple/roomlist.h
index b85933b76b..83161b8360 100644
--- a/libpurple/roomlist.h
+++ b/libpurple/roomlist.h
@@ -81,9 +81,7 @@ struct _PurpleRoomlistUiOps {
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Room List API */
@@ -412,8 +410,6 @@ PurpleRoomlistUiOps *purple_roomlist_get_ui_ops(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_ROOMLIST_H_ */
diff --git a/libpurple/savedstatuses.h b/libpurple/savedstatuses.h
index bd5b091343..53be07cd55 100644
--- a/libpurple/savedstatuses.h
+++ b/libpurple/savedstatuses.h
@@ -60,9 +60,7 @@ typedef struct _PurpleSavedStatusSub PurpleSavedStatusSub;
#include "status.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Saved status subsystem */
@@ -418,8 +416,7 @@ void purple_savedstatuses_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SAVEDSTATUSES_H_ */
+
diff --git a/libpurple/server.h b/libpurple/server.h
index 3ddff92036..d80b05d224 100644
--- a/libpurple/server.h
+++ b/libpurple/server.h
@@ -30,9 +30,7 @@
#include "conversation.h"
#include "prpl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Send a typing message to a given user over a given connection.
@@ -185,8 +183,7 @@ void serv_got_chat_in(PurpleConnection *g, int id, const char *who,
PurpleMessageFlags flags, const char *message, time_t mtime);
void serv_send_file(PurpleConnection *gc, const char *who, const char *file);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SERVER_H_ */
+
diff --git a/libpurple/signals.h b/libpurple/signals.h
index 8499cebe5f..aa732050ef 100644
--- a/libpurple/signals.h
+++ b/libpurple/signals.h
@@ -35,9 +35,7 @@ typedef void (*PurpleCallback)(void);
typedef void (*PurpleSignalMarshalFunc)(PurpleCallback cb, va_list args,
void *data, void **return_val);
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Signal API */
@@ -373,8 +371,7 @@ void purple_marshal_POINTER__POINTER_POINTER(
PurpleCallback cb, va_list args, void *data, void **return_val);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SIGNALS_H_ */
+
diff --git a/libpurple/smiley.h b/libpurple/smiley.h
index 9721c228da..c297d1daf0 100644
--- a/libpurple/smiley.h
+++ b/libpurple/smiley.h
@@ -50,9 +50,7 @@ typedef struct _PurpleSmileyClass PurpleSmileyClass;
#define PURPLE_IS_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SMILEY))
#define PURPLE_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SMILEY, PurpleSmileyClass))
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Custom Smiley API */
@@ -253,9 +251,7 @@ void purple_smileys_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SMILEY_H_ */
diff --git a/libpurple/sound.h b/libpurple/sound.h
index 352ab43efb..cd46ed137c 100644
--- a/libpurple/sound.h
+++ b/libpurple/sound.h
@@ -72,9 +72,7 @@ typedef struct _PurpleSoundUiOps
void (*_purple_reserved4)(void);
} PurpleSoundUiOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name Sound API */
@@ -136,8 +134,6 @@ void *purple_sounds_get_handle(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SOUND_H_ */
diff --git a/libpurple/sslconn.h b/libpurple/sslconn.h
index bb176505df..6987fb0e91 100644
--- a/libpurple/sslconn.h
+++ b/libpurple/sslconn.h
@@ -140,9 +140,7 @@ typedef struct
void (*_purple_reserved4)(void);
} PurpleSslOps;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name SSL API */
@@ -311,8 +309,6 @@ void purple_ssl_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_SSLCONN_H_ */
diff --git a/libpurple/status.h b/libpurple/status.h
index a0bed2eb6a..6c7e525776 100644
--- a/libpurple/status.h
+++ b/libpurple/status.h
@@ -148,9 +148,7 @@ typedef enum
#define PURPLE_MOOD_NAME "mood"
#define PURPLE_MOOD_COMMENT "moodtext"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name PurpleStatusPrimitive API */
@@ -945,8 +943,7 @@ void purple_status_uninit(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_STATUS_H_ */
+
diff --git a/libpurple/stringref.h b/libpurple/stringref.h
index cbb9eecb19..debbe1fd5c 100644
--- a/libpurple/stringref.h
+++ b/libpurple/stringref.h
@@ -29,12 +29,10 @@
#ifndef _PURPLE_STRINGREF_H_
#define _PURPLE_STRINGREF_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
typedef struct _PurpleStringref PurpleStringref;
+G_BEGIN_DECLS
+
/**
* Creates an immutable reference-counted string object. The newly
* created object will have a reference count of 1.
@@ -131,8 +129,6 @@ int purple_stringref_cmp(const PurpleStringref *s1, const PurpleStringref *s2);
*/
size_t purple_stringref_len(const PurpleStringref *stringref);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_STRINGREF_H_ */
diff --git a/libpurple/stun.h b/libpurple/stun.h
index b51a61c7e5..003f19f0cd 100644
--- a/libpurple/stun.h
+++ b/libpurple/stun.h
@@ -26,10 +26,6 @@
#ifndef _PURPLE_STUN_H_
#define _PURPLE_STUN_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**************************************************************************/
/** @name STUN API */
/**************************************************************************/
@@ -63,6 +59,8 @@ struct _PurpleStunNatDiscovery {
typedef void (*StunCallback) (PurpleStunNatDiscovery *);
+G_BEGIN_DECLS
+
/**
* Starts a NAT discovery. It returns a PurpleStunNatDiscovery if the discovery
* is already done. Otherwise the callback is called when the discovery is over
@@ -81,8 +79,6 @@ void purple_stun_init(void);
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_STUN_H_ */
diff --git a/libpurple/upnp.h b/libpurple/upnp.h
index b0e4ab4e47..d47c583527 100644
--- a/libpurple/upnp.h
+++ b/libpurple/upnp.h
@@ -29,9 +29,7 @@
typedef struct _UPnPMappingAddRemove UPnPMappingAddRemove;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************/
/** @name UPnP API */
@@ -125,8 +123,6 @@ UPnPMappingAddRemove *purple_upnp_remove_port_mapping(unsigned short portmap,
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_UPNP_H_ */
diff --git a/libpurple/util.h b/libpurple/util.h
index 36d06ff165..cb39e6529a 100644
--- a/libpurple/util.h
+++ b/libpurple/util.h
@@ -58,10 +58,6 @@ typedef struct _PurpleKeyValuePair PurpleKeyValuePair;
#include "notify.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len);
struct _PurpleKeyValuePair
@@ -71,6 +67,8 @@ struct _PurpleKeyValuePair
};
+G_BEGIN_DECLS
+
/**
* Creates a new PurpleMenuAction.
*
@@ -1459,8 +1457,6 @@ const gchar *purple_get_host_name(void);
*/
gchar *purple_uuid_random(void);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_UTIL_H_ */
diff --git a/libpurple/value.h b/libpurple/value.h
index b8724ac40f..5cd26afbc9 100644
--- a/libpurple/value.h
+++ b/libpurple/value.h
@@ -88,9 +88,7 @@ typedef enum
*/
typedef struct _PurpleValue PurpleValue;
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Creates a new PurpleValue.
@@ -464,8 +462,6 @@ int purple_value_get_enum(const PurpleValue *value);
*/
void *purple_value_get_boxed(const PurpleValue *value);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_VALUE_H_ */
diff --git a/libpurple/whiteboard.h b/libpurple/whiteboard.h
index bd2d4fdfad..3fa491095a 100644
--- a/libpurple/whiteboard.h
+++ b/libpurple/whiteboard.h
@@ -79,9 +79,7 @@ struct _PurpleWhiteboardPrplOps
void (*_purple_reserved4)(void);
};
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
/******************************************************************************/
/** @name PurpleWhiteboard API */
@@ -330,8 +328,6 @@ gpointer purple_whiteboard_get_ui_data(const PurpleWhiteboard *wb);
/*@}*/
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* _PURPLE_WHITEBOARD_H_ */
diff --git a/libpurple/xmlnode.h b/libpurple/xmlnode.h
index 359eef0e03..8bbf0b1a7d 100644
--- a/libpurple/xmlnode.h
+++ b/libpurple/xmlnode.h
@@ -28,10 +28,6 @@
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**
* The valid types for an xmlnode
*/
@@ -61,6 +57,8 @@ struct _xmlnode
GHashTable *namespace_map; /**< The namespace map. */
};
+G_BEGIN_DECLS
+
/**
* Creates a new xmlnode.
*
@@ -360,9 +358,7 @@ void xmlnode_free(xmlnode *node);
xmlnode *xmlnode_from_file(const char *dir, const char *filename,
const char *description, const char *process);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PURPLE_XMLNODE_H_ */
diff --git a/pidgin/gtkaccount.h b/pidgin/gtkaccount.h
index e9a5a5319b..8410d8817d 100644
--- a/pidgin/gtkaccount.h
+++ b/pidgin/gtkaccount.h
@@ -37,6 +37,8 @@ typedef enum
} PidginAccountDialogType;
+G_BEGIN_DECLS
+
/**
* Shows the accounts window.
*/
@@ -80,4 +82,6 @@ void pidgin_account_init(void);
*/
void pidgin_account_uninit(void);
+G_END_DECLS
+
#endif /* _PIDGINACCOUNT_H_ */
diff --git a/pidgin/gtkblist-theme.h b/pidgin/gtkblist-theme.h
index db5c6fb9be..2a29137de8 100644
--- a/pidgin/gtkblist-theme.h
+++ b/pidgin/gtkblist-theme.h
@@ -79,6 +79,8 @@ typedef struct
} PidginBlistLayout;
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name PidginThemeFont API */
/**************************************************************************/
@@ -146,7 +148,6 @@ const gchar * pidgin_theme_font_get_color_describe(PidginThemeFont *font);
/**************************************************************************/
/** @name Purple Buddy List Theme API */
/**************************************************************************/
-G_BEGIN_DECLS
/**
* GObject foo.
@@ -182,7 +183,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns The buddy list layout.
*/
- PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme);
+PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme);
/**
* Returns the background color to be used with expanded groups.
@@ -191,7 +192,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A gdk color.
*/
- GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme);
+GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used with expanded groups.
@@ -200,7 +201,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme);
/**
* Returns the background color to be used with collapsed groups.
@@ -209,7 +210,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A gdk color.
*/
- GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme);
+GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used with collapsed groups.
@@ -218,7 +219,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme);
/**
* Returns the colors to be used for contacts and chats.
@@ -227,7 +228,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A gdkcolor for contacts and chats.
*/
- GdkColor *pidgin_blist_theme_get_contact_color(PidginBlistTheme *theme);
+GdkColor *pidgin_blist_theme_get_contact_color(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for expanded contacts.
@@ -236,7 +237,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for online buddies.
@@ -245,7 +246,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for away and idle buddies.
@@ -254,7 +255,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for offline buddies.
@@ -263,7 +264,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for idle buddies.
@@ -272,7 +273,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for buddies with unread messages.
@@ -281,7 +282,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for chats with unread messages
@@ -291,7 +292,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme);
/**
* Returns the text font and color to be used for a buddy's status message.
@@ -300,7 +301,7 @@ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme);
*
* @returns A font and color pair.
*/
- PidginThemeFont *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme);
+PidginThemeFont *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme);
/* Set Methods */
@@ -434,4 +435,5 @@ void pidgin_blist_theme_set_unread_message_nick_said_text_info(PidginBlistTheme
void pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair);
G_END_DECLS
+
#endif /* PIDGIN_BLIST_THEME_H */
diff --git a/pidgin/gtkblist.h b/pidgin/gtkblist.h
index ff0a023df9..2a41402874 100644
--- a/pidgin/gtkblist.h
+++ b/pidgin/gtkblist.h
@@ -127,6 +127,8 @@ struct _PidginBuddyList {
#define PIDGIN_IS_PIDGIN_BLIST(list) \
(purple_blist_get_ui_ops() == pidgin_blist_get_ui_ops())
+G_BEGIN_DECLS
+
/**************************************************************************
* @name GTK+ Buddy List API
**************************************************************************/
@@ -397,5 +399,6 @@ void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget);
*/
void pidgin_blist_tooltip_destroy(void);
+G_END_DECLS
#endif /* _PIDGINBLIST_H_ */
diff --git a/pidgin/gtkcellrendererexpander.h b/pidgin/gtkcellrendererexpander.h
index 983a9bd84a..d95b9bdaee 100644
--- a/pidgin/gtkcellrendererexpander.h
+++ b/pidgin/gtkcellrendererexpander.h
@@ -23,11 +23,6 @@
#include <gtk/gtk.h>
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
#define PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER (pidgin_cell_renderer_expander_get_type())
#define PIDGIN_CELL_RENDERER_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER, PidginCellRendererExpander))
#define PIDGIN_CELL_RENDERER_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_GTK_CELL_RENDERER_EXPANDER, PidginCellRendererExpanderClass))
@@ -48,12 +43,11 @@ struct _PidginCellRendererExpanderClass {
GtkCellRendererClass parent_class;
};
+G_BEGIN_DECLS
+
GType pidgin_cell_renderer_expander_get_type (void);
GtkCellRenderer *pidgin_cell_renderer_expander_new (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* _PIDGINCELLRENDEREREXPANDER_H_ */
diff --git a/pidgin/gtkcertmgr.h b/pidgin/gtkcertmgr.h
index 8971be41e1..f64968ce2e 100644
--- a/pidgin/gtkcertmgr.h
+++ b/pidgin/gtkcertmgr.h
@@ -43,6 +43,8 @@ struct _PidginCertificateManager {
gchar *label;
};
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name Certificate Manager API */
/**************************************************************************/
@@ -59,4 +61,6 @@ void pidgin_certmgr_hide(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGINCERTMGR_H_ */
diff --git a/pidgin/gtkconn.h b/pidgin/gtkconn.h
index 9fda617259..27408b2039 100644
--- a/pidgin/gtkconn.h
+++ b/pidgin/gtkconn.h
@@ -25,6 +25,8 @@
#ifndef _PIDGINCONN_H_
#define _PIDGINCONN_H_
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name GTK+ Connection API */
/**************************************************************************/
@@ -56,4 +58,6 @@ void pidgin_connection_init(void);
*/
void pidgin_connection_uninit(void);
+G_END_DECLS
+
#endif /* _PIDGINCONN_H_ */
diff --git a/pidgin/gtkconv-theme.c b/pidgin/gtkconv-theme.c
index d306594ee1..7a7a3a8150 100644
--- a/pidgin/gtkconv-theme.c
+++ b/pidgin/gtkconv-theme.c
@@ -28,6 +28,7 @@
#include "xmlnode.h"
#include "pidgin.h"
+#include "internal.h"
#include "gtkconv.h"
#include "gtkwebview.h"
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
index 9565dadfe8..1b93eed78d 100644
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -196,6 +196,7 @@ static gboolean update_send_to_selection(PidginWindow *win);
static void generate_send_to_items(PidginWindow *win);
/* Prototypes. <-- because Paco-Paco hates this comment. */
+static void load_conv_theme(PidginConversation *gtkconv);
static gboolean infopane_entry_activate(PidginConversation *gtkconv);
static void got_typing_keypress(PidginConversation *gtkconv, gboolean first);
static void gray_stuff_out(PidginConversation *gtkconv);
@@ -448,12 +449,12 @@ debug_command_cb(PurpleConversation *conv,
static void clear_conversation_scrollback_cb(PurpleConversation *conv,
void *data)
{
- PidginConversation *gtkconv = NULL;
-
- gtkconv = PIDGIN_CONVERSATION(conv);
+ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if (PIDGIN_CONVERSATION(conv))
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(gtkconv->webview), "", "");
+ if (PIDGIN_CONVERSATION(conv)) {
+ load_conv_theme(gtkconv);
+ gtkconv->last_flags = 0;
+ }
}
static PurpleCmdRet
@@ -2195,19 +2196,13 @@ entry_key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer data)
case GDK_Page_Up:
case GDK_KP_Page_Up:
-/* TODO WEBKIT: Write this. */
-#if 0
- gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
-#endif /* if 0 */
+ gtk_webview_page_up(GTK_WEBVIEW(gtkconv->webview));
return TRUE;
break;
case GDK_Page_Down:
case GDK_KP_Page_Down:
-/* TODO WEBKIT: Write this. */
-#if 0
- gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
-#endif /* if 0 */
+ gtk_webview_page_down(GTK_WEBVIEW(gtkconv->webview));
return TRUE;
break;
@@ -5086,6 +5081,8 @@ replace_header_tokens(PurpleConversation *conv, const char *text)
GString *str;
const char *cur = text;
const char *prev = cur;
+ time_t mtime;
+ struct tm *tm = NULL;
if (text == NULL || *text == '\0')
return NULL;
@@ -5122,6 +5119,7 @@ replace_header_tokens(PurpleConversation *conv, const char *text)
} else if (g_str_has_prefix(cur, "%timeOpened")) {
const char *tmp = cur + strlen("%timeOpened");
char *format = NULL;
+
if (*tmp == '{') {
const char *end;
tmp++;
@@ -5131,11 +5129,22 @@ replace_header_tokens(PurpleConversation *conv, const char *text)
format = g_strndup(tmp, end - tmp);
fin = end + 1;
}
- replace = purple_utf8_strftime(format ? format : "%X", NULL);
+
+ if (!tm) {
+ mtime = time(NULL);
+ tm = localtime(&mtime);
+ }
+
+ replace = purple_utf8_strftime(format ? format : "%X", tm);
g_free(format);
} else if (g_str_has_prefix(cur, "%dateOpened%")) {
- replace = purple_date_format_short(NULL);
+ if (!tm) {
+ mtime = time(NULL);
+ tm = localtime(&mtime);
+ }
+
+ replace = purple_date_format_short(tm);
} else {
cur++;
@@ -5237,15 +5246,52 @@ static void
conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data)
{
PidginConversation *gtkconv = user_data;
- const char *path;
- char *js;
+ char *path, *js;
path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject));
js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path);
+ g_free(path);
gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js);
g_free(js);
}
+static void
+load_conv_theme(PidginConversation *gtkconv)
+{
+ char *header, *footer;
+ char *template;
+ char *basedir, *baseuri;
+
+ header = replace_header_tokens(gtkconv->active_conv,
+ pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
+ footer = replace_header_tokens(gtkconv->active_conv,
+ pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
+ template = replace_template_tokens(gtkconv->theme, header, footer);
+ g_free(header);
+ g_free(footer);
+
+ if (template == NULL)
+ return;
+
+ set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
+
+ basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
+ baseuri = g_strdup_printf("file://%s", basedir);
+ webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template,
+ "text/html", "UTF-8", baseuri);
+
+ if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
+ gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview),
+ "document.getElementById('Chat').className = 'groupchat'");
+
+ g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
+ G_CALLBACK(conv_variant_changed_cb), gtkconv);
+
+ g_free(basedir);
+ g_free(baseuri);
+ g_free(template);
+}
+
static GtkWidget *
setup_common_pane(PidginConversation *gtkconv)
{
@@ -5256,8 +5302,6 @@ setup_common_pane(PidginConversation *gtkconv)
PurpleBuddy *buddy;
gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT);
int buddyicon_size = 0;
- char *header, *footer;
- char *template;
/* Setup the top part of the pane */
vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
@@ -5351,36 +5395,7 @@ setup_common_pane(PidginConversation *gtkconv)
frame = pidgin_create_webview(FALSE, &gtkconv->webview, NULL, &webview_sw);
gtk_widget_set_size_request(gtkconv->webview, -1, 0);
- header = replace_header_tokens(conv,
- pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
- footer = replace_header_tokens(conv,
- pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
- template = replace_template_tokens(gtkconv->theme, header, footer);
- g_free(header);
- g_free(footer);
-
- if (template != NULL) {
- char *basedir;
- char *baseuri;
-
- purple_debug_info("webkit", "template: %s\n", template);
-
- set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
-
- basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
- baseuri = g_strdup_printf("file://%s", basedir);
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, "text/html", "UTF-8", baseuri);
-
- if (chat)
- gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), "document.getElementById('Chat').className = 'groupchat'");
-
- g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
- G_CALLBACK(conv_variant_changed_cb), gtkconv);
-
- g_free(basedir);
- g_free(baseuri);
- g_free(template);
- }
+ load_conv_theme(gtkconv);
if (chat) {
GtkWidget *hpaned;
@@ -6142,14 +6157,16 @@ replace_message_tokens(
GString *str;
const char *cur = text;
const char *prev = cur;
+ struct tm *tm = NULL;
- if (text == NULL)
- return g_strdup("");
+ if (text == NULL || *text == '\0')
+ return NULL;
str = g_string_new(NULL);
while ((cur = strchr(cur, '%'))) {
const char *replace = NULL;
const char *fin = NULL;
+ gpointer freeval = NULL;
if (g_str_has_prefix(cur, "%message%")) {
replace = message;
@@ -6161,6 +6178,7 @@ replace_message_tokens(
} else if (g_str_has_prefix(cur, "%time")) {
const char *tmp = cur + strlen("%time");
char *format = NULL;
+
if (*tmp == '{') {
char *end;
tmp++;
@@ -6170,11 +6188,18 @@ replace_message_tokens(
format = g_strndup(tmp, end - tmp);
fin = end + 1;
}
- replace = purple_utf8_strftime(format ? format : "%X", NULL);
+
+ if (!tm)
+ tm = localtime(&mtime);
+
+ replace = purple_utf8_strftime(format ? format : "%X", tm);
g_free(format);
} else if (g_str_has_prefix(cur, "%shortTime%")) {
- replace = purple_utf8_strftime("%H:%M", NULL);
+ if (!tm)
+ tm = localtime(&mtime);
+
+ replace = purple_utf8_strftime("%H:%M", tm);
} else if (g_str_has_prefix(cur, "%userIconPath%")) {
if (flags & PURPLE_MESSAGE_SEND) {
@@ -6185,14 +6210,14 @@ replace_message_tokens(
replace = purple_imgstore_get_filename(img);
}
if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
- replace = g_build_filename("Outgoing", "buddy_icon.png", NULL);
+ replace = freeval = g_build_filename("Outgoing", "buddy_icon.png", NULL);
}
} else if (flags & PURPLE_MESSAGE_RECV) {
PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
if (icon)
replace = purple_buddy_icon_get_full_path(icon);
if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
- replace = g_build_filename("Incoming", "buddy_icon.png", NULL);
+ replace = freeval = g_build_filename("Incoming", "buddy_icon.png", NULL);
}
}
@@ -6217,6 +6242,8 @@ replace_message_tokens(
g_string_append_len(str, prev, cur - prev);
if (replace)
g_string_append(str, replace);
+ g_free(freeval);
+ replace = freeval = NULL;
/* And update the pointers */
if (fin) {
@@ -6324,23 +6351,40 @@ pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *a
old_flags = gtkconv->last_flags;
if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) {
- message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
func = "appendNextMessage";
+
} else if (flags & PURPLE_MESSAGE_SEND) {
- message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
+
} else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) {
- message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
- func = "appendNextMessage";
+ GList *history = purple_conversation_get_message_history(conv);
+ PurpleConvMessage *last_msg = (PurpleConvMessage *)history->data;
+
+ /* If the senders are the same, use appendNextMessage */
+ if (purple_strequal(purple_conversation_message_get_sender(last_msg), name)) {
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
+ func = "appendNextMessage";
+ } else {
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
+ }
} else if (flags & PURPLE_MESSAGE_RECV) {
- message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
+
} else {
- message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
+ message_html = pidgin_conversation_theme_get_template(gtkconv->theme,
+ PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
}
gtkconv->last_flags = flags;
smileyed = smiley_parse_markup(message, purple_account_get_protocol_id(account));
msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
- escape = gtk_webview_quote_js_string(msg);
+ escape = gtk_webview_quote_js_string(msg ? msg : "");
script = g_strdup_printf("%s(%s)", func, escape);
purple_debug_info("webkit", "JS: %s\n", script);
diff --git a/pidgin/gtkconv.h b/pidgin/gtkconv.h
index e573d01b7b..416a2810cf 100644
--- a/pidgin/gtkconv.h
+++ b/pidgin/gtkconv.h
@@ -157,6 +157,8 @@ struct _PidginConversation
/*@}*/
+G_BEGIN_DECLS
+
/**************************************************************************
* @name GTK+ Conversation API
**************************************************************************/
@@ -269,4 +271,6 @@ void pidgin_conversations_uninit(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGIN_CONVERSATION_H_ */
diff --git a/pidgin/gtkconvwin.h b/pidgin/gtkconvwin.h
index c27f92ce8f..6914fb248a 100644
--- a/pidgin/gtkconvwin.h
+++ b/pidgin/gtkconvwin.h
@@ -107,6 +107,8 @@ struct _PidginWindow
/*@}*/
+G_BEGIN_DECLS
+
/**************************************************************************
* @name GTK+ Conversation Window API
**************************************************************************/
@@ -153,4 +155,6 @@ void pidgin_conv_placement_place(PidginConversation *gtkconv);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGIN_CONVERSATION_WINDOW_H_ */
diff --git a/pidgin/gtkdebug.h b/pidgin/gtkdebug.h
index 75f0a8535e..853bec56d6 100644
--- a/pidgin/gtkdebug.h
+++ b/pidgin/gtkdebug.h
@@ -28,6 +28,8 @@
#include "debug.h"
+G_BEGIN_DECLS
+
/**
* Initializes the GTK+ debug system.
*/
@@ -62,4 +64,6 @@ void pidgin_debug_window_hide(void);
*/
PurpleDebugUiOps *pidgin_debug_get_ui_ops(void);
+G_END_DECLS
+
#endif /* _PIDGINDEBUG_H_ */
diff --git a/pidgin/gtkdialogs.h b/pidgin/gtkdialogs.h
index adda62074a..19419d607b 100644
--- a/pidgin/gtkdialogs.h
+++ b/pidgin/gtkdialogs.h
@@ -30,6 +30,8 @@
#include "account.h"
#include "conversation.h"
+G_BEGIN_DECLS
+
/* Functions in gtkdialogs.c (these should actually stay in this file) */
void pidgin_dialogs_destroy_all(void);
void pidgin_dialogs_about(void);
@@ -53,4 +55,6 @@ void pidgin_dialogs_merge_groups(PurpleGroup *, const char *);
/* This macro should probably be moved elsewhere */
#define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED)
+G_END_DECLS
+
#endif /* _PIDGINDIALOGS_H_ */
diff --git a/pidgin/gtkdnd-hints.h b/pidgin/gtkdnd-hints.h
index a53b9b5835..ed2f4c37ef 100644
--- a/pidgin/gtkdnd-hints.h
+++ b/pidgin/gtkdnd-hints.h
@@ -52,6 +52,8 @@ typedef enum {
} DndHintPosition;
+G_BEGIN_DECLS
+
/**
* Shows a drag-and-drop hint at the specified location.
*
@@ -84,4 +86,6 @@ void dnd_hints_hide_all(void);
void dnd_hints_show_relative(DndHintWindowId id, GtkWidget *widget,
DndHintPosition horiz, DndHintPosition vert);
+G_END_DECLS
+
#endif /* _PIDGIN_DND_HINTS_H_ */
diff --git a/pidgin/gtkdocklet.h b/pidgin/gtkdocklet.h
index af8538b7bd..94e6a66b4d 100644
--- a/pidgin/gtkdocklet.h
+++ b/pidgin/gtkdocklet.h
@@ -25,9 +25,13 @@
#ifndef _GTKDOCKLET_H_
#define _GTKDOCKLET_H_
+G_BEGIN_DECLS
+
void pidgin_docklet_init(void);
void pidgin_docklet_uninit(void);
void*pidgin_docklet_get_handle(void);
+G_END_DECLS
+
#endif /* _GTKDOCKLET_H_ */
diff --git a/pidgin/gtkeventloop.h b/pidgin/gtkeventloop.h
index 0593a0f9e2..937f211bd2 100644
--- a/pidgin/gtkeventloop.h
+++ b/pidgin/gtkeventloop.h
@@ -28,6 +28,8 @@
#include "eventloop.h"
+G_BEGIN_DECLS
+
/**
* Returns the GTK+ event loop UI operations structure.
*
@@ -35,4 +37,6 @@
*/
PurpleEventLoopUiOps *pidgin_eventloop_get_ui_ops(void);
+G_END_DECLS
+
#endif /* _PIDGINEVENTLOOP_H_ */
diff --git a/pidgin/gtkft.h b/pidgin/gtkft.h
index 12f8b380ff..3863188d02 100644
--- a/pidgin/gtkft.h
+++ b/pidgin/gtkft.h
@@ -36,6 +36,8 @@
*/
typedef struct _PidginXferDialog PidginXferDialog;
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name GTK+ File Transfer Dialog API */
/**************************************************************************/
@@ -145,4 +147,6 @@ PurpleXferUiOps *pidgin_xfers_get_ui_ops(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGINFT_H_ */
diff --git a/pidgin/gtkidle.h b/pidgin/gtkidle.h
index d869584d28..aee04ccf23 100644
--- a/pidgin/gtkidle.h
+++ b/pidgin/gtkidle.h
@@ -28,6 +28,8 @@
#include "idle.h"
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name GTK+ Idle API */
/**************************************************************************/
@@ -42,4 +44,6 @@ PurpleIdleUiOps *pidgin_idle_get_ui_ops(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGIN_IDLE_H_ */
diff --git a/pidgin/gtkimhtml.h b/pidgin/gtkimhtml.h
index 4b2f2bd46b..3ba49731c2 100644
--- a/pidgin/gtkimhtml.h
+++ b/pidgin/gtkimhtml.h
@@ -31,9 +31,7 @@
#include "connection.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**************************************************************************
* @name Structures
@@ -828,8 +826,6 @@ void gtk_imhtml_set_populate_primary_clipboard(GtkIMHtml *imhtml, gboolean popul
/*@}*/
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PIDGINIMHTML_H_ */
diff --git a/pidgin/gtkimhtmltoolbar.h b/pidgin/gtkimhtmltoolbar.h
index 4e0db0237d..13efbb47a8 100644
--- a/pidgin/gtkimhtmltoolbar.h
+++ b/pidgin/gtkimhtmltoolbar.h
@@ -26,9 +26,7 @@
#include <gtk/gtk.h>
#include "gtkimhtml.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
#define DEFAULT_FONT_FACE "Helvetica 12"
@@ -98,8 +96,6 @@ void gtk_imhtmltoolbar_associate_smileys (GtkIMHtmlToolbar *toolbar, const char
void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar,
PurpleConversation *conv);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PIDGINIMHTMLTOOLBAR_H_ */
diff --git a/pidgin/gtklog.h b/pidgin/gtklog.h
index 3fd56484b0..0797a76bf9 100644
--- a/pidgin/gtklog.h
+++ b/pidgin/gtklog.h
@@ -52,6 +52,7 @@ struct _PidginLogViewer {
};
+G_BEGIN_DECLS
void pidgin_log_show(PurpleLogType type, const char *buddyname, PurpleAccount *account);
void pidgin_log_show_contact(PurpleContact *contact);
@@ -82,4 +83,6 @@ void pidgin_log_uninit(void);
/*@}*/
+G_END_DECLS
+
#endif
diff --git a/pidgin/gtkmain.c b/pidgin/gtkmain.c
index 622da25b4a..feaabb6819 100644
--- a/pidgin/gtkmain.c
+++ b/pidgin/gtkmain.c
@@ -719,7 +719,16 @@ int main(int argc, char *argv[])
/* set a user-specified config directory */
if (opt_config_dir_arg != NULL) {
- purple_util_set_user_dir(opt_config_dir_arg);
+ if (g_path_is_absolute(opt_config_dir_arg)) {
+ purple_util_set_user_dir(opt_config_dir_arg);
+ } else {
+ /* Make an absolute (if not canonical) path */
+ char *cwd = g_get_current_dir();
+ char *path = g_build_path(G_DIR_SEPARATOR_S, cwd, opt_config_dir_arg, NULL);
+ purple_util_set_user_dir(path);
+ g_free(path);
+ g_free(cwd);
+ }
}
/*
diff --git a/pidgin/gtknotify.h b/pidgin/gtknotify.h
index b5973a4995..d1e6561645 100644
--- a/pidgin/gtknotify.h
+++ b/pidgin/gtknotify.h
@@ -29,6 +29,8 @@
#include "notify.h"
#include "pounce.h"
+G_BEGIN_DECLS
+
/**
* Adds a buddy pounce to the buddy pounce dialog
*
@@ -59,4 +61,6 @@ void pidgin_notify_init(void);
*/
void pidgin_notify_uninit(void);
+G_END_DECLS
+
#endif /* _PIDGINNOTIFY_H_ */
diff --git a/pidgin/gtkplugin.h b/pidgin/gtkplugin.h
index 8b07be4f12..817c03592e 100644
--- a/pidgin/gtkplugin.h
+++ b/pidgin/gtkplugin.h
@@ -56,6 +56,8 @@ struct _PidginPluginUiInfo
#define PIDGIN_PLUGIN_UI_INFO(plugin) \
((PidginPluginUiInfo *)(plugin)->info->ui_info)
+G_BEGIN_DECLS
+
/**
* Returns the configuration frame widget for a GTK+ plugin, if one
* exists.
@@ -77,4 +79,6 @@ void pidgin_plugins_save(void);
*/
void pidgin_plugin_dialog_show(void);
+G_END_DECLS
+
#endif /* _PIDGINPLUGIN_H_ */
diff --git a/pidgin/gtkpluginpref.h b/pidgin/gtkpluginpref.h
index d0f9add1c4..1a433d2178 100644
--- a/pidgin/gtkpluginpref.h
+++ b/pidgin/gtkpluginpref.h
@@ -31,9 +31,7 @@
#include "pidgin.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+G_BEGIN_DECLS
/**
* Creates a Gtk Preference frame for a PurplePluginPrefFrame
@@ -43,8 +41,6 @@ extern "C" {
*/
GtkWidget *pidgin_plugin_pref_create_frame(PurplePluginPrefFrame *frame);
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
#endif /* _PIDGINPLUGINPREF_H_ */
diff --git a/pidgin/gtkpounce.h b/pidgin/gtkpounce.h
index ce5bbc6505..224d319d16 100644
--- a/pidgin/gtkpounce.h
+++ b/pidgin/gtkpounce.h
@@ -28,6 +28,8 @@
#include "pounce.h"
+G_BEGIN_DECLS
+
/**
* Displays a New Buddy Pounce or Edit Buddy Pounce dialog.
*
@@ -60,4 +62,6 @@ void *pidgin_pounces_get_handle(void);
*/
void pidgin_pounces_init(void);
+G_END_DECLS
+
#endif /* _PIDGINPOUNCE_H_ */
diff --git a/pidgin/gtkprefs.h b/pidgin/gtkprefs.h
index fc7119c7a4..bc19210ab7 100644
--- a/pidgin/gtkprefs.h
+++ b/pidgin/gtkprefs.h
@@ -29,6 +29,8 @@
#include "prefs.h"
+G_BEGIN_DECLS
+
/**
* Initializes all UI-specific preferences.
*/
@@ -128,4 +130,6 @@ GtkWidget *pidgin_prefs_dropdown_from_list(GtkWidget *page,
*/
void pidgin_prefs_update_old(void);
+G_END_DECLS
+
#endif /* _PIDGINPREFS_H_ */
diff --git a/pidgin/gtkprivacy.h b/pidgin/gtkprivacy.h
index 0be6a05483..6ee81a4745 100644
--- a/pidgin/gtkprivacy.h
+++ b/pidgin/gtkprivacy.h
@@ -28,6 +28,8 @@
#include "privacy.h"
+G_BEGIN_DECLS
+
/**
* Initializes the GTK+ privacy subsystem.
*/
@@ -72,4 +74,6 @@ void pidgin_request_add_block(PurpleAccount *account, const char *name);
*/
PurplePrivacyUiOps *pidgin_privacy_get_ui_ops(void);
+G_END_DECLS
+
#endif /* _PIDGINPRIVACY_H_ */
diff --git a/pidgin/gtkrequest.h b/pidgin/gtkrequest.h
index 83e466f6aa..77aca7c830 100644
--- a/pidgin/gtkrequest.h
+++ b/pidgin/gtkrequest.h
@@ -28,6 +28,8 @@
#include "request.h"
+G_BEGIN_DECLS
+
/**
* Returns the UI operations structure for GTK+ request functions.
*
@@ -35,4 +37,6 @@
*/
PurpleRequestUiOps *pidgin_request_get_ui_ops(void);
+G_END_DECLS
+
#endif /* _PIDGINREQUEST_H_ */
diff --git a/pidgin/gtkroomlist.h b/pidgin/gtkroomlist.h
index ed905e5c6b..1851132d18 100644
--- a/pidgin/gtkroomlist.h
+++ b/pidgin/gtkroomlist.h
@@ -28,6 +28,8 @@
#include "roomlist.h"
+G_BEGIN_DECLS
+
/**
* Initializes the room list subsystem.
*/
@@ -53,4 +55,6 @@ void pidgin_roomlist_dialog_show(void);
*/
void pidgin_roomlist_dialog_show_with_account(PurpleAccount *account);
+G_END_DECLS
+
#endif /* _PIDGINROOMLIST_H_ */
diff --git a/pidgin/gtksavedstatuses.h b/pidgin/gtksavedstatuses.h
index 144fd052c7..e582de8eb2 100644
--- a/pidgin/gtksavedstatuses.h
+++ b/pidgin/gtksavedstatuses.h
@@ -29,6 +29,8 @@
#include "savedstatuses.h"
#include "status.h"
+G_BEGIN_DECLS
+
/**
* Shows the status window.
*/
@@ -85,4 +87,6 @@ void pidgin_status_init(void);
*/
void pidgin_status_uninit(void);
+G_END_DECLS
+
#endif /* _PIDGINSAVEDSTATUSES_H_ */
diff --git a/pidgin/gtksession.h b/pidgin/gtksession.h
index fb7711329e..ad0909453b 100644
--- a/pidgin/gtksession.h
+++ b/pidgin/gtksession.h
@@ -26,6 +26,8 @@
#ifndef _PIDGINSESSION_H_
#define _PIDGINSESSION_H_
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name X Windows session subsystem */
/**************************************************************************/
@@ -51,4 +53,6 @@ void pidgin_session_end(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGINSESSION_H_ */
diff --git a/pidgin/gtksmiley.h b/pidgin/gtksmiley.h
index fb65227db1..2d7b5e381d 100644
--- a/pidgin/gtksmiley.h
+++ b/pidgin/gtksmiley.h
@@ -31,6 +31,8 @@
typedef struct _PidginSmiley PidginSmiley;
+G_BEGIN_DECLS
+
/**
* Add a PurpleSmiley to the GtkIMHtmlSmiley's list to be able to use it
* in pidgin
@@ -108,4 +110,6 @@ void pidgin_smiley_editor_set_image(PidginSmiley *editor, GdkPixbuf *image);
*/
void pidgin_smiley_editor_set_data(PidginSmiley *editor, gpointer data, gsize datasize);
+G_END_DECLS
+
#endif /* PIDGIN_GTKSMILEY_H */
diff --git a/pidgin/gtksound.h b/pidgin/gtksound.h
index 872b865f51..147cd9409d 100644
--- a/pidgin/gtksound.h
+++ b/pidgin/gtksound.h
@@ -28,6 +28,8 @@
#include "sound.h"
+G_BEGIN_DECLS
+
/**************************************************************************/
/** @name GTK+ Sound API */
/**************************************************************************/
@@ -72,4 +74,6 @@ gboolean pidgin_sound_is_customized(void);
/*@}*/
+G_END_DECLS
+
#endif /* _PIDGINSOUND_H_ */
diff --git a/pidgin/gtksourceundomanager.h b/pidgin/gtksourceundomanager.h
index 0148455476..931486512d 100644
--- a/pidgin/gtksourceundomanager.h
+++ b/pidgin/gtksourceundomanager.h
@@ -57,6 +57,8 @@ struct _GtkSourceUndoManagerClass
void (*can_redo) (GtkSourceUndoManager *um, gboolean can_redo);
};
+G_BEGIN_DECLS
+
GType gtk_source_undo_manager_get_type (void) G_GNUC_CONST;
GtkSourceUndoManager* gtk_source_undo_manager_new (GtkTextBuffer *buffer);
@@ -78,6 +80,8 @@ void gtk_source_undo_manager_set_max_undo_levels
(GtkSourceUndoManager *um,
gint undo_levels);
+G_END_DECLS
+
#endif /* __GTK_SOURCE_UNDO_MANAGER_H__ */
diff --git a/pidgin/gtkthemes.h b/pidgin/gtkthemes.h
index 7d739f8e1b..8343a99d63 100644
--- a/pidgin/gtkthemes.h
+++ b/pidgin/gtkthemes.h
@@ -46,6 +46,8 @@ struct smiley_theme {
extern struct smiley_theme *current_smiley_theme;
extern GSList *smiley_themes;
+G_BEGIN_DECLS
+
void pidgin_themes_init(void);
gboolean pidgin_themes_smileys_disabled(void);
@@ -62,4 +64,6 @@ void pidgin_themes_remove_smiley_theme(const char *file);
GSList *pidgin_themes_get_proto_smileys(const char *id);
+G_END_DECLS
+
#endif /* _PIDGINTHEMES_H_ */
diff --git a/pidgin/gtkutils.h b/pidgin/gtkutils.h
index 84456a7ad7..2999d5fa37 100644
--- a/pidgin/gtkutils.h
+++ b/pidgin/gtkutils.h
@@ -31,10 +31,6 @@
#include "prpl.h"
#include "util.h"
-
-
-
-
typedef enum
{
PIDGIN_BUTTON_HORIZONTAL,
@@ -80,6 +76,8 @@ typedef struct {
typedef gboolean (*PidginFilterBuddyCompletionEntryFunc) (const PidginBuddyCompletionEntry *completion_entry, gpointer user_data);
+G_BEGIN_DECLS
+
/**
* Sets up a gtkimhtml widget, loads it with smileys, and sets the
* default signal handlers.
@@ -903,5 +901,7 @@ void pidgin_utils_init(void);
*/
void pidgin_utils_uninit(void);
+G_END_DECLS
+
#endif /* _PIDGINUTILS_H_ */
diff --git a/pidgin/gtkwebview.c b/pidgin/gtkwebview.c
index 9317045098..7664fd84e6 100644
--- a/pidgin/gtkwebview.c
+++ b/pidgin/gtkwebview.c
@@ -25,79 +25,78 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <JavaScriptCore/JavaScript.h>
+#include "internal.h"
+#include "pidgin.h"
-#include "util.h"
#include "gtkwebview.h"
-#include "imgstore.h"
-static WebKitWebViewClass *parent_class = NULL;
+#define MAX_SCROLL_TIME 0.4 /* seconds */
+#define SCROLL_DELAY 33 /* milliseconds */
+
+#define GTK_WEBVIEW_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_WEBVIEW, GtkWebViewPriv))
+
+/******************************************************************************
+ * Structs
+ *****************************************************************************/
-struct GtkWebViewPriv {
+typedef struct _GtkWebViewPriv {
GHashTable *images; /**< a map from id to temporary file for the image */
- gboolean empty; /**< whether anything has been appended **/
+ gboolean empty; /**< whether anything has been appended **/
/* JS execute queue */
GQueue *js_queue;
gboolean is_loading;
+
+ /* Scroll adjustments */
GtkAdjustment *vadj;
guint scroll_src;
GTimer *scroll_time;
-};
+} GtkWebViewPriv;
-GtkWidget *
-gtk_webview_new(void)
-{
- GtkWebView* ret = GTK_WEBVIEW(g_object_new(gtk_webview_get_type(), NULL));
- return GTK_WIDGET(ret);
-}
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
-static char *
-get_image_filename_from_id(GtkWebView* view, int id)
-{
- char *filename = NULL;
- FILE *file;
- PurpleStoredImage* img;
-
- if (!view->priv->images)
- view->priv->images = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
+static WebKitWebViewClass *parent_class = NULL;
- filename = (char *)g_hash_table_lookup(view->priv->images, GINT_TO_POINTER(id));
- if (filename)
- return filename;
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
- /* else get from img store */
- file = purple_mkstemp(&filename, TRUE);
+static const char *
+get_image_src_from_id(GtkWebViewPriv *priv, int id)
+{
+ char *src;
+ PurpleStoredImage *img;
+
+ if (priv->images) {
+ /* Check for already loaded image */
+ src = (char *)g_hash_table_lookup(priv->images, GINT_TO_POINTER(id));
+ if (src)
+ return src;
+ } else {
+ priv->images = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, g_free);
+ }
+ /* Find image in store */
img = purple_imgstore_find_by_id(id);
- fwrite(purple_imgstore_get_data(img), purple_imgstore_get_size(img), 1, file);
- g_hash_table_insert(view->priv->images, GINT_TO_POINTER(id), filename);
- fclose(file);
- return filename;
-}
+ src = (char *)purple_imgstore_get_filename(img);
+ if (src) {
+ src = g_strdup_printf("file://%s", src);
+ } else {
+ char *tmp;
+ tmp = purple_base64_encode(purple_imgstore_get_data(img),
+ purple_imgstore_get_size(img));
+ src = g_strdup_printf("data:base64,%s", tmp);
+ g_free(tmp);
+ }
-static void
-clear_single_image(gpointer key, gpointer value, gpointer userdata)
-{
- g_unlink((char *)value);
-}
+ g_hash_table_insert(priv->images, GINT_TO_POINTER(id), src);
-static void
-clear_images(GtkWebView *view)
-{
- if (!view->priv->images)
- return;
- g_hash_table_foreach(view->priv->images, clear_single_image, NULL);
- g_hash_table_unref(view->priv->images);
+ return src;
}
/*
@@ -106,10 +105,10 @@ clear_images(GtkWebView *view)
* purple changes the way it works.
*/
static char *
-replace_img_id_with_src(GtkWebView *view, const char *html)
+replace_img_id_with_src(GtkWebViewPriv *priv, const char *html)
{
- GString *buffer = g_string_sized_new(strlen(html));
- const char* cur = html;
+ GString *buffer = g_string_new(NULL);
+ const char *cur = html;
char *id;
int nid;
@@ -152,39 +151,57 @@ replace_img_id_with_src(GtkWebView *view, const char *html)
/* let's dump this, tag and then dump the src information */
g_string_append_len(buffer, img, cur - img);
- g_string_append_printf(buffer, " src='file://%s' ", get_image_filename_from_id(view, nid));
+ g_string_append_printf(buffer, " src='%s' ", get_image_src_from_id(priv, nid));
}
return g_string_free(buffer, FALSE);
}
-static void
-gtk_webview_finalize(GObject *view)
+static gboolean
+process_js_script_queue(GtkWebView *webview)
{
- gpointer temp;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ char *script;
- while ((temp = g_queue_pop_head(GTK_WEBVIEW(view)->priv->js_queue)))
- g_free(temp);
- g_queue_free(GTK_WEBVIEW(view)->priv->js_queue);
+ if (priv->is_loading)
+ return FALSE; /* we will be called when loaded */
+ if (!priv->js_queue || g_queue_is_empty(priv->js_queue))
+ return FALSE; /* nothing to do! */
- clear_images(GTK_WEBVIEW(view));
- g_free(GTK_WEBVIEW(view)->priv);
- G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(view));
+ script = g_queue_pop_head(priv->js_queue);
+ webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), script);
+ g_free(script);
+
+ return TRUE; /* there may be more for now */
}
static void
-gtk_webview_class_init(GtkWebViewClass *klass, gpointer userdata)
+webview_load_started(WebKitWebView *webview, WebKitWebFrame *frame,
+ gpointer userdata)
{
- parent_class = g_type_class_ref(webkit_web_view_get_type());
- G_OBJECT_CLASS(klass)->finalize = gtk_webview_finalize;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+
+ /* is there a better way to test for is_loading? */
+ priv->is_loading = TRUE;
+}
+
+static void
+webview_load_finished(WebKitWebView *webview, WebKitWebFrame *frame,
+ gpointer userdata)
+{
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+
+ priv->is_loading = FALSE;
+ g_idle_add((GSourceFunc)process_js_script_queue, webview);
}
static gboolean
-webview_link_clicked(WebKitWebView *view,
- WebKitWebFrame *frame,
- WebKitNetworkRequest *request,
- WebKitWebNavigationAction *navigation_action,
- WebKitWebPolicyDecision *policy_decision)
+webview_link_clicked(WebKitWebView *webview,
+ WebKitWebFrame *frame,
+ WebKitNetworkRequest *request,
+ WebKitWebNavigationAction *navigation_action,
+ WebKitWebPolicyDecision *policy_decision,
+ gpointer userdata)
{
const gchar *uri;
WebKitWebNavigationReason reason;
@@ -202,77 +219,155 @@ webview_link_clicked(WebKitWebView *view,
return TRUE;
}
+/*
+ * Smoothly scroll a WebView.
+ *
+ * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom.
+ */
static gboolean
-process_js_script_queue(GtkWebView *view)
+smooth_scroll_cb(gpointer data)
{
- char *script;
- if (view->priv->is_loading)
- return FALSE; /* we will be called when loaded */
- if (!view->priv->js_queue || g_queue_is_empty(view->priv->js_queue))
- return FALSE; /* nothing to do! */
+ GtkWebViewPriv *priv = data;
+ GtkAdjustment *adj;
+ gdouble max_val;
+ gdouble scroll_val;
- script = g_queue_pop_head(view->priv->js_queue);
- webkit_web_view_execute_script(WEBKIT_WEB_VIEW(view), script);
- g_free(script);
+ g_return_val_if_fail(priv->scroll_time != NULL, FALSE);
- return TRUE; /* there may be more for now */
+ adj = priv->vadj;
+#if GTK_CHECK_VERSION(2,14,0)
+ max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj);
+#else
+ max_val = adj->upper - adj->page_size;
+#endif
+ scroll_val = gtk_adjustment_get_value(adj) +
+ ((max_val - gtk_adjustment_get_value(adj)) / 3);
+
+ if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME
+ || scroll_val >= max_val) {
+ /* time's up. jump to the end and kill the timer */
+ gtk_adjustment_set_value(adj, max_val);
+ g_timer_destroy(priv->scroll_time);
+ priv->scroll_time = NULL;
+ g_source_remove(priv->scroll_src);
+ priv->scroll_src = 0;
+ return FALSE;
+ }
+
+ /* scroll by 1/3rd the remaining distance */
+ gtk_adjustment_set_value(adj, scroll_val);
+ return TRUE;
}
-static void
-webview_load_started(WebKitWebView *view,
- WebKitWebFrame *frame,
- gpointer userdata)
+static gboolean
+scroll_idle_cb(gpointer data)
{
- /* is there a better way to test for is_loading? */
- GTK_WEBVIEW(view)->priv->is_loading = TRUE;
+ GtkWebViewPriv *priv = data;
+ GtkAdjustment *adj = priv->vadj;
+ gdouble max_val;
+
+ if (adj) {
+#if GTK_CHECK_VERSION(2,14,0)
+ max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj);
+#else
+ max_val = adj->upper - adj->page_size;
+#endif
+ gtk_adjustment_set_value(adj, max_val);
+ }
+
+ priv->scroll_src = 0;
+ return FALSE;
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+
+GtkWidget *
+gtk_webview_new(void)
+{
+ return GTK_WIDGET(g_object_new(gtk_webview_get_type(), NULL));
}
static void
-webview_load_finished(WebKitWebView *view,
- WebKitWebFrame *frame,
- gpointer userdata)
+gtk_webview_finalize(GObject *webview)
{
- GTK_WEBVIEW(view)->priv->is_loading = FALSE;
- g_idle_add((GSourceFunc)process_js_script_queue, view);
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ gpointer temp;
+
+ while ((temp = g_queue_pop_head(priv->js_queue)))
+ g_free(temp);
+ g_queue_free(priv->js_queue);
+
+ if (priv->images)
+ g_hash_table_unref(priv->images);
+
+ G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(webview));
}
-void
-gtk_webview_safe_execute_script(GtkWebView *view, const char *script)
+static void
+gtk_webview_class_init(GtkWebViewClass *klass, gpointer userdata)
{
- g_queue_push_tail(view->priv->js_queue, g_strdup(script));
- g_idle_add((GSourceFunc)process_js_script_queue, view);
+ parent_class = g_type_class_ref(webkit_web_view_get_type());
+
+ g_type_class_add_private(klass, sizeof(GtkWebViewPriv));
+
+ G_OBJECT_CLASS(klass)->finalize = gtk_webview_finalize;
}
static void
-gtk_webview_init(GtkWebView *view, gpointer userdata)
+gtk_webview_init(GtkWebView *webview, gpointer userdata)
{
- view->priv = g_new0(struct GtkWebViewPriv, 1);
- g_signal_connect(view, "navigation-policy-decision-requested",
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+
+ priv->empty = TRUE;
+ priv->js_queue = g_queue_new();
+
+ g_signal_connect(webview, "navigation-policy-decision-requested",
G_CALLBACK(webview_link_clicked),
- view);
+ webview);
- g_signal_connect(view, "load-started",
+ g_signal_connect(webview, "load-started",
G_CALLBACK(webview_load_started),
- view);
+ webview);
- g_signal_connect(view, "load-finished",
+ g_signal_connect(webview, "load-finished",
G_CALLBACK(webview_load_finished),
- view);
+ webview);
+}
- view->priv->empty = TRUE;
- view->priv->js_queue = g_queue_new();
+GType
+gtk_webview_get_type(void)
+{
+ static GType mview_type = 0;
+ if (G_UNLIKELY(mview_type == 0)) {
+ static const GTypeInfo mview_info = {
+ sizeof(GtkWebViewClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)gtk_webview_class_init,
+ NULL,
+ NULL,
+ sizeof(GtkWebView),
+ 0,
+ (GInstanceInitFunc)gtk_webview_init,
+ NULL
+ };
+ mview_type = g_type_register_static(webkit_web_view_get_type(),
+ "GtkWebView", &mview_info, 0);
+ }
+ return mview_type;
}
+/*****************************************************************************
+ * Public API functions
+ *****************************************************************************/
-void
-gtk_webview_load_html_string_with_imgstore(GtkWebView *view, const char *html)
+gboolean
+gtk_webview_is_empty(GtkWebView *webview)
{
- char *html_imged;
-
- clear_images(view);
- html_imged = replace_img_id_with_src(view, html);
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(view), html_imged, "file:///");
- g_free(html_imged);
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ return priv->empty;
}
char *
@@ -299,14 +394,34 @@ gtk_webview_quote_js_string(const char *text)
}
cur++;
}
+
g_string_append_c(str, '"');
+
return g_string_free(str, FALSE);
}
+void
+gtk_webview_safe_execute_script(GtkWebView *webview, const char *script)
+{
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ g_queue_push_tail(priv->js_queue, g_strdup(script));
+ g_idle_add((GSourceFunc)process_js_script_queue, webview);
+}
void
-gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj)
+gtk_webview_load_html_string_with_imgstore(GtkWebView *webview, const char *html)
{
- webview->priv->vadj = vadj;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ char *html_imged;
+
+ if (priv->images) {
+ g_hash_table_unref(priv->images);
+ priv->images = NULL;
+ }
+
+ html_imged = replace_img_id_with_src(priv, html);
+ webkit_web_view_load_string(WEBKIT_WEB_VIEW(webview), html_imged, NULL,
+ NULL, "file:///");
+ g_free(html_imged);
}
/* this is a "hack", my plan is to eventually handle this
@@ -315,77 +430,34 @@ gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj)
* wrong to hardcode that here.
*/
void
-gtk_webview_append_html(GtkWebView *view, const char *html)
+gtk_webview_append_html(GtkWebView *webview, const char *html)
{
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
char *escaped = gtk_webview_quote_js_string(html);
char *script = g_strdup_printf("document.write(%s)", escaped);
- webkit_web_view_execute_script(WEBKIT_WEB_VIEW(view), script);
- view->priv->empty = FALSE;
- gtk_webview_scroll_to_end(view, TRUE);
+ webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), script);
+ priv->empty = FALSE;
+ gtk_webview_scroll_to_end(webview, TRUE);
g_free(script);
g_free(escaped);
}
-gboolean
-gtk_webview_is_empty(GtkWebView *view)
-{
- return view->priv->empty;
-}
-
-#define MAX_SCROLL_TIME 0.4 /* seconds */
-#define SCROLL_DELAY 33 /* milliseconds */
-
-/*
- * Smoothly scroll a WebView.
- *
- * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom.
- */
-static gboolean
-smooth_scroll_cb(gpointer data)
-{
- struct GtkWebViewPriv *priv = data;
- GtkAdjustment *adj = priv->vadj;
- gdouble max_val = adj->upper - adj->page_size;
- gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3);
-
- g_return_val_if_fail(priv->scroll_time != NULL, FALSE);
-
- if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) {
- /* time's up. jump to the end and kill the timer */
- gtk_adjustment_set_value(adj, max_val);
- g_timer_destroy(priv->scroll_time);
- priv->scroll_time = NULL;
- g_source_remove(priv->scroll_src);
- priv->scroll_src = 0;
- return FALSE;
- }
-
- /* scroll by 1/3rd the remaining distance */
- gtk_adjustment_set_value(adj, scroll_val);
- return TRUE;
-}
-
-static gboolean
-scroll_idle_cb(gpointer data)
+void
+gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj)
{
- struct GtkWebViewPriv *priv = data;
- GtkAdjustment *adj = priv->vadj;
- if (adj) {
- gtk_adjustment_set_value(adj, adj->upper - adj->page_size);
- }
- priv->scroll_src = 0;
- return FALSE;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ priv->vadj = vadj;
}
void
gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth)
{
- struct GtkWebViewPriv *priv = webview->priv;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
if (priv->scroll_time)
g_timer_destroy(priv->scroll_time);
if (priv->scroll_src)
g_source_remove(priv->scroll_src);
- if(smooth) {
+ if (smooth) {
priv->scroll_time = g_timer_new();
priv->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, priv, NULL);
} else {
@@ -394,26 +466,40 @@ gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth)
}
}
-GType
-gtk_webview_get_type(void)
+void gtk_webview_page_up(GtkWebView *webview)
{
- static GType mview_type = 0;
- if (G_UNLIKELY(mview_type == 0)) {
- static const GTypeInfo mview_info = {
- sizeof(GtkWebViewClass),
- NULL,
- NULL,
- (GClassInitFunc) gtk_webview_class_init,
- NULL,
- NULL,
- sizeof(GtkWebView),
- 0,
- (GInstanceInitFunc) gtk_webview_init,
- NULL
- };
- mview_type = g_type_register_static(webkit_web_view_get_type(),
- "GtkWebView", &mview_info, 0);
- }
- return mview_type;
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ GtkAdjustment *vadj = priv->vadj;
+ gdouble scroll_val;
+
+#if GTK_CHECK_VERSION(2,14,0)
+ scroll_val = gtk_adjustment_get_value(vadj) - gtk_adjustment_get_page_size(vadj);
+ scroll_val = MAX(scroll_val, gtk_adjustment_get_lower(vadj));
+#else
+ scroll_val = gtk_adjustment_get_value(vadj) - vadj->page_size;
+ scroll_val = MAX(scroll_val, vadj->lower);
+#endif
+
+ gtk_adjustment_set_value(vadj, scroll_val);
+}
+
+void gtk_webview_page_down(GtkWebView *webview)
+{
+ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview);
+ GtkAdjustment *vadj = priv->vadj;
+ gdouble scroll_val;
+ gdouble page_size;
+
+#if GTK_CHECK_VERSION(2,14,0)
+ page_size = gtk_adjustment_get_page_size(vadj);
+ scroll_val = gtk_adjustment_get_value(vadj) + page_size;
+ scroll_val = MIN(scroll_val, gtk_adjustment_get_upper(vadj) - page_size);
+#else
+ page_size = vadj->page_size;
+ scroll_val = gtk_adjustment_get_value(vadj) + page_size;
+ scroll_val = MIN(scroll_val, vadj->upper - page_size);
+#endif
+
+ gtk_adjustment_set_value(vadj, scroll_val);
}
diff --git a/pidgin/gtkwebview.h b/pidgin/gtkwebview.h
index ce0b608499..398bb66b53 100644
--- a/pidgin/gtkwebview.h
+++ b/pidgin/gtkwebview.h
@@ -32,34 +32,27 @@
#include <gtk/gtk.h>
#include <webkit/webkit.h>
-#include "notify.h"
-
#define GTK_TYPE_WEBVIEW (gtk_webview_get_type())
#define GTK_WEBVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_WEBVIEW, GtkWebView))
#define GTK_WEBVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_WEBVIEW, GtkWebViewClass))
#define GTK_IS_WEBVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_WEBVIEW))
-#define GTK_IS_WEBVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_WEBVIEW))
-
+#define GTK_IS_WEBVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_WEBVIEW))
+#define GTK_WEBVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_WEBVIEW, GtkWebViewClass))
-struct GtkWebViewPriv;
+typedef struct _GtkWebView GtkWebView;
+typedef struct _GtkWebViewClass GtkWebViewClass;
struct _GtkWebView
{
- WebKitWebView webkit_web_view;
-
- /*< private >*/
- struct GtkWebViewPriv *priv;
+ WebKitWebView parent;
};
-typedef struct _GtkWebView GtkWebView;
-
struct _GtkWebViewClass
{
WebKitWebViewClass parent;
};
-typedef struct _GtkWebViewClass GtkWebViewClass;
-
+G_BEGIN_DECLS
/**
* Returns the GType for a GtkWebView widget
@@ -76,12 +69,15 @@ GType gtk_webview_get_type(void);
GtkWidget *gtk_webview_new(void);
/**
- * Set the vertical adjustment for the GtkWebView.
+ * TODO WEBKIT: Right now this just tests whether an append has been called
+ * since the last clear or since the Widget was created. So it does not
+ * test for load_string's called in between.
*
- * @param webview The GtkWebView object
- * @param vadj The GtkAdjustment that control the webview
+ * @param webview The GtkWebView object
+ *
+ * @return gboolean indicating whether the webview is empty
*/
-void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj);
+gboolean gtk_webview_is_empty(GtkWebView *webview);
/**
* A very basic routine to append html, which can be considered
@@ -103,17 +99,6 @@ void gtk_webview_append_html(GtkWebView *webview, const char *markup);
void gtk_webview_load_html_string_with_imgstore(GtkWebView *webview, const char *html);
/**
- * TODO WEBKIT: Right now this just tests whether an append has been called
- * since the last clear or since the Widget was created. So it does not
- * test for load_string's called in between.
- *
- * @param webview The GtkWebView object
- *
- * @return gboolean indicating whether the webview is empty
- */
-gboolean gtk_webview_is_empty(GtkWebView *webview);
-
-/**
* Execute the JavaScript only after the webkit_webview_load_string
* loads completely. We also guarantee that the scripts are executed
* in the order they are called here. This is useful to avoid race
@@ -136,6 +121,14 @@ void gtk_webview_safe_execute_script(GtkWebView *webview, const char *script);
char *gtk_webview_quote_js_string(const char *str);
/**
+ * Set the vertical adjustment for the GtkWebView.
+ *
+ * @param webview The GtkWebView object
+ * @param vadj The GtkAdjustment that control the webview
+ */
+void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj);
+
+/**
* Scrolls the Webview to the end of its contents.
*
* @param webview The GtkWebView object
@@ -143,5 +136,21 @@ char *gtk_webview_quote_js_string(const char *str);
*/
void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth);
+/**
+ * Scrolls a GtkWebView up by one page.
+ *
+ * @param webview The GtkWebView.
+ */
+void gtk_webview_page_up(GtkWebView *webview);
+
+/**
+ * Scrolls a GtkWebView down by one page.
+ *
+ * @param webview The GtkWebView.
+ */
+void gtk_webview_page_down(GtkWebView *webview);
+
+G_END_DECLS
+
#endif /* _PIDGIN_WEBVIEW_H_ */
diff --git a/pidgin/gtkwhiteboard.h b/pidgin/gtkwhiteboard.h
index d5bad34a36..e6469adef0 100644
--- a/pidgin/gtkwhiteboard.h
+++ b/pidgin/gtkwhiteboard.h
@@ -59,9 +59,7 @@ typedef struct _PidginWhiteboard
int brush_size; /**< Brush size */
} PidginWhiteboard;
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
/*****************************************************************************/
/** @name PidginWhiteboard API */
@@ -77,8 +75,6 @@ PurpleWhiteboardUiOps *pidgin_whiteboard_get_ui_ops( void );
/*@}*/
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* _PIDGINWHITEBOARD_H_ */
diff --git a/pidgin/pidgintooltip.h b/pidgin/pidgintooltip.h
index 0d6519bcf9..22b97173f5 100644
--- a/pidgin/pidgintooltip.h
+++ b/pidgin/pidgintooltip.h
@@ -59,6 +59,8 @@ typedef gboolean (*PidginTooltipCreate)(GtkWidget *tipwindow,
*/
typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, gpointer userdata);
+G_BEGIN_DECLS
+
/**
* Setup tooltip drawing functions for a treeview.
*
@@ -101,4 +103,6 @@ void pidgin_tooltip_destroy(void);
void pidgin_tooltip_show(GtkWidget *widget, gpointer userdata,
PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb);
+G_END_DECLS
+
#endif
diff --git a/pidgin/plugins/Makefile.am b/pidgin/plugins/Makefile.am
index 4485e025e2..1741d15670 100644
--- a/pidgin/plugins/Makefile.am
+++ b/pidgin/plugins/Makefile.am
@@ -38,6 +38,7 @@ gtk_signals_test_la_LDFLAGS = -module -avoid-version
gtkbuddynote_la_LDFLAGS = -module -avoid-version
history_la_LDFLAGS = -module -avoid-version
iconaway_la_LDFLAGS = -module -avoid-version
+markerline_la_LDFLAGS = -module -avoid-version
notify_la_LDFLAGS = -module -avoid-version
pidginrc_la_LDFLAGS = -module -avoid-version
relnot_la_LDFLAGS = -module -avoid-version
@@ -56,6 +57,7 @@ plugin_LTLIBRARIES = \
gtkbuddynote.la \
history.la \
iconaway.la \
+ markerline.la \
notify.la \
pidginrc.la \
relnot.la \
@@ -80,6 +82,7 @@ gtk_signals_test_la_SOURCES = gtk-signals-test.c
gtkbuddynote_la_SOURCES = gtkbuddynote.c
history_la_SOURCES = history.c
iconaway_la_SOURCES = iconaway.c
+markerline_la_SOURCES = markerline.c
notify_la_SOURCES = notify.c
pidginrc_la_SOURCES = pidginrc.c
relnot_la_SOURCES = relnot.c
@@ -96,6 +99,7 @@ gtk_signals_test_la_LIBADD = $(GTK_LIBS)
gtkbuddynote_la_LIBADD = $(GTK_LIBS)
history_la_LIBADD = $(GTK_LIBS)
iconaway_la_LIBADD = $(GTK_LIBS)
+markerline_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS)
notify_la_LIBADD = $(GTK_LIBS)
pidginrc_la_LIBADD = $(GTK_LIBS)
relnot_la_LIBADD = $(GLIB_LIBS)
diff --git a/pidgin/plugins/markerline.c b/pidgin/plugins/markerline.c
index 7db983f3f2..461da4fd61 100644
--- a/pidgin/plugins/markerline.c
+++ b/pidgin/plugins/markerline.c
@@ -33,81 +33,38 @@
/* Purple headers */
#include <gtkconv.h>
-#include <gtkimhtml.h>
#include <gtkplugin.h>
+#include <gtkwebview.h>
#include <version.h>
#define PREF_PREFIX "/plugins/gtk/" PLUGIN_ID
#define PREF_IMS PREF_PREFIX "/ims"
#define PREF_CHATS PREF_PREFIX "/chats"
-static int
-imhtml_expose_cb(GtkWidget *widget, GdkEventExpose *event, PidginConversation *gtkconv)
-{
- int y, last_y, offset;
- GdkRectangle visible_rect;
- GtkTextIter iter;
- GdkRectangle buf;
- int pad;
- PurpleConversation *conv = gtkconv->active_conv;
- PurpleConversationType type = purple_conversation_get_type(conv);
-
- if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) ||
- (type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS)))
- return FALSE;
-
- gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect);
-
- offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "markerline"));
- if (offset)
- {
- gtk_text_buffer_get_iter_at_offset(gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)),
- &iter, offset);
-
- gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &iter, &buf);
- last_y = buf.y + buf.height;
- pad = (gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget)) +
- gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget))) / 2;
- last_y += pad;
- }
- else
- last_y = 0;
-
- gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT,
- 0, last_y, 0, &y);
-
- if (y >= event->area.y)
- {
- GdkColor red = {0, 0xffff, 0, 0};
- cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window));
-
- gdk_cairo_set_source_color(cr, &red);
- cairo_move_to(cr, 0.0, y + 0.5);
- cairo_rel_line_to(cr, visible_rect.width, 0.0);
- cairo_set_line_width(cr, 1.0);
- cairo_stroke(cr);
- cairo_destroy(cr);
- }
- return FALSE;
-}
-
static void
update_marker_for_gtkconv(PidginConversation *gtkconv)
{
- GtkTextIter iter;
- GtkTextBuffer *buffer;
+ PurpleConversation *conv;
+ PurpleConversationType type;
+
g_return_if_fail(gtkconv != NULL);
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml));
+ conv = gtkconv->active_conv;
+ type = purple_conversation_get_type(conv);
- if (!gtk_text_buffer_get_char_count(buffer))
+ if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) ||
+ (type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS)))
return;
- gtk_text_buffer_get_end_iter(buffer, &iter);
-
- g_object_set_data(G_OBJECT(gtkconv->imhtml), "markerline",
- GINT_TO_POINTER(gtk_text_iter_get_offset(&iter)));
- gtk_widget_queue_draw(gtkconv->imhtml);
+ gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview),
+ "var mhr = document.getElementById(\"markerhr\");"
+ "if (!mhr) {"
+ "mhr = document.createElement(\"hr\");"
+ "mhr.setAttribute(\"id\", \"markerhr\");"
+ "mhr.setAttribute(\"color\", \"#ff0000\");"
+ "mhr.setAttribute(\"size\", \"1\");"
+ "}"
+ "document.getElementById(\"Chat\").appendChild(mhr);");
}
static gboolean
@@ -125,28 +82,6 @@ focus_removed(GtkWidget *widget, GdkEventVisibility *event, PidginWindow *win)
return FALSE;
}
-#if 0
-static gboolean
-window_resized(GtkWidget *w, GdkEventConfigure *event, PidginWindow *win)
-{
- GList *list;
-
- list = pidgin_conv_window_get_gtkconvs(win);
-
- for (; list; list = list->next)
- update_marker_for_gtkconv(list->data);
-
- return FALSE;
-}
-
-static gboolean
-imhtml_resize_cb(GtkWidget *w, GtkAllocation *allocation, PidginConversation *gtkconv)
-{
- gtk_widget_queue_draw(w);
- return FALSE;
-}
-#endif
-
static void
page_switched(GtkWidget *widget, GtkWidget *page, gint num, PidginWindow *win)
{
@@ -156,7 +91,9 @@ page_switched(GtkWidget *widget, GtkWidget *page, gint num, PidginWindow *win)
static void
detach_from_gtkconv(PidginConversation *gtkconv, gpointer null)
{
- g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml), imhtml_expose_cb, gtkconv);
+ gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview),
+ "var mhr = document.getElementById(\"markerhr\");"
+ "if (mhr) mhr.parentNode.removeChild(mhr);");
}
static void
@@ -165,16 +102,13 @@ detach_from_pidgin_window(PidginWindow *win, gpointer null)
g_list_foreach(pidgin_conv_window_get_gtkconvs(win), (GFunc)detach_from_gtkconv, NULL);
g_signal_handlers_disconnect_by_func(G_OBJECT(win->notebook), page_switched, win);
g_signal_handlers_disconnect_by_func(G_OBJECT(win->window), focus_removed, win);
-
- gtk_widget_queue_draw(win->window);
}
static void
attach_to_gtkconv(PidginConversation *gtkconv, gpointer null)
{
detach_from_gtkconv(gtkconv, NULL);
- g_signal_connect(G_OBJECT(gtkconv->imhtml), "expose_event",
- G_CALLBACK(imhtml_expose_cb), gtkconv);
+ update_marker_for_gtkconv(gtkconv);
}
static void
@@ -187,8 +121,6 @@ attach_to_pidgin_window(PidginWindow *win, gpointer null)
g_signal_connect(G_OBJECT(win->notebook), "switch_page",
G_CALLBACK(page_switched), win);
-
- gtk_widget_queue_draw(win->window);
}
static void
@@ -220,15 +152,15 @@ static void
jump_to_markerline(PurpleConversation *conv, gpointer null)
{
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- int offset;
- GtkTextIter iter;
if (!gtkconv)
return;
- offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->imhtml), "markerline"));
- gtk_text_buffer_get_iter_at_offset(GTK_IMHTML(gtkconv->imhtml)->text_buffer, &iter, offset);
- gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &iter, 0, TRUE, 0, 0);
+ gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview),
+ "var mhr = document.getElementById(\"markerhr\");"
+ "if (mhr) {"
+ "window.scroll(0, mhr.offsetTop);"
+ "}");
}
static void
diff --git a/pidgin/smileyparser.h b/pidgin/smileyparser.h
index a8dc349eb3..a1c1e550b7 100644
--- a/pidgin/smileyparser.h
+++ b/pidgin/smileyparser.h
@@ -20,6 +20,10 @@
*
*/
+G_BEGIN_DECLS
+
char *
smiley_parse_markup(const char *markup, const char *sml);
+G_END_DECLS
+
diff --git a/pidgin/themes/Template.html b/pidgin/themes/Template.html
index 0a7f9d6662..e3c80eb39b 100644
--- a/pidgin/themes/Template.html
+++ b/pidgin/themes/Template.html
@@ -3,66 +3,215 @@
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<base href="%@">
- <script type="text/ecmascript" defer="defer">
-
+ <script type="text/javascript" defer="defer">
+ // NOTE:
+ // Any percent signs in this file must be escaped!
+ // Use two escape signs (%%) to display it, this is passed through a format call!
+
+ function appendHTML(html) {
+ var node = document.getElementById("Chat");
+ var range = document.createRange();
+ range.selectNode(node);
+ var documentFragment = range.createContextualFragment(html);
+ node.appendChild(documentFragment);
+ }
+
+ // a coalesced HTML object buffers and outputs DOM objects en masse.
+ // saves A LOT of CSS recalculation time when loading many messages.
+ // (ex. a long twitter timeline)
+ function CoalescedHTML() {
+ var self = this;
+ this.fragment = document.createDocumentFragment();
+ this.timeoutID = 0;
+ this.coalesceRounds = 0;
+ this.isCoalescing = false;
+ this.isConsecutive = undefined;
+ this.shouldScroll = undefined;
+
+ var appendElement = function (elem) {
+ document.getElementById("Chat").appendChild(elem);
+ };
+
+ function outputHTML() {
+ var insert = document.getElementById("insert");
+ if(!!insert && self.isConsecutive) {
+ insert.parentNode.replaceChild(self.fragment, insert);
+ } else {
+ if(insert)
+ insert.parentNode.removeChild(insert);
+ // insert the documentFragment into the live DOM
+ appendElement(self.fragment);
+ }
+ alignChat(self.shouldScroll);
+
+ // reset state to empty/non-coalescing
+ self.shouldScroll = undefined;
+ self.isConsecutive = undefined;
+ self.isCoalescing = false;
+ self.coalesceRounds = 0;
+ }
+
+ // creates and returns a new documentFragment, containing all content nodes
+ // which can be inserted as a single node.
+ function createHTMLNode(html) {
+ var range = document.createRange();
+ range.selectNode(document.getElementById("Chat"));
+ return range.createContextualFragment(html);
+ }
+
+ // removes first insert node from the internal fragment.
+ function rmInsertNode() {
+ var insert = self.fragment.querySelector("#insert");
+ if(insert)
+ insert.parentNode.removeChild(insert);
+ }
+
+ function setShouldScroll(flag) {
+ if(flag && undefined === self.shouldScroll)
+ self.shouldScroll = flag;
+ }
+
+ // hook in a custom method to append new data
+ // to the chat.
+ this.setAppendElementMethod = function (func) {
+ if(typeof func === 'function')
+ appendElement = func;
+ }
+
+ // (re)start the coalescing timer.
+ // we wait 25ms for a new message to come in.
+ // If we get one, restart the timer and wait another 10ms.
+ // If not, run outputHTML()
+ // We do this a maximum of 400 times, for 10s max that can be spent
+ // coalescing input, since this will block display.
+ this.coalesce = function() {
+ window.clearTimeout(self.timeoutID);
+ self.timeoutID = window.setTimeout(outputHTML, 25);
+ self.isCoalescing = true;
+ self.coalesceRounds += 1;
+ if(400 < self.coalesceRounds)
+ self.cancel();
+ }
+
+ // if we need to append content into an insertion div,
+ // we need to clear the buffer and cancel the timeout.
+ this.cancel = function() {
+ if(self.isCoalescing) {
+ window.clearTimeout(self.timeoutID);
+ outputHTML();
+ }
+ }
+
+
+ // coalased analogs to the global functions
+
+ this.append = function(html, shouldScroll) {
+ // if we started this fragment with a consecuative message,
+ // cancel and output before we continue
+ if(self.isConsecutive) {
+ self.cancel();
+ }
+ self.isConsecutive = false;
+ rmInsertNode();
+ var node = createHTMLNode(html);
+ self.fragment.appendChild(node);
+
+ node = null;
+
+ setShouldScroll(shouldScroll);
+ self.coalesce();
+ }
+
+ this.appendNext = function(html, shouldScroll) {
+ if(undefined === self.isConsecutive)
+ self.isConsecutive = true;
+ var node = createHTMLNode(html);
+ var insert = self.fragment.querySelector("#insert");
+ if(insert) {
+ insert.parentNode.replaceChild(node, insert);
+ } else {
+ self.fragment.appendChild(node);
+ }
+ node = null;
+ setShouldScroll(shouldScroll);
+ self.coalesce();
+ }
+
+ this.replaceLast = function (html, shouldScroll) {
+ rmInsertNode();
+ var node = createHTMLNode(html);
+ var lastMessage = self.fragment.lastChild;
+ lastMessage.parentNode.replaceChild(node, lastMessage);
+ node = null;
+ setShouldScroll(shouldScroll);
+ }
+ }
+ var coalescedHTML;
+
//Appending new content to the message view
function appendMessage(html) {
- shouldScroll = nearBottom();
-
- //Remove any existing insertion point
- insert = document.getElementById("insert");
- if(insert) insert.parentNode.removeChild(insert);
-
- //Append the new message to the bottom of our chat block
- chat = document.getElementById("Chat");
- range = document.createRange();
- range.selectNode(chat);
- documentFragment = range.createContextualFragment(html);
- chat.appendChild(documentFragment);
-
- alignChat(shouldScroll);
+ var shouldScroll;
+
+ // Only call nearBottom() if should scroll is undefined.
+ if(undefined === coalescedHTML.shouldScroll) {
+ shouldScroll = nearBottom();
+ } else {
+ shouldScroll = coalescedHTML.shouldScroll;
+ }
+ appendMessageNoScroll(html, shouldScroll);
}
- function appendMessageNoScroll(html) {
- //Remove any existing insertion point
- insert = document.getElementById("insert");
- if(insert) insert.parentNode.removeChild(insert);
- //Append the new message to the bottom of our chat block
- chat = document.getElementById("Chat");
- range = document.createRange();
- range.selectNode(chat);
- documentFragment = range.createContextualFragment(html);
- chat.appendChild(documentFragment);
+ function appendMessageNoScroll(html, shouldScroll) {
+ shouldScroll = shouldScroll || false;
+ // always try to coalesce new, non-griuped, messages
+ coalescedHTML.append(html, shouldScroll)
}
+
function appendNextMessage(html){
- shouldScroll = nearBottom();
-
- //Locate the insertion point
- insert = document.getElementById("insert");
-
- //make new node
- range = document.createRange();
- range.selectNode(insert.parentNode);
- newNode = range.createContextualFragment(html);
-
- //swap
- insert.parentNode.replaceChild(newNode,insert);
-
- alignChat(shouldScroll);
+ var shouldScroll;
+ if(undefined === coalescedHTML.shouldScroll) {
+ shouldScroll = nearBottom();
+ } else {
+ shouldScroll = coalescedHTML.shouldScroll;
+ }
+ appendNextMessageNoScroll(html, shouldScroll);
}
- function appendNextMessageNoScroll(html){
- //Locate the insertion point
- insert = document.getElementById("insert");
-
- //make new node
- range = document.createRange();
- range.selectNode(insert.parentNode);
- newNode = range.createContextualFragment(html);
- //swap
- insert.parentNode.replaceChild(newNode,insert);
+ function appendNextMessageNoScroll(html, shouldScroll){
+ shouldScroll = shouldScroll || false;
+ // only group next messages if we're already coalescing input
+ coalescedHTML.appendNext(html, shouldScroll);
}
-
+
+ function replaceLastMessage(html){
+ var shouldScroll;
+ // only replace messages if we're already coalescing
+ if(coalescedHTML.isCoalescing){
+ if(undefined === coalescedHTML.shouldScroll) {
+ shouldScroll = nearBottom();
+ } else {
+ shouldScroll = coalescedHTML.shouldScroll;
+ }
+ coalescedHTML.replaceLast(html, shouldScroll);
+ } else {
+ shouldScroll = nearBottom();
+ //Retrieve the current insertion point, then remove it
+ //This requires that there have been an insertion point... is there a better way to retrieve the last element? -evands
+ var insert = document.getElementById("insert");
+ if(insert){
+ var parentNode = insert.parentNode;
+ parentNode.removeChild(insert);
+ var lastMessage = document.getElementById("Chat").lastChild;
+ document.getElementById("Chat").removeChild(lastMessage);
+ }
+
+ //Now append the message itself
+ appendHTML(html);
+
+ alignChat(shouldScroll);
+ }
+ }
+
//Auto-scroll to bottom. Use nearBottom to determine if a scrollToBottom is desired.
function nearBottom() {
return ( document.body.scrollTop >= ( document.body.offsetHeight - ( window.innerHeight * 1.2 ) ) );
@@ -73,89 +222,119 @@
//Dynamically exchange the active stylesheet
function setStylesheet( id, url ) {
- code = "<style id=\"" + id + "\" type=\"text/css\" media=\"screen,print\">";
- if( url.length ) code += "@import url( \"" + url + "\" );";
+ var code = "<style id=\"" + id + "\" type=\"text/css\" media=\"screen,print\">";
+ if( url.length )
+ code += "@import url( \"" + url + "\" );";
code += "</style>";
- range = document.createRange();
- head = document.getElementsByTagName( "head" ).item(0);
+ var range = document.createRange();
+ var head = document.getElementsByTagName( "head" ).item(0);
range.selectNode( head );
- documentFragment = range.createContextualFragment( code );
+ var documentFragment = range.createContextualFragment( code );
head.removeChild( document.getElementById( id ) );
head.appendChild( documentFragment );
}
-
- //Swap an image with its alt-tag text on click, or expand/unexpand an attached image
- document.onclick = imageCheck;
- function imageCheck() {
- node = event.target;
- if(node.tagName == 'IMG' && !client.zoomImage(node) && node.alt) {
- a = document.createElement('a');
- a.setAttribute('onclick', 'imageSwap(this)');
- a.setAttribute('src', node.getAttribute('src'));
- a.className = node.className;
- text = document.createTextNode(node.alt);
- a.appendChild(text);
- node.parentNode.replaceChild(a, node);
- }
+
+ /* Converts emoticon images to textual emoticons; all emoticons in message if alt is held */
+ document.onclick = function imageCheck() {
+ var node = event.target;
+ if (node.tagName.toLowerCase() != 'img')
+ return;
+
+ imageSwap(node, false);
}
- function imageSwap(node) {
- shouldScroll = nearBottom();
+ /* Converts textual emoticons to images if textToImagesFlag is true, otherwise vice versa */
+ function imageSwap(node, textToImagesFlag) {
+ var shouldScroll = nearBottom();
+ var images = [node];
+ if (event.altKey) {
+ while (node.id != "Chat" && node.parentNode.id != "Chat")
+ node = node.parentNode;
+ images = node.querySelectorAll(textToImagesFlag ? "a" : "img");
+ }
+
+ for (var i = 0; i < images.length; i++) {
+ textToImagesFlag ? textToImage(images[i]) : imageToText(images[i]);
+ }
+
+ alignChat(shouldScroll);
+ }
+
+ function textToImage(node) {
+ if (!node.getAttribute("isEmoticon"))
+ return;
//Swap the image/text
- img = document.createElement('img');
+ var img = document.createElement('img');
img.setAttribute('src', node.getAttribute('src'));
img.setAttribute('alt', node.firstChild.nodeValue);
img.className = node.className;
node.parentNode.replaceChild(img, node);
-
- alignChat(shouldScroll);
}
-
+
+ function imageToText(node)
+ {
+ if (client.zoomImage(node) || !node.alt)
+ return;
+ var a = document.createElement('a');
+ a.setAttribute('onclick', 'imageSwap(this, true)');
+ a.setAttribute('src', node.getAttribute('src'));
+ a.setAttribute('isEmoticon', true);
+ a.className = node.className;
+ var text = document.createTextNode(node.alt);
+ a.appendChild(text);
+ node.parentNode.replaceChild(a, node);
+ }
+
//Align our chat to the bottom of the window. If true is passed, view will also be scrolled down
function alignChat(shouldScroll) {
var windowHeight = window.innerHeight;
-
+
if (windowHeight > 0) {
var contentElement = document.getElementById('Chat');
- var contentHeight = contentElement.offsetHeight;
- if (windowHeight - contentHeight > 0) {
+ var heightDifference = (windowHeight - contentElement.offsetHeight);
+ if (heightDifference > 0) {
contentElement.style.position = 'relative';
- contentElement.style.top = (windowHeight - contentHeight) + 'px';
+ contentElement.style.top = heightDifference + 'px';
} else {
contentElement.style.position = 'static';
}
}
-
+
if (shouldScroll) scrollToBottom();
}
-
- function windowDidResize(){
+
+ window.onresize = function windowDidResize(){
alignChat(true/*nearBottom()*/); //nearBottom buggy with inactive tabs
}
-
- window.onresize = windowDidResize;
+
+ function initStyle() {
+ alignChat(true);
+ if(!coalescedHTML)
+ coalescedHTML = new CoalescedHTML();
+ }
</script>
-
+
<style type="text/css">
- .actionMessageUserName:before { content:"*"; }
+ .actionMessageUserName { display:none; }
+ .actionMessageBody:before { content:"*"; }
.actionMessageBody:after { content:"*"; }
- *{ word-wrap:break-word; }
- img.scaledToFitImage { height:auto; width:100%; }
+ * { word-wrap:break-word; text-rendering: optimizelegibility; }
+ img.scaledToFitImage { height: auto; max-width: 100%%; }
</style>
-
+
<!-- This style is shared by all variants. !-->
- <style id="baseStyle" type="text/css" media="screen,print">
+ <style id="baseStyle" type="text/css" media="screen,print">
%@
</style>
-
+
<!-- Although we call this mainStyle for legacy reasons, it's actually the variant style !-->
- <style id="mainStyle" type="text/css" media="screen,print">
+ <style id="mainStyle" type="text/css" media="screen,print">
@import url( "%@" );
</style>
</head>
-<body onload="alignChat(true);" style="==bodyBackground==">
+<body onload="initStyle();" style="==bodyBackground==">
%@
<div id="Chat">
</div>