Update python binding
[empathy.git] / libempathy / empathy-message.c
blob6d74c07225e14ede004eb8b18df8f94b21c6e12b
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * Authors: Mikael Hallendal <micke@imendio.com>
22 * Xavier Claessens <xclaesse@gmail.com>
25 #include "config.h"
27 #include <string.h>
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)
36 typedef struct {
37 TpChannelTextMessageType type;
38 EmpathyContact *sender;
39 EmpathyContact *receiver;
40 gchar *body;
41 time_t timestamp;
42 guint id;
43 } EmpathyMessagePriv;
45 static void empathy_message_finalize (GObject *object);
46 static void message_get_property (GObject *object,
47 guint param_id,
48 GValue *value,
49 GParamSpec *pspec);
50 static void message_set_property (GObject *object,
51 guint param_id,
52 const GValue *value,
53 GParamSpec *pspec);
55 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
57 enum {
58 PROP_0,
59 PROP_TYPE,
60 PROP_SENDER,
61 PROP_RECEIVER,
62 PROP_BODY,
63 PROP_TIMESTAMP,
66 static void
67 empathy_message_class_init (EmpathyMessageClass *class)
69 GObjectClass *object_class;
71 object_class = G_OBJECT_CLASS (class);
72 object_class->finalize = empathy_message_finalize;
73 object_class->get_property = message_get_property;
74 object_class->set_property = message_set_property;
76 g_object_class_install_property (object_class,
77 PROP_TYPE,
78 g_param_spec_uint ("type",
79 "Message Type",
80 "The type of message",
81 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
82 TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
83 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
84 G_PARAM_READWRITE));
85 g_object_class_install_property (object_class,
86 PROP_SENDER,
87 g_param_spec_object ("sender",
88 "Message Sender",
89 "The sender of the message",
90 EMPATHY_TYPE_CONTACT,
91 G_PARAM_READWRITE));
92 g_object_class_install_property (object_class,
93 PROP_RECEIVER,
94 g_param_spec_object ("receiver",
95 "Message Receiver",
96 "The receiver of the message",
97 EMPATHY_TYPE_CONTACT,
98 G_PARAM_READWRITE));
99 g_object_class_install_property (object_class,
100 PROP_BODY,
101 g_param_spec_string ("body",
102 "Message Body",
103 "The content of the message",
104 NULL,
105 G_PARAM_READWRITE));
106 g_object_class_install_property (object_class,
107 PROP_TIMESTAMP,
108 g_param_spec_long ("timestamp",
109 "timestamp",
110 "timestamp",
112 G_MAXLONG,
114 G_PARAM_READWRITE));
117 g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
121 static void
122 empathy_message_init (EmpathyMessage *message)
124 EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
125 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
127 message->priv = priv;
128 priv->timestamp = empathy_time_get_current ();
131 static void
132 empathy_message_finalize (GObject *object)
134 EmpathyMessagePriv *priv;
136 priv = GET_PRIV (object);
138 if (priv->sender) {
139 g_object_unref (priv->sender);
141 if (priv->receiver) {
142 g_object_unref (priv->receiver);
145 g_free (priv->body);
147 G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
150 static void
151 message_get_property (GObject *object,
152 guint param_id,
153 GValue *value,
154 GParamSpec *pspec)
156 EmpathyMessagePriv *priv;
158 priv = GET_PRIV (object);
160 switch (param_id) {
161 case PROP_TYPE:
162 g_value_set_uint (value, priv->type);
163 break;
164 case PROP_SENDER:
165 g_value_set_object (value, priv->sender);
166 break;
167 case PROP_RECEIVER:
168 g_value_set_object (value, priv->receiver);
169 break;
170 case PROP_BODY:
171 g_value_set_string (value, priv->body);
172 break;
173 default:
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
175 break;
179 static void
180 message_set_property (GObject *object,
181 guint param_id,
182 const GValue *value,
183 GParamSpec *pspec)
185 EmpathyMessagePriv *priv;
187 priv = GET_PRIV (object);
189 switch (param_id) {
190 case PROP_TYPE:
191 empathy_message_set_tptype (EMPATHY_MESSAGE (object),
192 g_value_get_uint (value));
193 break;
194 case PROP_SENDER:
195 empathy_message_set_sender (EMPATHY_MESSAGE (object),
196 EMPATHY_CONTACT (g_value_get_object (value)));
197 break;
198 case PROP_RECEIVER:
199 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
200 EMPATHY_CONTACT (g_value_get_object (value)));
201 break;
202 case PROP_BODY:
203 empathy_message_set_body (EMPATHY_MESSAGE (object),
204 g_value_get_string (value));
205 break;
206 default:
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
208 break;
212 EmpathyMessage *
213 empathy_message_new (const gchar *body)
215 return g_object_new (EMPATHY_TYPE_MESSAGE,
216 "body", body,
217 NULL);
220 TpChannelTextMessageType
221 empathy_message_get_tptype (EmpathyMessage *message)
223 EmpathyMessagePriv *priv;
225 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
226 TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
228 priv = GET_PRIV (message);
230 return priv->type;
233 void
234 empathy_message_set_tptype (EmpathyMessage *message,
235 TpChannelTextMessageType type)
237 EmpathyMessagePriv *priv;
239 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
241 priv = GET_PRIV (message);
243 priv->type = type;
245 g_object_notify (G_OBJECT (message), "type");
248 EmpathyContact *
249 empathy_message_get_sender (EmpathyMessage *message)
251 EmpathyMessagePriv *priv;
253 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
255 priv = GET_PRIV (message);
257 return priv->sender;
260 void
261 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
263 EmpathyMessagePriv *priv;
264 EmpathyContact *old_sender;
266 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
267 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
269 priv = GET_PRIV (message);
271 old_sender = priv->sender;
272 priv->sender = g_object_ref (contact);
274 if (old_sender) {
275 g_object_unref (old_sender);
278 g_object_notify (G_OBJECT (message), "sender");
281 EmpathyContact *
282 empathy_message_get_receiver (EmpathyMessage *message)
284 EmpathyMessagePriv *priv;
286 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
288 priv = GET_PRIV (message);
290 return priv->receiver;
293 void
294 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
296 EmpathyMessagePriv *priv;
297 EmpathyContact *old_receiver;
299 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
300 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
302 priv = GET_PRIV (message);
304 old_receiver = priv->receiver;
305 priv->receiver = g_object_ref (contact);
307 if (old_receiver) {
308 g_object_unref (old_receiver);
311 g_object_notify (G_OBJECT (message), "receiver");
314 const gchar *
315 empathy_message_get_body (EmpathyMessage *message)
317 EmpathyMessagePriv *priv;
319 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
321 priv = GET_PRIV (message);
323 return priv->body;
326 void
327 empathy_message_set_body (EmpathyMessage *message,
328 const gchar *body)
330 EmpathyMessagePriv *priv = GET_PRIV (message);
331 TpChannelTextMessageType type;
333 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
335 g_free (priv->body);
336 priv->body = NULL;
338 type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
339 if (g_str_has_prefix (body, "/me")) {
340 type = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
341 body += 4;
343 else if (g_str_has_prefix (body, "/say")) {
344 body += 5;
347 if (body) {
348 priv->body = g_strdup (body);
351 if (type != priv->type) {
352 empathy_message_set_tptype (message, type);
355 g_object_notify (G_OBJECT (message), "body");
358 time_t
359 empathy_message_get_timestamp (EmpathyMessage *message)
361 EmpathyMessagePriv *priv;
363 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
365 priv = GET_PRIV (message);
367 return priv->timestamp;
370 void
371 empathy_message_set_timestamp (EmpathyMessage *message,
372 time_t timestamp)
374 EmpathyMessagePriv *priv;
376 g_return_if_fail (EMPATHY_IS_MESSAGE (message));
377 g_return_if_fail (timestamp >= -1);
379 priv = GET_PRIV (message);
381 if (timestamp <= 0) {
382 priv->timestamp = empathy_time_get_current ();
383 } else {
384 priv->timestamp = timestamp;
387 g_object_notify (G_OBJECT (message), "timestamp");
390 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
391 gboolean
392 empathy_message_should_highlight (EmpathyMessage *message)
394 EmpathyContact *contact;
395 const gchar *msg, *to;
396 gchar *cf_msg, *cf_to;
397 gchar *ch;
398 gboolean ret_val;
400 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
402 ret_val = FALSE;
404 msg = empathy_message_get_body (message);
405 if (!msg) {
406 return FALSE;
409 contact = empathy_message_get_receiver (message);
410 if (!contact || !empathy_contact_is_user (contact)) {
411 return FALSE;
414 to = empathy_contact_get_name (contact);
415 if (!to) {
416 return FALSE;
419 cf_msg = g_utf8_casefold (msg, -1);
420 cf_to = g_utf8_casefold (to, -1);
422 ch = strstr (cf_msg, cf_to);
423 if (ch == NULL) {
424 goto finished;
426 if (ch != cf_msg) {
427 /* Not first in the message */
428 if (!IS_SEPARATOR (*(ch - 1))) {
429 goto finished;
433 ch = ch + strlen (cf_to);
434 if (ch >= cf_msg + strlen (cf_msg)) {
435 ret_val = TRUE;
436 goto finished;
439 if (IS_SEPARATOR (*ch)) {
440 ret_val = TRUE;
441 goto finished;
444 finished:
445 g_free (cf_msg);
446 g_free (cf_to);
448 return ret_val;
451 TpChannelTextMessageType
452 empathy_message_type_from_str (const gchar *type_str)
454 if (strcmp (type_str, "normal") == 0) {
455 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
457 if (strcmp (type_str, "action") == 0) {
458 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
460 else if (strcmp (type_str, "notice") == 0) {
461 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
463 else if (strcmp (type_str, "auto-reply") == 0) {
464 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
467 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
470 const gchar *
471 empathy_message_type_to_str (TpChannelTextMessageType type)
473 switch (type) {
474 case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
475 return "action";
476 case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
477 return "notice";
478 case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
479 return "auto-reply";
480 default:
481 return "normal";
485 guint
486 empathy_message_get_id (EmpathyMessage *message)
488 EmpathyMessagePriv *priv = GET_PRIV (message);
490 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
492 return priv->id;
495 void
496 empathy_message_set_id (EmpathyMessage *message, guint id)
498 EmpathyMessagePriv *priv = GET_PRIV (message);
500 priv->id = id;
503 gboolean
504 empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
506 EmpathyMessagePriv *priv1;
507 EmpathyMessagePriv *priv2;
509 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
510 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
512 priv1 = GET_PRIV (message1);
513 priv2 = GET_PRIV (message2);
515 if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {
516 return TRUE;
519 return FALSE;