1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2004-2007 Imendio AB
4 * Copyright (C) 2007-2008 Collabora Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 * Authors: Mikael Hallendal <micke@imendio.com>
22 * Xavier Claessens <xclaesse@gmail.com>
29 #include <telepathy-glib/util.h>
31 #include "empathy-message.h"
32 #include "empathy-utils.h"
33 #include "empathy-enum-types.h"
35 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyMessage)
37 TpChannelTextMessageType type;
38 EmpathyContact *sender;
39 EmpathyContact *receiver;
45 TpChannelTextMessageFlags flags;
48 static void empathy_message_finalize (GObject *object);
49 static void message_get_property (GObject *object,
53 static void message_set_property (GObject *object,
58 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
73 empathy_message_class_init (EmpathyMessageClass *class)
75 GObjectClass *object_class;
77 object_class = G_OBJECT_CLASS (class);
78 object_class->finalize = empathy_message_finalize;
79 object_class->get_property = message_get_property;
80 object_class->set_property = message_set_property;
82 g_object_class_install_property (object_class,
84 g_param_spec_uint ("type",
86 "The type of message",
87 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
88 TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
89 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
91 g_object_class_install_property (object_class,
93 g_param_spec_object ("sender",
95 "The sender of the message",
98 g_object_class_install_property (object_class,
100 g_param_spec_object ("receiver",
102 "The receiver of the message",
103 EMPATHY_TYPE_CONTACT,
105 g_object_class_install_property (object_class,
107 g_param_spec_string ("body",
109 "The content of the message",
112 g_object_class_install_property (object_class,
114 g_param_spec_long ("timestamp",
121 g_object_class_install_property (object_class,
123 g_param_spec_boolean ("is-backlog",
125 "If the message belongs to history",
130 g_object_class_install_property (object_class,
132 g_param_spec_boolean ("incoming",
134 "If this is an incoming (as opposed to sent) message",
136 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
138 g_object_class_install_property (object_class,
140 g_param_spec_uint ("flags",
142 "The TpChannelTextMessageFlags of this message",
144 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
146 g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
151 empathy_message_init (EmpathyMessage *message)
153 EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
154 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
156 message->priv = priv;
157 priv->timestamp = empathy_time_get_current ();
161 empathy_message_finalize (GObject *object)
163 EmpathyMessagePriv *priv;
165 priv = GET_PRIV (object);
168 g_object_unref (priv->sender);
170 if (priv->receiver) {
171 g_object_unref (priv->receiver);
176 G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
180 message_get_property (GObject *object,
185 EmpathyMessagePriv *priv;
187 priv = GET_PRIV (object);
191 g_value_set_uint (value, priv->type);
194 g_value_set_object (value, priv->sender);
197 g_value_set_object (value, priv->receiver);
200 g_value_set_string (value, priv->body);
203 g_value_set_boolean (value, priv->incoming);
206 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
212 message_set_property (GObject *object,
217 EmpathyMessagePriv *priv;
219 priv = GET_PRIV (object);
223 empathy_message_set_tptype (EMPATHY_MESSAGE (object),
224 g_value_get_uint (value));
227 empathy_message_set_sender (EMPATHY_MESSAGE (object),
228 EMPATHY_CONTACT (g_value_get_object (value)));
231 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
232 EMPATHY_CONTACT (g_value_get_object (value)));
235 empathy_message_set_body (EMPATHY_MESSAGE (object),
236 g_value_get_string (value));
239 priv->incoming = g_value_get_boolean (value);
242 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
248 empathy_message_new (const gchar *body)
250 return g_object_new (EMPATHY_TYPE_MESSAGE,
255 TpChannelTextMessageType
256 empathy_message_get_tptype (EmpathyMessage *message)
258 EmpathyMessagePriv *priv;
260 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
261 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
263 priv = GET_PRIV (message);
269 empathy_message_set_tptype (EmpathyMessage *message,
270 TpChannelTextMessageType type)
272 EmpathyMessagePriv *priv;
274 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
276 priv = GET_PRIV (message);
280 g_object_notify (G_OBJECT (message), "type");
284 empathy_message_get_sender (EmpathyMessage *message)
286 EmpathyMessagePriv *priv;
288 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
290 priv = GET_PRIV (message);
296 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
298 EmpathyMessagePriv *priv;
299 EmpathyContact *old_sender;
301 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
302 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
304 priv = GET_PRIV (message);
306 old_sender = priv->sender;
307 priv->sender = g_object_ref (contact);
310 g_object_unref (old_sender);
313 g_object_notify (G_OBJECT (message), "sender");
317 empathy_message_get_receiver (EmpathyMessage *message)
319 EmpathyMessagePriv *priv;
321 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
323 priv = GET_PRIV (message);
325 return priv->receiver;
329 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
331 EmpathyMessagePriv *priv;
332 EmpathyContact *old_receiver;
334 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
335 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
337 priv = GET_PRIV (message);
339 old_receiver = priv->receiver;
340 priv->receiver = g_object_ref (contact);
343 g_object_unref (old_receiver);
346 g_object_notify (G_OBJECT (message), "receiver");
350 empathy_message_get_body (EmpathyMessage *message)
352 EmpathyMessagePriv *priv;
354 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
356 priv = GET_PRIV (message);
362 empathy_message_set_body (EmpathyMessage *message,
365 EmpathyMessagePriv *priv = GET_PRIV (message);
367 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
372 priv->body = g_strdup (body);
377 g_object_notify (G_OBJECT (message), "body");
381 empathy_message_get_timestamp (EmpathyMessage *message)
383 EmpathyMessagePriv *priv;
385 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
387 priv = GET_PRIV (message);
389 return priv->timestamp;
393 empathy_message_set_timestamp (EmpathyMessage *message,
396 EmpathyMessagePriv *priv;
398 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
399 g_return_if_fail (timestamp >= -1);
401 priv = GET_PRIV (message);
403 if (timestamp <= 0) {
404 priv->timestamp = empathy_time_get_current ();
406 priv->timestamp = timestamp;
409 g_object_notify (G_OBJECT (message), "timestamp");
413 empathy_message_is_backlog (EmpathyMessage *message)
415 EmpathyMessagePriv *priv;
417 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
419 priv = GET_PRIV (message);
421 return priv->is_backlog;
425 empathy_message_set_is_backlog (EmpathyMessage *message,
428 EmpathyMessagePriv *priv;
430 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
432 priv = GET_PRIV (message);
434 priv->is_backlog = is_backlog;
436 g_object_notify (G_OBJECT (message), "is-backlog");
439 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
441 empathy_message_should_highlight (EmpathyMessage *message)
443 EmpathyContact *contact;
444 const gchar *msg, *to;
445 gchar *cf_msg, *cf_to;
448 TpChannelTextMessageFlags flags;
450 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
454 msg = empathy_message_get_body (message);
459 contact = empathy_message_get_receiver (message);
460 if (!contact || !empathy_contact_is_user (contact)) {
464 to = empathy_contact_get_name (contact);
469 flags = empathy_message_get_flags (message);
470 if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK) {
471 /* FIXME: Ideally we shouldn't highlight scrollback messages only if they
472 * have already been received by the user before (and so are in the logs) */
476 cf_msg = g_utf8_casefold (msg, -1);
477 cf_to = g_utf8_casefold (to, -1);
479 ch = strstr (cf_msg, cf_to);
484 /* Not first in the message */
485 if (!IS_SEPARATOR (*(ch - 1))) {
490 ch = ch + strlen (cf_to);
491 if (ch >= cf_msg + strlen (cf_msg)) {
496 if (IS_SEPARATOR (*ch)) {
508 TpChannelTextMessageType
509 empathy_message_type_from_str (const gchar *type_str)
511 if (strcmp (type_str, "normal") == 0) {
512 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
514 if (strcmp (type_str, "action") == 0) {
515 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
517 else if (strcmp (type_str, "notice") == 0) {
518 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
520 else if (strcmp (type_str, "auto-reply") == 0) {
521 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
524 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
528 empathy_message_type_to_str (TpChannelTextMessageType type)
531 case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
533 case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
535 case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
543 empathy_message_get_id (EmpathyMessage *message)
545 EmpathyMessagePriv *priv = GET_PRIV (message);
547 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
553 empathy_message_set_id (EmpathyMessage *message, guint id)
555 EmpathyMessagePriv *priv = GET_PRIV (message);
561 empathy_message_set_incoming (EmpathyMessage *message, gboolean incoming)
563 EmpathyMessagePriv *priv;
565 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
567 priv = GET_PRIV (message);
569 priv->incoming = incoming;
571 g_object_notify (G_OBJECT (message), "incoming");
575 empathy_message_is_incoming (EmpathyMessage *message)
577 EmpathyMessagePriv *priv = GET_PRIV (message);
579 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
581 return priv->incoming;
585 empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
587 EmpathyMessagePriv *priv1;
588 EmpathyMessagePriv *priv2;
590 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
591 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
593 priv1 = GET_PRIV (message1);
594 priv2 = GET_PRIV (message2);
596 if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {
603 TpChannelTextMessageFlags
604 empathy_message_get_flags (EmpathyMessage *self)
606 EmpathyMessagePriv *priv = GET_PRIV (self);
608 g_return_val_if_fail (EMPATHY_IS_MESSAGE (self), 0);
614 empathy_message_set_flags (EmpathyMessage *self,
615 TpChannelTextMessageFlags flags)
617 EmpathyMessagePriv *priv;
619 g_return_if_fail (EMPATHY_IS_MESSAGE (self));
621 priv = GET_PRIV (self);
625 g_object_notify (G_OBJECT (self), "flags");