/*
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 <gtk/gtk.h>
#include <glade/glade.h>
#include <silcincludes.h>
#include <silcclient.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#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);
}
/* <mynickname> */
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 { /* <someone 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;
}
syntax highlighted by Code2HTML, v. 0.9.1