mirror of
https://github.com/moparisthebest/hexchat
synced 2024-11-29 20:52:16 -05:00
This is a combination of 18 commits. The first commit's message is: Here is the initial banlist branch of RichardHitt/hexchat. Changed files are only src/fe-gtk/{banlist.c,fe-gtk.h}. This version works and contains my first efforts at selective sensitization of radio buttons and control buttons. From this point I intend to undertake a stepwise redesign. Step 1 will be to make the existing banlist code work for multiple simultaneous banlist windows (for different channels, obviously). It will be a hackathon with the only goal of getting it working. Step 2 will be the objectization and alpha-stage tidying-up of all the terrible looking stuff I will have done in Step 1. This is the 2nd commit message: Here's the post-Step-1 commit. It works for multiple banlist windows. Note particularly what I've done to banlist.h. Note that for many functions in banlist.c the argument is now a banlist_info *, rather than a session *. Note in banlist.c the initialization of array modes[] which contains driving information for the checkboxes. Of course those checkboxes aren't yet implemented. Maybe in Step 2 I will change to checkboxes from radio buttons; but definitely I will change to letting modes[] drive processing. This is the 3rd commit message: Converted to checkboxes. Much additional work. Note that the infrastructure for Auto-invite is not yet present in the hexchat tree. I'm nearly done with banlist, I think! This is the 4th commit message: Fleshed out 'invite'. Tagged masks uniformly, e.g. (b) (e) (I). General cleanup, nearly at the point of beta quality. This is the 5th commit message: Added fourth mode type: quiet. Did lots and lots of cleanup. Beta-ready? This is the 6th commit message: Get the banlist timestamps properly sortable. This is the 7th commit message: Redesign the supports_foo() routines. Now they're responsible for setting the flags in ->capable, ->readable, ->writeable. This is the 8th commit message: Deleted a couple of RBH comments. This is the 9th commit message: Now the ESC key will close the banlist window. This is the 10th commit message: Fix the fe-text occurrence of fe_add_ban_list(). This is the 11th commit message: Fixed also fe_ban_list_end() and removed fe_is_banwindow(). This is the 12th commit message: Use old-style initialization for array of structures modes[] This is the 13th commit message: Oops, incomplete regression of modes[] initialization. This fixes. This is the 14th commit message: Fixed strptime buy implementing a special version here. Fixed column width concerns by setting resizable and autosize. This is the 15th commit message: Get rid of testing line. This is the 16th commit message: Changed to gtkutil_destroy_on_esc () This is the 17th commit message: Remove no-longer-used functnion This is the 18th commit message: Minor cleanups to banlist.c, banlist.h Please enter the commit message for your changes. Lines starting with '#' will be ignored, and an empty message aborts the commit. Author: RichardHitt <rbh00@netcom.com> Committer: Richard Hitt <rbh00@f17.rbh00.pacbell.net> Not currently on any branch. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: src/common/fe.h modified: src/common/hexchat.h modified: src/common/inbound.c modified: src/common/modes.c modified: src/common/proto-irc.c modified: src/common/server.c modified: src/fe-gtk/banlist.c modified: src/fe-gtk/banlist.h modified: src/fe-gtk/fe-gtk.c modified: src/fe-gtk/fe-gtk.h modified: src/fe-gtk/maingui.c modified: src/fe-text/fe-text.c
This commit is contained in:
parent
c5404b8e25
commit
f5631b2e22
@ -59,9 +59,8 @@ int fe_is_chanwindow (struct server *serv);
|
|||||||
void fe_add_chan_list (struct server *serv, char *chan, char *users,
|
void fe_add_chan_list (struct server *serv, char *chan, char *users,
|
||||||
char *topic);
|
char *topic);
|
||||||
void fe_chan_list_end (struct server *serv);
|
void fe_chan_list_end (struct server *serv);
|
||||||
int fe_is_banwindow (struct session *sess);
|
gboolean fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int rplcode);
|
||||||
void fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exemption);
|
gboolean fe_ban_list_end (struct session *sess, int rplcode);
|
||||||
void fe_ban_list_end (struct session *sess, int is_exemption);
|
|
||||||
void fe_notify_update (char *name);
|
void fe_notify_update (char *name);
|
||||||
void fe_notify_ask (char *name, char *networks);
|
void fe_notify_ask (char *name, char *networks);
|
||||||
void fe_text_clear (struct session *sess, int lines);
|
void fe_text_clear (struct session *sess, int lines);
|
||||||
|
@ -575,6 +575,7 @@ typedef struct server
|
|||||||
unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */
|
unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */
|
||||||
unsigned int have_sasl:1; /* SASL capability */
|
unsigned int have_sasl:1; /* SASL capability */
|
||||||
unsigned int have_except:1; /* ban exemptions +e */
|
unsigned int have_except:1; /* ban exemptions +e */
|
||||||
|
unsigned int have_invite:1; /* invite exemptions +I */
|
||||||
unsigned int using_cp1255:1; /* encoding is CP1255/WINDOWS-1255? */
|
unsigned int using_cp1255:1; /* encoding is CP1255/WINDOWS-1255? */
|
||||||
unsigned int using_irc:1; /* encoding is "IRC" (CP1252/UTF-8 hybrid)? */
|
unsigned int using_irc:1; /* encoding is "IRC" (CP1252/UTF-8 hybrid)? */
|
||||||
unsigned int use_who:1; /* whether to use WHO command to get dcc_ip */
|
unsigned int use_who:1; /* whether to use WHO command to get dcc_ip */
|
||||||
|
@ -1272,12 +1272,14 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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, int rplcode)
|
||||||
{
|
{
|
||||||
char *time_str = ctime (&stamp);
|
char *time_str = ctime (&stamp);
|
||||||
server *serv = sess->server;
|
server *serv = sess->server;
|
||||||
|
char *nl;
|
||||||
|
|
||||||
time_str[19] = 0; /* get rid of the \n */
|
if ((nl = strchr (time_str, '\n')))
|
||||||
|
*nl = 0;
|
||||||
if (stamp == 0)
|
if (stamp == 0)
|
||||||
time_str = "";
|
time_str = "";
|
||||||
|
|
||||||
@ -1288,18 +1290,17 @@ inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *bann
|
|||||||
goto nowindow;
|
goto nowindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fe_is_banwindow (sess))
|
if (!fe_add_ban_list (sess, mask, banner, time_str, rplcode))
|
||||||
{
|
{
|
||||||
nowindow:
|
nowindow:
|
||||||
/* let proto-irc.c do the 'goto def' for exemptions */
|
/* let proto-irc.c do the 'goto def' for exemptions */
|
||||||
if (is_exemption)
|
if (rplcode == 348) /* RPL_EXCEPTLIST */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
EMIT_SIGNAL (XP_TE_BANLIST, sess, chan, mask, banner, time_str, 0);
|
EMIT_SIGNAL (XP_TE_BANLIST, sess, chan, mask, banner, time_str, 0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fe_add_ban_list (sess, mask, banner, time_str, is_exemption);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,6 +824,10 @@ inbound_005 (server * serv, char *word[])
|
|||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
serv->have_except = TRUE;
|
serv->have_except = TRUE;
|
||||||
#endif
|
#endif
|
||||||
|
} else if (strcmp (word[w], "INVEX") == 0)
|
||||||
|
{
|
||||||
|
/* supports mode letter +I, default channel invite */
|
||||||
|
serv->have_invite = TRUE;
|
||||||
} else if (strncmp (word[w], "ELIST=", 6) == 0)
|
} else if (strncmp (word[w], "ELIST=", 6) == 0)
|
||||||
{
|
{
|
||||||
/* supports LIST >< min/max user counts? */
|
/* supports LIST >< min/max user counts? */
|
||||||
|
@ -778,8 +778,18 @@ process_numeric (session * sess, int n,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 346: /* +I-list entry */
|
||||||
|
if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 346))
|
||||||
|
goto def;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 347: /* end of invite list */
|
||||||
|
if (!fe_ban_list_end (sess, 347))
|
||||||
|
goto def;
|
||||||
|
break;
|
||||||
|
|
||||||
case 348: /* +e-list entry */
|
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], 348))
|
||||||
goto def;
|
goto def;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -790,9 +800,8 @@ process_numeric (session * sess, int n,
|
|||||||
sess = serv->front_session;
|
sess = serv->front_session;
|
||||||
goto def;
|
goto def;
|
||||||
}
|
}
|
||||||
if (!fe_is_banwindow (sess))
|
if (!fe_ban_list_end (sess, 349))
|
||||||
goto def;
|
goto def;
|
||||||
fe_ban_list_end (sess, TRUE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 353: /* NAMES */
|
case 353: /* NAMES */
|
||||||
@ -806,7 +815,8 @@ process_numeric (session * sess, int n,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 367: /* banlist entry */
|
case 367: /* banlist entry */
|
||||||
inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], FALSE);
|
if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 367))
|
||||||
|
goto def;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 368:
|
case 368:
|
||||||
@ -816,9 +826,8 @@ process_numeric (session * sess, int n,
|
|||||||
sess = serv->front_session;
|
sess = serv->front_session;
|
||||||
goto def;
|
goto def;
|
||||||
}
|
}
|
||||||
if (!fe_is_banwindow (sess))
|
if (!fe_ban_list_end (sess, 368))
|
||||||
goto def;
|
goto def;
|
||||||
fe_ban_list_end (sess, FALSE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 369: /* WHOWAS end */
|
case 369: /* WHOWAS end */
|
||||||
@ -881,6 +890,18 @@ process_numeric (session * sess, int n,
|
|||||||
notify_set_online (serv, word[4]);
|
notify_set_online (serv, word[4]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 728: /* +q-list entry */
|
||||||
|
/* NOTE: FREENODE returns these results inconsistent with e.g. +b */
|
||||||
|
/* Who else has imlemented MODE_QUIET, I wonder? */
|
||||||
|
if (!inbound_banlist (sess, atol (word[8]), word[4], word[6], word[7], 728))
|
||||||
|
goto def;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 729: /* end of quiet list */
|
||||||
|
if (!fe_ban_list_end (sess, 729))
|
||||||
|
goto def;
|
||||||
|
break;
|
||||||
|
|
||||||
case 903: /* successful SASL auth */
|
case 903: /* successful SASL auth */
|
||||||
case 904: /* aborted SASL auth */
|
case 904: /* aborted SASL auth */
|
||||||
case 905: /* failed SASL auth */
|
case 905: /* failed SASL auth */
|
||||||
|
@ -1890,6 +1890,7 @@ server_set_defaults (server *serv)
|
|||||||
serv->have_idmsg = FALSE;
|
serv->have_idmsg = FALSE;
|
||||||
serv->have_sasl = FALSE;
|
serv->have_sasl = FALSE;
|
||||||
serv->have_except = FALSE;
|
serv->have_except = FALSE;
|
||||||
|
serv->have_invite = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <gtk/gtkmessagedialog.h>
|
#include <gtk/gtkmessagedialog.h>
|
||||||
#include <gtk/gtktreeview.h>
|
#include <gtk/gtktreeview.h>
|
||||||
#include <gtk/gtktreeselection.h>
|
#include <gtk/gtktreeselection.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
#include "../common/hexchat.h"
|
#include "../common/hexchat.h"
|
||||||
#include "../common/fe.h"
|
#include "../common/fe.h"
|
||||||
@ -46,6 +47,52 @@
|
|||||||
#include "maingui.h"
|
#include "maingui.h"
|
||||||
#include "banlist.h"
|
#include "banlist.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These supports_* routines set capable, readable, writable bits */
|
||||||
|
static void supports_bans (banlist_info *, int);
|
||||||
|
static void supports_exempt (banlist_info *, int);
|
||||||
|
static void supports_invite (banlist_info *, int);
|
||||||
|
static void supports_quiet (banlist_info *, int);
|
||||||
|
|
||||||
|
static mode_info modes[MODE_CT] = {
|
||||||
|
{
|
||||||
|
"Bans",
|
||||||
|
"(b) ",
|
||||||
|
'b',
|
||||||
|
RPL_BANLIST,
|
||||||
|
RPL_ENDOFBANLIST,
|
||||||
|
1<<MODE_BAN,
|
||||||
|
supports_bans
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
"Exempts",
|
||||||
|
"(e) ",
|
||||||
|
'e',
|
||||||
|
RPL_EXCEPTLIST,
|
||||||
|
RPL_ENDOFEXCEPTLIST,
|
||||||
|
1<<MODE_EXEMPT,
|
||||||
|
supports_exempt
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
"Invites",
|
||||||
|
"(I) ",
|
||||||
|
'I',
|
||||||
|
RPL_INVITELIST,
|
||||||
|
RPL_ENDOFINVITELIST,
|
||||||
|
1<<MODE_INVITE,
|
||||||
|
supports_invite
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
"Quiets",
|
||||||
|
"(q) ",
|
||||||
|
'q',
|
||||||
|
RPL_QUIETLIST,
|
||||||
|
RPL_ENDOFQUIETLIST,
|
||||||
|
1<<MODE_QUIET,
|
||||||
|
supports_quiet
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* model for the banlist tree */
|
/* model for the banlist tree */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -58,7 +105,7 @@ enum
|
|||||||
static GtkTreeView *
|
static GtkTreeView *
|
||||||
get_view (struct session *sess)
|
get_view (struct session *sess)
|
||||||
{
|
{
|
||||||
return GTK_TREE_VIEW (sess->res->banlist_treeview);
|
return GTK_TREE_VIEW (sess->res->banlist->treeview);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkListStore *
|
static GtkListStore *
|
||||||
@ -67,91 +114,281 @@ get_store (struct session *sess)
|
|||||||
return GTK_LIST_STORE (gtk_tree_view_get_model (get_view (sess)));
|
return GTK_LIST_STORE (gtk_tree_view_get_model (get_view (sess)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
supports_exempt (server *serv)
|
supports_bans (banlist_info *banl, int i)
|
||||||
{
|
{
|
||||||
|
int bit = 1<<i;
|
||||||
|
|
||||||
|
banl->capable |= bit;
|
||||||
|
banl->readable |= bit;
|
||||||
|
banl->writeable |= bit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supports_exempt (banlist_info *banl, int i)
|
||||||
|
{
|
||||||
|
server *serv = banl->sess->server;
|
||||||
char *cm = serv->chanmodes;
|
char *cm = serv->chanmodes;
|
||||||
|
int bit = 1<<i;
|
||||||
|
|
||||||
if (serv->have_except)
|
if (serv->have_except)
|
||||||
return TRUE;
|
goto yes;
|
||||||
|
|
||||||
if (!cm)
|
if (!cm)
|
||||||
return FALSE;
|
return;
|
||||||
|
|
||||||
while (*cm)
|
while (*cm)
|
||||||
{
|
{
|
||||||
if (*cm == ',')
|
if (*cm == ',')
|
||||||
break;
|
break;
|
||||||
if (*cm == 'e')
|
if (*cm == 'e')
|
||||||
return TRUE;
|
goto yes;
|
||||||
cm++;
|
cm++;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
return FALSE;
|
yes:
|
||||||
|
banl->capable |= bit;
|
||||||
|
banl->writeable |= bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exempt)
|
supports_invite (banlist_info *banl, int i)
|
||||||
{
|
{
|
||||||
|
server *serv = banl->sess->server;
|
||||||
|
char *cm = serv->chanmodes;
|
||||||
|
int bit = 1<<i;
|
||||||
|
|
||||||
|
if (serv->have_invite)
|
||||||
|
goto yes;
|
||||||
|
|
||||||
|
if (!cm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (*cm)
|
||||||
|
{
|
||||||
|
if (*cm == ',')
|
||||||
|
break;
|
||||||
|
if (*cm == 'I')
|
||||||
|
goto yes;
|
||||||
|
cm++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
yes:
|
||||||
|
banl->capable |= bit;
|
||||||
|
banl->writeable |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supports_quiet (banlist_info *banl, int i)
|
||||||
|
{
|
||||||
|
server *serv = banl->sess->server;
|
||||||
|
char *cm = serv->chanmodes;
|
||||||
|
int bit = 1<<i;
|
||||||
|
|
||||||
|
if (!cm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (*cm)
|
||||||
|
{
|
||||||
|
if (*cm == ',')
|
||||||
|
break;
|
||||||
|
if (*cm == modes[i].letter)
|
||||||
|
goto yes;
|
||||||
|
cm++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
yes:
|
||||||
|
banl->capable |= bit;
|
||||||
|
banl->readable |= bit;
|
||||||
|
banl->writeable |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fe_add_ban_list() and fe_ban_list_end() return TRUE if consumed, FALSE otherwise */
|
||||||
|
gboolean
|
||||||
|
fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int rplcode)
|
||||||
|
{
|
||||||
|
banlist_info *banl = sess->res->banlist;
|
||||||
|
int i;
|
||||||
GtkListStore *store;
|
GtkListStore *store;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
|
||||||
store = get_store (sess);
|
if (!banl)
|
||||||
gtk_list_store_append (store, &iter);
|
return FALSE;
|
||||||
|
|
||||||
if (is_exempt)
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
if (modes[i].code == rplcode)
|
||||||
|
break;
|
||||||
|
if (i == MODE_CT)
|
||||||
{
|
{
|
||||||
snprintf (buf, sizeof (buf), "(EX) %s", mask);
|
/* printf ("Unexpected value in fe_add_ban_list: %d\n", rplcode); */
|
||||||
gtk_list_store_set (store, &iter, 0, buf, 1, who, 2, when, -1);
|
return FALSE;
|
||||||
} else
|
|
||||||
{
|
|
||||||
gtk_list_store_set (store, &iter, 0, mask, 1, who, 2, when, -1);
|
|
||||||
}
|
}
|
||||||
|
if (banl->pending & 1<<i)
|
||||||
|
{
|
||||||
|
store = get_store (sess);
|
||||||
|
gtk_list_store_append (store, &iter);
|
||||||
|
|
||||||
|
g_snprintf (buf, sizeof buf, "%s%s", modes[i].tag, mask);
|
||||||
|
gtk_list_store_set (store, &iter, 0, buf, 1, who, 2, when, -1);
|
||||||
|
|
||||||
|
banl->line_ct++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/* Sensitize checkboxes and buttons as appropriate for the moment */
|
||||||
fe_ban_list_end (struct session *sess, int is_exemption)
|
static void
|
||||||
|
banlist_sensitize (banlist_info *banl)
|
||||||
{
|
{
|
||||||
gtk_widget_set_sensitive (sess->res->banlist_butRefresh, TRUE);
|
int checkable, i;
|
||||||
|
|
||||||
|
/* CHECKBOXES -- */
|
||||||
|
checkable = banl->sess->me->op? banl->writeable: banl->readable;
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
{
|
||||||
|
if (banl->checkboxes[i] == NULL)
|
||||||
|
continue;
|
||||||
|
if ((checkable & 1<<i) == 0)
|
||||||
|
/* Checkbox is not checkable. Grey it and uncheck it. */
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (banl->checkboxes[i], FALSE);
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (banl->checkboxes[i]), FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Checkbox is checkable. Be sure it's sensitive. */
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (banl->checkboxes[i], TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BUTTONS --- */
|
||||||
|
if (banl->sess->me->op == 0 || banl->line_ct == 0)
|
||||||
|
{
|
||||||
|
/* If user is not op or list is empty, buttons should be all greyed */
|
||||||
|
gtk_widget_set_sensitive (banl->but_clear, FALSE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_crop, FALSE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_remove, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If no lines are selected, only the CLEAR button should be sensitive */
|
||||||
|
if (banl->select_ct == 0)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (banl->but_clear, TRUE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_crop, FALSE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_remove, FALSE);
|
||||||
|
}
|
||||||
|
/* If any lines are selected, only the REMOVE and CROP buttons should be sensitive */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (banl->but_clear, FALSE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_crop, TRUE);
|
||||||
|
gtk_widget_set_sensitive (banl->but_remove, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set "Refresh" sensitvity */
|
||||||
|
gtk_widget_set_sensitive (banl->but_refresh, banl->pending? FALSE: banl->checked? TRUE: FALSE);
|
||||||
|
}
|
||||||
|
/* fe_ban_list_end() returns TRUE if consumed, FALSE otherwise */
|
||||||
|
gboolean
|
||||||
|
fe_ban_list_end (struct session *sess, int rplcode)
|
||||||
|
{
|
||||||
|
banlist_info *banl = sess->res->banlist;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!banl)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
if (modes[i].endcode == rplcode)
|
||||||
|
break;
|
||||||
|
if (i == MODE_CT)
|
||||||
|
{
|
||||||
|
/* printf ("Unexpected rplcode value in fe_ban_list_end: %d\n", rplcode); */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (banl->pending & modes[i].bit)
|
||||||
|
{
|
||||||
|
banl->pending &= ~modes[i].bit;
|
||||||
|
if (!banl->pending)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (banl->but_refresh, TRUE);
|
||||||
|
banlist_sensitize (banl);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
banlist_select_changed (GtkWidget *item, banlist_info *banl)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
|
||||||
|
if (banl->line_ct == 0)
|
||||||
|
banl->select_ct = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list = gtk_tree_selection_get_selected_rows (GTK_TREE_SELECTION (item), NULL);
|
||||||
|
banl->select_ct = list? 1: 0;
|
||||||
|
g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
|
||||||
|
g_list_free (list);
|
||||||
|
}
|
||||||
|
banlist_sensitize (banl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * Performs the actual refresh operations.
|
* * Performs the actual refresh operations.
|
||||||
* */
|
* */
|
||||||
static void
|
static void
|
||||||
banlist_do_refresh (struct session *sess)
|
banlist_do_refresh (banlist_info *banl)
|
||||||
{
|
{
|
||||||
|
session *sess = banl->sess;
|
||||||
char tbuf[256];
|
char tbuf[256];
|
||||||
|
int i;
|
||||||
|
char *tbufp;
|
||||||
|
|
||||||
|
banlist_sensitize (banl);
|
||||||
|
|
||||||
if (sess->server->connected)
|
if (sess->server->connected)
|
||||||
{
|
{
|
||||||
GtkListStore *store;
|
GtkListStore *store;
|
||||||
|
|
||||||
gtk_widget_set_sensitive (sess->res->banlist_butRefresh, FALSE);
|
g_snprintf (tbuf, sizeof tbuf, DISPLAY_NAME": Ban List (%s, %s)",
|
||||||
|
|
||||||
snprintf (tbuf, sizeof tbuf, DISPLAY_NAME": Ban List (%s, %s)",
|
|
||||||
sess->channel, sess->server->servername);
|
sess->channel, sess->server->servername);
|
||||||
mg_set_title (sess->res->banlist_window, tbuf);
|
mg_set_title (banl->window, tbuf);
|
||||||
|
|
||||||
store = get_store (sess);
|
store = get_store (sess);
|
||||||
gtk_list_store_clear (store);
|
gtk_list_store_clear (store);
|
||||||
|
banl->line_ct = 0;
|
||||||
handle_command (sess, "ban", FALSE);
|
banl->pending = banl->checked;
|
||||||
|
if (banl->pending)
|
||||||
if (supports_exempt (sess->server))
|
|
||||||
{
|
{
|
||||||
snprintf (tbuf, sizeof (tbuf), "quote mode %s +e", sess->channel);
|
tbufp = tbuf + g_snprintf (tbuf, sizeof tbuf, "quote mode %s +", sess->channel);
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
if (banl->pending & 1<<i)
|
||||||
|
{
|
||||||
|
*tbufp++ = modes[i].letter;
|
||||||
|
}
|
||||||
|
*tbufp = 0;
|
||||||
handle_command (sess, tbuf, FALSE);
|
handle_command (sess, tbuf, FALSE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else
|
else
|
||||||
{
|
{
|
||||||
fe_message (_("Not connected."), FE_MSG_ERROR);
|
fe_message (_("Not connected."), FE_MSG_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_refresh (GtkWidget * wid, struct session *sess)
|
banlist_refresh (GtkWidget * wid, banlist_info *banl)
|
||||||
{
|
{
|
||||||
/* JG NOTE: Didn't see actual use of wid here, so just forwarding
|
/* JG NOTE: Didn't see actual use of wid here, so just forwarding
|
||||||
* * this to chanlist_do_refresh because I use it without any widget
|
* * this to chanlist_do_refresh because I use it without any widget
|
||||||
@ -159,123 +396,106 @@ banlist_refresh (GtkWidget * wid, struct session *sess)
|
|||||||
* * or apply for the first time if the list has not yet been
|
* * or apply for the first time if the list has not yet been
|
||||||
* * received.
|
* * received.
|
||||||
* */
|
* */
|
||||||
banlist_do_refresh (sess);
|
banlist_do_refresh (banl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
banlist_unban_inner (gpointer none, struct session *sess, int do_exempts)
|
banlist_unban_inner (gpointer none, banlist_info *banl, int mode_num)
|
||||||
{
|
{
|
||||||
|
session *sess = banl->sess;
|
||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
GtkTreeSelection *sel;
|
GtkTreeSelection *sel;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
char tbuf[2048];
|
char tbuf[2048];
|
||||||
char **masks, *tmp, *space;
|
char **masks, *mask;
|
||||||
int num_sel, i;
|
int num_sel, taglen, i;
|
||||||
|
|
||||||
|
|
||||||
/* grab the list of selected items */
|
/* grab the list of selected items */
|
||||||
model = GTK_TREE_MODEL (get_store (sess));
|
model = GTK_TREE_MODEL (get_store (sess));
|
||||||
sel = gtk_tree_view_get_selection (get_view (sess));
|
sel = gtk_tree_view_get_selection (get_view (sess));
|
||||||
num_sel = 0;
|
|
||||||
if (gtk_tree_model_get_iter_first (model, &iter))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (gtk_tree_selection_iter_is_selected (sel, &iter))
|
|
||||||
num_sel++;
|
|
||||||
}
|
|
||||||
while (gtk_tree_model_iter_next (model, &iter));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_sel < 1)
|
if (!gtk_tree_model_get_iter_first (model, &iter))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* create an array of all the masks */
|
taglen = strlen (modes[mode_num].tag);
|
||||||
masks = calloc (1, num_sel * sizeof (char *));
|
masks = g_malloc (sizeof (char *) * banl->line_ct);
|
||||||
|
num_sel = 0;
|
||||||
i = 0;
|
|
||||||
gtk_tree_model_get_iter_first (model, &iter);
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (gtk_tree_selection_iter_is_selected (sel, &iter))
|
if (gtk_tree_selection_iter_is_selected (sel, &iter))
|
||||||
{
|
{
|
||||||
gtk_tree_model_get (model, &iter, MASK_COLUMN, &masks[i], -1);
|
/* Get the mask part of this selected line */
|
||||||
space = strchr (masks[i], ' ');
|
gtk_tree_model_get (model, &iter, MASK_COLUMN, &mask, -1);
|
||||||
|
|
||||||
if (do_exempts)
|
/* If it's the wrong type of mask, just continue */
|
||||||
{
|
if (strncmp (modes[mode_num].tag, mask, taglen) != 0)
|
||||||
if (space)
|
continue;
|
||||||
{
|
|
||||||
/* remove the "(EX) " */
|
/* Otherwise add it to our array of mask pointers */
|
||||||
tmp = masks[i];
|
masks[num_sel++] = g_strdup (mask + taglen);
|
||||||
masks[i] = g_strdup (space + 1);
|
g_free (mask);
|
||||||
g_free (tmp);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if (!space)
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (gtk_tree_model_iter_next (model, &iter));
|
while (gtk_tree_model_iter_next (model, &iter));
|
||||||
|
|
||||||
/* and send to server */
|
/* and send to server */
|
||||||
if (do_exempts)
|
if (num_sel)
|
||||||
send_channel_modes (sess, tbuf, masks, 0, i, '-', 'e', 0);
|
send_channel_modes (sess, tbuf, masks, 0, num_sel, '-', modes[mode_num].letter, 0);
|
||||||
else
|
|
||||||
send_channel_modes (sess, tbuf, masks, 0, i, '-', 'b', 0);
|
|
||||||
|
|
||||||
/* now free everything, and refresh banlist */
|
/* now free everything */
|
||||||
for (i=0; i < num_sel; i++)
|
for (i=0; i < num_sel; i++)
|
||||||
g_free (masks[i]);
|
g_free (masks[i]);
|
||||||
free (masks);
|
g_free (masks);
|
||||||
|
|
||||||
return num_sel;
|
return num_sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_unban (GtkWidget * wid, struct session *sess)
|
banlist_unban (GtkWidget * wid, banlist_info *banl)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int i, num = 0;
|
||||||
|
|
||||||
num += banlist_unban_inner (wid, sess, FALSE);
|
for (i = 0; i < MODE_CT; i++)
|
||||||
num += banlist_unban_inner (wid, sess, TRUE);
|
num += banlist_unban_inner (wid, banl, i);
|
||||||
|
|
||||||
|
/* This really should not occur with the redesign */
|
||||||
if (num < 1)
|
if (num < 1)
|
||||||
{
|
{
|
||||||
fe_message (_("You must select some bans."), FE_MSG_ERROR);
|
fe_message (_("You must select some bans."), FE_MSG_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
banlist_do_refresh (sess);
|
banlist_do_refresh (banl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_clear_cb (GtkDialog *dialog, gint response, gpointer sess)
|
banlist_clear_cb (GtkDialog *dialog, gint response, gpointer data)
|
||||||
{
|
{
|
||||||
|
banlist_info *banl = data;
|
||||||
GtkTreeSelection *sel;
|
GtkTreeSelection *sel;
|
||||||
|
|
||||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||||
|
|
||||||
if (response == GTK_RESPONSE_OK)
|
if (response == GTK_RESPONSE_OK)
|
||||||
{
|
{
|
||||||
sel = gtk_tree_view_get_selection (get_view (sess));
|
sel = gtk_tree_view_get_selection (get_view (banl->sess));
|
||||||
gtk_tree_selection_select_all (sel);
|
gtk_tree_selection_select_all (sel);
|
||||||
banlist_unban (NULL, sess);
|
banlist_unban (NULL, banl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_clear (GtkWidget * wid, struct session *sess)
|
banlist_clear (GtkWidget * wid, banlist_info *banl)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
|
|
||||||
dialog = gtk_message_dialog_new (NULL, 0,
|
dialog = gtk_message_dialog_new (NULL, 0,
|
||||||
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
|
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 listed items in %s?"), banl->sess->channel);
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (dialog), "response",
|
g_signal_connect (G_OBJECT (dialog), "response",
|
||||||
G_CALLBACK (banlist_clear_cb), sess);
|
G_CALLBACK (banlist_clear_cb), banl);
|
||||||
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
|
||||||
gtk_widget_show (dialog);
|
gtk_widget_show (dialog);
|
||||||
}
|
}
|
||||||
@ -298,8 +518,9 @@ banlist_add_selected_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *it
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_crop (GtkWidget * wid, struct session *sess)
|
banlist_crop (GtkWidget * wid, banlist_info *banl)
|
||||||
{
|
{
|
||||||
|
session *sess = banl->sess;
|
||||||
GtkTreeSelection *select;
|
GtkTreeSelection *select;
|
||||||
GSList *list = NULL, *node;
|
GSList *list = NULL, *node;
|
||||||
int num_sel;
|
int num_sel;
|
||||||
@ -322,22 +543,112 @@ banlist_crop (GtkWidget * wid, struct session *sess)
|
|||||||
g_slist_foreach (list, (GFunc)g_free, NULL);
|
g_slist_foreach (list, (GFunc)g_free, NULL);
|
||||||
g_slist_free (list);
|
g_slist_free (list);
|
||||||
|
|
||||||
banlist_unban (NULL, sess);
|
banlist_unban (NULL, banl);
|
||||||
} else
|
} else
|
||||||
fe_message (_("You must select some bans."), FE_MSG_ERROR);
|
fe_message (_("You must select some bans."), FE_MSG_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
banlist_toggle (GtkWidget *item, gpointer data)
|
||||||
|
{
|
||||||
|
banlist_info *banl = data;
|
||||||
|
int i, bit = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
if (banl->checkboxes[i] == item)
|
||||||
|
{
|
||||||
|
bit = 1<<i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bit) /* Should be gassert() */
|
||||||
|
{
|
||||||
|
banl->checked &= ~bit;
|
||||||
|
banl->checked |= (GTK_TOGGLE_BUTTON (item)->active)? bit: 0;
|
||||||
|
banlist_do_refresh (banl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTICE: The official strptime() is not available on all platforms so
|
||||||
|
* I've implemented a special version here. The official version is
|
||||||
|
* vastly more general than this: it uses locales for weekday and month
|
||||||
|
* names and its second arg is a format character-string. This special
|
||||||
|
* version depends on the format returned by ctime(3) whose manpage
|
||||||
|
* says it returns:
|
||||||
|
* "a null-terminated string of the form "Wed Jun 30 21:49:08 1993\n"
|
||||||
|
*
|
||||||
|
* If the real strpftime() comes available, use this format string:
|
||||||
|
* #define DATE_FORMAT "%a %b %d %T %Y"
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
strptime (char *ti, struct tm *tm)
|
||||||
|
{
|
||||||
|
/* Expect something like "Sat Mar 16 21:24:27 2013" */
|
||||||
|
static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
|
||||||
|
int M = -1, d = -1, h = -1, m = -1, s = -1, y = -1;
|
||||||
|
|
||||||
|
if (*ti == 0)
|
||||||
|
{
|
||||||
|
memset (tm, 0, sizeof *tm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* No need to supply tm->tm_wday; mktime() doesn't read it */
|
||||||
|
ti += 4;
|
||||||
|
while ((mon[++M]))
|
||||||
|
if (strncmp (ti, mon[M], 3) == 0)
|
||||||
|
break;
|
||||||
|
ti += 4;
|
||||||
|
|
||||||
|
d = strtol (ti, &ti, 10);
|
||||||
|
h = strtol (++ti, &ti, 10);
|
||||||
|
m = strtol (++ti, &ti, 10);
|
||||||
|
s = strtol (++ti, &ti, 10);
|
||||||
|
y = strtol (++ti, NULL, 10) - 1900;
|
||||||
|
|
||||||
|
tm->tm_sec = s;
|
||||||
|
tm->tm_min = m;
|
||||||
|
tm->tm_hour = h;
|
||||||
|
tm->tm_mday = d;
|
||||||
|
tm->tm_mon = M;
|
||||||
|
tm->tm_year = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
banlist_date_sort (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct tm tm1, tm2;
|
||||||
|
time_t t1, t2;
|
||||||
|
char *time1, *time2;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, a, 2, &time1, -1);
|
||||||
|
gtk_tree_model_get(model, b, 2, &time2, -1);
|
||||||
|
strptime (time1, &tm1);
|
||||||
|
strptime (time2, &tm2);
|
||||||
|
t1 = mktime (&tm1);
|
||||||
|
t2 = mktime (&tm2);
|
||||||
|
|
||||||
|
if (t1 < t2) return 1;
|
||||||
|
if (t1 == t2) return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static GtkWidget *
|
static GtkWidget *
|
||||||
banlist_treeview_new (GtkWidget *box)
|
banlist_treeview_new (GtkWidget *box, banlist_info *banl)
|
||||||
{
|
{
|
||||||
GtkListStore *store;
|
GtkListStore *store;
|
||||||
GtkWidget *view;
|
GtkWidget *view;
|
||||||
GtkTreeSelection *select;
|
GtkTreeSelection *select;
|
||||||
GtkTreeViewColumn *col;
|
GtkTreeViewColumn *col;
|
||||||
|
GtkTreeSortable *sortable;
|
||||||
|
|
||||||
store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
|
store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
|
||||||
G_TYPE_STRING);
|
G_TYPE_STRING);
|
||||||
g_return_val_if_fail (store != NULL, NULL);
|
g_return_val_if_fail (store != NULL, NULL);
|
||||||
|
|
||||||
|
sortable = GTK_TREE_SORTABLE (store);
|
||||||
|
gtk_tree_sortable_set_sort_func (sortable, 2, banlist_date_sort, GINT_TO_POINTER (2), NULL);
|
||||||
|
|
||||||
view = gtkutil_treeview_new (box, GTK_TREE_MODEL (store), NULL,
|
view = gtkutil_treeview_new (box, GTK_TREE_MODEL (store), NULL,
|
||||||
MASK_COLUMN, _("Mask"),
|
MASK_COLUMN, _("Mask"),
|
||||||
FROM_COLUMN, _("From"),
|
FROM_COLUMN, _("From"),
|
||||||
@ -345,17 +656,25 @@ banlist_treeview_new (GtkWidget *box)
|
|||||||
|
|
||||||
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), MASK_COLUMN);
|
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), MASK_COLUMN);
|
||||||
gtk_tree_view_column_set_alignment (col, 0.5);
|
gtk_tree_view_column_set_alignment (col, 0.5);
|
||||||
gtk_tree_view_column_set_min_width (col, 300);
|
gtk_tree_view_column_set_min_width (col, 100);
|
||||||
gtk_tree_view_column_set_sort_column_id (col, MASK_COLUMN);
|
gtk_tree_view_column_set_sort_column_id (col, MASK_COLUMN);
|
||||||
|
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
||||||
|
gtk_tree_view_column_set_resizable (col, TRUE);
|
||||||
|
|
||||||
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), FROM_COLUMN);
|
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), FROM_COLUMN);
|
||||||
gtk_tree_view_column_set_alignment (col, 0.5);
|
gtk_tree_view_column_set_alignment (col, 0.5);
|
||||||
gtk_tree_view_column_set_sort_column_id (col, FROM_COLUMN);
|
gtk_tree_view_column_set_sort_column_id (col, FROM_COLUMN);
|
||||||
|
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
||||||
|
gtk_tree_view_column_set_resizable (col, TRUE);
|
||||||
|
|
||||||
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), DATE_COLUMN);
|
col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), DATE_COLUMN);
|
||||||
gtk_tree_view_column_set_alignment (col, 0.5);
|
gtk_tree_view_column_set_alignment (col, 0.5);
|
||||||
|
gtk_tree_view_column_set_sort_column_id (col, DATE_COLUMN);
|
||||||
|
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
||||||
|
gtk_tree_view_column_set_resizable (col, TRUE);
|
||||||
|
|
||||||
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
|
||||||
|
g_signal_connect (G_OBJECT (select), "changed", G_CALLBACK (banlist_select_changed), banl);
|
||||||
gtk_tree_selection_set_mode (select, GTK_SELECTION_MULTIPLE);
|
gtk_tree_selection_set_mode (select, GTK_SELECTION_MULTIPLE);
|
||||||
|
|
||||||
gtk_widget_show (view);
|
gtk_widget_show (view);
|
||||||
@ -363,56 +682,99 @@ banlist_treeview_new (GtkWidget *box)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
banlist_closegui (GtkWidget *wid, session *sess)
|
banlist_closegui (GtkWidget *wid, banlist_info *banl)
|
||||||
{
|
{
|
||||||
if (is_session (sess))
|
session *sess = banl->sess;
|
||||||
sess->res->banlist_window = 0;
|
|
||||||
|
if (sess->res->banlist == banl)
|
||||||
|
{
|
||||||
|
g_free (banl);
|
||||||
|
sess->res->banlist = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
banlist_opengui (struct session *sess)
|
banlist_opengui (struct session *sess)
|
||||||
{
|
{
|
||||||
GtkWidget *vbox1;
|
banlist_info *banl;
|
||||||
GtkWidget *bbox;
|
int i;
|
||||||
|
GtkWidget *table, *vbox, *bbox;
|
||||||
char tbuf[256];
|
char tbuf[256];
|
||||||
|
|
||||||
if (sess->res->banlist_window)
|
|
||||||
{
|
|
||||||
mg_bring_tofront (sess->res->banlist_window);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sess->type != SESS_CHANNEL)
|
if (sess->type != SESS_CHANNEL)
|
||||||
{
|
{
|
||||||
fe_message (_("You can only open the Ban List window while in a channel tab."), FE_MSG_ERROR);
|
fe_message (_("You can only open the Ban List window while in a channel tab."), FE_MSG_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Ban List (%s)"),
|
if (!sess->res->banlist)
|
||||||
|
{
|
||||||
|
sess->res->banlist = g_malloc0 (sizeof (banlist_info));
|
||||||
|
if (!sess->res->banlist)
|
||||||
|
{
|
||||||
|
fe_message (_("Banlist initialization failed."), FE_MSG_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
banl = sess->res->banlist;
|
||||||
|
if (banl->window)
|
||||||
|
{
|
||||||
|
mg_bring_tofront (banl->window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New banlist for this session -- Initialize it */
|
||||||
|
banl->sess = sess;
|
||||||
|
/* For each mode set its bit in capable/readable/writeable */
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
modes[i].tester (banl, i);
|
||||||
|
/* Force on the checkmark in the "Bans" box */
|
||||||
|
banl->checked = 1<<MODE_BAN;
|
||||||
|
|
||||||
|
g_snprintf (tbuf, sizeof tbuf, _(DISPLAY_NAME": Ban List (%s)"),
|
||||||
sess->server->servername);
|
sess->server->servername);
|
||||||
|
|
||||||
sess->res->banlist_window = mg_create_generic_tab ("BanList", tbuf, FALSE,
|
banl->window = mg_create_generic_tab ("BanList", tbuf, FALSE,
|
||||||
TRUE, banlist_closegui, sess, 550, 200, &vbox1, sess->server);
|
TRUE, banlist_closegui, banl, 550, 200, &vbox, sess->server);
|
||||||
|
gtkutil_destroy_on_esc (banl->window);
|
||||||
|
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (banl->window), 3);
|
||||||
|
gtk_box_set_spacing (GTK_BOX (vbox), 3);
|
||||||
|
|
||||||
/* create banlist view */
|
/* create banlist view */
|
||||||
sess->res->banlist_treeview = banlist_treeview_new (vbox1);
|
banl->treeview = banlist_treeview_new (vbox, banl);
|
||||||
|
|
||||||
|
table = gtk_table_new (1, 3, FALSE);
|
||||||
|
gtk_table_set_col_spacings (GTK_TABLE (table), 16);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), table, 0, 0, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < MODE_CT; i++)
|
||||||
|
{
|
||||||
|
if (!(banl->capable & 1<<i))
|
||||||
|
continue;
|
||||||
|
banl->checkboxes[i] = gtk_check_button_new_with_label (_(modes[i].name));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (banl->checkboxes[i]), (banl->checked & 1<<i? TRUE: FALSE));
|
||||||
|
g_signal_connect (G_OBJECT (banl->checkboxes[i]), "toggled",
|
||||||
|
G_CALLBACK (banlist_toggle), banl);
|
||||||
|
gtk_table_attach (GTK_TABLE (table), banl->checkboxes[i], i+1, i+2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bbox = gtk_hbutton_box_new ();
|
bbox = gtk_hbutton_box_new ();
|
||||||
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
|
||||||
gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
|
gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
|
||||||
gtk_box_pack_end (GTK_BOX (vbox1), bbox, 0, 0, 0);
|
gtk_box_pack_end (GTK_BOX (vbox), bbox, 0, 0, 0);
|
||||||
gtk_widget_show (bbox);
|
gtk_widget_show (bbox);
|
||||||
|
|
||||||
gtkutil_button (bbox, GTK_STOCK_REMOVE, 0, banlist_unban, sess,
|
banl->but_remove = gtkutil_button (bbox, GTK_STOCK_REMOVE, 0, banlist_unban, banl,
|
||||||
_("Remove"));
|
_("Remove"));
|
||||||
gtkutil_button (bbox, GTK_STOCK_REMOVE, 0, banlist_crop, sess,
|
banl->but_crop = gtkutil_button (bbox, GTK_STOCK_REMOVE, 0, banlist_crop, banl,
|
||||||
_("Crop"));
|
_("Crop"));
|
||||||
gtkutil_button (bbox, GTK_STOCK_CLEAR, 0, banlist_clear, sess,
|
banl->but_clear = gtkutil_button (bbox, GTK_STOCK_CLEAR, 0, banlist_clear, banl,
|
||||||
_("Clear"));
|
_("Clear"));
|
||||||
|
|
||||||
sess->res->banlist_butRefresh = gtkutil_button (bbox, GTK_STOCK_REFRESH, 0, banlist_refresh, sess, _("Refresh"));
|
banl->but_refresh = gtkutil_button (bbox, GTK_STOCK_REFRESH, 0, banlist_refresh, banl, _("Refresh"));
|
||||||
|
|
||||||
banlist_do_refresh (sess);
|
banlist_do_refresh (banl);
|
||||||
|
|
||||||
gtk_widget_show (sess->res->banlist_window);
|
gtk_widget_show_all (banl->window);
|
||||||
}
|
}
|
||||||
|
@ -1 +1,60 @@
|
|||||||
|
#ifndef BANLIST_H
|
||||||
|
#define BANLIST_H
|
||||||
|
|
||||||
|
#include "../common/hexchat.h"
|
||||||
void banlist_opengui (session *sess);
|
void banlist_opengui (session *sess);
|
||||||
|
|
||||||
|
#ifndef RPL_BANLIST
|
||||||
|
/* Where's that darn header file, that would have all these defines ? */
|
||||||
|
#define RPL_BANLIST 367
|
||||||
|
#define RPL_ENDOFBANLIST 368
|
||||||
|
#define RPL_INVITELIST 346
|
||||||
|
#define RPL_ENDOFINVITELIST 347
|
||||||
|
#define RPL_EXCEPTLIST 348
|
||||||
|
#define RPL_ENDOFEXCEPTLIST 349
|
||||||
|
#define RPL_QUIETLIST 728
|
||||||
|
#define RPL_ENDOFQUIETLIST 729
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum banlist_modes_e {
|
||||||
|
MODE_BAN,
|
||||||
|
MODE_EXEMPT,
|
||||||
|
MODE_INVITE,
|
||||||
|
MODE_QUIET,
|
||||||
|
MODE_CT
|
||||||
|
} banlist_modes;
|
||||||
|
|
||||||
|
typedef struct banlist_info_s banlist_info;
|
||||||
|
|
||||||
|
typedef struct mode_info_s {
|
||||||
|
char *name; /* Checkbox name, e.g. "Bans" */
|
||||||
|
char *tag; /* Prefix line with this, e.g. "(EX) " for MODE_EXEMPT */
|
||||||
|
char letter; /* /mode-command letter, e.g. 'b' for MODE_BAN */
|
||||||
|
int code; /* rfc RPL_foo code, e.g. 367 for RPL_BANLIST */
|
||||||
|
int endcode; /* rfc RPL_ENDOFfoo code, e.g. 368 for RPL_ENDOFBANLIST */
|
||||||
|
int bit; /* Mask bit, e.g., 1<<MODE_BAN */
|
||||||
|
void (*tester)(banlist_info *, int); /* Function returns true to set bit into checkable */
|
||||||
|
} mode_info;
|
||||||
|
|
||||||
|
typedef struct banlist_info_s {
|
||||||
|
session *sess;
|
||||||
|
int capable; /* MODE bitmask */
|
||||||
|
int readable; /* subset of capable if not op */
|
||||||
|
int writeable; /* subset of capable if op */
|
||||||
|
int checked; /* subset of (op? writeable: readable) */
|
||||||
|
int pending; /* subset of checked */
|
||||||
|
int current; /* index of currently processing mode */
|
||||||
|
int line_ct; /* count of presented lines */
|
||||||
|
int select_ct; /* count of selected lines */
|
||||||
|
/* Not really; 1 if any are selected otherwise 0 */
|
||||||
|
GtkWidget *window;
|
||||||
|
GtkWidget *treeview;
|
||||||
|
GtkWidget *radios[MODE_CT];
|
||||||
|
GtkWidget *checkboxes[MODE_CT];
|
||||||
|
GtkWidget *but_remove;
|
||||||
|
GtkWidget *but_crop;
|
||||||
|
GtkWidget *but_clear;
|
||||||
|
GtkWidget *but_refresh;
|
||||||
|
GtkWidget *checkbox[MODE_CT]; /* Checkbox widget for mode */
|
||||||
|
} banlist_info;
|
||||||
|
#endif /* BANLIST_H */
|
||||||
|
@ -604,14 +604,6 @@ fe_is_chanwindow (struct server *serv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
fe_is_banwindow (struct session *sess)
|
|
||||||
{
|
|
||||||
if (!sess->res->banlist_window)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
fe_notify_update (char *name)
|
fe_notify_update (char *name)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <gtk/gtkwidget.h>
|
#include <gtk/gtkwidget.h>
|
||||||
#include <gtk/gtkcontainer.h>
|
#include <gtk/gtkcontainer.h>
|
||||||
#include <gtk/gtksignal.h>
|
#include <gtk/gtksignal.h>
|
||||||
|
#include "banlist.h"
|
||||||
|
|
||||||
#undef gtk_signal_connect
|
#undef gtk_signal_connect
|
||||||
#define gtk_signal_connect g_signal_connect
|
#define gtk_signal_connect g_signal_connect
|
||||||
@ -97,10 +98,7 @@ struct server_gui
|
|||||||
|
|
||||||
typedef struct restore_gui
|
typedef struct restore_gui
|
||||||
{
|
{
|
||||||
/* banlist stuff */
|
banlist_info *banlist;
|
||||||
GtkWidget *banlist_window;
|
|
||||||
GtkWidget *banlist_treeview;
|
|
||||||
GtkWidget *banlist_butRefresh;
|
|
||||||
|
|
||||||
void *tab; /* (chan *) */
|
void *tab; /* (chan *) */
|
||||||
|
|
||||||
|
@ -3530,8 +3530,8 @@ fe_server_callback (server *serv)
|
|||||||
void
|
void
|
||||||
fe_session_callback (session *sess)
|
fe_session_callback (session *sess)
|
||||||
{
|
{
|
||||||
if (sess->res->banlist_window)
|
if (sess->res->banlist && sess->res->banlist->window)
|
||||||
mg_close_gen (NULL, sess->res->banlist_window);
|
mg_close_gen (NULL, sess->res->banlist->window);
|
||||||
|
|
||||||
if (sess->res->input_text)
|
if (sess->res->input_text)
|
||||||
free (sess->res->input_text);
|
free (sess->res->input_text);
|
||||||
|
@ -651,17 +651,12 @@ void
|
|||||||
fe_chan_list_end (struct server *serv)
|
fe_chan_list_end (struct server *serv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
int
|
gboolean
|
||||||
fe_is_banwindow (struct session *sess)
|
fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int rplcode)
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void
|
|
||||||
fe_add_ban_list (struct session *sess, char *mask, char *who, char *when, int is_exemption)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void
|
gboolean
|
||||||
fe_ban_list_end (struct session *sess, int is_exemption)
|
fe_ban_list_end (struct session *sess, int rplcode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user