~ubuntu-branches/ubuntu/vivid/sflphone/vivid

« back to all changes in this revision

Viewing changes to gnome/src/messaging/message_tab.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2013-06-30 11:40:56 UTC
  • mfrom: (4.1.18 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130630114056-0np50jkyqo6vnmii
Tags: 1.2.3-2
* changeset_r92d62cfc54732bbbcfff2b1d36c096b120b981a5.diff 
  - fixes automatic endian detection 
* Update Vcs: fixes vcs-field-not-canonical

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2012 Savoir-Faire Linux Inc.
 
3
 *  Author: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 3 of the License, or
 
8
 *  (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
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 
18
 *
 
19
 *  Additional permission under GNU GPL version 3 section 7:
 
20
 *
 
21
 *  If you modify this program, or any covered work, by linking or
 
22
 *  combining it with the OpenSSL project's OpenSSL library (or a
 
23
 *  modified version of that library), containing parts covered by the
 
24
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 
25
 *  grants you additional permission to convey the resulting work.
 
26
 *  Corresponding Source for a non-source form of such a combination
 
27
 *  shall include the source code for the parts of OpenSSL used as well
 
28
 *  as that of the covered work.
 
29
 */
 
30
#include "message_tab.h"
 
31
 
 
32
#include "../dbus/dbus.h"
 
33
#include <glib.h>
 
34
#include "../mainwindow.h"
 
35
#include <string.h>
 
36
 
 
37
static GtkWidget  *tab_box    = NULL ;
 
38
static GHashTable *tabs       = NULL ;
 
39
static GtkPaned   *paned      = NULL ;
 
40
static int        vpanes_s    = -1   ;
 
41
static int        skip_height = -3   ;
 
42
 
 
43
 
 
44
static GtkTextIter* start_link = NULL;
 
45
static GtkTextIter* end_link   = NULL;
 
46
 
 
47
/////////////////////HELPERS/////////////////////////
 
48
 
 
49
 
 
50
/*I really don't know why we need this, but without, it doesn't work*/
 
51
message_tab *
 
52
force_lookup(const gchar *id)
 
53
{
 
54
   GList *list = g_hash_table_get_keys(tabs);
 
55
   for (guint k=0;k<g_list_length(list);k++) {
 
56
      if (!strcmp(id,(gchar*)g_list_nth(list,k)->data)) {
 
57
         return g_hash_table_lookup(tabs,(const gchar*)g_list_nth(list,k)->data);
 
58
      }
 
59
   }
 
60
   return NULL;
 
61
}
 
62
 
 
63
void
 
64
disable_conference_calls(conference_obj_t *call)
 
65
{
 
66
    if (tabs) {
 
67
        guint size = g_slist_length(call->participant_list);
 
68
        for (guint i = 0; i < size;i++) {
 
69
               const gchar* id = (gchar*)g_slist_nth(call->participant_list,i)->data;
 
70
               message_tab *tab = force_lookup(id);
 
71
               if (tab)
 
72
                   gtk_widget_hide(tab->entry);
 
73
        }
 
74
    }
 
75
}
 
76
 
 
77
 
 
78
 
 
79
/////////////////////GETTERS/////////////////////////
 
80
 
 
81
GtkWidget *get_tab_box()
 
82
{
 
83
   if (!tab_box) {
 
84
      tab_box = gtk_notebook_new();
 
85
      gtk_notebook_set_scrollable(GTK_NOTEBOOK(tab_box),TRUE);
 
86
   }
 
87
   return tab_box;
 
88
}
 
89
 
 
90
 
 
91
 
 
92
/////////////////////SETTERS/////////////////////////
 
93
 
 
94
void
 
95
toggle_messaging()
 
96
{
 
97
    GtkWidget *box = get_tab_box();
 
98
    if (gtk_widget_get_visible(box))
 
99
        gtk_widget_show(box);
 
100
    else
 
101
        gtk_widget_hide(box);
 
102
}
 
103
 
 
104
 
 
105
void
 
106
show_messaging()
 
107
{
 
108
    gtk_widget_show(get_tab_box());
 
109
    if (vpanes_s > 0)
 
110
        gtk_paned_set_position(GTK_PANED(paned),vpanes_s);
 
111
}
 
112
 
 
113
void
 
114
set_message_tab_height(GtkPaned* _paned, int height)
 
115
{
 
116
   if ( skip_height >=0 || skip_height == -3 ) {
 
117
      paned    = _paned;
 
118
      vpanes_s = height;
 
119
   }
 
120
   skip_height++;
 
121
}
 
122
 
 
123
static void
 
124
append_message(message_tab* self, const gchar* name, const gchar* message)
 
125
{
 
126
    GtkTextIter current_end,new_end;
 
127
    gtk_text_buffer_get_end_iter( self->buffer, &current_end           );
 
128
    gtk_text_buffer_insert      ( self->buffer, &current_end, name, -1 );
 
129
    gtk_text_buffer_insert      ( self->buffer, &current_end, ": ", -1 );
 
130
 
 
131
    gtk_text_buffer_get_end_iter(self->buffer, &current_end);
 
132
    for (unsigned int i=0;i<strlen(name)+2;i++){
 
133
        if (!gtk_text_iter_backward_char(&current_end))
 
134
            break;
 
135
    }
 
136
 
 
137
    gtk_text_buffer_get_end_iter(self->buffer, &new_end);
 
138
    gtk_text_buffer_apply_tag_by_name(self->buffer, "b", &current_end, &new_end);
 
139
 
 
140
    gtk_text_buffer_insert      ( self->buffer, &new_end, message,    -1 );
 
141
    gtk_text_buffer_insert      ( self->buffer, &new_end, "\n"   ,    -1 );
 
142
    gtk_text_buffer_get_end_iter( self->buffer, &new_end                 );
 
143
    gtk_text_view_scroll_to_iter( self->view  , &new_end,FALSE,0,0,FALSE );
 
144
 
 
145
    start_link = NULL;
 
146
    end_link   = NULL;
 
147
}
 
148
 
 
149
//////////////////////SLOTS//////////////////////////
 
150
 
 
151
static void
 
152
on_enter(GtkEntry *entry, gpointer user_data)
 
153
{
 
154
    start_link = NULL;
 
155
    end_link   = NULL;
 
156
    message_tab *tab = (message_tab*)user_data;
 
157
    append_message(tab,(gchar*)"Me",gtk_entry_get_text(entry));
 
158
    if (tab->call)
 
159
        dbus_send_text_message(tab->call->_callID,gtk_entry_get_text(entry));
 
160
    else if (tab->conf)
 
161
        dbus_send_text_message(tab->conf->_confID,gtk_entry_get_text(entry));
 
162
    gtk_entry_set_text(entry,"");
 
163
}
 
164
 
 
165
static void
 
166
on_close(G_GNUC_UNUSED GtkWidget *button, gpointer data)
 
167
{
 
168
    message_tab *tab = (message_tab*)data;
 
169
    gtk_widget_destroy(tab->widget);
 
170
    if (tab->call)
 
171
      g_hash_table_remove(tabs,tab->call->_callID);
 
172
    else if (tab->conf)
 
173
       g_hash_table_remove(tabs,tab->conf->_confID);
 
174
}
 
175
 
 
176
static void
 
177
on_focus_in(G_GNUC_UNUSED GtkEntry *entry, G_GNUC_UNUSED gpointer user_data)
 
178
{
 
179
    main_window_pause_keygrabber(TRUE);
 
180
}
 
181
 
 
182
static void
 
183
on_focus_out(G_GNUC_UNUSED GtkEntry *entry, G_GNUC_UNUSED gpointer user_data)
 
184
{
 
185
    main_window_pause_keygrabber(FALSE);
 
186
}
 
187
 
 
188
static void
 
189
on_clicked(GtkTextBuffer *textbuffer, G_GNUC_UNUSED GtkTextIter *location, G_GNUC_UNUSED GtkTextMark *mark, SFLPhoneClient *client)
 
190
{
 
191
   if (start_link && end_link && gtk_text_iter_compare(start_link,location) <= 0 && gtk_text_iter_compare(location,end_link) <= 0) {
 
192
       gchar* text = gtk_text_buffer_get_text(textbuffer,start_link,end_link,FALSE);
 
193
       start_link = NULL;
 
194
       end_link = NULL;
 
195
       if (strlen(text)) {
 
196
           gchar* url_command = g_settings_get_string(client->settings, "messaging-url-command");
 
197
           if (!url_command || !strlen(url_command))
 
198
               url_command = g_strdup("xdg-open");
 
199
 
 
200
           const gchar* argv[] = {url_command, text, NULL};
 
201
           g_spawn_async(NULL,(gchar**)argv,NULL,G_SPAWN_SEARCH_PATH|G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL,NULL,NULL,NULL,NULL);
 
202
           gtk_text_buffer_remove_all_tags(textbuffer,start_link,end_link );
 
203
           start_link = NULL;
 
204
           end_link   = NULL;
 
205
           g_free(url_command);
 
206
       }
 
207
   }
 
208
}
 
209
 
 
210
static void
 
211
on_cursor_motion(G_GNUC_UNUSED GtkTextView *view, GdkEvent *event, gpointer data)
 
212
{
 
213
   /* Convert mouse position into text iterators*/
 
214
   gint x,y;
 
215
   GtkTextIter cursor_pos,end_iter,end_match,start_match,end_match_b,start_match_b,start_real,end_real;
 
216
   gtk_text_buffer_get_end_iter          (((message_tab*) data)->buffer, &end_iter                                                              );
 
217
   gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW(view),GTK_TEXT_WINDOW_TEXT,((GdkEventMotion*)event)->x,((GdkEventMotion*)event)->y,&x,&y);
 
218
   gtk_text_view_get_iter_at_location    (GTK_TEXT_VIEW(view),&cursor_pos,x,y                                                                   );
 
219
   gboolean ret = gtk_text_iter_backward_search(&cursor_pos," ",GTK_TEXT_SEARCH_TEXT_ONLY | GTK_TEXT_SEARCH_VISIBLE_ONLY,&start_match_b,&end_match_b,NULL);
 
220
   if ( ret ) {
 
221
        if (gtk_text_iter_forward_search(&cursor_pos," ",GTK_TEXT_SEARCH_TEXT_ONLY | GTK_TEXT_SEARCH_VISIBLE_ONLY,&start_match,&end_match,NULL)
 
222
           && gtk_text_iter_get_line(&end_match) == gtk_text_iter_get_line(&cursor_pos)) {
 
223
            start_real = end_match_b;
 
224
            end_real   = start_match;
 
225
        }
 
226
        else {
 
227
            gtk_text_iter_forward_visible_line(&cursor_pos);
 
228
            start_real = end_match_b;
 
229
            end_real   = cursor_pos ;
 
230
        }
 
231
 
 
232
        /*Get the word under cursor*/
 
233
        gchar* text = gtk_text_buffer_get_text(((message_tab*) data)->buffer,&start_real,&end_real,FALSE);
 
234
 
 
235
        /*Match the regex*/
 
236
        GError     *error          = NULL;
 
237
        gchar      *pattern_string = "^[a-z]*\\://[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,3}(/\\S*)?$";
 
238
        GRegex     *regex          = g_regex_new( pattern_string, 0, 0, &error );
 
239
        GMatchInfo *match_info     = NULL;
 
240
        GdkWindow  *win            = gtk_text_view_get_window(GTK_TEXT_VIEW(view),GTK_TEXT_WINDOW_TEXT);
 
241
 
 
242
        g_regex_match( regex, text, 0, &match_info );
 
243
        if (g_match_info_matches( match_info )) {
 
244
            /*Is a link*/
 
245
            while( g_match_info_matches( match_info ) ) {
 
246
                  g_match_info_next( match_info, &error );
 
247
                  if (gtk_text_iter_get_buffer(&start_real) == ((message_tab*) data)->buffer && gtk_text_iter_get_buffer(&end_real) == ((message_tab*) data)->buffer) {
 
248
                      gtk_text_buffer_remove_all_tags(((message_tab*) data)->buffer,&start_real, &end_real);
 
249
                      gtk_text_buffer_apply_tag_by_name(((message_tab*) data)->buffer, "link", &start_real, &end_real);
 
250
                  }
 
251
            }
 
252
            GdkCursor *cur = gdk_cursor_new(GDK_HAND2);
 
253
            start_link     = gtk_text_iter_copy(&start_real);
 
254
            end_link       = gtk_text_iter_copy(&end_real);
 
255
            gdk_window_set_cursor(win,cur);
 
256
        }
 
257
        else {
 
258
            /*Is not a link, cleaning previous link*/
 
259
            GdkCursor *cur = gdk_cursor_new(GDK_XTERM);
 
260
            gdk_window_set_cursor(win,cur);
 
261
            if (start_link && end_link && gtk_text_iter_get_buffer(start_link) == ((message_tab*) data)->buffer && gtk_text_iter_get_buffer(end_link) == ((message_tab*) data)->buffer) {
 
262
               gtk_text_buffer_remove_all_tags(((message_tab*) data)->buffer,start_link,end_link );
 
263
                /*g_free(start_link);
 
264
                g_free(end_link);*/
 
265
               start_link = NULL;
 
266
               end_link   = NULL;
 
267
            }
 
268
        }
 
269
   }
 
270
}
 
