]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-theme-boxes.c
Make use of tp-glib debug system.
[empathy.git] / libempathy-gtk / empathy-theme-boxes.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 Imendio AB
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include <string.h>
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include "empathy-ui-utils.h"
29 #include "empathy-theme-boxes.h"
30
31 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
32 #include <libempathy/empathy-debug.h>
33
34 #define MARGIN 4
35 #define HEADER_PADDING 2
36
37 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME_BOXES, EmpathyThemeBoxesPriv))
38
39 typedef struct _EmpathyThemeBoxesPriv EmpathyThemeBoxesPriv;
40
41 struct _EmpathyThemeBoxesPriv {
42         gchar *header_foreground;
43         gchar *header_background;
44         gchar *header_line_background;
45         gchar *text_foreground;
46         gchar *text_background;
47         gchar *action_foreground;
48         gchar *highlight_foreground;
49         gchar *time_foreground;
50         gchar *event_foreground;
51         gchar *invite_foreground;
52         gchar *link_foreground;
53 };
54
55 static void     theme_boxes_finalize          (GObject            *object);
56 static void     theme_boxes_get_property      (GObject            *object,
57                                                guint               param_id,
58                                                GValue             *value,
59                                                GParamSpec         *pspec);
60 static void     theme_boxes_set_property      (GObject            *object,
61                                                guint               param_id,
62                                                const GValue       *value,
63                                                GParamSpec         *pspec);
64 static void     theme_boxes_define_theme_tags (EmpathyTheme        *theme,
65                                                EmpathyChatView     *view);
66 static void     theme_boxes_update_view       (EmpathyTheme        *theme,
67                                                EmpathyChatView     *view);
68 static void     theme_boxes_append_message    (EmpathyTheme        *theme,
69                                                EmpathyChatView     *view,
70                                                EmpathyMessage      *message);
71 static void     theme_boxes_append_event      (EmpathyTheme        *theme,
72                                                EmpathyChatView     *view,
73                                                const gchar        *str);
74 static void     theme_boxes_append_timestamp  (EmpathyTheme        *theme,
75                                                EmpathyChatView     *view,
76                                                EmpathyMessage      *message,
77                                                gboolean            show_date,
78                                                gboolean            show_time);
79 static void     theme_boxes_append_spacing    (EmpathyTheme        *theme,
80                                                EmpathyChatView     *view);
81
82 enum {
83         PROP_0,
84         PROP_HEADER_FOREGROUND,
85         PROP_HEADER_BACKGROUND,
86         PROP_HEADER_LINE_BACKGROUND,
87         PROP_TEXT_FOREGROUND,
88         PROP_TEXT_BACKGROUND,
89         PROP_ACTION_FOREGROUND,
90         PROP_HIGHLIGHT_FOREGROUND,
91         PROP_TIME_FOREGROUND,
92         PROP_EVENT_FOREGROUND,
93         PROP_INVITE_FOREGROUND,
94         PROP_LINK_FOREGROUND
95 };
96
97 enum {
98         PROP_FLOP,
99         PROP_MY_PROP
100 };
101
102 G_DEFINE_TYPE (EmpathyThemeBoxes, empathy_theme_boxes, EMPATHY_TYPE_THEME);
103
104 static void
105 empathy_theme_boxes_class_init (EmpathyThemeBoxesClass *class)
106 {
107         GObjectClass     *object_class;
108         EmpathyThemeClass *theme_class;
109
110         object_class = G_OBJECT_CLASS (class);
111         theme_class  = EMPATHY_THEME_CLASS (class);
112
113         object_class->finalize       = theme_boxes_finalize;
114         object_class->get_property   = theme_boxes_get_property;
115         object_class->set_property   = theme_boxes_set_property;
116
117         theme_class->update_view      = theme_boxes_update_view;
118         theme_class->append_message   = theme_boxes_append_message;
119         theme_class->append_event     = theme_boxes_append_event;
120         theme_class->append_timestamp = theme_boxes_append_timestamp;
121         theme_class->append_spacing   = theme_boxes_append_spacing;
122
123         g_object_class_install_property (object_class,
124                                          PROP_HEADER_FOREGROUND,
125                                          g_param_spec_string ("header-foreground",
126                                                               "",
127                                                               "",
128                                                               NULL,
129                                                               G_PARAM_READWRITE));
130
131         g_object_class_install_property (object_class,
132                                          PROP_HEADER_BACKGROUND,
133                                          g_param_spec_string ("header-background",
134                                                               "",
135                                                               "",
136                                                               NULL,
137                                                               G_PARAM_READWRITE));
138
139         g_object_class_install_property (object_class,
140                                          PROP_HEADER_LINE_BACKGROUND,
141                                          g_param_spec_string ("header-line-background",
142                                                               "",
143                                                               "",
144                                                               NULL,
145                                                               G_PARAM_READWRITE));
146
147
148         g_object_class_install_property (object_class,
149                                          PROP_TEXT_FOREGROUND,
150                                          g_param_spec_string ("text-foreground",
151                                                               "",
152                                                               "",
153                                                               NULL,
154                                                               G_PARAM_READWRITE));
155
156         g_object_class_install_property (object_class,
157                                          PROP_TEXT_BACKGROUND,
158                                          g_param_spec_string ("text-background",
159                                                               "",
160                                                               "",
161                                                               NULL,
162                                                               G_PARAM_READWRITE));
163
164         g_object_class_install_property (object_class,
165                                          PROP_ACTION_FOREGROUND,
166                                          g_param_spec_string ("action-foreground",
167                                                               "",
168                                                               "",
169                                                               NULL,
170                                                               G_PARAM_READWRITE));
171
172         g_object_class_install_property (object_class,
173                                          PROP_HIGHLIGHT_FOREGROUND,
174                                          g_param_spec_string ("highlight-foreground",
175                                                               "",
176                                                               "",
177                                                               NULL,
178                                                               G_PARAM_READWRITE));
179
180         g_object_class_install_property (object_class,
181                                          PROP_TIME_FOREGROUND,
182                                          g_param_spec_string ("time-foreground",
183                                                               "",
184                                                               "",
185                                                               NULL,
186                                                               G_PARAM_READWRITE));
187
188         g_object_class_install_property (object_class,
189                                          PROP_EVENT_FOREGROUND,
190                                          g_param_spec_string ("event-foreground",
191                                                               "",
192                                                               "",
193                                                               NULL,
194                                                               G_PARAM_READWRITE));
195
196         g_object_class_install_property (object_class,
197                                          PROP_INVITE_FOREGROUND,
198                                          g_param_spec_string ("invite-foreground",
199                                                               "",
200                                                               "",
201                                                               NULL,
202                                                               G_PARAM_READWRITE));
203
204         g_object_class_install_property (object_class,
205                                          PROP_LINK_FOREGROUND,
206                                          g_param_spec_string ("link-foreground",
207                                                               "",
208                                                               "",
209                                                               NULL,
210                                                               G_PARAM_READWRITE));
211
212         g_type_class_add_private (object_class, sizeof (EmpathyThemeBoxesPriv));
213 }
214
215 static void
216 empathy_theme_boxes_init (EmpathyThemeBoxes *theme)
217 {
218         EmpathyThemeBoxesPriv *priv;
219
220         priv = GET_PRIV (theme);
221 }
222
223 static void
224 theme_boxes_finalize (GObject *object)
225 {
226         EmpathyThemeBoxesPriv *priv;
227
228         priv = GET_PRIV (object);
229
230         g_free (priv->header_foreground);
231         g_free (priv->header_background);
232         g_free (priv->header_line_background);
233         g_free (priv->text_foreground);
234         g_free (priv->text_background);
235         g_free (priv->action_foreground);
236         g_free (priv->highlight_foreground);
237         g_free (priv->time_foreground);
238         g_free (priv->event_foreground);
239         g_free (priv->invite_foreground);
240         g_free (priv->link_foreground);
241         
242         (G_OBJECT_CLASS (empathy_theme_boxes_parent_class)->finalize) (object);
243 }
244
245 static void
246 theme_boxes_get_property (GObject    *object,
247                           guint       param_id,
248                           GValue     *value,
249                           GParamSpec *pspec)
250 {
251         EmpathyThemeBoxesPriv *priv;
252
253         priv = GET_PRIV (object);
254
255         switch (param_id) {
256         case PROP_HEADER_FOREGROUND:
257                 g_value_set_string (value, priv->header_foreground);
258                 break;
259         case PROP_HEADER_BACKGROUND:
260                 g_value_set_string (value, priv->header_background);
261                 break;
262         case PROP_HEADER_LINE_BACKGROUND:
263                 g_value_set_string (value, priv->header_line_background);
264                 break;
265         case PROP_TEXT_FOREGROUND:
266                 g_value_set_string (value, priv->text_foreground);
267                 break;
268         case PROP_TEXT_BACKGROUND:
269                 g_value_set_string (value, priv->text_background);
270                 break;
271         case PROP_ACTION_FOREGROUND:
272                 g_value_set_string (value, priv->action_foreground);
273                 break;
274         case PROP_HIGHLIGHT_FOREGROUND:
275                 g_value_set_string (value, priv->highlight_foreground);
276                 break;
277         case PROP_TIME_FOREGROUND:
278                 g_value_set_string (value, priv->time_foreground);
279                 break;
280         case PROP_EVENT_FOREGROUND:
281                 g_value_set_string (value, priv->event_foreground);
282                 break;
283         case PROP_INVITE_FOREGROUND:
284                 g_value_set_string (value, priv->invite_foreground);
285                 break;
286         case PROP_LINK_FOREGROUND:
287                 g_value_set_string (value, priv->link_foreground);
288                 break;
289         default:
290                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
291                 break;
292         }
293 }
294 static void
295 theme_boxes_set_property (GObject      *object,
296                           guint         param_id,
297                           const GValue *value,
298                           GParamSpec   *pspec)
299 {
300         EmpathyThemeBoxesPriv *priv;
301
302         priv = GET_PRIV (object);
303
304         switch (param_id) {
305         case PROP_HEADER_FOREGROUND:
306                 g_free (priv->header_foreground);
307                 priv->header_foreground = g_value_dup_string (value);
308                 g_object_notify (object, "header-foreground");
309                 break;
310         case PROP_HEADER_BACKGROUND:
311                 g_free (priv->header_background);
312                 priv->header_background = g_value_dup_string (value);
313                 g_object_notify (object, "header-background");
314                 break;
315         case PROP_HEADER_LINE_BACKGROUND:
316                 g_free (priv->header_line_background);
317                 priv->header_line_background = g_value_dup_string (value);
318                 g_object_notify (object, "header-line_background");
319                 break;
320         case PROP_TEXT_FOREGROUND:
321                 g_free (priv->text_foreground);
322                 priv->text_foreground = g_value_dup_string (value);
323                 g_object_notify (object, "text-foreground");
324                 break;
325         case PROP_TEXT_BACKGROUND:
326                 g_free (priv->text_background);
327                 priv->text_background = g_value_dup_string (value);
328                 g_object_notify (object, "text-background");
329                 break;
330         case PROP_ACTION_FOREGROUND:
331                 g_free (priv->action_foreground);
332                 priv->action_foreground = g_value_dup_string (value);
333                 g_object_notify (object, "action-foreground");
334                 break;
335         case PROP_HIGHLIGHT_FOREGROUND:
336                 g_free (priv->highlight_foreground);
337                 priv->highlight_foreground = g_value_dup_string (value);
338                 g_object_notify (object, "highlight-foreground");
339                 break;
340         case PROP_TIME_FOREGROUND:
341                 g_free (priv->time_foreground);
342                 priv->time_foreground = g_value_dup_string (value);
343                 g_object_notify (object, "time-foreground");
344                 break;
345         case PROP_EVENT_FOREGROUND:
346                 g_free (priv->event_foreground);
347                 priv->event_foreground = g_value_dup_string (value);
348                 g_object_notify (object, "event-foreground");
349                 break;
350         case PROP_INVITE_FOREGROUND:
351                 g_free (priv->invite_foreground);
352                 priv->invite_foreground = g_value_dup_string (value);
353                 g_object_notify (object, "invite-foreground");
354                 break;
355         case PROP_LINK_FOREGROUND:
356                 g_free (priv->link_foreground);
357                 priv->link_foreground = g_value_dup_string (value);
358                 g_object_notify (object, "link-foreground");
359                 break;
360         default:
361                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
362                 break;
363         }
364 }
365
366 static void
367 theme_boxes_define_theme_tags (EmpathyTheme *theme, EmpathyChatView *view)
368 {
369         EmpathyThemeBoxesPriv *priv;
370         GtkTextBuffer         *buffer;
371         GtkTextTag            *tag;
372
373         priv = GET_PRIV (theme);
374
375         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
376
377         empathy_text_buffer_tag_set (buffer, "fancy-spacing",
378                                      "size", 3000,
379                                      "pixels-above-lines", 8,
380                                      NULL);
381
382         tag = empathy_text_buffer_tag_set (buffer, "fancy-header",
383                                            "weight", PANGO_WEIGHT_BOLD,
384                                            "pixels-above-lines", HEADER_PADDING,
385                                            "pixels-below-lines", HEADER_PADDING,
386                                            NULL);
387         if (priv->header_foreground) {
388                 g_object_set (tag,
389                               "foreground", priv->header_foreground,
390                               "paragraph-background", priv->header_background,
391                               NULL);
392         }
393
394         tag = empathy_text_buffer_tag_set (buffer, "fancy-header-line",
395                                            "size", 1,
396                                            NULL);
397         if (priv->header_line_background) {
398                 g_object_set (tag,
399                               "paragraph-background", priv->header_line_background,
400                               NULL);
401         }
402
403         tag = empathy_text_buffer_tag_set (buffer, "fancy-body",
404                                            "pixels-above-lines", 4,
405                                            NULL);
406         if (priv->text_background) {
407                 g_object_set (tag,
408                               "paragraph-background", priv->text_background,
409                               NULL);
410         }
411
412         if (priv->text_foreground) {
413                 g_object_set (tag,
414                               "foreground", priv->text_foreground,
415                               NULL);
416         }
417
418         tag = empathy_text_buffer_tag_set (buffer, "fancy-action",
419                                            "style", PANGO_STYLE_ITALIC,
420                                            "pixels-above-lines", 4,
421                                            NULL);
422
423         if (priv->text_background) {
424                 g_object_set (tag,
425                               "paragraph-background", priv->text_background,
426                               NULL);
427         }
428
429         if (priv->action_foreground) {
430                 g_object_set (tag,
431                               "foreground", priv->action_foreground,
432                               NULL);
433         }
434
435         tag = empathy_text_buffer_tag_set (buffer, "fancy-highlight",
436                                            "weight", PANGO_WEIGHT_BOLD,
437                                            "pixels-above-lines", 4,
438                                            NULL);
439         if (priv->text_background) {
440                 g_object_set (tag,
441                               "paragraph-background", priv->text_background,
442                               NULL);
443         }
444
445
446         if (priv->highlight_foreground) {
447                 g_object_set (tag,
448                               "foreground", priv->highlight_foreground,
449                               NULL);
450         }
451
452         tag = empathy_text_buffer_tag_set (buffer, "fancy-time",
453                                            "justification", GTK_JUSTIFY_CENTER,
454                                            NULL);
455         if (priv->time_foreground) {
456                 g_object_set (tag,
457                               "foreground", priv->time_foreground,
458                               NULL);
459         }
460
461         tag = empathy_text_buffer_tag_set (buffer, "fancy-event",
462                                            "justification", GTK_JUSTIFY_LEFT,
463                                            NULL);
464         if (priv->event_foreground) {
465                 g_object_set (tag,
466                               "foreground", priv->event_foreground,
467                               NULL);
468         }
469
470         tag = empathy_text_buffer_tag_set (buffer, "invite", NULL);
471         if (priv->invite_foreground) {
472                 g_object_set (tag,
473                               "foreground", priv->invite_foreground,
474                               NULL);
475         }
476
477         tag = empathy_text_buffer_tag_set (buffer, "fancy-link",
478                                            "underline", PANGO_UNDERLINE_SINGLE,
479                                            NULL);
480         if (priv->link_foreground) {
481                 g_object_set (tag,
482                               "foreground", priv->link_foreground,
483                               NULL);
484         } 
485 }
486
487 static void
488 theme_boxes_update_view (EmpathyTheme *theme, EmpathyChatView *view)
489 {
490         EmpathyThemeBoxesPriv *priv;
491
492         g_return_if_fail (EMPATHY_IS_THEME_BOXES (theme));
493         g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
494
495         priv = GET_PRIV (theme);
496
497         theme_boxes_define_theme_tags (theme, view);
498         
499         empathy_chat_view_set_margin (view, MARGIN);
500 }
501
502 static void
503 table_size_allocate_cb (GtkWidget     *view,
504                         GtkAllocation *allocation,
505                         GtkWidget     *box)
506 {
507         gint width, height;
508
509         gtk_widget_get_size_request (box, NULL, &height);
510
511         width = allocation->width;
512         
513         width -= \
514                 gtk_text_view_get_right_margin (GTK_TEXT_VIEW (view)) - \
515                 gtk_text_view_get_left_margin (GTK_TEXT_VIEW (view));
516         width -= 2 * MARGIN;
517         width -= 2 * HEADER_PADDING;
518
519         gtk_widget_set_size_request (box, width, height);
520 }
521
522 static void
523 theme_boxes_maybe_append_header (EmpathyTheme        *theme,
524                                  EmpathyChatView     *view,
525                                  EmpathyMessage      *msg)
526 {
527         EmpathyThemeBoxesPriv *priv;
528         EmpathyContact        *contact;
529         EmpathyContact        *last_contact;
530         GdkPixbuf            *avatar = NULL;
531         GtkTextBuffer        *buffer;
532         const gchar          *name;
533         GtkTextIter           iter;
534         GtkWidget            *label1, *label2;
535         GtkTextChildAnchor   *anchor;
536         GtkWidget            *box;
537         gchar                *str;
538         time_t                time;
539         gchar                *tmp;
540         GtkTextIter           start;
541         GdkColor              color;
542         gboolean              parse_success;
543
544         priv = GET_PRIV (theme);
545
546         contact = empathy_message_get_sender (msg);
547         name = empathy_contact_get_name (contact);
548         last_contact = empathy_chat_view_get_last_contact (view);
549         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
550
551         DEBUG ("Maybe add fancy header");
552
553         /* Only insert a header if the previously inserted block is not the same
554          * as this one. This catches all the different cases:
555          */
556         if (last_contact && empathy_contact_equal (last_contact, contact)) {
557                 return;
558         }
559
560         empathy_theme_append_spacing (theme, view);
561
562         gtk_text_buffer_get_end_iter (buffer, &iter);
563         gtk_text_buffer_insert_with_tags_by_name (buffer,
564                                                   &iter,
565                                                   "\n",
566                                                   -1,
567                                                   "fancy-header-line",
568                                                   NULL);
569
570         gtk_text_buffer_get_end_iter (buffer, &iter);
571         anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
572
573         box = gtk_hbox_new (FALSE, 0);
574
575
576         if (empathy_theme_get_show_avatars (theme)) {
577                 avatar = empathy_chat_view_get_avatar_pixbuf_with_cache (contact);
578                 if (avatar) {
579                         GtkWidget *image;
580
581                         image = gtk_image_new_from_pixbuf (avatar);
582
583                         gtk_box_pack_start (GTK_BOX (box), image,
584                                             FALSE, TRUE, 2);
585                 }
586         }
587
588         g_signal_connect_object (view, "size-allocate",
589                                  G_CALLBACK (table_size_allocate_cb),
590                                  box, 0);
591
592         str = g_markup_printf_escaped ("<b>%s</b>", name);
593
594         label1 = g_object_new (GTK_TYPE_LABEL,
595                                "label", str,
596                                "use-markup", TRUE,
597                                "xalign", 0.0,
598                                NULL);
599
600         parse_success = priv->header_foreground &&
601                         gdk_color_parse (priv->header_foreground, &color);
602
603         if (parse_success) {
604                 gtk_widget_modify_fg (label1, GTK_STATE_NORMAL, &color);
605         }
606
607         g_free (str);
608
609         time = empathy_message_get_timestamp (msg);
610
611         tmp = empathy_time_to_string_local (time, 
612                                            EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
613         str = g_strdup_printf ("<i>%s</i>", tmp);
614         g_free (tmp);
615
616         label2 = g_object_new (GTK_TYPE_LABEL,
617                                "label", str,
618                                "use-markup", TRUE,
619                                "xalign", 1.0,
620                                NULL);
621         
622         if (parse_success) {
623                 gtk_widget_modify_fg (label2, GTK_STATE_NORMAL, &color);
624         }
625
626         g_free (str);
627
628         gtk_misc_set_alignment (GTK_MISC (label1), 0.0, 0.5);
629         gtk_misc_set_alignment (GTK_MISC (label2), 1.0, 0.5);
630
631         gtk_box_pack_start (GTK_BOX (box), label1, TRUE, TRUE, 0);
632         gtk_box_pack_start (GTK_BOX (box), label2, TRUE, TRUE, 0);
633
634         gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (view),
635                                            box,
636                                            anchor);
637
638         gtk_widget_show_all (box);
639
640         gtk_text_buffer_get_end_iter (buffer, &iter);
641         start = iter;
642         gtk_text_iter_backward_char (&start);
643         gtk_text_buffer_apply_tag_by_name (buffer,
644                                            "fancy-header",
645                                            &start, &iter);
646
647         gtk_text_buffer_insert_with_tags_by_name (buffer,
648                                                   &iter,
649                                                   "\n",
650                                                   -1,
651                                                   "fancy-header",
652                                                   NULL);
653
654         gtk_text_buffer_get_end_iter (buffer, &iter);
655         gtk_text_buffer_insert_with_tags_by_name (buffer,
656                                                   &iter,
657                                                   "\n",
658                                                   -1,
659                                                   "fancy-header-line",
660                                                   NULL);
661 }
662
663 static void
664 theme_boxes_append_message (EmpathyTheme        *theme,
665                             EmpathyChatView     *view,
666                             EmpathyMessage      *message)
667 {
668         EmpathyContact *sender;
669
670         empathy_theme_maybe_append_date_and_time (theme, view, message);
671         theme_boxes_maybe_append_header (theme, view, message);
672
673         sender = empathy_message_get_sender (message);
674
675         if (empathy_message_get_type (message) == EMPATHY_MESSAGE_TYPE_ACTION) {
676                 gchar *body;
677
678                 body = g_strdup_printf (" * %s %s", 
679                                         empathy_contact_get_name (sender),
680                                         empathy_message_get_body (message));
681                 empathy_theme_append_text (theme, view, body,
682                                            "fancy-action", "fancy-link");
683         } else {
684                 empathy_theme_append_text (theme, view,
685                                            empathy_message_get_body (message),
686                                            "fancy-body", "fancy-link");
687         }
688 }
689
690 static void
691 theme_boxes_append_event (EmpathyTheme        *theme,
692                           EmpathyChatView     *view,
693                           const gchar        *str)
694 {
695         GtkTextBuffer *buffer;
696         GtkTextIter    iter;
697         gchar         *msg;
698
699         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
700
701         empathy_theme_maybe_append_date_and_time (theme, view, NULL);
702
703         gtk_text_buffer_get_end_iter (buffer, &iter);
704
705         msg = g_strdup_printf (" - %s\n", str);
706
707         gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
708                                                   msg, -1,
709                                                   "fancy-event",
710                                                   NULL);
711         g_free (msg);
712 }
713
714 static void
715 theme_boxes_append_timestamp (EmpathyTheme        *theme,
716                               EmpathyChatView     *view,
717                               EmpathyMessage      *message,
718                               gboolean            show_date,
719                               gboolean            show_time)
720 {
721         GtkTextBuffer *buffer;
722         time_t         timestamp;
723         GDate         *date;
724         GtkTextIter    iter;
725         GString       *str;
726         
727         if (!show_date) {
728                 return;
729         }
730
731         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
732
733         date = empathy_message_get_date_and_time (message, &timestamp);
734
735         str = g_string_new (NULL);
736
737         if (show_time || show_date) {
738                 empathy_theme_append_spacing (theme, view);
739
740                 g_string_append (str, "- ");
741         }
742
743         if (show_date) {
744                 gchar buf[256];
745
746                 g_date_strftime (buf, 256, _("%A %d %B %Y"), date);
747                 g_string_append (str, buf);
748
749                 if (show_time) {
750                         g_string_append (str, ", ");
751                 }
752         }
753
754         g_date_free (date);
755
756         if (show_time) {
757                 gchar *tmp;
758
759                 tmp = empathy_time_to_string_local (timestamp, EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
760                 g_string_append (str, tmp);
761                 g_free (tmp);
762         }
763
764         if (show_time || show_date) {
765                 g_string_append (str, " -\n");
766
767                 gtk_text_buffer_get_end_iter (buffer, &iter);
768                 gtk_text_buffer_insert_with_tags_by_name (buffer,
769                                                           &iter,
770                                                           str->str, -1,
771                                                           "fancy-time",
772                                                           NULL);
773
774                 empathy_chat_view_set_last_timestamp (view, timestamp);
775         }
776
777         g_string_free (str, TRUE);
778         
779 }
780
781 static void
782 theme_boxes_append_spacing (EmpathyTheme        *theme,
783                             EmpathyChatView     *view)
784 {
785         GtkTextBuffer *buffer;
786         GtkTextIter    iter;
787
788         g_return_if_fail (EMPATHY_IS_THEME (theme));
789         g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
790
791         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
792
793         gtk_text_buffer_get_end_iter (buffer, &iter);
794         gtk_text_buffer_insert_with_tags_by_name (buffer,
795                                                   &iter,
796                                                   "\n",
797                                                   -1,
798                                                   "cut",
799                                                   "fancy-spacing",
800                                                   NULL);
801 }
802