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;
46 static void empathy_message_finalize (GObject *object);
47 static void message_get_property (GObject *object,
51 static void message_set_property (GObject *object,
56 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
69 empathy_message_class_init (EmpathyMessageClass *class)
71 GObjectClass *object_class;
73 object_class = G_OBJECT_CLASS (class);
74 object_class->finalize = empathy_message_finalize;
75 object_class->get_property = message_get_property;
76 object_class->set_property = message_set_property;
78 g_object_class_install_property (object_class,
80 g_param_spec_uint ("type",
82 "The type of message",
83 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
84 TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
85 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
87 g_object_class_install_property (object_class,
89 g_param_spec_object ("sender",
91 "The sender of the message",
94 g_object_class_install_property (object_class,
96 g_param_spec_object ("receiver",
98 "The receiver of the message",
101 g_object_class_install_property (object_class,
103 g_param_spec_string ("body",
105 "The content of the message",
108 g_object_class_install_property (object_class,
110 g_param_spec_long ("timestamp",
117 g_object_class_install_property (object_class,
119 g_param_spec_boolean ("is-backlog",
121 "If the message belongs to history",
126 g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
131 empathy_message_init (EmpathyMessage *message)
133 EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
134 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
136 message->priv = priv;
137 priv->timestamp = empathy_time_get_current ();
141 empathy_message_finalize (GObject *object)
143 EmpathyMessagePriv *priv;
145 priv = GET_PRIV (object);
148 g_object_unref (priv->sender);
150 if (priv->receiver) {
151 g_object_unref (priv->receiver);
156 G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
160 message_get_property (GObject *object,
165 EmpathyMessagePriv *priv;
167 priv = GET_PRIV (object);
171 g_value_set_uint (value, priv->type);
174 g_value_set_object (value, priv->sender);
177 g_value_set_object (value, priv->receiver);
180 g_value_set_string (value, priv->body);
183 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
189 message_set_property (GObject *object,
194 EmpathyMessagePriv *priv;
196 priv = GET_PRIV (object);
200 empathy_message_set_tptype (EMPATHY_MESSAGE (object),
201 g_value_get_uint (value));
204 empathy_message_set_sender (EMPATHY_MESSAGE (object),
205 EMPATHY_CONTACT (g_value_get_object (value)));
208 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
209 EMPATHY_CONTACT (g_value_get_object (value)));
212 empathy_message_set_body (EMPATHY_MESSAGE (object),
213 g_value_get_string (value));
216 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
222 has_prefix_case (const gchar *s,
225 return g_ascii_strncasecmp (s, prefix, strlen (prefix)) == 0;
229 * Constructs an EmpathyMessage based on user input, which may include "/me"
232 * Returns: an #EmpathyMessage if @message could be parsed, or %NULL if
233 * @message was an unknown command.
236 empathy_message_new_from_entry (const gchar *message)
238 TpChannelTextMessageType t = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
240 g_return_val_if_fail (message != NULL, NULL);
242 if (message[0] == '/') {
243 if (g_ascii_strcasecmp (message, "/me") == 0) {
245 t = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
246 } else if (has_prefix_case (message, "/me ")) {
247 message += strlen ("/me ");
248 t = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
249 } else if (has_prefix_case (message, "/say ")) {
250 message += strlen ("/say ");
252 /* Also allow messages with two slashes before the
253 * first space, so it is possible to send a /unix/path.
254 * This heuristic is kind of crap.
256 gboolean second_slash = FALSE;
257 const gchar *m = message + 1;
259 while (!second_slash && *m != '\0' && *m != ' ') {
271 return g_object_new (EMPATHY_TYPE_MESSAGE,
278 empathy_message_new (const gchar *body)
280 return g_object_new (EMPATHY_TYPE_MESSAGE,
285 TpChannelTextMessageType
286 empathy_message_get_tptype (EmpathyMessage *message)
288 EmpathyMessagePriv *priv;
290 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
291 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
293 priv = GET_PRIV (message);
299 empathy_message_set_tptype (EmpathyMessage *message,
300 TpChannelTextMessageType type)
302 EmpathyMessagePriv *priv;
304 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
306 priv = GET_PRIV (message);
310 g_object_notify (G_OBJECT (message), "type");
314 empathy_message_get_sender (EmpathyMessage *message)
316 EmpathyMessagePriv *priv;
318 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
320 priv = GET_PRIV (message);
326 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
328 EmpathyMessagePriv *priv;
329 EmpathyContact *old_sender;
331 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
332 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
334 priv = GET_PRIV (message);
336 old_sender = priv->sender;
337 priv->sender = g_object_ref (contact);
340 g_object_unref (old_sender);
343 g_object_notify (G_OBJECT (message), "sender");
347 empathy_message_get_receiver (EmpathyMessage *message)
349 EmpathyMessagePriv *priv;
351 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
353 priv = GET_PRIV (message);
355 return priv->receiver;
359 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
361 EmpathyMessagePriv *priv;
362 EmpathyContact *old_receiver;
364 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
365 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
367 priv = GET_PRIV (message);
369 old_receiver = priv->receiver;
370 priv->receiver = g_object_ref (contact);
373 g_object_unref (old_receiver);
376 g_object_notify (G_OBJECT (message), "receiver");
380 empathy_message_get_body (EmpathyMessage *message)
382 EmpathyMessagePriv *priv;
384 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
386 priv = GET_PRIV (message);
392 empathy_message_set_body (EmpathyMessage *message,
395 EmpathyMessagePriv *priv = GET_PRIV (message);
397 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
402 priv->body = g_strdup (body);
407 g_object_notify (G_OBJECT (message), "body");
411 empathy_message_get_timestamp (EmpathyMessage *message)
413 EmpathyMessagePriv *priv;
415 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
417 priv = GET_PRIV (message);
419 return priv->timestamp;
423 empathy_message_set_timestamp (EmpathyMessage *message,
426 EmpathyMessagePriv *priv;
428 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
429 g_return_if_fail (timestamp >= -1);
431 priv = GET_PRIV (message);
433 if (timestamp <= 0) {
434 priv->timestamp = empathy_time_get_current ();
436 priv->timestamp = timestamp;
439 g_object_notify (G_OBJECT (message), "timestamp");
443 empathy_message_is_backlog (EmpathyMessage *message)
445 EmpathyMessagePriv *priv;
447 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
449 priv = GET_PRIV (message);
451 return priv->is_backlog;
455 empathy_message_set_is_backlog (EmpathyMessage *message,
458 EmpathyMessagePriv *priv;
460 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
462 priv = GET_PRIV (message);
464 priv->is_backlog = is_backlog;
466 g_object_notify (G_OBJECT (message), "is-backlog");
469 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
471 empathy_message_should_highlight (EmpathyMessage *message)
473 EmpathyContact *contact;
474 const gchar *msg, *to;
475 gchar *cf_msg, *cf_to;
479 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
483 msg = empathy_message_get_body (message);
488 contact = empathy_message_get_receiver (message);
489 if (!contact || !empathy_contact_is_user (contact)) {
493 to = empathy_contact_get_name (contact);
498 cf_msg = g_utf8_casefold (msg, -1);
499 cf_to = g_utf8_casefold (to, -1);
501 ch = strstr (cf_msg, cf_to);
506 /* Not first in the message */
507 if (!IS_SEPARATOR (*(ch - 1))) {
512 ch = ch + strlen (cf_to);
513 if (ch >= cf_msg + strlen (cf_msg)) {
518 if (IS_SEPARATOR (*ch)) {
530 TpChannelTextMessageType
531 empathy_message_type_from_str (const gchar *type_str)
533 if (strcmp (type_str, "normal") == 0) {
534 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
536 if (strcmp (type_str, "action") == 0) {
537 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
539 else if (strcmp (type_str, "notice") == 0) {
540 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
542 else if (strcmp (type_str, "auto-reply") == 0) {
543 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
546 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
550 empathy_message_type_to_str (TpChannelTextMessageType type)
553 case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
555 case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
557 case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
565 empathy_message_get_id (EmpathyMessage *message)
567 EmpathyMessagePriv *priv = GET_PRIV (message);
569 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
575 empathy_message_set_id (EmpathyMessage *message, guint id)
577 EmpathyMessagePriv *priv = GET_PRIV (message);
583 empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
585 EmpathyMessagePriv *priv1;
586 EmpathyMessagePriv *priv2;
588 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
589 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
591 priv1 = GET_PRIV (message1);
592 priv2 = GET_PRIV (message2);
594 if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {