diff --git a/.gitignore b/.gitignore index 0b15f43e..945b6cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ ltversion.m4 lt~obsolete.m4 pm_to_blib stamp-h1 +MYMETA.* docs/help/Makefile.am docs/help/[a-z]* 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/docs/help/in/dcc.in b/docs/help/in/dcc.in index c348b1ae..649cb12b 100644 --- a/docs/help/in/dcc.in +++ b/docs/help/in/dcc.in @@ -38,8 +38,8 @@ /DCC CHAT mike /DCC GET bob 'summer vacation.mkv' /DCC SEND sarah documents/resume.pdf - /DCC CLOSE mike - /DCC CLOSE bob 'summer vacation.mkv' + /DCC CLOSE get mike + /DCC CLOSE send bob 'summer vacation.mkv' %9See also:%9 CD diff --git a/src/common.h b/src/common.h index 86a079fe..0cf951b3 100644 --- a/src/common.h +++ b/src/common.h @@ -34,9 +34,6 @@ # include #endif #include -#ifdef WIN32 -# include -#endif #include #ifdef HAVE_GMODULE diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c index 2902ef8e..4966d77d 100644 --- a/src/core/channels-setup.c +++ b/src/core/channels-setup.c @@ -30,17 +30,36 @@ GSList *setupchannels; +static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel) +{ + char *name, *chatnet; + + name = config_node_get_str(node, "name", NULL); + chatnet = config_node_get_str(node, "chatnet", NULL); + + if (g_strcmp0(name, channel->name) != 0 || + g_strcmp0(chatnet, channel->chatnet) != 0) + return 1; + + return 0; +} + static void channel_setup_save(CHANNEL_SETUP_REC *channel) { - CONFIG_NODE *parentnode, *node; - int index; + CONFIG_NODE *parent_node, *node; + GSList *config_node; - index = g_slist_index(setupchannels, channel); + parent_node = iconfig_node_traverse("(channels", TRUE); - parentnode = iconfig_node_traverse("(channels", TRUE); - node = config_node_nth(parentnode, index); - if (node == NULL) - node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + /* Try to find this channel in the configuration */ + config_node = g_slist_find_custom(parent_node->value, channel, + (GCompareFunc)compare_channel_setup); + if (config_node != NULL) + /* Let's update this channel record */ + node = config_node->data; + else + /* Create a brand-new channel record */ + node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK); iconfig_node_clear(node); iconfig_node_set_str(node, "name", channel->name); @@ -65,10 +84,21 @@ void channel_setup_create(CHANNEL_SETUP_REC *channel) static void channel_config_remove(CHANNEL_SETUP_REC *channel) { - CONFIG_NODE *node; + CONFIG_NODE *parent_node; + GSList *config_node; - node = iconfig_node_traverse("channels", FALSE); - if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel)); + parent_node = iconfig_node_traverse("channels", FALSE); + + if (parent_node == NULL) + return; + + /* Try to find this channel in the configuration */ + config_node = g_slist_find_custom(parent_node->value, channel, + (GCompareFunc)compare_channel_setup); + + if (config_node != NULL) + /* Delete the channel from the configuration */ + iconfig_node_remove(parent_node, config_node->data); } static void channel_setup_destroy(CHANNEL_SETUP_REC *channel) diff --git a/src/core/commands.c b/src/core/commands.c index 9e451bc8..88d1208c 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -748,6 +748,11 @@ int cmd_get_params(const char *data, gpointer *free_me, int count, ...) if (cnt == 0 && count & PARAM_FLAG_GETREST) { /* get rest */ arg = datad; + + /* strip the trailing whitespace */ + if (count & PARAM_FLAG_STRIP_TRAILING_WS) { + arg = g_strchomp(arg); + } } else { arg = (count & PARAM_FLAG_NOQUOTES) ? cmd_get_param(&datad) : diff --git a/src/core/commands.h b/src/core/commands.h index d65185e5..72105ad3 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -152,6 +152,8 @@ int command_have_option(const char *cmd, const char *option); #define PARAM_FLAG_OPTCHAN 0x00010000 /* optional channel in first argument, but don't treat "*" as current channel */ #define PARAM_FLAG_OPTCHAN_NAME (0x00020000|PARAM_FLAG_OPTCHAN) +/* strip the trailing whitespace */ +#define PARAM_FLAG_STRIP_TRAILING_WS 0x00040000 char *cmd_get_param(char **data); char *cmd_get_quoted_param(char **data); diff --git a/src/core/core.c b/src/core/core.c index bbeec6f4..bf7cdd6b 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -83,7 +83,6 @@ static void sig_reload_config(int signo) static void read_settings(void) { -#ifndef WIN32 static int signals[] = { SIGINT, SIGQUIT, SIGTERM, SIGALRM, SIGUSR1, SIGUSR2 @@ -124,7 +123,6 @@ static void read_settings(void) settings_set_bool("override_coredump_limit", FALSE); } #endif -#endif } static void sig_gui_dialog(const char *type, const char *text) @@ -225,9 +223,7 @@ void core_init(void) client_start_time = time(NULL); modules_init(); -#ifndef WIN32 pidwait_init(); -#endif net_disconnect_init(); signals_init(); @@ -303,9 +299,7 @@ void core_deinit(void) signals_deinit(); net_disconnect_deinit(); -#ifndef WIN32 pidwait_deinit(); -#endif modules_deinit(); g_free(irssi_dir); diff --git a/src/core/ignore.c b/src/core/ignore.c index e70b741b..fd3c8a38 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -97,8 +97,8 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) match_wildcards((rec)->mask, nick))) #define ignore_match_server(rec, server) \ - ((rec)->servertag == NULL || \ - g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0) + ((rec)->servertag == NULL || ((server) != NULL && \ + g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0)) #define ignore_match_channel(rec, channel) \ ((rec)->channels == NULL || ((channel) != NULL && \ @@ -135,7 +135,6 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, char *nickmask; int len, best_mask, best_match, best_patt; - g_return_val_if_fail(server != NULL, 0); if (nick == NULL) nick = ""; chanrec = server == NULL || channel == NULL ? NULL : diff --git a/src/core/misc.c b/src/core/misc.c index 490b5a8f..aaa470f5 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -430,11 +430,7 @@ int mkpath(const char *path, int mode) dir = g_strndup(path, (int) (p-path)); if (stat(dir, &statbuf) != 0) { -#ifndef WIN32 if (mkdir(dir, mode) == -1) -#else - if (_mkdir(dir) == -1) -#endif { g_free(dir); return -1; diff --git a/src/core/net-disconnect.c b/src/core/net-disconnect.c index 321f79ac..6476e776 100644 --- a/src/core/net-disconnect.c +++ b/src/core/net-disconnect.c @@ -116,7 +116,6 @@ void net_disconnect_init(void) void net_disconnect_deinit(void) { -#ifndef WIN32 NET_DISCONNECT_REC *rec; time_t now, max; int first, fd; @@ -155,5 +154,4 @@ void net_disconnect_deinit(void) first = 0; } } -#endif } diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index e637e673..d6e767b6 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -77,14 +77,11 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, { RESOLVED_IP_REC rec; const char *errorstr; -#ifndef WIN32 int pid; -#endif int len; g_return_val_if_fail(addr != NULL, FALSE); -#ifndef WIN32 pid = fork(); if (pid > 0) { /* parent */ @@ -97,7 +94,6 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, g_warning("net_connect_thread(): fork() failed! " "Using blocking resolving"); } -#endif /* child */ srand(time(NULL)); @@ -138,10 +134,8 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, } } -#ifndef WIN32 if (pid == 0) _exit(99); -#endif /* we used blocking lookup */ return 0; @@ -157,9 +151,7 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) rec->host4 = NULL; rec->host6 = NULL; -#ifndef WIN32 fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK); -#endif /* get ip+error */ if (g_io_channel_read_block(pipe, rec, sizeof(*rec)) == -1) { @@ -201,9 +193,7 @@ void net_disconnect_nonblock(int pid) { g_return_if_fail(pid > 0); -#ifndef WIN32 kill(pid, SIGKILL); -#endif } static void simple_init(SIMPLE_THREAD_REC *rec, GIOChannel *handle) diff --git a/src/core/net-sendbuffer.c b/src/core/net-sendbuffer.c index 39257486..97fb551f 100644 --- a/src/core/net-sendbuffer.c +++ b/src/core/net-sendbuffer.c @@ -160,13 +160,9 @@ void net_sendbuffer_flush(NET_SENDBUF_REC *rec) /* set the socket blocking while doing this */ handle = g_io_channel_unix_get_fd(rec->handle); -#ifndef WIN32 fcntl(handle, F_SETFL, 0); -#endif while (!buffer_send(rec)) ; -#ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); -#endif } /* Returns the socket handle */ diff --git a/src/core/network.c b/src/core/network.c index bfaa47fb..0751aa95 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -45,11 +45,7 @@ union sockaddr_union { GIOChannel *g_io_channel_new(int handle) { GIOChannel *chan; -#ifdef WIN32 - chan = g_io_channel_win32_new_socket(handle); -#else chan = g_io_channel_unix_new(handle); -#endif g_io_channel_set_encoding(chan, NULL, NULL); g_io_channel_set_buffered(chan, FALSE); return chan; @@ -188,9 +184,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) return NULL; /* set socket options */ -#ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); -#endif setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); @@ -211,11 +205,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) sin_set_port(&so, port); ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so)); -#ifndef WIN32 if (ret < 0 && errno != EINPROGRESS) -#else - if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) -#endif { int old_errno = errno; close(handle); @@ -238,9 +228,7 @@ GIOChannel *net_connect_unix(const char *path) return NULL; /* set socket options */ -#ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); -#endif /* connect */ memset(&sa, 0, sizeof(sa)); @@ -297,9 +285,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port) return NULL; /* set socket options */ -#ifndef WIN32 fcntl(handle, F_SETFL, O_NONBLOCK); -#endif setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); @@ -342,9 +328,7 @@ GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port) if (addr != NULL) sin_get_ip(&so, addr); if (port != NULL) *port = sin_get_port(&so); -#ifndef WIN32 fcntl(ret, F_SETFL, O_NONBLOCK); -#endif return g_io_channel_new(ret); } diff --git a/src/core/network.h b/src/core/network.h index fa7e9675..73ac8dee 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -6,12 +6,10 @@ #endif #include -#ifndef WIN32 # include # include # include # include -#endif #ifndef AF_INET6 # ifdef PF_INET6 diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 771e3999..4a048282 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -423,17 +423,39 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) return rec; } +static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server) +{ + char *address, *chatnet; + int port; + + address = config_node_get_str(node, "address", NULL); + chatnet = config_node_get_str(node, "chatnet", NULL); + port = config_node_get_int(node, "port", 0); + + if (g_strcmp0(address, server->address) != 0 || + g_strcmp0(chatnet, server->chatnet) != 0 || + port != server->port) + return 1; + + return 0; +} + static void server_setup_save(SERVER_SETUP_REC *rec) { - CONFIG_NODE *parentnode, *node; - int index; + CONFIG_NODE *parent_node, *node; + GSList *config_node; - index = g_slist_index(setupservers, rec); + parent_node = iconfig_node_traverse("(servers", TRUE); - parentnode = iconfig_node_traverse("(servers", TRUE); - node = config_node_nth(parentnode, index); - if (node == NULL) - node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + /* Try to find this channel in the configuration */ + config_node = g_slist_find_custom(parent_node->value, rec, + (GCompareFunc)compare_server_setup); + if (config_node != NULL) + /* Let's update this server record */ + node = config_node->data; + else + /* Create a brand-new server record */ + node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK); iconfig_node_clear(node); iconfig_node_set_str(node, "address", rec->address); @@ -465,14 +487,21 @@ static void server_setup_save(SERVER_SETUP_REC *rec) static void server_setup_remove_config(SERVER_SETUP_REC *rec) { - CONFIG_NODE *node; - int index; + CONFIG_NODE *parent_node; + GSList *config_node; - node = iconfig_node_traverse("servers", FALSE); - if (node != NULL) { - index = g_slist_index(setupservers, rec); - iconfig_node_list_remove(node, index); - } + parent_node = iconfig_node_traverse("servers", FALSE); + + if (parent_node == NULL) + return; + + /* Try to find this server in the configuration */ + config_node = g_slist_find_custom(parent_node->value, rec, + (GCompareFunc)compare_server_setup); + + if (config_node != NULL) + /* Delete the server from the configuration */ + iconfig_node_remove(parent_node, config_node->data); } static void server_setup_destroy(SERVER_SETUP_REC *rec) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 4461de92..a4715d23 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -757,7 +757,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_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "completion", &optlist, &key, &value)) return; diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index a171596d..046d641a 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -122,7 +122,8 @@ static void cmd_join(const char *data, SERVER_REC *server) void *free_arg; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, + PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST | + PARAM_FLAG_STRIP_TRAILING_WS, "join", &optlist, &pdata)) return; diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index a15850e2..ee7f9424 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -168,9 +168,7 @@ void fe_common_core_init(void) keyboard_init(); printtext_init(); formats_init(); -#ifndef WIN32 fe_exec_init(); -#endif fe_expandos_init(); fe_help_init(); fe_ignore_init(); @@ -211,9 +209,7 @@ void fe_common_core_deinit(void) keyboard_deinit(); printtext_deinit(); formats_deinit(); -#ifndef WIN32 fe_exec_deinit(); -#endif fe_expandos_deinit(); fe_help_deinit(); fe_ignore_deinit(); diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 533cda31..d2f9de27 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -127,7 +127,8 @@ static void cmd_ignore(const char *data) return; } - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "ignore", &optlist, &mask, &levels)) return; diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index a39623d2..f2c4c014 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -87,8 +87,9 @@ static void cmd_log_open(const char *data) int level; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | - PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS, - "log open", &optlist, &fname, &levels)) + PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS | + PARAM_FLAG_STRIP_TRAILING_WS, "log open", &optlist, + &fname, &levels)) return; if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -616,7 +617,7 @@ static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item) static void sig_log_locked(LOG_REC *log) { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, - TXT_LOG_LOCKED, log->fname); + TXT_LOG_LOCKED, log->real_fname); } static void sig_log_create_failed(LOG_REC *log) @@ -656,11 +657,11 @@ static void sig_awaylog_show(LOG_REC *log, gpointer pmsgs, gpointer pfilepos) filepos = GPOINTER_TO_INT(pfilepos); if (msgs == 0) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_NO_AWAY_MSGS, log->fname); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_NO_AWAY_MSGS, log->real_fname); else { - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->fname, msgs); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->real_fname, msgs); - str = g_strdup_printf("\"%s\" %d", log->fname, filepos); + str = g_strdup_printf("\"%s\" %d", log->real_fname, filepos); signal_emit("command cat", 1, str); g_free(str); } diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index 2627989d..3bb43bf7 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -108,7 +108,8 @@ static void cmd_set(char *data) int clear, set_default; SETTINGS_REC *rec; - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_OPTIONS, + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | + PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS, "set", &optlist, &key, &value)) return; @@ -182,7 +183,7 @@ static void cmd_toggle(const char *data) void *free_arg; int type; - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &key, &value)) return; if (*key == '\0') diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index 466a2825..ba6f3242 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -413,6 +413,18 @@ void printtext_gui(const char *text) g_free(str); } +/* Like printtext_gui(), but don't expand % codes. */ +void printtext_gui_internal(const char *str) +{ + TEXT_DEST_REC dest; + + g_return_if_fail(str != NULL); + + memset(&dest, 0, sizeof(dest)); + + format_send_to_gui(&dest, str); +} + static void msg_beep_check(TEXT_DEST_REC *dest) { if (dest->level != 0 && (dest->level & MSGLEVEL_NO_ACT) == 0 && diff --git a/src/fe-common/core/printtext.h b/src/fe-common/core/printtext.h index 66ba28f4..ab8dfac1 100644 --- a/src/fe-common/core/printtext.h +++ b/src/fe-common/core/printtext.h @@ -23,6 +23,7 @@ void printtext_dest(TEXT_DEST_REC *dest, const char *text, ...); /* only GUI should call these - used for printing text to somewhere else than windows */ void printtext_gui(const char *text); +void printtext_gui_internal(const char *str); void printformat_module_gui(const char *module, int formatnum, ...); void printformat_module_gui_args(const char *module, int formatnum, va_list va); diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am index a5dd4c77..bf88f5cd 100644 --- a/src/fe-common/irc/Makefile.am +++ b/src/fe-common/irc/Makefile.am @@ -37,6 +37,7 @@ libfe_common_irc_a_SOURCES = \ pkginc_fe_common_ircdir=$(pkgincludedir)/src/fe-common/irc pkginc_fe_common_irc_HEADERS = \ fe-irc-server.h \ + fe-irc-channels.h \ module.h \ module-formats.h diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c index a23facbd..11a911d2 100644 --- a/src/fe-common/irc/fe-irc-commands.c +++ b/src/fe-common/irc/fe-irc-commands.c @@ -246,8 +246,8 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, CMD_IRC_SERVER(server); - if (!cmd_get_params(data, &free_arg, 2 | - PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, item, &channel, &nicks)) return; diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 176ee431..6e13ba4e 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -26,6 +26,7 @@ #include "gui-entry.h" #include "gui-printtext.h" #include "term.h" +#include "recode.h" #undef i_toupper #undef i_tolower @@ -345,6 +346,33 @@ void gui_entry_set_active(GUI_ENTRY_REC *entry) } } +/* Return screen length of plain string */ +static int scrlen_str(const char *str) +{ + int len = 0; + char *stripped; + g_return_val_if_fail(str != NULL, 0); + + str = stripped = strip_codes(str); + if (is_utf8() && g_utf8_validate(str, -1, NULL)) { + + 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); + } + + g_free(stripped); + return len; +} + void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) { int oldlen; @@ -355,11 +383,11 @@ void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) if (str != NULL) { g_free_not_null(entry->prompt); entry->prompt = g_strdup(str); - entry->promptlen = format_get_length(str); + entry->promptlen = scrlen_str(str); } if (entry->prompt != NULL) - gui_printtext(entry->xpos, entry->ypos, entry->prompt); + gui_printtext_internal(entry->xpos, entry->ypos, entry->prompt); if (entry->promptlen != oldlen) { gui_entry_fix_cursor(entry); diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index d8272df5..775e6044 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -109,6 +109,16 @@ void gui_printtext(int xpos, int ypos, const char *str) next_xpos = next_ypos = -1; } +void gui_printtext_internal(int xpos, int ypos, const char *str) +{ + next_xpos = xpos; + next_ypos = ypos; + + printtext_gui_internal(str); + + next_xpos = next_ypos = -1; +} + void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time) { GUI_WINDOW_REC *gui; diff --git a/src/fe-text/gui-printtext.h b/src/fe-text/gui-printtext.h index 33b7ce6f..d2671497 100644 --- a/src/fe-text/gui-printtext.h +++ b/src/fe-text/gui-printtext.h @@ -17,6 +17,7 @@ void gui_set_default_indent(const char *name); INDENT_FUNC get_default_indent_func(void); void gui_printtext(int xpos, int ypos, const char *str); +void gui_printtext_internal(int xpos, int ypos, const char *str); void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str); void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 0ca68d80..e7e76824 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -147,7 +147,6 @@ static void window_next_page(void) static void paste_buffer_join_lines(GArray *buf) { -#define IS_WHITE(c) ((c) == ' ' || (c) == '\t') unsigned int i, count, indent, line_len; unichar *arr, *dest, *last_lf_pos; int last_lf; @@ -177,15 +176,15 @@ static void paste_buffer_join_lines(GArray *buf) if (buf->len == 0) return; - arr = (unichar *) paste_buffer->data; + arr = (unichar *)buf->data; /* first line */ - if (IS_WHITE(arr[0])) + if (isblank(arr[0])) return; /* find the first beginning of indented line */ for (i = 1; i < buf->len; i++) { - if (arr[i-1] == '\n' && IS_WHITE(arr[i])) + if (arr[i-1] == '\n' && isblank(arr[i])) break; } if (i == buf->len) @@ -193,7 +192,7 @@ static void paste_buffer_join_lines(GArray *buf) /* get how much indentation we have.. */ for (indent = 0; i < buf->len; i++, indent++) { - if (!IS_WHITE(arr[i])) + if (!isblank(arr[i])) break; } if (i == buf->len) @@ -203,7 +202,7 @@ static void paste_buffer_join_lines(GArray *buf) count = indent; last_lf = TRUE; for (; i < buf->len; i++) { if (last_lf) { - if (IS_WHITE(arr[i])) + if (isblank(arr[i])) count++; else { last_lf = FALSE; @@ -220,11 +219,11 @@ static void paste_buffer_join_lines(GArray *buf) get longer than 400 chars */ dest = arr; last_lf = TRUE; last_lf_pos = NULL; line_len = 0; for (i = 0; i < buf->len; i++) { - if (last_lf && IS_WHITE(arr[i])) { + if (last_lf && isblank(arr[i])) { /* whitespace, ignore */ } else if (arr[i] == '\n') { if (!last_lf && i+1 != buf->len && - IS_WHITE(arr[i+1])) { + isblank(arr[i+1])) { last_lf_pos = dest; *dest++ = ' '; } else { diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index b1fa5e22..cad271c9 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -271,20 +271,6 @@ static void check_files(void) } } -#ifdef WIN32 -static void winsock_init(void) -{ - WORD wVersionRequested; - WSADATA wsaData; - - wVersionRequested = MAKEWORD(2, 2); - - if (WSAStartup(wVersionRequested, &wsaData) != 0) { - printf("Error initializing winsock\n"); - exit(1); - } -} -#endif int main(int argc, char **argv) { @@ -315,9 +301,6 @@ int main(int argc, char **argv) check_files(); -#ifdef WIN32 - winsock_init(); -#endif #ifdef HAVE_SOCKS SOCKSinit(argv[0]); #endif diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index 68dd45c0..198fdc4a 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -184,8 +184,8 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, if (server == NULL || !server->connected || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, - item, &channel, &nicks)) return; + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST | + PARAM_FLAG_STRIP_TRAILING_WS, item, &channel, &nicks)) return; if (!server_ischannel(SERVER(server), channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') { if (g_strcmp0(data, "*") != 0) @@ -262,8 +262,8 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, void *item) CMD_IRC_SERVER(server); - if (!cmd_get_params(data, &free_arg, 1 | - PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "ban", &optlist, &ban)) return; @@ -297,8 +297,8 @@ static void cmd_unban(const char *data, IRC_SERVER_REC *server, void *item) CMD_IRC_SERVER(server); - if (!cmd_get_params(data, &free_arg, 1 | - PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "unban", &optlist, &ban)) return; diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c index cd3ae677..5464e493 100644 --- a/src/irc/core/irc-cap.c +++ b/src/irc/core/irc-cap.c @@ -112,7 +112,8 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add /* Check whether the cap is supported by the server */ for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) { if (gslist_find_string(server->cap_supported, tmp->data)) { - g_string_append_c(cmd, ' '); + if (avail_caps > 0) + g_string_append_c(cmd, ' '); g_string_append(cmd, tmp->data); avail_caps++; diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c index 682be4c2..e775f530 100644 --- a/src/irc/core/irc-channels.c +++ b/src/irc/core/irc-channels.c @@ -174,6 +174,13 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server, const char *channel) { GSList *tmp; + char *fmt_channel; + + /* if 'channel' has no leading # this lookup is going to fail, add a + * octothorpe in front of it to handle this case. */ + fmt_channel = server_ischannel(SERVER(server), channel) ? + g_strdup(channel) : + g_strdup_printf("#%s", channel); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *rec = tmp->data; @@ -182,13 +189,19 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server, continue; /* check both !ABCDEchannel and !channel */ - if (IRC_SERVER(server)->nick_comp_func(channel, rec->name) == 0) + if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->name) == 0) { + g_free(fmt_channel); return rec; + } - if (IRC_SERVER(server)->nick_comp_func(channel, rec->visible_name) == 0) + if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->visible_name) == 0) { + g_free(fmt_channel); return rec; + } } + g_free(fmt_channel); + return NULL; } diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 47644753..3cc105ba 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -267,7 +267,8 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server, CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_GETREST, "list", &optlist, &str)) + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, + "list", &optlist, &str)) return; if (*str == '\0' && g_hash_table_lookup(optlist, "yes") == NULL && @@ -288,7 +289,8 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, CMD_IRC_SERVER(server); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | + PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest)) return; if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { @@ -320,7 +322,8 @@ static void cmd_names(const char *data, IRC_SERVER_REC *server, CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_GETREST, "names", &optlist, &channel)) + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, + "names", &optlist, &channel)) return; if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { @@ -501,7 +504,8 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server) CMD_IRC_SERVER(server); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nicks, &rest)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, + &nicks, &rest)) return; if (*nicks == '\0') nicks = server->nick; diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c index 667016aa..bcb9d1f6 100644 --- a/src/irc/core/irc-nicklist.c +++ b/src/irc/core/irc-nicklist.c @@ -55,30 +55,6 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick, return rec; } -#define isnickchar(a) \ - (i_isalnum(a) || (a) == '`' || (a) == '-' || (a) == '_' || \ - (a) == '[' || (a) == ']' || (a) == '{' || (a) == '}' || \ - (a) == '|' || (a) == '\\' || (a) == '^') - -/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ -char *irc_nick_strip(const char *nick) -{ - char *stripped, *spos; - - g_return_val_if_fail(nick != NULL, NULL); - - spos = stripped = g_strdup(nick); - while (isnickchar(*nick)) { - if (i_isalnum(*nick)) - *spos++ = *nick; - nick++; - } - if ((unsigned char) *nick >= 128) - *spos++ = *nick; /* just add it so that nicks won't match.. */ - *spos = '\0'; - return stripped; -} - int irc_nickcmp_rfc1459(const char *m, const char *n) { while (*m != '\0' && *n != '\0') { diff --git a/src/irc/core/irc-nicklist.h b/src/irc/core/irc-nicklist.h index 7302556b..2ae17d2c 100644 --- a/src/irc/core/irc-nicklist.h +++ b/src/irc/core/irc-nicklist.h @@ -8,9 +8,6 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick, int op, int halfop, int voice, int send_massjoin, const char *prefixes); -/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ -char *irc_nick_strip(const char *nick); - int irc_nickcmp_rfc1459(const char *, const char *); int irc_nickcmp_ascii(const char *, const char *); diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index 32a0c169..207461cc 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -835,10 +835,10 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, if (*data == '+' || *data == '-') { target = "*"; - if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST, &mode)) + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &mode)) return; } else { - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &mode)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &target, &mode)) return; } diff --git a/src/irc/dcc/dcc-send.c b/src/irc/dcc/dcc-send.c index 2ce84f18..ca29b9b9 100644 --- a/src/irc/dcc/dcc-send.c +++ b/src/irc/dcc/dcc-send.c @@ -174,8 +174,8 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, int queue, mode, passive; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_GETREST, "dcc send", - &optlist, &nick, &fileargs)) + PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, + "dcc send", &optlist, &nick, &fileargs)) return; chat = item_get_dcc(item); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 17f6c477..7f35585e 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, - &typestr, &nick, &arg)) + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST | + PARAM_FLAG_STRIP_TRAILING_WS, &typestr, &nick, &arg)) return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); diff --git a/src/irc/notifylist/notify-commands.c b/src/irc/notifylist/notify-commands.c index 67076106..0d4fd4f2 100644 --- a/src/irc/notifylist/notify-commands.c +++ b/src/irc/notifylist/notify-commands.c @@ -36,7 +36,8 @@ static void cmd_notify(gchar *data) g_return_if_fail(data != NULL); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + if (!cmd_get_params(data, &free_arg, + 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "notify", &optlist, &mask, &ircnets)) return; if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); diff --git a/src/perl/common/Irssi.pm b/src/perl/common/Irssi.pm index a9f93bf0..e2d9f963 100644 --- a/src/perl/common/Irssi.pm +++ b/src/perl/common/Irssi.pm @@ -159,6 +159,8 @@ if (!in_irssi()) { @Irssi::Channel::ISA = qw(Irssi::Windowitem); @Irssi::Query::ISA = qw(Irssi::Windowitem); + @Irssi::Chatnet::ISA = qw(); + @Irssi::Nick::ISA = qw(); Irssi::init(); diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index a245206c..db5c5f79 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -11,6 +11,7 @@ static void perl_irc_connect_fill_hash(HV *hv, IRC_SERVER_CONNECT_REC *conn) static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server) { + perl_irc_connect_fill_hash(hv, server->connrec); perl_server_fill_hash(hv, (SERVER_REC *) server); (void) hv_store(hv, "real_address", 12, new_pv(server->real_address), 0); diff --git a/src/perl/irssi-core.pl b/src/perl/irssi-core.pl index 38265a80..46066a38 100644 --- a/src/perl/irssi-core.pl +++ b/src/perl/irssi-core.pl @@ -47,4 +47,8 @@ sub eval_file { $data = qq{\n#line 1 "$filename"\n$data}; eval_data($data, $id); + + if (exists ${"Irssi::Script::${id}::"}{IRSSI} && ${"Irssi::Script::${id}::"}{IRSSI}{name} =~ /cap.sasl/ && ${"Irssi::Script::${id}::VERSION"} < 2) { + die "cap_sasl has been unloaded from Irssi ".Irssi::version()." because it conflicts with the built-in SASL support. See /help network for configuring SASL or read the ChangeLog for more information."; + } } diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c index dcda3bb5..d7a428e5 100644 --- a/src/perl/perl-common.c +++ b/src/perl/perl-common.c @@ -351,10 +351,12 @@ void perl_window_item_fill_hash(HV *hv, WI_ITEM_REC *item) g_return_if_fail(item != NULL); type = (char *) module_find_id_str("WINDOW ITEM TYPE", item->type); - chat_type = (char *) chat_protocol_find_id(item->chat_type)->name; (void) hv_store(hv, "type", 4, new_pv(type), 0); - (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + if (item->chat_type) { + chat_type = (char *) chat_protocol_find_id(item->chat_type)->name; + (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + } if (item->server != NULL) { (void) hv_store(hv, "server", 6, iobject_bless(item->server), 0); diff --git a/src/perl/ui/UI.xs b/src/perl/ui/UI.xs index 9db57e98..5ac3da4e 100644 --- a/src/perl/ui/UI.xs +++ b/src/perl/ui/UI.xs @@ -64,6 +64,19 @@ static void perl_text_dest_fill_hash(HV *hv, TEXT_DEST_REC *dest) (void) hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0); } +static void perl_exec_fill_hash(HV *hv, EXEC_WI_REC *item) +{ + g_return_if_fail(hv != NULL); + g_return_if_fail(item != NULL); + + perl_window_item_fill_hash(hv, (WI_ITEM_REC *) item); + /* we don't bless to Process here to avoid infinite recursion + in the simplistic script binding */ + if (item->process != NULL) { + (void) hv_store(hv, "process_id", 10, newSViv(item->process->id), 0); + } +} + static PLAIN_OBJECT_INIT_REC fe_plains[] = { { "Irssi::UI::Process", (PERL_OBJECT_FUNC) perl_process_fill_hash }, { "Irssi::UI::Window", (PERL_OBJECT_FUNC) perl_window_fill_hash }, @@ -94,6 +107,10 @@ CODE: initialized = TRUE; irssi_add_plains(fe_plains); + /* window items: fe-exec */ + irssi_add_object(module_get_uniq_id_str("WINDOW ITEM TYPE", "EXEC"), + 0, "Irssi::UI::Exec", + (PERL_OBJECT_FUNC) perl_exec_fill_hash); perl_themes_init(); void