/* Silky - A GTK+ client for SILC. Copyright (C) 2003, 2004, 2005 Toni Willberg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA http://silky.sourceforge.net/ */ #include #include #include #include #ifdef HAVE_CONFIG_H # include #endif #include "ui_channel.h" #include "support.h" #include "preferences.h" #include "gui.h" #include "log.h" #include "common.h" #include "callbacks.h" #include "ui_query.h" /* FIXME: this shouldn't be needed */ #include "ui_buddylist.h" extern GladeXML *xmlmain; extern SilkyChannel *channel_active; /* from channel.c */ extern silkyStruct *silky; /* this re-orders nicklist, using current GTK sort settings for this widget */ void refresh_gui_nicklist(SilkyChannel *channel) { GtkTreeView *treeview = GTK_TREE_VIEW(glade_xml_get_widget(channel->glade_xml, "nicktreeview")); GtkTreeModel *sorted_nicklist = gtk_tree_view_get_model(treeview); gint colid = 0; GtkSortType order; populate_gui_nicklist(channel); /* get current sort settings */ if( !gtk_tree_sortable_get_sort_column_id( GTK_TREE_SORTABLE(sorted_nicklist), &colid, &order) ) { debug("Couldn't get sort column id and order of nicklist."); debug_info("Re-ordering nicklist with default sort settings."); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(sorted_nicklist), USERLIST_COL_NICKNAME, GTK_SORT_ASCENDING); return; } debug("Re-ordering nicklist."); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(sorted_nicklist), colid, order); } /* this reads channel->members linked list and populates GUI nicklist accordingly */ /* - we'll sort it later */ void populate_gui_nicklist(SilkyChannel *channel) { GtkTreeView *treeview = GTK_TREE_VIEW(glade_xml_get_widget(channel->glade_xml, "nicktreeview")); GtkTreeModel *sn = gtk_tree_view_get_model(treeview); GtkListStore *liststore = GTK_LIST_STORE(gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(sn))); GtkWidget *usercount_label = glade_xml_get_widget(channel->glade_xml, "channel_usercount"); GtkTreeIter iter; SilkyChannelMember *ch; guint usercount = 0; /* first we clear the nicklist liststore... */ gtk_list_store_clear(liststore); /* ...and now let's start filling it anew */ for( ch = channel->members; ch; ch = ch->next ) { debug("Adding '%s' to nicklist.", CHMEMBER_NAME(ch)); gtk_list_store_append(liststore, &iter); /* founder column */ if( IS_CHANNEL_FOUNDER(ch) ) gtk_list_store_set(liststore, &iter, USERLIST_COL_FOUNDER, "*", -1); /* if muted, let's use the same column, for founders cannot be muted */ if( IS_CHANNEL_MUTED(ch) ) gtk_list_store_set(liststore, &iter, USERLIST_COL_FOUNDER, "&", -1); /* chanop column */ if( IS_CHANNEL_OP(ch) ) gtk_list_store_set(liststore, &iter, USERLIST_COL_CHANOP, "@", -1); /* nickname column */ gtk_list_store_set(liststore, &iter, USERLIST_COL_NICKNAME, CHMEMBER_NAME(ch), -1); /* clientid column (soon to be removed, redundant) */ gtk_list_store_set(liststore, &iter, USERLIST_COL_CLIENTID, ch->chuser->client->id, -1); usercount++; } gtk_label_set_text(GTK_LABEL(usercount_label), g_strdup_printf(ngettext("%d user", "%d users", usercount), usercount)); } /* This sets the colors to the nicklist widget. */ void silky_colorize_nicklist (GtkWidget *treeview) { gchar *value; GdkColor gdkcolor; debug("colorizing"); /* set BACKGROUND COLOR of the userlist */ value = prefs_get("color_background"); if (value && strlen(value) > 1 && strcmp("default", value) ) { gdk_color_parse(value, &gdkcolor); /* parse background color */ } else { gdk_color_parse("#ffffff", &gdkcolor); /* set default bgcolor to white */ } debug("setting channel nicklist's background color to '%s'", value); gtk_widget_modify_base(GTK_WIDGET(treeview), GTK_STATE_NORMAL, &gdkcolor); /* set color */ /* set FOREGROUND COLOR of the userlist, use color_text */ value = prefs_get("color_text"); if (value && strlen(value) > 1 && strcmp("default", value) ) { gdk_color_parse(value, &gdkcolor); /* parse background color */ debug("setting channel nicklist's foreground color to '%s'", value); } else { gdk_color_parse("#ffffff", &gdkcolor); /* set default bgcolor to white */ } gtk_widget_modify_text(GTK_WIDGET(treeview), GTK_STATE_NORMAL, &gdkcolor); /* set color */ return; } /******************** TAB COMPLETION ************************/ void channel_tab_completion( void ) { GtkEntry *inmes = GTK_ENTRY(glade_xml_get_widget( xmlmain, "inputbox" )); SilkyChannelMember *m = NULL; gchar *text, *ch; if( !channel_active ) { debug("Active tab is not a channel tab."); return; } /* only read prefix once */ if( !channel_active->tab_prefix ) { text = g_strdup(gtk_entry_get_text(inmes)); /* let's find space or start of string */ for( ch = g_utf8_offset_to_pointer(text, g_utf8_strlen(text, -1)); !g_unichar_isspace(g_utf8_get_char(ch)) && (ch = g_utf8_find_prev_char(text, ch)); ); /* now separate last "word" and put rest into prefix */ channel_active->tab_text = g_strndup(text, g_utf8_pointer_to_offset(text, ch)); if( channel_active->tab_text && g_utf8_strlen(channel_active->tab_text, -1) ) channel_active->tab_prefix = g_strdup(g_utf8_next_char(ch)); else channel_active->tab_prefix = g_strdup(text); g_free(text); /* we do not need this anymore */ } /* tab_prefix and tab_text should not be NULL for code further below */ if( !channel_active->tab_prefix ) channel_active->tab_prefix = g_strdup(""); if( !channel_active->tab_text ) channel_active->tab_text = g_strdup(""); /* make a foobar (SilkyChannelMember) with ->next pointing to start of memberlist, so we can start with ->next in both cases (first tab press or consequent tab presses */ if( !channel_active->tab_member ) { channel_active->tab_member = malloc(sizeof(SilkyChannelMember)); channel_active->tab_member->next = channel_active->members; } for( m = channel_active->tab_member->next; m; m = m->next ) { debug("Trying nick: '%s' against prefix '%s'", CHMEMBER_NAME(m), channel_active->tab_prefix); if( !g_utf8_collate(g_utf8_casefold(channel_active->tab_prefix, g_utf8_strlen(channel_active->tab_prefix, -1)), g_utf8_casefold(CHMEMBER_NAME(m), g_utf8_strlen(channel_active->tab_prefix, -1)) ) ) { debug("Found next suitable nick: '%s'", CHMEMBER_NAME(m)); channel_active->tab_member = m; if( g_utf8_strlen(channel_active->tab_text, -1) ) gtk_entry_set_text(inmes, g_strdup_printf("%s %s", channel_active->tab_text, CHMEMBER_NAME(m))); else gtk_entry_set_text(inmes, g_strdup_printf("%s: ", CHMEMBER_NAME(m))); return; } } channel_active->tab_member = NULL; } void channel_reset_tab_completion( void ) { if( !channel_active ) return; channel_active->tab_member = NULL; channel_active->tab_prefix = NULL; channel_active->tab_text = NULL; } /* Set back the original string to the ui. When user typed new topic, but lost focus and didn't press the button. */ gboolean on_topic_restore(GtkWidget *widget, gpointer user_data) { GtkWidget *wid_channel_topic; GtkWidget *topicbutton; SilcChannelEntry channel_entry; gchar *channel_name; return FALSE; /* FIXME: see how to reorder signals, this should be called AFTER on_topic is called. DISABLED NOW. */ channel_name = get_active_channel_name(); channel_entry = silc_client_get_channel(silky->client, silky->conn, channel_name); if (!channel_entry) { debug("didn't get channel_entry!"); return FALSE; /* =don't let gtk proceed */ } topicbutton = get_stored_channel_widget(channel_entry->channel_name, "button_change_topic"); if (!GTK_WIDGET_HAS_FOCUS(widget)) { /* .glade points to topic button */ debug("nothing to do as user pressed the button"); return FALSE; /* user pressed topic change button, tell gtk to go there */ } debug("restoring original topic"); wid_channel_topic = get_stored_channel_widget(channel_entry->channel_name, "channeltopic"); /* restore the old topic to UI */ gtk_entry_set_text(GTK_ENTRY(wid_channel_topic), channel_entry->topic); return FALSE; } /* when user changes the topic in the GUI */ gboolean on_topic(GtkWidget *widget, gpointer user_data) { const gchar *topic; gchar *channel_name; gboolean ret; SilcChannelEntry channel_entry; GtkWidget *wid_channel_topic; debug("on_topic()"); /* figure out the active channel */ channel_name = get_active_channel_name(); channel_entry = silc_client_get_channel(silky->client, silky->conn, channel_name); if (!channel_entry) { debug("didn't get channel_entry!"); return FALSE; } wid_channel_topic = get_stored_channel_widget(channel_entry->channel_name, "channeltopic"); topic = gtk_entry_get_text(GTK_ENTRY(wid_channel_topic)); debug("old topic: '%s', new topic: '%s'", channel_entry->topic, topic); if (channel_entry->topic && !strcmp(topic, channel_entry->topic)) { debug("topic not changed"); wid_channel_topic = get_stored_channel_widget(channel_entry->channel_name, "channeltopic"); gtk_entry_set_text(GTK_ENTRY(wid_channel_topic), channel_entry->topic); /* restore original string, just to be sure */ return FALSE; } else { gtk_entry_set_text(GTK_ENTRY(wid_channel_topic), topic); /* set new string to UI, ugly but required hack */ } ret = silc_client_command_call(silky->client, silky->conn, NULL, "TOPIC", channel_name, topic, NULL); if (ret == FALSE) { debug("\terror"); return FALSE; } else { debug("\tcommand sent successfully"); } /* set focus to inputbox */ gtk_window_set_focus(GTK_WINDOW(glade_xml_get_widget( xmlmain, "window_main" )), glade_xml_get_widget( xmlmain, "inputbox" )); return FALSE; } /* Get Channel Name of the active channel, if any FIXME: this shouldn't be needed anymore */ char * get_active_channel_name (void) { GtkNotebook *storednotebook; GtkWidget *active_page; gchar *channel_name; /* where are the names stored... */ storednotebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs")); if (!storednotebook) { debug("can not find storednotebook, returning NULL"); return NULL; } /* get active page entry */ active_page = gtk_notebook_get_nth_page(storednotebook, gtk_notebook_get_current_page(GTK_NOTEBOOK(storednotebook)) ); if (active_page == 0) /* if on console tab */ { debug("no console tab, returning NULL"); return NULL; } /* get name of the channel from active_page object */ channel_name = g_object_get_data(G_OBJECT(active_page), "channel_name"); if (!channel_name) { debug("didn't get channel_name, returning NULL"); return NULL; } debug("found active channel: '%s'", channel_name); return channel_name; } /* Get Channel ID of the active channel, if any */ SilcChannelID * get_active_channel_id (void) { GtkNotebook *storednotebook; GtkWidget *active_page; SilcChannelID *channel_id; debug("get_active_channel_id ()"); /* where are the names stored... */ storednotebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs")); if (!storednotebook) { debug("Did not get stored notebook"); return NULL; } /* get active page entry */ active_page = gtk_notebook_get_nth_page(storednotebook, gtk_notebook_get_current_page(GTK_NOTEBOOK(storednotebook)) ); if(!active_page) { debug("Did not get active page..."); return NULL; } /* get name of the channel from active_page object */ channel_id = g_object_get_data(G_OBJECT(active_page), "channel_id"); if (!channel_id) { debug("Did not get channel_id from active page"); return NULL; } debug ("\treturning channel_id"); return channel_id; } /* get stored channel widget from notebook by channel name FIXME: this shouldn't be necessary anymore*/ GtkWidget * get_stored_channel_widget (const char *channel_name, const char *widget_name) { GtkNotebook *storednotebook; GtkWidget *stored_channel_widget; GladeXML *stored_channel_xml; GtkWidget *stored_widget; debug("get_stored_channel_widget('%s', '%s')", channel_name, widget_name); /* get notebook widget */ storednotebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs")); /* get channel widget by channel_name */ stored_channel_widget = g_object_get_data(G_OBJECT(storednotebook), channel_name); if (!stored_channel_widget) { debug("no stored channel widget found, not on active channel"); printconsole(_("You are not on any channel.")); return NULL; } stored_channel_xml = glade_get_widget_tree(stored_channel_widget); stored_widget = glade_xml_get_widget (stored_channel_xml, widget_name); return stored_widget; } /* get stored channel "window" widget from notebook by channel name */ GtkWidget * get_stored_channel_window (const char *channel_name) { GtkNotebook *notebook; GtkWidget *page; notebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs")); page = g_object_get_data(G_OBJECT(notebook), channel_name); return page; } /* this prints given message to the CHANNEL tab, non-mime message */ int printchannel (const char *channel_name, const char *str) { GtkTextView *textview; GtkTextBuffer *buffer; gchar *timestamp; gchar *outstring; GtkTextIter iter; /* pointer to current location */ /* make sure it was utf8 */ if (!g_utf8_validate(str, -1, NULL)) { debug("Found non-utf8 string: '%s'", str); str = g_strdup(_("Non-unicode string received. Cannot display.")); } textview = GTK_TEXT_VIEW(get_stored_channel_widget(channel_name, "textviewwidget")); buffer = gtk_text_view_get_buffer(textview); if (!buffer) { debug("Can not find text buffer!"); return FALSE; } timestamp = utf_timestamp(); outstring = g_strdup_printf("[%s] %s\n", timestamp, str); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, outstring, -1, "message", NULL); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, "end_mark", &iter, FALSE); gtk_text_view_scroll_to_mark(textview, gtk_text_buffer_get_mark(buffer, "end_mark"), 0.1, FALSE, 0,1); g_free(timestamp); g_free(outstring); return TRUE; } /* prints stuff to channel, FIXME: rewrite this */ int print_mime_to_channel (SilcClientEntry client_entry, const char *channel_name, int message_signed, const gchar *content_type, ...) { gchar *nick_name; GtkTextView *textview; GtkTextBuffer *buffer = NULL; GtkTextIter iter; GtkScrolledWindow *swindow; GtkAdjustment *vadjustment; SilkyChannel *ch; /* fixme; should get ch as input, not channel_name */ unsigned char *message; int flags; unsigned char *mime_data_buffer; int mime_data_len; gchar *txt = NULL; va_list va; gchar *timestamp; gchar *outstring; GdkPixbufLoader *loader; GError *err; GdkPixbuf *pixbuf; /* strdup because modified here */ gchar *hilightwords = g_strdup( prefs_get("highlight_words") ); debug("print_mime_to_channel()"); /* get ch */ ch = channel_find_by_name(g_strdup(channel_name)); if (!content_type) { debug("content-type was null, aborting"); return FALSE; } nick_name = client_entry->nickname; textview = GTK_TEXT_VIEW(get_stored_channel_widget(channel_name, "textviewwidget")); if (!textview) { debug("didn't find textview for channel '%s'", channel_name); return FALSE; } /* get text buffer for output */ buffer = gtk_text_view_get_buffer(textview); if (!buffer) { debug("Can not find text buffer for channel '%s'", channel_name); return FALSE; } swindow = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(textview))); vadjustment = gtk_scrolled_window_get_vadjustment( swindow ); /* get end position for printing */ gtk_text_buffer_get_end_iter(buffer, &iter); va_start(va, content_type); /* last named argument before ... */ /* handle TYPE text/plain */ if (!strcmp(content_type, "text/plain")) { debug("content-type: '%s'", content_type); flags = va_arg(va, int); message = va_arg(va, unsigned char *); /* make sure it was utf8 */ if (!g_utf8_validate(message, -1, NULL)) { debug("Found non-utf8 string, can not display: '%s'", message); message = g_strdup(_("Non-unicode string received. Cannot display.")); } /* timestamp */ timestamp = utf_timestamp(); outstring = g_strdup_printf("[%s] ", timestamp); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, outstring, -1, "timestamp", NULL); /* set action flags to tabs */ if (g_pattern_match_simple(g_strconcat("*", silky->conn->local_entry->nickname, "*", NULL), message)) { debug("* my nick match"); hilight_channel_window_by_ch(ch, HILIGHT_NICK); } else if (g_pattern_match_simple(g_strconcat("*", hilightwords, "*", NULL), message)) { debug("* hilight wordlist match"); hilight_channel_window_by_ch(ch, HILIGHT_WORD); } else { hilight_channel_window_by_ch(ch, HILIGHT_SPEECH); } /* */ if ( client_entry->id == silky->conn->local_entry->id) { /* myself */ /* signed [S] */ if (flags & SILC_MESSAGE_FLAG_SIGNED) { gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "[S]", -1, "nickname-own", NULL); } if (flags & SILC_MESSAGE_FLAG_ACTION) { /* action */ gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "* ", -1, "nickname-own", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, nick_name, -1, "nickname-own", "context-nick", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, " ", -1, "nickname-own", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "action-own", NULL); } else { /* normal message */ gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "<", -1, "nickname-own", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, nick_name, -1, "nickname-own", "context-nick", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "> ", -1, "nickname-own", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "message-own", NULL); } } else { /* */ /* signed [?,S,F] unknown signature, signed and verified, failed to verify */ if (flags & SILC_MESSAGE_FLAG_SIGNED) { txt = g_strdup_printf("[%c]", (message_signed == 0 ? 'S' : (message_signed == 1 ? '?' : 'F'))); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, txt, -1, "nickname", NULL); } if ((flags & SILC_MESSAGE_FLAG_ACTION)) { /* action */ gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "* ", -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, nick_name, -1, "nickname", "context-nick", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, " ", -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "action", NULL); } else { /* normal message */ gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "<", -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, nick_name, -1, "nickname", "context-nick", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "> ", -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "message", NULL); } } gtk_text_buffer_insert (buffer, &iter, "\n", -1); } /* handle type image/anything */ if (!strcmp(content_type, "image/gif") || !strcmp(content_type, "image/png") || !strcmp(content_type, "image/jpeg")) { debug("content-type: '%s'", content_type); mime_data_buffer = va_arg(va, unsigned char *); mime_data_len = va_arg(va, int); debug("datalen: '%d'", mime_data_len); loader = gdk_pixbuf_loader_new (); err = NULL; /* this gives a warning but works?! */ if (!gdk_pixbuf_loader_write (loader, mime_data_buffer, mime_data_len, &err)) { if (err) { debug ("Unable to load pixbuf data, error: '%s'", err->message); } else { debug("Unable to load pixbuf data, no error!"); } } if (!gdk_pixbuf_loader_close (loader, &err)) { if (err) { debug ("Unable to close pixbuf, error: '%s'", err->message); } else { debug("Unable to close pixbuf, no error!"); } } pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); g_object_ref (pixbuf); g_object_unref (loader); /* insert nickname */ gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "<", -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, nick_name, -1, "nickname", NULL); gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, ">", -1, "nickname", NULL); /* insert the image and a newline*/ gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf); gtk_text_buffer_insert (buffer, &iter, "", -1); } va_end(va); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, "end_mark", &iter, FALSE); /* scroll to end only if we were already at the end before printing, this avoids scrolling when user is reading backlog */ if (vadjustment->upper - vadjustment->page_size == vadjustment->value) { gtk_text_view_scroll_to_mark(textview, gtk_text_buffer_get_mark(buffer, "end_mark"), 0.1, FALSE, 0, 1); } return 1; } void error_no_channel_oper_priv (gchar *channel_name) { printchannel(channel_name, g_strdup_printf(_("Permission denied. You are not channel operator of channel '%s'."), channel_name) ); } void error_no_channel_founder_priv (gchar *channel_name) { printchannel(channel_name, g_strdup_printf(_("Permission denied. You are not channel founder of channel '%s'."), channel_name) ); } void error_user_not_on_channel (gchar *channel_name) { printchannel(channel_name, g_strdup_printf(_("User is not on channel '%s'."), channel_name) ); } /* sets channel mode widgets */ gchar * set_cmode_window_widgets (gchar *channel_name, SilcUInt32 mode) { GtkToggleButton *toggle_button; gchar *str_mode; debug("cmode for '%s'", channel_name); /* set all modes cleared */ str_mode = g_strdup(""); /* clear dynamic string */ if (mode == SILC_CHANNEL_MODE_NONE) { str_mode = g_strdup("none"); } /* Check mode and construct str_mode string accordingly. Also TOGGLE togglebutton widgets in the channel */ toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_private")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_PRIVATE) { str_mode = g_strconcat(str_mode, "p", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); /* button down */ } else { gtk_toggle_button_set_active(toggle_button, FALSE); /* button up */ } /* CMODE TOPIC */ debug("BEFORE"); toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_topic")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_TOPIC) { str_mode = g_strconcat(str_mode, "t", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } debug("AFTER"); /* CMODE SECRET */ toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_secret")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_SECRET) { str_mode = g_strconcat(str_mode, "s", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } /* CMODE PRIVKEY */ /* toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_privkey")); if (mode & SILC_CHANNEL_MODE_PRIVKEY) { str_mode = g_strconcat(str_mode, "k", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } */ /* CMODE INVITE */ toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_invite")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_INVITE) { str_mode = g_strconcat(str_mode, "i", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } /* CMODE ULIMIT */ /* toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_ulimit")); if (mode & SILC_CHANNEL_MODE_ULIMIT) { str_mode = g_strconcat(str_mode, "l", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } */ /* CMODE PASSPHRASE */ /* toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_passphrase")); if (mode & SILC_CHANNEL_MODE_PASSPHRASE) { str_mode = g_strconcat(str_mode, "a", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } */ /* CMODE SILENCE_USERS */ toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_umute")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) { str_mode = g_strconcat(str_mode, "m", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } /* CMODE SILENCE_OPERS */ toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_omute")); /* get toggle button */ if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) { str_mode = g_strconcat(str_mode, "M", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } /* CMODE FOUNDER_AUTH */ /* toggle_button = GTK_TOGGLE_BUTTON(get_stored_channel_widget(channel_name, "cmode_founder")); if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { str_mode = g_strconcat(str_mode, "f", NULL); gtk_toggle_button_set_active(toggle_button, TRUE); } else { gtk_toggle_button_set_active(toggle_button, FALSE); } */ return str_mode; } /* user clicked a nick from userlist with left mousebutton. */ void on_nicklist_selected (GtkTreeSelection *selection, gpointer data) { GtkTreeIter iter; GtkTreeModel *model; gchar *nickname; SilcClientID *clientid; debug("on_nicklist_selected()"); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, USERLIST_COL_NICKNAME, &nickname, -1); gtk_tree_model_get (model, &iter, USERLIST_COL_CLIENTID, &clientid, -1); debug ("You selected '%s' ", nickname); g_free (nickname); } return; } void on_nicklist_activated (GtkTreeView *treeview, GtkTreePath *treepath, GtkTreeViewColumn *column, gpointer user_data) { GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(treeview); gchar *nickname; SilcClientID *clientid; SilcClientEntry cliententry; model = gtk_tree_view_get_model(treeview); gtk_tree_model_get_iter(model, &iter, treepath); debug("on_nicklist_activated()"); gtk_tree_model_get (model, &iter, USERLIST_COL_NICKNAME, &nickname, -1); gtk_tree_model_get (model, &iter, USERLIST_COL_CLIENTID, &clientid, -1); if (!clientid) { debug("Did not get clientid at on_nicklist_activated"); return; } if(SILC_ID_CLIENT_COMPARE(clientid, silky->conn->local_entry->id)) { debug("\tI won't talk to myself. Sorry."); printconsole(_("You do not want to talk to yourself.")); return; } cliententry = silc_client_get_client_by_id(silky->client, silky->conn, clientid); if (!cliententry) { debug("Did not get cliententry at on_nicklist_activated() "); return; } /* this opens new query window if no existing is open for the same clientid */ get_query_window(clientid); /* set focus to inputbox of the main window*/ gtk_widget_grab_focus(glade_xml_get_widget (xmlmain, "inputbox")); return; } /* Pops up a menu over nicklist when user presses right mousebutton . The menu object is created in silccallbacks.c */ gint on_nick_pressed (GtkTreeView *treeview, GdkEventButton *event) { GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; gchar *nickname; SilcClientID *clientid; GtkMenu *menu; GtkWidget *menuitem; debug("on_nick_pressed() button: %d", event->button); if (event->button == 3) { /* Get selected item from the nicklist */ selection = gtk_tree_view_get_selection(treeview); /* popup the menu only if something was selected */ if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, USERLIST_COL_NICKNAME, &nickname, -1); gtk_tree_model_get (model, &iter, USERLIST_COL_CLIENTID, &clientid, -1); debug ("You opened menu for '%s'", nickname); /* create the menu */ menu = GTK_MENU(gtk_menu_new()); /* ADD MENU items and signal handlers*/ /* WHOIS */ menuitem = gtk_menu_item_new_with_label(_("Who is")); g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_whois), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show (menuitem); /* send a message */ menuitem = gtk_menu_item_new_with_label(_("Send message")); g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_query), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show (menuitem); /* add to buddylist */ menuitem = gtk_menu_item_new_with_label(_("Add Buddy")); g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_buddy_add), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show (menuitem); /* a separator here */ menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* cumode +o user */ menuitem = gtk_menu_item_new_with_label(_("Op")); g_object_set_data(G_OBJECT(menuitem), "SILC_COMMAND_CUMODE", "+o"); /* op */ g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_cumode), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* cumode -o user */ menuitem = gtk_menu_item_new_with_label(_("Deop")); g_object_set_data(G_OBJECT(menuitem), "SILC_COMMAND_CUMODE", "-o"); /* deop */ g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_cumode), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* cumode +q user */ menuitem = gtk_menu_item_new_with_label(_("Mute")); g_object_set_data(G_OBJECT(menuitem), "SILC_COMMAND_CUMODE", "+q"); /* mute */ g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_cumode), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* cumode -q user */ menuitem = gtk_menu_item_new_with_label(_("Unmute")); g_object_set_data(G_OBJECT(menuitem), "SILC_COMMAND_CUMODE", "-q"); /* unmute */ g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_cumode), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* a separator here */ menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* kick user */ menuitem = gtk_menu_item_new_with_label(_("Kick")); g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_kick), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); /* kill user */ /* FIXME, the on_command_kill needs some work menuitem = gtk_menu_item_new_with_label(_("Kill")); g_signal_connect(menuitem, "activate", G_CALLBACK(on_command_kill), clientid); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show(menuitem); */ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time); } } return FALSE; }