271
 
 
272
 
 
273
/////////////////////MUTATORS////////////////////////
 
274
 
 
275
void
 
276
disable_messaging_tab(const gchar * id)
 
277
{
 
278
    message_tab *tab = NULL;
 
279
    if (tabs)
 
280
        tab = g_hash_table_lookup(tabs, id);
 
281
    if (tab != NULL)
 
282
        gtk_widget_hide(tab->entry);
 
283
    if (!g_list_length(gtk_container_get_children(GTK_CONTAINER(get_tab_box()))))
 
284
       gtk_widget_hide(get_tab_box());
 
285
}
 
286
 
 
287
static message_tab *
 
288
create_messaging_tab_common(const gchar* call_id, const gchar *label, SFLPhoneClient *client)
 
289
{
 
290
    show_messaging();
 
291
    /* Do not create a new tab if it already exist */
 
292
    message_tab *tab = NULL;
 
293
    if (tabs)
 
294
        tab = g_hash_table_lookup(tabs,call_id);
 
295
    if (tab) {
 
296
       return tab;
 
297
    }
 
298
 
 
299
    message_tab *self = g_new0(message_tab, 1);
 
300
 
 
301
    /* Create the main layout */
 
302
    GtkWidget *vbox            = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 
303
    GtkTextBuffer *text_buffer = gtk_text_buffer_new(NULL);
 
304
    if (text_buffer) {
 
305
      gtk_text_buffer_create_tag(text_buffer, "b", "weight", PANGO_WEIGHT_BOLD,NULL);
 
306
      gtk_text_buffer_create_tag(text_buffer, "link", "foreground", "#0000FF","underline",PANGO_UNDERLINE_SINGLE,NULL);
 
307
    }
 
308
 
 
309
    /* Create the conversation history widget*/
 
310
    GtkWidget *history_hbox    = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2  );
 
