diff --git a/default.theme b/default.theme index 1146f919..8b0f0ccc 100644 --- a/default.theme +++ b/default.theme @@ -223,6 +223,7 @@ abstracts = { dccownmsg = "[%r$0%K($1-%K)%n] "; dccownnick = "%R$0-%n"; dccownaction = "{action $0-}"; + dccownaction_target = "{action_core $0}%K:%c$1%n "; # DCC chat, others dccmsg = "[%G$1-%K(%g$0%K)%n] "; diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index e0bcc546..8f5494a4 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -39,6 +39,7 @@ libfe_common_core_a_SOURCES = \ noinst_HEADERS = \ command-history.h \ + chat-completion.h \ completion.h \ fe-channels.h \ fe-common-core.h \ diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index 6fddcd08..67631dd2 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -37,6 +37,7 @@ static int keep_privates_count, keep_publics_count; static int completion_lowercase; static const char *completion_char, *cmdchars; +static GSList *global_lastmsgs; #define SERVER_LAST_MSG_ADD(server, nick) \ last_msg_add(&((MODULE_SERVER_REC *) MODULE_DATA(server))->lastmsgs, \ @@ -109,6 +110,37 @@ static void last_msg_destroy(GSList **list, LAST_MSG_REC *rec) g_free(rec); } +void completion_last_message_add(const char *nick) +{ + g_return_if_fail(nick != NULL); + + last_msg_add(&global_lastmsgs, nick, TRUE, keep_privates_count); +} + +void completion_last_message_remove(const char *nick) +{ + LAST_MSG_REC *rec; + + g_return_if_fail(nick != NULL); + + rec = last_msg_find(global_lastmsgs, nick); + if (rec != NULL) last_msg_destroy(&global_lastmsgs, rec); +} + +void completion_last_message_rename(const char *oldnick, const char *newnick) +{ + LAST_MSG_REC *rec; + + g_return_if_fail(oldnick != NULL); + g_return_if_fail(newnick != NULL); + + rec = last_msg_find(global_lastmsgs, oldnick); + if (rec != NULL) { + g_free(rec->nick); + rec->nick = g_strdup(newnick); + } +} + static void sig_message_public(SERVER_REC *server, const char *msg, const char *nick, const char *address, const char *target) @@ -126,6 +158,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg, static void sig_message_private(SERVER_REC *server, const char *msg, const char *nick, const char *address) { + g_return_if_fail(server != NULL); + g_return_if_fail(nick != NULL); + SERVER_LAST_MSG_ADD(server, nick); } @@ -166,7 +201,7 @@ static void sig_message_own_private(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) { g_return_if_fail(server != NULL); - g_return_if_fail(msg != NULL); + g_return_if_fail(target != NULL); if (target != NULL && query_find(server, target) == NULL) SERVER_LAST_MSG_ADD(server, target); @@ -201,11 +236,11 @@ static int last_msg_cmp(LAST_MSG_REC *m1, LAST_MSG_REC *m2) return m1->time < m2->time ? 1 : -1; } -/* Complete /MSG from specified server */ +/* Complete /MSG from specified server, or from + global_lastmsgs if server is NULL */ static void completion_msg_server(GSList **list, SERVER_REC *server, const char *nick, const char *prefix) { - MODULE_SERVER_REC *mserver; LAST_MSG_REC *msg; GSList *tmp; int len; @@ -213,8 +248,9 @@ static void completion_msg_server(GSList **list, SERVER_REC *server, g_return_if_fail(nick != NULL); len = strlen(nick); - mserver = MODULE_DATA(server); - for (tmp = mserver->lastmsgs; tmp != NULL; tmp = tmp->next) { + tmp = server == NULL ? global_lastmsgs : + ((MODULE_SERVER_REC *) MODULE_DATA(server))->lastmsgs; + for (; tmp != NULL; tmp = tmp->next) { LAST_MSG_REC *rec = tmp->data; if (len != 0 && g_strncasecmp(rec->nick, nick, len) != 0) @@ -264,6 +300,7 @@ static GList *completion_msg(SERVER_REC *win_server, return convert_msglist(list); } + completion_msg_server(&list, NULL, nick, prefix); for (tmp = servers; tmp != NULL; tmp = tmp->next) { SERVER_REC *rec = tmp->data; @@ -739,6 +776,9 @@ void chat_completion_init(void) void chat_completion_deinit(void) { + while (global_lastmsgs != NULL) + last_msg_destroy(&global_lastmsgs, global_lastmsgs->data); + signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word); signal_remove("complete command msg", (SIGNAL_FUNC) sig_complete_msg); signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect); diff --git a/src/fe-common/core/chat-completion.h b/src/fe-common/core/chat-completion.h new file mode 100644 index 00000000..3cb70ca5 --- /dev/null +++ b/src/fe-common/core/chat-completion.h @@ -0,0 +1,8 @@ +#ifndef __CHAT_COMPLETION_H +#define __CHAT_COMPLETION_H + +void completion_last_message_add(const char *nick); +void completion_last_message_remove(const char *nick); +void completion_last_message_rename(const char *oldnick, const char *newnick); + +#endif diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index acb322c8..4301715a 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -32,6 +32,7 @@ #include "irc/dcc/dcc-chat.h" #include "completion.h" +#include "chat-completion.h" #include "themes.h" #include "fe-windows.h" @@ -53,9 +54,14 @@ static void dcc_connected(DCC_REC *dcc) printformat(dcc->server, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_CONNECTED, dcc->chat_id, dcc->addrstr, dcc->port); - if (autocreate_dccquery && query_find(NULL, sender) == NULL) - irc_query_create(dcc->server == NULL ? NULL : - dcc->server->tag, sender, TRUE); + if (query_find(NULL, sender) == NULL) { + if (!autocreate_dccquery) + completion_last_message_add(sender); + else + irc_query_create(dcc->server == NULL ? NULL : + dcc->server->tag, + sender, TRUE); + } g_free(sender); break; case DCC_TYPE_SEND: @@ -135,6 +141,8 @@ static void dcc_chat_action(const char *msg, DCC_REC *dcc) g_return_if_fail(msg != NULL); sender = g_strconcat("=", dcc->chat_id, NULL); + if (query_find(NULL, sender) == NULL) + completion_last_message_add(sender); printformat(NULL, sender, MSGLEVEL_DCCMSGS, IRCTXT_ACTION_DCC, dcc->chat_id, msg); g_free(sender); @@ -169,10 +177,13 @@ static void dcc_chat_msg(DCC_REC *dcc, const char *msg) else freemsg = NULL; + if (query_find(NULL, sender) == NULL) + completion_last_message_add(sender); printformat(NULL, sender, MSGLEVEL_DCCMSGS, query != NULL ? IRCTXT_DCC_MSG_QUERY : IRCTXT_DCC_MSG, dcc->chat_id, msg); - g_free_not_null(freemsg); + + g_free_not_null(freemsg); g_free(sender); } @@ -327,14 +338,19 @@ static void sig_dcc_destroyed(DCC_REC *dcc) return; nick = g_strconcat("=", dcc->chat_id, NULL); - query = query_find(NULL, nick); - g_free(nick); + query = query_find(NULL, nick); if (query != NULL) { /* DCC chat closed, close the query with it. */ if (dcc->connection_lost) query->unwanted = TRUE; query_destroy(query); + } else { + /* remove nick from msg completion + since it won't work anymore */ + completion_last_message_remove(nick); } + + g_free(nick); } static void sig_query_destroyed(QUERY_REC *query) @@ -354,6 +370,7 @@ static void sig_query_destroyed(QUERY_REC *query) static void cmd_msg(const char *data) { + QUERY_REC *query; DCC_REC *dcc; char *text, *target; void *free_arg; @@ -374,9 +391,13 @@ static void cmd_msg(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_DCC_CHAT_NOT_FOUND, target+1); } else { + query = query_find(NULL, target); + printformat(NULL, target, MSGLEVEL_DCCMSGS | MSGLEVEL_NOHILIGHT, - query_find(NULL, target) ? IRCTXT_OWN_DCC_QUERY : + query != NULL ? IRCTXT_OWN_DCC_QUERY : IRCTXT_OWN_DCC, dcc->mynick, target+1, text); + if (query == NULL) + completion_last_message_add(target); } cmd_params_free(free_arg); @@ -392,11 +413,12 @@ static void cmd_me(const char *data, SERVER_REC *server, WI_ITEM_REC *item) if (dcc == NULL) return; printformat(NULL, item->name, MSGLEVEL_DCCMSGS | MSGLEVEL_NOHILIGHT, - IRCTXT_OWN_DCC_ACTION, dcc->mynick, data); + IRCTXT_OWN_DCC_ACTION_QUERY, dcc->mynick, item->name, data); } static void cmd_action(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { + QUERY_REC *query; DCC_REC *dcc; char *target, *text; void *free_arg; @@ -419,8 +441,13 @@ static void cmd_action(const char *data, SERVER_REC *server, WI_ITEM_REC *item) printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_DCC_CHAT_NOT_FOUND, target+1); } else { + query = query_find(NULL, target); + printformat(NULL, target, MSGLEVEL_DCCMSGS | MSGLEVEL_NOHILIGHT, - IRCTXT_OWN_DCC_ACTION, dcc->mynick, text); + query != NULL ? IRCTXT_OWN_DCC_ACTION_QUERY : + IRCTXT_OWN_DCC_ACTION, dcc->mynick, target, text); + if (query == NULL) + completion_last_message_add(target); } cmd_params_free(free_arg); } diff --git a/src/fe-common/irc/dcc/module-formats.c b/src/fe-common/irc/dcc/module-formats.c index 57ddda63..3c5cce35 100644 --- a/src/fe-common/irc/dcc/module-formats.c +++ b/src/fe-common/irc/dcc/module-formats.c @@ -28,7 +28,8 @@ FORMAT_REC fecommon_irc_dcc_formats[] = { { NULL, "DCC", 0 }, { "own_dcc", "{dccownmsg dcc {dccownnick $1}}$2", 3, { 0, 0, 0 } }, - { "own_dcc_action", "{dccownaction $0}$1", 2, { 0, 0 } }, + { "own_dcc_action", "{dccownaction_target $0 $1}$2", 3, { 0, 0, 0 } }, + { "own_dcc_action_query", "{dccownaction $0}$2", 3, { 0, 0, 0 } }, { "own_dcc_ctcp", "{ownctcp ctcp $0}$1 $2", 3, { 0, 0, 0 } }, { "dcc_msg", "{dccmsg dcc $0}$1", 2, { 0, 0 } }, { "action_dcc", "{dccaction $0}$1", 2, { 0, 0 } }, diff --git a/src/fe-common/irc/dcc/module-formats.h b/src/fe-common/irc/dcc/module-formats.h index 3cbb89da..45839220 100644 --- a/src/fe-common/irc/dcc/module-formats.h +++ b/src/fe-common/irc/dcc/module-formats.h @@ -7,6 +7,7 @@ enum { IRCTXT_OWN_DCC, IRCTXT_OWN_DCC_ACTION, + IRCTXT_OWN_DCC_ACTION_QUERY, IRCTXT_OWN_DCC_CTCP, IRCTXT_DCC_MSG, IRCTXT_ACTION_DCC,