/******************************************************************** Copyright (C) 2001 Bassoukos Tassos 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., 675 Mass Ave, Cambridge, MA 02139, USA. *********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "bookmarks.h" #include "connection.h" #include "protocol.h" #include "messages.h" #include "transaction.h" #include "guiprefs.h" #include "smalltrans.h" #include "userlist.h" #include "guiutils.h" #include "hldat.h" #include "userwidget.h" #include "users.h" #include "privs.h" #include "chat.h" #include "pixmap.h" typedef struct { Connection *c; NotebookPage *notebook_page; UserWidget *user_list; UserlistOps *usersops; GtkWidget *user_text; GtkWidget *kick_dialog; GtkWidget *messagew; ChatWindowWidgets cww; int user_status; gboolean dont_message,dont_chat; } UserNBPData; #define USERS "UserPane" static void users_add_userlist(UserNBPData *u); static void pubchat_say(ChatWindowWidgets *cww, gpointer data, int emote); static void users_destroy(GtkButton *b,gpointer data){ UserNBPData *u=(UserNBPData *)data; connection_set_data(u->c,USERS,NULL); if(u->user_list!=NULL) userwidget_destroy(u->user_list); if(u->notebook_page!=NULL) gutils_nbpage_destroy(u->notebook_page); if(u->usersops!=NULL) userlist_rm_ops(u->c,u->usersops); if(u->kick_dialog!=NULL) gtk_widget_destroy(u->kick_dialog); u->notebook_page=NULL; u->user_list=NULL; gtk_signal_disconnect_by_data(GTK_OBJECT(u->c),u); free(u); } static void users_destroy_hook(Connection *c,gpointer data){ users_destroy(NULL,data); } void user_start_message(Connection *c,int socket){ if(c!=NULL && socket!=-1) message_create_simple(c,NULL,socket,NULL); } static void users_refresh(GtkButton *b,UserNBPData *u){ userlist_refresh(u->c); } static void users_dont_message(GtkButton *b,UserNBPData *u){ u->dont_message=(u->dont_message==TRUE)?FALSE:TRUE; users_update_self(u->c); } static void users_dont_chat(GtkButton *b,UserNBPData *u){ u->dont_chat=(u->dont_chat==TRUE)?FALSE:TRUE; users_update_self(u->c); } static GnomeUIInfo users_toolbar[] = { GNOMEUIINFO_ITEM_STOCK("Close",N_("Close userlist"), users_destroy, HL_STOCK_PIXMAP_CLOSE_PAGE), GNOMEUIINFO_ITEM_STOCK("Refresh",N_("Reload the userlist"), users_refresh, HL_STOCK_PIXMAP_REFRESH), GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_ITEM_STOCK("NoChat",N_("Indicate to other people that you don't wat to participate in private chat."), users_dont_chat, HL_STOCK_PIXMAP_USER_DONT_CHAT), GNOMEUIINFO_ITEM_STOCK("NoMsg",N_("Indicate to other pople that you don't want to be messaged."), users_dont_message, HL_STOCK_PIXMAP_USER_DONT_MSG), GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_RADIOLIST(NULL), GNOMEUIINFO_END }; typedef struct { UserNBPData *u; int status; } UserStatusData; static void user_select_status(GtkWidget *w,UserStatusData *usd){ if(usd->u->user_status==usd->status) return; usd->u->user_status=usd->status; users_update_self(usd->u->c); } static void user_free_ptr(GtkObject *o,gpointer ptr){ free(ptr); } static void users_create_notebook(UserNBPData *u){ GnomeUIInfo *ui; int count,i; char **statusv,**itemv,*t; GList *gl=NULL; UserStatusData *usd; statusv=g_strsplit(user_status_list,",",-1); for(count=0;statusv[count]!=NULL;count++); ui=calloc(sizeof(GnomeUIInfo),count+2); usd=calloc(sizeof(UserStatusData),count+1); usd[0].u=u; usd[0].status=0; for(i=1;statusv[i-1]!=NULL;i++){ usd[i].u=u; usd[i].status=i; itemv=g_strsplit(statusv[i-1],":",-1); ui[i].type=GNOME_APP_UI_ITEM; ui[i].hint=NULL; ui[i].pixmap_type=GNOME_APP_PIXMAP_STOCK; ui[i].user_data=&usd[i]; ui[i].moreinfo=user_select_status; t=strdup(pixmap_ensure_stock_icon_number(atoi(itemv[1]))); g_list_prepend(gl,t); ui[i].pixmap_info=t; t=strdup(itemv[0]); g_list_prepend(gl,t); ui[i].label=t; pixmap_ensure_stock_icon_number(atoi(itemv[3])); g_strfreev(itemv); } ui[0]=ui[1]; ui[0].label=_("Normal"); ui[0].pixmap_info=pixmap_ensure_stock_icon_number(417); ui[0].user_data=usd; ui[i]=users_toolbar[7]; users_toolbar[6].moreinfo=ui; u->notebook_page=gutils_nbpage_new("Main",users_toolbar,u->c,_("Users"),"users",u); gtk_signal_connect(GTK_OBJECT(u->notebook_page->dock),"destroy", GTK_SIGNAL_FUNC(user_free_ptr),(GtkObject *)usd); gtk_signal_connect(GTK_OBJECT(u->notebook_page->dock),"destroy", GTK_SIGNAL_FUNC(user_free_ptr),(GtkObject *)ui); // free(ui); g_list_foreach(gl,(GFunc)free,NULL); g_list_free(gl); g_strfreev(statusv); } static void users_create_gui(UserNBPData *u){ if(u->notebook_page!=NULL) return; users_create_notebook(u); u->cww.user_data=u; u->cww.sendmsg=pubchat_say; chat_pane_create(u->notebook_page,&u->cww,FALSE); u->user_list=u->cww.userwidget; u->user_text=u->cww.textarea; u->messagew=u->cww.message; userwidget_lists_userlist(u->user_list); users_add_userlist(u); if(u->c->version<150){ gutils_nbpage_toolbar_set_sensitive(u->notebook_page,3,FALSE); gutils_nbpage_toolbar_set_sensitive(u->notebook_page,4,FALSE); } } static UserNBPData *users_init(Connection *c){ UserNBPData *u=(UserNBPData *)calloc(sizeof(UserNBPData),1); u->c=c; u->notebook_page=NULL; u->user_list=NULL; u->kick_dialog=NULL; u->user_text=NULL; u->messagew=NULL; u->user_status=0; u->dont_message=FALSE; u->dont_chat=FALSE; connection_set_data(c,USERS,u); gtk_signal_connect(GTK_OBJECT(c),"destroy",GTK_SIGNAL_FUNC(users_destroy_hook),u); return u; } static UserNBPData *get_uld(Connection *c){ UserNBPData *u=(UserNBPData *)connection_get_data(c,USERS); if(u==NULL) u=users_init(c); return u; } void check_users(Connection *c){ UserNBPData *u=get_uld(c); if(u==NULL) u=users_init(c); if(auto_open_userlist==TRUE) users_create_gui(u); } void show_users(Connection *c){ UserNBPData *u=(UserNBPData *)connection_get_data(c,USERS); if(u==NULL){ check_users(c); u=(UserNBPData *)connection_get_data(c,USERS); } if(u->notebook_page==NULL) users_create_gui(u); gutils_nbpage_to_front(u->notebook_page); } /* =========================== */ static void users_add(Connection *c,int sock,gpointer data){ UserNBPData *u=(UserNBPData *)data; char buf[2048]; UserlistEntry *ule=get_user_by_socket(c,sock); if(userlist_no_connect==0){ sprintf(buf,_("<< %s has connected\n"),ule->name); gtk_text_insert(GTK_TEXT(u->user_text),NULL,NULL,NULL,buf,-1); } } static void users_rm(Connection *c,int sock,gpointer data){ UserNBPData *u=(UserNBPData *)data; char buf[2048]; UserlistEntry *ule=get_user_by_socket(c,sock); if(userlist_no_connect==0){ if(ule!=NULL && ule->name!=NULL) sprintf(buf,_(">> %s has disconnected\n"),ule->name); else sprintf(buf,_(">> Socket %d has disconnected\n"),sock); gtk_text_insert(GTK_TEXT(u->user_text),NULL,NULL,NULL,buf,-1); } } static UserlistOps uops={ NULL,NULL,NULL, NULL,users_add, NULL,users_rm }; static void users_add_userlist(UserNBPData *u){ UserlistOps *up=malloc(sizeof(UserlistOps)); *up=uops; u->usersops=up; userlist_add_ops(u->c,up,u); } /* =========================== */ static void users_display_userinfo(Transaction *t,Message *m,gpointer data){ HLObject *o; if(message_is_error(m)) return; o=message_find_object(m,HLO_MESSAGE); if(o!=NULL){ string_net_to_unix(o); message_display_text(t->c,o->data.string); } } void user_query_info(Connection *c,int socket){ Transaction *t; if(c==NULL || socket==-1) return; t=transaction_new(c,HLCT_GETUSERINFO); message_add_object(t->request,create_number(HLO_SOCKET,socket)); gtk_signal_connect(GTK_OBJECT(t),"response-received", GTK_SIGNAL_FUNC(users_display_userinfo),NULL); transaction_set_error_check(t,strdup(_("Could not get user info:"))); transaction_start(t); } /* ================================== */ static void users_get_current_status(UserNBPData *ud,char **nick,int *icon){ char **statv=g_strsplit(user_status_list,",",-1); char **itv; int i,status=ud->user_status-1; for(i=0;statv[i]!=NULL;i++); if(ud->user_status==0 || status>=i){ *nick=strdup(nickname); *icon=user_icon_number; } else { itv=g_strsplit(statv[status],":",-1); *icon=atoi(itv[3]); *nick=g_strdup_printf(user_status_format,nickname,itv[2]); g_strfreev(itv); } g_strfreev(statv); } static void users_update_common(Message *m){ int val; char *nick=NULL; UserNBPData *ud=get_uld(m->c); users_get_current_status(ud,&nick,&val); message_add_object(m,create_string(HLO_NICK,nick)); free(nick); message_add_object(m,create_number(HLO_ICON,val)); val=(ud->dont_message?ULE_STATUS_NOMSG:0)|(ud->dont_chat?ULE_STATUS_NOPRIVCHAT:0); val>>=2; message_add_object(m,create_number(HLO_BAN,val)); /* FIXME: obviously the naming is wrong... */ } void users_update_self(Connection *c){ Message *m=message_new(c,HLCI_CHANGENICKICON); users_update_common(m); message_fire_and_forget(m); } void users_register_self(Connection *c){ Transaction *t=transaction_new(c,HLCT_AGREEAGREEMENT); users_update_common(t->request); transaction_add_task(t,_("Sending user info..."),HL_STOCK_PIXMAP_USERS,0.5); transaction_set_error_check(t,strdup(_("Could not set nickname:"))); transaction_start(t); } /* ================================== */ typedef struct { Connection *c; int socket; GtkWidget *kick_dialog; } UserKick; static void users_start_kickban(UserKick *uk,gboolean is_ban){ Transaction *t; if(uk->socket==-1) return; t=transaction_new(uk->c,HLCT_KICK); message_add_object(t->request,create_number(HLO_SOCKET,uk->socket)); if(is_ban==TRUE) message_add_object(t->request,create_number(HLO_BAN,1)); transaction_set_error_check(t,strdup(is_ban?_("Could not ban:"):_("Could not kick:"))); transaction_start(t); if(uk->kick_dialog!=NULL) gtk_widget_destroy(uk->kick_dialog); } static void users_do_kick(GtkWidget *widget,gpointer p){ users_start_kickban(p,FALSE); } static void users_do_ban(GtkWidget *widget,gpointer p){ users_start_kickban(p,TRUE); } void user_start_kick(Connection *c, int socket){ UserlistEntry *ule=NULL; UserKick *uk; char buf[2048]; if(socket==-1 || c==NULL) return; ule=get_user_by_socket(c,socket); if(ule==NULL) return; uk=malloc(sizeof(UserKick)); uk->c=c; uk->socket=socket; uk->kick_dialog=gnome_dialog_new(_("Kick User?"),_("Ban"),_("Kick"), GNOME_STOCK_BUTTON_CANCEL,NULL); gnome_dialog_set_parent(GNOME_DIALOG(uk->kick_dialog), GTK_WINDOW(c->gui->main_window)); gnome_dialog_button_connect_object(GNOME_DIALOG(uk->kick_dialog),2, GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(uk->kick_dialog)); gnome_dialog_button_connect(GNOME_DIALOG(uk->kick_dialog),1,users_do_kick,uk); gnome_dialog_button_connect(GNOME_DIALOG(uk->kick_dialog),0,users_do_ban,uk); gtk_signal_connect(GTK_OBJECT(uk->kick_dialog),"delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy),NULL); gtk_signal_connect_object(GTK_OBJECT(uk->kick_dialog),"destroy", GTK_SIGNAL_FUNC(free),(GtkObject *)uk); sprintf(buf,_("Kick user %s ?"),ule->name); gtk_box_pack_end(GTK_BOX(GNOME_DIALOG(uk->kick_dialog)->vbox), gtk_label_new(buf),FALSE,FALSE,0); gtk_widget_show_all(uk->kick_dialog); } /* ======================================= */ static void pubchat_say(ChatWindowWidgets *cww, gpointer data, int emote){ UserNBPData *u=data; chat_pane_send_chat(u->c,cww,NULL,emote); } void pubchat_handle_received_message(Message *m){ Connection *c=m->c; UserNBPData *u=(UserNBPData *)connection_get_data(c,USERS); if((u==NULL || u->user_text==NULL) && auto_popup_pubchat==TRUE){ show_users(c); u=(UserNBPData *)connection_get_data(c,USERS); } if(u!=NULL && u->user_text!=NULL){ play_sound(HL_SOUND_CHAT); chat_pane_handle_chat(&u->cww,m); } else { message_unref(m); } }