]> git.0d.be Git - empathy.git/blob - libempathy/empathy-message.c
coding style fixes
[empathy.git] / libempathy / empathy-message.c
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.
5  *
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.
10  *
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.
15  *
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
20  *
21  * Authors: Mikael Hallendal <micke@imendio.com>
22  *          Xavier Claessens <xclaesse@gmail.com>
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28
29 #include <telepathy-glib/util.h>
30
31 #include "empathy-message.h"
32 #include "empathy-utils.h"
33 #include "empathy-enum-types.h"
34
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         gboolean                  is_backlog;
43         guint                     id;
44         gboolean                  incoming;
45 } EmpathyMessagePriv;
46
47 static void empathy_message_finalize   (GObject            *object);
48 static void message_get_property      (GObject            *object,
49                                        guint               param_id,
50                                        GValue             *value,
51                                        GParamSpec         *pspec);
52 static void message_set_property      (GObject            *object,
53                                        guint               param_id,
54                                        const GValue       *value,
55                                        GParamSpec         *pspec);
56
57 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
58
59 enum {
60         PROP_0,
61         PROP_TYPE,
62         PROP_SENDER,
63         PROP_RECEIVER,
64         PROP_BODY,
65         PROP_TIMESTAMP,
66         PROP_IS_BACKLOG,
67         PROP_INCOMING,
68 };
69
70 static void
71 empathy_message_class_init (EmpathyMessageClass *class)
72 {
73         GObjectClass *object_class;
74
75         object_class = G_OBJECT_CLASS (class);
76         object_class->finalize     = empathy_message_finalize;
77         object_class->get_property = message_get_property;
78         object_class->set_property = message_set_property;
79
80         g_object_class_install_property (object_class,
81                                          PROP_TYPE,
82                                          g_param_spec_uint ("type",
83                                                             "Message Type",
84                                                             "The type of message",
85                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
86                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
87                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
88                                                             G_PARAM_READWRITE));
89         g_object_class_install_property (object_class,
90                                          PROP_SENDER,
91                                          g_param_spec_object ("sender",
92                                                               "Message Sender",
93                                                               "The sender of the message",
94                                                               EMPATHY_TYPE_CONTACT,
95                                                               G_PARAM_READWRITE));
96         g_object_class_install_property (object_class,
97                                          PROP_RECEIVER,
98                                          g_param_spec_object ("receiver",
99                                                               "Message Receiver",
100                                                               "The receiver of the message",
101                                                               EMPATHY_TYPE_CONTACT,
102                                                               G_PARAM_READWRITE));
103         g_object_class_install_property (object_class,
104                                          PROP_BODY,
105                                          g_param_spec_string ("body",
106                                                               "Message Body",
107                                                               "The content of the message",
108                                                               NULL,
109                                                               G_PARAM_READWRITE));
110         g_object_class_install_property (object_class,
111                                          PROP_TIMESTAMP,
112                                          g_param_spec_long ("timestamp",
113                                                             "timestamp",
114                                                             "timestamp",
115                                                             -1,
116                                                             G_MAXLONG,
117                                                             -1,
118                                                             G_PARAM_READWRITE));
119         g_object_class_install_property (object_class,
120                                          PROP_IS_BACKLOG,
121                                          g_param_spec_boolean ("is-backlog",
122                                                                "History message",
123                                                                "If the message belongs to history",
124                                                                FALSE,
125                                                                G_PARAM_READWRITE));
126
127
128         g_object_class_install_property (object_class,
129                                          PROP_INCOMING,
130                                          g_param_spec_boolean ("incoming",
131                                                                "Incoming",
132                                                                "If this is an incoming (as opposed to sent) message",
133                                                                FALSE,
134                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
135
136         g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
137
138 }
139
140 static void
141 empathy_message_init (EmpathyMessage *message)
142 {
143         EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
144                 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
145
146         message->priv = priv;
147         priv->timestamp = empathy_time_get_current ();
148 }
149
150 static void
151 empathy_message_finalize (GObject *object)
152 {
153         EmpathyMessagePriv *priv;
154
155         priv = GET_PRIV (object);
156
157         if (priv->sender) {
158                 g_object_unref (priv->sender);
159         }
160         if (priv->receiver) {
161                 g_object_unref (priv->receiver);
162         }
163
164         g_free (priv->body);
165
166         G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
167 }
168
169 static void
170 message_get_property (GObject    *object,
171                       guint       param_id,
172                       GValue     *value,
173                       GParamSpec *pspec)
174 {
175         EmpathyMessagePriv *priv;
176
177         priv = GET_PRIV (object);
178
179         switch (param_id) {
180         case PROP_TYPE:
181                 g_value_set_uint (value, priv->type);
182                 break;
183         case PROP_SENDER:
184                 g_value_set_object (value, priv->sender);
185                 break;
186         case PROP_RECEIVER:
187                 g_value_set_object (value, priv->receiver);
188                 break;
189         case PROP_BODY:
190                 g_value_set_string (value, priv->body);
191                 break;
192         case PROP_INCOMING:
193                 g_value_set_boolean (value, priv->incoming);
194                 break;
195         default:
196                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
197                 break;
198         };
199 }
200
201 static void
202 message_set_property (GObject      *object,
203                       guint         param_id,
204                       const GValue *value,
205                       GParamSpec   *pspec)
206 {
207         EmpathyMessagePriv *priv;
208
209         priv = GET_PRIV (object);
210
211         switch (param_id) {
212         case PROP_TYPE:
213                 empathy_message_set_tptype (EMPATHY_MESSAGE (object),
214                                             g_value_get_uint (value));
215                 break;
216         case PROP_SENDER:
217                 empathy_message_set_sender (EMPATHY_MESSAGE (object),
218                                            EMPATHY_CONTACT (g_value_get_object (value)));
219                 break;
220         case PROP_RECEIVER:
221                 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
222                                              EMPATHY_CONTACT (g_value_get_object (value)));
223                 break;
224         case PROP_BODY:
225                 empathy_message_set_body (EMPATHY_MESSAGE (object),
226                                          g_value_get_string (value));
227                 break;
228         case PROP_INCOMING:
229                 priv->incoming = g_value_get_boolean (value);
230                 break;
231         default:
232                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
233                 break;
234         };
235 }
236
237 EmpathyMessage *
238 empathy_message_new (const gchar *body)
239 {
240         return g_object_new (EMPATHY_TYPE_MESSAGE,
241                              "body", body,
242                              NULL);
243 }
244
245 TpChannelTextMessageType
246 empathy_message_get_tptype (EmpathyMessage *message)
247 {
248         EmpathyMessagePriv *priv;
249
250         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
251                               TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
252
253         priv = GET_PRIV (message);
254
255         return priv->type;
256 }
257
258 void
259 empathy_message_set_tptype (EmpathyMessage           *message,
260                             TpChannelTextMessageType  type)
261 {
262         EmpathyMessagePriv *priv;
263
264         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
265
266         priv = GET_PRIV (message);
267
268         priv->type = type;
269
270         g_object_notify (G_OBJECT (message), "type");
271 }
272
273 EmpathyContact *
274 empathy_message_get_sender (EmpathyMessage *message)
275 {
276         EmpathyMessagePriv *priv;
277
278         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
279
280         priv = GET_PRIV (message);
281
282         return priv->sender;
283 }
284
285 void
286 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
287 {
288         EmpathyMessagePriv *priv;
289         EmpathyContact     *old_sender;
290
291         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
292         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
293
294         priv = GET_PRIV (message);
295
296         old_sender = priv->sender;
297         priv->sender = g_object_ref (contact);
298
299         if (old_sender) {
300                 g_object_unref (old_sender);
301         }
302
303         g_object_notify (G_OBJECT (message), "sender");
304 }
305
306 EmpathyContact *
307 empathy_message_get_receiver (EmpathyMessage *message)
308 {
309         EmpathyMessagePriv *priv;
310
311         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
312
313         priv = GET_PRIV (message);
314
315         return priv->receiver;
316 }
317
318 void
319 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
320 {
321         EmpathyMessagePriv *priv;
322         EmpathyContact     *old_receiver;
323
324         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
325         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
326
327         priv = GET_PRIV (message);
328
329         old_receiver = priv->receiver;
330         priv->receiver = g_object_ref (contact);
331
332         if (old_receiver) {
333                 g_object_unref (old_receiver);
334         }
335
336         g_object_notify (G_OBJECT (message), "receiver");
337 }
338
339 const gchar *
340 empathy_message_get_body (EmpathyMessage *message)
341 {
342         EmpathyMessagePriv *priv;
343
344         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
345
346         priv = GET_PRIV (message);
347
348         return priv->body;
349 }
350
351 void
352 empathy_message_set_body (EmpathyMessage *message,
353                           const gchar    *body)
354 {
355         EmpathyMessagePriv       *priv = GET_PRIV (message);
356
357         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
358
359         g_free (priv->body);
360
361         if (body) {
362                 priv->body = g_strdup (body);
363         } else {
364                 priv->body = NULL;
365         }
366
367         g_object_notify (G_OBJECT (message), "body");
368 }
369
370 time_t
371 empathy_message_get_timestamp (EmpathyMessage *message)
372 {
373         EmpathyMessagePriv *priv;
374
375         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
376
377         priv = GET_PRIV (message);
378
379         return priv->timestamp;
380 }
381
382 void
383 empathy_message_set_timestamp (EmpathyMessage *message,
384                                time_t          timestamp)
385 {
386         EmpathyMessagePriv *priv;
387
388         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
389         g_return_if_fail (timestamp >= -1);
390
391         priv = GET_PRIV (message);
392
393         if (timestamp <= 0) {
394                 priv->timestamp = empathy_time_get_current ();
395         } else {
396                 priv->timestamp = timestamp;
397         }
398
399         g_object_notify (G_OBJECT (message), "timestamp");
400 }
401
402 gboolean
403 empathy_message_is_backlog (EmpathyMessage *message)
404 {
405         EmpathyMessagePriv *priv;
406
407         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
408
409         priv = GET_PRIV (message);
410
411         return priv->is_backlog;
412 }
413
414 void
415 empathy_message_set_is_backlog (EmpathyMessage *message,
416                                 gboolean is_backlog)
417 {
418         EmpathyMessagePriv *priv;
419
420         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
421
422         priv = GET_PRIV (message);
423
424         priv->is_backlog = is_backlog;
425
426         g_object_notify (G_OBJECT (message), "is-backlog");
427 }
428
429 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
430 gboolean
431 empathy_message_should_highlight (EmpathyMessage *message)
432 {
433         EmpathyContact *contact;
434         const gchar   *msg, *to;
435         gchar         *cf_msg, *cf_to;
436         gchar         *ch;
437         gboolean       ret_val;
438
439         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
440
441         ret_val = FALSE;
442
443         msg = empathy_message_get_body (message);
444         if (!msg) {
445                 return FALSE;
446         }
447
448         contact = empathy_message_get_receiver (message);
449         if (!contact || !empathy_contact_is_user (contact)) {
450                 return FALSE;
451         }
452
453         to = empathy_contact_get_name (contact);
454         if (!to) {
455                 return FALSE;
456         }
457
458         cf_msg = g_utf8_casefold (msg, -1);
459         cf_to = g_utf8_casefold (to, -1);
460
461         ch = strstr (cf_msg, cf_to);
462         if (ch == NULL) {
463                 goto finished;
464         }
465         if (ch != cf_msg) {
466                 /* Not first in the message */
467                 if (!IS_SEPARATOR (*(ch - 1))) {
468                         goto finished;
469                 }
470         }
471
472         ch = ch + strlen (cf_to);
473         if (ch >= cf_msg + strlen (cf_msg)) {
474                 ret_val = TRUE;
475                 goto finished;
476         }
477
478         if (IS_SEPARATOR (*ch)) {
479                 ret_val = TRUE;
480                 goto finished;
481         }
482
483 finished:
484         g_free (cf_msg);
485         g_free (cf_to);
486
487         return ret_val;
488 }
489
490 TpChannelTextMessageType
491 empathy_message_type_from_str (const gchar *type_str)
492 {
493         if (strcmp (type_str, "normal") == 0) {
494                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
495         }
496         if (strcmp (type_str, "action") == 0) {
497                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
498         }
499         else if (strcmp (type_str, "notice") == 0) {
500                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
501         }
502         else if (strcmp (type_str, "auto-reply") == 0) {
503                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
504         }
505
506         return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
507 }
508
509 const gchar *
510 empathy_message_type_to_str (TpChannelTextMessageType type)
511 {
512         switch (type) {
513         case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
514                 return "action";
515         case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
516                 return "notice";
517         case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
518                 return "auto-reply";
519         default:
520                 return "normal";
521         }
522 }
523
524 guint
525 empathy_message_get_id (EmpathyMessage *message)
526 {
527         EmpathyMessagePriv *priv = GET_PRIV (message);
528
529         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
530
531         return priv->id;
532 }
533
534 void
535 empathy_message_set_id (EmpathyMessage *message, guint id)
536 {
537         EmpathyMessagePriv *priv = GET_PRIV (message);
538
539         priv->id = id;
540 }
541
542 void
543 empathy_message_set_incoming (EmpathyMessage *message, gboolean incoming)
544 {
545         EmpathyMessagePriv *priv;
546
547         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
548
549         priv = GET_PRIV (message);
550
551         priv->incoming = incoming;
552
553         g_object_notify (G_OBJECT (message), "incoming");
554 }
555
556 gboolean
557 empathy_message_is_incoming (EmpathyMessage *message)
558 {
559         EmpathyMessagePriv *priv = GET_PRIV (message);
560
561         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
562
563         return priv->incoming;
564 }
565
566 gboolean
567 empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
568 {
569         EmpathyMessagePriv *priv1;
570         EmpathyMessagePriv *priv2;
571
572         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message1), FALSE);
573         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message2), FALSE);
574
575         priv1 = GET_PRIV (message1);
576         priv2 = GET_PRIV (message2);
577
578         if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {
579                 return TRUE;
580         }
581
582         return FALSE;
583 }