mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05:00
Merge pull request #1079 from ailin-nemui/reformat2
reapply a theme to previous formats
This commit is contained in:
commit
86b72d5829
@ -6,7 +6,7 @@
|
||||
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
|
||||
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
|
||||
|
||||
#define IRSSI_ABI_VERSION 26
|
||||
#define IRSSI_ABI_VERSION 27
|
||||
|
||||
#define DEFAULT_SERVER_ADD_PORT 6667
|
||||
#define DEFAULT_SERVER_ADD_TLS_PORT 6697
|
||||
|
@ -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();
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
difficult message leveling system (which might be done if really
|
||||
needed..). */
|
||||
|
||||
/* clang-format off */
|
||||
/* Message levels */
|
||||
enum {
|
||||
MSGLEVEL_CRAP = 0x0000001,
|
||||
@ -38,8 +39,12 @@ enum {
|
||||
MSGLEVEL_NEVER = 0x4000000, /* never ignore / never log */
|
||||
MSGLEVEL_LASTLOG = 0x8000000, /* used for /lastlog */
|
||||
|
||||
MSGLEVEL_HIDDEN = 0x10000000 /* Hidden from view */
|
||||
MSGLEVEL_HIDDEN = 0x10000000, /* Hidden from view */
|
||||
MSGLEVEL_RESERVED1 = 0x20000000,
|
||||
MSGLEVEL_RESERVED2 = 0x40000000,
|
||||
MSGLEVEL_FORMAT = 0x80000000 /* Format data */
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
int level_get(const char *level);
|
||||
int level2bits(const char *level, int *errorp);
|
||||
|
@ -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
|
||||
|
@ -233,6 +233,7 @@ static void event_command(const char *data)
|
||||
(data[1] == *cmdchar && data[2] == '^'))
|
||||
&& !command_hide_output++) {
|
||||
signal_add_first("print starting", (SIGNAL_FUNC) sig_stop);
|
||||
signal_add_first("print noformat", (SIGNAL_FUNC) sig_stop);
|
||||
signal_add_first("print format", (SIGNAL_FUNC) sig_stop);
|
||||
signal_add_first("print text", (SIGNAL_FUNC) sig_stop);
|
||||
}
|
||||
@ -242,6 +243,7 @@ static void event_command_last(const char *data)
|
||||
{
|
||||
if (command_hide_output && !--command_hide_output) {
|
||||
signal_remove("print starting", (SIGNAL_FUNC) sig_stop);
|
||||
signal_remove("print noformat", (SIGNAL_FUNC) sig_stop);
|
||||
signal_remove("print format", (SIGNAL_FUNC) sig_stop);
|
||||
signal_remove("print text", (SIGNAL_FUNC) sig_stop);
|
||||
}
|
||||
|
@ -850,14 +850,13 @@ char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest, time_t t)
|
||||
return linestart;
|
||||
}
|
||||
|
||||
void format_newline(WINDOW_REC *window)
|
||||
void format_newline(TEXT_DEST_REC *dest)
|
||||
{
|
||||
g_return_if_fail(window != NULL);
|
||||
g_return_if_fail(dest != NULL);
|
||||
g_return_if_fail(dest->window != NULL);
|
||||
|
||||
signal_emit_id(signal_gui_print_text, 6, window,
|
||||
GINT_TO_POINTER(-1), GINT_TO_POINTER(-1),
|
||||
GINT_TO_POINTER(GUI_PRINT_FLAG_NEWLINE),
|
||||
"", NULL);
|
||||
signal_emit_id(signal_gui_print_text, 6, dest->window, GINT_TO_POINTER(-1),
|
||||
GINT_TO_POINTER(-1), GINT_TO_POINTER(GUI_PRINT_FLAG_NEWLINE), "", dest);
|
||||
}
|
||||
|
||||
#ifndef TERM_TRUECOLOR
|
||||
@ -1223,8 +1222,14 @@ char *strip_codes(const char *input)
|
||||
return str;
|
||||
}
|
||||
|
||||
/* send a fully parsed text string for GUI to print */
|
||||
void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
/* parse text string into GUI_PRINT_FLAG_* separated pieces and emit them to handler
|
||||
handler is a SIGNAL_FUNC with the following arguments:
|
||||
|
||||
WINDOW_REC *window, void *fgcolor_int, void *bgcolor_int,
|
||||
void *flags_int, const char *textpiece, TEXT_DEST_REC *dest
|
||||
|
||||
*/
|
||||
void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC handler)
|
||||
{
|
||||
THEME_REC *theme;
|
||||
char *dup, *str, *ptr, type;
|
||||
@ -1239,8 +1244,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
|
||||
if (*str == '\0') {
|
||||
/* empty line, write line info only */
|
||||
signal_emit_id(signal_gui_print_text, 6, dest->window, GINT_TO_POINTER(fgcolor),
|
||||
GINT_TO_POINTER(bgcolor), GINT_TO_POINTER(flags), str, dest);
|
||||
handler(dest->window, GINT_TO_POINTER(fgcolor), GINT_TO_POINTER(bgcolor),
|
||||
GINT_TO_POINTER(flags), str, dest);
|
||||
}
|
||||
|
||||
while (*str != '\0') {
|
||||
@ -1260,16 +1265,14 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
|
||||
if (*str != '\0' || (flags & GUI_PRINT_FLAG_CLRTOEOL)) {
|
||||
/* send the text to gui handler */
|
||||
signal_emit_id(signal_gui_print_text, 6, dest->window,
|
||||
GINT_TO_POINTER(fgcolor),
|
||||
GINT_TO_POINTER(bgcolor),
|
||||
GINT_TO_POINTER(flags), str,
|
||||
dest);
|
||||
handler(dest->window, GINT_TO_POINTER(fgcolor), GINT_TO_POINTER(bgcolor),
|
||||
GINT_TO_POINTER(flags), str, dest);
|
||||
flags &= ~(GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_CLRTOEOL);
|
||||
}
|
||||
|
||||
if (type == '\n') {
|
||||
format_newline(dest->window);
|
||||
handler(dest->window, GINT_TO_POINTER(-1), GINT_TO_POINTER(-1),
|
||||
GINT_TO_POINTER(GUI_PRINT_FLAG_NEWLINE), "", dest);
|
||||
fgcolor = theme->default_color;
|
||||
bgcolor = -1;
|
||||
flags &= GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_MONOSPACE;
|
||||
@ -1415,6 +1418,104 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
g_free(dup);
|
||||
}
|
||||
|
||||
inline static void gui_print_text_emitter(WINDOW_REC *window, void *fgcolor_int, void *bgcolor_int,
|
||||
void *flags_int, const char *textpiece,
|
||||
TEXT_DEST_REC *dest)
|
||||
{
|
||||
signal_emit_id(signal_gui_print_text, 6, window, fgcolor_int, bgcolor_int, flags_int,
|
||||
textpiece, dest);
|
||||
}
|
||||
|
||||
/* send a fully parsed text string for GUI to print */
|
||||
void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
format_send_as_gui_flags(dest, text, (SIGNAL_FUNC) gui_print_text_emitter);
|
||||
}
|
||||
|
||||
void format_gui_flags(GString *out, int *last_fg, int *last_bg, int *last_flags, int fg, int bg,
|
||||
int flags)
|
||||
{
|
||||
if (fg != *last_fg ||
|
||||
(flags & GUI_PRINT_FLAG_COLOR_24_FG) != (*last_flags & GUI_PRINT_FLAG_COLOR_24_FG)) {
|
||||
*last_fg = fg;
|
||||
|
||||
#ifdef TERM_TRUECOLOR
|
||||
if (flags & GUI_PRINT_FLAG_COLOR_24_FG) {
|
||||
*last_flags |= GUI_PRINT_FLAG_COLOR_24_FG;
|
||||
format_24bit_color(out, 0, fg);
|
||||
} else {
|
||||
*last_flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
|
||||
#endif
|
||||
if (fg < 0) {
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, (char) -1);
|
||||
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
|
||||
} else {
|
||||
format_ext_color(out, 0, fg);
|
||||
}
|
||||
#ifdef TERM_TRUECOLOR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (bg != *last_bg ||
|
||||
(flags & GUI_PRINT_FLAG_COLOR_24_BG) != (*last_flags & GUI_PRINT_FLAG_COLOR_24_BG)) {
|
||||
*last_bg = bg;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
if (flags & GUI_PRINT_FLAG_COLOR_24_BG) {
|
||||
*last_flags |= GUI_PRINT_FLAG_COLOR_24_BG;
|
||||
format_24bit_color(out, 1, bg);
|
||||
} else {
|
||||
*last_flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
|
||||
#endif
|
||||
if (bg < 0) {
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
|
||||
g_string_append_c(out, (char) -1);
|
||||
} else {
|
||||
format_ext_color(out, 1, bg);
|
||||
}
|
||||
#ifdef TERM_TRUECOLOR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((flags & GUI_PRINT_FLAG_UNDERLINE) != (*last_flags & GUI_PRINT_FLAG_UNDERLINE)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_UNDERLINE;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_UNDERLINE);
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_REVERSE) != (*last_flags & GUI_PRINT_FLAG_REVERSE)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_REVERSE;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_REVERSE);
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_BLINK) != (*last_flags & GUI_PRINT_FLAG_BLINK)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_BLINK;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_BLINK);
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_BOLD) != (*last_flags & GUI_PRINT_FLAG_BOLD)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_BOLD;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_BOLD);
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_ITALIC) != (*last_flags & GUI_PRINT_FLAG_ITALIC)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_ITALIC;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_ITALIC);
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_MONOSPACE) != (*last_flags & GUI_PRINT_FLAG_MONOSPACE)) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_MONOSPACE;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_MONOSPACE);
|
||||
}
|
||||
if (flags & GUI_PRINT_FLAG_INDENT) {
|
||||
*last_flags ^= GUI_PRINT_FLAG_INDENT;
|
||||
g_string_append_c(out, 4);
|
||||
g_string_append_c(out, FORMAT_STYLE_INDENT);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
timestamp_level = settings_get_bool("timestamps") ? MSGLEVEL_ALL : 0;
|
||||
|
@ -1,8 +1,9 @@
|
||||
#ifndef IRSSI_FE_COMMON_CORE_FORMATS_H
|
||||
#define IRSSI_FE_COMMON_CORE_FORMATS_H
|
||||
|
||||
#include <irssi/src/fe-common/core/themes.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/fe-common/core/fe-windows.h>
|
||||
#include <irssi/src/fe-common/core/themes.h>
|
||||
|
||||
#define GUI_PRINT_FLAG_BOLD 0x0001
|
||||
#define GUI_PRINT_FLAG_REVERSE 0x0002
|
||||
@ -35,6 +36,7 @@ struct _FORMAT_REC {
|
||||
int paramtypes[MAX_FORMAT_PARAMS];
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
#define PRINT_FLAG_SET_LINE_START 0x0001
|
||||
#define PRINT_FLAG_SET_LINE_START_IRSSI 0x0002
|
||||
#define PRINT_FLAG_UNSET_LINE_START 0x0040
|
||||
@ -45,6 +47,9 @@ struct _FORMAT_REC {
|
||||
#define PRINT_FLAG_SET_SERVERTAG 0x0010
|
||||
#define PRINT_FLAG_UNSET_SERVERTAG 0x0020
|
||||
|
||||
#define PRINT_FLAG_FORMAT 0x0080
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct _HILIGHT_REC HILIGHT_REC;
|
||||
|
||||
typedef struct _TEXT_DEST_REC {
|
||||
@ -113,7 +118,7 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server,
|
||||
const char *server_tag, const char *target,
|
||||
int level, WINDOW_REC *window);
|
||||
|
||||
void format_newline(WINDOW_REC *window);
|
||||
void format_newline(TEXT_DEST_REC *dest);
|
||||
|
||||
/* Return how many characters in `str' must be skipped before `len'
|
||||
characters of text is skipped. */
|
||||
@ -126,6 +131,14 @@ char *strip_codes(const char *input);
|
||||
|
||||
/* send a fully parsed text string for GUI to print */
|
||||
void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
|
||||
/* parse text string into GUI_PRINT_FLAG_* separated pieces and emit them to handler
|
||||
handler is a SIGNAL_FUNC with the following arguments:
|
||||
|
||||
WINDOW_REC *window, void *fgcolor_int, void *bgcolor_int,
|
||||
void *flags_int, const char *textpiece, TEXT_DEST_REC *dest
|
||||
|
||||
*/
|
||||
void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC handler);
|
||||
|
||||
#define FORMAT_COLOR_NOCHANGE ('0'-1) /* don't change this, at least hilighting depends this value */
|
||||
#define FORMAT_COLOR_EXT1 ('0'-2)
|
||||
@ -151,6 +164,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
|
||||
int format_expand_styles(GString *out, const char **format, int *flags);
|
||||
void format_ext_color(GString *out, int bg, int color);
|
||||
void format_24bit_color(GString *out, int bg, unsigned int color);
|
||||
void format_gui_flags(GString *out, int *last_fg, int *last_bg, int *last_flags, int fg, int bg,
|
||||
int flags);
|
||||
|
||||
void formats_init(void);
|
||||
void formats_deinit(void);
|
||||
|
@ -42,7 +42,7 @@ static int signal_print_noformat;
|
||||
|
||||
static int sending_print_starting;
|
||||
|
||||
static void print_line(TEXT_DEST_REC *dest, const char *text);
|
||||
static void print_line(TEXT_DEST_REC *dest, const char *text, int formatted);
|
||||
|
||||
void printformat_module_dest_args(const char *module, TEXT_DEST_REC *dest,
|
||||
int formatnum, va_list va)
|
||||
@ -63,7 +63,6 @@ void printformat_module_dest_charargs(const char *module, TEXT_DEST_REC *dest,
|
||||
int formatnum, char **arglist)
|
||||
{
|
||||
THEME_REC *theme;
|
||||
char *str;
|
||||
|
||||
theme = window_get_theme(dest->window);
|
||||
|
||||
@ -75,11 +74,6 @@ void printformat_module_dest_charargs(const char *module, TEXT_DEST_REC *dest,
|
||||
|
||||
signal_emit_id(signal_print_format, 5, theme, module,
|
||||
dest, GINT_TO_POINTER(formatnum), arglist);
|
||||
|
||||
str = format_get_text_theme_charargs(theme, module, dest,
|
||||
formatnum, arglist);
|
||||
if (str != NULL && *str != '\0') print_line(dest, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
void printformat_module_dest(const char *module, TEXT_DEST_REC *dest,
|
||||
@ -164,29 +158,6 @@ void printformat_module_gui(const char *module, int formatnum, ...)
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void print_line(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
THEME_REC *theme;
|
||||
char *str, *tmp, *stripped;
|
||||
|
||||
g_return_if_fail(dest != NULL);
|
||||
g_return_if_fail(text != NULL);
|
||||
|
||||
theme = window_get_theme(dest->window);
|
||||
tmp = format_get_level_tag(theme, dest);
|
||||
str = !theme->info_eol ? format_add_linestart(text, tmp) :
|
||||
format_add_lineend(text, tmp);
|
||||
g_free_not_null(tmp);
|
||||
|
||||
/* send both the formatted + stripped (for logging etc.) */
|
||||
stripped = strip_codes(str);
|
||||
signal_emit_id(signal_print_text, 3, dest, str, stripped);
|
||||
g_free_and_null(dest->hilight_color);
|
||||
|
||||
g_free(str);
|
||||
g_free(stripped);
|
||||
}
|
||||
|
||||
/* append string to `out', expand newlines. */
|
||||
static void printtext_append_str(TEXT_DEST_REC *dest, GString *out,
|
||||
const char *str)
|
||||
@ -195,7 +166,7 @@ static void printtext_append_str(TEXT_DEST_REC *dest, GString *out,
|
||||
if (*str != '\n')
|
||||
g_string_append_c(out, *str);
|
||||
else {
|
||||
print_line(dest, out->str);
|
||||
print_line(dest, out->str, 0);
|
||||
g_string_truncate(out, 0);
|
||||
}
|
||||
str++;
|
||||
@ -314,9 +285,7 @@ static void printtext_dest_args(TEXT_DEST_REC *dest, const char *text, va_list v
|
||||
}
|
||||
|
||||
str = printtext_get_args(dest, text, va);
|
||||
signal_emit_id(signal_print_noformat, 2,
|
||||
dest, str);
|
||||
print_line(dest, str);
|
||||
print_line(dest, str, 0);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
@ -361,8 +330,8 @@ void printtext_string(void *server, const char *target, int level, const char *t
|
||||
}
|
||||
|
||||
str = printtext_expand_formats(text, &dest.flags);
|
||||
print_line(&dest, str);
|
||||
g_free(str);
|
||||
print_line(&dest, str, 0);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
/* Like printtext_window(), but don't handle %s etc. */
|
||||
@ -383,8 +352,8 @@ void printtext_string_window(WINDOW_REC *window, int level, const char *text)
|
||||
}
|
||||
|
||||
str = printtext_expand_formats(text, &dest.flags);
|
||||
print_line(&dest, str);
|
||||
g_free(str);
|
||||
print_line(&dest, str, 0);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
void printtext_window(WINDOW_REC *window, int level, const char *text, ...)
|
||||
@ -476,6 +445,51 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text)
|
||||
signal_emit_id(signal_gui_print_text_finished, 1, dest->window);
|
||||
}
|
||||
|
||||
static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC *dest,
|
||||
void *formatnump, char **arglist)
|
||||
{
|
||||
int formatnum;
|
||||
char *str;
|
||||
|
||||
formatnum = GPOINTER_TO_INT(formatnump);
|
||||
str = format_get_text_theme_charargs(theme, module, dest, formatnum, arglist);
|
||||
if (str != NULL && *str != '\0')
|
||||
print_line(dest, str, 1);
|
||||
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void sig_print_noformat(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
THEME_REC *theme;
|
||||
char *str, *tmp, *stripped;
|
||||
|
||||
theme = window_get_theme(dest->window);
|
||||
tmp = format_get_level_tag(theme, dest);
|
||||
str = !theme->info_eol ? format_add_linestart(text, tmp) : format_add_lineend(text, tmp);
|
||||
g_free_not_null(tmp);
|
||||
|
||||
/* send both the formatted + stripped (for logging etc.) */
|
||||
stripped = strip_codes(str);
|
||||
signal_emit_id(signal_print_text, 3, dest, str, stripped);
|
||||
|
||||
g_free_and_null(dest->hilight_color);
|
||||
|
||||
g_free(str);
|
||||
g_free(stripped);
|
||||
}
|
||||
|
||||
static void print_line(TEXT_DEST_REC *dest, const char *text, int formatted)
|
||||
{
|
||||
g_return_if_fail(dest != NULL);
|
||||
g_return_if_fail(text != NULL);
|
||||
|
||||
if (!formatted)
|
||||
signal_emit_id(signal_print_noformat, 2, dest, text);
|
||||
else
|
||||
sig_print_noformat(dest, text);
|
||||
}
|
||||
|
||||
void printtext_multiline(void *server, const char *target, int level,
|
||||
const char *format, const char *text)
|
||||
{
|
||||
@ -522,6 +536,8 @@ void printtext_init(void)
|
||||
|
||||
read_settings();
|
||||
signal_add("print text", (SIGNAL_FUNC) sig_print_text);
|
||||
signal_add("print format", (SIGNAL_FUNC) sig_print_format);
|
||||
signal_add("print noformat", (SIGNAL_FUNC) sig_print_noformat);
|
||||
signal_add("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
||||
@ -529,6 +545,8 @@ void printtext_init(void)
|
||||
void printtext_deinit(void)
|
||||
{
|
||||
signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
|
||||
signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
|
||||
signal_remove("print noformat", (SIGNAL_FUNC) sig_print_noformat);
|
||||
signal_remove("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ irssi_SOURCES = \
|
||||
textbuffer.c \
|
||||
textbuffer-commands.c \
|
||||
textbuffer-view.c \
|
||||
textbuffer-formats.c \
|
||||
irssi.c \
|
||||
module-formats.c
|
||||
|
||||
@ -57,7 +58,8 @@ pkginc_fe_text_HEADERS = \
|
||||
statusbar-item.h \
|
||||
term.h \
|
||||
textbuffer.h \
|
||||
textbuffer-view.h
|
||||
textbuffer-view.h \
|
||||
textbuffer-formats.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
gui-entry.h \
|
||||
|
@ -19,8 +19,9 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/levels.h>
|
||||
#include <irssi/src/core/settings.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
|
||||
#include <irssi/src/fe-common/core/formats.h>
|
||||
#include <irssi/src/fe-common/core/printtext.h>
|
||||
@ -237,7 +238,7 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
|
||||
}
|
||||
}
|
||||
|
||||
static void get_colors(int *flags, int *fg, int *bg, int *attr)
|
||||
void gui_printtext_get_colors(int *flags, int *fg, int *bg, int *attr)
|
||||
{
|
||||
*attr = 0;
|
||||
if (*flags & GUI_PRINT_FLAG_MIRC_COLOR) {
|
||||
@ -329,23 +330,29 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
|
||||
GUI_WINDOW_REC *gui;
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
LINE_REC *insert_after;
|
||||
LINE_INFO_REC lineinfo;
|
||||
LINE_INFO_REC lineinfo = { 0 };
|
||||
int fg, bg, flags, attr;
|
||||
|
||||
flags = GPOINTER_TO_INT(pflags);
|
||||
fg = GPOINTER_TO_INT(fgcolor);
|
||||
bg = GPOINTER_TO_INT(bgcolor);
|
||||
get_colors(&flags, &fg, &bg, &attr);
|
||||
gui_printtext_get_colors(&flags, &fg, &bg, &attr);
|
||||
|
||||
if (window == NULL) {
|
||||
print_text_no_window(flags, fg, bg, attr, str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dest != NULL && dest->flags & PRINT_FLAG_FORMAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
lineinfo.level = dest == NULL ? 0 : dest->level;
|
||||
gui = WINDOW_GUI(window);
|
||||
lineinfo.time = (gui->use_insert_after && gui->insert_after_time) ?
|
||||
gui->insert_after_time : time(NULL);
|
||||
lineinfo.format =
|
||||
dest != NULL && dest->flags & PRINT_FLAG_FORMAT ? LINE_INFO_FORMAT_SET : NULL;
|
||||
|
||||
view = gui->view;
|
||||
insert_after = gui->use_insert_after ?
|
||||
@ -378,7 +385,8 @@ static void sig_gui_printtext_finished(WINDOW_REC *window)
|
||||
insert_after = WINDOW_GUI(window)->use_insert_after ?
|
||||
WINDOW_GUI(window)->insert_after : view->buffer->cur_line;
|
||||
|
||||
view_add_eol(view, &insert_after);
|
||||
if (insert_after != NULL)
|
||||
view_add_eol(view, &insert_after);
|
||||
remove_old_lines(view);
|
||||
}
|
||||
|
||||
|
@ -21,5 +21,6 @@ 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);
|
||||
void gui_printtext_window_border(int xpos, int ypos);
|
||||
void gui_printtext_get_colors(int *flags, int *fg, int *bg, int *attr);
|
||||
|
||||
#endif
|
||||
|
@ -43,10 +43,9 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window,
|
||||
|
||||
gui = g_new0(GUI_WINDOW_REC, 1);
|
||||
gui->parent = parent;
|
||||
gui->view = textbuffer_view_create(textbuffer_create(),
|
||||
window->width, window->height,
|
||||
settings_get_bool("scroll"),
|
||||
term_type == TERM_TYPE_UTF8);
|
||||
gui->view =
|
||||
textbuffer_view_create(textbuffer_create(window), window->width, window->height,
|
||||
settings_get_bool("scroll"), term_type == TERM_TYPE_UTF8);
|
||||
textbuffer_view_set_default_indent(gui->view,
|
||||
settings_get_int("indent"),
|
||||
!settings_get_bool("indent_always"),
|
||||
|
@ -71,6 +71,9 @@ void gui_expandos_deinit(void);
|
||||
void textbuffer_commands_init(void);
|
||||
void textbuffer_commands_deinit(void);
|
||||
|
||||
void textbuffer_formats_init(void);
|
||||
void textbuffer_formats_deinit(void);
|
||||
|
||||
void lastlog_init(void);
|
||||
void lastlog_deinit(void);
|
||||
|
||||
@ -168,6 +171,7 @@ static void textui_finish_init(void)
|
||||
textbuffer_init();
|
||||
textbuffer_view_init();
|
||||
textbuffer_commands_init();
|
||||
textbuffer_formats_init();
|
||||
gui_expandos_init();
|
||||
gui_printtext_init();
|
||||
gui_readline_init();
|
||||
@ -256,6 +260,7 @@ static void textui_deinit(void)
|
||||
mainwindow_activity_deinit();
|
||||
mainwindows_deinit();
|
||||
gui_expandos_deinit();
|
||||
textbuffer_formats_deinit();
|
||||
textbuffer_commands_deinit();
|
||||
textbuffer_view_deinit();
|
||||
textbuffer_deinit();
|
||||
|
@ -199,7 +199,7 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
|
||||
}
|
||||
|
||||
/* get the line text */
|
||||
textbuffer_line2text(rec, fhandle == NULL, line);
|
||||
textbuffer_line2text(WINDOW_GUI(window)->view->buffer, rec, fhandle == NULL, line);
|
||||
if (!settings_get_bool("timestamps")) {
|
||||
struct tm *tm = localtime(&rec->info.time);
|
||||
char timestamp[10];
|
||||
|
@ -23,6 +23,7 @@ executable('irssi',
|
||||
'statusbar.c',
|
||||
'term.c',
|
||||
'textbuffer-commands.c',
|
||||
'textbuffer-formats.c',
|
||||
'textbuffer-view.c',
|
||||
'textbuffer.c',
|
||||
)
|
||||
@ -53,6 +54,7 @@ install_headers(
|
||||
'statusbar-item.h',
|
||||
'statusbar.h',
|
||||
'term.h',
|
||||
'textbuffer-formats.h',
|
||||
'textbuffer-view.h',
|
||||
'textbuffer.h',
|
||||
),
|
||||
|
@ -19,14 +19,15 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include <irssi/src/fe-text/module-formats.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/commands.h>
|
||||
#include <irssi/src/core/misc.h>
|
||||
#include <irssi/src/core/levels.h>
|
||||
#include <irssi/src/core/settings.h>
|
||||
#include <irssi/src/core/servers.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/fe-text/module-formats.h>
|
||||
#include <irssi/src/fe-text/textbuffer-formats.h>
|
||||
|
||||
#include <irssi/src/fe-common/core/printtext.h>
|
||||
#include <irssi/src/fe-text/gui-windows.h>
|
||||
@ -340,14 +341,29 @@ static void cmd_scrollback_status(void)
|
||||
total_lines = 0; total_mem = 0;
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
|
||||
WINDOW_REC *window = tmp->data;
|
||||
int i;
|
||||
LINE_REC *tmp;
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
|
||||
view = WINDOW_GUI(window)->view;
|
||||
|
||||
window_mem = sizeof(TEXT_BUFFER_REC);
|
||||
window_mem += g_slist_length(view->buffer->text_chunks) *
|
||||
sizeof(TEXT_CHUNK_REC);
|
||||
window_mem += view->buffer->lines_count * sizeof(LINE_REC);
|
||||
for (tmp = view->buffer->cur_line; tmp != NULL; tmp = tmp->prev) {
|
||||
if (tmp->info.text != NULL) {
|
||||
window_mem += sizeof(char) * (strlen(tmp->info.text) + 1);
|
||||
}
|
||||
if (tmp->info.format != NULL) {
|
||||
window_mem += sizeof(TEXT_BUFFER_FORMAT_REC);
|
||||
for (i = 0; i < tmp->info.format->nargs; i++) {
|
||||
if (tmp->info.format->args[i] != NULL) {
|
||||
window_mem +=
|
||||
sizeof(char) *
|
||||
(strlen(tmp->info.format->args[i]) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
total_lines += view->buffer->lines_count;
|
||||
total_mem += window_mem;
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||
@ -368,6 +384,19 @@ static void cmd_scrollback_status(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* SYNTAX: SCROLLBACK REDRAW */
|
||||
static void cmd_scrollback_redraw(void)
|
||||
{
|
||||
GUI_WINDOW_REC *gui;
|
||||
|
||||
gui = WINDOW_GUI(active_win);
|
||||
|
||||
term_refresh_freeze();
|
||||
textbuffer_view_reset_cache(gui->view);
|
||||
gui_window_redraw(active_win);
|
||||
term_refresh_thaw();
|
||||
}
|
||||
|
||||
static void sig_away_changed(SERVER_REC *server)
|
||||
{
|
||||
GSList *tmp;
|
||||
@ -419,6 +448,7 @@ void textbuffer_commands_init(void)
|
||||
command_bind("scrollback home", NULL, (SIGNAL_FUNC) cmd_scrollback_home);
|
||||
command_bind("scrollback end", NULL, (SIGNAL_FUNC) cmd_scrollback_end);
|
||||
command_bind("scrollback status", NULL, (SIGNAL_FUNC) cmd_scrollback_status);
|
||||
command_bind("scrollback redraw", NULL, (SIGNAL_FUNC) cmd_scrollback_redraw);
|
||||
|
||||
command_set_options("clear", "all");
|
||||
command_set_options("scrollback clear", "all");
|
||||
@ -442,6 +472,7 @@ void textbuffer_commands_deinit(void)
|
||||
command_unbind("scrollback home", (SIGNAL_FUNC) cmd_scrollback_home);
|
||||
command_unbind("scrollback end", (SIGNAL_FUNC) cmd_scrollback_end);
|
||||
command_unbind("scrollback status", (SIGNAL_FUNC) cmd_scrollback_status);
|
||||
command_unbind("scrollback redraw", (SIGNAL_FUNC) cmd_scrollback_redraw);
|
||||
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
signal_remove("away mode changed", (SIGNAL_FUNC) sig_away_changed);
|
||||
|
351
src/fe-text/textbuffer-formats.c
Normal file
351
src/fe-text/textbuffer-formats.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include "module.h"
|
||||
#include <irssi/src/core/expandos.h>
|
||||
#include <irssi/src/core/levels.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/fe-common/core/printtext.h>
|
||||
#include <irssi/src/fe-common/core/themes.h>
|
||||
#include <irssi/src/fe-text/gui-printtext.h>
|
||||
#include <irssi/src/fe-text/gui-windows.h>
|
||||
#include <irssi/src/fe-text/textbuffer-formats.h>
|
||||
#include <irssi/src/fe-text/textbuffer-view.h>
|
||||
|
||||
TEXT_BUFFER_REC *color_buf;
|
||||
int scrollback_format;
|
||||
|
||||
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;
|
||||
|
||||
if (rec == NULL)
|
||||
return;
|
||||
if (rec == LINE_INFO_FORMAT_SET)
|
||||
return;
|
||||
|
||||
i_refstr_release(rec->module);
|
||||
i_refstr_release(rec->format);
|
||||
i_refstr_release(rec->server_tag);
|
||||
i_refstr_release(rec->target);
|
||||
i_refstr_release(rec->nick);
|
||||
if (rec->nargs >= 1) {
|
||||
i_refstr_release(rec->args[0]);
|
||||
}
|
||||
for (n = 1; n < rec->nargs; n++) {
|
||||
g_free(rec->args[n]);
|
||||
}
|
||||
rec->nargs = 0;
|
||||
g_free(rec->args);
|
||||
collector_free(&rec->expando_cache);
|
||||
g_slice_free(TEXT_BUFFER_FORMAT_REC, rec);
|
||||
}
|
||||
|
||||
static TEXT_BUFFER_FORMAT_REC *format_rec_new(const char *module, const char *format_tag,
|
||||
const char *server_tag, const char *target,
|
||||
const char *nick, int nargs, const char **args)
|
||||
{
|
||||
int n;
|
||||
TEXT_BUFFER_FORMAT_REC *ret = g_slice_new0(TEXT_BUFFER_FORMAT_REC);
|
||||
ret->module = i_refstr_intern(module);
|
||||
ret->format = i_refstr_intern(format_tag);
|
||||
ret->server_tag = i_refstr_intern(server_tag);
|
||||
ret->target = i_refstr_intern(target);
|
||||
ret->nick = i_refstr_intern(nick);
|
||||
ret->nargs = nargs;
|
||||
ret->args = g_new0(char *, nargs);
|
||||
if (nargs >= 1) {
|
||||
ret->args[0] = i_refstr_intern(args[0]);
|
||||
}
|
||||
for (n = 1; n < nargs; n++) {
|
||||
ret->args[n] = g_strdup(args[n]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LINE_INFO_REC *store_lineinfo_tmp(TEXT_DEST_REC *dest)
|
||||
{
|
||||
GUI_WINDOW_REC *gui;
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
LINE_INFO_REC *lineinfo;
|
||||
|
||||
gui = WINDOW_GUI(dest->window);
|
||||
view = gui->view;
|
||||
buffer = view->buffer;
|
||||
|
||||
lineinfo = g_new0(LINE_INFO_REC, 1);
|
||||
lineinfo->level = dest->level;
|
||||
lineinfo->time =
|
||||
(gui->use_insert_after && gui->insert_after_time) ? gui->insert_after_time : time(NULL);
|
||||
|
||||
buffer->cur_info = g_slist_prepend(buffer->cur_info, lineinfo);
|
||||
return lineinfo;
|
||||
}
|
||||
|
||||
static void free_lineinfo_tmp(WINDOW_REC *window)
|
||||
{
|
||||
GUI_WINDOW_REC *gui;
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
LINE_INFO_REC *info;
|
||||
|
||||
gui = WINDOW_GUI(window);
|
||||
buffer = gui->view->buffer;
|
||||
|
||||
if (buffer->cur_info == NULL)
|
||||
return;
|
||||
|
||||
info = buffer->cur_info->data;
|
||||
buffer->cur_info = g_slist_delete_link(buffer->cur_info, buffer->cur_info);
|
||||
textbuffer_format_rec_free(info->format);
|
||||
g_free(info);
|
||||
}
|
||||
|
||||
static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC *dest,
|
||||
void *formatnump, const char **args)
|
||||
{
|
||||
int formatnum;
|
||||
FORMAT_REC *formats;
|
||||
LINE_INFO_REC *info;
|
||||
|
||||
if (!scrollback_format)
|
||||
return;
|
||||
|
||||
info = store_lineinfo_tmp(dest);
|
||||
|
||||
formatnum = GPOINTER_TO_INT(formatnump);
|
||||
formats = g_hash_table_lookup(default_formats, module);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void sig_print_noformat(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
LINE_INFO_REC *info;
|
||||
|
||||
if (!scrollback_format)
|
||||
return;
|
||||
|
||||
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;
|
||||
LINE_REC *insert_after;
|
||||
LINE_INFO_REC *info;
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
|
||||
gui = WINDOW_GUI(window);
|
||||
buffer = gui->view->buffer;
|
||||
insert_after = gui->use_insert_after ? gui->insert_after : buffer->cur_line;
|
||||
|
||||
if (buffer->cur_info == NULL)
|
||||
return;
|
||||
|
||||
info = buffer->cur_info->data;
|
||||
|
||||
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
|
||||
gui-printtext.c:view_add_eol */
|
||||
insert_after = textbuffer_insert(buffer, insert_after, (const unsigned char[]){}, 0, info);
|
||||
|
||||
/* the TEXT_BUFFER_FORMAT_REC pointer is now owned by the textbuffer */
|
||||
info->format = LINE_INFO_FORMAT_SET;
|
||||
|
||||
if (gui->use_insert_after)
|
||||
gui->insert_after = insert_after;
|
||||
}
|
||||
|
||||
static void parse_colors_collector(const WINDOW_REC *window, const void *fgcolor_int,
|
||||
const void *bgcolor_int, const void *flags_int,
|
||||
const char *textpiece, const TEXT_DEST_REC *dest)
|
||||
{
|
||||
int fg, bg, flags, attr;
|
||||
|
||||
flags = GPOINTER_TO_INT(flags_int);
|
||||
fg = GPOINTER_TO_INT(fgcolor_int);
|
||||
bg = GPOINTER_TO_INT(bgcolor_int);
|
||||
gui_printtext_get_colors(&flags, &fg, &bg, &attr);
|
||||
|
||||
if (flags & GUI_PRINT_FLAG_NEWLINE) {
|
||||
g_string_append_c(color_buf->cur_text, '\n');
|
||||
}
|
||||
format_gui_flags(color_buf->cur_text, &color_buf->last_fg, &color_buf->last_bg,
|
||||
&color_buf->last_flags, fg, bg, flags);
|
||||
|
||||
g_string_append(color_buf->cur_text, textpiece);
|
||||
}
|
||||
|
||||
static char *parse_colors(TEXT_DEST_REC *dest, const char *text)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (text == NULL)
|
||||
return NULL;
|
||||
|
||||
color_buf = textbuffer_create(NULL);
|
||||
format_send_as_gui_flags(dest, text, (SIGNAL_FUNC) parse_colors_collector);
|
||||
tmp = g_strdup(color_buf->cur_text->str);
|
||||
textbuffer_destroy(color_buf);
|
||||
color_buf = NULL;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
{
|
||||
TEXT_DEST_REC dest;
|
||||
GUI_WINDOW_REC *gui;
|
||||
char *tmp, *text = NULL;
|
||||
|
||||
g_return_val_if_fail(buffer != NULL, NULL);
|
||||
g_return_val_if_fail(buffer->window != NULL, NULL);
|
||||
|
||||
gui = WINDOW_GUI(buffer->window);
|
||||
if (line == NULL || gui == NULL)
|
||||
return NULL;
|
||||
|
||||
if (line->info.level & MSGLEVEL_FORMAT && line->info.format != NULL) {
|
||||
LINE_REC *curr;
|
||||
THEME_REC *theme;
|
||||
int formatnum;
|
||||
TEXT_BUFFER_FORMAT_REC *format_rec;
|
||||
char *str;
|
||||
|
||||
curr = line;
|
||||
line = NULL;
|
||||
format_rec = curr->info.format;
|
||||
|
||||
format_create_dest(
|
||||
&dest,
|
||||
format_rec->server_tag != NULL ? server_find_tag(format_rec->server_tag) : NULL,
|
||||
format_rec->target, curr->info.level & ~MSGLEVEL_FORMAT, buffer->window);
|
||||
|
||||
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);
|
||||
memcpy(arglist, format_rec->args, format_rec->nargs * sizeof(char *));
|
||||
text = format_get_text_theme_charargs(theme, format_rec->module, &dest,
|
||||
formatnum, arglist);
|
||||
} else {
|
||||
text = g_strdup(format_rec->args[1]);
|
||||
}
|
||||
|
||||
if (*text != '\0') {
|
||||
current_time = curr->info.time;
|
||||
|
||||
tmp = format_get_level_tag(theme, &dest);
|
||||
str = !theme->info_eol ? format_add_linestart(text, tmp) :
|
||||
format_add_lineend(text, tmp);
|
||||
g_free_not_null(tmp);
|
||||
g_free_not_null(text);
|
||||
text = str;
|
||||
tmp = format_get_line_start(theme, &dest, curr->info.time);
|
||||
str = !theme->info_eol ? format_add_linestart(text, tmp) :
|
||||
format_add_lineend(text, tmp);
|
||||
g_free_not_null(tmp);
|
||||
g_free_not_null(text);
|
||||
text = str;
|
||||
/* str = g_strconcat(text, "\n", NULL); */
|
||||
/* g_free(text); */
|
||||
|
||||
dest.flags |= PRINT_FLAG_FORMAT;
|
||||
|
||||
current_time = (time_t) -1;
|
||||
} else if (format_rec->format != NULL) {
|
||||
g_free(text);
|
||||
text = NULL;
|
||||
}
|
||||
special_fill_cache(NULL);
|
||||
} else {
|
||||
format_create_dest(&dest, NULL, NULL, line->info.level, buffer->window);
|
||||
text = g_strdup(line->info.text);
|
||||
}
|
||||
tmp = parse_colors(&dest, text);
|
||||
g_free(text);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
scrollback_format = settings_get_bool("scrollback_format");
|
||||
}
|
||||
|
||||
void textbuffer_formats_init(void)
|
||||
{
|
||||
settings_add_bool("lookandfeel", "scrollback_format", TRUE);
|
||||
|
||||
read_settings();
|
||||
signal_add("print format", (SIGNAL_FUNC) sig_print_format);
|
||||
signal_add("print noformat", (SIGNAL_FUNC) sig_print_noformat);
|
||||
signal_add_first("gui print text finished", (SIGNAL_FUNC) sig_gui_print_text_finished);
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
||||
|
||||
void textbuffer_formats_deinit(void)
|
||||
{
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
|
||||
signal_remove("print noformat", (SIGNAL_FUNC) sig_print_noformat);
|
||||
signal_remove("gui print text finished", (SIGNAL_FUNC) sig_gui_print_text_finished);
|
||||
}
|
23
src/fe-text/textbuffer-formats.h
Normal file
23
src/fe-text/textbuffer-formats.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H
|
||||
#define IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H
|
||||
|
||||
#include <irssi/src/fe-text/textbuffer.h>
|
||||
|
||||
typedef struct _TEXT_BUFFER_FORMAT_REC {
|
||||
char *module;
|
||||
char *format;
|
||||
char *server_tag;
|
||||
char *target;
|
||||
char *nick;
|
||||
char **args;
|
||||
int nargs;
|
||||
GSList *expando_cache;
|
||||
int flags;
|
||||
} TEXT_BUFFER_FORMAT_REC;
|
||||
|
||||
void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec);
|
||||
char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line);
|
||||
void textbuffer_formats_init(void);
|
||||
void textbuffer_formats_deinit(void);
|
||||
|
||||
#endif
|
@ -21,9 +21,12 @@
|
||||
#define G_LOG_DOMAIN "TextBufferView"
|
||||
|
||||
#include "module.h"
|
||||
#include <irssi/src/fe-text/textbuffer-view.h>
|
||||
#include <irssi/src/core/levels.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/utf8.h>
|
||||
#include <irssi/src/fe-common/core/formats.h>
|
||||
#include <irssi/src/fe-text/textbuffer-formats.h>
|
||||
#include <irssi/src/fe-text/textbuffer-view.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
@ -93,6 +96,7 @@ textbuffer_cache_get(GSList *views, int width)
|
||||
|
||||
static int line_cache_destroy(void *key, LINE_CACHE_REC *cache)
|
||||
{
|
||||
g_free(cache->line_text);
|
||||
g_free(cache);
|
||||
return TRUE;
|
||||
}
|
||||
@ -114,52 +118,6 @@ static void textbuffer_cache_unref(TEXT_BUFFER_CACHE_REC *cache)
|
||||
#define FGATTR (ATTR_NOCOLORS | ATTR_RESETFG | FG_MASK | ATTR_FGCOLOR24)
|
||||
#define BGATTR (ATTR_NOCOLORS | ATTR_RESETBG | BG_MASK | ATTR_BGCOLOR24)
|
||||
|
||||
static void update_cmd_color(unsigned char cmd, int *color)
|
||||
{
|
||||
if ((cmd & 0x80) == 0) {
|
||||
if (cmd & LINE_COLOR_BG) {
|
||||
/* set background color */
|
||||
*color &= FGATTR;
|
||||
if ((cmd & LINE_COLOR_DEFAULT) == 0)
|
||||
*color |= (cmd & 0x0f) << BG_SHIFT;
|
||||
else {
|
||||
*color = (*color & FGATTR) | ATTR_RESETBG;
|
||||
}
|
||||
} else {
|
||||
/* set foreground color */
|
||||
*color &= BGATTR;
|
||||
if ((cmd & LINE_COLOR_DEFAULT) == 0)
|
||||
*color |= cmd & 0x0f;
|
||||
else {
|
||||
*color = (*color & BGATTR) | ATTR_RESETFG;
|
||||
}
|
||||
}
|
||||
} else switch (cmd) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
*color ^= ATTR_UNDERLINE;
|
||||
break;
|
||||
case LINE_CMD_REVERSE:
|
||||
*color ^= ATTR_REVERSE;
|
||||
break;
|
||||
case LINE_CMD_BLINK:
|
||||
*color ^= ATTR_BLINK;
|
||||
break;
|
||||
case LINE_CMD_BOLD:
|
||||
*color ^= ATTR_BOLD;
|
||||
break;
|
||||
case LINE_CMD_ITALIC:
|
||||
*color ^= ATTR_ITALIC;
|
||||
break;
|
||||
case LINE_CMD_MONOSPACE:
|
||||
/* ignored */
|
||||
break;
|
||||
case LINE_CMD_COLOR0:
|
||||
*color &= BGATTR;
|
||||
*color &= ~ATTR_FGCOLOR24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TERM_TRUECOLOR
|
||||
static void unformat_24bit_line_color(const unsigned char **ptr, int off, int *flags, unsigned int *fg, unsigned int *bg)
|
||||
{
|
||||
@ -167,6 +125,8 @@ static void unformat_24bit_line_color(const unsigned char **ptr, int off, int *f
|
||||
unsigned char rgbx[4];
|
||||
unsigned int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if ((*ptr)[i + off] == '\0')
|
||||
return;
|
||||
rgbx[i] = (*ptr)[i + off];
|
||||
}
|
||||
rgbx[3] -= 0x20;
|
||||
@ -202,6 +162,94 @@ static inline unichar read_unichar(const unsigned char *data, const unsigned cha
|
||||
return chr;
|
||||
}
|
||||
|
||||
static inline void unformat(const unsigned char **ptr, int *color, unsigned int *fg24,
|
||||
unsigned int *bg24)
|
||||
{
|
||||
switch (**ptr) {
|
||||
case FORMAT_STYLE_BLINK:
|
||||
*color ^= ATTR_BLINK;
|
||||
break;
|
||||
case FORMAT_STYLE_UNDERLINE:
|
||||
*color ^= ATTR_UNDERLINE;
|
||||
break;
|
||||
case FORMAT_STYLE_BOLD:
|
||||
*color ^= ATTR_BOLD;
|
||||
break;
|
||||
case FORMAT_STYLE_REVERSE:
|
||||
*color ^= ATTR_REVERSE;
|
||||
break;
|
||||
case FORMAT_STYLE_ITALIC:
|
||||
*color ^= ATTR_ITALIC;
|
||||
break;
|
||||
case FORMAT_STYLE_MONOSPACE:
|
||||
/* *color ^= ATTR_MONOSPACE; */
|
||||
break;
|
||||
case FORMAT_STYLE_DEFAULTS:
|
||||
*color = ATTR_RESET;
|
||||
break;
|
||||
case FORMAT_STYLE_CLRTOEOL:
|
||||
break;
|
||||
case FORMAT_COLOR_EXT1:
|
||||
*color &= ~ATTR_FGCOLOR24;
|
||||
*color = (*color & BGATTR) | (0x10 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case FORMAT_COLOR_EXT1_BG:
|
||||
*color &= ~ATTR_BGCOLOR24;
|
||||
*color = (*color & FGATTR) | (0x10 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case FORMAT_COLOR_EXT2:
|
||||
*color &= ~ATTR_FGCOLOR24;
|
||||
*color = (*color & BGATTR) | (0x60 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case FORMAT_COLOR_EXT2_BG:
|
||||
*color &= ~ATTR_BGCOLOR24;
|
||||
*color = (*color & FGATTR) | (0x60 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case FORMAT_COLOR_EXT3:
|
||||
*color &= ~ATTR_FGCOLOR24;
|
||||
*color = (*color & BGATTR) | (0xb0 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case FORMAT_COLOR_EXT3_BG:
|
||||
*color &= ~ATTR_BGCOLOR24;
|
||||
*color = (*color & FGATTR) | (0xb0 + *++*ptr - FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
case FORMAT_COLOR_24:
|
||||
unformat_24bit_line_color(ptr, 1, color, fg24, bg24);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (**ptr != FORMAT_COLOR_NOCHANGE) {
|
||||
if (**ptr == (unsigned char) 0xff) {
|
||||
*color = (*color & BGATTR) | ATTR_RESETFG;
|
||||
} else {
|
||||
*color = (*color & BGATTR) | (((unsigned char) **ptr - '0') & 0xf);
|
||||
}
|
||||
}
|
||||
if ((*ptr)[1] == '\0')
|
||||
break;
|
||||
|
||||
(*ptr)++;
|
||||
if (**ptr != FORMAT_COLOR_NOCHANGE) {
|
||||
if (**ptr == (unsigned char) 0xff) {
|
||||
*color = (*color & FGATTR) | ATTR_RESETBG;
|
||||
} else {
|
||||
*color = (*color & FGATTR) |
|
||||
((((unsigned char) **ptr - '0') & 0xf) << BG_SHIFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (**ptr == '\0')
|
||||
return;
|
||||
|
||||
(*ptr)++;
|
||||
}
|
||||
|
||||
#define NEXT_CHAR_OR_BREAK(p) \
|
||||
(p)++; \
|
||||
if (*(p) == '\0') \
|
||||
break
|
||||
|
||||
static LINE_CACHE_REC *
|
||||
view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
{
|
||||
@ -209,14 +257,12 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
LINE_CACHE_REC *rec;
|
||||
LINE_CACHE_SUB_REC *sub;
|
||||
GSList *lines;
|
||||
unsigned char cmd;
|
||||
char *line_text;
|
||||
const unsigned char *ptr, *next_ptr, *last_space_ptr;
|
||||
int xpos, pos, indent_pos, last_space, last_color, color, linecount;
|
||||
unsigned int last_bg24, last_fg24, bg24, fg24;
|
||||
int char_width;
|
||||
|
||||
g_return_val_if_fail(line->text != NULL, NULL);
|
||||
|
||||
color = ATTR_RESETFG | ATTR_RESETBG;
|
||||
xpos = 0; indent_pos = view->default_indent;
|
||||
last_space = last_color = 0; last_space_ptr = NULL; sub = NULL;
|
||||
@ -225,114 +271,132 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
indent_func = view->default_indent_func;
|
||||
linecount = 1;
|
||||
lines = NULL;
|
||||
for (ptr = line->text;;) {
|
||||
if (*ptr == '\0') {
|
||||
/* command */
|
||||
ptr++;
|
||||
cmd = *ptr;
|
||||
ptr++;
|
||||
|
||||
if (cmd == LINE_CMD_EOL)
|
||||
line_text = textbuffer_line_get_text(view->buffer, line);
|
||||
if (line_text != NULL) {
|
||||
for (ptr = (unsigned char *) line_text;;) {
|
||||
if (*ptr == '\0')
|
||||
break;
|
||||
|
||||
if (cmd == LINE_CMD_CONTINUE) {
|
||||
unsigned char *tmp;
|
||||
if (*ptr == '\n') {
|
||||
/* newline */
|
||||
xpos = 0;
|
||||
last_space = 0;
|
||||
|
||||
sub = g_new0(LINE_CACHE_SUB_REC, 1);
|
||||
|
||||
sub->start = ++ptr;
|
||||
sub->color = color;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
sub->fg24 = fg24;
|
||||
sub->bg24 = bg24;
|
||||
#endif
|
||||
|
||||
lines = g_slist_append(lines, sub);
|
||||
linecount++;
|
||||
|
||||
memcpy(&tmp, ptr, sizeof(char *));
|
||||
ptr = tmp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd == LINE_CMD_INDENT) {
|
||||
/* set indentation position here - don't do
|
||||
it if we're too close to right border */
|
||||
if (xpos < view->width-5) indent_pos = xpos;
|
||||
} else if (cmd == LINE_COLOR_EXT) {
|
||||
color &= ~ATTR_FGCOLOR24;
|
||||
color = (color & BGATTR) | *ptr++;
|
||||
} else if (cmd == LINE_COLOR_EXT_BG) {
|
||||
color &= ~ATTR_BGCOLOR24;
|
||||
color = (color & FGATTR) | (*ptr++ << BG_SHIFT);
|
||||
}
|
||||
#ifdef TERM_TRUECOLOR
|
||||
else if (cmd == LINE_COLOR_24)
|
||||
unformat_24bit_line_color(&ptr, 0, &color, &fg24, &bg24);
|
||||
#endif
|
||||
else
|
||||
update_cmd_color(cmd, &color);
|
||||
continue;
|
||||
}
|
||||
if (*ptr == 4) {
|
||||
/* format */
|
||||
NEXT_CHAR_OR_BREAK(ptr);
|
||||
|
||||
if (!view->utf8) {
|
||||
/* MH */
|
||||
if (term_type != TERM_TYPE_BIG5 ||
|
||||
ptr[1] == '\0' || !is_big5(ptr[0], ptr[1]))
|
||||
char_width = 1;
|
||||
else
|
||||
char_width = 2;
|
||||
next_ptr = ptr+char_width;
|
||||
} else {
|
||||
read_unichar(ptr, &next_ptr, &char_width);
|
||||
}
|
||||
|
||||
if (xpos + char_width > view->width && sub != NULL &&
|
||||
(last_space <= indent_pos || last_space <= 10) &&
|
||||
view->longword_noindent) {
|
||||
/* long word, remove the indentation from this line */
|
||||
xpos -= sub->indent;
|
||||
sub->indent = 0;
|
||||
sub->indent_func = NULL;
|
||||
}
|
||||
|
||||
if (xpos + char_width > view->width) {
|
||||
xpos = indent_func == NULL ? indent_pos :
|
||||
indent_func(view, line, -1);
|
||||
|
||||
sub = g_new0(LINE_CACHE_SUB_REC, 1);
|
||||
if (last_space > indent_pos && last_space > 10) {
|
||||
/* go back to last space */
|
||||
color = last_color; fg24 = last_fg24; bg24 = last_bg24;
|
||||
ptr = last_space_ptr;
|
||||
while (*ptr == ' ') ptr++;
|
||||
} else if (view->longword_noindent) {
|
||||
/* long word, no indentation in next line */
|
||||
xpos = 0;
|
||||
sub->continues = TRUE;
|
||||
if (*ptr == FORMAT_STYLE_INDENT) {
|
||||
/* set indentation position here - don't do
|
||||
it if we're too close to right border */
|
||||
if (xpos < view->width - 5)
|
||||
indent_pos = xpos;
|
||||
ptr++;
|
||||
} else {
|
||||
unformat(&ptr, &color, &fg24, &bg24);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sub->start = ptr;
|
||||
sub->indent = xpos;
|
||||
sub->indent_func = indent_func;
|
||||
sub->color = color;
|
||||
if (!view->utf8) {
|
||||
/* MH */
|
||||
if (term_type != TERM_TYPE_BIG5 || ptr[1] == '\0' ||
|
||||
!is_big5(ptr[0], ptr[1]))
|
||||
char_width = 1;
|
||||
else
|
||||
char_width = 2;
|
||||
next_ptr = ptr + char_width;
|
||||
} else {
|
||||
read_unichar(ptr, &next_ptr, &char_width);
|
||||
}
|
||||
|
||||
if (xpos + char_width > view->width && sub != NULL &&
|
||||
(last_space <= indent_pos || last_space <= 10) &&
|
||||
view->longword_noindent) {
|
||||
/* long word, remove the indentation from this line */
|
||||
xpos -= sub->indent;
|
||||
sub->indent = 0;
|
||||
sub->indent_func = NULL;
|
||||
}
|
||||
|
||||
if (xpos + char_width > view->width) {
|
||||
xpos =
|
||||
indent_func == NULL ? indent_pos : indent_func(view, line, -1);
|
||||
|
||||
sub = g_new0(LINE_CACHE_SUB_REC, 1);
|
||||
if (last_space > indent_pos && last_space > 10) {
|
||||
/* go back to last space */
|
||||
color = last_color;
|
||||
fg24 = last_fg24;
|
||||
bg24 = last_bg24;
|
||||
ptr = last_space_ptr;
|
||||
while (*ptr == ' ')
|
||||
ptr++;
|
||||
} else if (view->longword_noindent) {
|
||||
/* long word, no indentation in next line */
|
||||
xpos = 0;
|
||||
sub->continues = TRUE;
|
||||
}
|
||||
|
||||
sub->start = ptr;
|
||||
sub->indent = xpos;
|
||||
sub->indent_func = indent_func;
|
||||
sub->color = color;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
sub->fg24 = fg24; sub->bg24 = bg24;
|
||||
sub->fg24 = fg24;
|
||||
sub->bg24 = bg24;
|
||||
#endif
|
||||
|
||||
lines = g_slist_append(lines, sub);
|
||||
linecount++;
|
||||
lines = g_slist_append(lines, sub);
|
||||
linecount++;
|
||||
|
||||
last_space = 0;
|
||||
continue;
|
||||
last_space = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (view->break_wide && char_width > 1) {
|
||||
last_space = xpos;
|
||||
last_space_ptr = next_ptr;
|
||||
last_color = color;
|
||||
last_fg24 = fg24;
|
||||
last_bg24 = bg24;
|
||||
} else if (*ptr == ' ') {
|
||||
last_space = xpos;
|
||||
last_space_ptr = ptr;
|
||||
last_color = color;
|
||||
last_fg24 = fg24;
|
||||
last_bg24 = bg24;
|
||||
}
|
||||
|
||||
xpos += char_width;
|
||||
ptr = next_ptr;
|
||||
}
|
||||
|
||||
if (view->break_wide && char_width > 1) {
|
||||
last_space = xpos;
|
||||
last_space_ptr = next_ptr;
|
||||
last_color = color; last_fg24 = fg24; last_bg24 = bg24;
|
||||
} else if (*ptr == ' ') {
|
||||
last_space = xpos;
|
||||
last_space_ptr = ptr;
|
||||
last_color = color; last_fg24 = fg24; last_bg24 = bg24;
|
||||
}
|
||||
|
||||
xpos += char_width;
|
||||
ptr = next_ptr;
|
||||
}
|
||||
|
||||
rec = g_malloc(sizeof(LINE_CACHE_REC)-sizeof(LINE_CACHE_SUB_REC) +
|
||||
sizeof(LINE_CACHE_SUB_REC) * (linecount-1));
|
||||
rec->last_access = time(NULL);
|
||||
if (line_text == NULL) {
|
||||
linecount = 0;
|
||||
}
|
||||
rec->count = linecount;
|
||||
rec->line_text = line_text;
|
||||
|
||||
if (rec->count > 1) {
|
||||
for (pos = 0; lines != NULL; pos++) {
|
||||
@ -398,12 +462,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
INDENT_FUNC indent_func;
|
||||
LINE_CACHE_REC *cache;
|
||||
const unsigned char *text, *end, *text_newline;
|
||||
unsigned char *tmp;
|
||||
unichar chr;
|
||||
int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
unsigned int fg24, bg24;
|
||||
#endif
|
||||
|
||||
if (view->dirty) /* don't bother drawing anything - redraw is coming */
|
||||
return 0;
|
||||
@ -416,7 +477,8 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
need_move = TRUE; need_clrtoeol = FALSE;
|
||||
xpos = drawcount = 0; first = TRUE;
|
||||
text_newline = text =
|
||||
subline == 0 ? line->text : cache->lines[subline-1].start;
|
||||
subline == 0 ? (unsigned char *) cache->line_text : cache->lines[subline - 1].start;
|
||||
|
||||
for (;;) {
|
||||
if (text == text_newline) {
|
||||
if (need_clrtoeol && xpos < view->width + (view->width == term_width ? 0 : 1)) {
|
||||
@ -484,31 +546,29 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
subline++;
|
||||
}
|
||||
|
||||
if (*text == '\0') {
|
||||
/* command */
|
||||
text++;
|
||||
if (*text == LINE_CMD_EOL)
|
||||
break;
|
||||
if (*text == '\n') {
|
||||
/* newline */
|
||||
NEXT_CHAR_OR_BREAK(text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*text == LINE_CMD_CONTINUE) {
|
||||
/* jump to next block */
|
||||
memcpy(&tmp, text+1, sizeof(unsigned char *));
|
||||
text = tmp;
|
||||
continue;
|
||||
if (*text == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*text == 4) {
|
||||
/* format */
|
||||
NEXT_CHAR_OR_BREAK(text);
|
||||
|
||||
if (*text == FORMAT_STYLE_INDENT) {
|
||||
/* ??? */
|
||||
NEXT_CHAR_OR_BREAK(text);
|
||||
} else {
|
||||
if (*text == LINE_COLOR_EXT)
|
||||
color = (color & BGATTR & ~ATTR_FGCOLOR24) | *++text;
|
||||
else if (*text == LINE_COLOR_EXT_BG)
|
||||
color = (color & FGATTR & ~ATTR_BGCOLOR24) | (*++text << BG_SHIFT);
|
||||
#ifdef TERM_TRUECOLOR
|
||||
else if (*text == LINE_COLOR_24)
|
||||
unformat_24bit_line_color(&text, 1, &color, &fg24, &bg24);
|
||||
#endif
|
||||
else
|
||||
update_cmd_color(*text, &color);
|
||||
unformat(&text, &color, &fg24, &bg24);
|
||||
term_set_color2(view->window, color, fg24, bg24);
|
||||
if (*text == 0)
|
||||
break;
|
||||
}
|
||||
text++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
time_t last_access;
|
||||
|
||||
char *line_text;
|
||||
int count; /* number of real lines */
|
||||
|
||||
/* variable sized array, actually. starts from the second line,
|
||||
|
@ -26,176 +26,59 @@
|
||||
#include <irssi/src/core/utf8.h>
|
||||
#include <irssi/src/core/iregex.h>
|
||||
|
||||
#include <irssi/src/fe-text/textbuffer-formats.h>
|
||||
#include <irssi/src/fe-text/textbuffer.h>
|
||||
|
||||
#define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*))
|
||||
|
||||
TEXT_BUFFER_REC *textbuffer_create(void)
|
||||
TEXT_BUFFER_REC *textbuffer_create(WINDOW_REC *window)
|
||||
{
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
|
||||
buffer = g_slice_new0(TEXT_BUFFER_REC);
|
||||
buffer->window = window;
|
||||
buffer->last_eol = TRUE;
|
||||
buffer->last_fg = -1;
|
||||
buffer->last_bg = -1;
|
||||
return buffer;
|
||||
buffer->cur_text = g_string_sized_new(TEXT_CHUNK_USABLE_SIZE);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void textbuffer_destroy(TEXT_BUFFER_REC *buffer)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_if_fail(buffer != NULL);
|
||||
|
||||
textbuffer_remove_all_lines(buffer);
|
||||
g_slice_free(TEXT_BUFFER_REC, buffer);
|
||||
}
|
||||
|
||||
static TEXT_CHUNK_REC *text_chunk_find(TEXT_BUFFER_REC *buffer,
|
||||
const unsigned char *data)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = buffer->text_chunks; tmp != NULL; tmp = tmp->next) {
|
||||
TEXT_CHUNK_REC *rec = tmp->data;
|
||||
|
||||
if (data >= rec->buffer &&
|
||||
data < rec->buffer+sizeof(rec->buffer))
|
||||
return rec;
|
||||
g_string_free(buffer->cur_text, TRUE);
|
||||
for (tmp = buffer->cur_info; tmp != NULL; tmp = tmp->next) {
|
||||
LINE_INFO_REC *info = buffer->cur_info->data;
|
||||
textbuffer_format_rec_free(info->format);
|
||||
g_free(info->text);
|
||||
g_free(info);
|
||||
}
|
||||
g_slist_free(buffer->cur_info);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define mark_temp_eol(chunk) G_STMT_START { \
|
||||
(chunk)->buffer[(chunk)->pos] = 0; \
|
||||
(chunk)->buffer[(chunk)->pos+1] = LINE_CMD_EOL; \
|
||||
} G_STMT_END
|
||||
|
||||
static TEXT_CHUNK_REC *text_chunk_create(TEXT_BUFFER_REC *buffer)
|
||||
{
|
||||
TEXT_CHUNK_REC *rec;
|
||||
unsigned char *buf, *ptr, **pptr;
|
||||
|
||||
rec = g_slice_new(TEXT_CHUNK_REC);
|
||||
rec->pos = 0;
|
||||
rec->refcount = 0;
|
||||
|
||||
if (buffer->cur_line != NULL && buffer->cur_line->text != NULL) {
|
||||
/* create a link to new block from the old block */
|
||||
buf = buffer->cur_text->buffer + buffer->cur_text->pos;
|
||||
*buf++ = 0; *buf++ = (char) LINE_CMD_CONTINUE;
|
||||
|
||||
/* we want to store pointer to beginning of the new text
|
||||
block to char* buffer. this probably isn't ANSI-C
|
||||
compatible, and trying this without the pptr variable
|
||||
breaks at least NetBSD/Alpha, so don't go "optimize"
|
||||
it :) */
|
||||
ptr = rec->buffer; pptr = &ptr;
|
||||
memcpy(buf, pptr, sizeof(unsigned char *));
|
||||
} else {
|
||||
/* just to be safe */
|
||||
mark_temp_eol(rec);
|
||||
}
|
||||
|
||||
buffer->cur_text = rec;
|
||||
buffer->text_chunks = g_slist_append(buffer->text_chunks, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void text_chunk_destroy(TEXT_BUFFER_REC *buffer, TEXT_CHUNK_REC *chunk)
|
||||
{
|
||||
buffer->text_chunks = g_slist_remove(buffer->text_chunks, chunk);
|
||||
g_slice_free(TEXT_CHUNK_REC, chunk);
|
||||
}
|
||||
|
||||
static void text_chunk_line_free(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
{
|
||||
TEXT_CHUNK_REC *chunk;
|
||||
const unsigned char *text;
|
||||
unsigned char cmd, *tmp = NULL;
|
||||
|
||||
for (text = line->text;; text++) {
|
||||
if (*text != '\0')
|
||||
continue;
|
||||
|
||||
text++;
|
||||
cmd = *text;
|
||||
if (cmd == LINE_CMD_CONTINUE || cmd == LINE_CMD_EOL) {
|
||||
if (cmd == LINE_CMD_CONTINUE)
|
||||
memcpy(&tmp, text+1, sizeof(char *));
|
||||
|
||||
/* free the previous block */
|
||||
chunk = text_chunk_find(buffer, text);
|
||||
if (--chunk->refcount == 0) {
|
||||
if (buffer->cur_text == chunk)
|
||||
chunk->pos = 0;
|
||||
else
|
||||
text_chunk_destroy(buffer, chunk);
|
||||
}
|
||||
|
||||
if (cmd == LINE_CMD_EOL)
|
||||
break;
|
||||
|
||||
text = tmp-1;
|
||||
}
|
||||
}
|
||||
buffer->window = NULL;
|
||||
g_slice_free(TEXT_BUFFER_REC, buffer);
|
||||
}
|
||||
|
||||
static void text_chunk_append(TEXT_BUFFER_REC *buffer,
|
||||
const unsigned char *data, int len)
|
||||
{
|
||||
TEXT_CHUNK_REC *chunk;
|
||||
int left;
|
||||
int i;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
chunk = buffer->cur_text;
|
||||
while (chunk->pos + len >= TEXT_CHUNK_USABLE_SIZE) {
|
||||
left = TEXT_CHUNK_USABLE_SIZE - chunk->pos;
|
||||
|
||||
/* don't split utf-8 character. (assume we can split non-utf8 anywhere.) */
|
||||
if (left < len && !is_utf8_leading(data[left])) {
|
||||
int i;
|
||||
for (i = 1; i < 4 && left >= i; i++)
|
||||
if (is_utf8_leading(data[left - i])) {
|
||||
left -= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 5; i > 0; --i) {
|
||||
if (left >= i && data[left-i] == 0) {
|
||||
left -= i; /* don't split the commands */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(chunk->buffer + chunk->pos, data, left);
|
||||
chunk->pos += left;
|
||||
|
||||
chunk = text_chunk_create(buffer);
|
||||
chunk->refcount++;
|
||||
len -= left; data += left;
|
||||
}
|
||||
|
||||
memcpy(chunk->buffer + chunk->pos, data, len);
|
||||
chunk->pos += len;
|
||||
|
||||
mark_temp_eol(chunk);
|
||||
/* g_string_append_len(buffer->cur_text, (const char *)data, len); */
|
||||
g_string_append(buffer->cur_text, (const char *) data);
|
||||
}
|
||||
|
||||
static LINE_REC *textbuffer_line_create(TEXT_BUFFER_REC *buffer)
|
||||
{
|
||||
LINE_REC *rec;
|
||||
|
||||
if (buffer->cur_text == NULL)
|
||||
text_chunk_create(buffer);
|
||||
|
||||
rec = g_slice_new0(LINE_REC);
|
||||
rec->text = buffer->cur_text->buffer + buffer->cur_text->pos;
|
||||
|
||||
buffer->cur_text->refcount++;
|
||||
return rec;
|
||||
}
|
||||
|
||||
@ -241,103 +124,18 @@ int textbuffer_line_exists_after(LINE_REC *line, LINE_REC *search)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef TERM_TRUECOLOR
|
||||
static void format_24bit_line_color(unsigned char *out, int *pos, int bg, unsigned int color)
|
||||
{
|
||||
unsigned char rgb[] = { color >> 16, color >> 8, color };
|
||||
unsigned char x = bg ? 0x1 : 0;
|
||||
unsigned int i;
|
||||
out[(*pos)++] = LINE_COLOR_24;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (rgb[i] > 0x20)
|
||||
out[(*pos)++] = rgb[i];
|
||||
else {
|
||||
out[(*pos)++] = 0x20 + rgb[i];
|
||||
x |= 0x10 << i;
|
||||
}
|
||||
}
|
||||
out[(*pos)++] = 0x20 + x;
|
||||
}
|
||||
#endif
|
||||
|
||||
void textbuffer_line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
|
||||
int fg, int bg, int flags)
|
||||
{
|
||||
unsigned char data[22];
|
||||
int pos;
|
||||
GString *out = g_string_new(NULL);
|
||||
format_gui_flags(out, &buffer->last_fg, &buffer->last_bg, &buffer->last_flags, fg, bg,
|
||||
flags);
|
||||
|
||||
pos = 0;
|
||||
if (fg != buffer->last_fg
|
||||
|| (flags & GUI_PRINT_FLAG_COLOR_24_FG) != (buffer->last_flags & GUI_PRINT_FLAG_COLOR_24_FG)) {
|
||||
buffer->last_fg = fg;
|
||||
data[pos++] = 0;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
if (flags & GUI_PRINT_FLAG_COLOR_24_FG)
|
||||
format_24bit_line_color(data, &pos, 0, fg);
|
||||
else
|
||||
#endif
|
||||
if (fg < 0)
|
||||
data[pos++] = LINE_COLOR_DEFAULT;
|
||||
else if (fg < 16)
|
||||
data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg;
|
||||
else if (fg < 256) {
|
||||
data[pos++] = LINE_COLOR_EXT;
|
||||
data[pos++] = fg;
|
||||
}
|
||||
if (*(out->str) != '\0') {
|
||||
*line =
|
||||
textbuffer_insert(buffer, *line, (unsigned char *) out->str, out->len, NULL);
|
||||
}
|
||||
if (bg != buffer->last_bg
|
||||
|| (flags & GUI_PRINT_FLAG_COLOR_24_BG) != (buffer->last_flags & GUI_PRINT_FLAG_COLOR_24_BG)) {
|
||||
buffer->last_bg = bg;
|
||||
data[pos++] = 0;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
if (flags & GUI_PRINT_FLAG_COLOR_24_BG)
|
||||
format_24bit_line_color(data, &pos, 1, bg);
|
||||
else
|
||||
#endif
|
||||
if (bg < 0)
|
||||
data[pos++] = LINE_COLOR_BG | LINE_COLOR_DEFAULT;
|
||||
else if (bg < 16)
|
||||
data[pos++] = LINE_COLOR_BG | bg;
|
||||
else if (bg < 256) {
|
||||
data[pos++] = LINE_COLOR_EXT_BG;
|
||||
data[pos++] = bg;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & GUI_PRINT_FLAG_UNDERLINE) != (buffer->last_flags & GUI_PRINT_FLAG_UNDERLINE)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_UNDERLINE;
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_REVERSE) != (buffer->last_flags & GUI_PRINT_FLAG_REVERSE)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_REVERSE;
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_BLINK) != (buffer->last_flags & GUI_PRINT_FLAG_BLINK)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_BLINK;
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_BOLD) != (buffer->last_flags & GUI_PRINT_FLAG_BOLD)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_BOLD;
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_ITALIC) != (buffer->last_flags & GUI_PRINT_FLAG_ITALIC)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_ITALIC;
|
||||
}
|
||||
if ((flags & GUI_PRINT_FLAG_MONOSPACE) != (buffer->last_flags & GUI_PRINT_FLAG_MONOSPACE)) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_MONOSPACE;
|
||||
}
|
||||
if (flags & GUI_PRINT_FLAG_INDENT) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_INDENT;
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
*line = textbuffer_insert(buffer, *line, data, pos, NULL);
|
||||
}
|
||||
|
||||
buffer->last_flags = flags;
|
||||
g_string_free(out, TRUE);
|
||||
}
|
||||
|
||||
LINE_REC *textbuffer_append(TEXT_BUFFER_REC *buffer,
|
||||
@ -368,6 +166,11 @@ LINE_REC *textbuffer_insert(TEXT_BUFFER_REC *buffer, LINE_REC *insert_after,
|
||||
data[len-2] == 0 && data[len-1] == LINE_CMD_EOL;
|
||||
|
||||
if (buffer->last_eol) {
|
||||
if (!line->info.format) {
|
||||
line->info.text = g_strdup(buffer->cur_text->str);
|
||||
g_string_truncate(buffer->cur_text, 0);
|
||||
}
|
||||
|
||||
buffer->last_fg = -1;
|
||||
buffer->last_bg = -1;
|
||||
buffer->last_flags = 0;
|
||||
@ -395,145 +198,50 @@ void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
line->prev = line->next = NULL;
|
||||
|
||||
buffer->lines_count--;
|
||||
text_chunk_line_free(buffer, line);
|
||||
g_free(line->info.text);
|
||||
textbuffer_format_rec_free(line->info.format);
|
||||
g_slice_free(LINE_REC, line);
|
||||
}
|
||||
|
||||
/* Removes all lines from buffer */
|
||||
void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer)
|
||||
{
|
||||
GSList *tmp;
|
||||
LINE_REC *line;
|
||||
|
||||
g_return_if_fail(buffer != NULL);
|
||||
|
||||
for (tmp = buffer->text_chunks; tmp != NULL; tmp = tmp->next)
|
||||
g_slice_free(TEXT_CHUNK_REC, tmp->data);
|
||||
g_slist_free(buffer->text_chunks);
|
||||
buffer->text_chunks = NULL;
|
||||
|
||||
while (buffer->first_line != NULL) {
|
||||
line = buffer->first_line->next;
|
||||
g_free(buffer->first_line->info.text);
|
||||
textbuffer_format_rec_free(buffer->first_line->info.format);
|
||||
g_slice_free(LINE_REC, buffer->first_line);
|
||||
buffer->first_line = line;
|
||||
}
|
||||
buffer->lines_count = 0;
|
||||
|
||||
buffer->cur_line = NULL;
|
||||
buffer->cur_text = NULL;
|
||||
g_string_truncate(buffer->cur_text, 0);
|
||||
|
||||
buffer->last_eol = TRUE;
|
||||
}
|
||||
|
||||
static void set_color(GString *str, int cmd)
|
||||
void textbuffer_line2text(TEXT_BUFFER_REC *buffer, LINE_REC *line, int coloring, GString *str)
|
||||
{
|
||||
int color = -1;
|
||||
|
||||
if (!(cmd & LINE_COLOR_DEFAULT))
|
||||
color = (cmd & 0x0f)+'0';
|
||||
|
||||
if ((cmd & LINE_COLOR_BG) == 0) {
|
||||
/* change foreground color */
|
||||
g_string_append_printf(str, "\004%c%c",
|
||||
color, FORMAT_COLOR_NOCHANGE);
|
||||
} else {
|
||||
/* change background color */
|
||||
g_string_append_printf(str, "\004%c%c",
|
||||
FORMAT_COLOR_NOCHANGE, color);
|
||||
}
|
||||
}
|
||||
|
||||
void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
|
||||
{
|
||||
unsigned char cmd, *ptr, *tmp;
|
||||
char *ptr, *tmp;
|
||||
|
||||
g_return_if_fail(line != NULL);
|
||||
g_return_if_fail(str != NULL);
|
||||
|
||||
g_string_truncate(str, 0);
|
||||
|
||||
for (ptr = line->text;;) {
|
||||
if (*ptr != 0) {
|
||||
g_string_append_c(str, (char) *ptr);
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
cmd = *ptr;
|
||||
ptr++;
|
||||
|
||||
if (cmd == LINE_CMD_EOL) {
|
||||
/* end of line */
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == LINE_CMD_CONTINUE) {
|
||||
/* line continues in another address.. */
|
||||
memcpy(&tmp, ptr, sizeof(unsigned char *));
|
||||
ptr = tmp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!coloring) {
|
||||
/* no colors, skip coloring commands */
|
||||
if (cmd == LINE_COLOR_EXT || cmd == LINE_COLOR_EXT_BG)
|
||||
ptr++;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
else if (cmd == LINE_COLOR_24)
|
||||
ptr+=4;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cmd & LINE_CMD_EOL) == 0) {
|
||||
/* set color */
|
||||
set_color(str, cmd);
|
||||
} else switch (cmd) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
g_string_append_c(str, 31);
|
||||
break;
|
||||
case LINE_CMD_REVERSE:
|
||||
g_string_append_c(str, 22);
|
||||
break;
|
||||
case LINE_CMD_BLINK:
|
||||
g_string_append_printf(str, "\004%c",
|
||||
FORMAT_STYLE_BLINK);
|
||||
break;
|
||||
case LINE_CMD_BOLD:
|
||||
g_string_append_printf(str, "\004%c",
|
||||
FORMAT_STYLE_BOLD);
|
||||
break;
|
||||
case LINE_CMD_ITALIC:
|
||||
g_string_append_printf(str, "\004%c",
|
||||
FORMAT_STYLE_ITALIC);
|
||||
break;
|
||||
case LINE_CMD_MONOSPACE:
|
||||
g_string_append_printf(str, "\004%c",
|
||||
FORMAT_STYLE_MONOSPACE);
|
||||
break;
|
||||
case LINE_CMD_COLOR0:
|
||||
g_string_append_printf(str, "\004%c%c",
|
||||
'0', FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case LINE_CMD_INDENT:
|
||||
g_string_append_printf(str, "\004%c",
|
||||
FORMAT_STYLE_INDENT);
|
||||
break;
|
||||
case LINE_COLOR_EXT:
|
||||
format_ext_color(str, 0, *ptr++);
|
||||
break;
|
||||
case LINE_COLOR_EXT_BG:
|
||||
format_ext_color(str, 1, *ptr++);
|
||||
break;
|
||||
#ifdef TERM_TRUECOLOR
|
||||
case LINE_COLOR_24:
|
||||
g_string_append_printf(str, "\004%c", FORMAT_COLOR_24);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
ptr = textbuffer_line_get_text(buffer, line);
|
||||
if (coloring == 0) {
|
||||
tmp = ptr;
|
||||
ptr = strip_codes(tmp);
|
||||
g_free(tmp);
|
||||
}
|
||||
g_string_append(str, ptr);
|
||||
g_free(ptr);
|
||||
}
|
||||
|
||||
GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
|
||||
@ -575,7 +283,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
|
||||
(line->info.level & nolevel) == 0;
|
||||
|
||||
if (*text != '\0') {
|
||||
textbuffer_line2text(line, FALSE, str);
|
||||
textbuffer_line2text(buffer, line, FALSE, str);
|
||||
|
||||
if (line_matched) {
|
||||
line_matched = regexp ?
|
||||
|
@ -5,33 +5,23 @@
|
||||
wastes a lot of memory. */
|
||||
#define LINE_TEXT_CHUNK_SIZE (16384 - 16)
|
||||
|
||||
#define LINE_COLOR_BG 0x20
|
||||
#define LINE_COLOR_DEFAULT 0x10
|
||||
#define LINE_INFO_FORMAT_SET (void *) 0x1
|
||||
|
||||
enum {
|
||||
LINE_CMD_EOL=0x80, /* line ends here */
|
||||
LINE_CMD_CONTINUE, /* line continues in next block */
|
||||
LINE_CMD_COLOR0, /* change to black, would be same as \0\0 but it breaks things.. */
|
||||
LINE_CMD_UNDERLINE, /* enable/disable underlining */
|
||||
LINE_CMD_REVERSE, /* enable/disable reversed text */
|
||||
LINE_CMD_INDENT, /* if line is split, indent it at this position */
|
||||
LINE_CMD_BLINK, /* enable/disable blink */
|
||||
LINE_CMD_BOLD, /* enable/disable bold */
|
||||
LINE_CMD_ITALIC, /* enable/disable italic */
|
||||
LINE_CMD_MONOSPACE, /* enable/disable monospace (gui only) */
|
||||
LINE_COLOR_EXT, /* extended color */
|
||||
LINE_COLOR_EXT_BG, /* extended bg */
|
||||
#ifdef TERM_TRUECOLOR
|
||||
LINE_COLOR_24, /* 24bit color */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _TEXT_BUFFER_FORMAT_REC;
|
||||
|
||||
typedef struct {
|
||||
int level;
|
||||
time_t time;
|
||||
char *text;
|
||||
struct _TEXT_BUFFER_FORMAT_REC *format;
|
||||
} LINE_INFO_REC;
|
||||
|
||||
typedef struct _LINE_REC {
|
||||
struct _LINE_REC *prev, *next;
|
||||
/* Text in the line. \0 means that the next char will be a
|
||||
color or command.
|
||||
|
||||
@ -45,9 +35,6 @@ typedef struct _LINE_REC {
|
||||
|
||||
DO NOT ADD BLACK WITH \0\0 - this will break things. Use
|
||||
LINE_CMD_COLOR0 instead. */
|
||||
struct _LINE_REC *prev, *next;
|
||||
|
||||
unsigned char *text;
|
||||
LINE_INFO_REC info;
|
||||
} LINE_REC;
|
||||
|
||||
@ -58,12 +45,14 @@ typedef struct {
|
||||
} TEXT_CHUNK_REC;
|
||||
|
||||
typedef struct {
|
||||
GSList *text_chunks;
|
||||
LINE_REC *first_line;
|
||||
int lines_count;
|
||||
WINDOW_REC *window;
|
||||
|
||||
LINE_REC *first_line;
|
||||
int lines_count;
|
||||
|
||||
LINE_REC *cur_line;
|
||||
TEXT_CHUNK_REC *cur_text;
|
||||
GString *cur_text;
|
||||
GSList *cur_info;
|
||||
|
||||
int last_fg;
|
||||
int last_bg;
|
||||
@ -72,7 +61,7 @@ typedef struct {
|
||||
} TEXT_BUFFER_REC;
|
||||
|
||||
/* Create new buffer */
|
||||
TEXT_BUFFER_REC *textbuffer_create(void);
|
||||
TEXT_BUFFER_REC *textbuffer_create(WINDOW_REC *window);
|
||||
/* Destroy the buffer */
|
||||
void textbuffer_destroy(TEXT_BUFFER_REC *buffer);
|
||||
|
||||
@ -96,7 +85,7 @@ void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line);
|
||||
/* Removes all lines from buffer, ignoring reference counters */
|
||||
void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer);
|
||||
|
||||
void textbuffer_line2text(LINE_REC *line, int coloring, GString *str);
|
||||
void textbuffer_line2text(TEXT_BUFFER_REC *buffer, LINE_REC *line, int coloring, GString *str);
|
||||
GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
|
||||
int level, int nolevel, const char *text,
|
||||
int before, int after,
|
||||
|
@ -108,6 +108,7 @@ textui_sources = \
|
||||
textui/TextBufferView.xs \
|
||||
textui/Statusbar.xs \
|
||||
textui/Makefile.PL.in \
|
||||
textui/wrapper_buffer_line.h \
|
||||
textui/typemap \
|
||||
textui/module.h
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#define PERL_NO_GET_CONTEXT
|
||||
#include "module.h"
|
||||
#include "wrapper_buffer_line.h"
|
||||
#include <irssi/src/fe-text/textbuffer-formats.h>
|
||||
|
||||
MODULE = Irssi::TextUI::TextBuffer PACKAGE = Irssi
|
||||
PROTOTYPES: ENABLE
|
||||
@ -12,7 +14,7 @@ Irssi::TextUI::Line
|
||||
textbuffer_line_prev(line)
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
RETVAL = line->prev;
|
||||
RETVAL = perl_wrap_buffer_line(line->buffer, line->line->prev);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
@ -20,7 +22,7 @@ Irssi::TextUI::Line
|
||||
textbuffer_line_next(line)
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
RETVAL = line->next;
|
||||
RETVAL = perl_wrap_buffer_line(line->buffer, line->line->next);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
@ -33,8 +35,36 @@ PREINIT:
|
||||
SV *result;
|
||||
PPCODE:
|
||||
str = g_string_new(NULL);
|
||||
textbuffer_line2text(line, coloring, str);
|
||||
textbuffer_line2text(line->buffer, line->line, coloring, str);
|
||||
result = new_pv(str->str);
|
||||
XPUSHs(sv_2mortal(result));
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
void
|
||||
textbuffer_line_get_format(line)
|
||||
Irssi::TextUI::Line line
|
||||
PREINIT:
|
||||
HV *hv;
|
||||
AV *av;
|
||||
LINE_REC *l;
|
||||
TEXT_BUFFER_FORMAT_REC *f;
|
||||
int i;
|
||||
PPCODE:
|
||||
hv = newHV();
|
||||
l = line->line;
|
||||
if (l->info.format != NULL) {
|
||||
f = l->info.format;
|
||||
(void) hv_store(hv, "module", 6, new_pv(f->module), 0);
|
||||
(void) hv_store(hv, "format", 6, new_pv(f->format), 0);
|
||||
(void) hv_store(hv, "server_tag", 10, new_pv(f->server_tag), 0);
|
||||
(void) hv_store(hv, "target", 6, new_pv(f->target), 0);
|
||||
(void) hv_store(hv, "nick", 4, new_pv(f->nick), 0);
|
||||
av = newAV();
|
||||
for (i = 0; i < f->nargs; i++) {
|
||||
av_push(av, new_pv(f->args[i]));
|
||||
}
|
||||
(void) hv_store(hv, "args", 4, newRV_noinc((SV *) av), 0);
|
||||
} else {
|
||||
(void) hv_store(hv, "text", 4, new_pv(l->info.text), 0);
|
||||
}
|
||||
XPUSHs(sv_2mortal(newRV_noinc((SV *) hv)));
|
||||
|
@ -1,5 +1,6 @@
|
||||
#define PERL_NO_GET_CONTEXT
|
||||
#include "module.h"
|
||||
#include "wrapper_buffer_line.h"
|
||||
|
||||
MODULE = Irssi::TextUI::TextBufferView PACKAGE = Irssi::TextUI::TextBuffer PREFIX = textbuffer_
|
||||
PROTOTYPES: ENABLE
|
||||
@ -33,6 +34,10 @@ textbuffer_view_clear(view)
|
||||
Irssi::TextUI::Line
|
||||
textbuffer_view_get_lines(view)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
CODE:
|
||||
RETVAL = perl_wrap_buffer_line(view->buffer, textbuffer_view_get_lines(view));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
textbuffer_view_scroll(view, lines)
|
||||
@ -43,16 +48,24 @@ void
|
||||
textbuffer_view_scroll_line(view, line)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
textbuffer_view_scroll_line(view, line->line);
|
||||
|
||||
Irssi::TextUI::LineCache
|
||||
textbuffer_view_get_line_cache(view, line)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
RETVAL = textbuffer_view_get_line_cache(view, line->line);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
textbuffer_view_remove_line(view, line)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
textbuffer_view_remove_line(view, line->line);
|
||||
|
||||
void
|
||||
textbuffer_view_remove_all_lines(view)
|
||||
@ -68,6 +81,8 @@ textbuffer_view_set_bookmark(view, name, line)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
char *name
|
||||
Irssi::TextUI::Line line
|
||||
CODE:
|
||||
textbuffer_view_set_bookmark(view, name, line->line);
|
||||
|
||||
void
|
||||
textbuffer_view_set_bookmark_bottom(view, name)
|
||||
@ -78,6 +93,10 @@ Irssi::TextUI::Line
|
||||
textbuffer_view_get_bookmark(view, name)
|
||||
Irssi::TextUI::TextBufferView view
|
||||
char *name
|
||||
CODE:
|
||||
RETVAL = perl_wrap_buffer_line(view->buffer, textbuffer_view_get_bookmark(view, name));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
textbuffer_view_redraw(view)
|
||||
|
@ -1,11 +1,17 @@
|
||||
#define PERL_NO_GET_CONTEXT
|
||||
#include "module.h"
|
||||
#include "wrapper_buffer_line.h"
|
||||
|
||||
void perl_statusbar_init(void);
|
||||
void perl_statusbar_deinit(void);
|
||||
|
||||
static int initialized = FALSE;
|
||||
|
||||
static SV *buffer_line_bless(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
{
|
||||
return perl_buffer_line_bless(perl_wrap_buffer_line(buffer, line));
|
||||
}
|
||||
|
||||
static void perl_main_window_fill_hash(HV *hv, MAIN_WINDOW_REC *window)
|
||||
{
|
||||
(void) hv_store(hv, "active", 6, plain_bless(window->active, "Irssi::UI::Window"), 0);
|
||||
@ -20,9 +26,9 @@ static void perl_main_window_fill_hash(HV *hv, MAIN_WINDOW_REC *window)
|
||||
|
||||
static void perl_text_buffer_fill_hash(HV *hv, TEXT_BUFFER_REC *buffer)
|
||||
{
|
||||
(void) hv_store(hv, "first_line", 10, plain_bless(buffer->first_line, "Irssi::TextUI::Line"), 0);
|
||||
(void) hv_store(hv, "first_line", 10, buffer_line_bless(buffer, buffer->first_line), 0);
|
||||
(void) hv_store(hv, "lines_count", 11, newSViv(buffer->lines_count), 0);
|
||||
(void) hv_store(hv, "cur_line", 8, plain_bless(buffer->cur_line, "Irssi::TextUI::Line"), 0);
|
||||
(void) hv_store(hv, "cur_line", 8, buffer_line_bless(buffer, buffer->cur_line), 0);
|
||||
(void) hv_store(hv, "last_eol", 8, newSViv(buffer->last_eol), 0);
|
||||
}
|
||||
|
||||
@ -38,20 +44,22 @@ static void perl_text_buffer_view_fill_hash(HV *hv, TEXT_BUFFER_VIEW_REC *view)
|
||||
|
||||
(void) hv_store(hv, "ypos", 4, newSViv(view->ypos), 0);
|
||||
|
||||
(void) hv_store(hv, "startline", 9, plain_bless(view->startline, "Irssi::TextUI::Line"), 0);
|
||||
(void) hv_store(hv, "startline", 9, buffer_line_bless(view->buffer, view->startline), 0);
|
||||
(void) hv_store(hv, "subline", 7, newSViv(view->subline), 0);
|
||||
(void) hv_store(hv, "hidden_level", 12, newSViv(view->hidden_level), 0);
|
||||
|
||||
(void) hv_store(hv, "bottom_startline", 16, plain_bless(view->bottom_startline, "Irssi::TextUI::Line"), 0);
|
||||
(void) hv_store(hv, "bottom_startline", 16,
|
||||
buffer_line_bless(view->buffer, view->bottom_startline), 0);
|
||||
(void) hv_store(hv, "bottom_subline", 14, newSViv(view->bottom_subline), 0);
|
||||
|
||||
(void) hv_store(hv, "empty_linecount", 15, newSViv(view->empty_linecount), 0);
|
||||
(void) hv_store(hv, "bottom", 6, newSViv(view->bottom), 0);
|
||||
}
|
||||
|
||||
static void perl_line_fill_hash(HV *hv, LINE_REC *line)
|
||||
static void perl_line_fill_hash(HV *hv, struct Buffer_Line_Wrapper *line)
|
||||
{
|
||||
(void) hv_store(hv, "info", 4, plain_bless(&line->info, "Irssi::TextUI::LineInfo"), 0);
|
||||
(void) hv_store(hv, "info", 4, plain_bless(&Line(line)->info, "Irssi::TextUI::LineInfo"),
|
||||
0);
|
||||
}
|
||||
|
||||
static void perl_line_cache_fill_hash(HV *hv, LINE_CACHE_REC *cache)
|
||||
@ -242,7 +250,7 @@ CODE:
|
||||
format_create_dest(&dest, NULL, NULL, level, window);
|
||||
text = format_string_expand(str, NULL);
|
||||
text2 = g_strconcat(text, "\n", NULL);
|
||||
gui_printtext_after_time(&dest, prev, text2, time);
|
||||
gui_printtext_after_time(&dest, Line(prev), text2, time);
|
||||
g_free(text);
|
||||
g_free(text2);
|
||||
|
||||
@ -257,13 +265,14 @@ PREINIT:
|
||||
TEXT_DEST_REC dest;
|
||||
CODE:
|
||||
format_create_dest(&dest, NULL, NULL, level, window);
|
||||
gui_printtext_after_time(&dest, prev, str, time);
|
||||
gui_printtext_after_time(&dest, Line(prev), str, time);
|
||||
|
||||
Irssi::TextUI::Line
|
||||
last_line_insert(window)
|
||||
Irssi::UI::Window window
|
||||
CODE:
|
||||
RETVAL = WINDOW_GUI(window)->insert_after;
|
||||
RETVAL = perl_wrap_buffer_line(WINDOW_GUI(window)->view->buffer,
|
||||
WINDOW_GUI(window)->insert_after);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
@ -281,7 +290,7 @@ PREINIT:
|
||||
TEXT_DEST_REC dest;
|
||||
CODE:
|
||||
format_create_dest(&dest, server, target, level, NULL);
|
||||
gui_printtext_after_time(&dest, prev, str, time);
|
||||
gui_printtext_after_time(&dest, Line(prev), str, time);
|
||||
|
||||
BOOT:
|
||||
irssi_boot(TextUI__Statusbar);
|
||||
|
@ -11,7 +11,7 @@
|
||||
typedef MAIN_WINDOW_REC *Irssi__TextUI__MainWindow;
|
||||
typedef TEXT_BUFFER_REC *Irssi__TextUI__TextBuffer;
|
||||
typedef TEXT_BUFFER_VIEW_REC *Irssi__TextUI__TextBufferView;
|
||||
typedef LINE_REC *Irssi__TextUI__Line;
|
||||
typedef struct Buffer_Line_Wrapper *Irssi__TextUI__Line;
|
||||
typedef LINE_CACHE_REC *Irssi__TextUI__LineCache;
|
||||
typedef LINE_INFO_REC *Irssi__TextUI__LineInfo;
|
||||
typedef SBAR_ITEM_REC *Irssi__TextUI__StatusbarItem;
|
||||
|
@ -2,7 +2,7 @@ TYPEMAP
|
||||
Irssi::TextUI::MainWindow T_PlainObj
|
||||
Irssi::TextUI::TextBuffer T_PlainObj
|
||||
Irssi::TextUI::TextBufferView T_PlainObj
|
||||
Irssi::TextUI::Line T_PlainObj
|
||||
Irssi::TextUI::Line T_BufferLineWrapper
|
||||
Irssi::TextUI::LineCache T_PlainObj
|
||||
Irssi::TextUI::LineInfo T_PlainObj
|
||||
Irssi::TextUI::StatusbarItem T_PlainObj
|
||||
@ -12,8 +12,13 @@ INPUT
|
||||
T_PlainObj
|
||||
$var = irssi_ref_object($arg)
|
||||
|
||||
T_BufferLineWrapper
|
||||
$var = irssi_ref_buffer_line_wrap($arg)
|
||||
|
||||
OUTPUT
|
||||
|
||||
T_PlainObj
|
||||
$arg = plain_bless($var, \"$type\");
|
||||
|
||||
T_BufferLineWrapper
|
||||
$arg = perl_buffer_line_bless($var);
|
||||
|
90
src/perl/textui/wrapper_buffer_line.h
Normal file
90
src/perl/textui/wrapper_buffer_line.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef IRSSI_PERL_TEXTUI_WRAPPER_BUFFER_LINE_H
|
||||
#define IRSSI_PERL_TEXTUI_WRAPPER_BUFFER_LINE_H
|
||||
|
||||
/* This Buffer_Line_Wrapper is a compatibility shim so that the Perl
|
||||
* API does not change in Irssi ABI 24 even though the C API was
|
||||
* changed. That way scripts can continue to work unchanged. */
|
||||
|
||||
struct Buffer_Line_Wrapper {
|
||||
LINE_REC *line;
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
};
|
||||
|
||||
#define Line(wrapper) ((wrapper) == NULL ? NULL : (wrapper)->line)
|
||||
|
||||
static int magic_free_buffer_line(pTHX_ SV *sv, MAGIC *mg)
|
||||
{
|
||||
struct Buffer_Line_Wrapper *wrap = (struct Buffer_Line_Wrapper *) mg->mg_ptr;
|
||||
g_free(wrap);
|
||||
mg->mg_ptr = NULL;
|
||||
sv_setiv(sv, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MGVTBL vtbl_free_buffer_line = { NULL, NULL, NULL, NULL, magic_free_buffer_line };
|
||||
|
||||
static struct Buffer_Line_Wrapper *perl_wrap_buffer_line(TEXT_BUFFER_REC *buffer, LINE_REC *line)
|
||||
{
|
||||
struct Buffer_Line_Wrapper *wrap;
|
||||
|
||||
if (line == NULL)
|
||||
return NULL;
|
||||
|
||||
wrap = g_new0(struct Buffer_Line_Wrapper, 1);
|
||||
wrap->buffer = buffer;
|
||||
wrap->line = line;
|
||||
|
||||
return wrap;
|
||||
}
|
||||
|
||||
/* This function is more or less a copy of plain_bless, but with a
|
||||
special divertion to put the wrapper in _wrapper and the original
|
||||
line pointer in _irssi, in order to stay compatible with signals
|
||||
and scripts */
|
||||
static SV *perl_buffer_line_bless(struct Buffer_Line_Wrapper *object)
|
||||
{
|
||||
SV *ret, **tmp;
|
||||
HV *hv;
|
||||
const char *stash = "Irssi::TextUI::Line";
|
||||
|
||||
if (object == NULL)
|
||||
return &PL_sv_undef;
|
||||
|
||||
ret = irssi_bless_plain(stash, object);
|
||||
hv = hvref(ret);
|
||||
|
||||
tmp = hv_fetch(hv, "_irssi", 6, 0);
|
||||
|
||||
sv_magic(*tmp, NULL, '~', NULL, 0);
|
||||
|
||||
SvMAGIC(*tmp)->mg_private = 0x1551; /* HF */
|
||||
SvMAGIC(*tmp)->mg_virtual = &vtbl_free_buffer_line;
|
||||
SvMAGIC(*tmp)->mg_ptr = (char *) object;
|
||||
|
||||
(void) hv_store(hv, "_wrapper", 8, *tmp, 0);
|
||||
/* We have to put the Line Pointer in _irssi, not the
|
||||
compatibility wrapper */
|
||||
*tmp = newSViv((IV) object->line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is a copy of irssi_ref_object, but looking up the
|
||||
wrapper object in _wrapper instead */
|
||||
static void *irssi_ref_buffer_line_wrap(SV *o)
|
||||
{
|
||||
SV **sv;
|
||||
HV *hv;
|
||||
void *p;
|
||||
|
||||
hv = hvref(o);
|
||||
if (hv == NULL)
|
||||
return NULL;
|
||||
|
||||
sv = hv_fetch(hv, "_wrapper", 8, 0);
|
||||
if (sv == NULL)
|
||||
croak("variable is damaged");
|
||||
p = GINT_TO_POINTER(SvIV(*sv));
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@ test_paste_join_multiline_SOURCES = \
|
||||
../../src/fe-text/term-terminfo.c \
|
||||
../../src/fe-text/terminfo-core.c \
|
||||
../../src/fe-text/term.c \
|
||||
../../src/fe-text/textbuffer-formats.c \
|
||||
../../src/fe-text/textbuffer-view.c \
|
||||
../../src/fe-text/textbuffer.c \
|
||||
../../src/fe-text/gui-windows.c \
|
||||
|
@ -7,6 +7,7 @@ test_test_paste_join_multiline = executable('test-paste-join-multiline',
|
||||
'../../src/fe-text/term-terminfo.c',
|
||||
'../../src/fe-text/term.c',
|
||||
'../../src/fe-text/terminfo-core.c',
|
||||
'../../src/fe-text/textbuffer-formats.c',
|
||||
'../../src/fe-text/textbuffer-view.c',
|
||||
'../../src/fe-text/textbuffer.c',
|
||||
'mock-irssi.c',
|
||||
|
Loading…
Reference in New Issue
Block a user