aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk/empathy-theme-adium.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk/empathy-theme-adium.c')
-rw-r--r--libempathy-gtk/empathy-theme-adium.c659
1 files changed, 401 insertions, 258 deletions
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index 2ab3383b3..06410c528 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -22,7 +22,7 @@
#include "config.h"
#include <string.h>
-#include <glib/gi18n.h>
+#include <glib/gi18n-lib.h>
#include <webkit/webkit.h>
#include <telepathy-glib/dbus.h>
@@ -59,11 +59,13 @@ typedef struct {
gint64 last_timestamp;
gboolean last_is_backlog;
guint pages_loading;
- GList *message_queue;
+ /* Queue of GValue* containing an EmpathyMessage or string */
+ GQueue message_queue;
GtkWidget *inspector_window;
GSettings *gsettings_chat;
gboolean has_focus;
gboolean has_unread_message;
+ gboolean allow_scrolling;
} EmpathyThemeAdiumPriv;
struct _EmpathyAdiumData {
@@ -73,26 +75,27 @@ struct _EmpathyAdiumData {
gchar *default_avatar_filename;
gchar *default_incoming_avatar_filename;
gchar *default_outgoing_avatar_filename;
- gchar *template_html;
- gchar *in_content_html;
- gsize in_content_len;
- gchar *in_context_html;
- gsize in_context_len;
- gchar *in_nextcontent_html;
- gsize in_nextcontent_len;
- gchar *in_nextcontext_html;
- gsize in_nextcontext_len;
- gchar *out_content_html;
- gsize out_content_len;
- gchar *out_context_html;
- gsize out_context_len;
- gchar *out_nextcontent_html;
- gsize out_nextcontent_len;
- gchar *out_nextcontext_html;
- gsize out_nextcontext_len;
- gchar *status_html;
- gsize status_len;
GHashTable *info;
+ guint version;
+ gboolean custom_template;
+
+ /* HTML bits */
+ const gchar *template_html;
+ const gchar *content_html;
+ const gchar *in_content_html;
+ const gchar *in_context_html;
+ const gchar *in_nextcontent_html;
+ const gchar *in_nextcontext_html;
+ const gchar *out_content_html;
+ const gchar *out_context_html;
+ const gchar *out_nextcontent_html;
+ const gchar *out_nextcontext_html;
+ const gchar *status_html;
+
+ /* Above html strings are pointers to strings stored in this array.
+ * We do this because of fallbacks, some htmls could be pointing the
+ * same string. */
+ GPtrArray *strings_to_free;
};
static void theme_adium_iface_init (EmpathyChatViewIface *iface);
@@ -191,6 +194,36 @@ theme_adium_open_address_cb (GtkMenuItem *menuitem,
g_free (uri);
}
+/* Replace each %@ in format with string passed in args */
+static gchar *
+string_with_format (const gchar *format,
+ const gchar *first_string,
+ ...)
+{
+ va_list args;
+ const gchar *str;
+ GString *result;
+
+ va_start (args, first_string);
+ result = g_string_sized_new (strlen (format));
+ for (str = first_string; str != NULL; str = va_arg (args, const gchar *)) {
+ const gchar *next;
+
+ next = strstr (format, "%@");
+ if (next == NULL) {
+ break;
+ }
+
+ g_string_append_len (result, format, next - format);
+ g_string_append (result, str);
+ format = next + 2;
+ }
+ g_string_append (result, format);
+ va_end (args);
+
+ return g_string_free (result, FALSE);
+}
+
static void
theme_adium_match_newline (const gchar *text,
gssize len,
@@ -283,7 +316,7 @@ theme_adium_parse_body (EmpathyThemeAdium *self,
static void
escape_and_append_len (GString *string, const gchar *str, gint len)
{
- while (*str != '\0' && len != 0) {
+ while (str != NULL && *str != '\0' && len != 0) {
switch (*str) {
case '\\':
/* \ becomes \\ */
@@ -345,10 +378,36 @@ theme_adium_match_with_format (const gchar **str,
return TRUE;
}
+/* List of colors used by %senderColor%. Copied from
+ * adium/Frameworks/AIUtilities\ Framework/Source/AIColorAdditions.m
+ */
+static gchar *colors[] = {
+ "aqua", "aquamarine", "blue", "blueviolet", "brown", "burlywood", "cadetblue",
+ "chartreuse", "chocolate", "coral", "cornflowerblue", "crimson", "cyan",
+ "darkblue", "darkcyan", "darkgoldenrod", "darkgreen", "darkgrey", "darkkhaki",
+ "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred",
+ "darksalmon", "darkseagreen", "darkslateblue", "darkslategrey",
+ "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgrey",
+ "dodgerblue", "firebrick", "forestgreen", "fuchsia", "gold", "goldenrod",
+ "green", "greenyellow", "grey", "hotpink", "indianred", "indigo", "lawngreen",
+ "lightblue", "lightcoral",
+ "lightgreen", "lightgrey", "lightpink", "lightsalmon", "lightseagreen",
+ "lightskyblue", "lightslategrey", "lightsteelblue", "lime", "limegreen",
+ "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid",
+ "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen",
+ "mediumturquoise", "mediumvioletred", "midnightblue", "navy", "olive",
+ "olivedrab", "orange", "orangered", "orchid", "palegreen", "paleturquoise",
+ "palevioletred", "peru", "pink", "plum", "powderblue", "purple", "red",
+ "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen",
+ "sienna", "silver", "skyblue", "slateblue", "slategrey", "springgreen",
+ "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet",
+ "yellowgreen",
+};
+
static void
theme_adium_append_html (EmpathyThemeAdium *theme,
const gchar *func,
- const gchar *html, gsize len,
+ const gchar *html,
const gchar *message,
const gchar *avatar_filename,
const gchar *name,
@@ -363,10 +422,10 @@ theme_adium_append_html (EmpathyThemeAdium *theme,
gchar *script;
/* Make some search-and-replace in the html code */
- string = g_string_sized_new (len + strlen (message));
+ string = g_string_sized_new (strlen (html) + strlen (message));
g_string_append_printf (string, "%s(\"", func);
for (cur = html; *cur != '\0'; cur++) {
- const gchar *replace = "";
+ const gchar *replace = NULL;
gchar *dup_replace = NULL;
gchar *format = NULL;
@@ -380,11 +439,15 @@ theme_adium_append_html (EmpathyThemeAdium *theme,
} else if (theme_adium_match (&cur, "%sender%")) {
replace = name;
} else if (theme_adium_match (&cur, "%senderColor%")) {
- /* FIXME: A color derived from the user's name. If a
- * colon separated list of HTML colors is at
+ /* A color derived from the user's name.
+ * FIXME: If a colon separated list of HTML colors is at
* Incoming/SenderColors.txt it will be used instead of
* the default colors.
*/
+ if (contact_id != NULL) {
+ guint hash = g_str_hash (contact_id);
+ replace = colors[hash % G_N_ELEMENTS (colors)];
+ }
} else if (theme_adium_match (&cur, "%senderStatusIcon%")) {
/* FIXME: The path to the status icon of the sender
* (available, away, etc...)
@@ -493,13 +556,10 @@ theme_adium_append_event_escaped (EmpathyChatView *view,
EmpathyThemeAdium *theme = EMPATHY_THEME_ADIUM (view);
EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
- if (priv->data->status_html) {
- theme_adium_append_html (theme, "appendMessage",
- priv->data->status_html,
- priv->data->status_len,
- escaped, NULL, NULL, NULL, NULL,
- "event", empathy_time_get_current (), FALSE);
- }
+ theme_adium_append_html (theme, "appendMessage",
+ priv->data->status_html, escaped, NULL, NULL, NULL,
+ NULL, "event",
+ empathy_time_get_current (), FALSE);
/* There is no last contact */
if (priv->last_contact) {
@@ -511,11 +571,17 @@ theme_adium_append_event_escaped (EmpathyChatView *view,
static void
theme_adium_remove_focus_marks (EmpathyThemeAdium *theme)
{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
WebKitDOMDocument *dom;
WebKitDOMNodeList *nodes;
guint i;
GError *error = NULL;
+ if (!priv->has_unread_message)
+ return;
+
+ priv->has_unread_message = FALSE;
+
dom = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (theme));
if (dom == NULL) {
return;
@@ -580,17 +646,18 @@ theme_adium_append_message (EmpathyChatView *view,
EmpathyAvatar *avatar;
const gchar *avatar_filename = NULL;
gint64 timestamp;
- gchar *html = NULL;
- gsize len = 0;
+ const gchar *html = NULL;
const gchar *func;
const gchar *service_name;
GString *message_classes = NULL;
gboolean is_backlog;
gboolean consecutive;
+ gboolean action;
if (priv->pages_loading != 0) {
- priv->message_queue = g_list_prepend (priv->message_queue,
- g_object_ref (msg));
+ GValue *value = tp_g_value_slice_new (EMPATHY_TYPE_MESSAGE);
+ g_value_set_object (value, msg);
+ g_queue_push_tail (&priv->message_queue, value);
return;
}
@@ -606,17 +673,21 @@ theme_adium_append_message (EmpathyChatView *view,
body_escaped = theme_adium_parse_body (theme, body);
name = empathy_contact_get_alias (sender);
contact_id = empathy_contact_get_id (sender);
+ action = (empathy_message_get_tptype (msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION);
- /* If this is a /me, append an event */
- if (empathy_message_get_tptype (msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) {
+ /* If this is a /me probably */
+ if (action) {
gchar *str;
- str = g_strdup_printf ("%s %s", name, body_escaped);
- theme_adium_append_event_escaped (view, str);
-
- g_free (str);
+ if (priv->data->version >= 4 || !priv->data->custom_template) {
+ str = g_strdup_printf ("<span class='actionMessageUserName'>%s</span>"
+ "<span class='actionMessageBody'>%s</span>",
+ name, body_escaped);
+ } else {
+ str = g_strdup_printf ("*%s*", body_escaped);
+ }
g_free (body_escaped);
- return;
+ body_escaped = str;
}
/* Get the avatar filename, or a fallback */
@@ -656,10 +727,6 @@ theme_adium_append_message (EmpathyChatView *view,
message_classes = g_string_new ("message");
if (!priv->has_focus && !is_backlog) {
if (!priv->has_unread_message) {
- /* This is the first message we receive since we lost
- * focus; remove previous unread marks. */
- theme_adium_remove_focus_marks (theme);
-
g_string_append (message_classes, " firstFocus");
priv->has_unread_message = TRUE;
}
@@ -676,95 +743,56 @@ theme_adium_append_message (EmpathyChatView *view,
} else {
g_string_append (message_classes, " incoming");
}
+ if (empathy_message_should_highlight (msg)) {
+ g_string_append (message_classes, " mention");
+ }
+ if (empathy_message_get_tptype (msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY) {
+ g_string_append (message_classes, " autoreply");
+ }
+ if (action) {
+ g_string_append (message_classes, " action");
+ }
/* FIXME: other classes:
- * autoreply - the message is an automatic response, generally due to an
- * away status
- * mention - the incoming message (in groupchat) matches your username
- * or one of the mention keywords specified in Adium's
- * advanced prefs.
* status - the message is a status change
* event - the message is a notification of something happening
* (for example, encryption being turned on)
- * %status% - See %status% in theme_adium_append_html()
+ * %status% - See %status% in theme_adium_append_html ()
*/
/* Define javascript function to use */
if (consecutive) {
- func = "appendNextMessage";
+ func = priv->allow_scrolling ? "appendNextMessage" : "appendNextMessageNoScroll";
} else {
- func = "appendMessage";
+ func = priv->allow_scrolling ? "appendMessage" : "appendMessageNoScroll";
}
- /* Outgoing */
if (empathy_contact_is_user (sender)) {
- if (consecutive) {
- if (is_backlog) {
- html = priv->data->out_nextcontext_html;
- len = priv->data->out_nextcontext_len;
- }
-
- /* Not backlog, or fallback if NextContext.html
- * is missing */
- if (html == NULL) {
- html = priv->data->out_nextcontent_html;
- len = priv->data->out_nextcontent_len;
- }
- }
-
- /* Not consecutive, or fallback if NextContext.html and/or
- * NextContent.html are missing */
- if (html == NULL) {
- if (is_backlog) {
- html = priv->data->out_context_html;
- len = priv->data->out_context_len;
- }
-
- if (html == NULL) {
- html = priv->data->out_content_html;
- len = priv->data->out_content_len;
- }
- }
- }
-
- /* Incoming, or fallback if outgoing files are missing */
- if (html == NULL) {
- if (consecutive) {
- if (is_backlog) {
- html = priv->data->in_nextcontext_html;
- len = priv->data->in_nextcontext_len;
- }
-
- /* Note backlog, or fallback if NextContext.html
- * is missing */
- if (html == NULL) {
- html = priv->data->in_nextcontent_html;
- len = priv->data->in_nextcontent_len;
- }
+ /* out */
+ if (is_backlog) {
+ /* context */
+ html = consecutive ? priv->data->out_nextcontext_html : priv->data->out_context_html;
+ } else {
+ /* content */
+ html = consecutive ? priv->data->out_nextcontent_html : priv->data->out_content_html;
}
- /* Not consecutive, or fallback if NextContext.html and/or
- * NextContent.html are missing */
- if (html == NULL) {
- if (is_backlog) {
- html = priv->data->in_context_html;
- len = priv->data->in_context_len;
- }
-
- if (html == NULL) {
- html = priv->data->in_content_html;
- len = priv->data->in_content_len;
- }
+ /* remove all the unread marks when we are sending a message */
+ theme_adium_remove_focus_marks (theme);
+ } else {
+ /* in */
+ if (is_backlog) {
+ /* context */
+ html = consecutive ? priv->data->in_nextcontext_html : priv->data->in_context_html;
+ } else {
+ /* content */
+ html = consecutive ? priv->data->in_nextcontent_html : priv->data->in_content_html;
}
}
- if (html != NULL) {
- theme_adium_append_html (theme, func, html, len, body_escaped,
- avatar_filename, name, contact_id,
- service_name, message_classes->str,
- timestamp, is_backlog);
- } else {
- DEBUG ("Couldn't find HTML file for this message");
- }
+ theme_adium_append_html (theme, func, html, body_escaped,
+ avatar_filename, name, contact_id,
+ service_name, message_classes->str,
+ timestamp, is_backlog);
/* Keep the sender of the last displayed message */
if (priv->last_contact) {
@@ -782,8 +810,15 @@ static void
theme_adium_append_event (EmpathyChatView *view,
const gchar *str)
{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
gchar *str_escaped;
+ if (priv->pages_loading != 0) {
+ g_queue_push_tail (&priv->message_queue,
+ tp_g_value_slice_new_string (str));
+ return;
+ }
+
str_escaped = g_markup_escape_text (str, -1);
theme_adium_append_event_escaped (view, str_escaped);
g_free (str_escaped);
@@ -793,14 +828,18 @@ static void
theme_adium_scroll (EmpathyChatView *view,
gboolean allow_scrolling)
{
- /* FIXME: Is it possible? I guess we need a js function, but I don't
- * see any... */
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+
+ priv->allow_scrolling = allow_scrolling;
+ if (allow_scrolling) {
+ empathy_chat_view_scroll_down (view);
+ }
}
static void
theme_adium_scroll_down (EmpathyChatView *view)
{
- webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), "scrollToBottom()");
+ webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), "alignChat(true);");
}
static gboolean
@@ -891,11 +930,12 @@ static void
theme_adium_focus_toggled (EmpathyChatView *view,
gboolean has_focus)
{
+ EmpathyThemeAdium *self = (EmpathyThemeAdium *) view;
EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
priv->has_focus = has_focus;
- if (priv->has_focus) {
- priv->has_unread_message = FALSE;
+ if (!priv->has_focus) {
+ theme_adium_remove_focus_marks (self);
}
}
@@ -1028,6 +1068,7 @@ theme_adium_load_finished_cb (WebKitWebView *view,
{
EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
EmpathyChatView *chat_view = EMPATHY_CHAT_VIEW (view);
+ GList *l;
DEBUG ("Page loaded");
priv->pages_loading--;
@@ -1036,14 +1077,20 @@ theme_adium_load_finished_cb (WebKitWebView *view,
return;
/* Display queued messages */
- priv->message_queue = g_list_reverse (priv->message_queue);
- while (priv->message_queue) {
- EmpathyMessage *message = priv->message_queue->data;
+ for (l = priv->message_queue.head; l != NULL; l = l->next) {
+ GValue *value = l->data;
+
+ if (G_VALUE_HOLDS_OBJECT (value)) {
+ theme_adium_append_message (chat_view,
+ g_value_get_object (value));
+ } else {
+ theme_adium_append_event (chat_view,
+ g_value_get_string (value));
+ }
- theme_adium_append_message (chat_view, message);
- priv->message_queue = g_list_remove (priv->message_queue, message);
- g_object_unref (message);
+ tp_g_value_slice_free (value);
}
+ g_queue_clear (&priv->message_queue);
}
static void
@@ -1319,6 +1366,8 @@ empathy_theme_adium_init (EmpathyThemeAdium *theme)
theme->priv = priv;
+ g_queue_init (&priv->message_queue);
+ priv->allow_scrolling = TRUE;
priv->smiley_manager = empathy_smiley_manager_dup_singleton ();
g_signal_connect (theme, "load-finished",
@@ -1359,18 +1408,24 @@ empathy_adium_path_is_valid (const gchar *path)
ret = g_file_test (file, G_FILE_TEST_EXISTS);
g_free (file);
- if (ret == FALSE)
- return ret;
+ if (!ret)
+ return FALSE;
/* We ship a default Template.html as fallback if there is any problem
* with the one inside the theme. The only other required file is
- * Content.html for incoming messages (outgoing fallback to use
- * incoming). */
- file = g_build_filename (path, "Contents", "Resources", "Incoming",
- "Content.html", NULL);
+ * Content.html OR Incoming/Content.html*/
+ file = g_build_filename (path, "Contents", "Resources", "Content.html",
+ NULL);
ret = g_file_test (file, G_FILE_TEST_EXISTS);
g_free (file);
+ if (!ret) {
+ file = g_build_filename (path, "Contents", "Resources", "Incoming",
+ "Content.html", NULL);
+ ret = g_file_test (file, G_FILE_TEST_EXISTS);
+ g_free (file);
+ }
+
return ret;
}
@@ -1400,6 +1455,108 @@ empathy_adium_info_new (const gchar *path)
return info;
}
+static guint
+adium_info_get_version (GHashTable *info)
+{
+ return tp_asv_get_int32 (info, "MessageViewVersion", NULL);
+}
+
+static const gchar *
+adium_info_get_no_variant_name (GHashTable *info)
+{
+ const gchar *name = tp_asv_get_string (info, "DisplayNameForNoVariant");
+ return name ? name : _("Normal");
+}
+
+static const gchar *
+adium_info_get_default_or_first_variant (GHashTable *info)
+{
+ const gchar *name;
+ GPtrArray *variants;
+
+ name = empathy_adium_info_get_default_variant (info);
+ if (name != NULL) {
+ return name;
+ }
+
+ variants = empathy_adium_info_get_available_variants (info);
+ g_assert (variants->len > 0);
+ return g_ptr_array_index (variants, 0);
+}
+
+static gchar *
+adium_info_dup_path_for_variant (GHashTable *info,
+ const gchar *variant)
+{
+ guint version = adium_info_get_version (info);
+ const gchar *no_variant = adium_info_get_no_variant_name (info);
+
+ if (version <= 2 && !tp_strdiff (variant, no_variant)) {
+ return g_strdup ("main.css");
+ }
+
+ return g_strdup_printf ("Variants/%s.css", variant);
+
+}
+
+const gchar *
+empathy_adium_info_get_default_variant (GHashTable *info)
+{
+ if (adium_info_get_version (info) <= 2) {
+ return adium_info_get_no_variant_name (info);
+ }
+
+ return tp_asv_get_string (info, "DefaultVariant");
+}
+
+GPtrArray *
+empathy_adium_info_get_available_variants (GHashTable *info)
+{
+ GPtrArray *variants;
+ const gchar *path;
+ gchar *dirpath;
+ GDir *dir;
+
+ variants = tp_asv_get_boxed (info, "AvailableVariants", G_TYPE_PTR_ARRAY);
+ if (variants != NULL) {
+ return variants;
+ }
+
+ variants = g_ptr_array_new_with_free_func (g_free);
+ tp_asv_take_boxed (info, g_strdup ("AvailableVariants"),
+ G_TYPE_PTR_ARRAY, variants);
+
+ path = tp_asv_get_string (info, "path");
+ dirpath = g_build_filename (path, "Contents", "Resources", "Variants", NULL);
+ dir = g_dir_open (dirpath, 0, NULL);
+ if (dir != NULL) {
+ const gchar *name;
+
+ for (name = g_dir_read_name (dir);
+ name != NULL;
+ name = g_dir_read_name (dir)) {
+ gchar *display_name;
+
+ if (!g_str_has_suffix (name, ".css")) {
+ continue;
+ }
+
+ display_name = g_strdup (name);
+ strstr (display_name, ".css")[0] = '\0';
+ g_ptr_array_add (variants, display_name);
+ }
+ g_dir_close (dir);
+ }
+ g_free (dirpath);
+
+ if (adium_info_get_version (info) <= 2) {
+ g_ptr_array_add (variants,
+ g_strdup (adium_info_get_no_variant_name (info)));
+ }
+
+ return variants;
+}
+
GType
empathy_adium_data_get_type (void)
{
@@ -1419,16 +1576,10 @@ EmpathyAdiumData *
empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
{
EmpathyAdiumData *data;
- gchar *file;
gchar *template_html = NULL;
- gsize template_len;
gchar *footer_html = NULL;
- gsize footer_len;
- GString *string;
- gchar **strv = NULL;
- gchar *css_path;
- guint len = 0;
- guint i = 0;
+ gchar *variant_path;
+ gchar *tmp;
g_return_val_if_fail (empathy_adium_path_is_valid (path), NULL);
@@ -1438,121 +1589,121 @@ empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
data->basedir = g_strconcat (path, G_DIR_SEPARATOR_S "Contents"
G_DIR_SEPARATOR_S "Resources" G_DIR_SEPARATOR_S, NULL);
data->info = g_hash_table_ref (info);
+ data->version = adium_info_get_version (info);
+ data->strings_to_free = g_ptr_array_new_with_free_func (g_free);
+
+ DEBUG ("Loading theme at %s", path);
+
+#define LOAD(path, var) \
+ tmp = g_build_filename (data->basedir, path, NULL); \
+ g_file_get_contents (tmp, &var, NULL, NULL); \
+ g_free (tmp); \
+
+#define LOAD_CONST(path, var) \
+ { \
+ gchar *content; \
+ LOAD (path, content); \
+ if (content != NULL) { \
+ g_ptr_array_add (data->strings_to_free, content); \
+ } \
+ var = content; \
+ }
/* Load html files */
- file = g_build_filename (data->basedir, "Incoming", "Content.html", NULL);
- g_file_get_contents (file, &data->in_content_html, &data->in_content_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Incoming", "NextContent.html", NULL);
- g_file_get_contents (file, &data->in_nextcontent_html, &data->in_nextcontent_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Incoming", "Context.html", NULL);
- g_file_get_contents (file, &data->in_context_html, &data->in_context_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Incoming", "NextContext.html", NULL);
- g_file_get_contents (file, &data->in_nextcontext_html, &data->in_nextcontext_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Outgoing", "Content.html", NULL);
- g_file_get_contents (file, &data->out_content_html, &data->out_content_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Outgoing", "NextContent.html", NULL);
- g_file_get_contents (file, &data->out_nextcontent_html, &data->out_nextcontent_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Outgoing", "Context.html", NULL);
- g_file_get_contents (file, &data->out_context_html, &data->out_context_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Outgoing", "NextContext.html", NULL);
- g_file_get_contents (file, &data->out_nextcontext_html, &data->out_nextcontext_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Status.html", NULL);
- g_file_get_contents (file, &data->status_html, &data->status_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Footer.html", NULL);
- g_file_get_contents (file, &footer_html, &footer_len, NULL);
- g_free (file);
-
- file = g_build_filename (data->basedir, "Incoming", "buddy_icon.png", NULL);
- if (g_file_test (file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
- data->default_incoming_avatar_filename = file;
- } else {
- g_free (file);
+ LOAD_CONST ("Content.html", data->content_html);
+ LOAD_CONST ("Incoming/Content.html", data->in_content_html);
+ LOAD_CONST ("Incoming/NextContent.html", data->in_nextcontent_html);
+ LOAD_CONST ("Incoming/Context.html", data->in_context_html);
+ LOAD_CONST ("Incoming/NextContext.html", data->in_nextcontext_html);
+ LOAD_CONST ("Outgoing/Content.html", data->out_content_html);
+ LOAD_CONST ("Outgoing/NextContent.html", data->out_nextcontent_html);
+ LOAD_CONST ("Outgoing/Context.html", data->out_context_html);
+ LOAD_CONST ("Outgoing/NextContext.html", data->out_nextcontext_html);
+ LOAD_CONST ("Status.html", data->status_html);
+ LOAD ("Template.html", template_html);
+ LOAD ("Footer.html", footer_html);
+
+#undef LOAD_CONST
+#undef LOAD
+
+ /* HTML fallbacks: If we have at least content OR in_content, then
+ * everything else gets a fallback */
+
+#define FALLBACK(html, fallback) \
+ if (html == NULL) { \
+ html = fallback; \
}
- file = g_build_filename (data->basedir, "Outgoing", "buddy_icon.png", NULL);
- if (g_file_test (file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
- data->default_outgoing_avatar_filename = file;
- } else {
- g_free (file);
+ /* in_nextcontent -> in_content -> content */
+ FALLBACK (data->in_content_html, data->content_html);
+ FALLBACK (data->in_nextcontent_html, data->in_content_html);
+
+ /* context -> content */
+ FALLBACK (data->in_context_html, data->in_content_html);
+ FALLBACK (data->in_nextcontext_html, data->in_nextcontent_html);
+ FALLBACK (data->out_context_html, data->out_content_html);
+ FALLBACK (data->out_nextcontext_html, data->out_nextcontent_html);
+
+ /* out -> in */
+ FALLBACK (data->out_content_html, data->in_content_html);
+ FALLBACK (data->out_nextcontent_html, data->in_nextcontent_html);
+ FALLBACK (data->out_context_html, data->in_context_html);
+ FALLBACK (data->out_nextcontext_html, data->in_nextcontext_html);
+
+ /* status -> in_content */
+ FALLBACK (data->status_html, data->in_content_html);
+
+#undef FALLBACK
+
+ /* template -> empathy's template */
+ data->custom_template = (template_html != NULL);
+ if (template_html == NULL) {
+ tmp = empathy_file_lookup ("Template.html", "data");
+ g_file_get_contents (tmp, &template_html, NULL, NULL);
+ g_free (tmp);
}
- css_path = g_build_filename (data->basedir, "main.css", NULL);
-
- /* There is 2 formats for Template.html: The old one has 4 parameters,
- * the new one has 5 parameters. */
- file = g_build_filename (data->basedir, "Template.html", NULL);
- if (g_file_get_contents (file, &template_html, &template_len, NULL)) {
- strv = g_strsplit (template_html, "%@", -1);
- len = g_strv_length (strv);
+ /* Default avatar */
+ tmp = g_build_filename (data->basedir, "Incoming", "buddy_icon.png", NULL);
+ if (g_file_test (tmp, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ data->default_incoming_avatar_filename = tmp;
+ } else {
+ g_free (tmp);
}
- g_free (file);
-
- if (len != 5 && len != 6) {
- /* Either the theme has no template or it don't have the good
- * number of parameters. Fallback to use our own template. */
- g_free (template_html);
- g_strfreev (strv);
-
- file = empathy_file_lookup ("Template.html", "data");
- g_file_get_contents (file, &template_html, &template_len, NULL);
- g_free (file);
- strv = g_strsplit (template_html, "%@", -1);
- len = g_strv_length (strv);
+ tmp = g_build_filename (data->basedir, "Outgoing", "buddy_icon.png", NULL);
+ if (g_file_test (tmp, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ data->default_outgoing_avatar_filename = tmp;
+ } else {
+ g_free (tmp);
}
- /* Replace %@ with the needed information in the template html. */
- string = g_string_sized_new (template_len);
- g_string_append (string, strv[i++]);
- g_string_append (string, data->basedir);
- g_string_append (string, strv[i++]);
- if (len == 6) {
- const gchar *variant;
-
- /* We include main.css by default */
- g_string_append_printf (string, "@import url(\"%s\");", css_path);
- g_string_append (string, strv[i++]);
- variant = tp_asv_get_string (data->info, "DefaultVariant");
- if (variant) {
- g_string_append (string, "Variants/");
- g_string_append (string, variant);
- g_string_append (string, ".css");
- }
+ variant_path = adium_info_dup_path_for_variant (info,
+ adium_info_get_default_or_first_variant (info));
+
+ /* Old custom templates had only 4 parameters.
+ * New templates have 5 parameters */
+ if (data->version <= 2 && data->custom_template) {
+ tmp = string_with_format (template_html,
+ data->basedir,
+ variant_path,
+ "", /* The header */
+ footer_html ? footer_html : "",
+ NULL);
} else {
- /* FIXME: We should set main.css OR the variant css */
- g_string_append (string, css_path);
+ tmp = string_with_format (template_html,
+ data->basedir,
+ data->version <= 2 ? "" : "@import url( \"main.css\" );",
+ variant_path,
+ "", /* The header */
+ footer_html ? footer_html : "",
+ NULL);
}
- g_string_append (string, strv[i++]);
- g_string_append (string, ""); /* We don't want header */
- g_string_append (string, strv[i++]);
- /* FIXME: We should replace adium %macros% in footer */
- if (footer_html) {
- g_string_append (string, footer_html);
- }
- g_string_append (string, strv[i++]);
- data->template_html = g_string_free (string, FALSE);
+ g_ptr_array_add (data->strings_to_free, tmp);
+ data->template_html = tmp;
- g_free (footer_html);
g_free (template_html);
- g_free (css_path);
- g_strfreev (strv);
+ g_free (footer_html);
+ g_free (variant_path);
return data;
}
@@ -1588,20 +1739,12 @@ empathy_adium_data_unref (EmpathyAdiumData *data)
if (g_atomic_int_dec_and_test (&data->ref_count)) {
g_free (data->path);
g_free (data->basedir);
- g_free (data->template_html);
- g_free (data->in_content_html);
- g_free (data->in_nextcontent_html);
- g_free (data->in_context_html);
- g_free (data->in_nextcontext_html);
- g_free (data->out_content_html);
- g_free (data->out_nextcontent_html);
- g_free (data->out_context_html);
- g_free (data->out_nextcontext_html);
g_free (data->default_avatar_filename);
g_free (data->default_incoming_avatar_filename);
g_free (data->default_outgoing_avatar_filename);
- g_free (data->status_html);
g_hash_table_unref (data->info);
+ g_ptr_array_unref (data->strings_to_free);
+
g_slice_free (EmpathyAdiumData, data);
}
}