mirror of
https://github.com/irssi/irssi.git
synced 2025-01-03 14:56:47 -05:00
implement expando cache
- the expando values need to be stored now that the lines are reformattable, otherwise the old values are lost (and they depend on context only available at the time the line is initially printed) - the cache is collected from the special-vars evaluation code - the cache is controlled by the textbuffer-formats code, and stored in the text_buffer_format_rec
This commit is contained in:
parent
f95fc81130
commit
6b93d6e338
@ -34,16 +34,17 @@
|
||||
#endif
|
||||
|
||||
#include <irssi/src/core/chat-protocols.h>
|
||||
#include <irssi/src/core/servers.h>
|
||||
#include <irssi/src/core/chatnets.h>
|
||||
#include <irssi/src/core/commands.h>
|
||||
#include <irssi/src/core/expandos.h>
|
||||
#include <irssi/src/core/write-buffer.h>
|
||||
#include <irssi/src/core/ignore.h>
|
||||
#include <irssi/src/core/log.h>
|
||||
#include <irssi/src/core/rawlog.h>
|
||||
#include <irssi/src/core/ignore.h>
|
||||
#include <irssi/src/core/recode.h>
|
||||
#include <irssi/src/core/refstrings.h>
|
||||
#include <irssi/src/core/servers.h>
|
||||
#include <irssi/src/core/special-vars.h>
|
||||
#include <irssi/src/core/write-buffer.h>
|
||||
|
||||
#include <irssi/src/core/channels.h>
|
||||
#include <irssi/src/core/queries.h>
|
||||
@ -262,6 +263,7 @@ void core_init(void)
|
||||
|
||||
chat_commands_init();
|
||||
i_refstr_init();
|
||||
special_vars_init();
|
||||
wcwidth_wrapper_init();
|
||||
|
||||
settings_add_str("misc", "ignore_signals", "");
|
||||
@ -288,6 +290,7 @@ void core_deinit(void)
|
||||
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
|
||||
|
||||
wcwidth_wrapper_deinit();
|
||||
special_vars_deinit();
|
||||
i_refstr_deinit();
|
||||
chat_commands_deinit();
|
||||
|
||||
|
@ -19,12 +19,13 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include <irssi/src/core/expandos.h>
|
||||
#include <irssi/src/core/misc.h>
|
||||
#include <irssi/src/core/refstrings.h>
|
||||
#include <irssi/src/core/servers.h>
|
||||
#include <irssi/src/core/settings.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/special-vars.h>
|
||||
#include <irssi/src/core/expandos.h>
|
||||
#include <irssi/src/core/settings.h>
|
||||
#include <irssi/src/core/servers.h>
|
||||
#include <irssi/src/core/misc.h>
|
||||
#include <irssi/src/core/utf8.h>
|
||||
|
||||
#define isvarchar(c) \
|
||||
@ -40,6 +41,8 @@
|
||||
#endif
|
||||
|
||||
static SPECIAL_HISTORY_FUNC history_func = NULL;
|
||||
static GSList *special_collector;
|
||||
static GSList *special_cache;
|
||||
|
||||
static char *get_argument(char **cmd, char **arglist)
|
||||
{
|
||||
@ -121,8 +124,40 @@ static char *get_long_variable_value(const char *key, SERVER_REC *server,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_long_variable(char **cmd, SERVER_REC *server,
|
||||
void *item, int *free_ret, int getname)
|
||||
static gboolean cache_find(GSList **cache, const char *var, char **ret)
|
||||
{
|
||||
GSList *tmp;
|
||||
GSList *prev = NULL;
|
||||
|
||||
if (cache == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (tmp = *cache; tmp;) {
|
||||
if (g_strcmp0(var, tmp->data) == 0) {
|
||||
*ret = tmp->next->data;
|
||||
if (prev != NULL)
|
||||
prev->next->next = tmp->next->next;
|
||||
else
|
||||
*cache = tmp->next->next;
|
||||
|
||||
g_slist_free_1(tmp->next);
|
||||
g_slist_free_1(tmp);
|
||||
return TRUE;
|
||||
}
|
||||
prev = tmp;
|
||||
tmp = tmp->next->next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean cache_find_char(GSList **cache, char var, char **ret)
|
||||
{
|
||||
char varn[] = { var, '\0' };
|
||||
return cache_find(cache, varn, ret);
|
||||
}
|
||||
|
||||
static char *get_long_variable(char **cmd, SERVER_REC *server, void *item, int *free_ret,
|
||||
int getname, GSList **collector, GSList **cache)
|
||||
{
|
||||
char *start, *var, *ret;
|
||||
|
||||
@ -135,16 +170,23 @@ static char *get_long_variable(char **cmd, SERVER_REC *server,
|
||||
*free_ret = TRUE;
|
||||
return var;
|
||||
}
|
||||
if (cache_find(cache, var, &ret)) {
|
||||
g_free(var);
|
||||
return ret;
|
||||
}
|
||||
ret = get_long_variable_value(var, server, item, free_ret);
|
||||
if (collector != NULL) {
|
||||
*collector = g_slist_prepend(*collector, g_strdup(ret));
|
||||
*collector = g_slist_prepend(*collector, i_refstr_intern(var));
|
||||
}
|
||||
g_free(var);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* return the value of the variable found from `cmd'.
|
||||
if 'getname' is TRUE, return the name of the variable instead it's value */
|
||||
static char *get_variable(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used,
|
||||
int getname)
|
||||
static char *get_variable(char **cmd, SERVER_REC *server, void *item, char **arglist, int *free_ret,
|
||||
int *arg_used, int getname, GSList **collector, GSList **cache)
|
||||
{
|
||||
EXPANDO_FUNC func;
|
||||
|
||||
@ -158,7 +200,7 @@ static char *get_variable(char **cmd, SERVER_REC *server, void *item,
|
||||
|
||||
if (i_isalpha(**cmd) && isvarchar((*cmd)[1])) {
|
||||
/* long variable name.. */
|
||||
return get_long_variable(cmd, server, item, free_ret, getname);
|
||||
return get_long_variable(cmd, server, item, free_ret, getname, collector, cache);
|
||||
}
|
||||
|
||||
/* single character variable. */
|
||||
@ -167,15 +209,27 @@ static char *get_variable(char **cmd, SERVER_REC *server, void *item,
|
||||
return g_strdup_printf("%c", **cmd);
|
||||
}
|
||||
*free_ret = FALSE;
|
||||
{
|
||||
char *ret;
|
||||
if (cache_find_char(cache, **cmd, &ret)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
func = expando_find_char(**cmd);
|
||||
if (func == NULL)
|
||||
return NULL;
|
||||
else {
|
||||
char str[2];
|
||||
char *ret;
|
||||
|
||||
str[0] = **cmd; str[1] = '\0';
|
||||
current_expando = str;
|
||||
return func(server, item, free_ret);
|
||||
ret = func(server, item, free_ret);
|
||||
if (**cmd != 'Z' && collector != NULL) {
|
||||
*collector = g_slist_prepend(*collector, g_strdup(ret));
|
||||
*collector = g_slist_prepend(*collector, i_refstr_intern(str));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,9 +253,9 @@ static char *get_history(char **cmd, void *item, int *free_ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *get_special_value(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used,
|
||||
int flags)
|
||||
static char *get_special_value(char **cmd, SERVER_REC *server, void *item, char **arglist,
|
||||
int *free_ret, int *arg_used, int flags, GSList **collector,
|
||||
GSList **cache)
|
||||
{
|
||||
char command, *value, *p;
|
||||
int len;
|
||||
@ -236,8 +290,8 @@ static char *get_special_value(char **cmd, SERVER_REC *server, void *item,
|
||||
}
|
||||
}
|
||||
|
||||
value = get_variable(cmd, server, item, arglist, free_ret,
|
||||
arg_used, flags & PARSE_FLAG_GETNAME);
|
||||
value = get_variable(cmd, server, item, arglist, free_ret, arg_used,
|
||||
flags & PARSE_FLAG_GETNAME, collector, cache);
|
||||
|
||||
if (flags & PARSE_FLAG_GETNAME)
|
||||
return value;
|
||||
@ -440,8 +494,9 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item,
|
||||
brackets = TRUE;
|
||||
}
|
||||
|
||||
value = get_special_value(cmd, server, item, arglist,
|
||||
free_ret, arg_used, flags);
|
||||
value = get_special_value(cmd, server, item, arglist, free_ret, arg_used, flags,
|
||||
special_collector != NULL ? special_collector->data : NULL,
|
||||
&special_cache);
|
||||
if (**cmd == '\0')
|
||||
g_error("parse_special() : buffer overflow!");
|
||||
|
||||
@ -635,6 +690,22 @@ void special_history_func_set(SPECIAL_HISTORY_FUNC func)
|
||||
history_func = func;
|
||||
}
|
||||
|
||||
void special_push_collector(GSList **list)
|
||||
{
|
||||
special_collector = g_slist_prepend(special_collector, list);
|
||||
}
|
||||
|
||||
void special_pop_collector(void)
|
||||
{
|
||||
special_collector = g_slist_delete_link(special_collector, special_collector);
|
||||
}
|
||||
|
||||
void special_fill_cache(GSList *list)
|
||||
{
|
||||
g_slist_free(special_cache);
|
||||
special_cache = g_slist_copy(list);
|
||||
}
|
||||
|
||||
static void update_signals_hash(GHashTable **hash, int *signals)
|
||||
{
|
||||
void *signal_id;
|
||||
@ -758,3 +829,15 @@ int *special_vars_get_signals(const char *text)
|
||||
{
|
||||
return special_vars_signals_task(text, 0, NULL, TASK_GET_SIGNALS);
|
||||
}
|
||||
|
||||
void special_vars_init(void)
|
||||
{
|
||||
special_cache = NULL;
|
||||
special_collector = NULL;
|
||||
}
|
||||
|
||||
void special_vars_deinit(void)
|
||||
{
|
||||
g_slist_free(special_cache);
|
||||
g_slist_free(special_collector);
|
||||
}
|
||||
|
@ -32,6 +32,11 @@ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item,
|
||||
void eval_special_string(const char *cmd, const char *data,
|
||||
SERVER_REC *server, void *item);
|
||||
|
||||
void special_push_collector(GSList **list);
|
||||
void special_pop_collector(void);
|
||||
|
||||
void special_fill_cache(GSList *list);
|
||||
|
||||
void special_history_func_set(SPECIAL_HISTORY_FUNC func);
|
||||
|
||||
void special_vars_add_signals(const char *text,
|
||||
@ -41,4 +46,8 @@ void special_vars_remove_signals(const char *text,
|
||||
/* Returns [<signal id>, EXPANDO_ARG_xxx, <signal id>, ..., -1] */
|
||||
int *special_vars_get_signals(const char *text);
|
||||
|
||||
void special_vars_init(void);
|
||||
|
||||
void special_vars_deinit(void);
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <irssi/src/core/refstrings.h>
|
||||
#include <irssi/src/core/servers.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/special-vars.h>
|
||||
#include <irssi/src/fe-common/core/printtext.h>
|
||||
#include <irssi/src/fe-common/core/themes.h>
|
||||
#include <irssi/src/fe-text/gui-printtext.h>
|
||||
@ -13,6 +14,18 @@
|
||||
|
||||
TEXT_BUFFER_REC *color_buf;
|
||||
|
||||
static void collector_free(GSList **collector)
|
||||
{
|
||||
while (*collector) {
|
||||
GSList *next = (*collector)->next->next;
|
||||
i_refstr_release((*collector)->data);
|
||||
g_free((*collector)->next->data);
|
||||
g_slist_free_1((*collector)->next);
|
||||
g_slist_free_1((*collector));
|
||||
*collector = next;
|
||||
}
|
||||
}
|
||||
|
||||
void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec)
|
||||
{
|
||||
int n;
|
||||
@ -35,6 +48,7 @@ void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec)
|
||||
}
|
||||
rec->nargs = 0;
|
||||
g_free(rec->args);
|
||||
collector_free(&rec->expando_cache);
|
||||
g_slice_free(TEXT_BUFFER_FORMAT_REC, rec);
|
||||
}
|
||||
|
||||
@ -112,12 +126,14 @@ static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC
|
||||
|
||||
info->format = format_rec_new(module, formats[formatnum].tag, dest->server_tag,
|
||||
dest->target, dest->nick, formats[formatnum].params, args);
|
||||
special_push_collector(&info->format->expando_cache);
|
||||
|
||||
info->format->flags = dest->flags;
|
||||
dest->flags |= PRINT_FLAG_FORMAT;
|
||||
|
||||
signal_continue(5, theme, module, dest, formatnump, args);
|
||||
|
||||
special_pop_collector();
|
||||
free_lineinfo_tmp(dest->window);
|
||||
}
|
||||
|
||||
@ -125,19 +141,36 @@ static void sig_print_noformat(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
LINE_INFO_REC *info;
|
||||
|
||||
special_push_collector(NULL);
|
||||
info = store_lineinfo_tmp(dest);
|
||||
|
||||
info->format = format_rec_new(NULL, NULL, dest->server_tag, dest->target, dest->nick, 2,
|
||||
(const char *[]){ NULL, text });
|
||||
special_push_collector(&info->format->expando_cache);
|
||||
|
||||
info->format->flags = dest->flags;
|
||||
dest->flags |= PRINT_FLAG_FORMAT;
|
||||
|
||||
signal_continue(2, dest, text);
|
||||
|
||||
special_pop_collector();
|
||||
free_lineinfo_tmp(dest->window);
|
||||
}
|
||||
|
||||
static GSList *reverse_collector(GSList *a1)
|
||||
{
|
||||
GSList *b1, *c1;
|
||||
c1 = NULL;
|
||||
while (a1) {
|
||||
b1 = a1->next->next;
|
||||
a1->next->next = c1;
|
||||
|
||||
c1 = a1;
|
||||
a1 = b1;
|
||||
}
|
||||
return c1;
|
||||
}
|
||||
|
||||
static void sig_gui_print_text_finished(WINDOW_REC *window)
|
||||
{
|
||||
GUI_WINDOW_REC *gui;
|
||||
@ -157,6 +190,8 @@ static void sig_gui_print_text_finished(WINDOW_REC *window)
|
||||
if (info->format == NULL)
|
||||
return;
|
||||
|
||||
info->format->expando_cache = reverse_collector(info->format->expando_cache);
|
||||
|
||||
info->level |= MSGLEVEL_FORMAT;
|
||||
|
||||
/* the line will be inserted into the view with textbuffer_view_insert_line by
|
||||
@ -182,7 +217,7 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
if (line == NULL || gui == NULL)
|
||||
return NULL;
|
||||
|
||||
if (line->info.level & MSGLEVEL_FORMAT) {
|
||||
if (line->info.level & MSGLEVEL_FORMAT && line->info.format != NULL) {
|
||||
TEXT_DEST_REC dest;
|
||||
THEME_REC *theme;
|
||||
int formatnum;
|
||||
@ -200,6 +235,7 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
|
||||
theme = window_get_theme(dest.window);
|
||||
|
||||
special_fill_cache(format_rec->expando_cache);
|
||||
if (format_rec->format != NULL) {
|
||||
char *arglist[MAX_FORMAT_PARAMS] = { 0 };
|
||||
formatnum = format_find_tag(format_rec->module, format_rec->format);
|
||||
@ -238,6 +274,7 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
special_fill_cache(NULL);
|
||||
} else {
|
||||
return g_strdup(line->info.text);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ typedef struct _TEXT_BUFFER_FORMAT_REC {
|
||||
char *nick;
|
||||
char **args;
|
||||
int nargs;
|
||||
GSList *expando_cache;
|
||||
int flags;
|
||||
} TEXT_BUFFER_FORMAT_REC;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user