summaryrefslogtreecommitdiff
path: root/src/fe-common
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-common')
-rw-r--r--src/fe-common/core/chat-completion.c57
-rw-r--r--src/fe-common/irc/fe-irc-commands.c12
2 files changed, 63 insertions, 6 deletions
diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c
index 97cd0565..d610008f 100644
--- a/src/fe-common/core/chat-completion.c
+++ b/src/fe-common/core/chat-completion.c
@@ -173,6 +173,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
{
CHANNEL_REC *channel;
int own;
+ g_return_if_fail(nick != NULL);
channel = channel_find(server, target);
if (channel != NULL) {
@@ -185,6 +186,7 @@ static void sig_message_join(SERVER_REC *server, const char *channel,
const char *nick, const char *address)
{
CHANNEL_REC *chanrec;
+ g_return_if_fail(nick != NULL);
chanrec = channel_find(server, channel);
if (chanrec != NULL)
@@ -639,6 +641,59 @@ static void complete_window_nicks(GList **list, WINDOW_REC *window,
}
}
+/* Checks if a line is only nicks from autocompletion.
+ This lets us insert colons only at the beginning of a list
+ of nicks */
+static int only_nicks(const char *linestart)
+{
+ int i = 1;
+ char prev;
+
+ // at the beginning of the line
+ if (*linestart == '\0') {
+ return TRUE;
+ }
+
+ /* completion_char being a whole string introduces loads of edge cases
+ and can't be handled generally. Skip this case; we handled the
+ "beginning of line" case already */
+ if (completion_char[1] != '\0')
+ return FALSE;
+
+ /* This would make the completion char get inserted everywhere otherwise */
+ if (*completion_char == ' ')
+ return FALSE;
+
+ /* First ensure that the line is of the format "foo: bar: baz"
+ we check this by ensuring each space is preceded by a colon or
+ another space */
+ while (linestart[i] != '\0') {
+ if (linestart[i] == ' ') {
+ prev = linestart[i - 1];
+ if (prev != *completion_char && prev != ' ')
+ return FALSE;
+ }
+ i += 1;
+ }
+
+ /* There's an edge case here, if we're completing something
+ like `foo: bar ba<tab>`, then the `linestart` line will end
+ at "bar", and we'll miss the space. Ensure that the end
+ of the line is a colon followed by an optional series of spaces */
+ i -= 1;
+ while (i >= 0) {
+ if (linestart[i] == ' ') {
+ i--;
+ continue;
+ } else if (linestart[i] == *completion_char) {
+ return TRUE;
+ } else {
+ break;
+ }
+ }
+ return FALSE;
+}
+
static void sig_complete_word(GList **list, WINDOW_REC *window,
const char *word, const char *linestart,
int *want_space)
@@ -691,7 +746,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
} else if (channel != NULL) {
/* nick completion .. we could also be completing a nick
after /MSG from nicks in channel */
- const char *suffix = *linestart != '\0' ? NULL : completion_char;
+ const char *suffix = only_nicks(linestart) ? completion_char : NULL;
complete_window_nicks(list, window, word, suffix);
} else if (window->level & MSGLEVEL_MSGS) {
/* msgs window, complete /MSG nicks */
diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c
index 11a911d2..7a6b17a6 100644
--- a/src/fe-common/irc/fe-irc-commands.c
+++ b/src/fe-common/irc/fe-irc-commands.c
@@ -345,16 +345,18 @@ static void cmd_ts(const char *data)
}
typedef struct {
- IRC_SERVER_REC *server;
+ char *server_tag;
char *nick;
} OPER_PASS_REC;
static void cmd_oper_got_pass(const char *password, OPER_PASS_REC *rec)
{
- if (*password != '\0')
- irc_send_cmdv(rec->server, "OPER %s %s", rec->nick, password);
+ SERVER_REC *server_rec = server_find_tag(rec->server_tag);
+ if (*password != '\0' && IS_IRC_SERVER(server_rec))
+ irc_send_cmdv((IRC_SERVER_REC *) server_rec, "OPER %s %s", rec->nick, password);
g_free(rec->nick);
- g_free(rec);
+ g_free(rec->server_tag);
+ g_free(rec);
}
static void cmd_oper(const char *data, IRC_SERVER_REC *server)
@@ -374,7 +376,7 @@ static void cmd_oper(const char *data, IRC_SERVER_REC *server)
OPER_PASS_REC *rec;
rec = g_new(OPER_PASS_REC, 1);
- rec->server = server;
+ rec->server_tag = g_strdup(server->tag);
rec->nick = g_strdup(*nick != '\0' ? nick : server->nick);
format = format_get_text(MODULE_NAME, NULL, server, NULL,