311
    GtkWidget *h_left_spacer   = gtk_label_new ( ""                         );
 
312
    GtkWidget *h_right_spacer  = gtk_label_new ( ""                         );
 
313
    GtkWidget *scoll_area      = gtk_scrolled_window_new      ( NULL,NULL   );
 
314
    GtkWidget *text_box_widget = gtk_text_view_new_with_buffer( text_buffer );
 
315
    gtk_box_pack_start(GTK_BOX(history_hbox) , h_left_spacer  , FALSE , FALSE , 0);
 
316
    gtk_box_pack_start(GTK_BOX(history_hbox) , scoll_area     , TRUE  , TRUE  , 0);
 
317
    gtk_box_pack_start(GTK_BOX(history_hbox) , h_right_spacer , FALSE , FALSE , 0);
 
318
 
 
319
    gtk_text_view_set_editable ( GTK_TEXT_VIEW(text_box_widget),FALSE        );
 
320
    gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(text_box_widget),GTK_WRAP_CHAR);
 
321
 
 
322
    gtk_container_add(GTK_CONTAINER(scoll_area), text_box_widget);
 
323
 
 
324
    g_signal_connect(G_OBJECT(text_box_widget), "motion-notify-event" , G_CALLBACK(on_cursor_motion), self);
 
325
    g_signal_connect(G_OBJECT(text_buffer    ), "mark-set"            , G_CALLBACK(on_clicked      ), client);
 
