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.c55
-rw-r--r--src/fe-common/core/fe-common-core.c51
-rw-r--r--src/fe-common/core/fe-windows.h8
-rw-r--r--src/fe-common/core/formats.c27
-rw-r--r--src/fe-common/core/themes.c2
-rw-r--r--src/fe-common/core/window-commands.c7
-rw-r--r--src/fe-common/core/window-items.c2
-rw-r--r--src/fe-common/irc/fe-netjoin.c19
-rw-r--r--src/fe-common/irc/fe-netsplit.c22
9 files changed, 135 insertions, 58 deletions
diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c
index 97cd0565..7ecdd4a2 100644
--- a/src/fe-common/core/chat-completion.c
+++ b/src/fe-common/core/chat-completion.c
@@ -639,6 +639,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 +744,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/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index a3b7364c..209c2d9e 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -470,26 +470,49 @@ void fe_common_core_finish_init(void)
gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest)
{
+ WI_ITEM_REC *item;
+ int server_tag_len, channel_type, query_type;
+ char **tmp;
+
+ channel_type = module_get_uniq_id_str("WINDOW ITEM TYPE", "CHANNEL");
+ query_type = module_get_uniq_id_str("WINDOW ITEM TYPE", "QUERY");
+
g_return_val_if_fail(array != NULL, FALSE);
+ g_return_val_if_fail(dest != NULL, FALSE);
+ g_return_val_if_fail(dest->window != NULL, FALSE);
+ g_return_val_if_fail(dest->target != NULL, FALSE);
- if (strarray_find(array, "*") != -1)
- return TRUE;
+ item = window_item_find_window(dest->window, dest->server, dest->target);
+ if (item == NULL) {
+ return FALSE;
+ }
- if (strarray_find(array, dest->target) != -1)
- return TRUE;
+ server_tag_len = dest->server_tag != NULL ? strlen(dest->server_tag) : 0;
+ for (tmp = array; *tmp != NULL; tmp++) {
+ char *str = *tmp;
+ if (*str == '\0') {
+ continue;
+ }
- if (dest->server_tag != NULL) {
- char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, "*");
- int ret = strarray_find(array, tagtarget);
- g_free(tagtarget);
- if (ret != -1)
- return TRUE;
+ if (server_tag_len &&
+ g_ascii_strncasecmp(str, dest->server_tag, server_tag_len) == 0 &&
+ str[server_tag_len] == '/') {
+ str += server_tag_len + 1;
+ }
- tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target);
- ret = strarray_find(array, tagtarget);
- g_free(tagtarget);
- if (ret != -1)
+ if (g_strcmp0(str, "") == 0 || g_strcmp0(str, "::all") == 0) {
return TRUE;
+ } else if (g_ascii_strcasecmp(str, dest->target) == 0) {
+ return TRUE;
+ } else if (item->type == query_type &&
+ g_strcmp0(str, dest->target[0] == '=' ? "::dccqueries" :
+ "::queries") == 0) {
+ return TRUE;
+ } else if (item->type == channel_type &&
+ g_strcmp0(str, "::channels") == 0) {
+ return TRUE;
+ }
}
+
return FALSE;
}
diff --git a/src/fe-common/core/fe-windows.h b/src/fe-common/core/fe-windows.h
index 32d6cfcd..aaa773c8 100644
--- a/src/fe-common/core/fe-windows.h
+++ b/src/fe-common/core/fe-windows.h
@@ -11,6 +11,14 @@ enum {
DATA_LEVEL_HILIGHT
};
+enum {
+ MAIN_WINDOW_TYPE_NONE = -1,
+ MAIN_WINDOW_TYPE_DEFAULT = 0,
+ MAIN_WINDOW_TYPE_HIDDEN = 1,
+ MAIN_WINDOW_TYPE_SPLIT = 2,
+ MAIN_WINDOW_TYPE_RSPLIT = 3
+};
+
typedef struct {
char *servertag;
char *name;
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index 37db6f7c..4c819c2d 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -480,27 +480,30 @@ int format_real_length(const char *str, int len)
start = str;
tmp = g_string_new(NULL);
- while (*str != '\0' && len > 0) {
+ while (*str != '\0') {
+ oldstr = str;
if (*str == '%' && str[1] != '\0') {
str++;
if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL);
- str += adv;
- if (adv)
- continue;
- }
-
- /* %% or unknown %code, written as-is */
- if (*str != '%') {
- if (--len == 0)
- break;
+ if (adv) {
+ str += adv;
+ continue;
+ }
+ /* discount for unknown % */
+ if (--len < 0) {
+ str = oldstr;
+ break;
+ }
+ oldstr = str;
}
}
- oldstr = str;
len -= string_advance(&str, utf8);
- if (len < 0)
+ if (len < 0) {
str = oldstr;
+ break;
+ }
}
g_string_free(tmp, TRUE);
diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c
index cb1cce8f..6692985b 100644
--- a/src/fe-common/core/themes.c
+++ b/src/fe-common/core/themes.c
@@ -130,7 +130,7 @@ static char *theme_replace_expand(THEME_REC *theme, int index,
abstract = rec->data;
abstract = theme_format_expand_data(theme, (const char **) &abstract,
default_fg, default_bg,
- last_fg, last_bg, flags);
+ last_fg, last_bg, (flags | EXPAND_FLAG_IGNORE_REPLACES));
ret = parse_special_string(abstract, NULL, NULL, data, NULL,
PARSE_FLAG_ONLY_ARGS);
g_free(abstract);
diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c
index 57c81ac2..a81c0180 100644
--- a/src/fe-common/core/window-commands.c
+++ b/src/fe-common/core/window-commands.c
@@ -169,7 +169,7 @@ static void cmd_window(const char *data, void *server, WI_ITEM_REC *item)
command_runsub("window", data, server, item);
}
-/* SYNTAX: WINDOW NEW [HIDDEN|SPLIT] */
+/* SYNTAX: WINDOW NEW [HIDDEN|SPLIT|RSPLIT] */
static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
@@ -177,8 +177,9 @@ static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
g_return_if_fail(data != NULL);
- type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? 1 :
- (g_ascii_strcasecmp(data, "split") == 0 ? 2 : 0);
+ type = (g_ascii_strncasecmp(data, "hid", 3) == 0 || g_ascii_strcasecmp(data, "tab") == 0) ? MAIN_WINDOW_TYPE_HIDDEN :
+ g_ascii_strcasecmp(data, "split") == 0 ? MAIN_WINDOW_TYPE_SPLIT :
+ g_ascii_strncasecmp(data, "rs", 2) == 0 ? MAIN_WINDOW_TYPE_RSPLIT : MAIN_WINDOW_TYPE_DEFAULT;
signal_emit("gui window create override", 1, GINT_TO_POINTER(type));
window = window_create(NULL, FALSE);
diff --git a/src/fe-common/core/window-items.c b/src/fe-common/core/window-items.c
index bd6ae5e9..8eab7124 100644
--- a/src/fe-common/core/window-items.c
+++ b/src/fe-common/core/window-items.c
@@ -314,7 +314,7 @@ void window_item_create(WI_ITEM_REC *item, int automatic)
/* create new window to use */
if (settings_get_bool("autocreate_split_windows")) {
signal_emit("gui window create override", 1,
- GINT_TO_POINTER(0));
+ GINT_TO_POINTER(MAIN_WINDOW_TYPE_SPLIT));
}
window = window_create(item, automatic);
} else {
diff --git a/src/fe-common/irc/fe-netjoin.c b/src/fe-common/irc/fe-netjoin.c
index 8272093f..a7a2e4fe 100644
--- a/src/fe-common/irc/fe-netjoin.c
+++ b/src/fe-common/irc/fe-netjoin.c
@@ -245,23 +245,18 @@ static void print_netjoins(NETJOIN_SERVER_REC *server, const char *filter_channe
message before it. */
static void sig_print_starting(TEXT_DEST_REC *dest)
{
- NETJOIN_SERVER_REC *rec;
+ GSList *tmp, *next;
if (printing_joins)
return;
- if (!IS_IRC_SERVER(dest->server))
- return;
-
- if (!(dest->level & MSGLEVEL_PUBLIC))
- return;
-
- if (!server_ischannel(dest->server, dest->target))
- return;
+ for (tmp = joinservers; tmp != NULL; tmp = next) {
+ NETJOIN_SERVER_REC *server = tmp->data;
- rec = netjoin_find_server(IRC_SERVER(dest->server));
- if (rec != NULL && rec->netjoins != NULL)
- print_netjoins(rec, dest->target);
+ next = tmp->next;
+ if (server->netjoins != NULL)
+ print_netjoins(server, NULL);
+ }
}
static int sig_check_netjoins(void)
diff --git a/src/fe-common/irc/fe-netsplit.c b/src/fe-common/irc/fe-netsplit.c
index 4c69dd10..edd3fc34 100644
--- a/src/fe-common/irc/fe-netsplit.c
+++ b/src/fe-common/irc/fe-netsplit.c
@@ -199,7 +199,7 @@ static void temp_split_chan_free(TEMP_SPLIT_CHAN_REC *rec)
g_free(rec);
}
-static void print_splits(IRC_SERVER_REC *server, const char *channel)
+static void print_splits(IRC_SERVER_REC *server, const char *filter_channel)
{
TEMP_SPLIT_REC temp;
GSList *servers;
@@ -218,7 +218,7 @@ static void print_splits(IRC_SERVER_REC *server, const char *channel)
g_hash_table_foreach(server->splits,
(GHFunc) get_server_splits, &temp);
- print_server_splits(server, &temp, channel);
+ print_server_splits(server, &temp, filter_channel);
g_slist_foreach(temp.channels,
(GFunc) temp_split_chan_free, NULL);
@@ -247,23 +247,17 @@ static int check_server_splits(IRC_SERVER_REC *server)
message before it. */
static void sig_print_starting(TEXT_DEST_REC *dest)
{
- IRC_SERVER_REC *rec;
+ GSList *tmp;
if (printing_splits)
return;
- if (!IS_IRC_SERVER(dest->server))
- return;
-
- if (!(dest->level & MSGLEVEL_PUBLIC))
- return;
-
- if (!server_ischannel(dest->server, dest->target))
- return;
+ for (tmp = servers; tmp != NULL; tmp = tmp->next) {
+ IRC_SERVER_REC *rec = tmp->data;
- rec = IRC_SERVER(dest->server);
- if (rec->split_servers != NULL)
- print_splits(rec, dest->target);
+ if (IS_IRC_SERVER(rec) && rec->split_servers != NULL)
+ print_splits(rec, NULL);
+ }
}
static int sig_check_splits(void)