summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/ignore.c38
-rw-r--r--src/core/ignore.h10
-rw-r--r--src/fe-common/core/command-history.c35
-rw-r--r--src/fe-common/core/command-history.h1
-rw-r--r--src/fe-common/core/fe-ignore.c8
-rw-r--r--src/fe-common/core/fe-messages.c10
-rw-r--r--src/fe-common/core/fe-windows.c7
-rw-r--r--src/fe-common/core/fe-windows.h1
-rw-r--r--src/fe-common/core/formats.h4
-rw-r--r--src/fe-common/core/hilight-text.c10
-rw-r--r--src/fe-common/core/hilight-text.h2
-rw-r--r--src/fe-common/core/window-commands.c21
-rw-r--r--src/fe-text/gui-readline.c166
-rw-r--r--src/fe-text/term-terminfo.c8
-rw-r--r--src/fe-text/term.h2
-rw-r--r--src/irc/core/irc-commands.c202
-rw-r--r--src/irc/flood/autoignore.c2
-rw-r--r--src/irc/proxy/listen.c2
-rw-r--r--src/perl/perl-common.c3
-rw-r--r--src/perl/perl-core.c17
20 files changed, 382 insertions, 167 deletions
diff --git a/src/core/ignore.c b/src/core/ignore.c
index fd3c8a38..8d5a27c2 100644
--- a/src/core/ignore.c
+++ b/src/core/ignore.c
@@ -186,15 +186,8 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host,
return ignore_check_replies(chanrec, text, level);
}
-IGNORE_REC *ignore_find(const char *servertag, const char *mask,
- char **channels)
-{
- return ignore_find_noact(servertag, mask, channels, 0);
-}
-
-
-IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask,
- char **channels, int noact)
+IGNORE_REC *ignore_find_full(const char *servertag, const char *mask, const char *pattern,
+ char **channels, const int flags)
{
GSList *tmp;
char **chan;
@@ -216,18 +209,29 @@ IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask,
continue;
}
- if (noact && (rec->level & MSGLEVEL_NO_ACT) == 0)
+ if ((flags & IGNORE_FIND_NOACT) && (rec->level & MSGLEVEL_NO_ACT) == 0)
continue;
- if (!noact && (rec->level & MSGLEVEL_NO_ACT) != 0)
+ if (!(flags & IGNORE_FIND_NOACT) && (rec->level & MSGLEVEL_NO_ACT) != 0)
continue;
if ((rec->mask == NULL && mask != NULL) ||
- (rec->mask != NULL && mask == NULL)) continue;
+ (rec->mask != NULL && mask == NULL))
+ continue;
if (rec->mask != NULL && g_ascii_strcasecmp(rec->mask, mask) != 0)
continue;
+ /* match the pattern too if requested */
+ if (flags & IGNORE_FIND_PATTERN) {
+ if ((rec->pattern == NULL && pattern != NULL) ||
+ (rec->pattern != NULL && pattern == NULL))
+ continue;
+
+ if (rec->pattern != NULL && g_ascii_strcasecmp(rec->pattern, pattern) != 0)
+ continue;
+ }
+
if ((channels == NULL && rec->channels == NULL))
return rec; /* no channels - ok */
@@ -253,6 +257,16 @@ IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask,
return NULL;
}
+IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels)
+{
+ return ignore_find_full(servertag, mask, NULL, channels, 0);
+}
+
+IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact)
+{
+ return ignore_find_full(servertag, mask, NULL, channels, IGNORE_FIND_NOACT);
+}
+
static void ignore_set_config(IGNORE_REC *rec)
{
CONFIG_NODE *node;
diff --git a/src/core/ignore.h b/src/core/ignore.h
index 46025d4c..f889740f 100644
--- a/src/core/ignore.h
+++ b/src/core/ignore.h
@@ -31,6 +31,16 @@ extern GSList *ignores;
int ignore_check(SERVER_REC *server, const char *nick, const char *host,
const char *channel, const char *text, int level);
+enum {
+ IGNORE_FIND_PATTERN = 0x01, // Match the pattern
+ IGNORE_FIND_NOACT = 0x02, // Exclude the targets with NOACT level
+};
+
+IGNORE_REC *ignore_find_full (const char *servertag, const char *mask, const char *pattern,
+ char **channels, const int flags);
+
+// Convenience wrappers around ignore_find_full, for compatibility purpose
+
IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels);
IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact);
diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c
index f9c3884c..1060744e 100644
--- a/src/fe-common/core/command-history.c
+++ b/src/fe-common/core/command-history.c
@@ -94,13 +94,13 @@ HISTORY_REC *command_history_current(WINDOW_REC *window)
if (window == NULL)
return global_history;
- if (window_history)
- return window->history;
-
rec = command_history_find_name(window->history_name);
if (rec != NULL)
return rec;
+ if (window_history)
+ return window->history;
+
return global_history;
}
@@ -178,6 +178,17 @@ HISTORY_REC *command_history_create(const char *name)
return rec;
}
+void command_history_clear(HISTORY_REC *history)
+{
+ g_return_if_fail(history != NULL);
+
+ command_history_clear_pos_func(history, NULL);
+ g_list_foreach(history->list, (GFunc) g_free, NULL);
+ g_list_free(history->list);
+ history->list = NULL;
+ history->lines = 0;
+}
+
void command_history_destroy(HISTORY_REC *history)
{
g_return_if_fail(history != NULL);
@@ -186,9 +197,7 @@ void command_history_destroy(HISTORY_REC *history)
g_return_if_fail(history->refcount == 0);
histories = g_slist_remove(histories, history);
-
- g_list_foreach(history->list, (GFunc) g_free, NULL);
- g_list_free(history->list);
+ command_history_clear(history);
g_free_not_null(history->name);
g_free(history);
@@ -229,6 +238,18 @@ static void sig_window_destroyed(WINDOW_REC *window)
g_free_not_null(window->history_name);
}
+static void sig_window_history_cleared(WINDOW_REC *window, const char *name) {
+ HISTORY_REC *history;
+
+ if (name == NULL || *name == '\0') {
+ history = command_history_current(window);
+ } else {
+ history = command_history_find_name(name);
+ }
+
+ command_history_clear(history);
+}
+
static void sig_window_history_changed(WINDOW_REC *window, const char *oldname)
{
command_history_link(window->history_name);
@@ -279,6 +300,7 @@ void command_history_init(void)
signal_add("window created", (SIGNAL_FUNC) sig_window_created);
signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_add("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+ signal_add_last("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
@@ -287,6 +309,7 @@ void command_history_deinit(void)
signal_remove("window created", (SIGNAL_FUNC) sig_window_created);
signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_remove("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+ signal_remove("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
command_history_destroy(global_history);
diff --git a/src/fe-common/core/command-history.h b/src/fe-common/core/command-history.h
index 7b76246b..a572216b 100644
--- a/src/fe-common/core/command-history.h
+++ b/src/fe-common/core/command-history.h
@@ -28,6 +28,7 @@ const char *command_history_next(WINDOW_REC *window, const char *text);
void command_history_clear_pos(WINDOW_REC *window);
HISTORY_REC *command_history_create(const char *name);
+void command_history_clear(HISTORY_REC *history);
void command_history_destroy(HISTORY_REC *history);
void command_history_link(const char *name);
void command_history_unlink(const char *name);
diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c
index d2f9de27..a809ac91 100644
--- a/src/fe-common/core/fe-ignore.c
+++ b/src/fe-common/core/fe-ignore.c
@@ -158,8 +158,8 @@ static void cmd_ignore(const char *data)
channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
g_strsplit(chanarg, ",", -1);
- rec = patternarg != NULL ? NULL: ignore_find_noact(servertag, mask, channels,
- (level & MSGLEVEL_NO_ACT));
+ rec = ignore_find_full(servertag, mask, patternarg, channels,
+ IGNORE_FIND_PATTERN | ((level & MSGLEVEL_NO_ACT) ? IGNORE_FIND_NOACT : 0));
new_ignore = rec == NULL;
if (rec == NULL) {
@@ -237,9 +237,9 @@ static void cmd_unignore(const char *data)
chans[0] = mask;
mask = NULL;
}
- rec = ignore_find_noact("*", mask, (char **) chans, 0);
+ rec = ignore_find_full("*", mask, NULL, (char **) chans, 0);
if (rec == NULL) {
- rec = ignore_find_noact("*", mask, (char **) chans, 1);
+ rec = ignore_find_full("*", mask, NULL, (char **) chans, IGNORE_FIND_NOACT);
}
}
diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index d09c1b0b..3240fd10 100644
--- a/src/fe-common/core/fe-messages.c
+++ b/src/fe-common/core/fe-messages.c
@@ -214,10 +214,12 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
if (printnick == NULL)
printnick = nick;
+ TEXT_DEST_REC dest;
+ format_create_dest(&dest, server, target, level, NULL);
+ dest.address = address;
+ dest.nick = nick;
if (color != NULL) {
/* highlighted nick */
- TEXT_DEST_REC dest;
- format_create_dest(&dest, server, target, level, NULL);
hilight_update_text_dest(&dest,hilight);
if (!print_channel) /* message to active channel in window */
printformat_dest(&dest, TXT_PUBMSG_HILIGHT, color,
@@ -228,11 +230,11 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
nickmode);
} else {
if (!print_channel)
- printformat(server, target, level,
+ printformat_dest(&dest,
for_me ? TXT_PUBMSG_ME : TXT_PUBMSG,
printnick, msg, nickmode);
else
- printformat(server, target, level,
+ printformat_dest(&dest,
for_me ? TXT_PUBMSG_ME_CHANNEL :
TXT_PUBMSG_CHANNEL,
printnick, target, msg, nickmode);
diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c
index 1049137f..46c1593b 100644
--- a/src/fe-common/core/fe-windows.c
+++ b/src/fe-common/core/fe-windows.c
@@ -229,11 +229,16 @@ void window_set_history(WINDOW_REC *window, const char *name)
else
window->history_name = g_strdup(name);
- signal_emit("window history changed", 1, window, oldname);
+ signal_emit("window history changed", 2, window, oldname);
g_free_not_null(oldname);
}
+void window_clear_history(WINDOW_REC *window, const char *name)
+{
+ signal_emit("window history cleared", 2, window, name);
+}
+
void window_set_level(WINDOW_REC *window, int level)
{
g_return_if_fail(window != NULL);
diff --git a/src/fe-common/core/fe-windows.h b/src/fe-common/core/fe-windows.h
index 613f15f8..32d6cfcd 100644
--- a/src/fe-common/core/fe-windows.h
+++ b/src/fe-common/core/fe-windows.h
@@ -66,6 +66,7 @@ void window_change_server(WINDOW_REC *window, void *server);
void window_set_refnum(WINDOW_REC *window, int refnum);
void window_set_name(WINDOW_REC *window, const char *name);
void window_set_history(WINDOW_REC *window, const char *name);
+void window_clear_history(WINDOW_REC *window, const char *name);
void window_set_level(WINDOW_REC *window, int level);
void window_set_immortal(WINDOW_REC *window, int immortal);
diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h
index 07e1832c..8efd204c 100644
--- a/src/fe-common/core/formats.h
+++ b/src/fe-common/core/formats.h
@@ -45,11 +45,15 @@ struct _FORMAT_REC {
#define PRINT_FLAG_SET_SERVERTAG 0x0010
#define PRINT_FLAG_UNSET_SERVERTAG 0x0020
+typedef struct _HILIGHT_REC HILIGHT_REC;
+
typedef struct _TEXT_DEST_REC {
WINDOW_REC *window;
SERVER_REC *server;
const char *server_tag; /* if server is non-NULL, must be server->tag */
const char *target;
+ const char *nick;
+ const char *address;
int level;
int hilight_priority;
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 9822de1e..b746f636 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -325,11 +325,11 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
if (dest->level & MSGLEVEL_NOHILIGHT)
return;
- hilight_start = hilight_end = 0;
- hilight = hilight_match(dest->server, dest->target,
- NULL, NULL, dest->level, stripped,
- &hilight_start,
- &hilight_end);
+ hilight_start = hilight_end = 0;
+ hilight = hilight_match(dest->server, dest->target, dest->nick,
+ dest->address, dest->level, stripped,
+ &hilight_start, &hilight_end);
+
if (hilight == NULL)
return;
diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h
index 1692b8ab..3c897def 100644
--- a/src/fe-common/core/hilight-text.h
+++ b/src/fe-common/core/hilight-text.h
@@ -7,8 +7,6 @@
#include "formats.h"
-typedef struct _HILIGHT_REC HILIGHT_REC;
-
struct _HILIGHT_REC {
char *text;
diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c
index c6ab68c0..9e4aab3a 100644
--- a/src/fe-common/core/window-commands.c
+++ b/src/fe-common/core/window-commands.c
@@ -33,6 +33,7 @@
#include "window-items.h"
#include "windows-layout.h"
#include "printtext.h"
+#include "command-history.h"
static void window_print_binds(WINDOW_REC *win)
{
@@ -615,10 +616,25 @@ static void cmd_window_name(const char *data)
}
}
-/* SYNTAX: WINDOW HISTORY <name> */
+/* SYNTAX: WINDOW HISTORY [-clear] <name> */
void cmd_window_history(const char *data)
{
- window_set_history(active_win, data);
+ GHashTable *optlist;
+ char *name;
+ void *free_arg;
+
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS,
+ "window history", &optlist, &name))
+ return;
+
+ if (g_hash_table_lookup(optlist, "clear") != NULL) {
+ signal_continue(1, data);
+ window_clear_history(active_win, name);
+ } else {
+ window_set_history(active_win, name);
+ }
+
+ cmd_params_free(free_arg);
}
/* we're moving the first window to last - move the first contiguous block
@@ -883,6 +899,7 @@ void window_commands_init(void)
command_set_options("window number", "sticky");
command_set_options("window server", "sticky unsticky");
command_set_options("window theme", "delete");
+ command_set_options("window history", "clear");
}
void window_commands_deinit(void)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index a8f3ba99..5acfaf60 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -37,6 +37,7 @@
#include "gui-windows.h"
#include "utf8.h"
+#include <string.h>
#include <signal.h>
typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item);
@@ -60,11 +61,21 @@ static int paste_detect_time, paste_verify_line_count;
static char *paste_entry;
static int paste_entry_pos;
static GArray *paste_buffer;
+static GArray *paste_buffer_rest;
static char *paste_old_prompt;
static int paste_prompt, paste_line_count;
static int paste_join_multiline;
static int paste_timeout_id;
+static int paste_use_bracketed_mode;
+static int paste_bracketed_mode;
+static int paste_was_bracketed_mode;
+
+/* Terminal sequences that surround the input when the terminal has the
+ * bracketed paste mode active. Fror more details see
+ * https://cirw.in/blog/bracketed-paste */
+static const unichar bp_start[] = { 0x1b, '[', '2', '0', '0', '~' };
+static const unichar bp_end[] = { 0x1b, '[', '2', '0', '1', '~' };
static void sig_input(void);
@@ -247,9 +258,16 @@ static void paste_buffer_join_lines(GArray *buf)
g_array_set_size(buf, dest - arr);
}
+static void paste_send_line(char *text)
+{
+ /* we need to get the current history every time because it might change between calls */
+ command_history_add(command_history_current(active_win), text);
+
+ signal_emit("send command", 3, text, active_win->active_server, active_win->active);
+}
+
static void paste_send(void)
{
- HISTORY_REC *history;
unichar *arr;
GString *str;
char out[10], *text;
@@ -274,11 +292,7 @@ static void paste_send(void)
}
text = gui_entry_get_text(active_entry);
- history = command_history_current(active_win);
- command_history_add(history, text);
-
- signal_emit("send command", 3, text,
- active_win->active_server, active_win->active);
+ paste_send_line(text);
g_free(text);
}
@@ -286,12 +300,7 @@ static void paste_send(void)
str = g_string_new(NULL);
for (; i < paste_buffer->len; i++) {
if (arr[i] == '\r' || arr[i] == '\n') {
- history = command_history_current(active_win);
- command_history_add(history, str->str);
-
- signal_emit("send command", 3, str->str,
- active_win->active_server,
- active_win->active);
+ paste_send_line(str->str);
g_string_truncate(str, 0);
} else if (active_entry->utf8) {
out[g_unichar_to_utf8(arr[i], out)] = '\0';
@@ -305,7 +314,14 @@ static void paste_send(void)
}
}
- gui_entry_set_text(active_entry, str->str);
+ if (paste_was_bracketed_mode) {
+ /* the text before the bracket end should be sent along with the rest */
+ paste_send_line(str->str);
+ gui_entry_set_text(active_entry, "");
+ } else {
+ gui_entry_set_text(active_entry, str->str);
+ }
+
g_string_free(str, TRUE);
}
@@ -321,6 +337,12 @@ static void paste_flush(int send)
paste_send();
g_array_set_size(paste_buffer, 0);
+ /* re-add anything that may have been after the bracketed paste end */
+ if (paste_buffer_rest->len > 0) {
+ g_array_append_vals(paste_buffer, paste_buffer_rest->data, paste_buffer_rest->len);
+ g_array_set_size(paste_buffer_rest, 0);
+ }
+
gui_entry_set_prompt(active_entry,
paste_old_prompt == NULL ? "" : paste_old_prompt);
g_free(paste_old_prompt); paste_old_prompt = NULL;
@@ -434,22 +456,21 @@ static void key_send_line(void)
add_history = *str != '\0';
history = command_history_current(active_win);
+ if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
+ add_history = 0;
+
+ if (add_history && history != NULL) {
+ command_history_add(history, str);
+ }
+
if (redir == NULL) {
signal_emit("send command", 3, str,
active_win->active_server,
active_win->active);
} else {
- if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
- add_history = 0;
handle_entry_redirect(str);
}
- if (add_history) {
- history = command_history_find(history);
- if (history != NULL)
- command_history_add(history, str);
- }
-
if (active_entry != NULL)
gui_entry_set_text(active_entry, "");
command_history_clear_pos(active_win);
@@ -615,6 +636,8 @@ static void key_delete_to_next_space(void)
static gboolean paste_timeout(gpointer data)
{
+ paste_was_bracketed_mode = paste_bracketed_mode;
+
if (paste_line_count == 0) {
int i;
@@ -633,6 +656,70 @@ static gboolean paste_timeout(gpointer data)
return FALSE;
}
+static void paste_bracketed_end(int i, gboolean rest)
+{
+ unichar last_char;
+
+ /* if there's stuff after the end bracket, save it for later */
+ if (rest) {
+ unichar *start = ((unichar *) paste_buffer->data) + i + G_N_ELEMENTS(bp_end);
+ int len = paste_buffer->len - i - G_N_ELEMENTS(bp_end);
+
+ g_array_set_size(paste_buffer_rest, 0);
+ g_array_append_vals(paste_buffer_rest, start, len);
+ }
+
+ /* remove the rest, including the trailing sequence chars */
+ g_array_set_size(paste_buffer, i);
+
+ last_char = g_array_index(paste_buffer, unichar, i - 1);
+
+ if (paste_line_count > 0 && last_char != '\n' && last_char != '\r') {
+ /* there are newlines, but there's also stuff after the newline
+ * adjust line count to reflect this */
+ paste_line_count++;
+ }
+
+ /* decide what to do with the buffer */
+ paste_timeout(NULL);
+
+ paste_bracketed_mode = FALSE;
+}
+
+static void paste_bracketed_middle()
+{
+ int i;
+ int marklen = G_N_ELEMENTS(bp_end);
+ int len = paste_buffer->len - marklen;
+ unichar *ptr = (unichar *) paste_buffer->data;
+
+ if (len < 0) {
+ return;
+ }
+
+ for (i = 0; i <= len; i++, ptr++) {
+ if (ptr[0] == bp_end[0] && memcmp(ptr, bp_end, sizeof(bp_end)) == 0) {
+
+ /* if there are at least 6 bytes after the end,
+ * check for another start marker right afterwards */
+ if (i <= (len - marklen) &&
+ memcmp(ptr + marklen, bp_start, sizeof(bp_start)) == 0) {
+
+ /* remove both markers*/
+ g_array_remove_range(paste_buffer, i, marklen * 2);
+ len -= marklen * 2;
+
+ /* go one step back */
+ i--;
+ ptr--;
+ continue;
+ }
+ paste_bracketed_end(i, i != len);
+ break;
+ }
+ }
+}
+
static void sig_input(void)
{
if (!active_entry) {
@@ -646,21 +733,37 @@ static void sig_input(void)
unichar key;
term_gets(buffer, &line_count);
key = g_array_index(buffer, unichar, 0);
+ /* Either Ctrl-k or Ctrl-c is pressed */
if (key == 11 || key == 3)
paste_flush(key == 11);
g_array_free(buffer, TRUE);
} else {
term_gets(paste_buffer, &paste_line_count);
- if (paste_detect_time > 0 && paste_buffer->len >= 3) {
+
+ /* use the bracketed paste mode to detect when the user pastes
+ * some text into the entry */
+ if (paste_bracketed_mode) {
+ paste_bracketed_middle();
+
+ } else if (!paste_use_bracketed_mode && paste_detect_time > 0 && paste_buffer->len >= 3) {
if (paste_timeout_id != -1)
g_source_remove(paste_timeout_id);
paste_timeout_id = g_timeout_add(paste_detect_time, paste_timeout, NULL);
- } else {
+ } else if (!paste_bracketed_mode) {
int i;
for (i = 0; i < paste_buffer->len; i++) {
unichar key = g_array_index(paste_buffer, unichar, i);
signal_emit("gui key pressed", 1, GINT_TO_POINTER(key));
+
+ if (paste_bracketed_mode) {
+ /* just enabled by the signal, remove what was processed so far */
+ g_array_remove_range(paste_buffer, 0, i + 1);
+
+ /* handle single-line / small pastes here */
+ paste_bracketed_middle();
+ return;
+ }
}
g_array_set_size(paste_buffer, 0);
paste_line_count = 0;
@@ -668,6 +771,11 @@ static void sig_input(void)
}
}
+static void key_paste_start(void)
+{
+ paste_bracketed_mode = TRUE;
+}
+
time_t get_idle_time(void)
{
return last_keypress.tv_sec;
@@ -929,6 +1037,10 @@ static void setup_changed(void)
paste_verify_line_count = settings_get_int("paste_verify_line_count");
paste_join_multiline = settings_get_bool("paste_join_multiline");
+ paste_use_bracketed_mode = settings_get_bool("paste_use_bracketed_mode");
+
+ /* Enable the bracketed paste mode on demand */
+ term_set_bracketed_paste_mode(paste_use_bracketed_mode);
}
void gui_readline_init(void)
@@ -942,13 +1054,16 @@ void gui_readline_init(void)
paste_entry = NULL;
paste_entry_pos = 0;
paste_buffer = g_array_new(FALSE, FALSE, sizeof(unichar));
+ paste_buffer_rest = g_array_new(FALSE, FALSE, sizeof(unichar));
paste_old_prompt = NULL;
paste_timeout_id = -1;
+ paste_bracketed_mode = FALSE;
g_get_current_time(&last_keypress);
input_listen_init(STDIN_FILENO);
settings_add_str("history", "scroll_page_count", "/2");
settings_add_time("misc", "paste_detect_time", "5msecs");
+ settings_add_bool("misc", "paste_use_bracketed_mode", FALSE);
/* NOTE: function keys can generate at least 5 characters long
keycodes. this must be larger to allow them to work. */
settings_add_int("misc", "paste_verify_line_count", 5);
@@ -1021,6 +1136,8 @@ void gui_readline_init(void)
key_bind("key", NULL, "meta-O-M", "return", (SIGNAL_FUNC) key_combo);
+ key_bind("paste_start", "Bracketed paste start", "meta2-200~", "paste_start", (SIGNAL_FUNC) key_paste_start);
+
/* cursor movement */
key_bind("backward_character", "Move the cursor a character backward", "left", NULL, (SIGNAL_FUNC) key_backward_character);
key_bind("forward_character", "Move the cursor a character forward", "right", NULL, (SIGNAL_FUNC) key_forward_character);
@@ -1116,6 +1233,8 @@ void gui_readline_deinit(void)
key_configure_freeze();
+ key_unbind("paste_start", (SIGNAL_FUNC) key_paste_start);
+
key_unbind("backward_character", (SIGNAL_FUNC) key_backward_character);
key_unbind("forward_character", (SIGNAL_FUNC) key_forward_character);
key_unbind("backward_word", (SIGNAL_FUNC) key_backward_word);
@@ -1173,6 +1292,7 @@ void gui_readline_deinit(void)
key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop);
keyboard_destroy(keyboard);
g_array_free(paste_buffer, TRUE);
+ g_array_free(paste_buffer_rest, TRUE);
key_configure_thaw();
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 27be904e..3582b9e4 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -710,3 +710,11 @@ void term_gets(GArray *buffer, int *line_count)
}
}
}
+
+void term_set_bracketed_paste_mode(int enable)
+{
+ if (enable)
+ tputs("\e[?2004h", 0, term_putchar);
+ else
+ tputs("\e[?2004l", 0, term_putchar);
+}
diff --git a/src/fe-text/term.h b/src/fe-text/term.h
index f0a76c42..5f0a799e 100644
--- a/src/fe-text/term.h
+++ b/src/fe-text/term.h
@@ -94,6 +94,8 @@ void term_refresh(TERM_WINDOW *window);
void term_stop(void);
+void term_set_bracketed_paste_mode(int enable);
+
/* keyboard input handling */
void term_set_input_type(int type);
void term_gets(GArray *buffer, int *line_count);
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index 3cc105ba..6baf2f6d 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -61,16 +61,16 @@ static int knockout_tag;
/* SYNTAX: NOTICE <targets> <message> */
static void cmd_notice(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
const char *target, *msg;
char *recoded;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST,
- &target, &msg))
+ &target, &msg))
return;
if (g_strcmp0(target, "*") == 0)
target = item == NULL ? NULL : window_item_get_target(item);
@@ -88,16 +88,16 @@ static void cmd_notice(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: CTCP <targets> <ctcp command> [<ctcp data>] */
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
const char *target;
char *ctcpcmd, *ctcpdata;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
- &target, &ctcpcmd, &ctcpdata))
+ &target, &ctcpcmd, &ctcpdata))
return;
if (g_strcmp0(target, "*") == 0)
target = item == NULL ? NULL : window_item_get_target(item);
@@ -122,16 +122,16 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: NCTCP <targets> <ctcp command> [<ctcp data>] */
static void cmd_nctcp(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
const char *target;
char *ctcpcmd, *ctcpdata, *recoded;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
- &target, &ctcpcmd, &ctcpdata))
+ &target, &ctcpcmd, &ctcpdata))
return;
if (g_strcmp0(target, "*") == 0)
target = item == NULL ? NULL : window_item_get_target(item);
@@ -150,22 +150,22 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: PART [<channels>] [<message>] */
static void cmd_part(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
char *channame, *msg;
char *recoded = NULL;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
- PARAM_FLAG_OPTCHAN, item, &channame, &msg))
+ PARAM_FLAG_OPTCHAN, item, &channame, &msg))
return;
if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*msg == '\0') msg = (char *) settings_get_str("part_message");
- if (server->cmdcount > MAX_COMMANDS_ON_PART_UNTIL_PURGE)
+ if (server->cmdcount > MAX_COMMANDS_ON_PART_UNTIL_PURGE)
irc_server_purge_output(server, channame);
if (*msg != '\0')
@@ -186,11 +186,11 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
char *channame, *nicks, *reason, *recoded;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST |
- PARAM_FLAG_OPTCHAN, item,
- &channame, &nicks, &reason))
+ PARAM_FLAG_OPTCHAN, item,
+ &channame, &nicks, &reason))
return;
if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -213,11 +213,11 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *ite
char *recoded = NULL;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN |
- PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
- item, "topic", &optlist, &channame, &topic))
+ PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+ item, "topic", &optlist, &channame, &topic))
return;
if (*topic != '\0' || g_hash_table_lookup(optlist, "delete") != NULL)
@@ -239,7 +239,7 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *it
char *nick, *channame;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2, &nick, &channame))
return;
@@ -258,17 +258,17 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *it
/* SYNTAX: LIST [-yes] [<channel>] */
static void cmd_list(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
GHashTable *optlist;
char *str;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
- "list", &optlist, &str))
+ PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+ "list", &optlist, &str))
return;
if (*str == '\0' && g_hash_table_lookup(optlist, "yes") == NULL &&
@@ -282,7 +282,7 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: WHO [<nicks> | <channels> | **] */
static void cmd_who(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
char *channel, *rest;
void *free_arg;
@@ -290,7 +290,7 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
- PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest))
+ PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest))
return;
if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
@@ -313,29 +313,29 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
}
static void cmd_names(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
- GHashTable *optlist;
+ GHashTable *optlist;
char *channel;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
- "names", &optlist, &channel))
+ PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+ "names", &optlist, &channel))
return;
if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
if (!IS_IRC_CHANNEL(item))
- cmd_param_error(CMDERR_NOT_JOINED);
+ cmd_param_error(CMDERR_NOT_JOINED);
channel = IRC_CHANNEL(item)->name;
}
if (g_strcmp0(channel, "**") == 0) {
/* ** displays all nicks.. */
- irc_send_cmd(server, "NAMES");
+ irc_send_cmd(server, "NAMES");
} else {
irc_send_cmdv(server, "NAMES %s", channel);
}
@@ -346,12 +346,12 @@ static void cmd_names(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: NICK <new nick> */
static void cmd_nick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
{
- char *nick;
+ char *nick;
void *free_arg;
g_return_if_fail(data != NULL);
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 1, &nick))
return;
@@ -388,23 +388,23 @@ static char *get_redirect_nicklist(const char *nicks, int *free)
/* SYNTAX: WHOIS [-<server tag>] [<server>] [<nicks>] */
static void cmd_whois(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
GHashTable *optlist;
char *qserver, *query, *event_402, *str;
void *free_arg;
int free_nick;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_UNKNOWN_OPTIONS,
- "whois", &optlist, &qserver, &query))
+ PARAM_FLAG_UNKNOWN_OPTIONS,
+ "whois", &optlist, &qserver, &query))
return;
/* -<server tag> */
server = IRC_SERVER(cmd_options_get_server("whois", optlist,
- SERVER(server)));
+ SERVER(server)));
if (server == NULL) {
cmd_params_free(free_arg);
return;
@@ -439,15 +439,15 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
str = g_strconcat(qserver, " ", query, NULL);
server_redirect_event(server, "whois", 1, str, TRUE,
- NULL,
- "event 318", "whois end",
- "event 402", event_402,
- "event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
- "event 313", "whois oper",
- "event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
- "event 311", "whois event",
- "", "whois default event", NULL);
- g_free(str);
+ NULL,
+ "event 318", "whois end",
+ "event 402", event_402,
+ "event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
+ "event 313", "whois oper",
+ "event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
+ "event 311", "whois event",
+ "", "whois default event", NULL);
+ g_free(str);
server->whois_found = FALSE;
irc_send_cmd_split(server, tmpstr->str, 2, server->max_whois_in_cmd);
@@ -457,7 +457,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
}
static void event_whois(IRC_SERVER_REC *server, const char *data,
- const char *nick, const char *addr)
+ const char *nick, const char *addr)
{
server->whois_found = TRUE;
signal_emit("event 311", 4, server, data, nick, addr);
@@ -473,23 +473,23 @@ static void sig_whois_try_whowas(IRC_SERVER_REC *server, const char *data)
server->whowas_found = FALSE;
server_redirect_event(server, "whowas", 1, nick, -1, NULL,
- "event 314", "whowas event",
- "event 369", "whowas event end",
- "event 406", "event empty", NULL);
+ "event 314", "whowas event",
+ "event 369", "whowas event end",
+ "event 406", "event empty", NULL);
irc_send_cmdv(server, "WHOWAS %s 1", nick);
g_free(params);
}
static void event_end_of_whois(IRC_SERVER_REC *server, const char *data,
- const char *nick, const char *addr)
+ const char *nick, const char *addr)
{
signal_emit("event 318", 4, server, data, nick, addr);
server->whois_found = FALSE;
}
static void event_whowas(IRC_SERVER_REC *server, const char *data,
- const char *nick, const char *addr)
+ const char *nick, const char *addr)
{
server->whowas_found = TRUE;
signal_emit("event 314", 4, server, data, nick, addr);
@@ -502,17 +502,17 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
void *free_arg;
int free_nick;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
- &nicks, &rest))
+ &nicks, &rest))
return;
if (*nicks == '\0') nicks = server->nick;
nicks_redir = get_redirect_nicklist(nicks, &free_nick);
server_redirect_event(server, "whowas", 1, nicks_redir, -1, NULL,
- "event 301", "whowas away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
- "event 314", "whowas event", NULL);
+ "event 301", "whowas away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
+ "event 314", "whowas event", NULL);
if (free_nick) g_free(nicks_redir);
server->whowas_found = FALSE;
@@ -529,9 +529,9 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
{
GTimeVal tv;
- char *str;
+ char *str;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (*data == '\0') {
if (!IS_QUERY(item))
@@ -554,7 +554,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server)
void *free_arg;
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_GETREST, "away", &optlist, &reason)) return;
+ PARAM_FLAG_GETREST, "away", &optlist, &reason)) return;
if (g_hash_table_lookup(optlist, "one") != NULL)
irc_server_send_away(server, reason);
@@ -567,7 +567,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server)
/* SYNTAX: SCONNECT <new server> [[<port>] <existing server>] */
static void cmd_sconnect(const char *data, IRC_SERVER_REC *server)
{
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
irc_send_cmdv(server, "CONNECT %s", data);
@@ -600,11 +600,11 @@ static void cmd_wait(const char *data, IRC_SERVER_REC *server)
void *free_arg;
int n;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
- NULL, &optlist, &msecs))
+ PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
+ NULL, &optlist, &msecs))
return;
if (*msecs == '\0')
@@ -612,7 +612,7 @@ static void cmd_wait(const char *data, IRC_SERVER_REC *server)
/* -<server tag> */
server = IRC_SERVER(cmd_options_get_server(NULL, optlist,
- SERVER(server)));
+ SERVER(server)));
n = atoi(msecs);
if (server != NULL && n > 0) {
@@ -635,10 +635,10 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
IRC_CHANNEL_REC *chanrec;
GSList *tmp, *nicks;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN |
- PARAM_FLAG_GETREST, item, &channame, &msg))
+ PARAM_FLAG_GETREST, item, &channame, &msg))
return;
if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -654,11 +654,11 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
/* Fall back to manually noticing each op */
nicks = NULL;
g_hash_table_foreach(chanrec->nicks,
- (GHFunc) cmd_wall_hash, &nicks);
+ (GHFunc) cmd_wall_hash, &nicks);
args = g_strconcat(chanrec->name, " ", recoded, NULL);
msg = parse_special_string(settings_get_str("wall_format"),
- SERVER(server), item, args, NULL, 0);
+ SERVER(server), item, args, NULL, 0);
g_free(args);
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
@@ -666,7 +666,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
if (rec != chanrec->ownnick) {
irc_send_cmdv(server, "NOTICE %s :%s",
- rec->nick, msg);
+ rec->nick, msg);
}
}
@@ -680,17 +680,17 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
/* SYNTAX: KICKBAN [<channel>] <nicks> <reason> */
static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
- WI_ITEM_REC *item)
+ WI_ITEM_REC *item)
{
- IRC_CHANNEL_REC *chanrec;
+ IRC_CHANNEL_REC *chanrec;
char *channel, *nicks, *reason, *kickcmd, *bancmd, *recoded;
- char **nicklist, *spacenicks;
+ char **nicklist, *spacenicks;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
- item, &channel, &nicks, &reason))
+ item, &channel, &nicks, &reason))
return;
if (*channel == '\0' || *nicks == '\0')
@@ -701,7 +701,7 @@ static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
cmd_param_error(CMDERR_CHAN_NOT_FOUND);
nicklist = g_strsplit(nicks, ",", -1);
- spacenicks = g_strjoinv(" ", nicklist);
+ spacenicks = g_strjoinv(" ", nicklist);
g_strfreev(nicklist);
recoded = recode_out(SERVER(server), reason, channel);
@@ -709,9 +709,9 @@ static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
g_free(recoded);
bancmd = g_strdup_printf("%s %s", chanrec->name, spacenicks);
- g_free(spacenicks);
+ g_free(spacenicks);
- if (settings_get_bool("kick_first_on_kickban")) {
+ if (settings_get_bool("kick_first_on_kickban")) {
signal_emit("command kick", 3, kickcmd, server, chanrec);
signal_emit("command ban", 3, bancmd, server, chanrec);
} else {
@@ -742,14 +742,14 @@ static void knockout_timeout_server(IRC_SERVER_REC *server)
if (!IS_IRC_SERVER(server))
return;
- now = time(NULL);
+ now = time(NULL);
for (tmp = server->knockoutlist; tmp != NULL; tmp = next) {
KNOCKOUT_REC *rec = tmp->data;
next = tmp->next;
if (rec->unban_time <= now) {
/* timeout, unban. */
- ban_remove(rec->channel, rec->ban);
+ signal_emit("command unban", 3, rec->ban, server, rec->channel);
knockout_destroy(server, rec);
}
}
@@ -763,16 +763,16 @@ static int knockout_timeout(void)
/* SYNTAX: KNOCKOUT [<time>] <nicks> <reason> */
static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
- IRC_CHANNEL_REC *channel)
+ IRC_CHANNEL_REC *channel)
{
KNOCKOUT_REC *rec;
char *nicks, *reason, *timeoutstr, *kickcmd, *bancmd, *recoded;
- char **nicklist, *spacenicks, *banmasks;
+ char **nicklist, *spacenicks, *banmasks;
void *free_arg;
int timeleft;
GSList *ptr;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!IS_IRC_CHANNEL(channel))
cmd_return_error(CMDERR_NOT_JOINED);
@@ -780,14 +780,14 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
if (i_isdigit(*data)) {
/* first argument is the timeout */
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
- &timeoutstr, &nicks, &reason))
+ &timeoutstr, &nicks, &reason))
return;
if (!parse_time_interval(timeoutstr, &timeleft))
cmd_param_error(CMDERR_INVALID_TIME);
} else {
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST,
- &nicks, &reason))
+ &nicks, &reason))
return;
timeleft = settings_get_time("knockout_time");
}
@@ -795,7 +795,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
if (*nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
nicklist = g_strsplit(nicks, ",", -1);
- spacenicks = g_strjoinv(" ", nicklist);
+ spacenicks = g_strjoinv(" ", nicklist);
g_strfreev(nicklist);
banmasks = ban_get_masks(channel, spacenicks, 0);
@@ -808,7 +808,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
bancmd = *banmasks == '\0'? NULL :
g_strdup_printf("%s %s", channel->name, banmasks);
- if (settings_get_bool("kick_first_on_kickban")) {
+ if (settings_get_bool("kick_first_on_kickban")) {
signal_emit("command kick", 3, kickcmd, server, channel);
if (bancmd != NULL)
signal_emit("command ban", 3, bancmd, server, channel);
@@ -827,7 +827,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
for (ptr = server->knockoutlist; ptr != NULL; ptr = ptr->next) {
rec = ptr->data;
if (channel == rec->channel &&
- !g_strcmp0(rec->ban, banmasks))
+ !g_strcmp0(rec->ban, banmasks))
break;
}
if (ptr == NULL) {
@@ -845,10 +845,10 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server,
/* SYNTAX: SERVER PURGE [<target>] */
static void cmd_server_purge(const char *data, IRC_SERVER_REC *server)
{
- char *target;
+ char *target;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 1, &target))
return;
@@ -895,12 +895,12 @@ static void cmd_oper(const char *data, IRC_SERVER_REC *server)
char *nick, *password;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
- /* asking for password is handled by fe-common */
+ /* asking for password is handled by fe-common */
if (!cmd_get_params(data, &free_arg, 2, &nick, &password))
return;
- if (*password == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+ if (*password == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
irc_send_cmdv(server, "OPER %s %s", nick, password);
cmd_params_free(free_arg);
@@ -909,7 +909,7 @@ static void cmd_oper(const char *data, IRC_SERVER_REC *server)
/* SYNTAX: ACCEPT [[-]nick,...] */
static void cmd_accept(const char *data, IRC_SERVER_REC *server)
{
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (*data == '\0')
irc_send_cmd(server, "ACCEPT *");
@@ -920,7 +920,7 @@ static void cmd_accept(const char *data, IRC_SERVER_REC *server)
/* SYNTAX: UNSILENCE <nick!user@host> */
static void cmd_unsilence(const char *data, IRC_SERVER_REC *server)
{
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (*data == '\0')
cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -953,7 +953,7 @@ static void command_2self(const char *data, IRC_SERVER_REC *server)
char *target, *text;
void *free_arg;
- CMD_IRC_SERVER(server);
+ CMD_IRC_SERVER(server);
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text))
return;
@@ -998,8 +998,8 @@ void irc_commands_init(void)
command_bind_irc("admin", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: INFO [<server>] */
command_bind_irc("info", NULL, (SIGNAL_FUNC) command_self);
- /* SYNTAX: KNOCK <channel> */
- command_bind_irc("knock", NULL, (SIGNAL_FUNC) command_self);
+ /* SYNTAX: KNOCK <channel> */
+ command_bind_irc("knock", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: LINKS [[<server>] <mask>] */
command_bind_irc("links", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: LUSERS [<server mask> [<remote server>]] */
@@ -1081,7 +1081,7 @@ void irc_commands_deinit(void)
command_unbind("accept", (SIGNAL_FUNC) cmd_accept);
command_unbind("admin", (SIGNAL_FUNC) command_self);
command_unbind("info", (SIGNAL_FUNC) command_self);
- command_unbind("knock", (SIGNAL_FUNC) command_self);
+ command_unbind("knock", (SIGNAL_FUNC) command_self);
command_unbind("links", (SIGNAL_FUNC) command_self);
command_unbind("lusers", (SIGNAL_FUNC) command_self);
command_unbind("map", (SIGNAL_FUNC) command_self);
diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c
index 250a1fe8..86ff3ec5 100644
--- a/src/irc/flood/autoignore.c
+++ b/src/irc/flood/autoignore.c
@@ -66,7 +66,7 @@ static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host
mask = g_strdup_printf("%s!%s", nick, host);
if (level & check_level) {
- rec = ignore_find(server->tag, mask, NULL);
+ rec = ignore_find_full(server->tag, mask, NULL, NULL, 0);
if (rec == NULL)
autoignore_add(server, mask, level);
else
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index dcc94e6b..5dc9a704 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -681,8 +681,8 @@ static void read_settings(void)
while (add_listens != NULL) {
rec = add_listens->data;
add_listen(rec->ircnet, rec->port);
+ add_listens = g_slist_remove(add_listens, rec);
g_free(rec);
- add_listens = g_slist_remove(add_listens, add_listens->data);
}
g_strfreev(ports);
diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c
index d7a428e5..b641867f 100644
--- a/src/perl/perl-common.c
+++ b/src/perl/perl-common.c
@@ -246,10 +246,7 @@ char *perl_get_use_list(void)
void irssi_callXS(void (*subaddr)(pTHX_ CV* cv), CV *cv, SV **mark)
{
- dSP;
-
PUSHMARK(mark);
- PUTBACK;
(*subaddr)(aTHX_ cv);
}
diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c
index 2f28c718..cb690906 100644
--- a/src/perl/perl-core.c
+++ b/src/perl/perl-core.c
@@ -82,16 +82,18 @@ static void perl_script_destroy(PERL_SCRIPT_REC *script)
extern void boot_DynaLoader(pTHX_ CV* cv);
#if PERL_STATIC_LIBS == 1
-extern void boot_Irssi(CV *cv);
+extern void boot_Irssi(pTHX_ CV *cv);
XS(boot_Irssi_Core)
{
dXSARGS;
+ PERL_UNUSED_VAR(items);
irssi_callXS(boot_Irssi, cv, mark);
irssi_boot(Irc);
irssi_boot(UI);
irssi_boot(TextUI);
+ /* Make sure to keep this in line with perl_scripts_deinit below. */
XSRETURN_YES;
}
#endif
@@ -123,7 +125,7 @@ void perl_scripts_init(void)
perl_parse(my_perl, xs_init, G_N_ELEMENTS(perl_args), perl_args, NULL);
#if PERL_STATIC_LIBS == 1
- perl_eval_pv("Irssi::Core::boot_Irssi_Core();", TRUE);
+ perl_eval_pv("Irssi::Core::->boot_Irssi_Core(0.9);", TRUE);
#endif
perl_common_start();
@@ -155,6 +157,17 @@ void perl_scripts_deinit(void)
/* Unload all perl libraries loaded with dynaloader */
perl_eval_pv("foreach my $lib (@DynaLoader::dl_modules) { if ($lib =~ /^Irssi\\b/) { $lib .= '::deinit();'; eval $lib; } }", TRUE);
+#if PERL_STATIC_LIBS == 1
+ /* If perl is statically built we should manually deinit the modules
+ which are booted in boot_Irssi_Core above */
+ perl_eval_pv("foreach my $lib (qw("
+ "Irssi" " "
+ "Irssi::Irc" " "
+ "Irssi::UI" " "
+ "Irssi::TextUI"
+ ")) { eval $lib . '::deinit();'; }", TRUE);
+#endif
+
/* We could unload all libraries .. but this crashes with some
libraries, probably because we don't call some deinit function..
Anyway, this would free some memory with /SCRIPT RESET, but it