]> git.0d.be Git - empathy.git/blob - libempathy/empathy-message.c
Add missing include
[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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, 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 "empathy-message.h"
30 #include "empathy-utils.h"
31 #include "empathy-enum-types.h"
32
33 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyMessage)
34 typedef struct {
35         TpChannelTextMessageType  type;
36         EmpathyContact           *sender;
37         EmpathyContact           *receiver;
38         gchar                    *body;
39         time_t                    timestamp;
40 } EmpathyMessagePriv;
41
42 static void empathy_message_finalize   (GObject            *object);
43 static void message_get_property      (GObject            *object,
44                                        guint               param_id,
45                                        GValue             *value,
46                                        GParamSpec         *pspec);
47 static void message_set_property      (GObject            *object,
48                                        guint               param_id,
49                                        const GValue       *value,
50                                        GParamSpec         *pspec);
51
52 G_DEFINE_TYPE (EmpathyMessage, empathy_message, G_TYPE_OBJECT);
53
54 enum {
55         PROP_0,
56         PROP_TYPE,
57         PROP_SENDER,
58         PROP_RECEIVER,
59         PROP_BODY,
60         PROP_TIMESTAMP,
61 };
62
63 static void
64 empathy_message_class_init (EmpathyMessageClass *class)
65 {
66         GObjectClass *object_class;
67
68         object_class = G_OBJECT_CLASS (class);
69         object_class->finalize     = empathy_message_finalize;
70         object_class->get_property = message_get_property;
71         object_class->set_property = message_set_property;
72
73         g_object_class_install_property (object_class,
74                                          PROP_TYPE,
75                                          g_param_spec_uint ("type",
76                                                             "Message Type",
77                                                             "The type of message",
78                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
79                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
80                                                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
81                                                             G_PARAM_READWRITE));
82         g_object_class_install_property (object_class,
83                                          PROP_SENDER,
84                                          g_param_spec_object ("sender",
85                                                               "Message Sender",
86                                                               "The sender of the message",
87                                                               EMPATHY_TYPE_CONTACT,
88                                                               G_PARAM_READWRITE));
89         g_object_class_install_property (object_class,
90                                          PROP_RECEIVER,
91                                          g_param_spec_object ("receiver",
92                                                               "Message Receiver",
93                                                               "The receiver of the message",
94                                                               EMPATHY_TYPE_CONTACT,
95                                                               G_PARAM_READWRITE));
96         g_object_class_install_property (object_class,
97                                          PROP_BODY,
98                                          g_param_spec_string ("body",
99                                                               "Message Body",
100                                                               "The content of the message",
101                                                               NULL,
102                                                               G_PARAM_READWRITE));
103         g_object_class_install_property (object_class,
104                                          PROP_TIMESTAMP,
105                                          g_param_spec_long ("timestamp",
106                                                             "timestamp",
107                                                             "timestamp",
108                                                             -1,
109                                                             G_MAXLONG,
110                                                             -1,
111                                                             G_PARAM_READWRITE));
112
113
114         g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
115
116 }
117
118 static void
119 empathy_message_init (EmpathyMessage *message)
120 {
121         EmpathyMessagePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (message,
122                 EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
123
124         message->priv = priv;
125         priv->timestamp = empathy_time_get_current ();
126 }
127
128 static void
129 empathy_message_finalize (GObject *object)
130 {
131         EmpathyMessagePriv *priv;
132
133         priv = GET_PRIV (object);
134
135         if (priv->sender) {
136                 g_object_unref (priv->sender);
137         }
138         if (priv->receiver) {
139                 g_object_unref (priv->receiver);
140         }
141
142         g_free (priv->body);
143
144         G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
145 }
146
147 static void
148 message_get_property (GObject    *object,
149                       guint       param_id,
150                       GValue     *value,
151                       GParamSpec *pspec)
152 {
153         EmpathyMessagePriv *priv;
154
155         priv = GET_PRIV (object);
156
157         switch (param_id) {
158         case PROP_TYPE:
159                 g_value_set_uint (value, priv->type);
160                 break;
161         case PROP_SENDER:
162                 g_value_set_object (value, priv->sender);
163                 break;
164         case PROP_RECEIVER:
165                 g_value_set_object (value, priv->receiver);
166                 break;
167         case PROP_BODY:
168                 g_value_set_string (value, priv->body);
169                 break;
170         default:
171                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
172                 break;
173         };
174 }
175
176 static void
177 message_set_property (GObject      *object,
178                       guint         param_id,
179                       const GValue *value,
180                       GParamSpec   *pspec)
181 {
182         EmpathyMessagePriv *priv;
183
184         priv = GET_PRIV (object);
185
186         switch (param_id) {
187         case PROP_TYPE:
188                 empathy_message_set_tptype (EMPATHY_MESSAGE (object),
189                                             g_value_get_uint (value));
190                 break;
191         case PROP_SENDER:
192                 empathy_message_set_sender (EMPATHY_MESSAGE (object),
193                                            EMPATHY_CONTACT (g_value_get_object (value)));
194                 break;
195         case PROP_RECEIVER:
196                 empathy_message_set_receiver (EMPATHY_MESSAGE (object),
197                                              EMPATHY_CONTACT (g_value_get_object (value)));
198                 break;
199         case PROP_BODY:
200                 empathy_message_set_body (EMPATHY_MESSAGE (object),
201                                          g_value_get_string (value));
202                 break;
203         default:
204                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
205                 break;
206         };
207 }
208
209 EmpathyMessage *
210 empathy_message_new (const gchar *body)
211 {
212         return g_object_new (EMPATHY_TYPE_MESSAGE,
213                              "body", body,
214                              NULL);
215 }
216
217 TpChannelTextMessageType
218 empathy_message_get_tptype (EmpathyMessage *message)
219 {
220         EmpathyMessagePriv *priv;
221
222         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
223                               TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
224
225         priv = GET_PRIV (message);
226
227         return priv->type;
228 }
229
230 void
231 empathy_message_set_tptype (EmpathyMessage           *message,
232                             TpChannelTextMessageType  type)
233 {
234         EmpathyMessagePriv *priv;
235
236         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
237
238         priv = GET_PRIV (message);
239
240         priv->type = type;
241
242         g_object_notify (G_OBJECT (message), "type");
243 }
244
245 EmpathyContact *
246 empathy_message_get_sender (EmpathyMessage *message)
247 {
248         EmpathyMessagePriv *priv;
249
250         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
251
252         priv = GET_PRIV (message);
253
254         return priv->sender;
255 }
256
257 void
258 empathy_message_set_sender (EmpathyMessage *message, EmpathyContact *contact)
259 {
260         EmpathyMessagePriv *priv;
261         EmpathyContact     *old_sender;
262
263         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
264         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
265
266         priv = GET_PRIV (message);
267
268         old_sender = priv->sender;
269         priv->sender = g_object_ref (contact);
270
271         if (old_sender) {
272                 g_object_unref (old_sender);
273         }
274
275         g_object_notify (G_OBJECT (message), "sender");
276 }
277
278 EmpathyContact *
279 empathy_message_get_receiver (EmpathyMessage *message)
280 {
281         EmpathyMessagePriv *priv;
282
283         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
284
285         priv = GET_PRIV (message);
286
287         return priv->receiver;
288 }
289
290 void
291 empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
292 {
293         EmpathyMessagePriv *priv;
294         EmpathyContact     *old_receiver;
295
296         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
297         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
298
299         priv = GET_PRIV (message);
300
301         old_receiver = priv->receiver;
302         priv->receiver = g_object_ref (contact);
303
304         if (old_receiver) {
305                 g_object_unref (old_receiver);
306         }
307
308         g_object_notify (G_OBJECT (message), "receiver");
309 }
310
311 const gchar *
312 empathy_message_get_body (EmpathyMessage *message)
313 {
314         EmpathyMessagePriv *priv;
315
316         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
317
318         priv = GET_PRIV (message);
319
320         return priv->body;
321 }
322
323 void
324 empathy_message_set_body (EmpathyMessage *message,
325                           const gchar    *body)
326 {
327         EmpathyMessagePriv       *priv = GET_PRIV (message);
328         TpChannelTextMessageType  type;
329
330         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
331
332         g_free (priv->body);
333         priv->body = NULL;
334
335         type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
336         if (g_str_has_prefix (body, "/me")) {
337                 type = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
338                 body += 4;
339         }
340         else if (g_str_has_prefix (body, "/say")) {
341                 body += 5;
342         }
343
344         if (body) {
345                 priv->body = g_strdup (body);
346         }
347
348         if (type != priv->type) {
349                 empathy_message_set_tptype (message, type);
350         }
351
352         g_object_notify (G_OBJECT (message), "body");
353 }
354
355 time_t
356 empathy_message_get_timestamp (EmpathyMessage *message)
357 {
358         EmpathyMessagePriv *priv;
359
360         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
361
362         priv = GET_PRIV (message);
363
364         return priv->timestamp;
365 }
366
367 void
368 empathy_message_set_timestamp (EmpathyMessage *message,
369                                time_t          timestamp)
370 {
371         EmpathyMessagePriv *priv;
372
373         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
374         g_return_if_fail (timestamp >= -1);
375
376         priv = GET_PRIV (message);
377
378         if (timestamp <= 0) {
379                 priv->timestamp = empathy_time_get_current ();
380         } else {
381                 priv->timestamp = timestamp;
382         }
383
384         g_object_notify (G_OBJECT (message), "timestamp");
385 }
386
387 GDate *
388 empathy_message_get_date_and_time (EmpathyMessage *message, time_t *timestamp)
389 {
390         GDate *date;
391
392         *timestamp = 0;
393         if (message) {
394                 *timestamp = empathy_message_get_timestamp (message);
395         }
396
397         if (timestamp <= 0) {
398                 *timestamp = empathy_time_get_current ();
399         }
400
401         date = g_date_new ();
402         g_date_set_time_t (date, *timestamp);
403
404         return date;
405 }
406
407 #define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
408 gboolean
409 empathy_message_should_highlight (EmpathyMessage *message)
410 {
411         EmpathyContact *contact;
412         const gchar   *msg, *to;
413         gchar         *cf_msg, *cf_to;
414         gchar         *ch;
415         gboolean       ret_val;
416
417         g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
418
419         ret_val = FALSE;
420
421         msg = empathy_message_get_body (message);
422         if (!msg) {
423                 return FALSE;
424         }
425
426         contact = empathy_message_get_receiver (message);
427         if (!contact || !empathy_contact_is_user (contact)) {
428                 return FALSE;
429         }
430
431         to = empathy_contact_get_name (contact);
432         if (!to) {
433                 return FALSE;
434         }
435
436         cf_msg = g_utf8_casefold (msg, -1);
437         cf_to = g_utf8_casefold (to, -1);
438
439         ch = strstr (cf_msg, cf_to);
440         if (ch == NULL) {
441                 goto finished;
442         }
443         if (ch != cf_msg) {
444                 /* Not first in the message */
445                 if (!IS_SEPARATOR (*(ch - 1))) {
446                         goto finished;
447                 }
448         }
449
450         ch = ch + strlen (cf_to);
451         if (ch >= cf_msg + strlen (cf_msg)) {
452                 ret_val = TRUE;
453                 goto finished;
454         }
455
456         if (IS_SEPARATOR (*ch)) {
457                 ret_val = TRUE;
458                 goto finished;
459         }
460
461 finished:
462         g_free (cf_msg);
463         g_free (cf_to);
464
465         return ret_val;
466 }
467
468 TpChannelTextMessageType
469 empathy_message_type_from_str (const gchar *type_str)
470 {
471         if (strcmp (type_str, "normal") == 0) {
472                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
473         }
474         if (strcmp (type_str, "action") == 0) {
475                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
476         }
477         else if (strcmp (type_str, "notice") == 0) {
478                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE;
479         }
480         else if (strcmp (type_str, "auto-reply") == 0) {
481                 return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY;
482         }
483
484         return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
485 }
486
487 const gchar *
488 empathy_message_type_to_str (TpChannelTextMessageType type)
489 {
490         switch (type) {
491         case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION:
492                 return "action";
493         case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE:
494                 return "notice";
495         case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
496                 return "auto-reply";
497         default:
498                 return "normal";
499         }
500 }
501