]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-message.c
Merge commit 'jtellier/video-call-button-sensitivity'
[empathy.git] / libempathy / empathy-message.c
index 5c2028bd01975432c70fa60e89e21a60b042f717..a8fe6084cfe1495d54b8a5128f8671e08cad7b29 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2004-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
+ * Copyright (C) 2007-2008 Collabora Ltd.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -15,8 +15,8 @@
  *
  * You should have received a copy of the GNU General Public
  * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
  *
  * Authors: Mikael Hallendal <micke@imendio.com>
  *          Xavier Claessens <xclaesse@gmail.com>
 
 #include <string.h>
 
+#include <telepathy-glib/util.h>
+
 #include "empathy-message.h"
+#include "empathy-utils.h"
 #include "empathy-enum-types.h"
 
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv))
-
-typedef struct _EmpathyMessagePriv EmpathyMessagePriv;
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyMessage)
+typedef struct {
+       TpChannelTextMessageType  type;
+       EmpathyContact           *sender;
+       EmpathyContact           *receiver;
+       gchar                    *body;
+       time_t                    timestamp;
+       gboolean                  is_backlog;
+       guint                     id;
+} EmpathyMessagePriv;
 
-struct _EmpathyMessagePriv {
-       EmpathyMessageType  type;
-       EmpathyContact     *sender;
-       EmpathyContact     *receiver;
-       gchar              *body;
-       time_t              timestamp;
-};
-
-static void empathy_message_class_init (EmpathyMessageClass *class);
-static void empathy_message_init       (EmpathyMessage      *message);
 static void empathy_message_finalize   (GObject            *object);
 static void message_get_property      (GObject            *object,
                                       guint               param_id,
@@ -53,6 +53,8 @@ static void message_set_property      (GObject            *object,
                                       const GValue       *value,
                                       GParamSpec         *pspec);
 
+G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
+
 enum {
        PROP_0,
        PROP_TYPE,
@@ -60,55 +62,27 @@ enum {
        PROP_RECEIVER,
        PROP_BODY,
        PROP_TIMESTAMP,
+       PROP_IS_BACKLOG,
 };
 
-static gpointer parent_class = NULL;
-
-GType
-empathy_message_get_gtype (void)
-{
-       static GType type = 0;
-
-       if (!type) {
-               static const GTypeInfo info = {
-                       sizeof (EmpathyMessageClass),
-                       NULL, /* base_init */
-                       NULL, /* base_finalize */
-                       (GClassInitFunc) empathy_message_class_init,
-                       NULL, /* class_finalize */
-                       NULL, /* class_data */
-                       sizeof (EmpathyMessage),
-                       0,    /* n_preallocs */
-                       (GInstanceInitFunc) empathy_message_init
-               };
-
-               type = g_type_register_static (G_TYPE_OBJECT,
-                                              "EmpathyMessage",
-                                              &info, 0);
-       }
-
-       return type;
-}
-
 static void
 empathy_message_class_init (EmpathyMessageClass *class)
 {
        GObjectClass *object_class;
 
        object_class = G_OBJECT_CLASS (class);
-       parent_class = g_type_class_peek_parent (class);
-
        object_class->finalize     = empathy_message_finalize;
        object_class->get_property = message_get_property;
        object_class->set_property = message_set_property;
 
        g_object_class_install_property (object_class,
                                         PROP_TYPE,
-                                        g_param_spec_enum ("type",
+                                        g_param_spec_uint ("type",
                                                            "Message Type",
                                                            "The type of message",
-                                                           EMPATHY_TYPE_MESSAGE_TYPE,
-                                                           EMPATHY_MESSAGE_TYPE_NORMAL,
+                                                           TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+                                                           TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
+                                                           TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
                                                            G_PARAM_READWRITE));
        g_object_class_install_property (object_class,
                                         PROP_SENDER,
@@ -140,6 +114,13 @@ empathy_message_class_init (EmpathyMessageClass *class)
                                                            G_MAXLONG,
                                                            -1,
                                                            G_PARAM_READWRITE));
+       g_object_class_install_property (object_class,
+                                        PROP_IS_BACKLOG,
+                                        g_param_spec_boolean ("is-backlog",
+                                                              "History message",
+                                                              "If the message belongs to history",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
 
 
        g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
@@ -149,10 +130,10 @@ empathy_message_class_init (EmpathyMessageClass *class)
 static void
 empathy_message_init (EmpathyMessage *message)
 {
-       EmpathyMessagePriv *priv;
-
-       priv = GET_PRIV (message);
+       EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
+               EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
 
+       message->priv = priv;
        priv->timestamp = empathy_time_get_current ();
 }
 
@@ -172,7 +153,7 @@ empathy_message_finalize (GObject *object)
 
        g_free (priv->body);
 
-       (G_OBJECT_CLASS (parent_class)->finalize) (object);
+       G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
 }
 
 static void
@@ -187,7 +168,7 @@ message_get_property (GObject    *object,
 
        switch (param_id) {
        case PROP_TYPE:
-               g_value_set_enum (value, priv->type);
+               g_value_set_uint (value, priv->type);
                break;
        case PROP_SENDER:
                g_value_set_object (value, priv->sender);
@@ -216,8 +197,8 @@ message_set_property (GObject      *object,
 
        switch (param_id) {
        case PROP_TYPE:
-               empathy_message_set_type (EMPATHY_MESSAGE (object),
-                                         g_value_get_enum (value));
+               empathy_message_set_tptype (EMPATHY_MESSAGE (object),
+                                           g_value_get_uint (value));
                break;
        case PROP_SENDER:
                empathy_message_set_sender (EMPATHY_MESSAGE (object),
@@ -245,13 +226,13 @@ empathy_message_new (const gchar *body)
                             NULL);
 }
 
-EmpathyMessageType
-empathy_message_get_type (EmpathyMessage *message)
+TpChannelTextMessageType
+empathy_message_get_tptype (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
        g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
-                             EMPATHY_MESSAGE_TYPE_NORMAL);
+                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
 
        priv = GET_PRIV (message);
 
@@ -259,8 +240,8 @@ empathy_message_get_type (EmpathyMessage *message)
 }
 
 void
-empathy_message_set_type (EmpathyMessage     *message,
-                        EmpathyMessageType  type)
+empathy_message_set_tptype (EmpathyMessage           *message,
+                           TpChannelTextMessageType  type)
 {
        EmpathyMessagePriv *priv;
 
@@ -353,21 +334,19 @@ empathy_message_get_body (EmpathyMessage *message)
 
 void
 empathy_message_set_body (EmpathyMessage *message,
-                        const gchar   *body)
+                         const gchar    *body)
 {
-       EmpathyMessagePriv *priv;
-       EmpathyMessageType  type;
+       EmpathyMessagePriv       *priv = GET_PRIV (message);
+       TpChannelTextMessageType  type;
 
        g_return_if_fail (EMPATHY_IS_MESSAGE (message));
 
-       priv = GET_PRIV (message);
-
        g_free (priv->body);
        priv->body = NULL;
 
-       type = EMPATHY_MESSAGE_TYPE_NORMAL;
+       type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
        if (g_str_has_prefix (body, "/me")) {
-               type = EMPATHY_MESSAGE_TYPE_ACTION;
+               type = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
                body += 4;
        }
        else if (g_str_has_prefix (body, "/say")) {
@@ -379,7 +358,7 @@ empathy_message_set_body (EmpathyMessage *message,
        }
 
        if (type != priv->type) {
-               empathy_message_set_type (message, type);
+               empathy_message_set_tptype (message, type);
        }
 
        g_object_notify (G_OBJECT (message), "body");
@@ -417,37 +396,161 @@ empathy_message_set_timestamp (EmpathyMessage *message,
        g_object_notify (G_OBJECT (message), "timestamp");
 }
 
-EmpathyMessageType
+gboolean
+empathy_message_is_backlog (EmpathyMessage *message)
+{
+       EmpathyMessagePriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
+
+       priv = GET_PRIV (message);
+
+       return priv->is_backlog;
+}
+
+void
+empathy_message_set_is_backlog (EmpathyMessage *message,
+                               gboolean is_backlog)
+{
+       EmpathyMessagePriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_MESSAGE (message));
+
+       priv = GET_PRIV (message);
+
+       priv->is_backlog = is_backlog;
+
+       g_object_notify (G_OBJECT (message), "is-backlog");
+}
+
+#define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
+gboolean
+empathy_message_should_highlight (EmpathyMessage *message)
+{
+       EmpathyContact *contact;
+       const gchar   *msg, *to;
+       gchar         *cf_msg, *cf_to;
+       gchar         *ch;
+       gboolean       ret_val;
+
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
+
+       ret_val = FALSE;
+
+       msg = empathy_message_get_body (message);
+       if (!msg) {
+               return FALSE;
+       }
+
+       contact = empathy_message_get_receiver (message);
+       if (!contact || !empathy_contact_is_user (contact)) {
+               return FALSE;
+       }
+
+       to = empathy_contact_get_name (contact);
+       if (!to) {
+               return FALSE;
+       }
+
+       cf_msg = g_utf8_casefold (msg, -1);
+       cf_to = g_utf8_casefold (to, -1);
+
+       ch = strstr (cf_msg, cf_to);
+       if (ch == NULL) {
+               goto finished;
+       }
+       if (ch != cf_msg) {
+               /* Not first in the message */
+               if (!IS_SEPARATOR (*(ch - 1))) {
+                       goto finished;
+               }
+       }
+
+       ch = ch + strlen (cf_to);
+       if (ch >= cf_msg + strlen (cf_msg)) {
+               ret_val = TRUE;
+               goto finished;
+       }
+
+       if (IS_SEPARATOR (*ch)) {
+               ret_val = TRUE;
+               goto finished;
+       }
+
+finished:
+       g_free (cf_msg);
+       g_free (cf_to);
+
+       return ret_val;
+}
+
+TpChannelTextMessageType
 empathy_message_type_from_str (const gchar *type_str)
 {
        if (strcmp (type_str, "normal") == 0) {
-               return EMPATHY_MESSAGE_TYPE_NORMAL;
+               return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
        }
        if (strcmp (type_str, "action") == 0) {
-               return EMPATHY_MESSAGE_TYPE_ACTION;
+               return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
        }
        else if (strcmp (type_str, "notice") == 0) {
-               return EMPATHY_MESSAGE_TYPE_NOTICE;
+               return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
        }
        else if (strcmp (type_str, "auto-reply") == 0) {
-               return EMPATHY_MESSAGE_TYPE_AUTO_REPLY;
+               return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
        }
 
-       return EMPATHY_MESSAGE_TYPE_NORMAL;
+       return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
 }
 
 const gchar *
-empathy_message_type_to_str (EmpathyMessageType type)
+empathy_message_type_to_str (TpChannelTextMessageType type)
 {
        switch (type) {
-       case EMPATHY_MESSAGE_TYPE_ACTION:
+       case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
                return "action";
-       case EMPATHY_MESSAGE_TYPE_NOTICE:
+       case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
                return "notice";
-       case EMPATHY_MESSAGE_TYPE_AUTO_REPLY:
+       case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
                return "auto-reply";
        default:
                return "normal";
        }
 }
 
+guint
+empathy_message_get_id (EmpathyMessage *message)
+{
+       EmpathyMessagePriv *priv = GET_PRIV (message);
+
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
+
+       return priv->id;
+}
+
+void
+empathy_message_set_id (EmpathyMessage *message, guint id)
+{
+       EmpathyMessagePriv *priv = GET_PRIV (message);
+
+       priv->id = id;
+}
+
+gboolean
+empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
+{
+       EmpathyMessagePriv *priv1;
+       EmpathyMessagePriv *priv2;
+
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
+
+       priv1 = GET_PRIV (message1);
+       priv2 = GET_PRIV (message2);
+
+       if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {
+               return TRUE;
+       }
+
+       return FALSE;
+}