326
 
 
327
    GtkWidget *line_edit    = gtk_entry_new (                               );
 
328
    GtkWidget *hbox         = gtk_box_new   ( GTK_ORIENTATION_HORIZONTAL, 1 );
 
329
    GtkWidget *left_spacer  = gtk_label_new ( ""                            );
 
330
    GtkWidget *right_spacer = gtk_label_new ( ""                            );
 
331
    gtk_box_pack_start(GTK_BOX(hbox) , left_spacer  , FALSE , FALSE , 0);
 
332
    gtk_box_pack_start(GTK_BOX(hbox) , line_edit    , TRUE  , TRUE  , 0);
 
333
    gtk_box_pack_start(GTK_BOX(hbox) , right_spacer , FALSE , FALSE , 0);
 
334
 
 
335
    g_signal_connect(G_OBJECT(line_edit), "activate"        , G_CALLBACK(on_enter)    , self);
 
336
    g_signal_connect(G_OBJECT(line_edit), "focus-in-event"  , G_CALLBACK(on_focus_in) , self);
 
337
    g_signal_connect(G_OBJECT(line_edit), "focus-out-event" , G_CALLBACK(on_focus_out), self);
 
338
 
 
339
    self->view   = GTK_TEXT_VIEW(text_box_widget);
 
