I've written some code for XChat, modifying the banlist code (and some related functions and definitions in other files) to allow the existing Ban List code to show Exceptions or Invitations. Unlike the newly added feature of displaying Exceptions in the Ban List with an "(EX) " prefix, my code adds an 'e' and 'I' button to the topic bar buttons and allows lists to be opened for displaying only Exceptions and Invitations, performing a check on the server's numeric 005 CHANMODES to verify that the server supports each mode.
Also, given that I added 'I' to the topic bar, I thought it necessary to change the casing of the topic bar buttons to reflect the casing of the actual channel modes ('t' instead of 'T', 'n' instead of 'N', et cetera) to make clear the difference between 'i' (Invite Only) and 'I' (Invitation List).
Compiled with GCC 4.1.2 under Ubuntu Linux, all of my new code compiles without warning or error and runs as intended.
Any comments or criticisms are welcomed.
- Code: Select all
--- xchat-2.8.4/src/common/fe.h 2007-05-20 01:07:57.000000000 -0700
+++ xchat-2.8.4p1/src/common/fe.h 2007-09-20 23:21:45.000000000 -0700
@@ -60,8 +60,8 @@
char *topic);
void fe_chan_list_end (struct server *serv);
int fe_is_banwindow (struct session *sess);
-void fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exemption);
-void fe_ban_list_end (struct session *sess, int is_exemption);
+void fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, char mode);
+void fe_ban_list_end (struct session *sess, char mode);
void fe_notify_update (char *name);
void fe_text_clear (struct session *sess);
void fe_close_window (struct session *sess);
--- xchat-2.8.4/src/common/inbound.c 2007-06-20 01:48:42.000000000 -0700
+++ xchat-2.8.4p1/src/common/inbound.c 2007-09-20 23:13:30.000000000 -0700
@@ -43,7 +43,6 @@
#include "plugin.h"
#include "xchatc.h"
-
void
clear_channel (session *sess)
{
@@ -1229,7 +1228,7 @@
}
int
-inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, int is_exemption)
+inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, char mode)
{
char *time_str = ctime (&stamp);
server *serv = sess->server;
@@ -1249,14 +1248,14 @@
{
nowindow:
/* let proto-irc.c do the 'goto def' for exemptions */
- if (is_exemption)
+ if (mode == 'I' || mode == 'e')
return FALSE;
EMIT_SIGNAL (XP_TE_BANLIST, sess, chan, mask, banner, time_str, 0);
return TRUE;
}
- fe_add_ban_list (sess, mask, banner, time_str, is_exemption);
+ fe_add_ban_list (sess, mask, banner, time_str, mode);
return TRUE;
}
--- xchat-2.8.4/src/common/inbound.h 2007-06-11 07:36:10.000000000 -0700
+++ xchat-2.8.4p1/src/common/inbound.h 2007-09-20 22:53:34.000000000 -0700
@@ -18,7 +18,7 @@
void inbound_user_info_start (session *sess, char *nick);
int inbound_user_info (session *sess, char *chan, char *user, char *host, char *servname, char *nick, char *realname, unsigned int away);
void inbound_foundip (session *sess, char *ip);
-int inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, int is_exemption);
+int inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, char mode);
void inbound_ping_reply (session *sess, char *timestring, char *from);
void inbound_nameslist (server *serv, char *chan, char *names);
int inbound_nameslist_end (server *serv, char *chan);
--- xchat-2.8.4/src/common/modes.c 2007-06-30 21:14:27.000000000 -0700
+++ xchat-2.8.4p1/src/common/modes.c 2007-09-20 23:16:29.000000000 -0700
@@ -687,6 +687,11 @@
#ifndef WIN32
serv->have_except = TRUE;
#endif
+ } else if (strcmp (word[w], "INVEX") == 0)
+ {
+#ifndef WIN32
+ serv->have_invex = TRUE;
+#endif
} else if (strncmp (word[w], "ELIST=", 6) == 0)
{
/* supports LIST >< min/max user counts? */
--- xchat-2.8.4/src/common/proto-irc.c 2007-02-12 05:36:28.000000000 -0700
+++ xchat-2.8.4p1/src/common/proto-irc.c 2007-09-21 09:45:47.000000000 -0700
@@ -620,8 +620,24 @@
}
break;
+ case 346: /* +I-list entry*/
+ if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 'I'))
+ goto def;
+ break;
+ case 347:
+ sess = find_channel (serv, word[4]);
+ if (!sess)
+ {
+ sess = serv->front_session;
+ goto def;
+ }
+ if (!fe_is_banwindow (sess))
+ goto def;
+ fe_ban_list_end (sess,'I');
+ break;
+
case 348: /* +e-list entry */
- if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], TRUE))
+ if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 'e'))
goto def;
break;
@@ -634,7 +650,7 @@
}
if (!fe_is_banwindow (sess))
goto def;
- fe_ban_list_end (sess, TRUE);
+ fe_ban_list_end (sess,'e');
break;
case 353: /* NAMES */
@@ -648,7 +664,7 @@
break;
case 367: /* banlist entry */
- inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], FALSE);
+ inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 'b');
break;
case 368:
@@ -660,7 +676,7 @@
}
if (!fe_is_banwindow (sess))
goto def;
- fe_ban_list_end (sess, FALSE);
+ fe_ban_list_end (sess,'b');
break;
case 369: /* WHOWAS end */
--- xchat-2.8.4/src/common/server.c 2007-06-18 19:02:15.000000000 -0700
+++ xchat-2.8.4p1/src/common/server.c 2007-09-20 19:27:03.000000000 -0700
@@ -1837,6 +1837,7 @@
serv->have_capab = FALSE;
serv->have_idmsg = FALSE;
serv->have_except = FALSE;
+ serv->have_invex = FALSE;
}
char *
--- xchat-2.8.4/src/common/xchat.h 2007-06-18 18:54:46.000000000 -0700
+++ xchat-2.8.4p1/src/common/xchat.h 2007-09-21 09:46:30.000000000 -0700
@@ -506,6 +506,7 @@
unsigned int have_capab:1; /* supports CAPAB (005 tells us) */
unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */
unsigned int have_except:1; /* ban exemptions +e */
+ unsigned int have_invex:1; /* invite exemptions +I */
unsigned int using_cp1255:1; /* encoding is CP1255/WINDOWS-1255? */
unsigned int using_irc:1; /* encoding is "IRC" (CP1252/UTF-8 hybrid)? */
int use_who:1; /* whether to use WHO command to get dcc_ip */
--- xchat-2.8.4/src/fe-gtk/banlist.c 2007-06-30 21:13:20.000000000 -0700
+++ xchat-2.8.4p1/src/fe-gtk/banlist.c 2007-09-21 09:49:32.000000000 -0700
@@ -67,11 +67,14 @@
}
static gboolean
-supports_exempt (server *serv)
+supports_mode (server *serv,char mode)
{
char *cm = serv->chanmodes;
- if (serv->have_except)
+ if (mode == 'b') return TRUE;
+ if (mode == 'e' && serv->have_except)
+ return TRUE;
+ if (mode == 'I' && serv->have_invex)
return TRUE;
if (!cm)
@@ -81,7 +84,7 @@
{
if (*cm == ',')
break;
- if (*cm == 'e')
+ if (*cm == mode)
return TRUE;
cm++;
}
@@ -90,29 +93,25 @@
}
void
-fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exempt)
+fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, char mode)
{
GtkListStore *store;
GtkTreeIter iter;
- char buf[512];
-
- store = get_store (sess);
- gtk_list_store_append (store, &iter);
- if (is_exempt)
- {
- snprintf (buf, sizeof (buf), "(EX) %s", mask);
- gtk_list_store_set (store, &iter, 0, buf, 1, who, 2, when, -1);
- } else
+ if (sess->res->banlist_type == mode)
{
+ store = get_store (sess);
+ gtk_list_store_append (store, &iter);
+
gtk_list_store_set (store, &iter, 0, mask, 1, who, 2, when, -1);
}
}
void
-fe_ban_list_end (struct session *sess, int is_exemption)
+fe_ban_list_end (struct session *sess,char mode)
{
- gtk_widget_set_sensitive (sess->res->banlist_butRefresh, TRUE);
+ if (sess->res->banlist_type == mode)
+ gtk_widget_set_sensitive (sess->res->banlist_butRefresh, TRUE);
}
/**
@@ -128,24 +127,19 @@
gtk_widget_set_sensitive (sess->res->banlist_butRefresh, FALSE);
- snprintf (tbuf, sizeof tbuf, "XChat: Ban List (%s, %s)",
+ snprintf (tbuf, sizeof tbuf, "XChat: %s List (%s, %s)",
+ sess->res->banlist_type == 'b'?"Ban":
+ sess->res->banlist_type == 'e'?"Exception":"Invitation",
sess->channel, sess->server->servername);
mg_set_title (sess->res->banlist_window, tbuf);
store = get_store (sess);
gtk_list_store_clear (store);
- handle_command (sess, "ban", FALSE);
-#ifdef WIN32
- if (0)
-#else
- if (supports_exempt (sess->server))
- {
-#endif
- snprintf (tbuf, sizeof (tbuf), "quote mode %s +e", sess->channel);
- handle_command (sess, tbuf, FALSE);
- }
-
+ char mode_string[64];
+ snprintf(mode_string, sizeof mode_string, "mode %s %c",
+ sess->channel,sess->res->banlist_type);
+ handle_command (sess, mode_string, FALSE);
} else
{
fe_message (_("Not connected."), FE_MSG_ERROR);
@@ -165,13 +159,13 @@
}
static int
-banlist_unban_inner (gpointer none, struct session *sess, int do_exempts)
+banlist_unban_inner (gpointer none, struct session *sess, char mode)
{
GtkTreeModel *model;
GtkTreeSelection *sel;
GtkTreeIter iter;
char tbuf[2048];
- char **masks, *tmp, *space;
+ char **masks;
int num_sel, i;
/* grab the list of selected items */
@@ -201,32 +195,13 @@
if (gtk_tree_selection_iter_is_selected (sel, &iter))
{
gtk_tree_model_get (model, &iter, MASK_COLUMN, &masks[i], -1);
- space = strchr (masks[i], ' ');
-
- if (do_exempts)
- {
- if (space)
- {
- /* remove the "(EX) " */
- tmp = masks[i];
- masks[i] = g_strdup (space + 1);
- g_free (tmp);
- i++;
- }
- } else
- {
- if (!space)
- i++;
- }
+ ++i;
}
}
while (gtk_tree_model_iter_next (model, &iter));
/* and send to server */
- if (do_exempts)
- send_channel_modes (sess, tbuf, masks, 0, i, '-', 'e', 0);
- else
- send_channel_modes (sess, tbuf, masks, 0, i, '-', 'b', 0);
+ send_channel_modes (sess, tbuf, masks, 0, i, '-', mode, 0);
/* now free everything, and refresh banlist */
for (i=0; i < num_sel; i++)
@@ -241,12 +216,15 @@
{
int num = 0;
- num += banlist_unban_inner (wid, sess, FALSE);
- num += banlist_unban_inner (wid, sess, TRUE);
+ num += banlist_unban_inner (wid, sess, sess->res->banlist_type);
if (num < 1)
{
- fe_message (_("You must select some bans."), FE_MSG_ERROR);
+ char error_str[64];
+ snprintf(error_str,sizeof error_str,"You must select some %ss.",
+ sess->res->banlist_type == 'b'?"ban":
+ sess->res->banlist_type == 'e'?"exception":"invitation");
+ fe_message (error_str, FE_MSG_ERROR);
return;
}
@@ -275,7 +253,10 @@
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
- _("Are you sure you want to remove all bans in %s?"), sess->channel);
+ "Are you sure you want to remove all %ss in %s?",
+ sess->res->banlist_type == 'e'?"exception":
+ sess->res->banlist_type == 'b'?"ban":"invitation",
+ sess->channel);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (banlist_clear_cb), sess);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
@@ -325,8 +306,13 @@
g_slist_free (list);
banlist_unban (NULL, sess);
- } else
- fe_message (_("You must select some bans."), FE_MSG_ERROR);
+ } else {
+ char error_buf[64];
+ snprintf(error_buf,sizeof error_buf,"You must select some %ss.",
+ sess->res->banlist_type == 'e'?"exception":
+ sess->res->banlist_type == 'b'?"ban":"invitation");
+ fe_message (error_buf, FE_MSG_ERROR);
+ }
}
static GtkWidget *
@@ -368,11 +354,14 @@
banlist_closegui (GtkWidget *wid, session *sess)
{
if (is_session (sess))
+ {
sess->res->banlist_window = 0;
+ sess->res->banlist_type = 0;
+ }
}
void
-banlist_opengui (struct session *sess)
+banlist_opengui (struct session *sess,char mode)
{
GtkWidget *vbox1;
GtkWidget *bbox;
@@ -386,13 +375,28 @@
if (sess->type != SESS_CHANNEL)
{
- fe_message (_("You can only open the Ban List window while in a channel tab."), FE_MSG_ERROR);
+ char error_buf[96];
+ snprintf (error_buf, sizeof error_buf,
+ "You can only open the %s List window while in a channel tab.",
+ mode=='b'?"Ban":mode=='e'?"Exception":"Invitation");
+ fe_message (error_buf, FE_MSG_ERROR);
+ return;
+ }
+
+ if (!supports_mode(sess->server,mode))
+ {
+ char error_buf[96];
+ snprintf(error_buf, sizeof error_buf,
+ "This server does not support %ss.",
+ mode == 'e'?"exception":"invitation");
+ fe_message(error_buf, FE_MSG_ERROR);
return;
}
snprintf (tbuf, sizeof tbuf, _("XChat: Ban List (%s)"),
sess->server->servername);
+ sess->res->banlist_type = mode;
sess->res->banlist_window = mg_create_generic_tab ("BanList", tbuf, FALSE,
TRUE, banlist_closegui, sess, 550, 200, &vbox1, sess->server);
--- xchat-2.8.4/src/fe-gtk/banlist.h 2002-11-28 03:41:31.000000000 -0700
+++ xchat-2.8.4p1/src/fe-gtk/banlist.h 2007-09-20 19:10:59.000000000 -0700
@@ -1 +1 @@
-void banlist_opengui (session *sess);
+void banlist_opengui (session *sess,char mode);
--- xchat-2.8.4/src/fe-gtk/fe-gtk.h 2007-06-23 07:32:19.000000000 -0700
+++ xchat-2.8.4p1/src/fe-gtk/fe-gtk.h 2007-09-21 08:44:29.000000000 -0700
@@ -36,7 +36,9 @@
#define flag_l flag_wid[6]
#define flag_k flag_wid[7]
#define flag_b flag_wid[8]
-#define NUM_FLAG_WIDS 9
+#define flag_e flag_wid[9]
+#define flag_I flag_wid[10]
+#define NUM_FLAG_WIDS 11
struct server_gui
{
@@ -92,6 +94,7 @@
typedef struct restore_gui
{
/* banlist stuff */
+ char banlist_type;
GtkWidget *banlist_window;
GtkWidget *banlist_treeview;
GtkWidget *banlist_butRefresh;
@@ -170,7 +173,6 @@
extern GdkPixmap *channelwin_pix;
extern GdkPixmap *dialogwin_pix;
-
#ifdef USE_GTKSPELL
char *SPELL_ENTRY_GET_TEXT (GtkWidget *entry);
#define SPELL_ENTRY_SET_TEXT(e,txt) gtk_text_buffer_set_text (gtk_text_view_get_buffer(GTK_TEXT_VIEW(e)),txt,-1);
--- xchat-2.8.4/src/fe-gtk/maingui.c 2007-06-23 08:54:15.000000000 -0700
+++ xchat-2.8.4p1/src/fe-gtk/maingui.c 2007-09-21 09:47:50.000000000 -0700
@@ -2006,7 +2006,11 @@
return;
sess = current_sess;
- mode = tolower ((unsigned char) flag[0]);
+ /* Ambiguous casing was made clear and tolower() was removed to allow
+ * the function to react properly to both modes
+ * 'I' (invite exception mask) and 'i' (invite only).
+ */
+ mode = ((unsigned char) flag[0]);
switch (mode)
{
@@ -2020,7 +2024,19 @@
ignore_chanmode = TRUE;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sess->gui->flag_b), FALSE);
ignore_chanmode = FALSE;
- banlist_opengui (sess);
+ banlist_opengui (sess,'b');
+ break;
+ case 'e':
+ ignore_chanmode = TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sess->gui->flag_e), FALSE);
+ ignore_chanmode = FALSE;
+ banlist_opengui (sess,'e');
+ break;
+ case 'I':
+ ignore_chanmode = TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sess->gui->flag_I), FALSE);
+ ignore_chanmode = FALSE;
+ banlist_opengui (sess,'I');
break;
default:
mg_change_flag (but, sess, mode);
@@ -2093,15 +2109,17 @@
static void
mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
{
- gui->flag_t = mg_create_flagbutton (_("Topic Protection"), box, "T");
- gui->flag_n = mg_create_flagbutton (_("No outside messages"), box, "N");
- gui->flag_s = mg_create_flagbutton (_("Secret"), box, "S");
- gui->flag_i = mg_create_flagbutton (_("Invite Only"), box, "I");
- gui->flag_p = mg_create_flagbutton (_("Private"), box, "P");
- gui->flag_m = mg_create_flagbutton (_("Moderated"), box, "M");
- gui->flag_b = mg_create_flagbutton (_("Ban List"), box, "B");
+ gui->flag_t = mg_create_flagbutton (_("Topic Protection"), box, "t");
+ gui->flag_n = mg_create_flagbutton (_("No outside messages"), box, "n");
+ gui->flag_s = mg_create_flagbutton (_("Secret"), box, "s");
+ gui->flag_i = mg_create_flagbutton (_("Invite Only"), box, "i");
+ gui->flag_p = mg_create_flagbutton (_("Private"), box, "p");
+ gui->flag_m = mg_create_flagbutton (_("Moderated"), box, "m");
+ gui->flag_b = mg_create_flagbutton (_("Ban List"), box, "b");
+ gui->flag_e = mg_create_flagbutton ("Exception List", box, "e");
+ gui->flag_I = mg_create_flagbutton ("Invitation List", box, "I");
- gui->flag_k = mg_create_flagbutton (_("Keyword"), box, "K");
+ gui->flag_k = mg_create_flagbutton (_("Keyword"), box, "k");
gui->key_entry = gtk_entry_new ();
gtk_widget_set_name (gui->key_entry, "xchat-inputbox");
gtk_entry_set_max_length (GTK_ENTRY (gui->key_entry), 16);
@@ -2113,7 +2131,7 @@
if (prefs.style_inputbox)
mg_apply_entry_style (gui->key_entry);
- gui->flag_l = mg_create_flagbutton (_("User Limit"), box, "L");
+ gui->flag_l = mg_create_flagbutton (_("User Limit"), box, "l");
gui->limit_entry = gtk_entry_new ();
gtk_widget_set_name (gui->limit_entry, "xchat-inputbox");
gtk_entry_set_max_length (GTK_ENTRY (gui->limit_entry), 10);
--- xchat-2.8.4/src/fe-gtk/menu.c 2007-06-30 01:07:14.000000000 -0700
+++ xchat-2.8.4p1/src/fe-gtk/menu.c 2007-09-20 23:35:12.000000000 -0700
@@ -1143,7 +1143,19 @@
static void
menu_banlist (GtkWidget * wid, gpointer none)
{
- banlist_opengui (current_sess);
+ banlist_opengui (current_sess,'b');
+}
+
+static void
+menu_exclist (GtkWidget * wid, gpointer none)
+{
+ banlist_opengui (current_sess,'e');
+}
+
+static void
+menu_invlist (GtkWidget * wid, gpointer none)
+{
+ banlist_opengui (current_sess,'I');
}
#ifdef USE_PLUGIN
@@ -1459,8 +1471,10 @@
{N_("Channel List..."), menu_chanlist, 0, M_MENUITEM, 0, 0, 1},
{N_("Character Chart..."), ascii_open, 0, M_MENUITEM, 0, 0, 1},
{N_("Direct Chat..."), menu_dcc_chat_win, 0, M_MENUITEM, 0, 0, 1},
+ { "Exception List...", menu_exclist, 0, M_MENUITEM, 0, 0, 1},
{N_("File Transfers..."), menu_dcc_win, 0, M_MENUITEM, 0, 0, 1},
{N_("Ignore List..."), ignore_gui_open, 0, M_MENUITEM, 0, 0, 1},
+ { "Invitation List...", menu_invlist, 0, M_MENUITEM, 0, 0, 1},
{N_("Notify List..."), notify_opengui, 0, M_MENUITEM, 0, 0, 1},
{N_("Plugins and Scripts..."), menu_pluginlist, 0, M_MENUITEM, 0, 0, 1},
{N_("Raw Log..."), menu_rawlog, 0, M_MENUITEM, 0, 0, 1}, /* 62 */