From 3c95f6aae9826c10a50c4a0f12c16fca6038410c Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Mon, 2 Nov 2015 08:00:52 -0500
Subject: [PATCH 001/140] Make C-w and M-backspace work right.
---
src/fe-text/gui-entry.c | 38 +++++++++++++++++++++++++++-----------
src/fe-text/gui-entry.h | 4 +++-
src/fe-text/gui-readline.c | 7 +++++--
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 17a7c507..b7d58019 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -555,16 +555,31 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
return;
if (update_cutbuffer) {
- /* put erased text to cutbuffer */
- if (entry->cutbuffer_len < size) {
- g_free(entry->cutbuffer);
- entry->cutbuffer = g_new(unichar, size+1);
- }
+ if (entry->cutbuffer_len && update_cutbuffer == CUTBUFFER_PREPEND) {
+ int cutbuffer_new_size = entry->cutbuffer_len + size;
+ unichar *tmpcutbuffer = entry->cutbuffer;
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- entry->cutbuffer_len = size;
- entry->cutbuffer[size] = '\0';
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ memcpy(entry->cutbuffer + size, tmpcutbuffer,
+
+ entry->cutbuffer_len * sizeof(unichar));
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
+
+ g_free(tmpcutbuffer);
+ } else if (update_cutbuffer) {
+ /* put erased text to cutbuffer */
+ if (entry->cutbuffer_len < size) {
+ g_free(entry->cutbuffer);
+ entry->cutbuffer = g_new(unichar, size+1);
+ }
+ entry->cutbuffer_len = size;
+ entry->cutbuffer[size] = '\0';
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ }
}
if (entry->utf8)
@@ -601,7 +616,7 @@ void gui_entry_erase_cell(GUI_ENTRY_REC *entry)
gui_entry_draw(entry);
}
-void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
+void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat)
{
int to;
@@ -624,7 +639,8 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
}
if (to > 0) to++;
- gui_entry_erase(entry, entry->pos-to, TRUE);
+ gui_entry_erase(entry, entry->pos-to,
+ repeat ? CUTBUFFER_PREPEND : TRUE);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index 29d8dea2..006a1858 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -1,6 +1,8 @@
#ifndef __GUI_ENTRY_H
#define __GUI_ENTRY_H
+#define CUTBUFFER_PREPEND 42
+
typedef struct {
int text_len, text_alloc; /* as shorts, not chars */
unichar *text;
@@ -43,7 +45,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer);
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer);
void gui_entry_erase_cell(GUI_ENTRY_REC *entry);
-void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space);
+void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat);
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space);
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry);
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index ec61e317..4d645748 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -68,6 +68,8 @@ static int paste_timeout_id;
static void sig_input(void);
+static int key_repeated = FALSE;
+
void input_listen_init(int handle)
{
readtag = g_input_add_poll(handle,
@@ -361,6 +363,7 @@ static void sig_gui_key_pressed(gpointer keyp)
int ret;
key = GPOINTER_TO_INT(keyp);
+ key_repeated = key == prev_key;
if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HOTKEY) {
handle_key_redirect(key);
@@ -596,7 +599,7 @@ static void key_backspace(void)
static void key_delete_previous_word(void)
{
- gui_entry_erase_word(active_entry, FALSE);
+ gui_entry_erase_word(active_entry, FALSE, key_repeated);
}
static void key_delete_next_word(void)
@@ -606,7 +609,7 @@ static void key_delete_next_word(void)
static void key_delete_to_previous_space(void)
{
- gui_entry_erase_word(active_entry, TRUE);
+ gui_entry_erase_word(active_entry, TRUE, key_repeated);
}
static void key_delete_to_next_space(void)
From 1199ecc62f137eedb388b3dbd9b003cf1a8280f7 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Fri, 13 Nov 2015 13:42:28 -0500
Subject: [PATCH 002/140] a facility for prepending or replacing the cutbuffer
---
src/fe-text/gui-entry.c | 47 +++++++++++++++++++++-----------------
src/fe-text/gui-entry.h | 13 ++++++++---
src/fe-text/gui-readline.c | 12 +++++-----
3 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index a83bcf64..ec484cb5 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -534,7 +534,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
return buf;
}
-void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer)
+void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer)
{
int newpos, size = 0;
@@ -545,7 +545,7 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer)
gui_entry_erase(entry, size, update_cutbuffer);
}
-void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
+void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer)
{
size_t w = 0;
@@ -554,32 +554,39 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
if (size == 0 || entry->pos < size)
return;
- if (update_cutbuffer) {
- if (entry->cutbuffer_len && update_cutbuffer == CUTBUFFER_PREPEND) {
- int cutbuffer_new_size = entry->cutbuffer_len + size;
- unichar *tmpcutbuffer = entry->cutbuffer;
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ switch (update_cutbuffer) {
+ case CUTBUFFER_UPDATE_PREPEND:
+ if (entry->cutbuffer_len) {
+ int cutbuffer_new_size = entry->cutbuffer_len + size;
+ unichar *tmpcutbuffer = entry->cutbuffer;
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
- memcpy(entry->cutbuffer + size, tmpcutbuffer,
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ memcpy(entry->cutbuffer + size, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
+ entry->cutbuffer_len * sizeof(unichar));
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
- g_free(tmpcutbuffer);
- } else if (update_cutbuffer) {
+ g_free(tmpcutbuffer);
+ break;
+ }
+ /* fall through to REPLACE if cutbuffer_len was 0 */
+ case CUTBUFFER_UPDATE_REPLACE:
/* put erased text to cutbuffer */
if (entry->cutbuffer_len < size) {
g_free(entry->cutbuffer);
entry->cutbuffer = g_new(unichar, size+1);
}
+
entry->cutbuffer_len = size;
entry->cutbuffer[size] = '\0';
memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
- }
+ size * sizeof(unichar));
+ break;
+ case CUTBUFFER_UPDATE_NOOP:
+ break;
}
if (entry->utf8)
@@ -616,7 +623,7 @@ void gui_entry_erase_cell(GUI_ENTRY_REC *entry)
gui_entry_draw(entry);
}
-void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat)
+void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op)
{
int to;
@@ -639,8 +646,6 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat)
}
if (to > 0) to++;
- gui_entry_erase(entry, entry->pos-to,
- repeat ? CUTBUFFER_PREPEND : TRUE);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
@@ -666,7 +671,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
size = to-entry->pos;
entry->pos = to;
- gui_entry_erase(entry, size, TRUE);
+ gui_entry_erase(entry, size, CUTBUFFER_UPDATE_REPLACE);
}
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index 006a1858..0f86e431 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -22,6 +22,12 @@ typedef struct {
unsigned int utf8:1;
} GUI_ENTRY_REC;
+typedef enum {
+ CUTBUFFER_UPDATE_NOOP,
+ CUTBUFFER_UPDATE_REPLACE,
+ CUTBUFFER_UPDATE_PREPEND
+} CUTBUFFER_UPDATE_OP;
+
extern GUI_ENTRY_REC *active_entry;
GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8);
@@ -42,10 +48,10 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str);
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr);
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
-void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer);
-void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer);
+void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer);
+void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer);
void gui_entry_erase_cell(GUI_ENTRY_REC *entry);
-void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat);
+void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op);
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space);
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry);
@@ -62,4 +68,5 @@ void gui_entry_move_words(GUI_ENTRY_REC *entry, int count, int to_space);
void gui_entry_redraw(GUI_ENTRY_REC *entry);
+
#endif
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index c21925db..47689b4d 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -530,7 +530,7 @@ static void key_forward_to_space(void)
static void key_erase_line(void)
{
gui_entry_set_pos(active_entry, active_entry->text_len);
- gui_entry_erase(active_entry, active_entry->text_len, TRUE);
+ gui_entry_erase(active_entry, active_entry->text_len, CUTBUFFER_UPDATE_REPLACE);
}
static void key_erase_to_beg_of_line(void)
@@ -538,7 +538,7 @@ static void key_erase_to_beg_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
- gui_entry_erase(active_entry, pos, TRUE);
+ gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_REPLACE);
}
static void key_erase_to_end_of_line(void)
@@ -547,7 +547,7 @@ static void key_erase_to_end_of_line(void)
pos = gui_entry_get_pos(active_entry);
gui_entry_set_pos(active_entry, active_entry->text_len);
- gui_entry_erase(active_entry, active_entry->text_len - pos, TRUE);
+ gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_REPLACE);
}
static void key_yank_from_cutbuffer(void)
@@ -594,12 +594,12 @@ static void key_delete_character(void)
static void key_backspace(void)
{
- gui_entry_erase(active_entry, 1, FALSE);
+ gui_entry_erase(active_entry, 1, CUTBUFFER_UPDATE_NOOP);
}
static void key_delete_previous_word(void)
{
- gui_entry_erase_word(active_entry, FALSE, key_repeated);
+ gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_REPLACE);
}
static void key_delete_next_word(void)
@@ -609,7 +609,7 @@ static void key_delete_next_word(void)
static void key_delete_to_previous_space(void)
{
- gui_entry_erase_word(active_entry, TRUE, key_repeated);
+ gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_REPLACE);
}
static void key_delete_to_next_space(void)
From 7768f3e52074715e9c83bcded8607500e4434468 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Fri, 13 Nov 2015 13:51:56 -0500
Subject: [PATCH 003/140] remove cruft from previous implementation
---
src/fe-text/gui-entry.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index 0f86e431..498f95b9 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -1,8 +1,6 @@
#ifndef __GUI_ENTRY_H
#define __GUI_ENTRY_H
-#define CUTBUFFER_PREPEND 42
-
typedef struct {
int text_len, text_alloc; /* as shorts, not chars */
unichar *text;
From f90e10c5d27ee7d8a6663a432238cf487e7d372f Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Fri, 13 Nov 2015 14:01:25 -0500
Subject: [PATCH 004/140] remove more cruft from previous implementation
---
src/fe-text/gui-readline.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 47689b4d..0ca68d80 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -68,8 +68,6 @@ static int paste_timeout_id;
static void sig_input(void);
-static int key_repeated = FALSE;
-
void input_listen_init(int handle)
{
readtag = g_input_add_poll(handle,
@@ -363,7 +361,6 @@ static void sig_gui_key_pressed(gpointer keyp)
int ret;
key = GPOINTER_TO_INT(keyp);
- key_repeated = key == prev_key;
if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HOTKEY) {
handle_key_redirect(key);
From bb8c0bbf4caf87172255993ce8a86f91a8cd4208 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Fri, 13 Nov 2015 20:33:57 -0500
Subject: [PATCH 005/140] fix indentation, undelete line not meant to be
deleted.
---
src/fe-text/gui-entry.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index ec484cb5..650995bd 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -564,8 +564,8 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
memcpy(entry->cutbuffer, entry->text + entry->pos - size,
size * sizeof(unichar));
memcpy(entry->cutbuffer + size, tmpcutbuffer,
+ entry->cutbuffer_len * sizeof(unichar));
- entry->cutbuffer_len * sizeof(unichar));
entry->cutbuffer_len = cutbuffer_new_size;
entry->cutbuffer[cutbuffer_new_size] = '\0';
@@ -646,6 +646,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O
}
if (to > 0) to++;
+ gui_entry_erase(entry, entry->pos-to, TRUE);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
From 15dfb27f80922f6f3b751da9e1395994c3026a62 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Sat, 14 Nov 2015 09:07:35 -0500
Subject: [PATCH 006/140] use the enum name which was the original intended
change
---
src/fe-text/gui-entry.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 650995bd..176ee431 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -646,7 +646,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O
}
if (to > 0) to++;
- gui_entry_erase(entry, entry->pos-to, TRUE);
+ gui_entry_erase(entry, entry->pos-to, CUTBUFFER_UPDATE_REPLACE);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
From 25020808710f359e75a85a5252bf0f72443d09ee Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Thu, 14 Jan 2016 23:54:42 +0100
Subject: [PATCH 007/140] Change when the autocmds are sent.
As per #175 if a -botcmd is specified for a given channel without a
-bots parameter then the command is sent right after joining the
channel.
---
src/core/channels.c | 15 ++++++++++++---
src/irc/core/irc-channels-setup.c | 2 ++
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/core/channels.c b/src/core/channels.c
index 9af8b844..bfde605e 100644
--- a/src/core/channels.c
+++ b/src/core/channels.c
@@ -245,9 +245,18 @@ void channel_send_autocommands(CHANNEL_REC *channel)
if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd)
return;
- if (rec->botmasks == NULL || !*rec->botmasks) {
- /* just send the command. */
- eval_special_string(rec->autosendcmd, "", channel->server, channel);
+ if (channel->wholist == FALSE) {
+ /* if the autosendcmd alone (with no -bots parameter) has been
+ * specified then send it right after joining the channel, when
+ * the WHO list hasn't been yet retrieved.
+ * Depending on the value of the 'channel_max_who_sync' option
+ * the WHO list might not be retrieved after the join event. */
+
+ if (rec->botmasks == NULL || !*rec->botmasks) {
+ /* just send the command. */
+ eval_special_string(rec->autosendcmd, "", channel->server, channel);
+ }
+
return;
}
diff --git a/src/irc/core/irc-channels-setup.c b/src/irc/core/irc-channels-setup.c
index 2320352d..be69ad63 100644
--- a/src/irc/core/irc-channels-setup.c
+++ b/src/irc/core/irc-channels-setup.c
@@ -25,9 +25,11 @@
void irc_channels_setup_init(void)
{
signal_add("channel wholist", (SIGNAL_FUNC) channel_send_autocommands);
+ signal_add("channel joined", (SIGNAL_FUNC) channel_send_autocommands);
}
void irc_channels_setup_deinit(void)
{
signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_autocommands);
+ signal_remove("channel joined", (SIGNAL_FUNC) channel_send_autocommands);
}
From 4af3a4731ee21f063b90fdb051efa90f6788d99f Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 12 Jan 2016 23:38:50 +0100
Subject: [PATCH 008/140] continue head
---
INSTALL | 3 ++-
NEWS | 2 +-
configure.ac | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/INSTALL b/INSTALL
index a83a6c76..234c6cf6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,8 @@ To compile irssi you need:
For most people, this should work just fine:
- ./configure
+ ./autogen.sh (for people who just cloned the repository)
+ ./configure (if this script already exists, skip ./autogen.sh)
make
su
make install (not _really_ required except for perl support)
diff --git a/NEWS b/NEWS
index 405e8b4c..f44fdb56 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-v0.8.18-beta2 2016-01-13 The Irssi team
+v0.8.18-head 2016-xx-xx The Irssi team
* Modules will now require to define a
void MODULENAME ## _abicheck(int *version)
method to ensure that they are compiled against the correct Irssi
diff --git a/configure.ac b/configure.ac
index bf39c95f..c0efd5e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(irssi, 0.8.18-beta2)
+AC_INIT(irssi, 0.8.18-head)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_AUX_DIR(build-aux)
AC_PREREQ(2.50)
From eba160ca6df194913d80df67c19e929b9428d77e Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 24 Jan 2016 23:02:40 +0100
Subject: [PATCH 009/140] Duplicate the code paths for autocommands.
---
src/core/channels.c | 40 +++++++++++++++++++++----------
src/core/channels.h | 1 +
src/irc/core/irc-channels-setup.c | 4 ++--
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/src/core/channels.c b/src/core/channels.c
index bfde605e..9c3b92ba 100644
--- a/src/core/channels.c
+++ b/src/core/channels.c
@@ -231,6 +231,31 @@ static int match_nick_flags(SERVER_REC *server, NICK_REC *nick, char flag)
/* Send the auto send command to channel */
void channel_send_autocommands(CHANNEL_REC *channel)
+{
+ CHANNEL_SETUP_REC *rec;
+
+ g_return_if_fail(IS_CHANNEL(channel));
+
+ if (channel->session_rejoin)
+ return;
+
+ rec = channel_setup_find(channel->name, channel->server->connrec->chatnet);
+ if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd)
+ return;
+
+ /* if the autosendcmd alone (with no -bots parameter) has been
+ * specified then send it right after joining the channel, when
+ * the WHO list hasn't been yet retrieved.
+ * Depending on the value of the 'channel_max_who_sync' option
+ * the WHO list might not be retrieved after the join event. */
+
+ if (rec->botmasks == NULL || !*rec->botmasks) {
+ /* just send the command. */
+ eval_special_string(rec->autosendcmd, "", channel->server, channel);
+ }
+}
+
+void channel_send_botcommands(CHANNEL_REC *channel)
{
CHANNEL_SETUP_REC *rec;
NICK_REC *nick;
@@ -245,20 +270,9 @@ void channel_send_autocommands(CHANNEL_REC *channel)
if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd)
return;
- if (channel->wholist == FALSE) {
- /* if the autosendcmd alone (with no -bots parameter) has been
- * specified then send it right after joining the channel, when
- * the WHO list hasn't been yet retrieved.
- * Depending on the value of the 'channel_max_who_sync' option
- * the WHO list might not be retrieved after the join event. */
-
- if (rec->botmasks == NULL || !*rec->botmasks) {
- /* just send the command. */
- eval_special_string(rec->autosendcmd, "", channel->server, channel);
- }
-
+ /* this case has already been handled by channel_send_autocommands */
+ if (rec->botmasks == NULL || !*rec->botmasks)
return;
- }
/* find first available bot.. */
bots = g_strsplit(rec->botmasks, " ", -1);
diff --git a/src/core/channels.h b/src/core/channels.h
index 0839d69b..bd136fe2 100644
--- a/src/core/channels.h
+++ b/src/core/channels.h
@@ -31,6 +31,7 @@ void channel_change_visible_name(CHANNEL_REC *channel, const char *name);
/* Send the auto send command to channel */
void channel_send_autocommands(CHANNEL_REC *channel);
+void channel_send_botcommands(CHANNEL_REC *channel);
void channels_init(void);
void channels_deinit(void);
diff --git a/src/irc/core/irc-channels-setup.c b/src/irc/core/irc-channels-setup.c
index be69ad63..bbbc095c 100644
--- a/src/irc/core/irc-channels-setup.c
+++ b/src/irc/core/irc-channels-setup.c
@@ -24,12 +24,12 @@
void irc_channels_setup_init(void)
{
- signal_add("channel wholist", (SIGNAL_FUNC) channel_send_autocommands);
+ signal_add("channel wholist", (SIGNAL_FUNC) channel_send_botcommands);
signal_add("channel joined", (SIGNAL_FUNC) channel_send_autocommands);
}
void irc_channels_setup_deinit(void)
{
- signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_autocommands);
+ signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_botcommands);
signal_remove("channel joined", (SIGNAL_FUNC) channel_send_autocommands);
}
From d964950e5ddf9b83c67326b3a45108de4e5a44f2 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 24 Jan 2016 23:53:31 +0100
Subject: [PATCH 010/140] Serialize the 'name' attribute of the CHANNEL_REC.
This way the code doing the serialization in 'sig_layout_save_item' is
now symmetric with the loading code loading the data in
'sig_layout_restore'.
---
src/fe-common/core/windows-layout.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/fe-common/core/windows-layout.c b/src/fe-common/core/windows-layout.c
index 8ebcc12d..ce6b9910 100644
--- a/src/fe-common/core/windows-layout.c
+++ b/src/fe-common/core/windows-layout.c
@@ -168,12 +168,12 @@ static void sig_layout_save_item(WINDOW_REC *window, WI_ITEM_REC *item,
chat_protocol_find_id(item->chat_type);
if (proto != NULL)
iconfig_node_set_str(subnode, "chat_type", proto->name);
- iconfig_node_set_str(subnode, "name", item->visible_name);
+ iconfig_node_set_str(subnode, "name", item->name);
if (item->server != NULL) {
iconfig_node_set_str(subnode, "tag", item->server->tag);
if (IS_CHANNEL(item)) {
- rec = window_bind_add(window, item->server->tag, item->visible_name);
+ rec = window_bind_add(window, item->server->tag, item->name);
if (rec != NULL)
rec->sticky = TRUE;
}
From b229138b2ef6efc4ab91504801e27e9922b766b4 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 26 Jan 2016 09:33:46 +0100
Subject: [PATCH 011/140] Update perl.txt
Mention known Perl Bugs (#386)
---
docs/perl.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/perl.txt b/docs/perl.txt
index 9688341f..59f65462 100644
--- a/docs/perl.txt
+++ b/docs/perl.txt
@@ -1193,3 +1193,7 @@ Client->{}
--------------------
* Calling die in 'script error' handler causes segfault (#101)
* Storing and later using any Irssi object may result in use-after-free related crash
+ - Workaround: always acquire fresh objects
+* Calling $dcc->close from the "dcc created" signal will cause unstable behaviour and crashes (#386)
+ - Workaround: use "dcc request" signal instead AND call
+ &Irssi::signal_continue(@_); as the first thing
From 87c0827471763ad5c086d1377ed91980e4b6c8d1 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 27 Jan 2016 14:31:55 +0100
Subject: [PATCH 012/140] Delete the HAVE_IPV6 ifdef.
Welcome to the future.
---
src/core/network.c | 112 ++++-----------------------------------------
src/core/network.h | 10 +---
2 files changed, 10 insertions(+), 112 deletions(-)
diff --git a/src/core/network.c b/src/core/network.c
index 0751aa95..4d3997a1 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -30,17 +30,11 @@
union sockaddr_union {
struct sockaddr sa;
struct sockaddr_in sin;
-#ifdef HAVE_IPV6
struct sockaddr_in6 sin6;
-#endif
};
-#ifdef HAVE_IPV6
-# define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
+#define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
sizeof(so.sin6) : sizeof(so.sin))
-#else
-# define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
-#endif
GIOChannel *g_io_channel_new(int handle)
{
@@ -56,7 +50,7 @@ GIOChannel *g_io_channel_new(int handle)
IPADDR ip4_any = {
AF_INET,
-#if defined(HAVE_IPV6) && defined(IN6ADDR_ANY_INIT)
+#if defined(IN6ADDR_ANY_INIT)
IN6ADDR_ANY_INIT
#else
{ INADDR_ANY }
@@ -68,10 +62,8 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2)
if (ip1->family != ip2->family)
return 0;
-#ifdef HAVE_IPV6
if (ip1->family == AF_INET6)
return memcmp(&ip1->ip, &ip2->ip, sizeof(ip1->ip)) == 0;
-#endif
return memcmp(&ip1->ip, &ip2->ip, 4) == 0;
}
@@ -80,22 +72,16 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2)
static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
{
if (ip == NULL) {
-#ifdef HAVE_IPV6
so->sin6.sin6_family = AF_INET6;
so->sin6.sin6_addr = in6addr_any;
-#else
- so->sin.sin_family = AF_INET;
- so->sin.sin_addr.s_addr = INADDR_ANY;
-#endif
return;
}
so->sin.sin_family = ip->family;
-#ifdef HAVE_IPV6
+
if (ip->family == AF_INET6)
memcpy(&so->sin6.sin6_addr, &ip->ip, sizeof(ip->ip));
else
-#endif
memcpy(&so->sin.sin_addr, &ip->ip, 4);
}
@@ -103,31 +89,25 @@ void sin_get_ip(const union sockaddr_union *so, IPADDR *ip)
{
ip->family = so->sin.sin_family;
-#ifdef HAVE_IPV6
if (ip->family == AF_INET6)
memcpy(&ip->ip, &so->sin6.sin6_addr, sizeof(ip->ip));
else
-#endif
memcpy(&ip->ip, &so->sin.sin_addr, 4);
}
static void sin_set_port(union sockaddr_union *so, int port)
{
-#ifdef HAVE_IPV6
if (so->sin.sin_family == AF_INET6)
so->sin6.sin6_port = htons((unsigned short)port);
else
-#endif
so->sin.sin_port = htons((unsigned short)port);
}
static int sin_get_port(union sockaddr_union *so)
{
-#ifdef HAVE_IPV6
- if (so->sin.sin_family == AF_INET6)
- return ntohs(so->sin6.sin6_port);
-#endif
- return ntohs(so->sin.sin_port);
+ return ntohs((so->sin.sin_family == AF_INET6) ?
+ so->sin6.sin6_port :
+ so->sin.sin_port);
}
/* Connect to socket */
@@ -272,7 +252,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port)
/* create the socket */
handle = socket(so.sin.sin_family, SOCK_STREAM, 0);
-#ifdef HAVE_IPV6
+
if (handle == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) {
/* IPv6 is not supported by OS */
so.sin.sin_family = AF_INET;
@@ -280,7 +260,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port)
handle = socket(AF_INET, SOCK_STREAM, 0);
}
-#endif
+
if (handle == -1)
return NULL;
@@ -399,21 +379,15 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
Returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{
-#ifdef HAVE_IPV6
union sockaddr_union *so;
struct addrinfo hints, *ai, *ailist;
int ret, count_v4, count_v6, use_v4, use_v6;
-#else
- struct hostent *hp;
- int count;
-#endif
g_return_val_if_fail(addr != NULL, -1);
memset(ip4, 0, sizeof(IPADDR));
memset(ip6, 0, sizeof(IPADDR));
-#ifdef HAVE_IPV6
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM;
@@ -454,44 +428,21 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
}
freeaddrinfo(ailist);
return 0;
-#else
- hp = gethostbyname(addr);
- if (hp == NULL)
- return h_errno;
-
- /* count IPs */
- count = 0;
- while (hp->h_addr_list[count] != NULL)
- count++;
-
- if (count == 0)
- return HOST_NOT_FOUND; /* shouldn't happen? */
-
- /* if there are multiple addresses, return random one */
- ip4->family = AF_INET;
- memcpy(&ip4->ip, hp->h_addr_list[rand() % count], 4);
-
- return 0;
-#endif
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name)
{
-#ifdef HAVE_IPV6
union sockaddr_union so;
int host_error;
char hostname[NI_MAXHOST];
-#else
- struct hostent *hp;
-#endif
g_return_val_if_fail(ip != NULL, -1);
g_return_val_if_fail(name != NULL, -1);
*name = NULL;
-#ifdef HAVE_IPV6
+
memset(&so, 0, sizeof(so));
sin_set_ip(&so, ip);
@@ -502,36 +453,15 @@ int net_gethostbyaddr(IPADDR *ip, char **name)
return host_error;
*name = g_strdup(hostname);
-#else
- if (ip->family != AF_INET) return -1;
- hp = gethostbyaddr((const char *) &ip->ip, 4, AF_INET);
- if (hp == NULL) return -1;
-
- *name = g_strdup(hp->h_name);
-#endif
return 0;
}
int net_ip2host(IPADDR *ip, char *host)
{
-#ifdef HAVE_IPV6
if (!inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN))
return -1;
-#else
- unsigned long ip4;
- if (ip->family != AF_INET) {
- strcpy(host, "0.0.0.0");
- } else {
- ip4 = ntohl(ip->ip.s_addr);
- g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu",
- (ip4 & 0xff000000UL) >> 24,
- (ip4 & 0x00ff0000) >> 16,
- (ip4 & 0x0000ff00) >> 8,
- (ip4 & 0x000000ff));
- }
-#endif
return 0;
}
@@ -542,12 +472,8 @@ int net_host2ip(const char *host, IPADDR *ip)
if (strchr(host, ':') != NULL) {
/* IPv6 */
ip->family = AF_INET6;
-#ifdef HAVE_IPV6
if (inet_pton(AF_INET6, host, &ip->ip) == 0)
return -1;
-#else
- ip->ip.s_addr = 0;
-#endif
} else {
/* IPv4 */
ip->family = AF_INET;
@@ -582,40 +508,20 @@ int net_geterror(GIOChannel *handle)
/* get error of net_gethostname() */
const char *net_gethosterror(int error)
{
-#ifdef HAVE_IPV6
g_return_val_if_fail(error != 0, NULL);
return gai_strerror(error);
-#else
- switch (error) {
- case HOST_NOT_FOUND:
- return "Host not found";
- case NO_ADDRESS:
- return "No IP address found for name";
- case NO_RECOVERY:
- return "A non-recovable name server error occurred";
- case TRY_AGAIN:
- return "A temporary error on an authoritative name server";
- }
-
- /* unknown error */
- return NULL;
-#endif
}
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error)
{
-#ifdef HAVE_IPV6
#ifdef EAI_NODATA /* NODATA is deprecated */
return error != 1 && (error == EAI_NONAME || error == EAI_NODATA);
#else
return error != 1 && (error == EAI_NONAME);
#endif
-#else
- return error == HOST_NOT_FOUND || error == NO_ADDRESS;
-#endif
}
/* Get name of TCP service */
diff --git a/src/core/network.h b/src/core/network.h
index 73ac8dee..fb627b4d 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -21,19 +21,11 @@
struct _IPADDR {
unsigned short family;
-#ifdef HAVE_IPV6
struct in6_addr ip;
-#else
- struct in_addr ip;
-#endif
};
/* maxmimum string length of IP address */
-#ifdef HAVE_IPV6
-# define MAX_IP_LEN INET6_ADDRSTRLEN
-#else
-# define MAX_IP_LEN 20
-#endif
+#define MAX_IP_LEN INET6_ADDRSTRLEN
#define IPADDR_IS_V6(ip) ((ip)->family != AF_INET)
From 70c7949cfe2f07545e5eeb4291631916ab28d07f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 27 Jan 2016 14:42:50 +0100
Subject: [PATCH 013/140] Update the configure script and INSTALL.
Now that HAVE_IPV6 is gone remove all the references from the
buildscript and documentation.
---
INSTALL | 4 ----
acconfig.h | 1 -
configure.ac | 33 ---------------------------------
3 files changed, 38 deletions(-)
diff --git a/INSTALL b/INSTALL
index 234c6cf6..4b20c1ba 100644
--- a/INSTALL
+++ b/INSTALL
@@ -29,10 +29,6 @@ configure options
Build the irssi proxy (see startup-HOWTO).
- --disable-ipv6
-
- Disable IPv6 support.
-
--disable-ssl
Disable SSL support.
diff --git a/acconfig.h b/acconfig.h
index 9ace70d8..53e268d7 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -1,5 +1,4 @@
/* misc.. */
-#undef HAVE_IPV6
#undef HAVE_SOCKS_H
#undef HAVE_STATIC_PERL
#undef HAVE_GMODULE
diff --git a/configure.ac b/configure.ac
index c0efd5e3..1a579911 100644
--- a/configure.ac
+++ b/configure.ac
@@ -140,15 +140,6 @@ AC_ARG_WITH(perl,
fi,
want_perl=static)
-AC_ARG_ENABLE(ipv6,
-[ --disable-ipv6 Disable IPv6 support],
- if test x$enableval = xno; then
- want_ipv6=no
- else
- want_ipv6=yes
- fi,
- want_ipv6=yes)
-
AC_ARG_ENABLE(dane,
[ --enable-dane Enable DANE support],
if test x$enableval = xno ; then
@@ -577,29 +568,6 @@ COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS"
AC_SUBST(COMMON_NOUI_LIBS)
AC_SUBST(COMMON_LIBS)
-dnl **
-dnl ** IPv6 support
-dnl **
-
-have_ipv6=no
-if test "x$want_ipv6" = "xyes"; then
- AC_MSG_CHECKING([for IPv6])
- AC_CACHE_VAL(irssi_cv_type_in6_addr,
- [AC_TRY_COMPILE([
- #include
- #include
- #include
- #include
- #include ],
- [struct in6_addr i = in6addr_any; return &i == &i;],
- have_ipv6=yes,
- )])
- if test $have_ipv6 = yes; then
- AC_DEFINE(HAVE_IPV6)
- fi
- AC_MSG_RESULT($have_ipv6)
-fi
-
have_dane=no
if test "x$want_dane" = "xyes"; then
AC_MSG_CHECKING([for DANE])
@@ -742,7 +710,6 @@ echo "Install prefix ................... : $prefix"
echo
-echo "Building with IPv6 support ....... : $have_ipv6"
echo "Building with SSL support ........ : $have_openssl"
if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then
if test -f /etc/debian_version; then
From f31b2026b4732e57f88af14796ac0dea4b2d0131 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 27 Jan 2016 15:04:07 +0100
Subject: [PATCH 014/140] Minor style fix in net_ip2host.
---
src/core/network.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/core/network.c b/src/core/network.c
index 4d3997a1..28189661 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -459,10 +459,7 @@ int net_gethostbyaddr(IPADDR *ip, char **name)
int net_ip2host(IPADDR *ip, char *host)
{
- if (!inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN))
- return -1;
-
- return 0;
+ return inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN) ? 0 : -1;
}
int net_host2ip(const char *host, IPADDR *ip)
From 118eb0a68ce3250aa4528e6086b2bd0567e7638c Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 27 Jan 2016 15:54:29 +0100
Subject: [PATCH 015/140] Call getnameinfo with NI_NAMEREQD flag.
This way net_gethostbyaddr will fail when the system is unable to
resolve the address to a valid host name.
Without this flag in case of failure the function would return the ip
address instead of failing.
---
src/core/network.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/core/network.c b/src/core/network.c
index 28189661..8abc1ba1 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -447,8 +447,10 @@ int net_gethostbyaddr(IPADDR *ip, char **name)
sin_set_ip(&so, ip);
/* save error to host_error for later use */
- host_error = getnameinfo((struct sockaddr *) &so, sizeof(so),
- hostname, sizeof(hostname), NULL, 0, 0);
+ host_error = getnameinfo((struct sockaddr *)&so, sizeof(so),
+ hostname, sizeof(hostname),
+ NULL, 0,
+ NI_NAMEREQD);
if (host_error != 0)
return host_error;
From 0cc8276e896441a186a8080f127e35d60112d758 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 27 Jan 2016 16:16:27 +0100
Subject: [PATCH 016/140] Add AI_ADDRCONFIG to the getaddrinfo hints.
A first step to untangle the ipv4 vs ipv6 mess.
At the time of writing Linux, OpenBSD and FreeBSD all support the
AI_ADDRCONFIG flag.
---
src/core/network.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/core/network.c b/src/core/network.c
index 28189661..d777bdcc 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -390,6 +390,7 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
/* save error to host_error for later use */
ret = getaddrinfo(addr, NULL, &hints, &ailist);
From 7674fd5936de3190f1fd3bba3ef82370a2941064 Mon Sep 17 00:00:00 2001
From: dequis
Date: Fri, 29 Jan 2016 10:40:18 -0300
Subject: [PATCH 017/140] completion: Fix crash when the complist provided by a
script has nulls
Can be reproduced with aspell_complete.pl 1.00 by setting an invalid
dictionary with "/set spell_dict a"
---
src/fe-common/core/completion.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index a4715d23..1e7833a4 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -217,6 +217,11 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i
want_space = TRUE;
signal_emit("complete word", 5, &complist, window, word, linestart, &want_space);
last_want_space = want_space;
+
+ if (complist != NULL) {
+ /* Remove all nulls (from the signal) before doing further processing */
+ complist = g_list_remove_all(g_list_first(complist), NULL);
+ }
}
g_free(linestart);
From 876609901a5476ab2764a8002b9c57d25dc34f20 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Sat, 30 Jan 2016 09:34:46 -0500
Subject: [PATCH 018/140] add an append operation to cut buffer handling
---
src/fe-text/gui-entry.c | 46 +++++++++++++++++++++++++++--------------
src/fe-text/gui-entry.h | 1 +
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 6e13ba4e..58743ac3 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -582,25 +582,40 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
if (size == 0 || entry->pos < size)
return;
+ if (entry->cutbuffer_len == 0) {
+ update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
+ }
+ int cutbuffer_new_size = entry->cutbuffer_len + size;
+ unichar *tmpcutbuffer = entry->cutbuffer;
switch (update_cutbuffer) {
+ case CUTBUFFER_UPDATE_APPEND:
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ if (entry->cutbuffer) {
+ memcpy(entry->cutbuffer, tmpcutbuffer,
+ entry->cutbuffer_len * sizeof(unichar));
+ memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar),
+ entry->text + entry->pos - size, size * sizeof(unichar));
+
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ }
+ break;
+
case CUTBUFFER_UPDATE_PREPEND:
- if (entry->cutbuffer_len) {
- int cutbuffer_new_size = entry->cutbuffer_len + size;
- unichar *tmpcutbuffer = entry->cutbuffer;
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ if (entry->cutbuffer) {
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ memcpy(entry->cutbuffer + size, tmpcutbuffer,
+ entry->cutbuffer_len * sizeof(unichar));
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
- memcpy(entry->cutbuffer + size, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ }
+ break;
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
-
- g_free(tmpcutbuffer);
- break;
- }
- /* fall through to REPLACE if cutbuffer_len was 0 */
case CUTBUFFER_UPDATE_REPLACE:
/* put erased text to cutbuffer */
if (entry->cutbuffer_len < size) {
@@ -613,6 +628,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
memcpy(entry->cutbuffer, entry->text + entry->pos - size,
size * sizeof(unichar));
break;
+
case CUTBUFFER_UPDATE_NOOP:
break;
}
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index 498f95b9..d22a7fb8 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -23,6 +23,7 @@ typedef struct {
typedef enum {
CUTBUFFER_UPDATE_NOOP,
CUTBUFFER_UPDATE_REPLACE,
+ CUTBUFFER_UPDATE_APPEND,
CUTBUFFER_UPDATE_PREPEND
} CUTBUFFER_UPDATE_OP;
From 966d002b55eb0b49a04833e5a51b9ab265013eab Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Sat, 30 Jan 2016 11:32:08 -0500
Subject: [PATCH 019/140] remove memory allocation check, spaces to tabs
---
src/fe-text/gui-entry.c | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 58743ac3..78b9166d 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -589,32 +589,28 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
unichar *tmpcutbuffer = entry->cutbuffer;
switch (update_cutbuffer) {
case CUTBUFFER_UPDATE_APPEND:
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- if (entry->cutbuffer) {
- memcpy(entry->cutbuffer, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
- memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar),
- entry->text + entry->pos - size, size * sizeof(unichar));
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ memcpy(entry->cutbuffer, tmpcutbuffer,
+ entry->cutbuffer_len * sizeof(unichar));
+ memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar),
+ entry->text + entry->pos - size, size * sizeof(unichar));
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
- g_free(tmpcutbuffer);
- }
- break;
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ break;
case CUTBUFFER_UPDATE_PREPEND:
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- if (entry->cutbuffer) {
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
- memcpy(entry->cutbuffer + size, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
+ entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ memcpy(entry->cutbuffer + size, tmpcutbuffer,
+ entry->cutbuffer_len * sizeof(unichar));
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
- g_free(tmpcutbuffer);
- }
- break;
+ entry->cutbuffer_len = cutbuffer_new_size;
+ entry->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ break;
case CUTBUFFER_UPDATE_REPLACE:
/* put erased text to cutbuffer */
From 8708d8da49d68057ee8f32e64415c7109d237bd7 Mon Sep 17 00:00:00 2001
From: Lauri Nurmi
Date: Sun, 31 Jan 2016 20:49:59 +0200
Subject: [PATCH 020/140] Add .gitattributes to ensure all shell scripts have
LF as eol-style.
Some Git clients on Windows may use CRLF otherwise, which effectively prevents running such scripts.
---
.gitattributes | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..e1ae7d9d
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+# On Windows, some Git clients may normalize all text files' line-endings to
+# CRLF, which causes obscure errors when running shell scripts.
+*.sh eol=lf
From 8723c0fb339dcf58c164fbc741122f9c3657ddea Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt"
Date: Wed, 10 Feb 2016 09:47:10 -0500
Subject: [PATCH 021/140] fix whitespace
---
src/fe-text/gui-entry.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 78b9166d..27778b2b 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -582,11 +582,11 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
if (size == 0 || entry->pos < size)
return;
- if (entry->cutbuffer_len == 0) {
- update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
- }
- int cutbuffer_new_size = entry->cutbuffer_len + size;
- unichar *tmpcutbuffer = entry->cutbuffer;
+ if (entry->cutbuffer_len == 0) {
+ update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
+ }
+ int cutbuffer_new_size = entry->cutbuffer_len + size;
+ unichar *tmpcutbuffer = entry->cutbuffer;
switch (update_cutbuffer) {
case CUTBUFFER_UPDATE_APPEND:
entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
@@ -621,8 +621,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
entry->cutbuffer_len = size;
entry->cutbuffer[size] = '\0';
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
+ memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar));
break;
case CUTBUFFER_UPDATE_NOOP:
From 88e2449f832d5c64b8ea30047f15319a66b17c1f Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Wed, 17 Feb 2016 22:34:44 +0100
Subject: [PATCH 022/140] fix formatting
---
src/irc/proxy/listen.c | 70 +++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 5dc9a704..ad1e4588 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -48,7 +48,7 @@ static void remove_client(CLIENT_REC *rec)
signal_emit("proxy client disconnected", 1, rec);
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client %s:%d disconnected", rec->host, rec->port);
+ "Proxy: Client %s:%d disconnected", rec->host, rec->port);
g_free(rec->proxy_address);
net_sendbuffer_destroy(rec->handle, TRUE);
@@ -59,7 +59,7 @@ static void remove_client(CLIENT_REC *rec)
}
static void proxy_redirect_event(CLIENT_REC *client, const char *command,
- int count, const char *arg, int remote)
+ int count, const char *arg, int remote)
{
char *str;
@@ -67,7 +67,7 @@ static void proxy_redirect_event(CLIENT_REC *client, const char *command,
str = g_strdup_printf("proxy %p", client);
server_redirect_event(client->server, command, count,
- arg, remote, NULL, "", str, NULL);
+ arg, remote, NULL, "", str, NULL);
g_free(str);
}
@@ -94,15 +94,15 @@ static void grab_who(CLIENT_REC *client, const char *channel)
}
proxy_redirect_event(client, "who",
- client->server->one_endofwho ? 1 : count,
- arg->str, -1);
+ client->server->one_endofwho ? 1 : count,
+ arg->str, -1);
g_strfreev(list);
g_string_free(arg, TRUE);
}
static void handle_client_connect_cmd(CLIENT_REC *client,
- const char *cmd, const char *args)
+ const char *cmd, const char *args)
{
const char *password;
@@ -114,7 +114,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
else {
/* wrong password! */
remove_client(client);
- return;
+ return;
}
} else if (g_strcmp0(cmd, "NICK") == 0) {
g_free_not_null(client->nick);
@@ -130,8 +130,8 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
} else {
signal_emit("proxy client connected", 1, client);
printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client %s:%d connected",
- client->host, client->port);
+ "Proxy: Client %s:%d connected",
+ client->host, client->port);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -139,7 +139,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
}
static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
- const char *data)
+ const char *data)
{
GSList *tmp;
if (!client->connected) {
@@ -162,8 +162,8 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
g_ascii_strcasecmp(target, client->proxy_address) == 0 ||
g_ascii_strcasecmp(target, client->nick) == 0) {
proxy_outdata(client, ":%s PONG %s :%s\r\n",
- client->proxy_address,
- client->proxy_address, origin);
+ client->proxy_address,
+ client->proxy_address, origin);
g_free(params);
return;
}
@@ -174,25 +174,25 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
if (g_ascii_strcasecmp(args, "CTCP ON") == 0) {
/* client wants all ctcps */
client->want_ctcp = 1;
- for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
CLIENT_REC *rec = tmp->data;
- if ((g_ascii_strcasecmp(client->listen->ircnet,rec->listen->ircnet) == 0) &&
- /* kludgy way to check if the clients aren't the same */
- (client->recv_tag != rec->recv_tag)) {
- if (rec->want_ctcp == 1)
- proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n",
- rec->proxy_address, rec->nick, rec->listen->ircnet);
- rec->want_ctcp = 0;
- }
+ if (g_ascii_strcasecmp(client->listen->ircnet, rec->listen->ircnet) == 0 &&
+ /* kludgy way to check if the clients aren't the same */
+ client->recv_tag != rec->recv_tag) {
+ if (rec->want_ctcp == 1)
+ proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n",
+ rec->proxy_address, rec->nick, rec->listen->ircnet);
+ rec->want_ctcp = 0;
+ }
}
proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n",
- client->proxy_address, client->nick,client->listen->ircnet);
+ client->proxy_address, client->nick, client->listen->ircnet);
} else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) {
- /* client wants proxy to handle all ctcps */
+ /* client wants proxy to handle all ctcps */
client->want_ctcp = 0;
proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n",
- client->proxy_address, client->nick, client->listen->ircnet);
+ client->proxy_address, client->nick, client->listen->ircnet);
} else {
signal_emit("proxy client command", 3, client, args, data);
}
@@ -201,11 +201,11 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
if (client->server == NULL || !client->server->connected) {
proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n",
- client->proxy_address, client->nick);
- return;
+ client->proxy_address, client->nick);
+ return;
}
- /* check if the command could be redirected */
+ /* check if the command could be redirected */
if (g_strcmp0(cmd, "WHO") == 0)
grab_who(client, args);
else if (g_strcmp0(cmd, "WHOWAS") == 0)
@@ -263,29 +263,29 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
char *params, *target, *msg;
params = event_get_params(args, 2 | PARAM_FLAG_GETREST,
- &target, &msg);
+ &target, &msg);
proxy_outserver_all_except(client, "PRIVMSG %s", args);
ignore_next = TRUE;
if (*msg != '\001' || msg[strlen(msg)-1] != '\001') {
signal_emit(server_ischannel(SERVER(client->server), target) ?
- "message own_public" : "message own_private", 4,
- client->server, msg, target, target);
+ "message own_public" : "message own_private", 4,
+ client->server, msg, target, target);
} else if (strncmp(msg+1, "ACTION ", 7) == 0) {
/* action */
- msg[strlen(msg)-1] = '\0';
+ msg[strlen(msg)-1] = '\0';
signal_emit("message irc own_action", 3,
- client->server, msg+8, target);
+ client->server, msg+8, target);
} else {
- /* CTCP */
+ /* CTCP */
char *p;
msg[strlen(msg)-1] = '\0';
p = strchr(msg, ' ');
- if (p != NULL) *p++ = '\0'; else p = "";
+ if (p != NULL) *p++ = '\0'; else p = "";
signal_emit("message irc own_ctcp", 4,
- client->server, msg+1, p, target);
+ client->server, msg+1, p, target);
}
ignore_next = FALSE;
g_free(params);
From 4732e33ca9c9f9a48b57062ab254bf3aa90078bf Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Wed, 17 Feb 2016 23:06:51 +0100
Subject: [PATCH 023/140] irssi proxy: allow multiplexing multiple networks
over a single port
---
src/irc/proxy/listen.c | 58 +++++++++++++++++++++++++++++++++---------
src/irc/proxy/proxy.h | 1 +
src/perl/irc/Irc.xs | 1 +
3 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index ad1e4588..2322d47a 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -108,14 +108,44 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
password = settings_get_str("irssiproxy_password");
- if (password != NULL && g_strcmp0(cmd, "PASS") == 0) {
- if (g_strcmp0(password, args) == 0)
- client->pass_sent = TRUE;
- else {
+ if (g_strcmp0(cmd, "PASS") == 0) {
+ const char *args_pass;
+
+ if (!client->multiplex) {
+ args_pass = args;
+ } else {
+ IRC_SERVER_REC *server;
+ char *tag;
+ const char *tag_end;
+
+ if ((tag_end = strchr(args, ':'))) {
+ args_pass = tag_end + 1;
+ } else {
+ tag_end = args + strlen(args);
+ args_pass = "";
+ }
+
+ tag = g_strndup(args, tag_end - args);
+ server = IRC_SERVER(server_find_chatnet(tag));
+ g_free(tag);
+
+ if (!server) {
+ /* an invalid network was specified */
+ remove_client(client);
+ return;
+ }
+
+ client->server = server;
+ g_free(client->proxy_address);
+ client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args);
+ }
+
+ if (password && g_strcmp0(password, args_pass) != 0) {
/* wrong password! */
remove_client(client);
return;
}
+ client->pass_sent = TRUE;
} else if (g_strcmp0(cmd, "NICK") == 0) {
g_free_not_null(client->nick);
client->nick = g_strdup(args);
@@ -124,7 +154,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
}
if (client->nick != NULL && client->user_sent) {
- if (*password != '\0' && !client->pass_sent) {
+ if ((*password != '\0' || client->multiplex) && !client->pass_sent) {
/* client didn't send us PASS, kill it */
remove_client(client);
} else {
@@ -337,7 +367,7 @@ static void sig_listen(LISTEN_REC *listen)
CLIENT_REC *rec;
IPADDR ip;
NET_SENDBUF_REC *sendbuf;
- GIOChannel *handle;
+ GIOChannel *handle;
char host[MAX_IP_LEN];
int port;
@@ -352,9 +382,13 @@ static void sig_listen(LISTEN_REC *listen)
rec = g_new0(CLIENT_REC, 1);
rec->listen = listen;
rec->handle = sendbuf;
- rec->host = g_strdup(host);
+ rec->host = g_strdup(host);
rec->port = port;
- if (g_strcmp0(listen->ircnet, "*") == 0) {
+ if (g_strcmp0(listen->ircnet, "?") == 0) {
+ rec->multiplex = TRUE;
+ rec->proxy_address = g_strdup("multiplex.proxy");
+ rec->server = NULL;
+ } else if (g_strcmp0(listen->ircnet, "*") == 0) {
rec->proxy_address = g_strdup("irc.proxy");
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
} else {
@@ -363,15 +397,15 @@ static void sig_listen(LISTEN_REC *listen)
IRC_SERVER(server_find_chatnet(listen->ircnet));
}
rec->recv_tag = g_input_add(handle, G_INPUT_READ,
- (GInputFunction) sig_listen_client, rec);
+ (GInputFunction) sig_listen_client, rec);
proxy_clients = g_slist_prepend(proxy_clients, rec);
- rec->listen->clients = g_slist_prepend(rec->listen->clients, rec);
+ listen->clients = g_slist_prepend(listen->clients, rec);
signal_emit("proxy client connecting", 1, rec);
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: New client %s:%d on port %d (%s)",
- rec->host, rec->port, listen->port, listen->ircnet);
+ "Proxy: New client %s:%d on port %d (%s)",
+ rec->host, rec->port, listen->port, listen->ircnet);
}
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h
index 158b0675..f37e9c95 100644
--- a/src/irc/proxy/proxy.h
+++ b/src/irc/proxy/proxy.h
@@ -29,6 +29,7 @@ typedef struct {
unsigned int user_sent:1;
unsigned int connected:1;
unsigned int want_ctcp:1;
+ unsigned int multiplex:1;
} CLIENT_REC;
#endif
diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs
index db5c5f79..4217b4eb 100644
--- a/src/perl/irc/Irc.xs
+++ b/src/perl/irc/Irc.xs
@@ -157,6 +157,7 @@ static void perl_client_fill_hash(HV *hv, CLIENT_REC *client)
(void) hv_store(hv, "user_sent", 9, newSViv(client->user_sent), 0);
(void) hv_store(hv, "connected", 9, newSViv(client->connected), 0);
(void) hv_store(hv, "want_ctcp", 9, newSViv(client->want_ctcp), 0);
+ (void) hv_store(hv, "multiplex", 9, newSViv(client->multiplex), 0);
(void) hv_store(hv, "ircnet", 6, new_pv(client->listen->ircnet), 0);
}
From effb00b858db17b3abf27661682255bd8139a95a Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Thu, 18 Feb 2016 01:17:24 +0100
Subject: [PATCH 024/140] add some documentation
---
docs/proxy.txt | 12 ++++++++++++
docs/startup-HOWTO.html | 17 +++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/docs/proxy.txt b/docs/proxy.txt
index e6360a82..224d24e3 100644
--- a/docs/proxy.txt
+++ b/docs/proxy.txt
@@ -30,6 +30,18 @@ There we have 3 different irc networks answering in 3 ports. Note that
you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to
make it work properly.
+The special network name "?" allows the client to select the network
+dynamically on connect:
+
+ /SET irssiproxy_ports ?=2777
+
+Now the client can send : as the server password, e.g.
+
+ /CONNECT ... 2777 efnet:secret
+
+to connect to efnet. If there is no irssiproxy_password set, you can
+omit the ":" and just send the network name as the password.
+
By default, the proxy binds to all available interfaces. To make it
only listen on (for example) the loopback address:
diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html
index deff3116..1b912b96 100644
--- a/docs/startup-HOWTO.html
+++ b/docs/startup-HOWTO.html
@@ -735,6 +735,13 @@ reason, and you only use one server connection, you may simply set:
/SET irssiproxy_ports *=2777
+The special network name ?
allows the client to select the
+network dynamically on connect (see below):
+
+
+/SET irssiproxy_ports ?=2777
+
+
Usage in client side:
Just connect to the irssi proxy like it is a normal server with password
@@ -745,6 +752,16 @@ specified in /SET irssiproxy_password
. For example:
/SERVER ADD -network efnet my.irssi-proxy.org 2778 secret
+Or, if you used ?
in irssiproxy_ports
:
+
+
+/SERVER ADD -network IRCnet my.irssi-proxy.org 2777 IRCnet:secret
+/SERVER ADD -network efnet my.irssi-proxy.org 2777 efnet:secret
+
+
+I.e. the network to connect to is specified as part of the password,
+separated by :
from the actual proxy password.
+
Irssi proxy works fine with other IRC clients as well.
SOCKS
From c9ce0c521a559727493b42f422b5cc10ede2d9b2 Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Thu, 18 Feb 2016 02:23:00 +0100
Subject: [PATCH 025/140] make pointer check explicit
---
src/irc/proxy/listen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 2322d47a..cd946baa 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -118,7 +118,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
char *tag;
const char *tag_end;
- if ((tag_end = strchr(args, ':'))) {
+ if ((tag_end = strchr(args, ':')) != NULL) {
args_pass = tag_end + 1;
} else {
tag_end = args + strlen(args);
From 3167ccfbc21e6918133e5898f5e76596bb6de788 Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Thu, 18 Feb 2016 02:23:09 +0100
Subject: [PATCH 026/140] remove redundant check
---
src/irc/proxy/listen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index cd946baa..3ec83773 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -140,7 +140,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args);
}
- if (password && g_strcmp0(password, args_pass) != 0) {
+ if (g_strcmp0(password, args_pass) != 0) {
/* wrong password! */
remove_client(client);
return;
From 9f0e5da208f9ee775b82d50ff959d8599d1e1151 Mon Sep 17 00:00:00 2001
From: Manish Goregaokar
Date: Wed, 24 Feb 2016 00:35:27 +0530
Subject: [PATCH 027/140] use a #define'd LINE_SPLIT_LIMIT instead of
hardcoding 400
---
src/fe-text/gui-readline.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 0dd17394..51ccab5e 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -40,6 +40,9 @@
#include
#include
+/* After LINE_SPLIT_LIMIT characters, the message will be split into multiple lines */
+#define LINE_SPLIT_LIMIT 400
+
typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item);
typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item);
@@ -227,7 +230,7 @@ static void paste_buffer_join_lines(GArray *buf)
}
/* all looks fine - now remove the whitespace, but don't let lines
- get longer than 400 chars */
+ get longer than LINE_SPLIT_LIMIT chars */
dest = arr; last_lf = TRUE; last_lf_pos = NULL; line_len = 0;
for (i = 0; i < buf->len; i++) {
if (last_lf && isblank(arr[i])) {
@@ -245,7 +248,7 @@ static void paste_buffer_join_lines(GArray *buf)
last_lf = TRUE;
} else {
last_lf = FALSE;
- if (++line_len >= 400 && last_lf_pos != NULL) {
+ if (++line_len >= LINE_SPLIT_LIMIT && last_lf_pos != NULL) {
memmove(last_lf_pos+1, last_lf_pos,
(dest - last_lf_pos) * sizeof(unichar));
*last_lf_pos = '\n'; last_lf_pos = NULL;
From ef0c7d3e7a6df6de1f8280ae8ae777a068d073c7 Mon Sep 17 00:00:00 2001
From: Manish Goregaokar
Date: Wed, 24 Feb 2016 00:36:35 +0530
Subject: [PATCH 028/140] Make pasting warning appear when long pastes are
going to be split into many lines
---
src/fe-text/gui-readline.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 51ccab5e..ff91f9e3 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -360,11 +360,24 @@ static void insert_paste_prompt(void)
{
char *str;
+ /* The actual number of lines that will show up post-line-split */
+ int actual_line_count = paste_line_count;
+ int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT;
+
+ /* in case this prompt is happening due to line-splitting, calculate the
+ number of lines obtained from this. The number isn't entirely accurate;
+ we just choose the greater of the two since the exact value isn't
+ important */
+ if (split_lines > paste_verify_line_count &&
+ split_lines > paste_line_count) {
+ actual_line_count = split_lines;
+ }
+
paste_prompt = TRUE;
paste_old_prompt = g_strdup(active_entry->prompt);
printformat_window(active_win, MSGLEVEL_CLIENTNOTICE,
TXT_PASTE_WARNING,
- paste_line_count,
+ actual_line_count,
active_win->active == NULL ? "window" :
active_win->active->visible_name);
@@ -641,7 +654,11 @@ static gboolean paste_timeout(gpointer data)
{
paste_was_bracketed_mode = paste_bracketed_mode;
- if (paste_line_count == 0) {
+ /* number of lines after splitting extra-long messages */
+ int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT;
+
+ /* Take into account the fact that a line may be split every LINE_SPLIT_LIMIT characters */
+ if (paste_line_count == 0 && split_lines <= paste_verify_line_count) {
int i;
for (i = 0; i < paste_buffer->len; i++) {
@@ -650,8 +667,9 @@ static gboolean paste_timeout(gpointer data)
}
g_array_set_size(paste_buffer, 0);
} else if (paste_verify_line_count > 0 &&
- paste_line_count >= paste_verify_line_count &&
- active_win->active != NULL)
+ (paste_line_count >= paste_verify_line_count ||
+ split_lines > paste_verify_line_count) &&
+ active_win->active != NULL)
insert_paste_prompt();
else
paste_flush(TRUE);
From 4d234c175c69d3bcc80d9918fad98e3c6f69d23e Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Fri, 26 Feb 2016 18:40:51 +0100
Subject: [PATCH 029/140] fix proxy server name
---
src/irc/proxy/listen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 3ec83773..ef288201 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -137,7 +137,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
client->server = server;
g_free(client->proxy_address);
- client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args);
+ client->proxy_address = g_strdup_printf("%.*s.proxy", (int)(tag_end - args), args);
}
if (g_strcmp0(password, args_pass) != 0) {
From 3fc7e4d4ea7faaf3a14206c8b7c46ccc4b96309c Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Wed, 24 Feb 2016 18:59:00 +0100
Subject: [PATCH 030/140] reindent
---
src/irc/proxy/listen.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index ef288201..43cef27f 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -202,7 +202,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
if (g_strcmp0(cmd, "PROXY") == 0) {
if (g_ascii_strcasecmp(args, "CTCP ON") == 0) {
- /* client wants all ctcps */
+ /* client wants all ctcps */
client->want_ctcp = 1;
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
CLIENT_REC *rec = tmp->data;
@@ -494,12 +494,12 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line,
static void event_connected(IRC_SERVER_REC *server)
{
GSList *tmp;
- const char *chatnet;
+ const char *chatnet;
if (!IS_IRC_SERVER(server))
return;
- chatnet = server->connrec->chatnet;
+ chatnet = server->connrec->chatnet;
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
CLIENT_REC *rec = tmp->data;
@@ -508,7 +508,7 @@ static void event_connected(IRC_SERVER_REC *server)
(chatnet != NULL &&
g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) {
proxy_outdata(rec, ":%s NOTICE %s :Connected to server\r\n",
- rec->proxy_address, rec->nick);
+ rec->proxy_address, rec->nick);
rec->server = server;
proxy_client_reset_nick(rec);
}
@@ -516,7 +516,7 @@ static void event_connected(IRC_SERVER_REC *server)
}
static void proxy_server_disconnected(CLIENT_REC *client,
- IRC_SERVER_REC *server)
+ IRC_SERVER_REC *server)
{
GSList *tmp;
@@ -655,9 +655,9 @@ static void add_listen(const char *ircnet, int port)
}
rec->tag = g_input_add(rec->handle, G_INPUT_READ,
- (GInputFunction) sig_listen, rec);
+ (GInputFunction) sig_listen, rec);
- proxy_listens = g_slist_append(proxy_listens, rec);
+ proxy_listens = g_slist_append(proxy_listens, rec);
}
static void remove_listen(LISTEN_REC *rec)
From 8c1da2890c4ccbeac70d7798f29f00a81a770728 Mon Sep 17 00:00:00 2001
From: Lukas Mai
Date: Wed, 24 Feb 2016 19:00:31 +0100
Subject: [PATCH 031/140] irssi proxy: allow listening on unix sockets
---
src/common.h | 2 +-
src/irc/proxy/listen.c | 188 ++++++++++++++++++++++++++++++-----------
src/irc/proxy/proxy.c | 6 +-
src/irc/proxy/proxy.h | 5 +-
src/perl/irc/Irc.xs | 3 +-
5 files changed, 148 insertions(+), 56 deletions(-)
diff --git a/src/common.h b/src/common.h
index 966e28d0..729049ab 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 1
+#define IRSSI_ABI_VERSION 2
#define DEFAULT_SERVER_ADD_PORT 6667
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index 43cef27f..cde4c0be 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -31,6 +31,8 @@
#include "fe-common/core/printtext.h" /* FIXME: evil. need to do fe-proxy */
+#include
+
GSList *proxy_listens;
GSList *proxy_clients;
@@ -39,6 +41,66 @@ static int ignore_next;
static int enabled = FALSE;
+static int is_all_digits(const char *s)
+{
+ return strspn(s, "0123456789") == strlen(s);
+}
+
+static GIOChannel *net_listen_unix(const char *path)
+{
+ struct sockaddr_un sa;
+ int saved_errno, handle;
+
+ g_return_val_if_fail(path != NULL, NULL);
+
+ handle = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (handle == -1) {
+ return NULL;
+ }
+
+ fcntl(handle, F_SETFL, O_NONBLOCK);
+
+ memset(&sa, '\0', sizeof sa);
+ sa.sun_family = AF_UNIX;
+ strncpy(sa.sun_path, path, sizeof sa.sun_path - 1);
+ if (bind(handle, (struct sockaddr *)&sa, sizeof sa) == -1) {
+ saved_errno = errno;
+ goto error_close;
+ }
+
+ if (listen(handle, 1) == -1) {
+ saved_errno = errno;
+ goto error_unlink;
+ }
+
+ return g_io_channel_new(handle);
+
+error_unlink:
+ unlink(sa.sun_path);
+error_close:
+ close(handle);
+ errno = saved_errno;
+ return NULL;
+}
+
+static GIOChannel *net_accept_unix(GIOChannel *handle)
+{
+ struct sockaddr_un sa;
+ int ret;
+ socklen_t addrlen;
+
+ g_return_val_if_fail(handle != NULL, NULL);
+
+ addrlen = sizeof sa;
+ ret = accept(g_io_channel_unix_get_fd(handle), (struct sockaddr *)&sa, &addrlen);
+
+ if (ret < 0)
+ return NULL;
+
+ fcntl(ret, F_SETFL, O_NONBLOCK);
+ return g_io_channel_new(ret);
+}
+
static void remove_client(CLIENT_REC *rec)
{
g_return_if_fail(rec != NULL);
@@ -48,13 +110,13 @@ static void remove_client(CLIENT_REC *rec)
signal_emit("proxy client disconnected", 1, rec);
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client %s:%d disconnected", rec->host, rec->port);
+ "Proxy: Client %s disconnected", rec->addr);
g_free(rec->proxy_address);
net_sendbuffer_destroy(rec->handle, TRUE);
g_source_remove(rec->recv_tag);
g_free_not_null(rec->nick);
- g_free_not_null(rec->host);
+ g_free_not_null(rec->addr);
g_free(rec);
}
@@ -160,8 +222,8 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
} else {
signal_emit("proxy client connected", 1, client);
printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client %s:%d connected",
- client->host, client->port);
+ "Proxy: Client %s connected",
+ client->addr);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -370,20 +432,30 @@ static void sig_listen(LISTEN_REC *listen)
GIOChannel *handle;
char host[MAX_IP_LEN];
int port;
+ char *addr;
g_return_if_fail(listen != NULL);
/* accept connection */
- handle = net_accept(listen->handle, &ip, &port);
- if (handle == NULL)
- return;
- net_ip2host(&ip, host);
+ if (listen->port) {
+ handle = net_accept(listen->handle, &ip, &port);
+ if (handle == NULL)
+ return;
+ net_ip2host(&ip, host);
+ addr = g_strdup_printf("%s:%d", host, port);
+ } else {
+ /* no port => this is a unix socket */
+ handle = net_accept_unix(listen->handle);
+ if (handle == NULL)
+ return;
+ addr = g_strdup("(local)");
+ }
+
sendbuf = net_sendbuffer_create(handle, 0);
rec = g_new0(CLIENT_REC, 1);
rec->listen = listen;
rec->handle = sendbuf;
- rec->host = g_strdup(host);
- rec->port = port;
+ rec->addr = addr;
if (g_strcmp0(listen->ircnet, "?") == 0) {
rec->multiplex = TRUE;
rec->proxy_address = g_strdup("multiplex.proxy");
@@ -404,8 +476,8 @@ static void sig_listen(LISTEN_REC *listen)
signal_emit("proxy client connecting", 1, rec);
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: New client %s:%d on port %d (%s)",
- rec->host, rec->port, listen->port, listen->ircnet);
+ "Proxy: New client %s on port %s (%s)",
+ rec->addr, listen->port_or_path, listen->ircnet);
}
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
@@ -601,14 +673,19 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg,
proxy_outserver_all(server, "PRIVMSG %s :\001ACTION %s\001", target, msg);
}
-static LISTEN_REC *find_listen(const char *ircnet, int port)
+static LISTEN_REC *find_listen(const char *ircnet, int port, const char *port_or_path)
{
GSList *tmp;
for (tmp = proxy_listens; tmp != NULL; tmp = tmp->next) {
LISTEN_REC *rec = tmp->data;
- if (rec->port == port &&
+ if ((port
+ ? /* a tcp port */
+ rec->port == port
+ : /* a unix socket path */
+ g_strcmp0(rec->port_or_path, port_or_path) == 0
+ ) &&
g_ascii_strcasecmp(rec->ircnet, ircnet) == 0)
return rec;
}
@@ -616,43 +693,48 @@ static LISTEN_REC *find_listen(const char *ircnet, int port)
return NULL;
}
-static void add_listen(const char *ircnet, int port)
+static void add_listen(const char *ircnet, int port, const char *port_or_path)
{
LISTEN_REC *rec;
IPADDR ip4, ip6, *my_ip;
+ GIOChannel *handle;
- if (port <= 0 || *ircnet == '\0')
+ if (*port_or_path == '\0' || port < 0 || *ircnet == '\0')
return;
- /* bind to specific host/ip? */
- my_ip = NULL;
- if (*settings_get_str("irssiproxy_bind") != '\0') {
- if (net_gethostbyname(settings_get_str("irssiproxy_bind"),
- &ip4, &ip6) != 0) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
- "Proxy: can not resolve '%s' - aborting",
- settings_get_str("irssiproxy_bind"));
- return;
- }
+ if (port == 0) {
+ /* listening on a unix socket */
+ handle = net_listen_unix(port_or_path);
+ } else {
+ /* bind to specific host/ip? */
+ my_ip = NULL;
+ if (*settings_get_str("irssiproxy_bind") != '\0') {
+ if (net_gethostbyname(settings_get_str("irssiproxy_bind"),
+ &ip4, &ip6) != 0) {
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ "Proxy: can not resolve '%s' - aborting",
+ settings_get_str("irssiproxy_bind"));
+ return;
+ }
- my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 ||
- settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4;
+ my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 ||
+ settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4;
+ }
+ handle = net_listen(my_ip, &port);
+ }
+
+ if (handle == NULL) {
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ "Proxy: Listen in port %s failed: %s",
+ port_or_path, g_strerror(errno));
+ return;
}
rec = g_new0(LISTEN_REC, 1);
+ rec->handle = handle;
rec->ircnet = g_strdup(ircnet);
rec->port = port;
-
- rec->handle = net_listen(my_ip, &rec->port);
-
- if (rec->handle == NULL) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
- "Proxy: Listen in port %d failed: %s",
- rec->port, g_strerror(errno));
- g_free(rec->ircnet);
- g_free(rec);
- return;
- }
+ rec->port_or_path = g_strdup(port_or_path);
rec->tag = g_input_add(rec->handle, G_INPUT_READ,
(GInputFunction) sig_listen, rec);
@@ -667,8 +749,13 @@ static void remove_listen(LISTEN_REC *rec)
while (rec->clients != NULL)
remove_client(rec->clients->data);
+ /* remove unix socket because bind wants to (re)create it */
+ if (rec->port == 0)
+ unlink(rec->port_or_path);
+
net_disconnect(rec->handle);
g_source_remove(rec->tag);
+ g_free(rec->port_or_path);
g_free(rec->ircnet);
g_free(rec);
}
@@ -678,7 +765,7 @@ static void read_settings(void)
LISTEN_REC *rec;
GSList *remove_listens = NULL;
GSList *add_listens = NULL;
- char **ports, **tmp, *ircnet, *port;
+ char **ports, **tmp, *ircnet, *port_or_path;
int portnum;
remove_listens = g_slist_copy(proxy_listens);
@@ -686,20 +773,25 @@ static void read_settings(void)
ports = g_strsplit(settings_get_str("irssiproxy_ports"), " ", -1);
for (tmp = ports; *tmp != NULL; tmp++) {
ircnet = *tmp;
- port = strchr(ircnet, '=');
- if (port == NULL)
+ port_or_path = strchr(ircnet, '=');
+ if (port_or_path == NULL)
continue;
- *port++ = '\0';
- portnum = atoi(port);
- if (portnum <= 0)
- continue;
+ *port_or_path++ = '\0';
+ if (is_all_digits(port_or_path)) {
+ portnum = atoi(port_or_path);
+ if (portnum <= 0)
+ continue;
+ } else {
+ portnum = 0;
+ }
- rec = find_listen(ircnet, portnum);
+ rec = find_listen(ircnet, portnum, port_or_path);
if (rec == NULL) {
rec = g_new0(LISTEN_REC, 1);
rec->ircnet = ircnet; /* borrow */
rec->port = portnum;
+ rec->port_or_path = port_or_path; /* borrow */
add_listens = g_slist_prepend(add_listens, rec);
} else {
/* remove from the list of listens to remove == keep it */
@@ -714,7 +806,7 @@ static void read_settings(void)
while (add_listens != NULL) {
rec = add_listens->data;
- add_listen(rec->ircnet, rec->port);
+ add_listen(rec->ircnet, rec->port, rec->port_or_path);
add_listens = g_slist_remove(add_listens, rec);
g_free(rec);
}
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index 50a41b21..1a714045 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -44,10 +44,10 @@ static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server)
CLIENT_REC *rec = tmp->data;
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
- " %s:%d connect%s to %d (%s)",
- rec->host, rec->port,
+ " %s connect%s to %s (%s)",
+ rec->addr,
rec->connected ? "ed" : "ing",
- rec->listen->port, rec->listen->ircnet);
+ rec->listen->port_or_path, rec->listen->ircnet);
}
}
diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h
index f37e9c95..620ea605 100644
--- a/src/irc/proxy/proxy.h
+++ b/src/irc/proxy/proxy.h
@@ -9,17 +9,18 @@
typedef struct {
int port;
+ char *port_or_path;
char *ircnet;
int tag;
GIOChannel *handle;
GSList *clients;
+
} LISTEN_REC;
typedef struct {
- char *nick, *host;
- int port;
+ char *nick, *addr;
NET_SENDBUF_REC *handle;
int recv_tag;
char *proxy_address;
diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs
index 4217b4eb..3f8ccc2e 100644
--- a/src/perl/irc/Irc.xs
+++ b/src/perl/irc/Irc.xs
@@ -149,8 +149,7 @@ static void perl_notifylist_fill_hash(HV *hv, NOTIFYLIST_REC *notify)
static void perl_client_fill_hash(HV *hv, CLIENT_REC *client)
{
(void) hv_store(hv, "nick", 4, new_pv(client->nick), 0);
- (void) hv_store(hv, "host", 4, new_pv(client->host), 0);
- (void) hv_store(hv, "port", 4, newSViv(client->port), 0);
+ (void) hv_store(hv, "addr", 4, new_pv(client->addr), 0);
(void) hv_store(hv, "proxy_address", 13, new_pv(client->proxy_address), 0);
(void) hv_store(hv, "server", 6, iobject_bless(client->server), 0);
(void) hv_store(hv, "pass_sent", 9, newSViv(client->pass_sent), 0);
From 4baefd25747df116c19ea1301c5fe8fb7eef3716 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mantas=20Mikul=C4=97nas?=
Date: Tue, 8 Mar 2016 23:00:20 +0200
Subject: [PATCH 032/140] Fix SASL EXTERNAL authentication
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The "AUTHENTICATE" command is always required – it's part of the IRCv3
SASL framing. RFC 4422 only documents the Base64 payload.
---
src/irc/core/sasl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index a04eaf45..8fba9ba2 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -145,7 +145,7 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from
case SASL_MECHANISM_EXTERNAL:
/* Empty response */
- irc_send_cmdv(server, "+");
+ irc_send_cmdv(server, "AUTHENTICATE +");
break;
}
From e853392f430b9635cd7e8ada28c68426c2625298 Mon Sep 17 00:00:00 2001
From: dequis
Date: Fri, 11 Mar 2016 14:55:31 -0300
Subject: [PATCH 033/140] Remove sasl timeout source when the server
disconnects
---
src/irc/core/sasl.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 8fba9ba2..db099368 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -153,6 +153,20 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from
server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server);
}
+static void sasl_disconnected(IRC_SERVER_REC *server)
+{
+ g_return_if_fail(server != NULL);
+
+ if (!IS_IRC_SERVER(server)) {
+ return;
+ }
+
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
+}
+
void sasl_init(void)
{
signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start);
@@ -163,6 +177,7 @@ void sasl_init(void)
signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 906", (SIGNAL_FUNC) sasl_fail);
signal_add_first("event 907", (SIGNAL_FUNC) sasl_already);
+ signal_add_first("server disconnected", (SIGNAL_FUNC) sasl_disconnected);
}
void sasl_deinit(void)
@@ -175,4 +190,5 @@ void sasl_deinit(void)
signal_remove("event 905", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 906", (SIGNAL_FUNC) sasl_fail);
signal_remove("event 907", (SIGNAL_FUNC) sasl_already);
+ signal_remove("server disconnected", (SIGNAL_FUNC) sasl_disconnected);
}
From be733d24824fe2a3502a1e4ab76d50699052dd65 Mon Sep 17 00:00:00 2001
From: Will Storey
Date: Sun, 13 Mar 2016 13:28:04 -0700
Subject: [PATCH 034/140] Clear error queue before SSL I/O operations
Otherwise we can see errors that are not related to the operation
we check for. SSL_get_error() inspects the thread's error queue.
See https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html for
more information.
---
src/core/network-openssl.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c
index 465c4154..d0f23253 100644
--- a/src/core/network-openssl.c
+++ b/src/core/network-openssl.c
@@ -289,6 +289,7 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize
const char *errstr;
gchar *errmsg;
+ ERR_clear_error();
ret1 = SSL_read(chan->ssl, buf, len);
if(ret1 <= 0)
{
@@ -334,6 +335,7 @@ static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len
const char *errstr;
gchar *errmsg;
+ ERR_clear_error();
ret1 = SSL_write(chan->ssl, (const char *)buf, len);
if(ret1 <= 0)
{
@@ -581,6 +583,7 @@ int irssi_ssl_handshake(GIOChannel *handle)
X509 *cert;
const char *errstr;
+ ERR_clear_error();
ret = SSL_connect(chan->ssl);
if (ret <= 0) {
err = SSL_get_error(chan->ssl, ret);
From 8ab6bdf2ce884fa7363272805287c341b2b2fb01 Mon Sep 17 00:00:00 2001
From: Will Storey
Date: Sun, 13 Mar 2016 15:09:52 -0700
Subject: [PATCH 035/140] Add clear error calls to irssi_ssl_get_iochannel
---
src/core/network-openssl.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c
index d0f23253..a18e6fc7 100644
--- a/src/core/network-openssl.c
+++ b/src/core/network-openssl.c
@@ -473,6 +473,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_
if(!(fd = g_io_channel_unix_get_fd(handle)))
return NULL;
+ ERR_clear_error();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) {
g_error("Could not allocate memory for SSL context");
@@ -491,6 +492,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_
scert = convert_home(mycert);
if (mypkey && *mypkey)
spkey = convert_home(mypkey);
+ ERR_clear_error();
if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM))
g_warning("Loading of client certificate '%s' failed: %s", mycert, ERR_reason_error_string(ERR_get_error()));
else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM))
From 27c37cb3f39578b473a0684e6e55bf23d1910903 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sun, 13 Mar 2016 22:04:59 +0100
Subject: [PATCH 036/140] Return -1 from null-test to comply with the rest of
strarray_find
---
src/core/misc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index aaa470f5..c26610ec 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -169,8 +169,8 @@ int strarray_find(char **array, const char *item)
char **tmp;
int index;
- g_return_val_if_fail(array != NULL, 0);
- g_return_val_if_fail(item != NULL, 0);
+ g_return_val_if_fail(array != NULL, -1);
+ g_return_val_if_fail(item != NULL, -1);
index = 0;
for (tmp = array; *tmp != NULL; tmp++, index++) {
From 94b823c3cd410abb2fa54ecbcf298550d5e2ba88 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Fri, 11 Mar 2016 09:12:38 +0100
Subject: [PATCH 037/140] Use glob matching for activity_hide_targets
spaces vs tabs!
strarray_find* needs to return -1 if no index found
---
src/core/misc.c | 18 ++++++++++++++++++
src/core/misc.h | 1 +
src/fe-common/core/fe-common-core.c | 2 +-
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index aaa470f5..2284d3b1 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -181,6 +181,24 @@ int strarray_find(char **array, const char *item)
return -1;
}
+
+int strarray_find_glob(char **array, const char *item)
+{
+ char **tmp;
+ int index;
+
+ g_return_val_if_fail(array != NULL, -1);
+ g_return_val_if_fail(item != NULL, -1);
+
+ index = 0;
+ for (tmp = array; *tmp != NULL; tmp++, index++) {
+ if (g_pattern_match_simple(*tmp, item))
+ return index;
+ }
+
+ return -1;
+}
+
GSList *gslist_find_string(GSList *list, const char *key)
{
for (; list != NULL; list = list->next)
diff --git a/src/core/misc.h b/src/core/misc.h
index 7e78d3b9..dd8bb14c 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -111,6 +111,7 @@ char *replace_chars(char *str, char from, char to);
int strarray_length(char **array);
/* return index of `item' in `array' or -1 if not found */
int strarray_find(char **array, const char *item);
+int strarray_find_glob(char **array, const char *item);
/* string -> uoff_t */
uoff_t str_to_uofft(const char *str);
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index ee7f9424..f0549358 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -464,7 +464,7 @@ gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest)
if (dest->server_tag != NULL) {
char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target);
- int ret = strarray_find(array, tagtarget);
+ int ret = strarray_find_glob(array, tagtarget);
g_free(tagtarget);
if (ret != -1)
return TRUE;
From bcebed5a72308f57de8f96f6ab9ad5ccad93a811 Mon Sep 17 00:00:00 2001
From: KindOne
Date: Mon, 14 Mar 2016 21:23:37 -0400
Subject: [PATCH 038/140] Replace spaces with tabs
---
src/core/chat-commands.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c
index 8e881679..7f000cf5 100644
--- a/src/core/chat-commands.c
+++ b/src/core/chat-commands.c
@@ -117,8 +117,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
if (g_hash_table_lookup(optlist, "!") != NULL)
conn->no_autojoin_channels = TRUE;
- if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL)
- conn->no_autosendcmd = TRUE;
+ if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL)
+ conn->no_autosendcmd = TRUE;
if (g_hash_table_lookup(optlist, "noproxy") != NULL)
g_free_and_null(conn->proxy);
From f6c2805b91161a01378c9bbe853521c08d460c60 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Thu, 17 Mar 2016 22:27:05 +0100
Subject: [PATCH 039/140] Do not assume any default value for statusmsg.
If the server didn't send it then just skip the check, the old value it
defaulted to was possibly overlapping with the CHANTYPES leading to an
incorrect behaviour. Fixes #435.
---
src/irc/core/irc-servers.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 81f0c269..d6fb8018 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -81,12 +81,12 @@ static int ischannel_func(SERVER_REC *server, const char *data)
chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes");
if (chantypes == NULL)
chantypes = "#&!+"; /* normal, local, secure, modeless */
- statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
- if (statusmsg == NULL)
- statusmsg = "@+";
- while (strchr(statusmsg, *data) != NULL)
- data++;
+ statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
+ if (statusmsg != NULL) {
+ while (strchr(statusmsg, *data) != NULL)
+ data++;
+ }
return strchr(chantypes, *data) != NULL;
}
From 857e27aef6d04edc1e47d52d74031ba279d2da1a Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Thu, 17 Mar 2016 23:58:46 +0100
Subject: [PATCH 040/140] Don't use glob matching, just regular string
comparisons
---
src/core/misc.c | 20 +-------------------
src/core/misc.h | 1 -
src/fe-common/core/fe-common-core.c | 13 +++++++++++--
3 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 2284d3b1..c26610ec 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -169,30 +169,12 @@ int strarray_find(char **array, const char *item)
char **tmp;
int index;
- g_return_val_if_fail(array != NULL, 0);
- g_return_val_if_fail(item != NULL, 0);
-
- index = 0;
- for (tmp = array; *tmp != NULL; tmp++, index++) {
- if (g_ascii_strcasecmp(*tmp, item) == 0)
- return index;
- }
-
- return -1;
-}
-
-
-int strarray_find_glob(char **array, const char *item)
-{
- char **tmp;
- int index;
-
g_return_val_if_fail(array != NULL, -1);
g_return_val_if_fail(item != NULL, -1);
index = 0;
for (tmp = array; *tmp != NULL; tmp++, index++) {
- if (g_pattern_match_simple(*tmp, item))
+ if (g_ascii_strcasecmp(*tmp, item) == 0)
return index;
}
diff --git a/src/core/misc.h b/src/core/misc.h
index dd8bb14c..7e78d3b9 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -111,7 +111,6 @@ char *replace_chars(char *str, char from, char to);
int strarray_length(char **array);
/* return index of `item' in `array' or -1 if not found */
int strarray_find(char **array, const char *item);
-int strarray_find_glob(char **array, const char *item);
/* string -> uoff_t */
uoff_t str_to_uofft(const char *str);
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index f0549358..1b2ab1e2 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -459,12 +459,21 @@ gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest)
{
g_return_val_if_fail(array != NULL, FALSE);
+ if (strarray_find(array, "*") != -1)
+ return TRUE;
+
if (strarray_find(array, dest->target) != -1)
return TRUE;
if (dest->server_tag != NULL) {
- char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target);
- int ret = strarray_find_glob(array, tagtarget);
+ char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, "*");
+ int ret = strarray_find(array, tagtarget);
+ g_free(tagtarget);
+ if (ret != -1)
+ return TRUE;
+
+ tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target);
+ ret = strarray_find(array, tagtarget);
g_free(tagtarget);
if (ret != -1)
return TRUE;
From f31d37a85271e0196aeefd409f0ab361ffd8c2ff Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 18 Mar 2016 22:50:00 +0100
Subject: [PATCH 041/140] Make ischannel_func return false for empty strings
---
src/irc/core/irc-servers.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index d6fb8018..1df95f70 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -78,17 +78,23 @@ static int ischannel_func(SERVER_REC *server, const char *data)
IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
char *chantypes, *statusmsg;
+ g_return_val_if_fail(data != NULL, FALSE);
+
+ /* empty string is no channel */
+ if (*data == '\0')
+ return FALSE;
+
chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes");
if (chantypes == NULL)
chantypes = "#&!+"; /* normal, local, secure, modeless */
statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg");
- if (statusmsg != NULL) {
- while (strchr(statusmsg, *data) != NULL)
- data++;
- }
+ if (statusmsg != NULL)
+ data += strspn(data, statusmsg);
- return strchr(chantypes, *data) != NULL;
+ /* strchr(3) considers the trailing NUL as part of the string, make sure
+ * we didn't advance too much. */
+ return *data != '\0' && strchr(chantypes, *data) != NULL;
}
static char **split_line(const SERVER_REC *server, const char *line,
From 6745dd6159afc6ff220d09d7adc1923218fa756b Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Fri, 18 Mar 2016 20:18:58 +0100
Subject: [PATCH 042/140] Throw an error when a chatnet has no available url
If you type /connect and the chatnet has no url available
let's just throw an error instead of trying to process as a url.
---
src/core/chat-commands.c | 7 +++++++
src/core/commands.h | 3 ++-
src/core/servers-setup.c | 2 ++
src/fe-common/core/fe-core-commands.c | 3 ++-
src/fe-common/core/module-formats.c | 1 +
src/fe-common/core/module-formats.h | 1 +
6 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c
index 7f000cf5..a9404fa3 100644
--- a/src/core/chat-commands.c
+++ b/src/core/chat-commands.c
@@ -73,6 +73,13 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
conn = server_create_conn(proto != NULL ? proto->id : -1, addr,
atoi(portstr), chatnet, password, nick);
+ if (conn == NULL) {
+ signal_emit("error command", 1,
+ GINT_TO_POINTER(CMDERR_NO_SERVER_DEFINED));
+ cmd_params_free(free_arg);
+ return NULL;
+ }
+
if (proto == NULL)
proto = chat_protocol_find_id(conn->chat_type);
diff --git a/src/core/commands.h b/src/core/commands.h
index 72105ad3..93d6276b 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -41,7 +41,8 @@ enum {
CMDERR_INVALID_TIME, /* invalid time specification */
CMDERR_INVALID_CHARSET, /* invalid charset specification */
CMDERR_EVAL_MAX_RECURSE, /* eval hit recursion limit */
- CMDERR_PROGRAM_NOT_FOUND /* program not found */
+ CMDERR_PROGRAM_NOT_FOUND, /* program not found */
+ CMDERR_NO_SERVER_DEFINED, /* no server has been defined for a given chatnet */
};
/* Return the full command for `alias' */
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 4a048282..990d2d4b 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -323,6 +323,8 @@ server_create_conn(int chat_type, const char *dest, int port,
rec = create_chatnet_conn(chatrec->name, port, password, nick);
if (rec != NULL)
return rec;
+ /* The chatnet has no url to connect to */
+ return NULL;
}
chatrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c
index 7b1d7b94..97a246ec 100644
--- a/src/fe-common/core/fe-core-commands.c
+++ b/src/fe-common/core/fe-core-commands.c
@@ -51,7 +51,8 @@ static int ret_texts[] = {
TXT_INVALID_TIME,
TXT_INVALID_CHARSET,
TXT_EVAL_MAX_RECURSE,
- TXT_PROGRAM_NOT_FOUND
+ TXT_PROGRAM_NOT_FOUND,
+ TXT_NO_SERVER_DEFINED,
};
int command_hide_output;
diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c
index e6d32b6d..b897b0c6 100644
--- a/src/fe-common/core/module-formats.c
+++ b/src/fe-common/core/module-formats.c
@@ -223,6 +223,7 @@ FORMAT_REC fecommon_core_formats[] = {
{ "invalid_charset", "Invalid charset: $0", 1, { 0 } },
{ "eval_max_recurse", "/eval hit maximum recursion limit", 0 },
{ "program_not_found", "Could not find file or file is not executable", 0 },
+ { "no_server_defined", "No servers defined for this network, see /help server for how to add one", 0 },
/* ---- */
{ NULL, "Themes", 0 },
diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h
index 3f06bb97..de1e13f2 100644
--- a/src/fe-common/core/module-formats.h
+++ b/src/fe-common/core/module-formats.h
@@ -192,6 +192,7 @@ enum {
TXT_INVALID_CHARSET,
TXT_EVAL_MAX_RECURSE,
TXT_PROGRAM_NOT_FOUND,
+ TXT_NO_SERVER_DEFINED,
TXT_FILL_11,
From 8394973d5a3f37523e95fb5b51620de9284d743f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 20 Mar 2016 12:16:48 +0100
Subject: [PATCH 043/140] Bump the ABI version
Since a new format has been added.
---
src/common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/common.h b/src/common.h
index 729049ab..33dbd481 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 2
+#define IRSSI_ABI_VERSION 3
#define DEFAULT_SERVER_ADD_PORT 6667
From 550fe6f010f682d352077579d5056609a68e9814 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 20 Mar 2016 21:47:02 +0100
Subject: [PATCH 044/140] Use 0 as a sentinel value for sasl_timeout
If sasl_timeout is never initialized with a valid timeout id then
calling /disconnect on the server calls g_source_remove() with 0 as tag,
causing an harmless error message to be printed.
Beside that, the sasl_timeout field is defined as a unsigned int.
We can use 0 as sentiel since g_timeout_add returns tags that are always
greater than zero.
---
src/irc/core/sasl.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index db099368..b74b6a8c 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -34,7 +34,7 @@ static gboolean sasl_timeout(IRC_SERVER_REC *server)
irc_send_cmd_now(server, "AUTHENTICATE *");
cap_finish_negotiation(server);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
signal_emit("server sasl failure", 2, server, "The authentication timed out");
@@ -64,9 +64,9 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from
char *params, *error;
/* Stop any pending timeout, if any */
- if (server->sasl_timeout != -1) {
+ if (server->sasl_timeout != 0) {
g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
}
params = event_get_params(data, 2, NULL, &error);
@@ -81,9 +81,9 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from
static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *from)
{
- if (server->sasl_timeout != -1) {
+ if (server->sasl_timeout != 0) {
g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
}
signal_emit("server sasl success", 1, server);
@@ -94,9 +94,9 @@ static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *f
static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *from)
{
- if (server->sasl_timeout != -1) {
+ if (server->sasl_timeout != 0) {
g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
}
signal_emit("server sasl success", 1, server);
@@ -114,9 +114,9 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from
conn = server->connrec;
/* Stop the timer */
- if (server->sasl_timeout != -1) {
+ if (server->sasl_timeout != 0) {
g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
}
switch (conn->sasl_mechanism) {
@@ -161,9 +161,9 @@ static void sasl_disconnected(IRC_SERVER_REC *server)
return;
}
- if (server->sasl_timeout != -1) {
+ if (server->sasl_timeout != 0) {
g_source_remove(server->sasl_timeout);
- server->sasl_timeout = -1;
+ server->sasl_timeout = 0;
}
}
From 132d3c49f302a87d1357ba91ba715faa6bfcea29 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Sun, 20 Mar 2016 22:39:06 +0100
Subject: [PATCH 045/140] strip less whitespace from commands
fixes #445
---
src/fe-common/core/completion.c | 2 +-
src/fe-common/core/fe-settings.c | 2 +-
src/irc/dcc/dcc.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 1e7833a4..861054b5 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -762,7 +762,7 @@ static void cmd_completion(const char *data)
int len;
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+ PARAM_FLAG_GETREST,
"completion", &optlist, &key, &value))
return;
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 3bb43bf7..b689cbf9 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -109,7 +109,7 @@ static void cmd_set(char *data)
SETTINGS_REC *rec;
if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
- PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS,
+ PARAM_FLAG_OPTIONS,
"set", &optlist, &key, &value))
return;
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 7f35585e..17f6c477 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -496,8 +496,8 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server)
g_return_if_fail(data != NULL);
- if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST |
- PARAM_FLAG_STRIP_TRAILING_WS, &typestr, &nick, &arg))
+ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
+ &typestr, &nick, &arg))
return;
if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
From 7baf3a28bbcc1f92707ecb06f1d8e648388a474c Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Sun, 20 Mar 2016 22:43:12 +0100
Subject: [PATCH 046/140] correct quoting in /help dcc
---
docs/help/in/dcc.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in
index 649cb12b..dac31e58 100644
--- a/docs/help/in/dcc.in
+++ b/docs/help/in/dcc.in
@@ -36,10 +36,10 @@
%9Examples:%9
/DCC CHAT mike
- /DCC GET bob 'summer vacation.mkv'
- /DCC SEND sarah documents/resume.pdf
+ /DCC GET bob summer vacation.mkv
+ /DCC SEND sarah "summer vacation.mkv"
/DCC CLOSE get mike
- /DCC CLOSE send bob 'summer vacation.mkv'
+ /DCC CLOSE send bob summer vacation.mkv
%9See also:%9 CD
From 117c890d98d54fdee85a56f851acd6f4b3bd3be3 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 22 Mar 2016 14:43:31 +0100
Subject: [PATCH 047/140] cutbuffer: do not unconditionally use replace when
noop was requested
---
src/fe-text/gui-entry.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 27778b2b..f275c235 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -582,7 +582,8 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
if (size == 0 || entry->pos < size)
return;
- if (entry->cutbuffer_len == 0) {
+ if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP
+ && entry->cutbuffer_len == 0) {
update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
}
int cutbuffer_new_size = entry->cutbuffer_len + size;
From 938d0071c6119f7ec9aeaa88913c47f7af267131 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 22 Mar 2016 15:21:20 +0100
Subject: [PATCH 048/140] fix race condition in terminal init
remove the tcgetattr call to a single time on irssi load instead of
querying it each time. Fixes #450
---
src/fe-text/terminfo-core.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index 60927f1a..4db68cc7 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -496,7 +496,7 @@ void terminfo_setup_colors(TERM_REC *term, int force)
}
}
-static void terminfo_input_init(TERM_REC *term)
+static void terminfo_input_init0(TERM_REC *term)
{
tcgetattr(fileno(term->in), &term->old_tio);
memcpy(&term->tio, &term->old_tio, sizeof(term->tio));
@@ -518,8 +518,11 @@ static void terminfo_input_init(TERM_REC *term)
term->tio.c_cc[VSUSP] = _POSIX_VDISABLE;
#endif
- tcsetattr(fileno(term->in), TCSADRAIN, &term->tio);
+}
+static void terminfo_input_init(TERM_REC *term)
+{
+ tcsetattr(fileno(term->in), TCSADRAIN, &term->tio);
}
static void terminfo_input_deinit(TERM_REC *term)
@@ -673,6 +676,7 @@ static int term_setup(TERM_REC *term)
term->beep = term->TI_bel ? _beep : _ignore;
terminfo_setup_colors(term, FALSE);
+ terminfo_input_init0(term);
terminfo_cont(term);
return 1;
}
From e5ee243ab6ff7f640bdd45a232ad81ed97520a46 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 22 Mar 2016 15:45:08 +0100
Subject: [PATCH 049/140] Simplify some logic in server_create_conn
---
src/core/servers-setup.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 990d2d4b..0cecfece 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -321,10 +321,8 @@ server_create_conn(int chat_type, const char *dest, int port,
chatrec = chatnet_find(dest);
if (chatrec != NULL) {
rec = create_chatnet_conn(chatrec->name, port, password, nick);
- if (rec != NULL)
- return rec;
- /* The chatnet has no url to connect to */
- return NULL;
+ /* If rec is NULL the chatnet has no url to connect to */
+ return rec;
}
chatrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
From 8b54366d9525d94ae4b1d0d6914b22b7bf73112e Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 21 Mar 2016 15:23:12 +0100
Subject: [PATCH 050/140] Support quoted filenames in some /DCC commands
---
src/irc/dcc/dcc-get.c | 8 +++++---
src/irc/dcc/dcc.c | 6 ++++--
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c
index a8b1c967..ac281683 100644
--- a/src/irc/dcc/dcc-get.c
+++ b/src/irc/dcc/dcc-get.c
@@ -526,14 +526,14 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func,
{
GET_DCC_REC *dcc;
GSList *tmp, *next;
- char *nick, *fname;
+ char *nick, *arg, *fname;
void *free_arg;
int found;
g_return_if_fail(data != NULL);
- if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST,
- &nick, &fname))
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
+ PARAM_FLAG_STRIP_TRAILING_WS, &nick, &arg))
return;
if (*nick == '\0') {
@@ -548,6 +548,8 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func,
return;
}
+ fname = cmd_get_quoted_param(&arg);
+
found = FALSE;
for (tmp = dcc_conns; tmp != NULL; tmp = next) {
GET_DCC_REC *dcc = tmp->data;
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 17f6c477..c51f7c7a 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -490,7 +490,7 @@ static void event_no_such_nick(IRC_SERVER_REC *server, char *data)
static void cmd_dcc_close(char *data, IRC_SERVER_REC *server)
{
GSList *tmp, *next;
- char *typestr, *nick, *arg;
+ char *typestr, *nick, *arg, *fname;
void *free_arg;
int found, type;
@@ -510,13 +510,15 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server)
return;
}
+ fname = cmd_get_quoted_param(&arg);
+
found = FALSE;
for (tmp = dcc_conns; tmp != NULL; tmp = next) {
DCC_REC *dcc = tmp->data;
next = tmp->next;
if (dcc->type == type && g_ascii_strcasecmp(dcc->nick, nick) == 0 &&
- (*arg == '\0' || g_strcmp0(dcc->arg, arg) == 0)) {
+ (*fname == '\0' || g_strcmp0(dcc->arg, fname) == 0)) {
dcc_reject(dcc, server);
found = TRUE;
}
From be93c8d5bee1b923faa63e13957764e3f06e2ded Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 22 Mar 2016 16:03:05 +0100
Subject: [PATCH 051/140] Update the documentation about DCC
---
docs/help/in/dcc.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in
index dac31e58..18a77ee9 100644
--- a/docs/help/in/dcc.in
+++ b/docs/help/in/dcc.in
@@ -36,10 +36,10 @@
%9Examples:%9
/DCC CHAT mike
- /DCC GET bob summer vacation.mkv
+ /DCC GET bob "summer vacation.mkv"
/DCC SEND sarah "summer vacation.mkv"
/DCC CLOSE get mike
- /DCC CLOSE send bob summer vacation.mkv
+ /DCC CLOSE send bob "summer vacation.mkv"
%9See also:%9 CD
From 35d255fc8c2bc585bacbe59afb8cf9c6cc3cadc8 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 22 Mar 2016 16:05:14 +0100
Subject: [PATCH 052/140] Properly toggle bracketed paste mode on stop/cont
Fixes #449
---
src/common.h | 2 +-
src/fe-text/term-terminfo.c | 8 --------
src/fe-text/terminfo-core.c | 23 +++++++++++++++++++++++
src/fe-text/terminfo-core.h | 3 +++
4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/src/common.h b/src/common.h
index 729049ab..33dbd481 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 2
+#define IRSSI_ABI_VERSION 3
#define DEFAULT_SERVER_ADD_PORT 6667
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 3582b9e4..27be904e 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -710,11 +710,3 @@ 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/terminfo-core.c b/src/fe-text/terminfo-core.c
index 60927f1a..086c8801 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -395,6 +395,14 @@ static void _ignore_parm(TERM_REC *term, int param)
{
}
+static void term_dec_set_bracketed_paste_mode(int enable)
+{
+ if (enable)
+ tputs("\e[?2004h", 0, term_putchar);
+ else
+ tputs("\e[?2004l", 0, term_putchar);
+}
+
static void term_fill_capabilities(TERM_REC *term)
{
int i, ival;
@@ -535,6 +543,9 @@ void terminfo_cont(TERM_REC *term)
if (term->TI_smkx)
tput(tparm(term->TI_smkx));
+ if (term->bracketed_paste_enabled)
+ term_dec_set_bracketed_paste_mode(TRUE);
+
terminfo_input_init(term);
}
@@ -545,6 +556,9 @@ void terminfo_stop(TERM_REC *term)
/* move cursor to bottom of the screen */
terminfo_move(0, term->height-1);
+ if (term->bracketed_paste_enabled)
+ term_dec_set_bracketed_paste_mode(FALSE);
+
/* stop cup-mode */
if (term->TI_rmcup)
tput(tparm(term->TI_rmcup));
@@ -677,6 +691,15 @@ static int term_setup(TERM_REC *term)
return 1;
}
+void term_set_bracketed_paste_mode(int enable)
+{
+ if (current_term->bracketed_paste_enabled == enable)
+ return;
+
+ current_term->bracketed_paste_enabled = enable;
+ term_dec_set_bracketed_paste_mode(enable);
+}
+
TERM_REC *terminfo_core_init(FILE *in, FILE *out)
{
TERM_REC *old_term, *term;
diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h
index 21398791..0ef280a1 100644
--- a/src/fe-text/terminfo-core.h
+++ b/src/fe-text/terminfo-core.h
@@ -92,6 +92,9 @@ struct _TERM_REC {
/* Keyboard-transmit mode */
const char *TI_smkx;
const char *TI_rmkx;
+
+ /* Terminal mode states */
+ int bracketed_paste_enabled;
};
extern TERM_REC *current_term;
From 897016131eb2712095a7facaf9ab307164976450 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 21 Mar 2016 14:19:43 +0100
Subject: [PATCH 053/140] Don't call terminfo_cont() twice on resume
Fixes some weirdness when using ^Z with zsh.
---
src/fe-text/term-terminfo.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 3582b9e4..ed9c8d32 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -611,8 +611,6 @@ void term_stop(void)
{
terminfo_stop(current_term);
kill(getpid(), SIGTSTP);
- terminfo_cont(current_term);
- irssi_redraw();
}
static int input_utf8(const unsigned char *buffer, int size, unichar *result)
From b9914abbf3a7fae6d15f26650a98d8e74aa1fa05 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Tue, 22 Mar 2016 16:54:34 +0100
Subject: [PATCH 054/140] Make use of terminal application keys configurable
adds a new setting term_appkey_mode which can enable or disable the use
of keyboard transmit (application keys) mode. Fixes #430
---
src/fe-text/gui-readline.c | 2 ++
src/fe-text/term.h | 1 +
src/fe-text/terminfo-core.c | 23 +++++++++++++++++++----
src/fe-text/terminfo-core.h | 1 +
4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index ff91f9e3..b93e5f0f 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -1060,6 +1060,7 @@ static void setup_changed(void)
paste_join_multiline = settings_get_bool("paste_join_multiline");
paste_use_bracketed_mode = settings_get_bool("paste_use_bracketed_mode");
+ term_set_appkey_mode(settings_get_bool("term_appkey_mode"));
/* Enable the bracketed paste mode on demand */
term_set_bracketed_paste_mode(paste_use_bracketed_mode);
}
@@ -1082,6 +1083,7 @@ void gui_readline_init(void)
g_get_current_time(&last_keypress);
input_listen_init(STDIN_FILENO);
+ settings_add_bool("lookandfeel", "term_appkey_mode", TRUE);
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);
diff --git a/src/fe-text/term.h b/src/fe-text/term.h
index 5f0a799e..9b726d82 100644
--- a/src/fe-text/term.h
+++ b/src/fe-text/term.h
@@ -94,6 +94,7 @@ void term_refresh(TERM_WINDOW *window);
void term_stop(void);
+void term_set_appkey_mode(int enable);
void term_set_bracketed_paste_mode(int enable);
/* keyboard input handling */
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index aa833abf..15b00081 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -395,6 +395,12 @@ static void _ignore_parm(TERM_REC *term, int param)
{
}
+static void terminfo_set_appkey_mode(TERM_REC *term, int set)
+{
+ if (term->TI_smkx && term->TI_rmkx)
+ tput(tparm(set ? term->TI_smkx : term->TI_rmkx));
+}
+
static void term_dec_set_bracketed_paste_mode(int enable)
{
if (enable)
@@ -543,8 +549,8 @@ void terminfo_cont(TERM_REC *term)
if (term->TI_smcup)
tput(tparm(term->TI_smcup));
- if (term->TI_smkx)
- tput(tparm(term->TI_smkx));
+ if (term->appkey_enabled)
+ terminfo_set_appkey_mode(term, TRUE);
if (term->bracketed_paste_enabled)
term_dec_set_bracketed_paste_mode(TRUE);
@@ -566,8 +572,8 @@ void terminfo_stop(TERM_REC *term)
if (term->TI_rmcup)
tput(tparm(term->TI_rmcup));
- if (term->TI_rmkx)
- tput(tparm(term->TI_rmkx));
+ if (term->appkey_enabled)
+ terminfo_set_appkey_mode(term, FALSE);
/* reset input settings */
terminfo_input_deinit(term);
@@ -695,6 +701,15 @@ static int term_setup(TERM_REC *term)
return 1;
}
+void term_set_appkey_mode(int enable)
+{
+ if (current_term->appkey_enabled == enable)
+ return;
+
+ current_term->appkey_enabled = enable;
+ terminfo_set_appkey_mode(current_term, enable);
+}
+
void term_set_bracketed_paste_mode(int enable)
{
if (current_term->bracketed_paste_enabled == enable)
diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h
index 0ef280a1..1253fd9d 100644
--- a/src/fe-text/terminfo-core.h
+++ b/src/fe-text/terminfo-core.h
@@ -94,6 +94,7 @@ struct _TERM_REC {
const char *TI_rmkx;
/* Terminal mode states */
+ int appkey_enabled;
int bracketed_paste_enabled;
};
From aec2466e36ec32e97ec2eb8e1279e27a3d0fe0cb Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Mon, 21 Mar 2016 09:14:01 +0100
Subject: [PATCH 055/140] Improve cutbuffer handling
* Adds two new keys which you can bind in /bind:
yank_next_cutbuffer: Revert to the previous last deleted text
append_next_kill: Append next deletion
* Consecutive kills are now appended to the current cutbuffer
---
src/fe-text/gui-entry.c | 171 ++++++++++++++++++++++++++-----------
src/fe-text/gui-entry.h | 15 +++-
src/fe-text/gui-readline.c | 62 ++++++++++++--
3 files changed, 190 insertions(+), 58 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index f275c235..63dda34e 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -32,6 +32,8 @@
#undef i_tolower
#undef i_isalnum
+#define KILL_RING_MAX 10
+
static unichar i_toupper(unichar c)
{
if (term_type == TERM_TYPE_UTF8)
@@ -82,11 +84,22 @@ GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
void gui_entry_destroy(GUI_ENTRY_REC *entry)
{
+ GSList *tmp;
+
g_return_if_fail(entry != NULL);
if (active_entry == entry)
gui_entry_set_active(NULL);
+ for (tmp = entry->kill_ring; tmp != NULL; tmp = tmp->next) {
+ GUI_ENTRY_CUTBUFFER_REC *rec = tmp->data;
+ if (rec != NULL) {
+ g_free(rec->cutbuffer);
+ g_free(rec);
+ }
+ }
+ g_slist_free(entry->kill_ring);
+
g_free(entry->text);
g_free(entry->prompt);
g_free(entry);
@@ -546,22 +559,42 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
g_return_val_if_fail(entry != NULL, NULL);
- if (entry->cutbuffer == NULL)
+ if (entry->kill_ring == NULL || entry->kill_ring->data == NULL)
+ return NULL;
+
+ GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data;
+
+ if (tmp->cutbuffer == NULL)
return NULL;
if (entry->utf8)
- buf = g_ucs4_to_utf8(entry->cutbuffer, -1, NULL, NULL, NULL);
+ buf = g_ucs4_to_utf8(tmp->cutbuffer, -1, NULL, NULL, NULL);
else {
- buf = g_malloc(entry->cutbuffer_len*6 + 1);
+ buf = g_malloc(tmp->cutbuffer_len*6 + 1);
if (term_type == TERM_TYPE_BIG5)
- unichars_to_big5(entry->cutbuffer, buf);
+ unichars_to_big5(tmp->cutbuffer, buf);
else
- for (i = 0; i <= entry->cutbuffer_len; i++)
- buf[i] = entry->cutbuffer[i];
+ for (i = 0; i <= tmp->cutbuffer_len; i++)
+ buf[i] = tmp->cutbuffer[i];
}
return buf;
}
+char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry)
+{
+ g_return_val_if_fail(entry != NULL, NULL);
+
+ if (entry->kill_ring == NULL)
+ return NULL;
+
+ GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data;
+
+ entry->kill_ring = g_slist_remove(entry->kill_ring, tmp);
+ entry->kill_ring = g_slist_append(entry->kill_ring, tmp);
+
+ return gui_entry_get_cutbuffer(entry);
+}
+
void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer)
{
int newpos, size = 0;
@@ -573,6 +606,40 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP updat
gui_entry_erase(entry, size, update_cutbuffer);
}
+static GUI_ENTRY_CUTBUFFER_REC *get_cutbuffer_rec(GUI_ENTRY_REC *entry, CUTBUFFER_UPDATE_OP update_cutbuffer)
+{
+ GUI_ENTRY_CUTBUFFER_REC *tmp = NULL;
+
+ g_return_val_if_fail(entry != NULL, NULL);
+
+ if (entry->kill_ring == NULL) {
+ /* no kill ring exists */
+ entry->kill_ring = g_slist_prepend(entry->kill_ring, (void *)NULL);
+ } else {
+ tmp = entry->kill_ring->data;
+
+ if (tmp != NULL && tmp->cutbuffer_len > 0
+ && (!entry->previous_append_next_kill
+ || update_cutbuffer == CUTBUFFER_UPDATE_REPLACE)) {
+ /* a cutbuffer exists and should be replaced */
+ entry->kill_ring = g_slist_prepend(entry->kill_ring, (void *)NULL);
+ }
+ }
+
+ if (g_slist_length(entry->kill_ring) > KILL_RING_MAX) {
+ GUI_ENTRY_CUTBUFFER_REC *rec = g_slist_last(entry->kill_ring)->data;
+ entry->kill_ring = g_slist_remove(entry->kill_ring, rec);
+ if (rec != NULL) g_free(rec->cutbuffer);
+ g_free(rec);
+ }
+
+ if (entry->kill_ring->data == NULL) {
+ entry->kill_ring->data = g_new0(GUI_ENTRY_CUTBUFFER_REC, 1);
+ }
+
+ return entry->kill_ring->data;
+}
+
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer)
{
size_t w = 0;
@@ -582,51 +649,59 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_
if (size == 0 || entry->pos < size)
return;
- if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP
- && entry->cutbuffer_len == 0) {
- update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
- }
- int cutbuffer_new_size = entry->cutbuffer_len + size;
- unichar *tmpcutbuffer = entry->cutbuffer;
- switch (update_cutbuffer) {
- case CUTBUFFER_UPDATE_APPEND:
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- memcpy(entry->cutbuffer, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
- memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar),
- entry->text + entry->pos - size, size * sizeof(unichar));
+ if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP) {
+ int cutbuffer_new_size;
+ unichar *tmpcutbuffer;
+ GUI_ENTRY_CUTBUFFER_REC *tmp = get_cutbuffer_rec(entry, update_cutbuffer);
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
- g_free(tmpcutbuffer);
- break;
+ if (tmp->cutbuffer_len == 0) {
+ update_cutbuffer = CUTBUFFER_UPDATE_REPLACE;
+ }
- case CUTBUFFER_UPDATE_PREPEND:
- entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
- memcpy(entry->cutbuffer, entry->text + entry->pos - size,
- size * sizeof(unichar));
- memcpy(entry->cutbuffer + size, tmpcutbuffer,
- entry->cutbuffer_len * sizeof(unichar));
+ cutbuffer_new_size = tmp->cutbuffer_len + size;
+ tmpcutbuffer = tmp->cutbuffer;
+ entry->append_next_kill = TRUE;
+ switch (update_cutbuffer) {
+ case CUTBUFFER_UPDATE_APPEND:
+ tmp->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ memcpy(tmp->cutbuffer, tmpcutbuffer,
+ tmp->cutbuffer_len * sizeof(unichar));
+ memcpy(tmp->cutbuffer + tmp->cutbuffer_len * sizeof(unichar),
+ entry->text + entry->pos - size, size * sizeof(unichar));
- entry->cutbuffer_len = cutbuffer_new_size;
- entry->cutbuffer[cutbuffer_new_size] = '\0';
- g_free(tmpcutbuffer);
- break;
+ tmp->cutbuffer_len = cutbuffer_new_size;
+ tmp->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ break;
- case CUTBUFFER_UPDATE_REPLACE:
- /* put erased text to cutbuffer */
- if (entry->cutbuffer_len < size) {
- g_free(entry->cutbuffer);
- entry->cutbuffer = g_new(unichar, size+1);
- }
+ case CUTBUFFER_UPDATE_PREPEND:
+ tmp->cutbuffer = g_new(unichar, cutbuffer_new_size+1);
+ memcpy(tmp->cutbuffer, entry->text + entry->pos - size,
+ size * sizeof(unichar));
+ memcpy(tmp->cutbuffer + size, tmpcutbuffer,
+ tmp->cutbuffer_len * sizeof(unichar));
- entry->cutbuffer_len = size;
- entry->cutbuffer[size] = '\0';
- memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar));
- break;
+ tmp->cutbuffer_len = cutbuffer_new_size;
+ tmp->cutbuffer[cutbuffer_new_size] = '\0';
+ g_free(tmpcutbuffer);
+ break;
- case CUTBUFFER_UPDATE_NOOP:
- break;
+ case CUTBUFFER_UPDATE_REPLACE:
+ /* put erased text to cutbuffer */
+ if (tmp->cutbuffer_len < size) {
+ g_free(tmp->cutbuffer);
+ tmp->cutbuffer = g_new(unichar, size+1);
+ }
+
+ tmp->cutbuffer_len = size;
+ tmp->cutbuffer[size] = '\0';
+ memcpy(tmp->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar));
+ break;
+
+ case CUTBUFFER_UPDATE_NOOP:
+ /* cannot happen, handled in "if" */
+ break;
+ }
}
if (entry->utf8)
@@ -686,10 +761,10 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O
}
if (to > 0) to++;
- gui_entry_erase(entry, entry->pos-to, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase(entry, entry->pos-to, cutbuffer_op);
}
-void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
+void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op)
{
int to, size;
@@ -712,7 +787,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
size = to-entry->pos;
entry->pos = to;
- gui_entry_erase(entry, size, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase(entry, size, cutbuffer_op);
}
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry)
diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h
index d22a7fb8..8777f083 100644
--- a/src/fe-text/gui-entry.h
+++ b/src/fe-text/gui-entry.h
@@ -1,12 +1,16 @@
#ifndef __GUI_ENTRY_H
#define __GUI_ENTRY_H
+typedef struct {
+ int cutbuffer_len;
+ unichar *cutbuffer;
+} GUI_ENTRY_CUTBUFFER_REC;
+
typedef struct {
int text_len, text_alloc; /* as shorts, not chars */
unichar *text;
- int cutbuffer_len;
- unichar *cutbuffer;
+ GSList *kill_ring;
/* all as shorts, not chars */
int xpos, ypos, width; /* entry position in screen */
@@ -18,6 +22,10 @@ typedef struct {
int redraw_needed_from;
unsigned int utf8:1;
+
+ unsigned int previous_append_next_kill:1;
+ unsigned int append_next_kill:1;
+ unsigned int yank_preceded:1;
} GUI_ENTRY_REC;
typedef enum {
@@ -47,11 +55,12 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str);
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr);
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
+char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry);
void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer);
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer);
void gui_entry_erase_cell(GUI_ENTRY_REC *entry);
void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op);
-void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space);
+void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op);
void gui_entry_transpose_chars(GUI_ENTRY_REC *entry);
void gui_entry_transpose_words(GUI_ENTRY_REC *entry);
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index b93e5f0f..e0ffb4f1 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -73,6 +73,7 @@ static int paste_timeout_id;
static int paste_use_bracketed_mode;
static int paste_bracketed_mode;
static int paste_was_bracketed_mode;
+static int previous_yank_preceded;
/* Terminal sequences that surround the input when the terminal has the
* bracketed paste mode active. Fror more details see
@@ -440,11 +441,20 @@ static void sig_gui_key_pressed(gpointer keyp)
gui_entry_insert_char(active_entry, key);
ret = 1;
} else {
+ previous_yank_preceded = active_entry->yank_preceded;
+ active_entry->yank_preceded = FALSE;
+ active_entry->previous_append_next_kill = active_entry->append_next_kill;
+ active_entry->append_next_kill = FALSE;
ret = key_pressed(keyboard, str);
if (ret < 0) {
/* key wasn't used for anything, print it */
gui_entry_insert_char(active_entry, key);
}
+ if (ret == 0) {
+ /* combo not complete, ignore append_next_kill and yank_preceded */
+ active_entry->append_next_kill = active_entry->previous_append_next_kill;
+ active_entry->yank_preceded = previous_yank_preceded;
+ }
}
/* ret = 0 : some key create multiple characters - we're in the middle
@@ -571,7 +581,7 @@ static void key_erase_to_beg_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
- gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_PREPEND);
}
static void key_erase_to_end_of_line(void)
@@ -580,7 +590,7 @@ static void key_erase_to_end_of_line(void)
pos = gui_entry_get_pos(active_entry);
gui_entry_set_pos(active_entry, active_entry->text_len);
- gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_APPEND);
}
static void key_yank_from_cutbuffer(void)
@@ -590,7 +600,36 @@ static void key_yank_from_cutbuffer(void)
cutbuffer = gui_entry_get_cutbuffer(active_entry);
if (cutbuffer != NULL) {
gui_entry_insert_text(active_entry, cutbuffer);
- g_free(cutbuffer);
+ active_entry->yank_preceded = TRUE;
+ g_free(cutbuffer);
+ }
+}
+
+static void key_yank_next_cutbuffer(void)
+{
+ GUI_ENTRY_CUTBUFFER_REC *rec;
+ guint length = 0;
+ char *cutbuffer;
+
+ if (!previous_yank_preceded) {
+ if (settings_get_bool("bell_beeps")) {
+ signal_emit("beep", 0);
+ }
+ return;
+ }
+
+ if (active_entry->kill_ring == NULL)
+ return;
+
+ rec = active_entry->kill_ring->data;
+ if (rec != NULL) length = rec->cutbuffer_len;
+
+ cutbuffer = gui_entry_get_next_cutbuffer(active_entry);
+ if (cutbuffer != NULL) {
+ gui_entry_erase(active_entry, length, CUTBUFFER_UPDATE_NOOP);
+ gui_entry_insert_text(active_entry, cutbuffer);
+ active_entry->yank_preceded = TRUE;
+ g_free(cutbuffer);
}
}
@@ -632,22 +671,27 @@ static void key_backspace(void)
static void key_delete_previous_word(void)
{
- gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_PREPEND);
}
static void key_delete_next_word(void)
{
- gui_entry_erase_next_word(active_entry, FALSE);
+ gui_entry_erase_next_word(active_entry, FALSE, CUTBUFFER_UPDATE_APPEND);
}
static void key_delete_to_previous_space(void)
{
- gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_REPLACE);
+ gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_PREPEND);
}
static void key_delete_to_next_space(void)
{
- gui_entry_erase_next_word(active_entry, TRUE);
+ gui_entry_erase_next_word(active_entry, TRUE, CUTBUFFER_UPDATE_APPEND);
+}
+
+static void key_append_next_kill(void)
+{
+ active_entry->append_next_kill = TRUE;
}
static gboolean paste_timeout(gpointer data)
@@ -1191,6 +1235,8 @@ void gui_readline_init(void)
key_bind("erase_to_beg_of_line", "Erase everything before the cursor", NULL, NULL, (SIGNAL_FUNC) key_erase_to_beg_of_line);
key_bind("erase_to_end_of_line", "Erase everything after the cursor", "^K", NULL, (SIGNAL_FUNC) key_erase_to_end_of_line);
key_bind("yank_from_cutbuffer", "\"Undelete\", paste the last deleted text", "^Y", NULL, (SIGNAL_FUNC) key_yank_from_cutbuffer);
+ key_bind("yank_next_cutbuffer", "Revert to the previous last deleted text", NULL, NULL, (SIGNAL_FUNC) key_yank_next_cutbuffer);
+ key_bind("append_next_kill", "Append next deletion", NULL, NULL, (SIGNAL_FUNC) key_append_next_kill);
key_bind("transpose_characters", "Swap current and previous character", "^T", NULL, (SIGNAL_FUNC) key_transpose_characters);
key_bind("transpose_words", "Swap current and previous word", NULL, NULL, (SIGNAL_FUNC) key_transpose_words);
key_bind("capitalize_word", "Capitalize the current word", NULL, NULL, (SIGNAL_FUNC) key_capitalize_word);
@@ -1280,6 +1326,8 @@ void gui_readline_deinit(void)
key_unbind("erase_to_beg_of_line", (SIGNAL_FUNC) key_erase_to_beg_of_line);
key_unbind("erase_to_end_of_line", (SIGNAL_FUNC) key_erase_to_end_of_line);
key_unbind("yank_from_cutbuffer", (SIGNAL_FUNC) key_yank_from_cutbuffer);
+ key_unbind("yank_next_cutbuffer", (SIGNAL_FUNC) key_yank_next_cutbuffer);
+ key_unbind("append_next_kill", (SIGNAL_FUNC) key_append_next_kill);
key_unbind("transpose_characters", (SIGNAL_FUNC) key_transpose_characters);
key_unbind("transpose_words", (SIGNAL_FUNC) key_transpose_words);
From ec4ecd844bbc9c3254963862b0fff6be290db4ad Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Thu, 24 Mar 2016 16:01:07 +0100
Subject: [PATCH 056/140] Revert "Removed the obsolete SQUERY and SERVLIST
commands"
This reverts commit 4beebe3238dda96efd4c3a0a6f6002ad5afc96e7.
---
docs/help/in/list.in | 6 +++---
docs/help/in/servlist.in | 23 +++++++++++++++++++++++
docs/help/in/squery.in | 16 ++++++++++++++++
src/irc/core/irc-commands.c | 6 ++++++
4 files changed, 48 insertions(+), 3 deletions(-)
create mode 100644 docs/help/in/servlist.in
create mode 100644 docs/help/in/squery.in
diff --git a/docs/help/in/list.in b/docs/help/in/list.in
index 33f05e8b..b796eed0 100644
--- a/docs/help/in/list.in
+++ b/docs/help/in/list.in
@@ -25,10 +25,10 @@
%9Remarks:%9
Not all networks support server-side filtering and may provide a network
- service instead; on IRCnet, you may use the ALIS service:
+ service or service bot instead; on IRCnet, you may use the List service:
- /QUOTE SQUERY ALIS :HELP
+ /SQUERY List HELP
/MSG ALIS HELP
-%9See also:%9 QUOTE, STATS, WHOIS
+%9See also:%9 STATS, SQUERY, WHOIS
diff --git a/docs/help/in/servlist.in b/docs/help/in/servlist.in
new file mode 100644
index 00000000..0a0d025f
--- /dev/null
+++ b/docs/help/in/servlist.in
@@ -0,0 +1,23 @@
+
+%9Syntax:%9
+
+@SYNTAX:servlist@
+
+%9Parameters:%9
+
+ limits the output to the services which names matches
+ the mask.
+ limits the output to the services of the specified type.
+
+%9Description:%9
+
+ List the network services currently present on the
+ IRC network.
+
+%9Examples:%9
+
+ /SERVLIST *@javairc.*
+ /SERVLIST * 0xD000
+
+%9See also:%9 SQUERY
+
diff --git a/docs/help/in/squery.in b/docs/help/in/squery.in
new file mode 100644
index 00000000..59ee8008
--- /dev/null
+++ b/docs/help/in/squery.in
@@ -0,0 +1,16 @@
+
+%9Syntax:%9
+
+@SYNTAX:squery@
+
+%9Parameters:%9
+
+ - Service nickname or full hostmask of service to query.
+ - Message to send to the service.
+
+%9Description:%9
+
+ /SQUERY sends a query to the specified service.
+
+%9See also:%9 SERVLIST, LIST, MSG
+
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index 6baf2f6d..32ee8845 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -1018,11 +1018,15 @@ void irc_commands_init(void)
command_bind_irc("trace", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: VERSION [|] */
command_bind_irc("version", NULL, (SIGNAL_FUNC) command_self);
+ /* SYNTAX: SERVLIST [ []] */
+ command_bind_irc("servlist", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: SILENCE [[+|-]]
SILENCE [] */
command_bind_irc("silence", NULL, (SIGNAL_FUNC) command_self);
command_bind_irc("unsilence", NULL, (SIGNAL_FUNC) cmd_unsilence);
command_bind_irc("sconnect", NULL, (SIGNAL_FUNC) cmd_sconnect);
+ /* SYNTAX: SQUERY [] */
+ command_bind_irc("squery", NULL, (SIGNAL_FUNC) command_2self);
/* SYNTAX: DIE */
command_bind_irc("die", NULL, (SIGNAL_FUNC) command_self);
/* SYNTAX: HASH */
@@ -1091,9 +1095,11 @@ void irc_commands_deinit(void)
command_unbind("time", (SIGNAL_FUNC) command_self);
command_unbind("trace", (SIGNAL_FUNC) command_self);
command_unbind("version", (SIGNAL_FUNC) command_self);
+ command_unbind("servlist", (SIGNAL_FUNC) command_self);
command_unbind("silence", (SIGNAL_FUNC) command_self);
command_unbind("unsilence", (SIGNAL_FUNC) cmd_unsilence);
command_unbind("sconnect", (SIGNAL_FUNC) cmd_sconnect);
+ command_unbind("squery", (SIGNAL_FUNC) command_2self);
command_unbind("die", (SIGNAL_FUNC) command_self);
command_unbind("hash", (SIGNAL_FUNC) command_self);
command_unbind("oper", (SIGNAL_FUNC) cmd_oper);
From 2ba4b9d26afb87c2e661b1c07313ca78b3c5618e Mon Sep 17 00:00:00 2001
From: dequis
Date: Mon, 4 Apr 2016 03:47:48 -0300
Subject: [PATCH 057/140] net_gethosterror: Handle EAI_SYSTEM ("System error")
properly
That error code means "check errno". A few users got it and we never
figured out what happened - it usually fixed itself after restarting
something - so hopefully with this we'll have more information the next
time.
---
src/core/network.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/core/network.c b/src/core/network.c
index 76659f3e..3e1b7c70 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -510,7 +510,11 @@ const char *net_gethosterror(int error)
{
g_return_val_if_fail(error != 0, NULL);
- return gai_strerror(error);
+ if (error == EAI_SYSTEM) {
+ return strerror(errno);
+ } else {
+ return gai_strerror(error);
+ }
}
/* return TRUE if host lookup failed because it didn't exist (ie. not
From 9fa3869a97be7b79c0aa5f7a7e80d655b0a7f8d8 Mon Sep 17 00:00:00 2001
From: B Thibault
Date: Fri, 29 Apr 2016 00:12:28 +0200
Subject: [PATCH 058/140] retab
---
src/fe-common/core/hilight-text.c | 120 +++++++++++++++---------------
1 file changed, 60 insertions(+), 60 deletions(-)
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index b746f636..6aa19b88 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -49,7 +49,7 @@ static void reset_level_cache(void)
HILIGHT_REC *rec = tmp->data;
if (never_hilight_level & rec->level)
- never_hilight_level &= ~rec->level;
+ never_hilight_level &= ~rec->level;
}
}
@@ -68,17 +68,17 @@ static void hilight_add_config(HILIGHT_REC *rec)
node = iconfig_node_traverse("(hilights", TRUE);
node = iconfig_node_section(node, NULL, NODE_TYPE_BLOCK);
- iconfig_node_set_str(node, "text", rec->text);
- if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level);
- if (rec->color) iconfig_node_set_str(node, "color", rec->color);
- if (rec->act_color) iconfig_node_set_str(node, "act_color", rec->act_color);
- if (rec->priority > 0) iconfig_node_set_int(node, "priority", rec->priority);
- iconfig_node_set_bool(node, "nick", rec->nick);
- iconfig_node_set_bool(node, "word", rec->word);
- if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE);
- if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE);
- if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE);
- if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag);
+ iconfig_node_set_str(node, "text", rec->text);
+ if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level);
+ if (rec->color) iconfig_node_set_str(node, "color", rec->color);
+ if (rec->act_color) iconfig_node_set_str(node, "act_color", rec->act_color);
+ if (rec->priority > 0) iconfig_node_set_int(node, "priority", rec->priority);
+ iconfig_node_set_bool(node, "nick", rec->nick);
+ iconfig_node_set_bool(node, "word", rec->word);
+ if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE);
+ if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE);
+ if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE);
+ if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag);
if (rec->channels != NULL && *rec->channels != NULL) {
node = iconfig_node_section(node, "channels", NODE_TYPE_LIST);
@@ -191,7 +191,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels)
}
static int hilight_match_text(HILIGHT_REC *rec, const char *text,
- int *match_beg, int *match_end)
+ int *match_beg, int *match_end)
{
char *match;
@@ -200,9 +200,9 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text,
regmatch_t rmatch[1];
if (rec->regexp_compiled &&
- regexec(&rec->preg, text, 1, rmatch, 0) == 0) {
+ regexec(&rec->preg, text, 1, rmatch, 0) == 0) {
if (rmatch[0].rm_so > 0 &&
- match_beg != NULL && match_end != NULL) {
+ match_beg != NULL && match_end != NULL) {
*match_beg = rmatch[0].rm_so;
*match_end = rmatch[0].rm_eo;
}
@@ -222,7 +222,7 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text,
}
}
- return FALSE;
+ return FALSE;
}
#define hilight_match_level(rec, level) \
@@ -267,14 +267,14 @@ HILIGHT_REC *hilight_match(SERVER_REC *server, const char *channel,
HILIGHT_REC *rec = tmp->data;
if (!rec->nickmask && hilight_match_level(rec, level) &&
- hilight_match_channel(rec, channel) &&
- (rec->servertag == NULL ||
- (server != NULL && g_ascii_strcasecmp(rec->servertag, server->tag) == 0)) &&
- hilight_match_text(rec, str, match_beg, match_end))
+ hilight_match_channel(rec, channel) &&
+ (rec->servertag == NULL ||
+ (server != NULL && g_ascii_strcasecmp(rec->servertag, server->tag) == 0)) &&
+ hilight_match_text(rec, str, match_beg, match_end))
return rec;
}
- return NULL;
+ return NULL;
}
static char *hilight_get_act_color(HILIGHT_REC *rec)
@@ -308,7 +308,7 @@ void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec)
g_free_and_null(dest->hilight_color);
if (rec->act_color != NULL && g_strcmp0(rec->act_color, "%n") == 0)
dest->level |= MSGLEVEL_NO_ACT;
- else
+ else
dest->hilight_color = hilight_get_act_color(rec);
}
@@ -362,29 +362,29 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
/* hilight whole line */
char *tmp = strip_codes(text);
newstr = g_strconcat(color, tmp, NULL);
- g_free(tmp);
+ g_free(tmp);
} else {
/* hilight part of the line */
- GString *tmp;
- char *middle;
+ GString *tmp;
+ char *middle;
int pos, color_pos, color_len;
- tmp = g_string_new(NULL);
+ tmp = g_string_new(NULL);
- /* start of the line */
+ /* start of the line */
pos = strip_real_length(text, hilight_start, NULL, NULL);
g_string_append(tmp, text);
- g_string_truncate(tmp, pos);
+ g_string_truncate(tmp, pos);
/* color */
- g_string_append(tmp, color);
+ g_string_append(tmp, color);
/* middle of the line, stripped */
middle = strip_codes(text+pos);
- pos = tmp->len;
+ pos = tmp->len;
g_string_append(tmp, middle);
- g_string_truncate(tmp, pos+hilight_len);
- g_free(middle);
+ g_string_truncate(tmp, pos+hilight_len);
+ g_free(middle);
/* end of the line */
pos = strip_real_length(text, hilight_end,
@@ -398,8 +398,8 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
}
g_string_append(tmp, text+pos);
- newstr = tmp->str;
- g_string_free(tmp, FALSE);
+ newstr = tmp->str;
+ g_string_free(tmp, FALSE);
}
signal_emit("print text", 3, dest, newstr, stripped);
@@ -417,7 +417,7 @@ HILIGHT_REC *hilight_match_nick(SERVER_REC *server, const char *channel,
HILIGHT_REC *rec;
rec = hilight_match(server, channel, nick, address,
- level, msg, NULL, NULL);
+ level, msg, NULL, NULL);
return (rec == NULL || !rec->nick) ? NULL : rec;
}
@@ -475,7 +475,7 @@ static void read_hilight_config(void)
if (node != NULL) rec->channels = config_node_get_list(node);
}
- reset_cache();
+ reset_cache();
}
static void hilight_print(int index, HILIGHT_REC *rec)
@@ -519,10 +519,10 @@ static void hilight_print(int index, HILIGHT_REC *rec)
if (levelstr != NULL)
levelstr = g_strconcat(levelstr, " ", NULL);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
- TXT_HILIGHT_LINE, index, rec->text,
- chans != NULL ? chans : "",
- levelstr != NULL ? levelstr : "",
- options->str);
+ TXT_HILIGHT_LINE, index, rec->text,
+ chans != NULL ? chans : "",
+ levelstr != NULL ? levelstr : "",
+ options->str);
g_free_not_null(chans);
g_free_not_null(levelstr);
g_string_free(options, TRUE);
@@ -548,7 +548,7 @@ static void cmd_hilight_show(void)
[-network ] [-channels ] */
static void cmd_hilight(const char *data)
{
- GHashTable *optlist;
+ GHashTable *optlist;
HILIGHT_REC *rec;
char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text, *servertag;
char **channels;
@@ -562,7 +562,7 @@ static void cmd_hilight(const char *data)
}
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
- PARAM_FLAG_GETREST, "hilight", &optlist, &text))
+ PARAM_FLAG_GETREST, "hilight", &optlist, &text))
return;
chanarg = g_hash_table_lookup(optlist, "channels");
@@ -582,7 +582,7 @@ static void cmd_hilight(const char *data)
rec = g_new0(HILIGHT_REC, 1);
/* default to nick/word hilighting */
- rec->nick = TRUE;
+ rec->nick = TRUE;
rec->word = TRUE;
rec->text = g_strdup(text);
@@ -602,11 +602,11 @@ static void cmd_hilight(const char *data)
if (g_hash_table_lookup(optlist, "word") != NULL) {
rec->word = TRUE;
- rec->nick = FALSE;
+ rec->nick = FALSE;
}
if (g_hash_table_lookup(optlist, "nick") != NULL)
- rec->nick = TRUE;
+ rec->nick = TRUE;
rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL;
rec->fullword = g_hash_table_lookup(optlist, "full") != NULL;
@@ -631,7 +631,7 @@ static void cmd_hilight(const char *data)
hilight_create(rec);
hilight_print(g_slist_index(hilights, rec)+1, rec);
- cmd_params_free(free_arg);
+ cmd_params_free(free_arg);
reset_cache();
}
@@ -649,7 +649,7 @@ static void cmd_dehilight(const char *data)
} else {
/* with mask */
char *chans[2] = { "*", NULL };
- rec = hilight_find(data, chans);
+ rec = hilight_find(data, chans);
}
if (rec == NULL)
@@ -657,20 +657,20 @@ static void cmd_dehilight(const char *data)
else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_HILIGHT_REMOVED, rec->text);
hilight_remove(rec);
- reset_cache();
+ reset_cache();
}
}
static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel,
- NICK_REC *nick)
+ NICK_REC *nick)
{
GSList *tmp;
HILIGHT_REC *match;
- char *nickmask;
+ char *nickmask;
int len, best_match;
if (nick->host == NULL)
- return; /* don't check until host is known */
+ return; /* don't check until host is known */
nickmask = g_strconcat(nick->nick, "!", nick->host, NULL);
@@ -679,8 +679,8 @@ static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel,
HILIGHT_REC *rec = tmp->data;
if (rec->nickmask &&
- hilight_match_channel(rec, channel->name) &&
- match_wildcards(rec->text, nickmask)) {
+ hilight_match_channel(rec, channel->name) &&
+ match_wildcards(rec->text, nickmask)) {
len = strlen(rec->text);
if (best_match < len) {
best_match = len;
@@ -691,7 +691,7 @@ static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel,
g_free_not_null(nickmask);
if (match != NULL)
- g_hash_table_insert(list, nick, match);
+ g_hash_table_insert(list, nick, match);
}
static void read_settings(void)
@@ -706,14 +706,14 @@ void hilight_text_init(void)
settings_add_str("lookandfeel", "hilight_act_color", "%M");
settings_add_level("lookandfeel", "hilight_level", "PUBLIC DCCMSGS");
- read_settings();
+ read_settings();
nickmatch = nickmatch_init(hilight_nick_cache);
read_hilight_config();
signal_add_first("print text", (SIGNAL_FUNC) sig_print_text);
- signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
- signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+ signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
+ signal_add("setup changed", (SIGNAL_FUNC) read_settings);
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
@@ -723,11 +723,11 @@ void hilight_text_init(void)
void hilight_text_deinit(void)
{
hilights_destroy_all();
- nickmatch_deinit(nickmatch);
+ nickmatch_deinit(nickmatch);
signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
- signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config);
- signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
+ signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config);
+ signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
command_unbind("hilight", (SIGNAL_FUNC) cmd_hilight);
command_unbind("dehilight", (SIGNAL_FUNC) cmd_dehilight);
From d8a6e666994ec4265459ed1e6665c01eb651eb82 Mon Sep 17 00:00:00 2001
From: B Thibault
Date: Fri, 29 Apr 2016 01:01:34 +0200
Subject: [PATCH 059/140] Ref #421 (Add an option to make /hilight case
sensitive) Allow use of /hilight -case exAMPle (compatible with other
options) Added matchcase to hilight config file (exemple: { text = exAMPle;
matchcase = yes; } )
---
docs/help/in/hilight.in | 1 +
src/fe-common/core/hilight-text.c | 21 ++++++++++++++++-----
src/fe-common/core/hilight-text.h | 1 +
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in
index fabbc2ea..677e64c3 100644
--- a/docs/help/in/hilight.in
+++ b/docs/help/in/hilight.in
@@ -10,6 +10,7 @@
-line: Highlights the whole line.
-mask: Highlights all messages from users matching the mask.
-full: The text must match the full word.
+ -case: The text must match case.
-regexp: The text is a regular expression.
-color: The color the display the highlight in.
-actcolor: The color to mark the highlight activity in the statusbar.
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 6aa19b88..13c7c64d 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -78,6 +78,7 @@ static void hilight_add_config(HILIGHT_REC *rec)
if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE);
if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE);
if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE);
+ if (rec->case_sensitive) iconfig_node_set_bool(node, "matchcase", TRUE);
if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag);
if (rec->channels != NULL && *rec->channels != NULL) {
@@ -210,9 +211,16 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text,
}
#endif
} else {
- match = rec->fullword ?
- stristr_full(text, rec->text) :
- stristr(text, rec->text);
+ if (rec->case_sensitive) {
+ match = rec->fullword ?
+ strstr_full(text, rec->text) :
+ strstr(text, rec->text);
+ }
+ else {
+ match = rec->fullword ?
+ stristr_full(text, rec->text) :
+ stristr(text, rec->text);
+ }
if (match != NULL) {
if (match_beg != NULL && match_end != NULL) {
*match_beg = (int) (match-text);
@@ -464,6 +472,7 @@ static void read_hilight_config(void)
rec->priority = config_node_get_int(node, "priority", 0);
rec->nick = config_node_get_bool(node, "nick", TRUE);
rec->word = config_node_get_bool(node, "word", TRUE);
+ rec->case_sensitive = config_node_get_bool(node, "matchcase", FALSE);
rec->nickmask = config_node_get_bool(node, "mask", FALSE);
rec->fullword = config_node_get_bool(node, "fullword", FALSE);
@@ -495,6 +504,7 @@ static void hilight_print(int index, HILIGHT_REC *rec)
if (rec->nickmask) g_string_append(options, "-mask ");
if (rec->fullword) g_string_append(options, "-full ");
+ if (rec->case_sensitive) g_string_append(options, "-case ");
if (rec->regexp) {
g_string_append(options, "-regexp ");
#ifdef HAVE_REGEX_H
@@ -543,7 +553,7 @@ static void cmd_hilight_show(void)
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER);
}
-/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp]
+/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -case | -regexp]
[-color ] [-actcolor ] [-level ]
[-network ] [-channels ] */
static void cmd_hilight(const char *data)
@@ -611,6 +621,7 @@ static void cmd_hilight(const char *data)
rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL;
rec->fullword = g_hash_table_lookup(optlist, "full") != NULL;
rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
+ rec->case_sensitive = g_hash_table_lookup(optlist, "case") != NULL;
if (colorarg != NULL) {
g_free_and_null(rec->color);
@@ -717,7 +728,7 @@ void hilight_text_init(void)
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
- command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp");
+ command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp case");
}
void hilight_text_deinit(void)
diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h
index 3c897def..ae05e1ca 100644
--- a/src/fe-common/core/hilight-text.h
+++ b/src/fe-common/core/hilight-text.h
@@ -23,6 +23,7 @@ struct _HILIGHT_REC {
unsigned int nickmask:1; /* `text' is a nick mask */
unsigned int fullword:1; /* match `text' only for full words */
unsigned int regexp:1; /* `text' is a regular expression */
+ unsigned int case_sensitive:1;/* `text' must match case */
#ifdef HAVE_REGEX_H
unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */
regex_t preg;
From ddd54164304e8d4bc3b709dbe6d2eca7832cff81 Mon Sep 17 00:00:00 2001
From: B Thibault
Date: Fri, 29 Apr 2016 11:00:34 +0200
Subject: [PATCH 060/140] changed command-line -case to -matchcase
---
docs/help/in/hilight.in | 2 +-
src/fe-common/core/hilight-text.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in
index 677e64c3..2f396430 100644
--- a/docs/help/in/hilight.in
+++ b/docs/help/in/hilight.in
@@ -10,7 +10,7 @@
-line: Highlights the whole line.
-mask: Highlights all messages from users matching the mask.
-full: The text must match the full word.
- -case: The text must match case.
+ -matchcase: The text must match case.
-regexp: The text is a regular expression.
-color: The color the display the highlight in.
-actcolor: The color to mark the highlight activity in the statusbar.
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 13c7c64d..78815a42 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -504,7 +504,7 @@ static void hilight_print(int index, HILIGHT_REC *rec)
if (rec->nickmask) g_string_append(options, "-mask ");
if (rec->fullword) g_string_append(options, "-full ");
- if (rec->case_sensitive) g_string_append(options, "-case ");
+ if (rec->case_sensitive) g_string_append(options, "-matchcase ");
if (rec->regexp) {
g_string_append(options, "-regexp ");
#ifdef HAVE_REGEX_H
@@ -553,7 +553,7 @@ static void cmd_hilight_show(void)
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER);
}
-/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -case | -regexp]
+/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -matchcase | -regexp]
[-color ] [-actcolor ] [-level ]
[-network ] [-channels ] */
static void cmd_hilight(const char *data)
@@ -621,7 +621,7 @@ static void cmd_hilight(const char *data)
rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL;
rec->fullword = g_hash_table_lookup(optlist, "full") != NULL;
rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL;
- rec->case_sensitive = g_hash_table_lookup(optlist, "case") != NULL;
+ rec->case_sensitive = g_hash_table_lookup(optlist, "matchcase") != NULL;
if (colorarg != NULL) {
g_free_and_null(rec->color);
@@ -728,7 +728,7 @@ void hilight_text_init(void)
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
- command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp case");
+ command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp matchcase");
}
void hilight_text_deinit(void)
From e7a18759ecb02a0b1fcbb118b9e732e604268afd Mon Sep 17 00:00:00 2001
From: isundil
Date: Fri, 29 Apr 2016 22:17:48 +0000
Subject: [PATCH 061/140] Added case-sensitive regexp matching for hilights
---
src/fe-common/core/hilight-text.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 78815a42..d1c4718c 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -122,8 +122,11 @@ static void hilight_init_rec(HILIGHT_REC *rec)
{
#ifdef HAVE_REGEX_H
if (rec->regexp_compiled) regfree(&rec->preg);
- rec->regexp_compiled = !rec->regexp ? FALSE :
- regcomp(&rec->preg, rec->text, REG_EXTENDED|REG_ICASE) == 0;
+ if (!rec->regexp)
+ rec->regexp_compiled = FALSE;
+ else
+ rec->regexp_compiled = regcomp(&rec->preg, rec->text,
+ rec->case_sensitive ? REG_EXTENDED : (REG_EXTENDED|REG_ICASE)) == 0;
#endif
}
From b24921db7a49d01ce30245999483589bcea47d53 Mon Sep 17 00:00:00 2001
From: dennisschagt
Date: Sat, 30 Apr 2016 09:44:26 +0200
Subject: [PATCH 062/140] Correct error/typo "You"->"Your" in help message
---
docs/help/in/away.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/help/in/away.in b/docs/help/in/away.in
index e0cf3685..75bc46c4 100644
--- a/docs/help/in/away.in
+++ b/docs/help/in/away.in
@@ -8,8 +8,8 @@
-one: Marks yourself as away on the active server.
-all: Marks yourself as away on all the servers you are connected to.
- You away message; if no argument is given, your away status will be removed.
-
+ Your away message; if no argument is given, your away status will be removed.
+
%9Description:%9
Marks yourself as 'away'; this method is used to inform people that you
From b63339af89abc9830ecf8c56916db9eb1a42e005 Mon Sep 17 00:00:00 2001
From: isundil
Date: Sat, 30 Apr 2016 18:26:26 +0000
Subject: [PATCH 063/140] Increased ABI version
---
src/common.h | 2 +-
src/fe-common/core/hilight-text.c | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/common.h b/src/common.h
index 33dbd481..4fd6d331 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 3
+#define IRSSI_ABI_VERSION 4
#define DEFAULT_SERVER_ADD_PORT 6667
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index d1c4718c..36e1e78c 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -218,8 +218,7 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text,
match = rec->fullword ?
strstr_full(text, rec->text) :
strstr(text, rec->text);
- }
- else {
+ } else {
match = rec->fullword ?
stristr_full(text, rec->text) :
stristr(text, rec->text);
From 47e792da05f79c624a190fd5780e07f171fd7bd1 Mon Sep 17 00:00:00 2001
From: pisculichi
Date: Mon, 2 May 2016 16:01:48 +0000
Subject: [PATCH 064/140] Fix some ANSI C issues.
---
src/fe-common/core/fe-messages.c | 5 +++--
src/fe-common/core/themes.c | 2 +-
src/fe-text/gui-entry.c | 9 ++++++---
src/fe-text/gui-readline.c | 3 ++-
src/fe-text/statusbar.c | 2 +-
src/irc/proxy/proxy.c | 3 ++-
6 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index 3240fd10..bc2a30d6 100644
--- a/src/fe-common/core/fe-messages.c
+++ b/src/fe-common/core/fe-messages.c
@@ -175,6 +175,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
int for_me, print_channel, level;
char *nickmode, *color, *freemsg = NULL;
HILIGHT_REC *hilight;
+ TEXT_DEST_REC dest;
/* NOTE: this may return NULL if some channel is just closed with
/WINDOW CLOSE and server still sends the few last messages */
@@ -214,7 +215,6 @@ 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;
@@ -396,8 +396,9 @@ static void sig_message_quit(SERVER_REC *server, const char *nick,
count = 0; windows = NULL;
chans = g_string_new(NULL);
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
+ CHANNEL_REC *rec;
level = MSGLEVEL_QUITS;
- CHANNEL_REC *rec = tmp->data;
+ rec = tmp->data;
if (!nicklist_find(rec, nick))
continue;
diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c
index 58e7b557..2b1459be 100644
--- a/src/fe-common/core/themes.c
+++ b/src/fe-common/core/themes.c
@@ -365,9 +365,9 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
GString *str;
char *ret;
theme_rm_col dummy, reset;
+ int braces = 1; /* we start with one brace opened */
dummy.m[0] = '\0';
strcpy(reset.m, "n");
- int braces = 1; /* we start with one brace opened */
str = g_string_new(NULL);
while (**format != '\0' && braces != 0) {
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 63dda34e..31fe0e1e 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -554,6 +554,7 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr)
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
{
+ GUI_ENTRY_CUTBUFFER_REC *tmp;
char *buf;
int i;
@@ -562,7 +563,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
if (entry->kill_ring == NULL || entry->kill_ring->data == NULL)
return NULL;
- GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data;
+ tmp = entry->kill_ring->data;
if (tmp->cutbuffer == NULL)
return NULL;
@@ -582,12 +583,14 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry)
{
+ GUI_ENTRY_CUTBUFFER_REC *tmp;
+
g_return_val_if_fail(entry != NULL, NULL);
if (entry->kill_ring == NULL)
return NULL;
- GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data;
+ tmp = entry->kill_ring->data;
entry->kill_ring = g_slist_remove(entry->kill_ring, tmp);
entry->kill_ring = g_slist_append(entry->kill_ring, tmp);
@@ -608,7 +611,7 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP updat
static GUI_ENTRY_CUTBUFFER_REC *get_cutbuffer_rec(GUI_ENTRY_REC *entry, CUTBUFFER_UPDATE_OP update_cutbuffer)
{
- GUI_ENTRY_CUTBUFFER_REC *tmp = NULL;
+ GUI_ENTRY_CUTBUFFER_REC *tmp;
g_return_val_if_fail(entry != NULL, NULL);
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index e0ffb4f1..7c71edd7 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -696,10 +696,11 @@ static void key_append_next_kill(void)
static gboolean paste_timeout(gpointer data)
{
+ int split_lines;
paste_was_bracketed_mode = paste_bracketed_mode;
/* number of lines after splitting extra-long messages */
- int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT;
+ split_lines = paste_buffer->len / LINE_SPLIT_LIMIT;
/* Take into account the fact that a line may be split every LINE_SPLIT_LIMIT characters */
if (paste_line_count == 0 && split_lines <= paste_verify_line_count) {
diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c
index 5448243a..f0dff828 100644
--- a/src/fe-text/statusbar.c
+++ b/src/fe-text/statusbar.c
@@ -671,8 +671,8 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
WI_ITEM_REC *wiitem;
char *tmpstr, *tmpstr2;
theme_rm_col reset;
- strcpy(reset.m, "n");
int len;
+ strcpy(reset.m, "n");
if (str == NULL)
str = statusbar_item_get_value(item);
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index 1a714045..2875d2c2 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -28,13 +28,14 @@
/* SYNTAX: IRSSIPROXY STATUS */
static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server)
{
+ GSList *tmp;
+
if (!settings_get_bool("irssiproxy")) {
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
"Proxy is currently disabled");
return;
}
- GSList *tmp;
printtext(server, NULL, MSGLEVEL_CLIENTNOTICE,
"Proxy: Currently connected clients: %d",
From 3376d324e1e174e2885efbb7f1f056bc2a0d2857 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Mon, 9 May 2016 16:55:35 +0200
Subject: [PATCH 065/140] improve perl @INC detection
---
acconfig.h | 30 ---------------------
configure.ac | 74 ++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 58 insertions(+), 46 deletions(-)
delete mode 100644 acconfig.h
diff --git a/acconfig.h b/acconfig.h
deleted file mode 100644
index 53e268d7..00000000
--- a/acconfig.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* misc.. */
-#undef HAVE_SOCKS_H
-#undef HAVE_STATIC_PERL
-#undef HAVE_GMODULE
-
-/* macros/curses checks */
-#undef HAS_CURSES
-#undef USE_SUNOS_CURSES
-#undef USE_BSD_CURSES
-#undef USE_SYSV_CURSES
-#undef USE_NCURSES
-#undef NO_COLOR_CURSES
-#undef SCO_FLAVOR
-
-/* our own curses checks */
-#undef HAVE_NCURSES_USE_DEFAULT_COLORS
-#undef HAVE_CURSES_IDCOK
-#undef HAVE_CURSES_RESIZETERM
-#undef HAVE_CURSES_WRESIZE
-
-/* terminfo/termcap */
-#undef HAVE_TERMINFO
-
-/* What type should be used for uoff_t */
-#undef UOFF_T_INT
-#undef UOFF_T_LONG
-#undef UOFF_T_LONG_LONG
-
-/* printf()-format for uoff_t, eg. "u" or "lu" or "llu" */
-#undef PRIuUOFF_T
diff --git a/configure.ac b/configure.ac
index 2c47bd2b..0e5f2f0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,7 +79,6 @@ AC_ARG_WITH(modules,
if test "x$prefix" != "xNONE"; then
prefix=`eval echo $prefix`
PERL_MM_PARAMS="INSTALLDIRS=perl INSTALL_BASE=$prefix"
- perl_library_dir="PERL_USE_LIB"
perl_set_use_lib=yes
perl_prefix_note=yes
@@ -97,30 +96,35 @@ AC_ARG_WITH(perl-staticlib,
AC_ARG_WITH(perl-lib,
-[ --with-perl-lib=[site|vendor|DIR] Specify where to install the
+[ --with-perl-lib=[perl|site|vendor|DIR] Specify where to install the
Perl libraries for irssi, default is site],
if test "x$withval" = xyes; then
want_perl=yes
elif test "x$withval" = xno; then
want_perl=no
+ elif test "x$withval" = xperl; then
+ want_perl=yes
+ perl_prefix_note=no
+ PERL_MM_PARAMS="INSTALLDIRS=perl"
+ perl_set_use_lib=no
elif test "x$withval" = xsite; then
want_perl=yes
perl_prefix_note=no
PERL_MM_PARAMS=""
+ perl_set_use_lib=no
elif test "x$withval" = xvendor; then
want_perl=yes
perl_prefix_note=no
if test -z "`$perlpath -v|grep '5\.0'`"; then
PERL_MM_PARAMS="INSTALLDIRS=vendor"
else
- PERL_MM_PARAMS="INSTALLDIRS=perl PREFIX=`perl -e 'use Config; print $Config{prefix}'`"
+ PERL_MM_PARAMS="INSTALLDIRS=perl PREFIX=`$perlpath -e 'use Config; print $Config{prefix}'`"
fi
- perl_library_dir="(vendor default - `$perlpath -e 'use Config; print $Config{archlib}'`)"
+ perl_set_use_lib=no
else
want_perl=yes
perl_prefix_note=no
PERL_MM_PARAMS="INSTALLDIRS=perl LIB=$withval"
- perl_library_dir="PERL_USE_LIB"
perl_set_use_lib=yes
fi,
want_perl=yes)
@@ -371,7 +375,7 @@ if test "$want_perl" != "no"; then
dnl * complain about them. Normally there's only few options
dnl * that we want to keep:
dnl * -Ddefine -Uundef -I/path -fopt -mopt
- PERL_CFLAGS=`echo $PERL_CFLAGS | $perlpath -pe 's/^(.* )?-[^DUIfm][^ ]+/\1/g; s/^(.* )?\+[^ ]+/\1/g'`
+ PERL_CFLAGS=`echo $PERL_CFLAGS | $perlpath -pe 's/^(.* )?-@<:@^DUIfm@:>@@<:@^ @:>@+/\1/g; s/^(.* )?\+@<:@^ @:>@+/\1/g'`
PERL_EXTRA_OPTS="CCCDLFLAGS=\"-fPIC\""
AC_SUBST(PERL_EXTRA_OPTS)
@@ -455,13 +459,37 @@ if test "$want_perl" != "no"; then
PERL_STATIC_LIBS=0
fi
+ # remove any prefix from PERL_MM_OPT
+ PERL_MM_OPT=`perl -MText::ParseWords -e 'sub qu{$_=shift;s{^(.*?)=(.*)$}{($a,$b)=($1,$2);$b=~s/"/\\\\"/g;qq{$a="$b"}}ge if /@<:@\s"@:>@/;$_} local $,=" "; print map qu($_), grep !/^(INSTALL_BASE|PREFIX)=/, shellwords(@ARGV)' "$PERL_MM_OPT"`
# figure out the correct @INC path - we'll need to do this
# through MakeMaker since it's difficult to get it right
# otherwise.
+ $perlpath -MExtUtils::MakeMaker -e 'WriteMakefile(NAME => "test", MAKEFILE => "Makefile.test", FIRST_MAKEFILE => "/dev/null", NO_META => 1, NO_MYMETA => 1);' $PERL_MM_PARAMS >/dev/null
+ echo 'show-INSTALLDIRS:' >> Makefile.test
+ echo ' @echo $(INSTALLDIRS)' >> Makefile.test
+ perl_INSTALLDIRS=`$am_make -f Makefile.test show-INSTALLDIRS`
+ if test "x$perl_INSTALLDIRS" = "xsite"; then
+ perl_library_dir="site default"
+ perl_INSTALL_VAR=INSTALLSITEARCH
+ elif test "x$perl_INSTALLDIRS" = "xvendor"; then
+ perl_library_dir="vendor default"
+ perl_INSTALL_VAR=INSTALLVENDORARCH
+ else
+ perl_library_dir="module default"
+ perl_INSTALL_VAR=INSTALLARCHLIB
+ fi
+ echo 'show-ARCHLIB:' >> Makefile.test
+ echo ' @echo $('"$perl_INSTALL_VAR"')' >> Makefile.test
+ perl_use_lib=`$am_make -f Makefile.test show-ARCHLIB`
+ rm -f Makefile.test
if test "x$perl_set_use_lib" = "xyes"; then
- perl -e 'use ExtUtils::MakeMaker; WriteMakefile("NAME" => "test", "MAKEFILE" => "Makefile.test");' $PERL_MM_PARAMS >/dev/null
- PERL_USE_LIB=`perl -e 'open(F, "Makefile.test"); while () { chomp; if (/^(\w+) = (.*$)/) { $keys{$1} = $2; } }; $key = $keys{INSTALLARCHLIB}; while ($key =~ /\\$\((\w+)\)/) { $value = $keys{$1}; $key =~ s/\\$\($1\)/$value/; }; print $key;'`
- rm -f Makefile.test
+ if $perlpath -e 'exit ! grep $_ eq $ARGV@<:@0@:>@, grep /^\//, @INC' "$perl_use_lib"; then
+ perl_library_dir="other path in @INC"
+ perl_set_use_lib=no
+ else
+ perl_library_dir="prepends to @INC with /set perl_use_lib"
+ PERL_USE_LIB="$perl_use_lib"
+ fi
fi
AC_SUBST(perl_module_lib)
@@ -477,6 +505,7 @@ if test "$want_perl" != "no"; then
AC_SUBST(PERL_CFLAGS)
AC_SUBST(PERL_USE_LIB)
+ AC_SUBST(PERL_MM_OPT)
AC_SUBST(PERL_MM_PARAMS)
AC_SUBST(PERL_STATIC_LIBS)
fi
@@ -591,6 +620,25 @@ else
want_truecolor=no
fi
+AH_TEMPLATE(HAS_CURSES, [macros/curses checks])
+AH_TEMPLATE(HAVE_CURSES_IDCOK)
+AH_TEMPLATE(HAVE_CURSES_RESIZETERM)
+AH_TEMPLATE(HAVE_CURSES_WRESIZE)
+AH_TEMPLATE(HAVE_GMODULE)
+AH_TEMPLATE(HAVE_NCURSES_USE_DEFAULT_COLORS, [our own curses checks])
+AH_TEMPLATE(HAVE_SOCKS_H, [misc..])
+AH_TEMPLATE(HAVE_STATIC_PERL)
+AH_TEMPLATE(HAVE_TERMINFO, [terminfo/termcap])
+AH_TEMPLATE(NO_COLOR_CURSES)
+AH_TEMPLATE(PRIuUOFF_T, [printf()-format for uoff_t, eg. "u" or "lu" or "llu"])
+AH_TEMPLATE(SCO_FLAVOR)
+AH_TEMPLATE(UOFF_T_INT, [What type should be used for uoff_t])
+AH_TEMPLATE(UOFF_T_LONG)
+AH_TEMPLATE(UOFF_T_LONG_LONG)
+AH_TEMPLATE(USE_NCURSES)
+AH_TEMPLATE(USE_SUNOS_CURSES)
+AH_TEMPLATE(USE_SYSV_CURSES)
+
AC_CONFIG_FILES([
Makefile
src/Makefile
@@ -692,13 +740,7 @@ if test "x$want_perl" != "xno" -a "x$perl_mod_error" != "x"; then
fi
if test "x$want_perl" != "xno"; then
- if test "$perl_library_dir" = "PERL_USE_LIB"; then
- perl_library_dir=$PERL_USE_LIB
- fi
- if test -z "$perl_library_dir"; then
- perl_library_dir="(site default - `$perlpath -e 'use Config; print $Config{sitearch}'`)"
- fi
- echo "Perl library directory ........... : $perl_library_dir"
+ echo "Perl library directory ........... : ($perl_library_dir - $perl_use_lib)"
if test "x$perl_prefix_note" = "xyes"; then
echo " - NOTE: This was automatically set to the same directory you gave with"
echo " --prefix. If you want the perl libraries to install to their 'correct'"
From affbf71f102cc740aeda180fd3297c1cc6c8f7de Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 11 May 2016 11:43:08 +0200
Subject: [PATCH 066/140] add silent flag to make, should stop GNU make from
turning on -w
---
configure.ac | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0e5f2f0d..04e2b0b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -467,7 +467,7 @@ if test "$want_perl" != "no"; then
$perlpath -MExtUtils::MakeMaker -e 'WriteMakefile(NAME => "test", MAKEFILE => "Makefile.test", FIRST_MAKEFILE => "/dev/null", NO_META => 1, NO_MYMETA => 1);' $PERL_MM_PARAMS >/dev/null
echo 'show-INSTALLDIRS:' >> Makefile.test
echo ' @echo $(INSTALLDIRS)' >> Makefile.test
- perl_INSTALLDIRS=`$am_make -f Makefile.test show-INSTALLDIRS`
+ perl_INSTALLDIRS=`$am_make -s -f Makefile.test show-INSTALLDIRS`
if test "x$perl_INSTALLDIRS" = "xsite"; then
perl_library_dir="site default"
perl_INSTALL_VAR=INSTALLSITEARCH
@@ -480,7 +480,7 @@ if test "$want_perl" != "no"; then
fi
echo 'show-ARCHLIB:' >> Makefile.test
echo ' @echo $('"$perl_INSTALL_VAR"')' >> Makefile.test
- perl_use_lib=`$am_make -f Makefile.test show-ARCHLIB`
+ perl_use_lib=`$am_make -s -f Makefile.test show-ARCHLIB`
rm -f Makefile.test
if test "x$perl_set_use_lib" = "xyes"; then
if $perlpath -e 'exit ! grep $_ eq $ARGV@<:@0@:>@, grep /^\//, @INC' "$perl_use_lib"; then
From 5538578820550c1a62dc4d0e6451332229eeee75 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 01:26:33 +0200
Subject: [PATCH 067/140] Move utf8.{h,c} from fe-common/core to core.
---
src/core/Makefile.am | 1 +
src/{fe-common => }/core/utf8.c | 2 ++
src/{fe-common => }/core/utf8.h | 3 +++
src/{fe-common => }/core/wcwidth.c | 0
src/fe-common/core/Makefile.am | 5 -----
src/fe-common/core/module.h | 2 +-
src/fe-text/term.h | 2 +-
7 files changed, 8 insertions(+), 7 deletions(-)
rename src/{fe-common => }/core/utf8.c (96%)
rename src/{fe-common => }/core/utf8.h (93%)
rename src/{fe-common => }/core/wcwidth.c (100%)
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index fc32e17e..cc200034 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -44,6 +44,7 @@ libcore_a_SOURCES = \
settings.c \
signals.c \
special-vars.c \
+ utf8.c \
write-buffer.c
structure_headers = \
diff --git a/src/fe-common/core/utf8.c b/src/core/utf8.c
similarity index 96%
rename from src/fe-common/core/utf8.c
rename to src/core/utf8.c
index 2d07ea8e..1ab6def9 100644
--- a/src/fe-common/core/utf8.c
+++ b/src/core/utf8.c
@@ -22,5 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "utf8.h"
#include "module.h"
+#include "wcwidth.c"
diff --git a/src/fe-common/core/utf8.h b/src/core/utf8.h
similarity index 93%
rename from src/fe-common/core/utf8.h
rename to src/core/utf8.h
index 3c15dc7d..63261a24 100644
--- a/src/fe-common/core/utf8.h
+++ b/src/core/utf8.h
@@ -8,6 +8,9 @@
#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
#define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
+#include
+typedef guint32 unichar;
+
/* Returns width for character (0-2). */
int mk_wcwidth(unichar c);
diff --git a/src/fe-common/core/wcwidth.c b/src/core/wcwidth.c
similarity index 100%
rename from src/fe-common/core/wcwidth.c
rename to src/core/wcwidth.c
diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am
index e755b510..63f91fa6 100644
--- a/src/fe-common/core/Makefile.am
+++ b/src/fe-common/core/Makefile.am
@@ -24,8 +24,6 @@ libfe_common_core_a_SOURCES = \
fe-queries.c \
fe-server.c \
fe-settings.c \
- utf8.c \
- wcwidth.c \
formats.c \
hilight-text.c \
keyboard.c \
@@ -62,6 +60,3 @@ pkginc_fe_common_core_HEADERS = \
window-items.h \
windows-layout.h \
fe-windows.h
-
-noinst_HEADERS = \
- utf8.h
diff --git a/src/fe-common/core/module.h b/src/fe-common/core/module.h
index 51b61b3e..db712ec7 100644
--- a/src/fe-common/core/module.h
+++ b/src/fe-common/core/module.h
@@ -2,7 +2,7 @@
#define MODULE_NAME "fe-common/core"
-typedef guint32 unichar;
+#include "utf8.h"
typedef struct {
time_t time;
char *nick;
diff --git a/src/fe-text/term.h b/src/fe-text/term.h
index 9b726d82..0c7847f6 100644
--- a/src/fe-text/term.h
+++ b/src/fe-text/term.h
@@ -27,7 +27,7 @@ typedef struct _TERM_WINDOW TERM_WINDOW;
#define TERM_TYPE_UTF8 1
#define TERM_TYPE_BIG5 2
-typedef guint32 unichar;
+#include "utf8.h"
extern TERM_WINDOW *root_window;
extern int term_width, term_height;
From 5c74a3bb88db0fa32c459f8494e9f5a62a821baa Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 01:39:14 +0200
Subject: [PATCH 068/140] Move advance() from fe-common/core to core.
---
src/core/utf8.c | 15 +++++++++++++++
src/core/utf8.h | 5 +++++
src/fe-common/core/formats.c | 16 ----------------
3 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index 1ab6def9..6daa878a 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -26,3 +26,18 @@
#include "module.h"
#include "wcwidth.c"
+int advance(char const **str, gboolean utf8)
+{
+ if (utf8) {
+ gunichar c;
+
+ c = g_utf8_get_char(*str);
+ *str = g_utf8_next_char(*str);
+
+ return unichar_isprint(c) ? mk_wcwidth(c) : 1;
+ } else {
+ *str += 1;
+
+ return 1;
+ }
+}
diff --git a/src/core/utf8.h b/src/core/utf8.h
index 63261a24..09397f69 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -14,6 +14,11 @@ typedef guint32 unichar;
/* Returns width for character (0-2). */
int mk_wcwidth(unichar c);
+/* Advance the str pointer one character further; return the number of columns
+ * occupied by the skipped character.
+ */
+int advance(char const **str, gboolean utf8);
+
#define unichar_isprint(c) (((c) & ~0x80) >= 32)
#define is_utf8_leading(c) (((c) & 0xc0) != 0x80)
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index ccf48394..7daecfcf 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -420,22 +420,6 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server,
window_find_closest(server, target, level);
}
-static int advance (char const **str, gboolean utf8)
-{
- if (utf8) {
- gunichar c;
-
- c = g_utf8_get_char(*str);
- *str = g_utf8_next_char(*str);
-
- return unichar_isprint(c) ? mk_wcwidth(c) : 1;
- } else {
- *str += 1;
-
- return 1;
- }
-}
-
/* Return length of text part in string (ie. without % codes) */
int format_get_length(const char *str)
{
From b0afcc96dbc13cf3a5ed94686bb227ab0d86ceaa Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 01:52:37 +0200
Subject: [PATCH 069/140] Rename advance() into string_advance().
---
src/core/utf8.c | 2 +-
src/core/utf8.h | 2 +-
src/fe-common/core/formats.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index 6daa878a..1daaf03f 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -26,7 +26,7 @@
#include "module.h"
#include "wcwidth.c"
-int advance(char const **str, gboolean utf8)
+int string_advance(char const **str, gboolean utf8)
{
if (utf8) {
gunichar c;
diff --git a/src/core/utf8.h b/src/core/utf8.h
index 09397f69..50ee0886 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -17,7 +17,7 @@ int mk_wcwidth(unichar c);
/* Advance the str pointer one character further; return the number of columns
* occupied by the skipped character.
*/
-int advance(char const **str, gboolean utf8);
+int string_advance(char const **str, gboolean utf8);
#define unichar_isprint(c) (((c) & ~0x80) >= 32)
#define is_utf8_leading(c) (((c) & 0xc0) != 0x80)
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index 7daecfcf..def03e10 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -449,7 +449,7 @@ int format_get_length(const char *str)
len++;
}
- len += advance(&str, utf8);
+ len += string_advance(&str, utf8);
}
g_string_free(tmp, TRUE);
@@ -491,7 +491,7 @@ int format_real_length(const char *str, int len)
}
oldstr = str;
- len -= advance(&str, utf8);
+ len -= string_advance(&str, utf8);
if (len < 0)
str = oldstr;
}
From 2c8648a9c889fc0a7c4b24367a3f81f08dedccb2 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 02:10:02 +0200
Subject: [PATCH 070/140] Introduce string_policy().
---
src/core/utf8.c | 13 +++++++++++++
src/core/utf8.h | 14 ++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index 1daaf03f..d931ba19 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -25,6 +25,8 @@
#include "utf8.h"
#include "module.h"
#include "wcwidth.c"
+/* Provide is_utf8(): */
+#include "recode.h"
int string_advance(char const **str, gboolean utf8)
{
@@ -41,3 +43,14 @@ int string_advance(char const **str, gboolean utf8)
return 1;
}
}
+
+int string_policy(const char *str)
+{
+ if (is_utf8()) {
+ if (!str || g_utf8_validate(str, -1, NULL)) {
+ /* No string provided or valid UTF-8 string: treat as UTF-8: */
+ return TREAT_STRING_AS_UTF8;
+ }
+ }
+ return TREAT_STRING_AS_BYTES;
+}
diff --git a/src/core/utf8.h b/src/core/utf8.h
index 50ee0886..fa11b737 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -19,6 +19,20 @@ int mk_wcwidth(unichar c);
*/
int string_advance(char const **str, gboolean utf8);
+/* TREAT_STRING_AS_BYTES means strings are to be treated using strncpy,
+ * strnlen, etc.
+ * TREAT_STRING_AS_UTF8 means strings are to be treated using g_utf8_*
+ * functions.
+ */
+#define TREAT_STRING_AS_BYTES 0
+#define TREAT_STRING_AS_UTF8 1
+
+/* Return how the str string ought to be treated: TREAT_STRING_AS_UTF8 if the
+ * terminal handles UTF-8 and if the string appears to be a valid UTF-8 string;
+ * TREAT_STRING_AS_BYTES otherwise.
+ */
+int string_policy(const char *str);
+
#define unichar_isprint(c) (((c) & ~0x80) >= 32)
#define is_utf8_leading(c) (((c) & 0xc0) != 0x80)
From 21c07c006066115af4604e26cd89cf60f94a7d53 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 02:27:19 +0200
Subject: [PATCH 071/140] Leverage string_policy().
---
src/core/utf8.c | 5 +++--
src/core/utf8.h | 2 +-
src/fe-common/core/formats.c | 8 ++++----
src/fe-text/gui-entry.c | 2 +-
4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index d931ba19..c9303d19 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -28,9 +28,9 @@
/* Provide is_utf8(): */
#include "recode.h"
-int string_advance(char const **str, gboolean utf8)
+int string_advance(char const **str, int policy)
{
- if (utf8) {
+ if (policy == TREAT_STRING_AS_UTF8) {
gunichar c;
c = g_utf8_get_char(*str);
@@ -38,6 +38,7 @@ int string_advance(char const **str, gboolean utf8)
return unichar_isprint(c) ? mk_wcwidth(c) : 1;
} else {
+ /* Assume TREAT_STRING_AS_BYTES: */
*str += 1;
return 1;
diff --git a/src/core/utf8.h b/src/core/utf8.h
index fa11b737..f1a8f0e1 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -17,7 +17,7 @@ int mk_wcwidth(unichar c);
/* Advance the str pointer one character further; return the number of columns
* occupied by the skipped character.
*/
-int string_advance(char const **str, gboolean utf8);
+int string_advance(char const **str, int policy);
/* TREAT_STRING_AS_BYTES means strings are to be treated using strncpy,
* strnlen, etc.
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index def03e10..3e88426f 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -425,12 +425,12 @@ int format_get_length(const char *str)
{
GString *tmp;
int len;
- gboolean utf8;
+ int utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0);
- utf8 = is_utf8() && g_utf8_validate(str, -1, NULL);
+ utf8 = string_policy(str);
tmp = g_string_new(NULL);
len = 0;
@@ -464,12 +464,12 @@ int format_real_length(const char *str, int len)
GString *tmp;
const char *start;
const char *oldstr;
- gboolean utf8;
+ int utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0);
g_return_val_if_fail(len >= 0, 0);
- utf8 = is_utf8() && g_utf8_validate(str, -1, NULL);
+ utf8 = string_policy(str);
start = str;
tmp = g_string_new(NULL);
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 63dda34e..beea2273 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -367,7 +367,7 @@ static int scrlen_str(const char *str)
g_return_val_if_fail(str != NULL, 0);
str = stripped = strip_codes(str);
- if (is_utf8() && g_utf8_validate(str, -1, NULL)) {
+ if (string_policy(str) == TREAT_STRING_AS_UTF8) {
while (*str != '\0') {
gunichar c;
From 35b3ccc6a407f83eba4f0c3787cc5c174bd3385c Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 02:47:26 +0200
Subject: [PATCH 072/140] Introduce string_length() and string_width().
---
src/core/utf8.c | 34 ++++++++++++++++++++++++++++++++++
src/core/utf8.h | 9 +++++++++
2 files changed, 43 insertions(+)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index c9303d19..7c75c374 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -55,3 +55,37 @@ int string_policy(const char *str)
}
return TREAT_STRING_AS_BYTES;
}
+
+int string_length(const char *str, int policy)
+{
+ g_return_val_if_fail(str != NULL, 0);
+
+ if (policy == -1) {
+ policy = string_policy(str);
+ }
+
+ if (policy == TREAT_STRING_AS_UTF8) {
+ return g_utf8_strlen(str, -1);
+ }
+ else {
+ /* Assume TREAT_STRING_AS_BYTES: */
+ return strlen(str);
+ }
+}
+
+int string_width(const char *str, int policy)
+{
+ int len;
+
+ g_return_val_if_fail(str != NULL, 0);
+
+ if (policy == -1) {
+ policy = string_policy(str);
+ }
+
+ len = 0;
+ while (*str != '\0') {
+ len += string_advance(&str, policy);
+ }
+ return len;
+}
diff --git a/src/core/utf8.h b/src/core/utf8.h
index f1a8f0e1..6f02c5a0 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -33,6 +33,15 @@ int string_advance(char const **str, int policy);
*/
int string_policy(const char *str);
+/* Return the length of the str string according to the given policy; if policy
+ * is -1, this function will call string_policy().
+ */
+int string_length(const char *str, int policy);
+/* Return the screen width of the str string according to the given policy; if
+ * policy is -1, this function will call string_policy().
+ */
+int string_width(const char *str, int policy);
+
#define unichar_isprint(c) (((c) & ~0x80) >= 32)
#define is_utf8_leading(c) (((c) & 0xc0) != 0x80)
From 719efc44a3c3c3db8f12b6ff40d2021837d9a902 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 03:04:08 +0200
Subject: [PATCH 073/140] Introduce string_chars_for_width().
---
src/core/utf8.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
src/core/utf8.h | 6 ++++++
2 files changed, 50 insertions(+)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index 7c75c374..d1f58599 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -89,3 +89,47 @@ int string_width(const char *str, int policy)
}
return len;
}
+
+int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned int *bytes)
+{
+ const char *c, *previous_c;
+ int str_width, char_width, char_count;
+
+ g_return_val_if_fail(str != NULL, -1);
+
+ /* Handle the dummy case where n is 0: */
+ if (!n) {
+ if (bytes) {
+ *bytes = 0;
+ }
+ return 0;
+ }
+
+ if (policy == -1) {
+ policy = string_policy(str);
+ }
+
+ /* Iterate over characters until we reach n: */
+ char_count = 0;
+ str_width = 0;
+ c = str;
+ while (*c != '\0') {
+ previous_c = c;
+ char_width = string_advance(&c, policy);
+ if (str_width + char_width > n) {
+ /* We stepped beyond n, get one step back and stop there: */
+ c = previous_c;
+ break;
+ }
+ ++ char_count;
+ str_width += char_width;
+ }
+ /* At this point, we know that char_count characters reach str_width
+ * columns, which is less than or equal to n. */
+
+ /* Optionally provide the equivalent amount of bytes: */
+ if (bytes) {
+ *bytes = c - str;
+ }
+ return char_count;
+}
diff --git a/src/core/utf8.h b/src/core/utf8.h
index 6f02c5a0..411b2048 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -42,6 +42,12 @@ int string_length(const char *str, int policy);
*/
int string_width(const char *str, int policy);
+/* Return the amount of characters from str it takes to reach n columns, or -1 if
+ * str is NULL. Optionally return the equivalent amount of bytes.
+ * If policy is -1, this function will call string_policy().
+ */
+int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned int *bytes);
+
#define unichar_isprint(c) (((c) & ~0x80) >= 32)
#define is_utf8_leading(c) (((c) & 0xc0) != 0x80)
From 09ca3ad48f57b7febd6ad353fb38dbe9234e7e70 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 03:31:23 +0200
Subject: [PATCH 074/140] Fix indentation of display_sorted_nicks().
This was done assuming an "indent with tab, align with spaces" approach.
get_alignment also benefited from a minor indentation fix.
---
src/core/special-vars.c | 2 +-
src/fe-common/core/fe-channels.c | 64 ++++++++++++++++----------------
2 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/src/core/special-vars.c b/src/core/special-vars.c
index 4dcc3d2f..d6794d96 100644
--- a/src/core/special-vars.c
+++ b/src/core/special-vars.c
@@ -340,7 +340,7 @@ static char *get_alignment(const char *text, int align, int flags, char pad)
}
ret = str->str;
- g_string_free(str, FALSE);
+ g_string_free(str, FALSE);
return ret;
}
diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c
index 046d641a..fd44be11 100644
--- a/src/fe-common/core/fe-channels.c
+++ b/src/fe-common/core/fe-channels.c
@@ -328,35 +328,35 @@ static int get_nick_length(void *data)
static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
{
- WINDOW_REC *window;
+ WINDOW_REC *window;
TEXT_DEST_REC dest;
GString *str;
GSList *tmp;
- char *format, *stripped, *prefix_format;
+ char *format, *stripped, *prefix_format;
char *linebuf, nickmode[2] = { 0, 0 };
int *columns, cols, rows, last_col_rows, col, row, max_width;
- int item_extra, linebuf_size, formatnum;
+ int item_extra, linebuf_size, formatnum;
window = window_find_closest(channel->server, channel->visible_name,
- MSGLEVEL_CLIENTCRAP);
- max_width = window->width;
+ MSGLEVEL_CLIENTCRAP);
+ max_width = window->width;
- /* get the length of item extra stuff ("[ ] ") */
+ /* get the length of item extra stuff ("[ ] ") */
format = format_get_text(MODULE_NAME, NULL,
- channel->server, channel->visible_name,
- TXT_NAMES_NICK, " ", "");
+ channel->server, channel->visible_name,
+ TXT_NAMES_NICK, " ", "");
stripped = strip_codes(format);
item_extra = strlen(stripped);
- g_free(stripped);
+ g_free(stripped);
g_free(format);
if (settings_get_int("names_max_width") > 0 &&
settings_get_int("names_max_width") < max_width)
max_width = settings_get_int("names_max_width");
- /* remove width of the timestamp from max_width */
+ /* remove width of the timestamp from max_width */
format_create_dest(&dest, channel->server, channel->visible_name,
- MSGLEVEL_CLIENTCRAP, NULL);
+ MSGLEVEL_CLIENTCRAP, NULL);
format = format_get_line_start(current_theme, &dest, time(NULL));
if (format != NULL) {
stripped = strip_codes(format);
@@ -365,11 +365,11 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
g_free(format);
}
- /* remove width of the prefix from max_width */
+ /* remove width of the prefix from max_width */
prefix_format = format_get_text(MODULE_NAME, NULL,
- channel->server, channel->visible_name,
- TXT_NAMES_PREFIX,
- channel->visible_name);
+ channel->server, channel->visible_name,
+ TXT_NAMES_PREFIX,
+ channel->visible_name);
if (prefix_format != NULL) {
stripped = strip_codes(prefix_format);
max_width -= strlen(stripped);
@@ -384,19 +384,19 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
/* calculate columns */
cols = get_max_column_count(nicklist, get_nick_length, max_width,
- settings_get_int("names_max_columns"),
- item_extra, 3, &columns, &rows);
+ settings_get_int("names_max_columns"),
+ item_extra, 3, &columns, &rows);
nicklist = columns_sort_list(nicklist, rows);
- /* rows in last column */
+ /* rows in last column */
last_col_rows = rows-(cols*rows-g_slist_length(nicklist));
if (last_col_rows == 0)
- last_col_rows = rows;
+ last_col_rows = rows;
str = g_string_new(prefix_format);
linebuf_size = max_width+1; linebuf = g_malloc(linebuf_size);
- col = 0; row = 0;
+ col = 0; row = 0;
for (tmp = nicklist; tmp != NULL; tmp = tmp->next) {
NICK_REC *rec = tmp->data;
@@ -407,39 +407,39 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
if (linebuf_size < columns[col]-item_extra+1) {
linebuf_size = (columns[col]-item_extra+1)*2;
- linebuf = g_realloc(linebuf, linebuf_size);
+ linebuf = g_realloc(linebuf, linebuf_size);
}
memset(linebuf, ' ', columns[col]-item_extra);
linebuf[columns[col]-item_extra] = '\0';
memcpy(linebuf, rec->nick, strlen(rec->nick));
- formatnum = rec->op ? TXT_NAMES_NICK_OP :
- rec->halfop ? TXT_NAMES_NICK_HALFOP :
- rec->voice ? TXT_NAMES_NICK_VOICE :
- TXT_NAMES_NICK;
+ formatnum = rec->op ? TXT_NAMES_NICK_OP :
+ rec->halfop ? TXT_NAMES_NICK_HALFOP :
+ rec->voice ? TXT_NAMES_NICK_VOICE :
+ TXT_NAMES_NICK;
format = format_get_text(MODULE_NAME, NULL,
- channel->server,
- channel->visible_name,
- formatnum, nickmode, linebuf);
+ channel->server,
+ channel->visible_name,
+ formatnum, nickmode, linebuf);
g_string_append(str, format);
g_free(format);
if (++col == cols) {
printtext(channel->server, channel->visible_name,
- MSGLEVEL_CLIENTCRAP, "%s", str->str);
+ MSGLEVEL_CLIENTCRAP, "%s", str->str);
g_string_truncate(str, 0);
if (prefix_format != NULL)
- g_string_assign(str, prefix_format);
+ g_string_assign(str, prefix_format);
col = 0; row++;
if (row == last_col_rows)
- cols--;
+ cols--;
}
}
if (str->len > strlen(prefix_format)) {
printtext(channel->server, channel->visible_name,
- MSGLEVEL_CLIENTCRAP, "%s", str->str);
+ MSGLEVEL_CLIENTCRAP, "%s", str->str);
}
g_slist_free(nicklist);
From 97a4ee78fd08e58fce62c6c0b22de94b625c90f6 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 03:42:56 +0200
Subject: [PATCH 075/140] get_alignment: handle UTF-8 strings.
get_alignment now works with columns (width), not bytes, although it is liable
to work with bytes if the given text is not a valid UTF-8 string.
---
src/core/special-vars.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/core/special-vars.c b/src/core/special-vars.c
index d6794d96..64011b8e 100644
--- a/src/core/special-vars.c
+++ b/src/core/special-vars.c
@@ -25,6 +25,7 @@
#include "settings.h"
#include "servers.h"
#include "misc.h"
+#include "utf8.h"
#define ALIGN_RIGHT 0x01
#define ALIGN_CUT 0x02
@@ -320,18 +321,24 @@ static char *get_alignment(const char *text, int align, int flags, char pad)
{
GString *str;
char *ret;
+ int policy;
+ unsigned int cut_bytes;
g_return_val_if_fail(text != NULL, NULL);
+ policy = string_policy(text);
+
str = g_string_new(text);
/* cut */
- if ((flags & ALIGN_CUT) && align > 0 && str->len > align)
- g_string_truncate(str, align);
+ if ((flags & ALIGN_CUT) && align > 0 && string_width(text, policy) > align) {
+ string_chars_for_width(text, policy, align, &cut_bytes);
+ g_string_truncate(str, cut_bytes);
+ }
/* add pad characters */
if (flags & ALIGN_PAD) {
- while (str->len < align) {
+ while (string_width(str->str, policy) < align) {
if (flags & ALIGN_RIGHT)
g_string_prepend_c(str, pad);
else
From f1b5b515b9f91866d241ba6dbf5e1db6827ff61a Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 03:51:48 +0200
Subject: [PATCH 076/140] Make get_alignment() available outside special-vars.c
---
src/core/special-vars.c | 6 +-----
src/core/special-vars.h | 7 +++++++
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/core/special-vars.c b/src/core/special-vars.c
index 64011b8e..fe6bbed2 100644
--- a/src/core/special-vars.c
+++ b/src/core/special-vars.c
@@ -27,10 +27,6 @@
#include "misc.h"
#include "utf8.h"
-#define ALIGN_RIGHT 0x01
-#define ALIGN_CUT 0x02
-#define ALIGN_PAD 0x04
-
#define isvarchar(c) \
(i_isalnum(c) || (c) == '_')
@@ -317,7 +313,7 @@ static int get_alignment_args(char **data, int *align, int *flags, char *pad)
}
/* return the aligned text */
-static char *get_alignment(const char *text, int align, int flags, char pad)
+char *get_alignment(const char *text, int align, int flags, char pad)
{
GString *str;
char *ret;
diff --git a/src/core/special-vars.h b/src/core/special-vars.h
index 11262dad..300dae0e 100644
--- a/src/core/special-vars.h
+++ b/src/core/special-vars.h
@@ -9,9 +9,16 @@
#define PARSE_FLAG_ESCAPE_THEME 0x08 /* if any arguments/variables contain { or } chars, escape them with % */
#define PARSE_FLAG_ONLY_ARGS 0x10 /* expand only arguments ($0 $1 etc.) but no other $variables */
+#define ALIGN_RIGHT 0x01
+#define ALIGN_CUT 0x02
+#define ALIGN_PAD 0x04
+
typedef char* (*SPECIAL_HISTORY_FUNC)
(const char *text, void *item, int *free_ret);
+/* Cut and/or pad text so it takes exactly "align" characters on the screen */
+char *get_alignment(const char *text, int align, int flags, char pad);
+
/* Parse and expand text after '$' character. return value has to be
g_free()'d if `free_ret' is TRUE. */
char *parse_special(char **cmd, SERVER_REC *server, void *item,
From 29beafcf6fd50ecb8a9f3b2b642c2d29c022a4e3 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 04:08:15 +0200
Subject: [PATCH 077/140] Improve UTF-8 handling in display_sorted_nicks().
---
src/fe-common/core/fe-channels.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c
index fd44be11..d87c4ce5 100644
--- a/src/fe-common/core/fe-channels.c
+++ b/src/fe-common/core/fe-channels.c
@@ -26,6 +26,8 @@
#include "levels.h"
#include "misc.h"
#include "settings.h"
+#include "special-vars.h"
+#include "utf8.h"
#include "chat-protocols.h"
#include "chatnets.h"
@@ -323,7 +325,7 @@ static void cmd_channel_remove(const char *data)
static int get_nick_length(void *data)
{
- return strlen(((NICK_REC *) data)->nick);
+ return string_width(((NICK_REC *) data)->nick, -1);
}
static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
@@ -333,9 +335,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
GString *str;
GSList *tmp;
char *format, *stripped, *prefix_format;
- char *linebuf, nickmode[2] = { 0, 0 };
+ char *aligned_nick, nickmode[2] = { 0, 0 };
int *columns, cols, rows, last_col_rows, col, row, max_width;
- int item_extra, linebuf_size, formatnum;
+ int item_extra, formatnum;
window = window_find_closest(channel->server, channel->visible_name,
MSGLEVEL_CLIENTCRAP);
@@ -394,7 +396,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
last_col_rows = rows;
str = g_string_new(prefix_format);
- linebuf_size = max_width+1; linebuf = g_malloc(linebuf_size);
col = 0; row = 0;
for (tmp = nicklist; tmp != NULL; tmp = tmp->next) {
@@ -405,13 +406,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
else
nickmode[0] = ' ';
- if (linebuf_size < columns[col]-item_extra+1) {
- linebuf_size = (columns[col]-item_extra+1)*2;
- linebuf = g_realloc(linebuf, linebuf_size);
- }
- memset(linebuf, ' ', columns[col]-item_extra);
- linebuf[columns[col]-item_extra] = '\0';
- memcpy(linebuf, rec->nick, strlen(rec->nick));
+ aligned_nick = get_alignment(rec->nick,
+ columns[col]-item_extra,
+ ALIGN_PAD, ' ');
formatnum = rec->op ? TXT_NAMES_NICK_OP :
rec->halfop ? TXT_NAMES_NICK_HALFOP :
@@ -420,8 +417,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
format = format_get_text(MODULE_NAME, NULL,
channel->server,
channel->visible_name,
- formatnum, nickmode, linebuf);
+ formatnum, nickmode, aligned_nick);
g_string_append(str, format);
+ g_free(aligned_nick);
g_free(format);
if (++col == cols) {
@@ -446,7 +444,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
g_string_free(str, TRUE);
g_free_not_null(columns);
g_free_not_null(prefix_format);
- g_free(linebuf);
}
void fe_channels_nicklist(CHANNEL_REC *channel, int flags)
From 72064de9fe064a7536b501fc470edf75fc393314 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 04:19:38 +0200
Subject: [PATCH 078/140] Simplify scrlen_str() using string_width().
---
src/fe-text/gui-entry.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index beea2273..949a43d3 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -366,22 +366,8 @@ static int scrlen_str(const char *str)
char *stripped;
g_return_val_if_fail(str != NULL, 0);
- str = stripped = strip_codes(str);
- if (string_policy(str) == TREAT_STRING_AS_UTF8) {
-
- while (*str != '\0') {
- gunichar c;
-
- c = g_utf8_get_char(str);
- str = g_utf8_next_char(str);
-
- len += unichar_isprint(c) ? mk_wcwidth(c) : 1;
- }
-
- } else {
- len = strlen(str);
- }
-
+ stripped = strip_codes(str);
+ len = string_width(stripped, -1);
g_free(stripped);
return len;
}
From a26a387545ae530cb3222fd4daa5ed088e068de2 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 17:31:11 +0200
Subject: [PATCH 079/140] Adjust some conditions.
---
src/core/utf8.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index d1f58599..29b277e1 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -48,7 +48,7 @@ int string_advance(char const **str, int policy)
int string_policy(const char *str)
{
if (is_utf8()) {
- if (!str || g_utf8_validate(str, -1, NULL)) {
+ if (str == NULL || g_utf8_validate(str, -1, NULL)) {
/* No string provided or valid UTF-8 string: treat as UTF-8: */
return TREAT_STRING_AS_UTF8;
}
@@ -98,8 +98,8 @@ int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned
g_return_val_if_fail(str != NULL, -1);
/* Handle the dummy case where n is 0: */
- if (!n) {
- if (bytes) {
+ if (n == 0) {
+ if (bytes != NULL) {
*bytes = 0;
}
return 0;
@@ -128,7 +128,7 @@ int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned
* columns, which is less than or equal to n. */
/* Optionally provide the equivalent amount of bytes: */
- if (bytes) {
+ if (bytes != NULL) {
*bytes = c - str;
}
return char_count;
From 5d69b4c4a7d334ca29e61969712f5f8eedfa5cd9 Mon Sep 17 00:00:00 2001
From: Xavier G
Date: Fri, 13 May 2016 17:35:47 +0200
Subject: [PATCH 080/140] Convert string policies from #define to enum.
---
src/core/utf8.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/core/utf8.h b/src/core/utf8.h
index 411b2048..5bb53193 100644
--- a/src/core/utf8.h
+++ b/src/core/utf8.h
@@ -24,8 +24,10 @@ int string_advance(char const **str, int policy);
* TREAT_STRING_AS_UTF8 means strings are to be treated using g_utf8_*
* functions.
*/
-#define TREAT_STRING_AS_BYTES 0
-#define TREAT_STRING_AS_UTF8 1
+enum str_policy {
+ TREAT_STRING_AS_BYTES,
+ TREAT_STRING_AS_UTF8
+};
/* Return how the str string ought to be treated: TREAT_STRING_AS_UTF8 if the
* terminal handles UTF-8 and if the string appears to be a valid UTF-8 string;
From 8b847034efa20f23c96f35522f9f7615a5ab498c Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 11 May 2016 21:51:41 +0200
Subject: [PATCH 081/140] update news and authors
---
AUTHORS | 1 +
NEWS | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/AUTHORS b/AUTHORS
index 7ded5017..cb48e07a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -97,3 +97,4 @@ Other patches (grep for "patch" in ChangeLog) by:
Paul Johnson
KindOne
Fabian Kurz
+ Todd Pratt
diff --git a/NEWS b/NEWS
index 0d450b02..00d35f9d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,27 @@
v0.8.20-head 2016-xx-xx The Irssi team
* Removed --disable-ipv6
+ * /connect Network now aborts with an error if no servers have been
+ added to that network.
+ * /dcc commands now use quotes around spaces consistently.
+ irssiproxy can now forward all tags through a single port.
+ + irssiproxy can also listen on unix sockets.
+ send channel -botcmds immediately when no mask is specified (#175).
+ + the kill buffer now remembers consecutive kills.
+ New bindings were added: yank_next_cutbuffer and append_next_kill
+ + connections will avoid looking up IPv6 addresses if the machine does
+ not have an IPv6 address assigned (exact behaviour is implementation
+ defined).
+ + Fix potential crash if scripts insert undef values into the completion
+ list.
+ + Paste warning is now also shown on pasting overlong lines.
+ + autolog_ignore_targets and activity_hide_targets learn a new syntax
+ tag/* and * to ignore whole networks or everything.
+ + /hilight got a -matchcase flag to hilight case sensitively (#421).
+ - /squery and /servlist commands have been restored.
+ - Where Irssi would previously only report "System error" on connect,
+ it will now try harder to retrieve the system error message.
+ - IP addresses are no longer stored when resolve_reverse_lookup is
+ used.
v0.8.19 2016-03-23 The Irssi team
- Fixed regression when joining and parting channels on IRCnet (#435)
From 5995c0619dc2bf6d789e5b93abe8a531ceb1f45a Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 18 May 2016 14:39:52 +0200
Subject: [PATCH 082/140] abi increase for #480
---
src/common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/common.h b/src/common.h
index 4fd6d331..66892b78 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 4
+#define IRSSI_ABI_VERSION 5
#define DEFAULT_SERVER_ADD_PORT 6667
From 8d5edff5151761d5b069badad836cb26724ae1ae Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 18 May 2016 14:43:54 +0200
Subject: [PATCH 083/140] update news and authors
---
AUTHORS | 1 +
NEWS | 1 +
2 files changed, 2 insertions(+)
diff --git a/AUTHORS b/AUTHORS
index cb48e07a..eea359cc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -98,3 +98,4 @@ Other patches (grep for "patch" in ChangeLog) by:
KindOne
Fabian Kurz
Todd Pratt
+ xavierog
diff --git a/NEWS b/NEWS
index 00d35f9d..5312aef5 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ v0.8.20-head 2016-xx-xx The Irssi team
it will now try harder to retrieve the system error message.
- IP addresses are no longer stored when resolve_reverse_lookup is
used.
+ - /names and $[...] now uses utf8 string operations (#40, #411).
v0.8.19 2016-03-23 The Irssi team
- Fixed regression when joining and parting channels on IRCnet (#435)
From 36beddc64f881c2c9618b449ed5c590d41872455 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 18 May 2016 15:32:35 +0200
Subject: [PATCH 084/140] test make dist in travis
---
.travis.yml | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 46f58766..804dc58c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,11 +16,31 @@ addons:
before_install:
- perl -V
+ - ./autogen.sh --with-proxy --with-bot --with-perl=module
+ - make dist
+ - cd ..
+ - tar xaf */irssi-*.tar.*
+ - cd irssi-*
-install: true
-
-script:
- - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
- - cat config.log
+install:
+ - ./configure --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
- make CFLAGS="-Wall -Werror"
- make install
+
+before_script:
+ - cd
+ - mkdir irssi-test
+ - echo echo automated irssi launch test > irssi-test/startup;
+ echo ^set settings_autosave off >> irssi-test/startup;
+ echo ^set -clear log_close_string >> irssi-test/startup;
+ echo ^set -clear log_day_changed >> irssi-test/startup;
+ echo ^set -clear log_open_string >> irssi-test/startup;
+ echo ^set log_timestamp '* ' >> irssi-test/startup;
+ echo ^window log on >> irssi-test/startup
+ - echo load perl >> irssi-test/startup
+ - echo load proxy >> irssi-test/startup
+ - echo ^quit >> irssi-test/startup
+ - irssi-build/bin/irssi --home irssi-test
+ - cat irc.log.*
+
+script: true
From 02221eae373c5db93d1c715d836d79c724d361c7 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Wed, 18 May 2016 15:42:09 +0200
Subject: [PATCH 085/140] fix dist compilation failure
remove illegal wcwidth.c include and compile wcwidth.c
correct #include in wcwidth.c
fallout from #480
---
src/core/Makefile.am | 2 ++
src/core/utf8.c | 2 +-
src/core/wcwidth.c | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index cc200034..af323234 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -45,6 +45,7 @@ libcore_a_SOURCES = \
signals.c \
special-vars.c \
utf8.c \
+ wcwidth.c \
write-buffer.c
structure_headers = \
@@ -94,6 +95,7 @@ pkginc_core_HEADERS = \
settings.h \
signals.h \
special-vars.h \
+ utf8.h \
window-item-def.h \
write-buffer.h \
$(structure_headers)
diff --git a/src/core/utf8.c b/src/core/utf8.c
index 29b277e1..c53d8816 100644
--- a/src/core/utf8.c
+++ b/src/core/utf8.c
@@ -24,7 +24,7 @@
#include "utf8.h"
#include "module.h"
-#include "wcwidth.c"
+
/* Provide is_utf8(): */
#include "recode.h"
diff --git a/src/core/wcwidth.c b/src/core/wcwidth.c
index 80d20fa1..711c4646 100644
--- a/src/core/wcwidth.c
+++ b/src/core/wcwidth.c
@@ -59,7 +59,7 @@
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
-#include "module.h"
+#include "utf8.h"
struct interval {
int first;
From f1d0c8ff99c4a0627d96c6ae0db39d917689fb07 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 1 Jun 2016 22:29:13 +0200
Subject: [PATCH 086/140] Correct the name of the emitted signal.
There's a typo in 'sasl_fail', the signal that's emitted should be
'server sasl failure' and not 'server sasl fail'.
---
src/irc/core/sasl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index b74b6a8c..f080ae59 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -71,7 +71,7 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from
params = event_get_params(data, 2, NULL, &error);
- signal_emit("server sasl fail", 2, server, error);
+ signal_emit("server sasl failure", 2, server, error);
/* Terminate the negotiation */
cap_finish_negotiation(server);
From 03aec7d3b369231b52960db7238f30cc46dd8e01 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Thu, 10 Dec 2015 14:07:07 +0100
Subject: [PATCH 087/140] silent make perl
---
src/perl/Makefile.am | 14 ++++++-
src/perl/Makefile_silent.pm | 76 ++++++++++++++++++++++++++++++++++
src/perl/common/Makefile.PL.in | 2 +-
src/perl/irc/Makefile.PL.in | 2 +-
src/perl/textui/Makefile.PL.in | 2 +-
src/perl/ui/Makefile.PL.in | 2 +-
6 files changed, 92 insertions(+), 6 deletions(-)
create mode 100644 src/perl/Makefile_silent.pm
diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am
index a09c49a5..b17fd664 100644
--- a/src/perl/Makefile.am
+++ b/src/perl/Makefile.am
@@ -117,16 +117,26 @@ textui_sources = \
EXTRA_DIST = \
get-signals.pl \
irssi-core.pl \
+ Makefile_silent.pm \
$(common_sources) \
$(irc_sources) \
$(ui_sources) \
$(textui_sources)
+am_v_pl__show_gen = $(am__v_pl__show_gen_$(V))
+am_v_pl__hide_gen = $(am__v_pl__hide_gen_$(V))
+am__v_pl__show_gen_ = $(am__v_pl__show_gen_$(AM_DEFAULT_VERBOSITY))
+am__v_pl__hide_gen_ = $(am__v_pl__hide_gen_$(AM_DEFAULT_VERBOSITY))
+am__v_pl__show_gen_0 = echo " GEN " $$dir ;
+am__v_pl__hide_gen_0 = > /dev/null
+am__v_pl__show_gen_1 =
+am__v_pl__hide_gen_1 =
+
all-local:
- for dir in $(perl_dirs); do \
+ $(AM_V_GEN)for dir in $(perl_dirs); do \
cd $$dir && \
if [ ! -f Makefile ]; then \
- $(perlpath) Makefile.PL $(PERL_MM_PARAMS); \
+ $(am_v_pl__show_gen)$(perlpath) Makefile.PL $(PERL_MM_PARAMS) $(am_v_pl__hide_gen); \
fi && \
($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS) || \
$(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \
diff --git a/src/perl/Makefile_silent.pm b/src/perl/Makefile_silent.pm
new file mode 100644
index 00000000..e6036c98
--- /dev/null
+++ b/src/perl/Makefile_silent.pm
@@ -0,0 +1,76 @@
+push @ExtUtils::MakeMaker::Overridable, qw(pm_to_blib);
+my $verb = $AM_DEFAULT_VERBOSITY;
+package MY {
+ sub _center {
+ my $z = shift;
+ length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z "
+ }
+ sub _silent_cmd {
+ my $z = shift;
+ $z =~ s{\t(?:- ?)?\K(?=\$\((?|(CC)CMD|(XS)UBPPRUN|(LD|MV|CHMOD)|(RM)_R?F|(CP)_NONEMPTY|FULL_(AR)\)))}{\$(PL_AM_V_$1)}g;
+ $z
+ }
+ sub c_o { _silent_cmd(shift->SUPER::c_o(@_)) }
+ sub xs_c { _silent_cmd(shift->SUPER::xs_c(@_)) }
+ sub xs_o { _silent_cmd(shift->SUPER::xs_o(@_)) }
+ sub dynamic_lib { _silent_cmd(shift->SUPER::dynamic_lib(@_)) }
+ sub static_lib { _silent_cmd(shift->SUPER::static_lib(@_)) }
+ sub dynamic_bs {
+ my $ret = shift->SUPER::dynamic_bs(@_);
+ $ret =~ s{Running Mkbootstrap for}{\$(PL_AM_V_BS_Text)}g;
+ _silent_cmd($ret)
+ }
+ sub pm_to_blib {
+ my $ret = shift->SUPER::pm_to_blib(@_);
+ $ret =~ s{^(\t(?:- ?)?)(?:\$\(NOECHO\) ?)?(.*-e ['"]pm_to_blib(.*\\\n)*.*)$}{$1\$(PL_AM_V_BLIB)$2\$(PL_AM_V_BLIB_Hide)}mg;
+ $ret
+ }
+ sub post_constants {
+ my $ret = shift->SUPER::post_constants(@_);
+ my @terse = qw(cc xs ld chmod cp ar blib);
+ my @silent = qw(mv rm);
+ my @special = qw(BLIB_Hide);
+
+ #default verbosity from command line parameter
+ $ret .= "
+AM_DEFAULT_VERBOSITY = @{[$verb ? 1 : 0]}
+";
+ #default options forward
+ $ret .= "
+PL_AM_V_${_} = \$(pl_am__v_${_}_\$(V))
+pl_am__v_${_}_ = \$(pl_am__v_${_}_\$(AM_DEFAULT_VERBOSITY))
+" for @special, map uc, @terse, @silent;
+
+ #quoted plain text needs extra quotes
+ $ret .= "
+PL_AM_V_BS_Text = \"\$(pl_am__v_BS_Text_\$(V))\"
+pl_am__v_BS_Text_ = \$(pl_am__v_BS_Text_\$(AM_DEFAULT_VERBOSITY))
+"
+ #hide pm_to_blib output
+. "
+pl_am__v_BLIB_Hide_0 = \$(DEV_NULL)
+pl_am__v_BLIB_Hide_1 =
+"
+ #text for Mkbootstrap
+. "
+pl_am__v_BS_Text_0 = \"@{[_center('BS')]}\"
+pl_am__v_BS_Text_1 = \"Running Mkbootstrap for\"
+";
+ #"terse" output
+ $ret .= "
+pl_am__v_${_}_0 = \$(NOECHO)echo \"@{[_center($_)]}\" \$\@;
+" for map uc, @terse;
+
+ #no output
+ $ret .= "
+pl_am__v_${_}_0 = \$(NOECHO)
+" for map uc, @silent;
+
+ #in verbose mode the "terse" echo expands to nothing
+ $ret .= "
+pl_am__v_${_}_1 =
+" for map uc, @terse, @silent;
+ $ret
+ }
+};
+1;
diff --git a/src/perl/common/Makefile.PL.in b/src/perl/common/Makefile.PL.in
index 4e545e7c..84a80403 100644
--- a/src/perl/common/Makefile.PL.in
+++ b/src/perl/common/Makefile.PL.in
@@ -1,4 +1,4 @@
-use ExtUtils::MakeMaker;
+use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm";
WriteMakefile('NAME' => 'Irssi',
'LIBS' => '',
diff --git a/src/perl/irc/Makefile.PL.in b/src/perl/irc/Makefile.PL.in
index 8f1e94d5..0fbc5241 100644
--- a/src/perl/irc/Makefile.PL.in
+++ b/src/perl/irc/Makefile.PL.in
@@ -1,4 +1,4 @@
-use ExtUtils::MakeMaker;
+use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm";
WriteMakefile('NAME' => 'Irssi::Irc',
'LIBS' => '',
diff --git a/src/perl/textui/Makefile.PL.in b/src/perl/textui/Makefile.PL.in
index 9e80274b..3541f75c 100644
--- a/src/perl/textui/Makefile.PL.in
+++ b/src/perl/textui/Makefile.PL.in
@@ -1,4 +1,4 @@
-use ExtUtils::MakeMaker;
+use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm";
WriteMakefile('NAME' => 'Irssi::TextUI',
'LIBS' => '',
diff --git a/src/perl/ui/Makefile.PL.in b/src/perl/ui/Makefile.PL.in
index a349918e..ed87d528 100644
--- a/src/perl/ui/Makefile.PL.in
+++ b/src/perl/ui/Makefile.PL.in
@@ -1,4 +1,4 @@
-use ExtUtils::MakeMaker;
+use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm";
WriteMakefile('NAME' => 'Irssi::UI',
'LIBS' => '',
From e0c8a9f3986249d8abde462bccdb00cd3d914ebc Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Sun, 5 Jun 2016 11:36:13 +0200
Subject: [PATCH 088/140] perl 5.10 fix
---
src/perl/Makefile_silent.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/perl/Makefile_silent.pm b/src/perl/Makefile_silent.pm
index e6036c98..372e4046 100644
--- a/src/perl/Makefile_silent.pm
+++ b/src/perl/Makefile_silent.pm
@@ -1,6 +1,6 @@
push @ExtUtils::MakeMaker::Overridable, qw(pm_to_blib);
my $verb = $AM_DEFAULT_VERBOSITY;
-package MY {
+{ package MY;
sub _center {
my $z = shift;
length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z "
@@ -72,5 +72,5 @@ pl_am__v_${_}_1 =
" for map uc, @terse, @silent;
$ret
}
-};
+}
1;
From bb190be0bfac956ada4f74a514ff70f28b114efa Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 13 Feb 2016 13:12:29 +0100
Subject: [PATCH 089/140] Replace mkpath with g_mkdir_with_parents
---
src/core/log.c | 2 +-
src/core/misc.c | 38 -------------------------------------
src/core/misc.h | 2 --
src/core/rawlog.c | 2 +-
src/core/settings.c | 2 +-
src/fe-common/core/fe-log.c | 2 +-
6 files changed, 4 insertions(+), 44 deletions(-)
diff --git a/src/core/log.c b/src/core/log.c
index 8306d2df..6af1effc 100644
--- a/src/core/log.c
+++ b/src/core/log.c
@@ -114,7 +114,7 @@ int log_start_logging(LOG_REC *log)
/* path may contain variables (%time, $vars),
make sure the directory is created */
dir = g_path_get_dirname(log->real_fname);
- mkpath(dir, log_dir_create_mode);
+ g_mkdir_with_parents(dir, log_dir_create_mode);
g_free(dir);
}
diff --git a/src/core/misc.c b/src/core/misc.c
index c26610ec..a8a0975a 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -407,44 +407,6 @@ int regexp_match(const char *str, const char *regexp)
#endif
}
-/* Create the directory and all it's parent directories */
-int mkpath(const char *path, int mode)
-{
- struct stat statbuf;
- const char *p;
- char *dir;
-
- g_return_val_if_fail(path != NULL, -1);
-
- p = g_path_skip_root((char *) path);
- if (p == NULL) {
- /* not a full path, maybe not what we wanted
- but continue anyway.. */
- p = path;
- }
- for (;;) {
- if (*p != G_DIR_SEPARATOR && *p != '\0') {
- p++;
- continue;
- }
-
- dir = g_strndup(path, (int) (p-path));
- if (stat(dir, &statbuf) != 0) {
- if (mkdir(dir, mode) == -1)
- {
- g_free(dir);
- return -1;
- }
- }
- g_free(dir);
-
- if (*p++ == '\0')
- break;
- }
-
- return 0;
-}
-
/* convert ~/ to $HOME */
char *convert_home(const char *path)
{
diff --git a/src/core/misc.h b/src/core/misc.h
index 7e78d3b9..58b665bf 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -39,8 +39,6 @@ GSList *hashtable_get_keys(GHashTable *hash);
/* easy way to check if regexp matches */
int regexp_match(const char *str, const char *regexp);
-/* Create the directory and all it's parent directories */
-int mkpath(const char *path, int mode);
/* convert ~/ to $HOME */
char *convert_home(const char *path);
diff --git a/src/core/rawlog.c b/src/core/rawlog.c
index 875c0ef2..2b46c50d 100644
--- a/src/core/rawlog.c
+++ b/src/core/rawlog.c
@@ -150,7 +150,7 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname)
int f;
dir = g_path_get_dirname(fname);
- mkpath(dir, log_dir_create_mode);
+ g_mkdir_with_parents(dir, log_dir_create_mode);
g_free(dir);
path = convert_home(fname);
diff --git a/src/core/settings.c b/src/core/settings.c
index 8e493124..17fc4115 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -683,7 +683,7 @@ static void init_configfile(void)
if (stat(get_irssi_dir(), &statbuf) != 0) {
/* ~/.irssi not found, create it. */
- if (mkpath(get_irssi_dir(), 0700) != 0) {
+ if (g_mkdir_with_parents(get_irssi_dir(), 0700) != 0) {
g_error("Couldn't create %s directory", get_irssi_dir());
}
} else if (!S_ISDIR(statbuf.st_mode)) {
diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c
index f2c4c014..5bc5c4e1 100644
--- a/src/fe-common/core/fe-log.c
+++ b/src/fe-common/core/fe-log.c
@@ -453,7 +453,7 @@ static void autolog_open(SERVER_REC *server, const char *server_tag,
log_item_add(log, LOG_ITEM_TARGET, target, server_tag);
dir = g_path_get_dirname(log->real_fname);
- mkpath(dir, log_dir_create_mode);
+ g_mkdir_with_parents(dir, log_dir_create_mode);
g_free(dir);
log->temp = TRUE;
From 8289f360757870b56a15576a20e79e1f2ca30fef Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 13 Feb 2016 13:15:33 +0100
Subject: [PATCH 090/140] Check the return value of open() in rawlog.c
---
src/core/rawlog.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/core/rawlog.c b/src/core/rawlog.c
index 2b46c50d..5927e730 100644
--- a/src/core/rawlog.c
+++ b/src/core/rawlog.c
@@ -157,6 +157,11 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname)
f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode);
g_free(path);
+ if (f < 0) {
+ g_warning("rawlog open() failed: %s", strerror(errno));
+ return;
+ }
+
rawlog_dump(rawlog, f);
close(f);
}
From 72712a0c62b0403f0fa472ccbe34fda8fb2cd530 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 13 Feb 2016 13:18:24 +0100
Subject: [PATCH 091/140] Replace strocpy with g_strlcpy
The only difference was that the former returned 1 if the buffer was
overflown, but the return value was never checked.
---
src/core/misc.c | 14 --------------
src/core/misc.h | 3 ---
src/irc/core/irc-nicklist.c | 2 +-
src/irc/dcc/dcc-get.c | 6 +++---
4 files changed, 4 insertions(+), 21 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index a8a0975a..682d006c 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -773,20 +773,6 @@ char *escape_string(const char *str)
return ret;
}
-int strocpy(char *dest, const char *src, size_t dstsize)
-{
- if (dstsize == 0)
- return -1;
-
- while (*src != '\0' && dstsize > 1) {
- *dest++ = *src++;
- dstsize--;
- }
-
- *dest++ = '\0';
- return *src == '\0' ? 0 : -1;
-}
-
int nearest_power(int num)
{
int n = 1;
diff --git a/src/core/misc.h b/src/core/misc.h
index 58b665bf..fdb16a49 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -83,9 +83,6 @@ int parse_size(const char *size, int *bytes);
Stop when `end_char' is found from string. */
int is_numeric(const char *str, char end_char);
-/* Like strlcpy(), but return -1 if buffer was overflown, 0 if not. */
-int strocpy(char *dest, const char *src, size_t dstsize);
-
/* strstr() with case-ignoring */
char *stristr(const char *data, const char *key);
diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c
index bcb9d1f6..b22f3269 100644
--- a/src/irc/core/irc-nicklist.c
+++ b/src/irc/core/irc-nicklist.c
@@ -48,7 +48,7 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
rec->send_massjoin = send_massjoin;
if (prefixes != NULL) {
- strocpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
+ g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
}
nicklist_insert(CHANNEL(channel), rec);
diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c
index ac281683..e7b796bb 100644
--- a/src/irc/dcc/dcc-get.c
+++ b/src/irc/dcc/dcc-get.c
@@ -473,8 +473,8 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data,
net_ip2host(&temp_dcc->addr, temp_dcc->addrstr);
else {
/* with IPv6, show it to us as it was sent */
- strocpy(temp_dcc->addrstr, address,
- sizeof(temp_dcc->addrstr));
+ g_strlcpy(temp_dcc->addrstr, address,
+ sizeof(temp_dcc->addrstr));
}
/* This new signal is added to let us invoke
@@ -508,7 +508,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data,
net_ip2host(&dcc->addr, dcc->addrstr);
else {
/* with IPv6, show it to us as it was sent */
- strocpy(dcc->addrstr, address, sizeof(dcc->addrstr));
+ g_strlcpy(dcc->addrstr, address, sizeof(dcc->addrstr));
}
dcc->port = port;
dcc->size = size;
From 7a3c6fe86ca55b4ef69b11443b87359b333bc20b Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 13 Feb 2016 14:16:05 +0100
Subject: [PATCH 092/140] Replace strarray_length with g_strv_length
---
src/core/ignore.c | 2 +-
src/core/misc.c | 14 --------------
src/core/misc.h | 2 --
src/core/special-vars.c | 2 +-
src/fe-common/core/hilight-text.c | 2 +-
src/irc/dcc/dcc-chat.c | 2 +-
src/irc/dcc/dcc-get.c | 2 +-
src/irc/dcc/dcc-resume.c | 2 +-
src/irc/dcc/dcc-server.c | 2 +-
9 files changed, 7 insertions(+), 23 deletions(-)
diff --git a/src/core/ignore.c b/src/core/ignore.c
index 8d5a27c2..2047dc9d 100644
--- a/src/core/ignore.c
+++ b/src/core/ignore.c
@@ -241,7 +241,7 @@ IGNORE_REC *ignore_find_full(const char *servertag, const char *mask, const char
if (channels == NULL || rec->channels == NULL)
continue; /* other doesn't have channels */
- if (strarray_length(channels) != strarray_length(rec->channels))
+ if (g_strv_length(channels) != g_strv_length(rec->channels))
continue; /* different amount of channels */
/* check that channels match */
diff --git a/src/core/misc.c b/src/core/misc.c
index 682d006c..70d09e55 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -150,20 +150,6 @@ int find_substr(const char *list, const char *item)
return FALSE;
}
-int strarray_length(char **array)
-{
- int len;
-
- g_return_val_if_fail(array != NULL, 0);
-
- len = 0;
- while (*array) {
- len++;
- array++;
- }
- return len;
-}
-
int strarray_find(char **array, const char *item)
{
char **tmp;
diff --git a/src/core/misc.h b/src/core/misc.h
index fdb16a49..f8f1786f 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -102,8 +102,6 @@ char *show_lowascii(const char *str);
/* replace all `from' chars in string to `to' chars. returns `str' */
char *replace_chars(char *str, char from, char to);
-/* return how many items `array' has */
-int strarray_length(char **array);
/* return index of `item' in `array' or -1 if not found */
int strarray_find(char **array, const char *item);
diff --git a/src/core/special-vars.c b/src/core/special-vars.c
index fe6bbed2..6ca080fc 100644
--- a/src/core/special-vars.c
+++ b/src/core/special-vars.c
@@ -44,7 +44,7 @@ static char *get_argument(char **cmd, char **arglist)
arg = 0;
max = -1;
- argcount = arglist == NULL ? 0 : strarray_length(arglist);
+ argcount = arglist == NULL ? 0 : g_strv_length(arglist);
if (**cmd == '*') {
/* get all arguments */
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 36e1e78c..4691a708 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -178,7 +178,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels)
if (channels == NULL || rec->channels == NULL)
continue; /* other doesn't have channels */
- if (strarray_length(channels) != strarray_length(rec->channels))
+ if (g_strv_length(channels) != g_strv_length(rec->channels))
continue; /* different amount of channels */
/* check that channels match */
diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c
index e3dbe72d..ca90b8d8 100644
--- a/src/irc/dcc/dcc-chat.c
+++ b/src/irc/dcc/dcc-chat.c
@@ -619,7 +619,7 @@ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data,
/* CHAT */
/* CHAT 0 (DCC CHAT passive protocol) */
params = g_strsplit(data, " ", -1);
- paramcount = strarray_length(params);
+ paramcount = g_strv_length(params);
if (paramcount < 3) {
g_strfreev(params);
diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c
index e7b796bb..f7a95bb9 100644
--- a/src/irc/dcc/dcc-get.c
+++ b/src/irc/dcc/dcc-get.c
@@ -423,7 +423,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data,
/* SEND [...] */
/* SEND 0 (DCC SEND passive protocol) */
params = g_strsplit(data, " ", -1);
- paramcount = strarray_length(params);
+ paramcount = g_strv_length(params);
if (paramcount < 4) {
signal_emit("dcc error ctcp", 5, "SEND", data,
diff --git a/src/irc/dcc/dcc-resume.c b/src/irc/dcc/dcc-resume.c
index 11b28aef..36f84ddf 100644
--- a/src/irc/dcc/dcc-resume.c
+++ b/src/irc/dcc/dcc-resume.c
@@ -88,7 +88,7 @@ static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick,
/* RESUME|ACCEPT */
/* RESUME|ACCEPT 0 (passive protocol) */
params = g_strsplit(data, " ", -1);
- paramcount = strarray_length(params);
+ paramcount = g_strv_length(params);
if (paramcount < 3)
return 0;
diff --git a/src/irc/dcc/dcc-server.c b/src/irc/dcc/dcc-server.c
index 30224ff9..7ae572cd 100644
--- a/src/irc/dcc/dcc-server.c
+++ b/src/irc/dcc/dcc-server.c
@@ -245,7 +245,7 @@ static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg)
/* 120 clientnickname filesize filename */
params = g_strsplit(msg, " ", -1);
- paramcount = strarray_length(params);
+ paramcount = g_strv_length(params);
if (paramcount < 3) {
g_strfreev(params);
From 0f9d2b35700db69c66c5878b5562852565753dd2 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sat, 13 Feb 2016 16:26:36 +0100
Subject: [PATCH 093/140] Remove unused regexp_match
---
src/core/misc.c | 18 ------------------
src/core/misc.h | 3 ---
2 files changed, 21 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 70d09e55..48a49fa3 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -375,24 +375,6 @@ char *stristr_full(const char *data, const char *key)
return strstr_full_case(data, key, TRUE);
}
-int regexp_match(const char *str, const char *regexp)
-{
-#ifdef HAVE_REGEX_H
- regex_t preg;
- int ret;
-
- if (regcomp(&preg, regexp, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0)
- return 0;
-
- ret = regexec(&preg, str, 0, NULL, 0);
- regfree(&preg);
-
- return ret == 0;
-#else
- return FALSE;
-#endif
-}
-
/* convert ~/ to $HOME */
char *convert_home(const char *path)
{
diff --git a/src/core/misc.h b/src/core/misc.h
index f8f1786f..df17998f 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -36,9 +36,6 @@ char *gslist_to_string(GSList *list, const char *delimiter);
items while using this list, use g_slist_free() after you're done with it */
GSList *hashtable_get_keys(GHashTable *hash);
-/* easy way to check if regexp matches */
-int regexp_match(const char *str, const char *regexp);
-
/* convert ~/ to $HOME */
char *convert_home(const char *path);
From e0b290c34fc116c043f51396e2770821ec357522 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Wed, 17 Feb 2016 23:21:38 +0100
Subject: [PATCH 094/140] Update the g_istr_hash function to use the djb hash
---
src/core/misc.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 48a49fa3..74ca4725 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -401,22 +401,15 @@ int g_istr_cmp(gconstpointer v, gconstpointer v2)
return g_ascii_strcasecmp((const char *) v, (const char *) v2);
}
-/* a char* hash function from ASU */
-unsigned int g_istr_hash(gconstpointer v)
+guint g_istr_hash(gconstpointer v)
{
- const char *s = (const char *) v;
- unsigned int h = 0, g;
+ const signed char *p;
+ guint32 h = 5381;
- while (*s != '\0') {
- h = (h << 4) + i_toupper(*s);
- if ((g = h & 0xf0000000UL)) {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
- s++;
- }
+ for (p = v; *p != '\0'; p++)
+ h = (h << 5) + h + g_ascii_toupper(*p);
- return h /* % M */;
+ return h;
}
/* Find `mask' from `data', you can use * and ? wildcards. */
From cc70e8c581713309c64eb15c3999341d17988e19 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 5 Jun 2016 16:48:27 +0200
Subject: [PATCH 095/140] Clean up some GTimeVal juggling
---
src/irc/core/irc-servers.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 1df95f70..5b4af2ac 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -212,7 +212,6 @@ static void server_init(IRC_SERVER_REC *server)
{
IRC_SERVER_CONNECT_REC *conn;
char *address, *ptr, *username, *cmd;
- GTimeVal now;
g_return_if_fail(server != NULL);
@@ -287,9 +286,8 @@ static void server_init(IRC_SERVER_REC *server)
/* prevent the queue from sending too early, we have a max cut off of 120 secs */
/* this will reset to 1 sec after we get the 001 event */
- g_get_current_time(&now);
- memcpy(&((IRC_SERVER_REC *)server)->wait_cmd, &now, sizeof(GTimeVal));
- ((IRC_SERVER_REC *)server)->wait_cmd.tv_sec += 120;
+ g_get_current_time(&server->wait_cmd);
+ g_time_val_add(&server->wait_cmd, 120 * G_USEC_PER_SEC);
}
SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn)
@@ -535,7 +533,7 @@ void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len)
server->wait_cmd.tv_sec = 0;
else {
memcpy(&server->wait_cmd, &server->last_cmd, sizeof(GTimeVal));
- server->wait_cmd.tv_sec += 2 + len/100;
+ g_time_val_add(&server->wait_cmd, (2 + len/100) * G_USEC_PER_SEC);
}
}
@@ -695,7 +693,6 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
static void event_connected(IRC_SERVER_REC *server, const char *data, const char *from)
{
char *params, *nick;
- GTimeVal now;
g_return_if_fail(server != NULL);
@@ -718,8 +715,7 @@ static void event_connected(IRC_SERVER_REC *server, const char *data, const char
server->real_connect_time = time(NULL);
/* let the queue send now that we are identified */
- g_get_current_time(&now);
- memcpy(&server->wait_cmd, &now, sizeof(GTimeVal));
+ g_get_current_time(&server->wait_cmd);
if (server->connrec->usermode != NULL) {
/* Send the user mode, before the autosendcmd.
From 2e8744319d5e5e47799ec20b2f737c437e8c6398 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 5 Jun 2016 16:54:20 +0200
Subject: [PATCH 096/140] str_to_uofft is a tiny wrapper over strtoul{,l}
---
src/core/misc.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 74ca4725..9081abe1 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -515,15 +515,11 @@ int dec2octal(int decimal)
/* string -> uoff_t */
uoff_t str_to_uofft(const char *str)
{
- uoff_t ret;
-
- ret = 0;
- while (*str != '\0') {
- ret = ret*10 + (*str - '0');
- str++;
- }
-
- return ret;
+#ifdef UOFF_T_LONG_LONG
+ return (uoff_t)strtoull(str, NULL, 10);
+#else
+ return (uoff_t)strtoul(str, NULL, 10);
+#endif
}
/* convert all low-ascii (<32) to ^ combinations */
From 0060f682c213dc25901f4c0ab01a01176e14da9e Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 5 Jun 2016 17:24:27 +0200
Subject: [PATCH 097/140] Factor out some redundant code and remove
hashtable_get_keys
---
src/core/misc.c | 22 ++++++++++++++++------
src/core/misc.h | 4 +---
src/core/servers.c | 16 +++-------------
src/fe-common/core/fe-exec.c | 15 +++------------
src/fe-text/lastlog.c | 17 +++--------------
5 files changed, 26 insertions(+), 48 deletions(-)
diff --git a/src/core/misc.c b/src/core/misc.c
index 9081abe1..bc9f504e 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -20,6 +20,7 @@
#include "module.h"
#include "misc.h"
+#include "commands.h"
#ifdef HAVE_REGEX_H
# include
@@ -265,14 +266,23 @@ void hash_save_key(char *key, void *value, GSList **list)
*list = g_slist_append(*list, key);
}
-/* save all keys in hash table to linked list - you shouldn't remove any
- items while using this list, use g_slist_free() after you're done with it */
-GSList *hashtable_get_keys(GHashTable *hash)
+/* remove all the options from the optlist hash table that are valid for the
+ * command cmd */
+GList *optlist_remove_known(const char *cmd, GHashTable *optlist)
{
- GSList *list;
+ GList *list, *tmp, *next;
+
+ list = g_hash_table_get_keys(optlist);
+ if (cmd != NULL && list != NULL) {
+ for (tmp = list; tmp != NULL; tmp = next) {
+ char *option = tmp->data;
+ next = tmp->next;
+
+ if (command_have_option(cmd, option))
+ list = g_list_remove(list, option);
+ }
+ }
- list = NULL;
- g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list);
return list;
}
diff --git a/src/core/misc.h b/src/core/misc.h
index df17998f..c095e131 100644
--- a/src/core/misc.h
+++ b/src/core/misc.h
@@ -32,9 +32,7 @@ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter);
/* `list' contains char* */
char *gslist_to_string(GSList *list, const char *delimiter);
-/* save all keys in hash table to linked list - you shouldn't remove any
- items while using this list, use g_slist_free() after you're done with it */
-GSList *hashtable_get_keys(GHashTable *hash);
+GList *optlist_remove_known(const char *cmd, GHashTable *optlist);
/* convert ~/ to $HOME */
char *convert_home(const char *path);
diff --git a/src/core/servers.c b/src/core/servers.c
index 3342304e..d6297c4d 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -684,21 +684,11 @@ SERVER_REC *cmd_options_get_server(const char *cmd,
SERVER_REC *defserver)
{
SERVER_REC *server;
- GSList *list, *tmp, *next;
+ GList *list;
/* get all the options, then remove the known ones. there should
be only one left - the server tag. */
- list = hashtable_get_keys(optlist);
- if (cmd != NULL) {
- for (tmp = list; tmp != NULL; tmp = next) {
- char *option = tmp->data;
- next = tmp->next;
-
- if (command_have_option(cmd, option))
- list = g_slist_remove(list, option);
- }
- }
-
+ list = optlist_remove_known(cmd, optlist);
if (list == NULL)
return defserver;
@@ -713,7 +703,7 @@ SERVER_REC *cmd_options_get_server(const char *cmd,
server = NULL;
}
- g_slist_free(list);
+ g_list_free(list);
return server;
}
diff --git a/src/fe-common/core/fe-exec.c b/src/fe-common/core/fe-exec.c
index b5f289ce..36990866 100644
--- a/src/fe-common/core/fe-exec.c
+++ b/src/fe-common/core/fe-exec.c
@@ -237,22 +237,13 @@ static int signal_name_to_id(const char *name)
static int cmd_options_get_signal(const char *cmd,
GHashTable *optlist)
{
- GSList *list, *tmp, *next;
+ GList *list;
char *signame;
int signum;
/* get all the options, then remove the known ones. there should
be only one left - the signal */
- list = hashtable_get_keys(optlist);
- if (cmd != NULL) {
- for (tmp = list; tmp != NULL; tmp = next) {
- char *option = tmp->data;
- next = tmp->next;
-
- if (command_have_option(cmd, option))
- list = g_slist_remove(list, option);
- }
- }
+ list = optlist_remove_known(cmd, optlist);
if (list == NULL)
return -1;
@@ -272,7 +263,7 @@ static int cmd_options_get_signal(const char *cmd,
return -2;
}
- g_slist_free(list);
+ g_list_free(list);
return signum;
}
diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c
index 166d2847..c0b1dde8 100644
--- a/src/fe-text/lastlog.c
+++ b/src/fe-text/lastlog.c
@@ -39,21 +39,10 @@
Returns -1 if unknown option was given. */
int cmd_options_get_level(const char *cmd, GHashTable *optlist)
{
- GSList *list, *tmp, *next;
+ GList *list;
int level, retlevel;
- /* get all the options, then remove the known ones. there should
- be only one left - the server tag. */
- list = hashtable_get_keys(optlist);
- if (cmd != NULL) {
- for (tmp = list; tmp != NULL; tmp = next) {
- char *option = tmp->data;
- next = tmp->next;
-
- if (command_have_option(cmd, option))
- list = g_slist_remove(list, option);
- }
- }
+ list = optlist_remove_known(cmd, optlist);
retlevel = 0;
while (list != NULL) {
@@ -68,7 +57,7 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist)
}
retlevel |= level;
- list = g_slist_remove(list, list->data);
+ list = g_list_remove(list, list->data);
}
return retlevel;
From 98fce5f8074abcf5d35a1834952e42cd79384db2 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 5 Jun 2016 22:47:04 +0200
Subject: [PATCH 098/140] Deprecate net_connect()
---
src/core/network.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/network.h b/src/core/network.h
index fb627b4d..03f3b813 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -37,7 +37,7 @@ GIOChannel *g_io_channel_new(int handle);
int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
/* Connect to socket */
-GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip);
+GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) G_GNUC_DEPRECATED;
/* Connect to socket with ip address and SSL*/
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server);
int irssi_ssl_handshake(GIOChannel *handle);
From 9fd286fed8d231f9c78353f5d746ed82e3bc05c4 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 5 Jun 2016 22:47:29 +0200
Subject: [PATCH 099/140] Bump the ABI
---
src/common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/common.h b/src/common.h
index 66892b78..0a7b72f0 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,7 +6,7 @@
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
-#define IRSSI_ABI_VERSION 5
+#define IRSSI_ABI_VERSION 6
#define DEFAULT_SERVER_ADD_PORT 6667
From d6d74c0da981af22fb8cbfa68d3bdc5446c55155 Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Mon, 6 Jun 2016 16:58:40 +0200
Subject: [PATCH 100/140] Do not crash on OPTCHAN when item has no server
May fix bugs.debian.org#826525
---
src/core/commands.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/core/commands.c b/src/core/commands.c
index 88d1208c..607baf77 100644
--- a/src/core/commands.c
+++ b/src/core/commands.c
@@ -666,7 +666,7 @@ get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name)
const char *ret;
char *tmp, *origtmp, *channel;
- if (active_item == NULL) {
+ if (active_item == NULL || active_item->server == NULL) {
/* no active channel in window, channel required */
return cmd_get_param(data);
}
@@ -674,11 +674,13 @@ get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name)
origtmp = tmp = g_strdup(*data);
channel = cmd_get_param(&tmp);
- if (g_strcmp0(channel, "*") == 0 && !require_name) {
+ if (g_strcmp0(channel, "*") == 0 && IS_CHANNEL(active_item) &&
+ !require_name) {
/* "*" means active channel */
cmd_get_param(data);
ret = window_item_get_target(active_item);
- } else if (!server_ischannel(active_item->server, channel)) {
+ } else if (IS_CHANNEL(active_item) &&
+ !server_ischannel(active_item->server, channel)) {
/* we don't have channel parameter - use active channel */
ret = window_item_get_target(active_item);
} else {
From bf9d9494db89e7de45653e4797e2977c6e185c13 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 12 Jun 2016 15:26:07 +0200
Subject: [PATCH 101/140] Add a CHOICE type to the settings system.
This is useful to let the user choose an option between a finite set of
valid alternatives.
---
src/core/settings.c | 95 ++++++++++++++++++++++++++++----
src/core/settings.h | 14 ++++-
src/fe-common/core/completion.c | 17 +++++-
src/fe-common/core/fe-settings.c | 5 ++
4 files changed, 113 insertions(+), 18 deletions(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index 8e493124..9c2389bc 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -148,11 +148,34 @@ int settings_get_size(const char *key)
return str == NULL ? 0 : bytes;
}
+int settings_get_choice(const char *key)
+{
+ SETTINGS_REC *rec;
+ CONFIG_NODE *node;
+ char *str;
+ int idx;
+
+ rec = settings_get(key, SETTING_TYPE_CHOICE);
+ if (rec == NULL) return -1;
+
+ node = iconfig_node_traverse("settings", FALSE);
+ node = node == NULL ? NULL : iconfig_node_section(node, rec->module, -1);
+
+ str = node == NULL ? rec->default_value.v_string :
+ config_node_get_str(node, key, rec->default_value.v_string);
+
+ idx = strarray_find(rec->choices, str);
+ return (idx < 0) ? rec->default_value.v_int : idx;
+}
+
char *settings_get_print(SETTINGS_REC *rec)
{
char *value = NULL;
switch(rec->type) {
+ case SETTING_TYPE_CHOICE:
+ value = g_strdup(rec->choices[settings_get_choice(rec->key)]);
+ break;
case SETTING_TYPE_BOOLEAN:
value = g_strdup(settings_get_bool(rec->key) ? "ON" : "OFF");
break;
@@ -172,13 +195,31 @@ char *settings_get_print(SETTINGS_REC *rec)
static void settings_add(const char *module, const char *section,
const char *key, SettingType type,
- const SettingValue *default_value)
+ const SettingValue *default_value,
+ const char *choices)
{
SETTINGS_REC *rec;
+ char **choices_vec = NULL;
g_return_if_fail(key != NULL);
g_return_if_fail(section != NULL);
+ if (type == SETTING_TYPE_CHOICE) {
+ if (choices == NULL) {
+ g_warning("Trying to add setting '%s' with no choices.", key);
+ return;
+ }
+
+ choices_vec = g_strsplit(choices, ",", -1);
+
+ /* validate the default value */
+ if (default_value->v_int < 0 || default_value->v_int >= g_strv_length(choices_vec)) {
+ g_warning("Trying to add setting '%s' with an invalid default value.", key);
+ g_strfreev(choices_vec);
+ return;
+ }
+ }
+
rec = g_hash_table_lookup(settings, key);
if (rec != NULL) {
/* Already exists, make sure it's correct type */
@@ -197,6 +238,7 @@ static void settings_add(const char *module, const char *section,
rec->type = type;
rec->default_value = *default_value;
+ rec->choices = choices_vec;
g_hash_table_insert(settings, rec->key, rec);
}
}
@@ -208,7 +250,17 @@ void settings_add_str_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_string = g_strdup(def);
- settings_add(module, section, key, SETTING_TYPE_STRING, &default_value);
+ settings_add(module, section, key, SETTING_TYPE_STRING, &default_value, NULL);
+}
+
+void settings_add_choice_module(const char *module, const char *section,
+ const char *key, int def, const char *choices)
+{
+ SettingValue default_value;
+
+ memset(&default_value, 0, sizeof(default_value));
+ default_value.v_int = def;
+ settings_add(module, section, key, SETTING_TYPE_CHOICE, &default_value, choices);
}
void settings_add_int_module(const char *module, const char *section,
@@ -218,7 +270,7 @@ void settings_add_int_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_int = def;
- settings_add(module, section, key, SETTING_TYPE_INT, &default_value);
+ settings_add(module, section, key, SETTING_TYPE_INT, &default_value, NULL);
}
void settings_add_bool_module(const char *module, const char *section,
@@ -228,8 +280,7 @@ void settings_add_bool_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_bool = def;
- settings_add(module, section, key, SETTING_TYPE_BOOLEAN,
- &default_value);
+ settings_add(module, section, key, SETTING_TYPE_BOOLEAN, &default_value, NULL);
}
void settings_add_time_module(const char *module, const char *section,
@@ -239,7 +290,7 @@ void settings_add_time_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_string = g_strdup(def);
- settings_add(module, section, key, SETTING_TYPE_TIME, &default_value);
+ settings_add(module, section, key, SETTING_TYPE_TIME, &default_value, NULL);
}
void settings_add_level_module(const char *module, const char *section,
@@ -249,7 +300,7 @@ void settings_add_level_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_string = g_strdup(def);
- settings_add(module, section, key, SETTING_TYPE_LEVEL, &default_value);
+ settings_add(module, section, key, SETTING_TYPE_LEVEL, &default_value, NULL);
}
void settings_add_size_module(const char *module, const char *section,
@@ -259,14 +310,16 @@ void settings_add_size_module(const char *module, const char *section,
memset(&default_value, 0, sizeof(default_value));
default_value.v_string = g_strdup(def);
- settings_add(module, section, key, SETTING_TYPE_SIZE, &default_value);
+ settings_add(module, section, key, SETTING_TYPE_SIZE, &default_value, NULL);
}
static void settings_destroy(SETTINGS_REC *rec)
{
if (rec->type != SETTING_TYPE_INT &&
- rec->type != SETTING_TYPE_BOOLEAN)
+ rec->type != SETTING_TYPE_BOOLEAN &&
+ rec->type != SETTING_TYPE_CHOICE)
g_free(rec->default_value.v_string);
+ g_strfreev(rec->choices);
g_free(rec->module);
g_free(rec->section);
g_free(rec->key);
@@ -328,6 +381,24 @@ static CONFIG_NODE *settings_get_node(const char *key)
return iconfig_node_section(node, rec->module, NODE_TYPE_BLOCK);
}
+gboolean settings_set_choice(const char *key, const char *value)
+{
+ SETTINGS_REC *rec;
+
+ rec = settings_get_record(key);
+ /* XXX: The leading/trailing whitespace makes the test fail */
+ if (rec != NULL && g_strv_contains((const char **)rec->choices, value) == FALSE) {
+ char *msg = g_strjoinv(",", rec->choices);
+ g_warning("Invalid value for '%s', must be one of: %s", key, msg);
+ g_free(msg);
+
+ return FALSE;
+ }
+
+ settings_set_str(key, value);
+ return TRUE;
+}
+
void settings_set_str(const char *key, const char *value)
{
iconfig_node_set_str(settings_get_node(key), key, value);
@@ -343,7 +414,7 @@ void settings_set_bool(const char *key, int value)
iconfig_node_set_bool(settings_get_node(key), key, value);
}
-int settings_set_time(const char *key, const char *value)
+gboolean settings_set_time(const char *key, const char *value)
{
int msecs;
@@ -354,7 +425,7 @@ int settings_set_time(const char *key, const char *value)
return TRUE;
}
-int settings_set_level(const char *key, const char *value)
+gboolean settings_set_level(const char *key, const char *value)
{
int iserror;
@@ -366,7 +437,7 @@ int settings_set_level(const char *key, const char *value)
return TRUE;
}
-int settings_set_size(const char *key, const char *value)
+gboolean settings_set_size(const char *key, const char *value)
{
int size;
diff --git a/src/core/settings.h b/src/core/settings.h
index 6f2cf129..d174f250 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -8,6 +8,7 @@ typedef enum {
SETTING_TYPE_TIME,
SETTING_TYPE_LEVEL,
SETTING_TYPE_SIZE,
+ SETTING_TYPE_CHOICE,
SETTING_TYPE_ANY
} SettingType;
@@ -26,6 +27,7 @@ typedef struct {
SettingType type;
SettingValue default_value;
+ char **choices;
} SETTINGS_REC;
/* macros for handling the default Irssi configuration */
@@ -58,6 +60,7 @@ int settings_get_bool(const char *key);
int settings_get_time(const char *key); /* as milliseconds */
int settings_get_level(const char *key);
int settings_get_size(const char *key); /* as bytes */
+int settings_get_choice(const char *key);
char *settings_get_print(SETTINGS_REC *rec);
/* Functions to add/remove settings */
@@ -73,6 +76,8 @@ void settings_add_level_module(const char *module, const char *section,
const char *key, const char *def);
void settings_add_size_module(const char *module, const char *section,
const char *key, const char *def);
+void settings_add_choice_module(const char *module, const char *section,
+ const char *key, int def, const char *choices);
void settings_remove(const char *key);
void settings_remove_module(const char *module);
@@ -88,13 +93,16 @@ void settings_remove_module(const char *module);
settings_add_level_module(MODULE_NAME, section, key, def)
#define settings_add_size(section, key, def) \
settings_add_size_module(MODULE_NAME, section, key, def)
+#define settings_add_choice(section, key, def, choices) \
+ settings_add_choice_module(MODULE_NAME, section, key, def, choices)
void settings_set_str(const char *key, const char *value);
void settings_set_int(const char *key, int value);
void settings_set_bool(const char *key, int value);
-int settings_set_time(const char *key, const char *value);
-int settings_set_level(const char *key, const char *value);
-int settings_set_size(const char *key, const char *value);
+gboolean settings_set_time(const char *key, const char *value);
+gboolean settings_set_level(const char *key, const char *value);
+gboolean settings_set_size(const char *key, const char *value);
+gboolean settings_set_choice(const char *key, const char *value);
/* Get the type (SETTING_TYPE_xxx) of `key' */
SettingType settings_get_type(const char *key);
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 861054b5..0e9982d5 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -690,9 +690,20 @@ static void sig_complete_set(GList **list, WINDOW_REC *window,
else if (*line != '\0' && *word == '\0') {
SETTINGS_REC *rec = settings_get_record(line);
if (rec != NULL) {
- char *value = settings_get_print(rec);
- if (value != NULL)
- *list = g_list_append(*list, value);
+ /* show the whole list of valid options */
+ if (rec->type == SETTING_TYPE_CHOICE) {
+ char **tmp = rec->choices;
+
+ while (*tmp)
+ *list = g_list_append(*list, g_strdup(*tmp++));
+ }
+ /* show the current option */
+ else {
+ char *value = settings_get_print(rec);
+
+ if (value != NULL)
+ *list = g_list_append(*list, value);
+ }
}
}
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index b689cbf9..e25886ec 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -142,6 +142,11 @@ static void cmd_set(char *data)
else
set_int(key, value);
break;
+ case SETTING_TYPE_CHOICE:
+ settings_set_choice(key, clear ? "" :
+ set_default ? rec->choices[rec->default_value.v_int] :
+ value);
+ break;
case SETTING_TYPE_STRING:
settings_set_str(key, clear ? "" :
set_default ? rec->default_value.v_string :
From 86c5e56ef41c70030e43d03b4c01e2df8188c30b Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 12 Jun 2016 16:26:18 +0200
Subject: [PATCH 102/140] Make rejoin_channels_mode of type CHOICE
---
src/irc/core/irc-servers.c | 32 ++++++++------------------------
1 file changed, 8 insertions(+), 24 deletions(-)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 1df95f70..6f5803ed 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -623,39 +623,25 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
GString *chans, *keys;
char *ret;
int use_keys;
- char *rejoin_channels_mode;
+ int rejoin_channels_mode;
g_return_val_if_fail(server != NULL, FALSE);
- rejoin_channels_mode = g_strdup(settings_get_str("rejoin_channels_on_reconnect"));
+ rejoin_channels_mode = settings_get_choice("rejoin_channels_on_reconnect");
- if (rejoin_channels_mode == NULL ||
- (g_ascii_strcasecmp(rejoin_channels_mode, "on") != 0 &&
- g_ascii_strcasecmp(rejoin_channels_mode, "off") != 0 &&
- g_ascii_strcasecmp(rejoin_channels_mode, "auto") != 0)) {
- g_warning("Invalid value for 'rejoin_channels_on_reconnect', valid values are 'on', 'off', 'auto', using 'on' as default value.");
- g_free(rejoin_channels_mode);
- rejoin_channels_mode = g_strdup("on");
- }
+ /* do we want to rejoin channels in the first place? */
+ if(rejoin_channels_mode == 0)
+ return g_strdup("");
chans = g_string_new(NULL);
keys = g_string_new(NULL);
use_keys = FALSE;
- /* do we want to rejoin channels in the first place? */
- if(g_ascii_strcasecmp(rejoin_channels_mode, "off") == 0) {
- g_string_free(chans, TRUE);
- g_string_free(keys, TRUE);
- g_free(rejoin_channels_mode);
- return g_strdup("");
- }
-
/* get currently joined channels */
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet);
- if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
- g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
+ if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
g_string_append_printf(chans, "%s,", channel->name);
g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key);
if (channel->key != NULL)
@@ -668,8 +654,7 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
REJOIN_REC *rec = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag);
- if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) ||
- g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) {
+ if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
g_string_append_printf(chans, "%s,", rec->channel);
g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
rec->key);
@@ -687,7 +672,6 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
ret = chans->str;
g_string_free(chans, FALSE);
g_string_free(keys, TRUE);
- g_free(rejoin_channels_mode);
return ret;
}
@@ -1033,7 +1017,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server)
void irc_servers_init(void)
{
- settings_add_str("servers", "rejoin_channels_on_reconnect", "on");
+ settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off,on,auto");
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
settings_add_str("misc", "split_line_start", "");
settings_add_str("misc", "split_line_end", "");
From 31f12c10df52e44e7cef0245fc55ae38159ce9e3 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 12 Jun 2016 16:38:34 +0200
Subject: [PATCH 103/140] Use strarray_find instead of g_strv_contains
---
src/core/settings.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index 9c2389bc..9871ad30 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -387,7 +387,7 @@ gboolean settings_set_choice(const char *key, const char *value)
rec = settings_get_record(key);
/* XXX: The leading/trailing whitespace makes the test fail */
- if (rec != NULL && g_strv_contains((const char **)rec->choices, value) == FALSE) {
+ if (rec != NULL && strarray_find(rec->choices, value) < 0) {
char *msg = g_strjoinv(",", rec->choices);
g_warning("Invalid value for '%s', must be one of: %s", key, msg);
g_free(msg);
From 7307b48bd6928207ded9e186af3f3b97625f00bb Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 12 Jun 2016 22:58:35 +0200
Subject: [PATCH 104/140] Sort the completion results
Make sure the current option is shown first.
---
src/fe-common/core/completion.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 0e9982d5..c87fdb50 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -690,19 +690,20 @@ static void sig_complete_set(GList **list, WINDOW_REC *window,
else if (*line != '\0' && *word == '\0') {
SETTINGS_REC *rec = settings_get_record(line);
if (rec != NULL) {
+ char *value = settings_get_print(rec);
+
+ /* show the current option first */
+ if (value != NULL)
+ *list = g_list_append(*list, value);
+
/* show the whole list of valid options */
if (rec->type == SETTING_TYPE_CHOICE) {
- char **tmp = rec->choices;
+ char **tmp;
- while (*tmp)
- *list = g_list_append(*list, g_strdup(*tmp++));
- }
- /* show the current option */
- else {
- char *value = settings_get_print(rec);
-
- if (value != NULL)
- *list = g_list_append(*list, value);
+ for (tmp = rec->choices; *tmp; tmp++) {
+ if (g_ascii_strcasecmp(*tmp, value) != 0)
+ *list = g_list_append(*list, g_strdup(*tmp));
+ }
}
}
}
From 6f795f020d5c374023dc9ca647b267aef0a76950 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Sun, 12 Jun 2016 23:39:22 +0200
Subject: [PATCH 105/140] Strip the surrounding whitespace.
---
src/core/settings.c | 2 +-
src/fe-common/core/fe-settings.c | 20 ++++++++++++++++----
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index 9871ad30..8509a9ff 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -386,7 +386,7 @@ gboolean settings_set_choice(const char *key, const char *value)
SETTINGS_REC *rec;
rec = settings_get_record(key);
- /* XXX: The leading/trailing whitespace makes the test fail */
+
if (rec != NULL && strarray_find(rec->choices, value) < 0) {
char *msg = g_strjoinv(",", rec->choices);
g_warning("Invalid value for '%s', must be one of: %s", key, msg);
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index e25886ec..ca1f871d 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -67,6 +67,7 @@ static void set_print_pattern(const char *pattern)
static void set_boolean(const char *key, const char *value)
{
char *stripped_value;
+
stripped_value = g_strdup(value);
g_strstrip(stripped_value);
@@ -79,7 +80,7 @@ static void set_boolean(const char *key, const char *value)
else
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE);
- g_free(stripped_value);
+ g_free(stripped_value);
}
static void set_int(const char *key, const char *value)
@@ -99,6 +100,16 @@ static void set_int(const char *key, const char *value)
settings_set_int(key, (int)longval);
}
+static void set_choice(const char *key, const char *value)
+{
+ char *stripped_value;
+
+ stripped_value = g_strdup(value);
+ g_strstrip(stripped_value);
+ settings_set_choice(key, stripped_value);
+ g_free(stripped_value);
+}
+
/* SYNTAX: SET [-clear | -default] [ []] */
static void cmd_set(char *data)
{
@@ -143,9 +154,10 @@ static void cmd_set(char *data)
set_int(key, value);
break;
case SETTING_TYPE_CHOICE:
- settings_set_choice(key, clear ? "" :
- set_default ? rec->choices[rec->default_value.v_int] :
- value);
+ if (clear || set_default)
+ settings_set_choice(key, rec->choices[rec->default_value.v_int]);
+ else
+ set_choice(key, value);
break;
case SETTING_TYPE_STRING:
settings_set_str(key, clear ? "" :
From 9ea155f8df5fe9b3d67e8729f611b87a0c2a82c9 Mon Sep 17 00:00:00 2001
From: dequis
Date: Sun, 12 Jun 2016 20:28:06 -0300
Subject: [PATCH 106/140] servers-reconnect: pass unix_socket attribute to new
connection
Trying to /reconnect unix sockets turned them into inet.
---
src/core/servers-reconnect.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c
index f419035b..58c9dd09 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -190,6 +190,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
dest->away_reason = g_strdup(src->away_reason);
dest->no_autojoin_channels = src->no_autojoin_channels;
dest->no_autosendcmd = src->no_autosendcmd;
+ dest->unix_socket = src->unix_socket;
dest->use_ssl = src->use_ssl;
dest->ssl_cert = g_strdup(src->ssl_cert);
From 9a30ab53df226acb4586a2f214f3994a7b8b32ea Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 13 Jun 2016 14:03:00 +0200
Subject: [PATCH 107/140] Move the validation of the CHOICE setting value
Also, use a FORMAT to show the error message.
---
src/core/settings.c | 8 ++------
src/fe-common/core/fe-settings.c | 10 +++++++++-
src/fe-common/core/module-formats.c | 1 +
src/fe-common/core/module-formats.h | 1 +
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index 8509a9ff..0716103a 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -387,15 +387,11 @@ gboolean settings_set_choice(const char *key, const char *value)
rec = settings_get_record(key);
- if (rec != NULL && strarray_find(rec->choices, value) < 0) {
- char *msg = g_strjoinv(",", rec->choices);
- g_warning("Invalid value for '%s', must be one of: %s", key, msg);
- g_free(msg);
-
+ if (rec != NULL && strarray_find(rec->choices, value) < 0)
return FALSE;
- }
settings_set_str(key, value);
+
return TRUE;
}
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index ca1f871d..6f69d930 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -106,7 +106,15 @@ static void set_choice(const char *key, const char *value)
stripped_value = g_strdup(value);
g_strstrip(stripped_value);
- settings_set_choice(key, stripped_value);
+
+ if (settings_set_choice(key, stripped_value) == FALSE) {
+ SETTINGS_REC *rec = settings_get_record(key);
+ char *msg = g_strjoinv(",", rec->choices);
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_CHOICE, msg);
+ g_free(msg);
+ }
+
g_free(stripped_value);
}
diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c
index b897b0c6..5c07f14c 100644
--- a/src/fe-common/core/module-formats.c
+++ b/src/fe-common/core/module-formats.c
@@ -221,6 +221,7 @@ FORMAT_REC fecommon_core_formats[] = {
{ "invalid_level", "Invalid message level", 0 },
{ "invalid_size", "Invalid size", 0 },
{ "invalid_charset", "Invalid charset: $0", 1, { 0 } },
+ { "invalid_choice", "Invalid choice, must be one of $0", 1, { 0 } },
{ "eval_max_recurse", "/eval hit maximum recursion limit", 0 },
{ "program_not_found", "Could not find file or file is not executable", 0 },
{ "no_server_defined", "No servers defined for this network, see /help server for how to add one", 0 },
diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h
index de1e13f2..2b45ff6b 100644
--- a/src/fe-common/core/module-formats.h
+++ b/src/fe-common/core/module-formats.h
@@ -190,6 +190,7 @@ enum {
TXT_INVALID_LEVEL,
TXT_INVALID_SIZE,
TXT_INVALID_CHARSET,
+ TXT_INVALID_CHOICE,
TXT_EVAL_MAX_RECURSE,
TXT_PROGRAM_NOT_FOUND,
TXT_NO_SERVER_DEFINED,
From 439e21f12746519d36e205a3ac053c882d67c024 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 13 Jun 2016 14:07:04 +0200
Subject: [PATCH 108/140] Use ; as separator instead of ,
---
src/core/settings.c | 2 +-
src/irc/core/irc-servers.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index 0716103a..e6b5d16f 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -210,7 +210,7 @@ static void settings_add(const char *module, const char *section,
return;
}
- choices_vec = g_strsplit(choices, ",", -1);
+ choices_vec = g_strsplit(choices, ";", -1);
/* validate the default value */
if (default_value->v_int < 0 || default_value->v_int >= g_strv_length(choices_vec)) {
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 6f5803ed..c8ba0a48 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -1017,7 +1017,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server)
void irc_servers_init(void)
{
- settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off,on,auto");
+ settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off;on;auto");
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
settings_add_str("misc", "split_line_start", "");
settings_add_str("misc", "split_line_end", "");
From 5c8423a08cd9ffbe3363f3b0e5722e4a32157914 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 13 Jun 2016 20:27:37 +0200
Subject: [PATCH 109/140] Add a space after the comma when listing the options.
---
src/fe-common/core/fe-settings.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 6f69d930..abbd45a8 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -109,7 +109,7 @@ static void set_choice(const char *key, const char *value)
if (settings_set_choice(key, stripped_value) == FALSE) {
SETTINGS_REC *rec = settings_get_record(key);
- char *msg = g_strjoinv(",", rec->choices);
+ char *msg = g_strjoinv(", ", rec->choices);
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_CHOICE, msg);
g_free(msg);
From 78c1c1518a7382628368b09f8744189edf3ceef3 Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 6 Jun 2016 22:25:32 +0200
Subject: [PATCH 110/140] Be smart about case-matching the nicks.
If the prefix contains an uppercase letter then don't use the
case-insensitive search functions.
---
src/fe-common/core/chat-completion.c | 38 +++++++++++++++++++++-------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c
index c37c77cd..b212de5f 100644
--- a/src/fe-common/core/chat-completion.c
+++ b/src/fe-common/core/chat-completion.c
@@ -52,6 +52,18 @@ static int completion_auto, completion_strict;
last_msg_add(&((MODULE_CHANNEL_REC *) MODULE_DATA(channel))->lastmsgs, \
nick, own, keep_publics_count)
+static int contains_uppercase(const char *s1)
+{
+ const char *ch;
+
+ for (ch = s1; *ch != '\0'; ch++) {
+ if (g_ascii_isupper(*ch))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static LAST_MSG_REC *last_msg_find(GSList *list, const char *nick)
{
while (list != NULL) {
@@ -336,7 +348,8 @@ GList *completion_msg(SERVER_REC *win_server,
}
static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel,
- const char *nick, const char *suffix)
+ const char *nick, const char *suffix,
+ const int match_case)
{
MODULE_CHANNEL_REC *mchannel;
GSList *tmp;
@@ -352,8 +365,10 @@ static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel,
for (tmp = mchannel->lastmsgs; tmp != NULL; tmp = tmp->next) {
LAST_MSG_REC *rec = tmp->data;
- if (g_ascii_strncasecmp(rec->nick, nick, len) == 0 &&
- glist_find_icase_string(*outlist, rec->nick) == NULL) {
+ if ((match_case? strncmp(rec->nick, nick, len)
+ : g_ascii_strncasecmp(rec->nick, nick, len)) == 0 &&
+ (match_case? glist_find_string(*outlist, rec->nick)
+ : glist_find_icase_string(*outlist, rec->nick)) == NULL) {
str = g_strconcat(rec->nick, suffix, NULL);
if (completion_lowercase) ascii_strdown(str);
if (rec->own)
@@ -368,7 +383,8 @@ static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel,
static GList *completion_nicks_nonstrict(CHANNEL_REC *channel,
const char *nick,
- const char *suffix)
+ const char *suffix,
+ const int match_case)
{
GSList *nicks, *tmp;
GList *list;
@@ -404,7 +420,8 @@ static GList *completion_nicks_nonstrict(CHANNEL_REC *channel,
*out = '\0';
/* add to list if 'cleaned' nick matches */
- if (g_ascii_strncasecmp(str, nick, len) == 0) {
+ if ((match_case? strncmp(str, nick, len)
+ : g_ascii_strncasecmp(str, nick, len)) == 0) {
tnick = g_strconcat(rec->nick, suffix, NULL);
if (completion_lowercase)
ascii_strdown(tnick);
@@ -428,7 +445,7 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
GSList *nicks, *tmp;
GList *list;
char *str;
- int len;
+ int len, match_case;
g_return_val_if_fail(channel != NULL, NULL);
g_return_val_if_fail(nick != NULL, NULL);
@@ -437,9 +454,11 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
if (suffix != NULL && *suffix == '\0')
suffix = NULL;
+ match_case = contains_uppercase(nick);
+
/* put first the nicks who have recently said something */
list = NULL;
- complete_from_nicklist(&list, channel, nick, suffix);
+ complete_from_nicklist(&list, channel, nick, suffix, match_case);
/* and add the rest of the nicks too */
len = strlen(nick);
@@ -447,7 +466,8 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
NICK_REC *rec = tmp->data;
- if (g_ascii_strncasecmp(rec->nick, nick, len) == 0 &&
+ if ((match_case? strncmp(rec->nick, nick, len)
+ : g_ascii_strncasecmp(rec->nick, nick, len)) == 0 &&
rec != channel->ownnick) {
str = g_strconcat(rec->nick, suffix, NULL);
if (completion_lowercase)
@@ -463,7 +483,7 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
/* remove non alphanum chars from nick and search again in case
list is still NULL ("foo" would match "_foo_" f.e.) */
if (!completion_strict)
- list = g_list_concat(list, completion_nicks_nonstrict(channel, nick, suffix));
+ list = g_list_concat(list, completion_nicks_nonstrict(channel, nick, suffix, match_case));
return list;
}
From 862729d7a39be25aee3524a52e19f9735dec6e1f Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Tue, 7 Jun 2016 15:45:39 +0200
Subject: [PATCH 111/140] Add a completion_match_case setting.
---
src/fe-common/core/chat-completion.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c
index b212de5f..3e144602 100644
--- a/src/fe-common/core/chat-completion.c
+++ b/src/fe-common/core/chat-completion.c
@@ -38,11 +38,18 @@
#include "chat-completion.h"
#include "window-items.h"
+enum {
+ COMPLETE_MCASE_NEVER = 0,
+ COMPLETE_MCASE_ALWAYS,
+ COMPLETE_MCASE_AUTO,
+};
+
static int keep_privates_count, keep_publics_count;
static int completion_lowercase;
static char *completion_char, *cmdchars;
static GSList *global_lastmsgs;
static int completion_auto, completion_strict;
+static int completion_match_case;
#define SERVER_LAST_MSG_ADD(server, nick) \
last_msg_add(&((MODULE_SERVER_REC *) MODULE_DATA(server))->lastmsgs, \
@@ -52,7 +59,7 @@ static int completion_auto, completion_strict;
last_msg_add(&((MODULE_CHANNEL_REC *) MODULE_DATA(channel))->lastmsgs, \
nick, own, keep_publics_count)
-static int contains_uppercase(const char *s1)
+static gboolean contains_uppercase(const char *s1)
{
const char *ch;
@@ -454,7 +461,8 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
if (suffix != NULL && *suffix == '\0')
suffix = NULL;
- match_case = contains_uppercase(nick);
+ match_case = completion_match_case == COMPLETE_MCASE_ALWAYS ||
+ (completion_match_case == COMPLETE_MCASE_AUTO && contains_uppercase(nick));
/* put first the nicks who have recently said something */
list = NULL;
@@ -1150,6 +1158,8 @@ static void read_settings(void)
completion_auto = settings_get_bool("completion_auto");
completion_strict = settings_get_bool("completion_strict");
+ completion_match_case = settings_get_choice("completion_nicks_match_case");
+
g_free_not_null(completion_char);
completion_char = g_strdup(settings_get_str("completion_char"));
@@ -1170,6 +1180,7 @@ void chat_completion_init(void)
settings_add_int("completion", "completion_keep_privates", 10);
settings_add_bool("completion", "completion_nicks_lowercase", FALSE);
settings_add_bool("completion", "completion_strict", FALSE);
+ settings_add_choice("completion", "completion_nicks_match_case", COMPLETE_MCASE_AUTO, "never;always;auto");
settings_add_bool("lookandfeel", "expand_escapes", FALSE);
From 2da49e3ca6357b65e31fb494b2edb0d22e73c62c Mon Sep 17 00:00:00 2001
From: LemonBoy
Date: Mon, 13 Jun 2016 22:14:08 +0200
Subject: [PATCH 112/140] Don't crash when the key isn't found.
---
src/core/settings.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/core/settings.c b/src/core/settings.c
index e6b5d16f..1242293d 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -153,7 +153,7 @@ int settings_get_choice(const char *key)
SETTINGS_REC *rec;
CONFIG_NODE *node;
char *str;
- int idx;
+ int index;
rec = settings_get(key, SETTING_TYPE_CHOICE);
if (rec == NULL) return -1;
@@ -164,8 +164,10 @@ int settings_get_choice(const char *key)
str = node == NULL ? rec->default_value.v_string :
config_node_get_str(node, key, rec->default_value.v_string);
- idx = strarray_find(rec->choices, str);
- return (idx < 0) ? rec->default_value.v_int : idx;
+ if (str == NULL || (index = strarray_find(rec->choices, str)) < 0)
+ return rec->default_value.v_int;
+
+ return index;
}
char *settings_get_print(SETTINGS_REC *rec)
From 77ad62fadbcd9d5ce33889417de0099e035d8ddc Mon Sep 17 00:00:00 2001
From: ailin-nemui
Date: Thu, 16 Jun 2016 21:30:46 +0200
Subject: [PATCH 113/140] completion fixes
---
src/fe-common/core/completion.c | 56 ++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index c87fdb50..46fd9db7 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -37,8 +37,11 @@ static int last_want_space, last_line_pos;
#define isseparator_notspace(c) \
((c) == ',')
+#define isseparator_space(c) \
+ ((c) == ' ')
+
#define isseparator(c) \
- ((c) == ' ' || isseparator_notspace(c))
+ (isseparator_space(c) || isseparator_notspace(c))
void chat_completion_init(void);
void chat_completion_deinit(void);
@@ -153,20 +156,23 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i
word = NULL;
linestart = NULL;
} else {
+ char* old_wordstart;
+
/* get the word we want to complete */
word = get_word_at(line, *pos, &wordstart);
+ old_wordstart = wordstart;
+
startpos = (int) (wordstart-line);
wordlen = strlen(word);
- /* get the start of line until the word we're completing */
- if (isseparator(*line)) {
- /* empty space at the start of line */
- if (wordstart == line)
- wordstart += strlen(wordstart);
- } else {
- while (wordstart > line && isseparator(wordstart[-1]))
- wordstart--;
- }
+ /* remove trailing spaces from linestart */
+ while (wordstart > line && isseparator_space(wordstart[-1]))
+ wordstart--;
+
+ /* unless everything was spaces */
+ if (old_wordstart > line && wordstart == line)
+ wordstart = old_wordstart - 1;
+
linestart = g_strndup(line, (int) (wordstart-line));
/* completions usually add space after the word, that makes
@@ -175,19 +181,24 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i
BUT if we start completion with "/msg ", we don't
want to complete the /msg word, but instead complete empty
word with /msg being in linestart. */
- if (!erase && *pos > 0 && line[*pos-1] == ' ' &&
- (*linestart == '\0' || wordstart[-1] != ' ')) {
+ if (!erase && *pos > 0 && isseparator_space(line[*pos-1]) &&
+ (*linestart == '\0' || !isseparator_space(wordstart[-1]))) {
char *old;
- old = linestart;
+ old = linestart;
linestart = *linestart == '\0' ?
g_strdup(word) :
- g_strconcat(linestart, " ", word, NULL);
+ g_strdup_printf("%s%c%s",
+ /* do not accidentally duplicate the word separator */
+ line == wordstart - 1 ? "" : linestart,
+ wordstart[-1], word);
g_free(old);
g_free(word);
word = g_strdup("");
- startpos = strlen(linestart)+1;
+
+ startpos = *linestart == '\0' ? 0 :
+ strlen(linestart)+1;
wordlen = 0;
}
@@ -397,7 +408,8 @@ static GList *completion_get_aliases(const char *alias, char cmdchar)
continue;
if (g_ascii_strncasecmp(node->key, alias, len) == 0) {
- word = g_strdup_printf("%c%s", cmdchar, node->key);
+ word = cmdchar == '\0' ? g_strdup(node->key) :
+ g_strdup_printf("%c%s", cmdchar, node->key);
/* add matching alias to completion list, aliases will
be appended after command completions and kept in
uppercase to show it's an alias */
@@ -589,13 +601,19 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
/* command completion? */
cmdchars = settings_get_str("cmdchars");
- if (*word != '\0' && *linestart == '\0' && strchr(cmdchars, *word)) {
+ if (*word != '\0' && ((*linestart == '\0' && strchr(cmdchars, *word)) ||
+ (*linestart != '\0' && linestart[1] == '\0' &&
+ strchr(cmdchars, *linestart)))) {
+ gboolean skip = *linestart == '\0' ? TRUE : FALSE;
+
/* complete /command */
- *list = completion_get_commands(word+1, *word);
+ *list = completion_get_commands(word + (skip ? 1 : 0),
+ skip ? *word : '\0');
/* complete aliases, too */
*list = g_list_concat(*list,
- completion_get_aliases(word+1, *word));
+ completion_get_aliases(word + (skip ? 1 : 0),
+ skip ? *word : '\0'));
if (*list != NULL) signal_stop();
return;
From 92a2384ab06c542c8f6a3d0f80a54892d74dc649 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sat, 18 Jun 2016 17:51:58 +0200
Subject: [PATCH 114/140] Add /channel modify
---
src/fe-common/core/fe-channels.c | 38 +++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c
index 046d641a..fe8e4807 100644
--- a/src/fe-common/core/fe-channels.c
+++ b/src/fe-common/core/fe-channels.c
@@ -246,9 +246,7 @@ static void cmd_channel(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
}
}
-/* SYNTAX: CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ]
- [] */
-static void cmd_channel_add(const char *data)
+static void cmd_channel_add_modify(const char *data, gboolean add)
{
GHashTable *optlist;
CHATNET_REC *chatnetrec;
@@ -257,18 +255,19 @@ static void cmd_channel_add(const char *data)
void *free_arg;
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
- "channel add", &optlist, &channel, &chatnet, &password))
+ "channel add", &optlist, &channel, &chatnet, &password))
return;
- if (*chatnet == '\0' || *channel == '\0')
+ if (*chatnet == '\0' || *channel == '\0') {
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+ }
chatnetrec = chatnet_find(chatnet);
if (chatnetrec == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- TXT_UNKNOWN_CHATNET, chatnet);
+ TXT_UNKNOWN_CHATNET, chatnet);
cmd_params_free(free_arg);
- return;
+ return;
}
botarg = g_hash_table_lookup(optlist, "bots");
@@ -276,10 +275,17 @@ static void cmd_channel_add(const char *data)
rec = channel_setup_find(channel, chatnet);
if (rec == NULL) {
+ if (!add) {
+ cmd_params_free(free_arg);
+ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ TXT_CHANSETUP_NOT_FOUND, channel, chatnet);
+ return;
+ }
+
rec = CHAT_PROTOCOL(chatnetrec)->create_channel_setup();
rec->name = g_strdup(channel);
rec->chatnet = g_strdup(chatnet);
- } else {
+ } else if (!add) {
if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks);
if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd);
if (*password != '\0') g_free_and_null(rec->password);
@@ -299,6 +305,20 @@ static void cmd_channel_add(const char *data)
cmd_params_free(free_arg);
}
+/* SYNTAX: CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ]
+ [] */
+static void cmd_channel_add(const char *data)
+{
+ cmd_channel_add_modify(data, 1);
+}
+
+/* SYNTAX: CHANNEL MODIFY [-auto | -noauto] [-bots ] [-botcmd ]
+ [] */
+static void cmd_channel_modify(const char *data)
+{
+ cmd_channel_add_modify(data, 0);
+}
+
/* SYNTAX: CHANNEL REMOVE */
static void cmd_channel_remove(const char *data)
{
@@ -622,6 +642,7 @@ void fe_channels_init(void)
command_bind("join", NULL, (SIGNAL_FUNC) cmd_join);
command_bind("channel", NULL, (SIGNAL_FUNC) cmd_channel);
command_bind("channel add", NULL, (SIGNAL_FUNC) cmd_channel_add);
+ command_bind("channel modify", NULL, (SIGNAL_FUNC) cmd_channel_modify);
command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove);
command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list);
command_bind("names", NULL, (SIGNAL_FUNC) cmd_names);
@@ -643,6 +664,7 @@ void fe_channels_deinit(void)
command_unbind("join", (SIGNAL_FUNC) cmd_join);
command_unbind("channel", (SIGNAL_FUNC) cmd_channel);
command_unbind("channel add", (SIGNAL_FUNC) cmd_channel_add);
+ command_unbind("channel modify", (SIGNAL_FUNC) cmd_channel_modify);
command_unbind("channel remove", (SIGNAL_FUNC) cmd_channel_remove);
command_unbind("channel list", (SIGNAL_FUNC) cmd_channel_list);
command_unbind("names", (SIGNAL_FUNC) cmd_names);
From 1dd1dde1d46439dac17bb7f053f2665ed31a4a5e Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sat, 18 Jun 2016 17:52:26 +0200
Subject: [PATCH 115/140] Add /server modify
---
src/fe-common/core/fe-server.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c
index 429e6dac..f3792b47 100644
--- a/src/fe-common/core/fe-server.c
+++ b/src/fe-common/core/fe-server.c
@@ -104,7 +104,7 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist)
return server;
}
-static void cmd_server_add(const char *data)
+static void cmd_server_add_modify(const char *data, gboolean add)
{
GHashTable *optlist;
SERVER_SETUP_REC *rec;
@@ -113,7 +113,7 @@ static void cmd_server_add(const char *data)
int port;
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
- "server add", &optlist, &addr, &portstr, &password))
+ "server add", &optlist, &addr, &portstr, &password))
return;
if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -124,6 +124,13 @@ static void cmd_server_add(const char *data)
rec = server_setup_find(addr, port, chatnet);
if (rec == NULL) {
+ if (!add) {
+ cmd_params_free(free_arg);
+ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ TXT_SETUPSERVER_NOT_FOUND, addr, port);
+ return;
+ }
+
rec = create_server_setup(optlist);
if (rec == NULL) {
cmd_params_free(free_arg);
@@ -131,7 +138,7 @@ static void cmd_server_add(const char *data)
}
rec->address = g_strdup(addr);
rec->port = port;
- } else {
+ } else if (!add) {
value = g_hash_table_lookup(optlist, "port");
if (value != NULL && *value != '\0') rec->port = atoi(value);
@@ -205,6 +212,16 @@ static void cmd_server_add(const char *data)
cmd_params_free(free_arg);
}
+static void cmd_server_add(const char *data)
+{
+ cmd_server_add_modify(data, 1);
+}
+
+static void cmd_server_modify(const char *data)
+{
+ cmd_server_add_modify(data, 0);
+}
+
/* SYNTAX: SERVER REMOVE [] [] */
static void cmd_server_remove(const char *data)
{
@@ -388,6 +405,7 @@ void fe_server_init(void)
command_bind("server", NULL, (SIGNAL_FUNC) cmd_server);
command_bind("server connect", NULL, (SIGNAL_FUNC) cmd_server_connect);
command_bind("server add", NULL, (SIGNAL_FUNC) cmd_server_add);
+ command_bind("server modify", NULL, (SIGNAL_FUNC) cmd_server_modify);
command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove);
command_bind_first("server", NULL, (SIGNAL_FUNC) server_command);
command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command);
@@ -412,6 +430,7 @@ void fe_server_deinit(void)
command_unbind("server", (SIGNAL_FUNC) cmd_server);
command_unbind("server connect", (SIGNAL_FUNC) cmd_server_connect);
command_unbind("server add", (SIGNAL_FUNC) cmd_server_add);
+ command_unbind("server modify", (SIGNAL_FUNC) cmd_server_modify);
command_unbind("server remove", (SIGNAL_FUNC) cmd_server_remove);
command_unbind("server", (SIGNAL_FUNC) server_command);
command_unbind("disconnect", (SIGNAL_FUNC) server_command);
From 421288cf5066267b60580af2b6ae511c46570bf0 Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sat, 18 Jun 2016 17:52:47 +0200
Subject: [PATCH 116/140] Add /network modify
---
src/fe-common/irc/fe-ircnet.c | 47 +++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 4d7037d5..90697bba 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -88,14 +88,7 @@ static void cmd_network_list(void)
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NETWORK_FOOTER);
}
-/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ]
- [-host ] [-usermode ] [-autosendcmd ]
- [-querychans ] [-whois ] [-msgs ]
- [-kicks ] [-modes ] [-cmdspeed ]
- [-cmdmax ] [-sasl_mechanism ]
- [-sasl_username ] [-sasl_password ]
- */
-static void cmd_network_add(const char *data)
+static void cmd_network_add_modify(const char *data, gboolean add)
{
GHashTable *optlist;
char *name, *value;
@@ -103,15 +96,23 @@ static void cmd_network_add(const char *data)
IRC_CHATNET_REC *rec;
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
- "network add", &optlist, &name))
+ "network add", &optlist, &name))
return;
+
if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
rec = ircnet_find(name);
if (rec == NULL) {
+ if (!add) {
+ cmd_params_free(free_arg);
+ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ IRCTXT_NETWORK_NOT_FOUND, name);
+ return;
+ }
+
rec = g_new0(IRC_CHATNET_REC, 1);
rec->name = g_strdup(name);
- } else {
+ } else if (!add) {
if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick);
if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username);
if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
@@ -174,6 +175,30 @@ static void cmd_network_add(const char *data)
cmd_params_free(free_arg);
}
+/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ]
+ [-host ] [-usermode ] [-autosendcmd ]
+ [-querychans ] [-whois ] [-msgs ]
+ [-kicks ] [-modes ] [-cmdspeed ]
+ [-cmdmax ] [-sasl_mechanism ]
+ [-sasl_username ] [-sasl_password ]
+ */
+static void cmd_network_add(const char *data)
+{
+ cmd_network_add_modify(data, 1);
+}
+
+/* SYNTAX: NETWORK MODIFY [-nick ] [-user ] [-realname ]
+ [-host ] [-usermode ] [-autosendcmd ]
+ [-querychans ] [-whois ] [-msgs ]
+ [-kicks ] [-modes ] [-cmdspeed ]
+ [-cmdmax ] [-sasl_mechanism ]
+ [-sasl_username ] [-sasl_password ]
+ */
+static void cmd_network_modify(const char *data)
+{
+ cmd_network_add_modify(data, 0);
+}
+
/* SYNTAX: NETWORK REMOVE */
static void cmd_network_remove(const char *data)
{
@@ -206,6 +231,7 @@ void fe_ircnet_init(void)
command_bind("network", NULL, (SIGNAL_FUNC) cmd_network);
command_bind("network list", NULL, (SIGNAL_FUNC) cmd_network_list);
command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add);
+ command_bind("network modify", NULL, (SIGNAL_FUNC) cmd_network_modify);
command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove);
command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed "
@@ -218,5 +244,6 @@ void fe_ircnet_deinit(void)
command_unbind("network", (SIGNAL_FUNC) cmd_network);
command_unbind("network list", (SIGNAL_FUNC) cmd_network_list);
command_unbind("network add", (SIGNAL_FUNC) cmd_network_add);
+ command_unbind("network modify", (SIGNAL_FUNC) cmd_network_modify);
command_unbind("network remove", (SIGNAL_FUNC) cmd_network_remove);
}
From 1d2113a6387d70caa399cb3311b15203d2d99fda Mon Sep 17 00:00:00 2001
From: Jari Matilainen
Date: Sat, 18 Jun 2016 17:53:35 +0200
Subject: [PATCH 117/140] Add /server modify SYNTAX
---
src/fe-common/irc/fe-irc-server.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c
index 2cb99a2f..360fe212 100644
--- a/src/fe-common/irc/fe-irc-server.c
+++ b/src/fe-common/irc/fe-irc-server.c
@@ -50,12 +50,19 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target)
return target;
}
+
/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ]
[-ssl_verify] [-ssl_cafile ] [-ssl_capath ]
[-ssl_ciphers ]
[-auto | -noauto] [-network ] [-host ]
[-cmdspeed ] [-cmdmax ] [-port ]
[ []] */
+/* SYNTAX: SERVER MODIFY [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ]
+ [-ssl_verify] [-ssl_cafile ] [-ssl_capath ]
+ [-ssl_ciphers ]
+ [-auto | -noauto] [-network ] [-host ]
+ [-cmdspeed ] [-cmdmax