340
    self->widget = vbox       ;
 
341
    self->buffer = text_buffer;
 
342
    self->entry  = line_edit  ;
 
343
 
 
344
    /* Setup the tab label */
 
345
    GtkWidget *tab_label        = gtk_label_new           ( label                              );
 
346
    GtkWidget *tab_label_vbox   = gtk_box_new             ( GTK_ORIENTATION_HORIZONTAL, 0      );
 
347
    GtkWidget *tab_close_button = gtk_button_new          (                                    );
 
348
    GtkWidget *button_image     = gtk_image_new_from_stock( GTK_STOCK_CLOSE,GTK_ICON_SIZE_MENU );
 
349
    gtk_box_set_spacing (GTK_BOX(tab_label_vbox),0);
 
350
 
 
351
    /*TODO make it work*/
 
352
    /*   GtkRcStyle *style = gtk_rc_style_new();
 
353
         style->xthickness = 0;
 
354
         style->ythickness = 0;
 
355
         gtk_widget_modify_style(tab_close_button,style);*/
 
356
    gtk_button_set_image(GTK_BUTTON(tab_close_button),button_image);
 
357
    g_signal_connect(G_OBJECT(tab_close_button), "clicked", G_CALLBACK(on_close), self);
 
358
 
 
359
    /* Fill the layout ans show everything */
 
360
    gtk_box_pack_start(GTK_BOX(vbox)          , history_hbox    , TRUE , TRUE , 0);
 
361
    gtk_box_pack_start(GTK_BOX(vbox)          , hbox            , FALSE, FALSE, 0);
 
362
    gtk_box_pack_start(GTK_BOX(tab_label_vbox), tab_label       , TRUE , TRUE , 0);
 
363
    gtk_box_pack_start(GTK_BOX(tab_label_vbox), tab_close_button, FALSE, FALSE, 0);
 
364
 
 
365
    gtk_widget_show (tab_label       );
 
366
    gtk_widget_show (tab_close_button);
 
367
    gtk_widget_show (tab_label_vbox  );
 
368
    gtk_widget_show (vbox            );
 
369
    gtk_widget_show (scoll_area      );
 
370
    gtk_widget_show (text_box_widget );
 
371
    gtk_widget_show (history_hbox    );
 
372
    gtk_widget_show (h_left_spacer   );
 
373
    gtk_widget_show (h_right_spacer  );
 
374
    gtk_widget_show (hbox            );
 
375
    gtk_widget_show (line_edit       );
 
376
    gtk_widget_show (left_spacer     );
 
377
    gtk_widget_show (right_spacer    );
 
378
 
 
379
    self->index = gtk_notebook_append_page(GTK_NOTEBOOK(get_tab_box()),vbox,tab_label_vbox);
 
380
    gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(get_tab_box()),vbox,TRUE);
 
381
    gtk_notebook_set_current_page(GTK_NOTEBOOK(get_tab_box()),self->index);
 
382
 
 
383
    /* Keep track of the tab */
 
384
    if (!tabs) {
 
385
      tabs = g_hash_table_new(NULL,g_str_equal);
 
386
    }
 
387
    g_hash_table_insert(tabs,(gpointer)call_id,(gpointer)self);
 
388
 
 
389
    return self;
 
390
}
 
391
 
 
392
static message_tab *
 
393
new_text_message_common(const gchar* id, const gchar* message, const gchar *name, SFLPhoneClient *client)
 
394
{
 
395
    gtk_widget_show(get_tab_box());
 
396
    message_tab *tab = NULL;
 
397
    if (tabs)
 
398
        tab = g_hash_table_lookup(tabs, id);
 
399
    if (!tab)
 
400
        tab = create_messaging_tab_common(id, name, client);
 
401
    append_message(tab, name, message);
 
402
    return tab;
 
403
}
 
404
 
 
405
void
 
406
new_text_message(callable_obj_t* call, const gchar* message, SFLPhoneClient *client)
 
407
{
 
408
    gchar* label_text;
 
409
    if (g_strcmp0(call->_display_name, "") == 0)
 
410
       label_text = call->_display_name;
 
411
    else
 
412
       label_text = "Peer";
 
413
    message_tab *tab = new_text_message_common(call->_callID, message, label_text, client);
 
414
    tab->call = call;
 
415
}
 
416
 
 
417
void
 
418
new_text_message_conf(conference_obj_t* conf, const gchar* message,const gchar* from, SFLPhoneClient *client)
 
419
{
 
420
    disable_conference_calls(conf);
 
421
    message_tab *tab = new_text_message_common(conf->_confID, message,
 
422
                                               strlen(from) ? from : "Conference", client);
 
423
    tab->conf = conf;
 
424
}
 
425
 
 
426
message_tab *
 
427
create_messaging_tab(callable_obj_t* call, SFLPhoneClient *client)
 
428
{
 
429
    const gchar *confID = dbus_get_conference_id(call->_callID);
 
430
    if (strlen(confID) > 0 && ((tabs && force_lookup(confID) == NULL) || !tabs)) {
 
431
        return create_messaging_tab_common(confID, "Conference", client);
 
432
    }
 
433
    else if (strlen(confID) > 0 && tabs) {
 
434
        return force_lookup(confID);
 
435
    }
 
436
    gchar* label_text;
 
437
    if (strcmp(call->_display_name,""))
 
438
       label_text = call->_display_name;
 
439
    else
 
440
       label_text = call->_peer_number ;
 
441
    message_tab* self = create_messaging_tab_common(call->_callID, label_text, client);
 
442
 
 
443
    self->call = call;
 
444
    self->conf = NULL;
 
445
    return self;
 
446
}
 
447
 
 
448
message_tab *
 
449
create_messaging_tab_conf(conference_obj_t* call, SFLPhoneClient *client)
 
450
{
 
451
    if (call->_confID && strlen(call->_confID)) {
 
452
        message_tab* self = create_messaging_tab_common(call->_confID, "Conference", client);
 
453
        self->conf = call;
 
454
        self->call = NULL;
 
455
        disable_conference_calls(call);
 
456
        return self;
 
457
    }
 
458
    return NULL;
 
459
}