1
0
mirror of https://github.com/irssi/irssi.git synced 2024-09-29 04:45:57 -04:00

Finish 256 colour support for Irssi

256 colour patch is cleaned up and the remaining cases are made work,
this includes especially Theme support, which was not implemented
before. Changes not related to colours were reverted again, making a
review of the two patches against master easier to follow.

As a byproduct of the Hex-colour code parser, the 24bit colours are
also implemented. Actually using them in the terminal is guarded by a
compile time switch (as well as a run time switch), as it breaks the
existing colour protocol and requires additional storage.

To make a seamless usage, down-conversion is provided for 8 and 16
colours.

Diverging from Tom's approach, the colour protocol is reverted back to
the original one. Unfortunately, the changes required in the Theme
engine will break the API.

For more details, please refer to the patch documentation at either
http://irssi-docs.wikispaces.com/Notes-256-Colour or
https://github.com/shabble/irssi-docs/wiki/Notes-256-Colour
This commit is contained in:
Ailin Nemui 2014-01-09 15:20:29 +01:00
parent 2d4edc5187
commit 96a292d40e
28 changed files with 908 additions and 497 deletions

View File

@ -78,3 +78,5 @@ Other patches (grep for "patch" in ChangeLog) by:
Ismael Luceno
Thomas Karpiniec
Svante Kvarnström
Ailin Nemui (Nei)
Tom Feist (shabble)

View File

@ -166,6 +166,15 @@ AC_ARG_ENABLE(dane,
fi,
want_dane=no)
AC_ARG_ENABLE(true-color,
[ --enable-true-color Build with true color support in terminal],
if test x$enableval = xno ; then
want_truecolor=no
else
want_truecolor=yes
fi,
want_truecolor=no)
dnl **
dnl ** SSL Library checks (OpenSSL)
dnl **
@ -643,6 +652,12 @@ if test "x$want_dane" = "xyes"; then
fi
fi
if test "x$want_truecolor" = "xyes" -a "x$want_termcap" != "xyes" -a "x$want_terminfo" = "xyes" ; then
AC_DEFINE([TERM_TRUECOLOR], [], [true color support in terminal])
else
want_truecolor=no
fi
AC_CONFIG_FILES([
Makefile
src/Makefile
@ -761,6 +776,7 @@ echo "Building with SSL support ........ : $have_openssl"
echo "Building with 64bit DCC support .. : $offt_64bit"
echo "Building with garbage collector .. : $have_gc"
echo "Building with DANE support ....... : $have_dane"
echo "Building with true color support.. : $want_truecolor"
echo
echo "If there are any problems, read the INSTALL file."

View File

@ -27,6 +27,8 @@
%| Marks the indentation position
%# Monospace font on/off (useful with lists and GUI)
%% A single %
%XAB %xAB Color from extended plane (A=1-7, B=0-Z)
%ZAABBCC %zAABBCC HTML color (in hex notation)
In .theme files %n works a bit differently. See default.theme
for more information.

View File

@ -130,6 +130,7 @@ aliases = {
CHAT = "dcc chat";
RUN = "SCRIPT LOAD";
CALC = "exec - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi";
CUBES = "/script exec Irssi::active_win->print(\"%_bases\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x0\\${_}0\\$_\" } '0'..'9','A'..'F' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_cubes\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { my \\$y = \\$_*6 \\; join '', map { my \\$x = \\$_ \\; map { \"%x\\$x\\$_\\$x\\$_\" } @{['0'..'9','A'..'Z']}[\\$y .. \\$y+5] } 1..6 }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) for 0..5 \\; Irssi::active_win->print(\"%_grays\", MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print( do { join '', map { \"%x7\\${_}7\\$_\" } 'A'..'X' }, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; Irssi::active_win->print(\"%_mIRC extended colours\", MSGLEVEL_CLIENTCRAP) \\; my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 0..15 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) \\; for my \\$z (0..6) { my \\$x \\; \\$x .= sprintf \"\00399,%02d%02d\",\\$_,\\$_ for 16+(\\$z*12)..16+(\\$z*12)+11 \\; Irssi::active_win->print(\\$x, MSGLEVEL_NEVER | MSGLEVEL_CLIENTCRAP) }";
SBAR = "STATUSBAR";
INVITELIST = "mode $C +I";
Q = "QUERY";

View File

@ -39,10 +39,6 @@
#endif
#include <glib.h>
/* TODO: wrap this in some autoconf macro bullocks? */
#include <glib/gstdio.h>
#ifdef HAVE_GMODULE
# include <gmodule.h>
#endif

View File

@ -51,7 +51,7 @@ void session_upgrade(void)
return;
execv(session_args[0], session_args);
g_message( "exec failed: %s: %s\n",
fprintf(stderr, "exec failed: %s: %s\n",
session_args[0], g_strerror(errno));
}

View File

@ -55,9 +55,6 @@ static int no_autoconnect;
static char *cmdline_nick;
static char *cmdline_hostname;
static char *irssi_logfile = NULL;
static FILE * logfile_FILE = NULL;
void fe_core_log_init(void);
void fe_core_log_deinit(void);
@ -123,26 +120,13 @@ static void sig_channel_destroyed(CHANNEL_REC *channel)
void fe_common_core_register_options(void)
{
static GOptionEntry options[]
= {
{ "connect", 'c', 0, G_OPTION_ARG_STRING, &autocon_server,
"Automatically connect to server/network", "SERVER"
},
{ "password", 'w', 0, G_OPTION_ARG_STRING, &autocon_password,
"Autoconnect password", "PASSWORD"
},
{ "port", 'p', 0, G_OPTION_ARG_INT, &autocon_port,
"Autoconnect port", "PORT" },
{ "noconnect", '!', 0, G_OPTION_ARG_NONE, &no_autoconnect,
"Disable autoconnecting", NULL },
static GOptionEntry options[] = {
{ "connect", 'c', 0, G_OPTION_ARG_STRING, &autocon_server, "Automatically connect to server/network", "SERVER" },
{ "password", 'w', 0, G_OPTION_ARG_STRING, &autocon_password, "Autoconnect password", "PASSWORD" },
{ "port", 'p', 0, G_OPTION_ARG_INT, &autocon_port, "Autoconnect port", "PORT" },
{ "noconnect", '!', 0, G_OPTION_ARG_NONE, &no_autoconnect, "Disable autoconnecting", NULL },
{ "nick", 'n', 0, G_OPTION_ARG_STRING, &cmdline_nick, "Specify nick to use", NULL },
{ "hostname", 'h', 0, G_OPTION_ARG_STRING, &cmdline_hostname,
"Specify host name to use", NULL },
{ "logfile", 0, 0, G_OPTION_ARG_FILENAME, &irssi_logfile,
"Logfile to write debugging data which would otherwise be printed " \
"to STDERR or as Irssi internal messages", "PATH"
},
{ "hostname", 'h', 0, G_OPTION_ARG_STRING, &cmdline_hostname, "Specify host name to use", NULL },
{ NULL }
};
@ -159,9 +143,6 @@ void fe_common_core_init(void)
{
const char *str;
logfile_FILE = g_fopen(irssi_logfile, "a");
if (logfile_FILE == NULL) irssi_logfile = NULL;
settings_add_bool("lookandfeel", "timestamps", TRUE);
settings_add_level("lookandfeel", "timestamp_level", "ALL");
settings_add_time("lookandfeel", "timestamp_timeout", "0");
@ -262,10 +243,6 @@ void fe_common_core_deinit(void)
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
if (irssi_logfile && logfile_FILE) {
fclose(logfile_FILE);
}
}
void glog_func(const char *log_domain, GLogLevelFlags log_level,
@ -280,24 +257,17 @@ void glog_func(const char *log_domain, GLogLevelFlags log_level,
case G_LOG_LEVEL_CRITICAL:
reason = "critical";
break;
case G_LOG_LEVEL_MESSAGE:
reason = "msg";
break;
default:
reason = "error";
break;
}
if (irssi_logfile != NULL && logfile_FILE != NULL) {
fprintf(logfile_FILE, "GLib: %s: %s", reason, message);
fflush(logfile_FILE);
} else { // if (windows == NULL)
fprintf(stderr, "GLib %s: %s", reason, message);
if (windows == NULL)
fprintf(stderr, "GLib %s: %s\n", reason, message);
else {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
TXT_GLIB_ERROR, reason, message);
}
/* else { */
/* printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, */
/* TXT_GLIB_ERROR, reason, message); */
/* } */
}
#define MSGS_WINDOW_LEVELS (MSGLEVEL_MSGS|MSGLEVEL_ACTIONS|MSGLEVEL_DCCMSGS)

View File

@ -348,12 +348,12 @@ static void process_exec(PROCESS_REC *rec, const char *cmd)
if (rec->shell) {
execvp(shell_args[0], (char **) shell_args);
g_message( "Exec: /bin/sh: %s\n", g_strerror(errno));
fprintf(stderr, "Exec: /bin/sh: %s\n", g_strerror(errno));
} else {
args = g_strsplit(cmd, " ", -1);
execvp(args[0], args);
g_message( "Exec: %s: %s\n", args[0], g_strerror(errno));
fprintf(stderr, "Exec: %s: %s\n", args[0], g_strerror(errno));
}
_exit(-1);

View File

@ -588,6 +588,63 @@ static void window_print_daychange(WINDOW_REC *window, struct tm *tm)
printtext_string_window(window, MSGLEVEL_NEVER, str);
}
short color_24bit_256 (const unsigned char rgb[])
{
static const int cstep_size = 40;
static const int cstep_start = 0x5f;
static const int gstep_size = 10;
static const int gstep_start = 0x08;
int dist[3] = {0};
int r[3], gr[3];
size_t i;
for (i = 0; i < 3; ++i) {
const int n = rgb[i];
gr[i] = -1;
if (n < cstep_start /2) {
r[i] = 0;
dist[i] = -cstep_size/2;
}
else {
r[i] = 1+((n-cstep_start + cstep_size /2)/cstep_size);
dist[i] = ((n-cstep_start + cstep_size /2)%cstep_size - cstep_size/2);
}
if (n < gstep_start /2) {
gr[i] = -1;
}
else {
gr[i] = ((n-gstep_start + gstep_size /2)/gstep_size);
}
}
if (r[0] == r[1] && r[1] == r[2] &&
4*abs(dist[0]) < gstep_size && 4*abs(dist[1]) < gstep_size && 4*abs(dist[2]) < gstep_size) {
/* skip gray detection */
}
else {
const int j = r[1] == r[2] ? 0 : 1;
if ((r[0] == r[1] || r[j] == r[2]) && abs(r[j]-r[(j+1)%3]) <= 1) {
const int k = gr[1] == gr[2] ? 0 : 1;
if ((gr[0] == gr[1] || gr[k] == gr[2]) && abs(gr[k]-gr[(k+1)%3]) <= 2) {
if (gr[k] < 0) {
r[0] = r[1] = r[2] = 0;
}
else if (gr[k] > 23) {
r[0] = r[1] = r[2] = 5;
}
else {
r[0] = 6;
r[1] = (gr[k] / 6);
r[2] = gr[k]%6;
}
}
}
}
return 16 + r[0]*36 + r[1] * 6 + r[2];
}
static void sig_print_text(void)
{
GSList *tmp;

View File

@ -97,4 +97,6 @@ void window_bind_remove_unsticky(WINDOW_REC *window);
void windows_init(void);
void windows_deinit(void);
short color_24bit_256(const unsigned char rgb[]);
#endif

View File

@ -66,8 +66,6 @@ static void format_expand_code(const char **format, GString *out, int *flags)
{
int set;
g_message( "format_expand_codes()\n");
if (flags == NULL) {
/* flags are being ignored - skip the code */
while (**format != ']')
@ -103,22 +101,89 @@ static void format_expand_code(const char **format, GString *out, int *flags)
}
}
void format_ext_color(GString *out, int bg, int color)
{
g_string_append_c(out, 4);
if (bg && color < 0x10)
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
if (color < 0x10)
g_string_append_c(out, color+'0');
else {
if (color < 0x60)
g_string_append_c(out, bg ? FORMAT_COLOR_EXT1_BG
: FORMAT_COLOR_EXT1);
else if (color < 0xb0)
g_string_append_c(out, bg ? FORMAT_COLOR_EXT2_BG
: FORMAT_COLOR_EXT2);
else
g_string_append_c(out, bg ? FORMAT_COLOR_EXT3_BG
: FORMAT_COLOR_EXT3);
g_string_append_c(out, FORMAT_COLOR_NOCHANGE + ((color-0x10)%0x50));
}
if (!bg && color < 0x10)
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
}
#ifdef TERM_TRUECOLOR
void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int *flags)
{
unsigned int color;
unsigned char rgbx[4];
unsigned int i;
for (i = 0; i < 4; ++i) {
rgbx[i] = (*ptr)[i + off];
}
rgbx[3] -= 0x20;
*ptr += 4;
for (i = 0; i < 3; ++i) {
if (rgbx[3] & (0x10 << i))
rgbx[i] -= 0x20;
}
color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2];
if (rgbx[3] & 0x1) {
*bgcolor = color;
*flags |= GUI_PRINT_FLAG_COLOR_24_BG;
}
else {
*fgcolor = color;
*flags |= GUI_PRINT_FLAG_COLOR_24_FG;
}
}
#endif
void format_24bit_color(GString *out, int bg, unsigned int color)
{
unsigned char rgb[] = { color >> 16, color >> 8, color };
#ifdef TERM_TRUECOLOR
unsigned char x = bg ? 0x1 : 0;
unsigned int i;
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_COLOR_24);
for (i = 0; i < 3; ++i) {
if (rgb[i] > 0x20)
g_string_append_c(out, rgb[i]);
else {
g_string_append_c(out, 0x20 + rgb[i]);
x |= 0x10 << i;
}
}
g_string_append_c(out, 0x20 + x);
#else /* !TERM_TRUECOLOR */
format_ext_color(out, bg, color_24bit_256(rgb));
#endif /* TERM_TRUECOLOR */
}
int format_expand_styles(GString *out, const char **format, int *flags)
{
int retval = 1;
int retval = 1;
char *p, fmt;
/* storage for numerical parsing code for %x/X formats. */
unsigned char accum = 0;
int tmp, i;
//memset(num_buf, 0, 4);
int tmp;
unsigned int tmp2;
fmt = **format;
g_message( "format_expand_styles: fmtchar: %c\n", fmt);
switch (fmt) {
case '{':
case '}':
@ -134,7 +199,6 @@ int format_expand_styles(GString *out, const char **format, int *flags)
case '9':
case '_':
/* bold on/off */
g_message( "setting bold flag: %04x\n", FORMAT_STYLE_BOLD);
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_STYLE_BOLD);
break;
@ -177,45 +241,61 @@ int format_expand_styles(GString *out, const char **format, int *flags)
format_expand_code(format, out, flags);
break;
case 'x':
tmp = 0;
accum = 0;
for (i = 1; i < 3; i++) {
char fmtchar = (*format)[i];
g_message("Format X: code: %c\n", fmtchar);
tmp = g_ascii_xdigit_value(fmtchar);
if (tmp != -1) {
accum = accum * 16 + tmp;
}
}
retval += i - 1;
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
g_string_append_c(out, accum);
g_message("Format x: code: %d (0x%02x)\n", accum, accum);
break;
case 'X':
tmp = 0;
accum = 0;
for (i = 1; i < 3; i++) {
char fmtchar = (*format)[i];
g_message("Format X: code: %c\n", fmtchar);
tmp = g_ascii_xdigit_value(fmtchar);
if (tmp != -1) {
accum = accum * 16 + tmp;
}
}
g_string_append_c(out, 4);
g_string_append_c(out, accum);
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
retval += i - 1;
if ((*format)[1] < '0' || (*format)[1] > '7')
break;
g_message("Format X: code: %d (0x%02x)\n", accum, accum);
break;
tmp = 16 + ((*format)[1]-'0'-1)*36;
if (tmp > 231) {
if (!isalpha((*format)[2]))
break;
tmp += (*format)[2] >= 'a' ? (*format)[2] - 'a' : (*format)[2] - 'A';
if (tmp > 255)
break;
}
else if (tmp > 0) {
if (!isalnum((*format)[2]))
break;
if ((*format)[2] >= 'a')
tmp += 10 + (*format)[2] - 'a';
else if ((*format)[2] >= 'A')
tmp += 10 + (*format)[2] - 'A';
else
tmp += (*format)[2] - '0';
}
else {
if (!isxdigit((*format)[2]))
break;
tmp = g_ascii_xdigit_value((*format)[2]);
}
retval += 2;
format_ext_color(out, fmt == 'x', tmp);
break;
case 'z':
case 'Z':
tmp2 = 0;
for (tmp = 1; tmp < 7; ++tmp) {
if (!isxdigit((*format)[tmp])) {
tmp2 = UINT_MAX;
break;
}
tmp2 <<= 4;
tmp2 |= g_ascii_xdigit_value((*format)[tmp]);
}
if (tmp2 == UINT_MAX)
break;
retval += 6;
format_24bit_color(out, fmt == 'z', tmp2);
break;
default:
/* check if it's a background color */
p = strchr(format_backs, fmt);
@ -223,8 +303,6 @@ int format_expand_styles(GString *out, const char **format, int *flags)
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
g_string_append_c(out, (char) ((int) (p-format_backs)+'0'));
g_message( "BG: Printing: %d '%s'\n",
((int) (p-format_backs)+'0'), out->str);
break;
}
@ -232,7 +310,6 @@ int format_expand_styles(GString *out, const char **format, int *flags)
if (fmt == 'p') fmt = 'm';
p = strchr(format_fores, fmt);
if (p != NULL) {
/* color code indicator for format_send_to_gui */
g_string_append_c(out, 4);
g_string_append_c(out, (char) ((int) (p-format_fores)+'0'));
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
@ -244,13 +321,12 @@ int format_expand_styles(GString *out, const char **format, int *flags)
p = strchr(format_boldfores, fmt);
if (p != NULL) {
g_string_append_c(out, 4);
/* +8 selects bold version */
g_string_append_c(out, (char) (8+(int) (p-format_boldfores)+'0'));
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
break;
}
return 0;
return FALSE;
}
return retval;
@ -375,10 +451,9 @@ int format_get_length(const char *str)
if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL);
str += adv;
if (adv > 1) {
if (adv)
continue;
}
}
/* %% or unknown %code, written as-is */
if (*str != '%')
@ -415,10 +490,9 @@ int format_real_length(const char *str, int len)
if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL);
str += adv;
if (adv > 1) {
if (adv)
continue;
}
}
/* %% or unknown %code, written as-is */
if (*str != '%') {
@ -439,8 +513,6 @@ int format_real_length(const char *str, int len)
char *format_string_expand(const char *text, int *flags)
{
g_message( "format_string_expand: flags: %04x\n", *flags);
GString *out;
char code, *ret;
int adv;
@ -454,13 +526,13 @@ char *format_string_expand(const char *text, int *flags)
while (*text != '\0') {
if (code == '%') {
/* color code */
adv = format_expand_styles(out, &text, flags);
if (!adv) {
adv = format_expand_styles(out, &text, flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, '%');
g_string_append_c(out, *text);
} else {
text += adv -1;
} else {
text += adv - 1;
}
code = 0;
} else {
@ -492,13 +564,13 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
while (*text != '\0') {
if (code == '%') {
/* color code */
adv = format_expand_styles(out, &text, &dest->flags);
if (!adv) {
adv = format_expand_styles(out, &text, &dest->flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, '%');
g_string_append_c(out, *text);
} else {
text += adv -1;
} else {
text += adv - 1;
}
code = 0;
} else if (code == '$') {
@ -789,13 +861,22 @@ void format_newline(WINDOW_REC *window)
"", NULL);
}
#ifndef TERM_TRUECOLOR
inline static int color_24bit_256_int(unsigned int color)
{
unsigned char rgb[] = { color >> 16, color >> 8, color };
return color_24bit_256(rgb);
}
#endif /* !TERM_TRUECOLOR */
/* parse ANSI color string */
static const char *get_ansi_color(THEME_REC *theme, const char *str,
int *fg_ret, int *bg_ret, int *flags_ret)
{
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
const char *start;
int fg, bg, flags, num;
int fg, bg, flags, num, i;
unsigned int num2;
if (*str != '[')
return str;
@ -822,28 +903,127 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
/* reset colors back to default */
fg = theme->default_color;
bg = -1;
flags &= ~GUI_PRINT_FLAG_INDENT;
flags &= ~(GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT);
break;
case 1:
/* hilight */
flags |= GUI_PRINT_FLAG_BOLD;
break;
case 22:
/* normal */
flags &= ~GUI_PRINT_FLAG_BOLD;
break;
case 4:
/* underline */
flags |= GUI_PRINT_FLAG_UNDERLINE;
break;
case 24:
/* not underline */
flags &= ~GUI_PRINT_FLAG_UNDERLINE;
break;
case 5:
/* blink */
flags |= GUI_PRINT_FLAG_BLINK;
break;
case 25:
/* steady */
flags &= ~GUI_PRINT_FLAG_BLINK;
break;
case 7:
/* reverse */
flags |= GUI_PRINT_FLAG_REVERSE;
break;
case 27:
/* positive */
flags &= ~GUI_PRINT_FLAG_REVERSE;
break;
case 39:
/* reset fg */
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = theme->default_color;
break;
case 49:
/* reset bg */
bg = -1;
flags &= ~(GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT);
break;
case 38:
case 48:
/* ANSI indexed color or RGB color */
if (*str != ';') break;
str++;
for (num2 = 0; i_isdigit(*str); str++)
num2 = num2*10 + (*str-'0');
switch (num2) {
case 2:
/* RGB */
num2 = 0;
for (i = 0; i < 3; ++i) {
num2 <<= 8;
if (*str != ';' && *str != ':') {
i = -1;
break;
}
str++;
for (; i_isdigit(*str); str++)
num2 = (num2&~0xff) |
(((num2&0xff) * 10 + (*str-'0'))&0xff);
}
if (i == -1) break;
#ifdef TERM_TRUECOLOR
if (num == 38) {
flags |= GUI_PRINT_FLAG_COLOR_24_FG;
fg = num2;
} else if (num == 48) {
flags |= GUI_PRINT_FLAG_COLOR_24_BG;
bg = num2;
}
#else /* !TERM_TRUECOLOR */
if (num == 38) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = color_24bit_256_int(num2);
} else if (num == 48) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = color_24bit_256_int(num2);
}
#endif
break;
case 5:
/* indexed */
if (*str != ';') break;
str++;
for (num2 = 0; i_isdigit(*str); str++)
num2 = num2*10 + (*str-'0');
if (num == 38) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = num2;
} else if (num == 48) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = num2;
}
break;
}
break;
default:
if (num >= 30 && num <= 37) {
if (fg == -1) fg = 0;
fg = (fg & 0xf8) | ansitab[num-30];
}
if (num >= 40 && num <= 47) {
if (bg == -1) bg = 0;
bg = (bg & 0xf8) | ansitab[num-40];
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = ansitab[num-30];
} else if (num >= 40 && num <= 47) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = ansitab[num-40];
} else if (num >= 90 && num <= 97) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = 8 + ansitab[num-90];
} else if (num >= 100 && num <= 107) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = 8 + ansitab[num-100];
}
break;
}
@ -903,14 +1083,10 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret)
if (bg_ret) *bg_ret = bg;
}
/* TODO: What are these magic numbers!?
*/
#define IS_COLOR_CODE(c) \
((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \
(c) == 15 || (c) == 22 || (c) == 27 || (c) == 31)
//#define IS_COLOR_CODE(c) ((c) < 255)
/* Return how many characters in `str' must be skipped before `len'
characters of text is skipped. */
int strip_real_length(const char *str, int len,
@ -935,6 +1111,20 @@ int strip_real_length(const char *str, int len,
*last_color_len = (int) (str-mircstart);
} else if (*str == 4 && str[1] != '\0') {
#ifdef TERM_TRUECOLOR
if (str[1] == FORMAT_COLOR_24 && str[2] != '\0') {
if (str[3] == '\0') str++;
else if (str[4] == '\0') str += 2;
else if (str[5] == '\0') str += 3;
else {
if (last_color_pos != NULL)
*last_color_pos = (int) (str-start);
if (last_color_len != NULL)
*last_color_len = 6;
str+=4;
}
} else
#endif
if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') {
if (last_color_pos != NULL)
*last_color_pos = (int) (str-start);
@ -984,6 +1174,14 @@ char *strip_codes(const char *input)
/* irssi color */
if (p[2] != '\0') {
#ifdef TERM_TRUECOLOR
if (p[1] == FORMAT_COLOR_24) {
if (p[3] == '\0') p += 2;
else if (p[4] == '\0') p += 3;
else if (p[5] == '\0') p += 4;
else p += 5;
} else
#endif /* TERM_TRUECOLOR */
p += 2;
continue;
}
@ -1013,10 +1211,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
dup = str = g_strdup(text);
flags = 0;
fgcolor = theme->default_color;
bgcolor = -1;
flags = 0; fgcolor = theme->default_color; bgcolor = -1;
while (*str != '\0') {
type = '\0';
for (ptr = str; *ptr != '\0'; ptr++) {
@ -1038,17 +1233,12 @@ 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 */
g_message("format_send_to_gui: sending: fg: 0x%04x, " \
"bg: 0x%04x flags: 0x%04x\n", fgcolor, bgcolor, flags);
signal_emit_id(signal_gui_print_text, 6, 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);
/* fprintf("format_send_to_gui: resetting flags: 0x%04x\n", flags); */
}
if (type == '\n') {
@ -1063,12 +1253,12 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
switch (type)
{
case MIRC_BOLD_MARKER:
case 2:
/* bold */
if (!hide_text_style)
flags ^= GUI_PRINT_FLAG_BOLD;
break;
case MIRC_COLOR_MARKER:
case 3:
/* MIRC color */
get_mirc_color((const char **) &ptr,
hide_colors ? NULL : &fgcolor,
@ -1076,7 +1266,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
if (!hide_colors)
flags |= GUI_PRINT_FLAG_MIRC_COLOR;
break;
case LINE_FORMAT_MARKER:
case 4:
/* user specific colors */
flags &= ~GUI_PRINT_FLAG_MIRC_COLOR;
switch (*ptr) {
@ -1088,12 +1278,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
break;
case FORMAT_STYLE_BOLD:
flags ^= GUI_PRINT_FLAG_BOLD;
g_message(
"format bold spotted, flags now: 0x%04x\n",
flags);
break;
case FORMAT_STYLE_REVERSE:
flags ^= GUI_PRINT_FLAG_REVERSE;
break;
@ -1110,16 +1295,47 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
break;
case FORMAT_STYLE_CLRTOEOL:
break;
case FORMAT_COLOR_EXT1:
fgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT1_BG:
bgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
case FORMAT_COLOR_EXT2:
fgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT2_BG:
bgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
case FORMAT_COLOR_EXT3:
fgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT3_BG:
bgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
#ifdef TERM_TRUECOLOR
case FORMAT_COLOR_24:
unformat_24bit_color(&ptr, 1, &fgcolor, &bgcolor, &flags);
break;
#endif
default:
if (*ptr != FORMAT_COLOR_NOCHANGE) {
fgcolor = (unsigned char) *ptr-'0';
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fgcolor = *ptr==(char)0xff ? -1 : (unsigned char) *ptr-'0';
}
if (ptr[1] == '\0')
break;
ptr++;
if (*ptr != FORMAT_COLOR_NOCHANGE) {
bgcolor = *ptr-'0';
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0';
}
}
ptr++;

View File

@ -4,12 +4,6 @@
#include "themes.h"
#include "fe-windows.h"
/* various types of colour codings possible. */
#define MIRC_BOLD_MARKER ('\002')
#define MIRC_COLOR_MARKER ('\003')
#define LINE_FORMAT_MARKER ('\004')
#define GUI_PRINT_FLAG_BOLD 0x0001
#define GUI_PRINT_FLAG_REVERSE 0x0002
#define GUI_PRINT_FLAG_UNDERLINE 0x0004
@ -19,6 +13,8 @@
#define GUI_PRINT_FLAG_NEWLINE 0x0080
#define GUI_PRINT_FLAG_CLRTOEOL 0x0100
#define GUI_PRINT_FLAG_MONOSPACE 0x0200
#define GUI_PRINT_FLAG_COLOR_24_FG 0x0400
#define GUI_PRINT_FLAG_COLOR_24_BG 0x0800
#define MAX_FORMAT_PARAMS 10
#define DEFAULT_FORMAT_ARGLIST_SIZE 200
@ -127,6 +123,15 @@ char *strip_codes(const char *input);
void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
#define FORMAT_COLOR_NOCHANGE ('0'-1) /* don't change this, at least hilighting depends this value */
#define FORMAT_COLOR_EXT1 ('0'-2)
#define FORMAT_COLOR_EXT2 ('0'-3)
#define FORMAT_COLOR_EXT3 ('0'-4)
#define FORMAT_COLOR_EXT1_BG ('0'-5)
#define FORMAT_COLOR_EXT2_BG ('0'-9)
#define FORMAT_COLOR_EXT3_BG ('0'-10)
#ifdef TERM_TRUECOLOR
#define FORMAT_COLOR_24 ('0'-13)
#endif
#define FORMAT_STYLE_SPECIAL 0x60
#define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL)
@ -138,6 +143,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
#define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL)
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 formats_init(void);
void formats_deinit(void);

View File

@ -256,12 +256,12 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
break;
}
default:
adv = format_expand_styles(out, &str, &dest->flags);
if (!adv) {
adv = format_expand_styles(out, &str, &dest->flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, *str);
} else {
str += adv -1;
} else {
str += adv - 1;
}
break;
}
@ -277,6 +277,7 @@ static char *printtext_expand_formats(const char *str, int *flags)
GString *out;
char *ret;
int adv;
out = g_string_new(NULL);
for (; *str != '\0'; str++) {
if (*str != '%') {
@ -292,7 +293,7 @@ static char *printtext_expand_formats(const char *str, int *flags)
g_string_append_c(out, '%');
g_string_append_c(out, *str);
} else {
str += adv -1;
str += adv - 1;
}
}

View File

@ -115,8 +115,8 @@ void theme_destroy(THEME_REC *rec)
}
static char *theme_replace_expand(THEME_REC *theme, int index,
char default_fg, char default_bg,
char *last_fg, char *last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *last_fg, theme_rm_col *last_bg,
char chr, int flags)
{
GSList *rec;
@ -168,15 +168,44 @@ static void theme_format_append_variable(GString *str, const char **format)
g_free(value);
}
static inline int chr_is_valid_rgb(const char format[])
{
int tmp;
for (tmp = 1; tmp < 7; ++tmp) {
if (!isxdigit(format[tmp]))
return tmp;
}
return 0;
}
static inline int chr_is_valid_ext(const char format[])
{
if (format[1] < '0' || format[1] > '7')
return 1;
if (format[1] == '7') {
if (!isalpha(format[2]) || format[2] == 'y' || format[2] == 'Y'
|| format[2] =='z' || format[2] == 'Z')
return 2;
} else if (format[1] == '0') {
if (!isxdigit(format[2]))
return 2;
} else if (!isalnum(format[2]))
return 2;
return 0;
}
/* append next "item", either a character, $variable or %format */
static void theme_format_append_next(THEME_REC *theme, GString *str,
const char **format,
char default_fg, char default_bg,
char *last_fg, char *last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *last_fg, theme_rm_col *last_bg,
int flags)
{
int index;
unsigned char chr;
char *t;
chr = **format;
if ((chr == '$' || chr == '%') &&
@ -203,22 +232,50 @@ static void theme_format_append_next(THEME_REC *theme, GString *str,
/* %n = change to default color */
g_string_append(str, "%n");
if (default_bg != 'n') {
if (default_bg.m[0] != 'n') {
g_string_append_c(str, '%');
g_string_append_c(str, default_bg);
g_string_append(str, default_bg.m);
}
if (default_fg != 'n') {
if (default_fg.m[0] != 'n') {
g_string_append_c(str, '%');
g_string_append_c(str, default_fg);
g_string_append(str, default_fg.m);
}
*last_fg = default_fg;
*last_bg = default_bg;
} else if (chr == 'z' || chr == 'Z') {
if (chr_is_valid_rgb(*format) == 0) {
t = chr == 'z' ? (*last_bg).m : (*last_fg).m;
strncpy(t, *format, 7);
t[7] = '\0';
g_string_append_c(str, '%');
g_string_append(str, t);
(*format)+=6;
} else {
g_string_append(str, "%%");
g_string_append_c(str, **format);
}
} else if (chr == 'x' || chr == 'X') {
if (chr_is_valid_ext(*format) == 0) {
t = chr == 'x' ? (*last_bg).m : (*last_fg).m;
strncpy(t, *format, 3);
t[3] = '\0';
g_string_append_c(str, '%');
g_string_append(str, t);
(*format)+=2;
} else {
g_string_append(str, "%%");
g_string_append_c(str, **format);
}
} else {
if (IS_FGCOLOR_FORMAT(chr))
*last_fg = chr;
if (IS_BGCOLOR_FORMAT(chr))
*last_bg = chr;
if (IS_FGCOLOR_FORMAT(chr)) {
(*last_fg).m[0] = chr;
(*last_fg).m[1] = '\0';
}
if (IS_BGCOLOR_FORMAT(chr)) {
(*last_bg).m[0] = chr;
(*last_bg).m[1] = '\0';
}
g_string_append_c(str, '%');
g_string_append_c(str, chr);
}
@ -306,7 +363,10 @@ static int data_is_empty(const char **data)
char *theme_format_expand_get(THEME_REC *theme, const char **format)
{
GString *str;
char *ret, dummy;
char *ret;
theme_rm_col dummy, reset;
dummy.m[0] = '\0';
strcpy(reset.m, "n");
int braces = 1; /* we start with one brace opened */
str = g_string_new(NULL);
@ -321,7 +381,7 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
continue;
} else {
theme_format_append_next(theme, str, format,
'n', 'n',
reset, reset,
&dummy, &dummy, 0);
continue;
}
@ -343,15 +403,19 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
/* expand a single {abstract ...data... } */
static char *theme_format_expand_abstract(THEME_REC *theme,
const char **formatp,
char default_fg, char default_bg,
theme_rm_col *last_fg,
theme_rm_col *last_bg,
int flags)
{
GString *str;
const char *p, *format;
char *abstract, *data, *ret;
theme_rm_col default_fg, default_bg;
int len;
format = *formatp;
default_fg = *last_fg;
default_bg = *last_bg;
/* get abstract name first */
p = format;
@ -425,7 +489,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* abstract may itself contain abstracts or replaces */
p = abstract;
ret = theme_format_expand_data(theme, &p, default_fg, default_bg,
&default_fg, &default_bg,
last_fg, last_bg,
flags | EXPAND_FLAG_LASTCOLOR_ARG);
g_free(abstract);
return ret;
@ -433,13 +497,13 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* expand the data part in {abstract data} */
char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg,
char *save_last_fg, char *save_last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags)
{
GString *str;
char *ret, *abstract;
char last_fg, last_bg;
theme_rm_col last_fg, last_bg;
int recurse_flags;
last_fg = default_fg;
@ -482,7 +546,7 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
/* get a single {...} */
abstract = theme_format_expand_abstract(theme, format,
last_fg, last_bg,
&last_fg, &last_bg,
recurse_flags);
if (abstract != NULL) {
g_string_append(str, abstract);
@ -490,13 +554,11 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
}
}
if ((flags & EXPAND_FLAG_LASTCOLOR_ARG) == 0) {
/* save the last color */
if (save_last_fg != NULL)
*save_last_fg = last_fg;
if (save_last_bg != NULL)
*save_last_bg = last_bg;
}
ret = str->str;
g_string_free(str, FALSE);
@ -510,7 +572,8 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
{
GString *str;
char *ret, last_fg, last_bg;
char *ret;
char last_fg, last_bg;
str = g_string_new(NULL);
@ -543,8 +606,12 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
if (IS_FGCOLOR_FORMAT(*format))
last_fg = *format;
else if (*format == 'Z' || *format == 'X')
last_fg = '\0';
if (IS_BGCOLOR_FORMAT(*format))
last_bg = *format;
else if (*format == 'z' || *format == 'x')
last_bg = '\0';
}
format++;
}
@ -558,11 +625,13 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
char *theme_format_expand(THEME_REC *theme, const char *format)
{
char *data, *ret;
theme_rm_col reset;
strcpy(reset.m, "n");
g_return_val_if_fail(theme != NULL, NULL);
g_return_val_if_fail(format != NULL, NULL);
data = theme_format_expand_data(theme, &format, 'n', 'n', NULL, NULL,
data = theme_format_expand_data(theme, &format, reset, reset, NULL, NULL,
EXPAND_FLAG_ROOT);
ret = theme_format_compress_colors(theme, data);
g_free(data);
@ -944,10 +1013,6 @@ static int theme_read(THEME_REC *theme, const char *path)
config_get_int(config, NULL, "default_color", -1);
theme->info_eol = config_get_bool(config, NULL, "info_eol", FALSE);
/* FIXME: remove after 0.7.99 */
if (theme->default_color == 0 &&
config_get_int(config, NULL, "default_real_color", -1) != -1)
theme->default_color = -1;
theme_read_replaces(config, theme);
if (path != NULL)

View File

@ -57,10 +57,14 @@ void theme_set_default_abstract(const char *key, const char *value);
#define EXPAND_FLAG_ROOT 0x10
#define EXPAND_FLAG_LASTCOLOR_ARG 0x20
typedef struct {
char m[8];
} theme_rm_col;
char *theme_format_expand(THEME_REC *theme, const char *format);
char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg,
char *save_last_fg, char *save_last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags);
void themes_reload(void);

View File

@ -29,7 +29,14 @@
#include "gui-printtext.h"
#include "gui-windows.h"
int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7 };
int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7,
/* 16-27 */ 52, 94, 100, 58, 22, 29, 23, 24, 17, 54, 53, 89,
/* 28-39 */ 88, 130, 142, 64, 28, 35, 30, 25, 18, 91, 90, 125,
/* 40-51 */ 124, 166, 184, 106, 34, 49, 37, 33, 19, 129, 127, 161,
/* 52-63 */ 196, 208, 226, 154, 46, 86, 51, 75, 21, 171, 201, 198,
/* 64-75 */ 203, 215, 227, 191, 83, 122, 87, 111, 63, 177, 207, 205,
/* 76-87 */ 217, 223, 229, 193, 157, 158, 159, 153, 147, 183, 219, 212,
/* 88-98 */ 16, 233, 235, 237, 239, 241, 244, 247, 250, 254, 231, -1 };
static int scrollback_lines, scrollback_time, scrollback_burst_remove;
static int next_xpos, next_ypos;
@ -145,44 +152,43 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
static void get_colors(int flags, int *fg, int *bg, int *attr)
{
if (flags & GUI_PRINT_FLAG_MIRC_COLOR) {
g_message( "getcolor: handling mirc colors\n");
/* mirc colors - real range is 0..15, but after 16
colors wrap to 0, 1, ... */
if (*bg >= 0) *bg = mirc_colors[*bg % 16];
if (*fg >= 0) *fg = mirc_colors[*fg % 16];
/* TODO: What to do here? */
if (settings_get_bool("mirc_blink_fix"))
*bg &= ~0x08;
}
if (*fg < 0 || *fg > 255) {
g_message( "getcolor: fg %d outside range, setting to -1\n", *fg);
*fg = -1;
}
if (*bg < 0 || *bg > 255) {
g_message( "getcolor: bf %d outside range, setting to -1\n", *bg);
*bg = -1;
}
*attr = 0;
if (flags & GUI_PRINT_FLAG_REVERSE) {
*attr |= ATTR_REVERSE;
g_message( "getcolor: setting flag_reverse\n");
if (flags & GUI_PRINT_FLAG_MIRC_COLOR) {
/* mirc colors - extended colours proposal */
if (*bg >= 0) {
*bg = mirc_colors[*bg % 100];
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
if (settings_get_bool("mirc_blink_fix"))
*bg = term_color256map[*bg&0xff] & ~0x08;
}
if (*fg >= 0) {
*fg = mirc_colors[*fg % 100];
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
}
}
if (flags & GUI_PRINT_FLAG_BOLD) {
*attr |= ATTR_BOLD;
g_message( "getcolor: setting flag_bold\n");
if (flags & GUI_PRINT_FLAG_COLOR_24_FG)
*attr |= ATTR_FGCOLOR24;
else if (*fg < 0 || *fg > 255) {
*fg = -1;
*attr |= ATTR_RESETFG;
}
if (flags & GUI_PRINT_FLAG_UNDERLINE) {
*attr |= ATTR_UNDERLINE;
g_message( "getcolor: setting flag_underline\n");
}
if (flags & GUI_PRINT_FLAG_BLINK) {
*attr |= ATTR_BLINK;
g_message( "getcolor: setting flag_blink\n");
else
*attr |= *fg;
if (flags & GUI_PRINT_FLAG_COLOR_24_BG)
*attr |= ATTR_BGCOLOR24;
else if (*bg < 0 || *bg > 255) {
*bg = -1;
*attr |= ATTR_RESETBG;
}
else
*attr |= (*bg << BG_SHIFT);
if (flags & GUI_PRINT_FLAG_REVERSE) *attr |= ATTR_REVERSE;
if (flags & GUI_PRINT_FLAG_BOLD) *attr |= ATTR_BOLD;
if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE;
if (flags & GUI_PRINT_FLAG_BLINK) *attr |= ATTR_BLINK;
}
static void view_add_eol(TEXT_BUFFER_VIEW_REC *view, LINE_REC **line)
@ -203,33 +209,15 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
LINE_INFO_REC lineinfo;
int fg, bg, flags, attr;
attr = 0;
flags = GPOINTER_TO_INT(pflags);
fg = GPOINTER_TO_INT(fgcolor);
bg = GPOINTER_TO_INT(bgcolor);
g_message( "SGPT str: '%s'\n", str);
g_message( "SGPT start: fg: %d (%02x), bg: %d (%02x) attr: %d (%04x), flags: %d (0x%04x)\n",
fg, fg, bg, bg, attr, attr, flags, flags);
get_colors(flags, &fg, &bg, &attr);
g_message( "SGPT getcol: fg: %d (%02x), bg: %d (%02x) attr: %d (%04x)\n",
fg, fg, (bg << 8), (bg << 8), attr, attr);
if (window == NULL) {
g_return_if_fail(next_xpos != -1);
attr |= fg >= 0 ? fg : ATTR_RESETFG;
attr |= bg >= 0 ? (bg << 8) : ATTR_RESETBG;
g_message(
"SGPT nowin: fg: %d (%02x), bg: %d (%02x) attr: %d (%04x)\n",
fg, fg, (bg << 8), (bg << 8), attr, attr);
term_set_color(root_window, attr);
term_set_color2(root_window, attr, fg, bg);
term_move(root_window, next_xpos, next_ypos);
if (flags & GUI_PRINT_FLAG_CLRTOEOL)

View File

@ -670,6 +670,8 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
SERVER_REC *server;
WI_ITEM_REC *wiitem;
char *tmpstr, *tmpstr2;
theme_rm_col reset;
strcpy(reset.m, "n");
int len;
if (str == NULL)
@ -690,7 +692,7 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
/* expand templates */
tmpstr = theme_format_expand_data(current_theme, &str,
'n', 'n',
reset, reset,
NULL, NULL,
EXPAND_FLAG_ROOT |
EXPAND_FLAG_IGNORE_REPLACES |

View File

@ -275,21 +275,25 @@ static int get_attr(int color)
{
int attr;
if ((color & FG_MASK) >> 4)
color = (color & ~FG_MASK) | term_color256map[color & FG_MASK];
if ((color & BG_MASK) >> (BG_SHIFT + 4))
color = (color & ~BG_MASK) | (term_color256map[(color & BG_MASK) >> BG_SHIFT] << BG_SHIFT);
if (!term_use_colors)
attr = (color & 0x70) ? A_REVERSE : 0;
else if ((color & 0xff) == 8 || (color & (0xff | ATTR_RESETFG)) == 0)
attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0;
else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0)
attr = COLOR_PAIR(63);
else if ((color & 0x77) == 0)
else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0)
attr = A_NORMAL;
else {
if (color & ATTR_RESETFG) {
color &= ~0x0f;
color &= ~FG_MASK;
color |= settings_get_int("default_color");
}
attr = COLOR_PAIR((color&7) | ((color&0x70)>>1));
attr = COLOR_PAIR((color&0x7) | ((color&(0x7<<BG_SHIFT))>>BG_SHIFT<<3));
}
if ((color & 0x08) || (color & ATTR_BOLD)) attr |= A_BOLD;
if ((color & 0x8) || (color & ATTR_BOLD)) attr |= A_BOLD;
if (color & ATTR_BLINK) attr |= A_BLINK;
if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
@ -298,6 +302,11 @@ static int get_attr(int color)
}
/* Change active color */
void term_set_color2(TERM_WINDOW *window, int col, unsigned int fg_ignore, unsigned int bg_ignore)
{
term_set_color(window, col);
}
void term_set_color(TERM_WINDOW *window, int col)
{
wattrset(window->win, get_attr(col));

View File

@ -22,9 +22,12 @@
#include "signals.h"
#include "term.h"
#include "terminfo-core.h"
#include "fe-windows.h"
#include "utf8.h"
#include <signal.h>
#include <termios.h>
#include <stdio.h>
/* returns number of characters in the beginning of the buffer being a
a single character, or -1 if more input is needed. The character will be
@ -48,7 +51,8 @@ static int vcmove, vcx, vcy, curs_visible;
static int crealx, crealy, cforcemove;
static int curs_x, curs_y;
static int last_fg, last_bg, last_attrs;
static unsigned int last_fg, last_bg;
static int last_attrs;
static GSource *sigcont_source;
static volatile sig_atomic_t got_sigcont;
@ -293,118 +297,119 @@ void term_window_scroll(TERM_WINDOW *window, int count)
term_lines_empty[window->y+y] = FALSE;
}
void term_set_color(TERM_WINDOW *window, int col)
inline static int term_putchar(int c)
{
return fputc(c, current_term->out);
}
/* copied from terminfo-core.c */
int tputs();
static int term_set_color_24bit(int bg, unsigned int lc)
{
static char buf[20];
const unsigned char color[] = { lc >> 16, lc >> 8, lc };
if (!term_use_colors24) {
if (bg)
terminfo_set_bg(color_24bit_256(color));
else
terminfo_set_fg(color_24bit_256(color));
return -1;
}
/* \e[x8;2;...;...;...m */
sprintf(buf, "\033[%d8;2;%d;%d;%dm", bg ? 4 : 3, color[0], color[1], color[2]);
return tputs(buf, 0, term_putchar);
}
#define COLOR_RESET UINT_MAX
/* Change active color */
void term_set_color2(TERM_WINDOW *window, int col, unsigned int fgcol24, unsigned int bgcol24)
{
int set_normal;
int fg = (col & FG_MASK);
int bg = (col & BG_MASK) >> 8;
// int attrs = (col & 0xff0000) >> 16;
unsigned int fg = (col & ATTR_FGCOLOR24) ? fgcol24 << 8 : (col & FG_MASK);
unsigned int bg = (col & ATTR_BGCOLOR24) ? bgcol24 << 8 : ((col & BG_MASK) >> BG_SHIFT);
if (col != ATTR_RESET) {
g_message( "T-TI: set color called with col: %d (%08x)\n", col, col);
g_message( "T-TI: fg: %d (0x%02x), bg: %d (0x%02x)\n", fg, fg, bg, bg);
} else {
//g_message( "T-TI: set color called with col: %d (%08x)\n", col, col);
}
set_normal = ((col & ATTR_RESETFG) && last_fg != ATTR_COLOR_UNDEFINED) ||
((col & ATTR_RESETBG) && last_bg != ATTR_COLOR_UNDEFINED);
if (((last_attrs & ATTR_BOLD) && !(col & ATTR_BOLD)) ||
((last_attrs & ATTR_BLINK) && !(col & ATTR_BLINK))) {
set_normal = ((col & ATTR_RESETFG) && last_fg != COLOR_RESET) ||
((col & ATTR_RESETBG) && last_bg != COLOR_RESET);
if (((last_attrs & ATTR_BOLD) && (col & ATTR_BOLD) == 0) ||
((last_attrs & ATTR_BLINK) && (col & ATTR_BLINK) == 0)) {
/* we'll need to get rid of bold/blink - this can only be
done with setting the default color */
set_normal = TRUE;
}
if (set_normal) {
last_fg = last_bg = ATTR_COLOR_UNDEFINED;
last_fg = last_bg = COLOR_RESET;
last_attrs = 0;
g_message( "setnormal: setting last_* to 0%04x\n", last_fg);
terminfo_set_normal();
/* terminfo_set_bg(123); */
//terminfo_set_fg(47);
}
/* if colors are disabled, any background color setting enables
* reverse video mode
*/
if (!term_use_colors && bg > 0) {
if (!term_use_colors && bg > 0)
col |= ATTR_REVERSE;
}
/* reversed text (use standout) */
if (col & ATTR_REVERSE) {
if ((last_attrs & ATTR_REVERSE) == 0) {
g_message( "setreverse: on\n");
if ((last_attrs & ATTR_REVERSE) == 0)
terminfo_set_standout(TRUE);
}
} else if (last_attrs & ATTR_REVERSE) {
g_message( "setreverse: off\n");
} else if (last_attrs & ATTR_REVERSE)
terminfo_set_standout(FALSE);
}
/* set foreground color */
if (fg != last_fg && (fg != 0 || (col & ATTR_RESETFG) == 0)) {
if (fg != last_fg &&
(fg != 0 || (col & ATTR_RESETFG) == 0)) {
if (term_use_colors) {
last_fg = fg;
terminfo_set_fg(last_fg);
g_message( "setfg: setting fg to %d (0x%04x)\n", fg, fg);
if (!(fg & 0xff))
term_set_color_24bit(0, last_fg >> 8);
else
terminfo_set_fg(last_fg);
}
}
/* set background color */
/* TODO: What magic numbers? - originally 0xf0 - 11110000
*
*/
if (col & 0x8000 && window->term->TI_colors == 8) {
g_message( "0x080 match: setting attr_bold\n");
if (window && (term_color256map[bg&0xff]&8) == window->term->TI_colors)
col |= ATTR_BLINK;
}
if (col & ATTR_BLINK) {
g_message( "setblink\n");
if (col & ATTR_BLINK)
current_term->set_blink(current_term);
}
if (bg != last_bg && (bg != 0 || (col & ATTR_RESETBG) == 0)) {
if (bg != last_bg &&
(bg != 0 || (col & ATTR_RESETBG) == 0)) {
if (term_use_colors) {
last_bg = bg;
terminfo_set_bg(last_bg);
g_message( "setbg: setting bg to %d (0x%04x)\n", bg, bg);
if (!(bg & 0xff))
term_set_color_24bit(1, last_bg >> 8);
else
terminfo_set_bg(last_bg);
}
}
/* bold */
/* TODO: maybe make this fg > 7, since that implies a bright
* color,which bold can emulate.
*/
if (fg > 0 && window->term->TI_colors == 8) {
g_message( "0x080 match: setting attr_bold\n");
if (window && (term_color256map[fg&0xff]&8) == window->term->TI_colors)
col |= ATTR_BOLD;
}
if (col & ATTR_BOLD) {
g_message("setbold\n");
if (col & ATTR_BOLD)
terminfo_set_bold();
}
/* underline */
if (col & ATTR_UNDERLINE) {
if ((last_attrs & ATTR_UNDERLINE) == 0) {
if ((last_attrs & ATTR_UNDERLINE) == 0)
terminfo_set_uline(TRUE);
}
} else if (last_attrs & ATTR_UNDERLINE) {
} else if (last_attrs & ATTR_UNDERLINE)
terminfo_set_uline(FALSE);
}
/* update the new attribute settings whilst ignoring color values. */
last_attrs = col & ~( BG_MASK | FG_MASK );
/* update the new attribute settings whilst ignoring color values. */
last_attrs = col & ~( BG_MASK | FG_MASK );
}
void term_set_color(TERM_WINDOW *window, int col)
{
term_set_color2(window, col &~(ATTR_FGCOLOR24|ATTR_BGCOLOR24), UINT_MAX, UINT_MAX);
}
void term_move(TERM_WINDOW *window, int x, int y)
{
if (x >= 0 && y >= 0) {

View File

@ -37,6 +37,7 @@
int term_width, term_height;
int term_use_colors;
int term_use_colors24;
int term_type;
static int force_colors;
@ -106,10 +107,28 @@ static void cmd_redraw(void)
irssi_redraw();
}
int term_color256map[] = {
0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15,
0, 0, 1, 1, 1, 1, 0, 0, 3, 1, 1, 9, 2, 2, 3, 3, 3, 3,
2, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3,11,10,10, 3, 3,11,11,
0, 0, 5, 1, 1, 9, 0, 8, 8, 8, 9, 9, 2, 8, 8, 8, 9, 9,
2, 8, 8, 8, 9, 9, 2, 8, 8, 3, 3,11,10,10, 3, 3,11,11,
4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 9, 9,
6, 8, 8, 8, 8, 9, 6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7,
4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 8, 9,
6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7,
4, 4, 5, 5, 5,13, 4, 8, 8, 5, 5,13, 6, 8, 8, 8, 7, 7,
6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7,
12,12, 5, 5,13,13,12,12, 5, 5,13,13, 6, 6, 8, 7, 7, 7,
6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7,14,14, 7, 7, 7,15,
0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
7, 7, 7, 7, 7, 7, 0 };
static void read_settings(void)
{
const char *str;
int old_colors = term_use_colors;
int old_colors24 = term_use_colors24;
int old_type = term_type;
/* set terminal type */
@ -133,7 +152,14 @@ static void read_settings(void)
term_use_colors = settings_get_bool("colors") &&
(force_colors || term_has_colors());
if (term_use_colors != old_colors)
#ifdef TERM_TRUECOLOR
term_use_colors24 = settings_get_bool("colors_ansi_24bit") &&
(force_colors || term_has_colors());
#else
term_use_colors24 = FALSE;
#endif
if (term_use_colors != old_colors || term_use_colors24 != old_colors24)
irssi_redraw();
}
@ -149,6 +175,12 @@ void term_common_init(void)
force_colors = FALSE;
term_use_colors = term_has_colors() && settings_get_bool("colors");
#ifdef TERM_TRUECOLOR
settings_add_bool("lookandfeel", "colors_ansi_24bit", FALSE);
term_use_colors24 = term_has_colors() && settings_get_bool("colors_ansi_24bit");
#else
term_use_colors24 = FALSE;
#endif
read_settings();
if (g_get_charset(&dummy)) {

View File

@ -3,30 +3,19 @@
typedef struct _TERM_WINDOW TERM_WINDOW;
/* text attributes */
#define FG_MASK ( 0x00ff )
#define BG_MASK ( 0xff00 )
#define BG_SHIFT 8
/* text attributes */
#define ATTR_RESETFG ( 0x010000 )
#define ATTR_RESETBG ( 0x020000 )
#define ATTR_BOLD ( 0x040000 )
#define ATTR_BLINK ( 0x080000 )
#define ATTR_BLINK ( 0x080000 )
#define ATTR_UNDERLINE ( 0x100000 )
#define ATTR_REVERSE ( 0x200000 )
/* can also mean default color, probably. */
#define ATTR_COLOR_UNDEFINED ( -1 )
#define EXT_COLOR_BLACK ( 0 )
#define EXT_COLOR_RED ( 1 )
#define EXT_COLOR_GREEN ( 2 )
#define EXT_COLOR_YELLOW ( 3 )
#define EXT_COLOR_BLUE ( 4 )
#define EXT_COLOR_MAGENTA ( 5 )
#define EXT_COLOR_CYAN ( 6 )
#define EXT_COLOR_WHITE ( 7 )
#define ATTR_FGCOLOR24 ( 0x400000 )
#define ATTR_BGCOLOR24 ( 0x800000 )
#define ATTR_RESET (ATTR_RESETFG|ATTR_RESETBG)
@ -42,6 +31,8 @@ typedef guint32 unichar;
extern TERM_WINDOW *root_window;
extern int term_width, term_height;
extern int term_use_colors, term_type;
extern int term_use_colors24;
extern int term_color256map[];
/* Initialize / deinitialize terminal */
int term_init(void);
@ -80,10 +71,9 @@ void term_window_clear(TERM_WINDOW *window);
/* Scroll window up/down */
void term_window_scroll(TERM_WINDOW *window, int count);
void term_set_color2(TERM_WINDOW *window, int col, unsigned int fgcol24, unsigned int bgcol24);
void term_set_color(TERM_WINDOW *window, int col);
void term_set_extended_color(TERM_WINDOW *window, int fg, int bg);
void term_move(TERM_WINDOW *window, int x, int y);
void term_addch(TERM_WINDOW *window, char chr);
void term_add_unichar(TERM_WINDOW *window, unichar chr);

View File

@ -331,16 +331,29 @@ static void _set_standout(TERM_REC *term, int set)
tput(tparm(set ? term->TI_smso : term->TI_rmso));
}
inline static int color256(const TERM_REC *term, const int color) {
if (color < term->TI_colors)
return color;
if (color < 16)
return color % term->TI_colors;
if (color < 256)
return term_color256map[color] % term->TI_colors;
return color % term->TI_colors;
}
/* Change foreground color */
static void _set_fg(TERM_REC *term, int color)
{
tput(tparm(term->TI_fg[color % term->TI_colors]));
tput(tparm(term->TI_fg[color256(term, color)]));
}
/* Change background color */
static void _set_bg(TERM_REC *term, int color)
{
tput(tparm(term->TI_bg[color % term->TI_colors]));
tput(tparm(term->TI_bg[color256(term, color)]));
}
/* Beep */
@ -519,19 +532,19 @@ static int term_setup(TERM_REC *term)
term_env = getenv("TERM");
if (term_env == NULL) {
g_message( "TERM environment not set\n");
fprintf(stderr, "TERM environment not set\n");
return 0;
}
#ifdef HAVE_TERMINFO
if (setupterm(term_env, 1, &err) != 0) {
g_message( "setupterm() failed for TERM=%s: %d\n", term_env, err);
fprintf(stderr, "setupterm() failed for TERM=%s: %d\n", term_env, err);
return 0;
}
#else
if (tgetent(term->buffer1, term_env) < 1)
{
g_message( "Termcap not found for TERM=%s\n", term_env);
fprintf(stderr, "Termcap not found for TERM=%s\n", term_env);
return 0;
}
#endif
@ -544,7 +557,7 @@ static int term_setup(TERM_REC *term)
else if (term->TI_hpa && term->TI_vpa)
term->move = _move_pa;
else {
g_message( "Terminal doesn't support cursor movement\n");
fprintf(stderr, "Terminal doesn't support cursor movement\n");
return 0;
}
term->move_relative = _move_relative;
@ -561,7 +574,7 @@ static int term_setup(TERM_REC *term)
else if (term->scroll == NULL && (term->TI_il1 && term->TI_dl1))
term->scroll = _scroll_line_1;
else if (term->scroll == NULL) {
g_message( "Terminal doesn't support scrolling\n");
fprintf(stderr, "Terminal doesn't support scrolling\n");
return 0;
}
@ -578,7 +591,7 @@ static int term_setup(TERM_REC *term)
/* we could do this by line inserts as well, but don't
bother - if some terminal has insert line it most probably
has delete line as well, if not a regular clear screen */
g_message( "Terminal doesn't support clearing screen\n");
fprintf(stderr, "Terminal doesn't support clearing screen\n");
return 0;
}
@ -586,7 +599,7 @@ static int term_setup(TERM_REC *term)
if (term->TI_el)
term->clrtoeol = _clrtoeol;
else {
g_message( "Terminal doesn't support clearing to end of line\n");
fprintf(stderr, "Terminal doesn't support clearing to end of line\n");
return 0;
}

View File

@ -16,8 +16,6 @@
#define terminfo_set_bold() current_term->set_bold(current_term)
#define terminfo_set_uline(set) current_term->set_uline(current_term, set)
#define terminfo_set_standout(set) current_term->set_standout(current_term, set)
// new
#define terminfo_set_blink() current_term->set_blink(current_term)
#define terminfo_is_colors_set(term) (term->TI_fg != NULL)
#define terminfo_beep(term) current_term->beep(current_term)

View File

@ -104,65 +104,78 @@ static void textbuffer_cache_unref(TEXT_BUFFER_CACHE_REC *cache)
textbuffer_cache_destroy(cache);
}
#define FGATTR (ATTR_NOCOLORS | ATTR_RESETFG | 0xff)
#define BGATTR (ATTR_NOCOLORS | ATTR_RESETBG | 0xff00)
#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)
{
static int next_color_bg = 0;
g_message( "update_cmd_color() color: 0x%08x, cmd: 0x%08x\n", *color, cmd);
if (cmd & 0x80) { /* cmd message */
switch (cmd) {
if ((cmd & 0x80) == 0) {
if (cmd & LINE_COLOR_BG) {
/* set background color */
*color &= FGATTR;
*color &= ~ATTR_FGCOLOR24;
if ((cmd & LINE_COLOR_DEFAULT) == 0)
*color |= (cmd & 0x0f) << BG_SHIFT;
else {
*color = (*color & FGATTR) | ATTR_RESETBG;
}
} else {
/* set foreground color */
*color &= BGATTR;
*color &= ~ATTR_BGCOLOR24;
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;
g_message( "update_cmd_color() toggle underline 0x%08d\n", *color);
break;
case LINE_CMD_REVERSE:
*color ^= ATTR_REVERSE;
g_message( "update_cmd_color() toggle reverse 0x%08d\n", *color);
break;
case LINE_CMD_BLINK:
*color ^= ATTR_BLINK;
g_message( "update_cmd_color() toggle blink 0x%08d\n", *color);
break;
case LINE_CMD_BOLD:
*color ^= ATTR_BOLD;
g_message( "update_cmd_color() toggle bold 0x%08d\n", *color);
break;
case LINE_CMD_COLOR0:
*color &= BGATTR;
g_message( "update_cmd_color() set BGATTR RESET 0x%08d\n", *color);
break;
case LINE_CMD_SELECT_FG:
next_color_bg = 0;
g_message( "update_cmd_color() Next color will be FG\n");
break;
case LINE_CMD_SELECT_BG:
next_color_bg = 1;
g_message( "update_cmd_color() Next color will be BG\n");
*color &= ~ATTR_FGCOLOR24;
break;
}
} else {
if (next_color_bg == 1) {
*color = cmd << 8;
} else {
*color = cmd;
}
}
}
#ifdef TERM_TRUECOLOR
static void unformat_24bit_line_color(const unsigned char **ptr, int off, int *flags, int *fg, int *bg)
{
unsigned int color;
unsigned char rgbx[4];
unsigned int i;
for (i = 0; i < 4; ++i) {
rgbx[i] = (*ptr)[i + off];
}
rgbx[3] -= 0x20;
*ptr += 4;
for (i = 0; i < 3; ++i) {
if (rgbx[3] & (0x10 << i))
rgbx[i] -= 0x20;
}
color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2];
if (rgbx[3] & 0x1) {
*flags = (*flags & FGATTR) | ATTR_BGCOLOR24;
*bg = color;
}
else {
*flags = (*flags & BGATTR) | ATTR_FGCOLOR24;
*fg = color;
}
}
#endif
static inline unichar read_unichar(const unsigned char *data, const unsigned char **next, int *width)
{
unichar chr = g_utf8_get_char_validated(data, -1);
@ -188,6 +201,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
unsigned char cmd;
const unsigned char *ptr, *next_ptr, *last_space_ptr;
int xpos, pos, indent_pos, last_space, last_color, color, linecount;
int last_bg24, last_fg24, bg24, fg24;
int char_width;
g_return_val_if_fail(line->text != NULL, NULL);
@ -221,7 +235,18 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
/* 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
} 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;
}
@ -253,7 +278,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
sub = g_new0(LINE_CACHE_SUB_REC, 1);
if (last_space > indent_pos && last_space > 10) {
/* go back to last space */
color = last_color;
color = last_color; fg24 = last_fg24; bg24 = last_bg24;
ptr = last_space_ptr;
while (*ptr == ' ') ptr++;
} else if (view->longword_noindent) {
@ -266,6 +291,9 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
sub->indent = xpos;
sub->indent_func = indent_func;
sub->color = color;
#ifdef TERM_TRUECOLOR
sub->fg24 = fg24; sub->bg24 = bg24;
#endif
lines = g_slist_append(lines, sub);
linecount++;
@ -277,11 +305,11 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
if (!view->utf8 && char_width > 1) {
last_space = xpos;
last_space_ptr = next_ptr;
last_color = color;
last_color = color; last_fg24 = fg24; last_bg24 = bg24;
} else if (*ptr == ' ') {
last_space = xpos;
last_space_ptr = ptr;
last_color = color;
last_color = color; last_fg24 = fg24; last_bg24 = bg24;
}
xpos += char_width;
@ -359,7 +387,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
const unsigned char *text, *end, *text_newline;
unsigned char *tmp;
unichar chr;
int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width;
int xpos, color, fg24, bg24, drawcount, first, need_move, need_clrtoeol, char_width;
if (view->dirty) /* don't bother drawing anything - redraw is coming */
return 0;
@ -373,7 +401,6 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
xpos = drawcount = 0; first = TRUE;
text_newline = text =
subline == 0 ? line->text : cache->lines[subline-1].start;
g_message( "view_line_draw()\n");
for (;;) {
if (text == text_newline) {
if (need_clrtoeol && xpos < term_width) {
@ -395,6 +422,10 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
if (indent_func == NULL)
xpos = cache->lines[subline-1].indent;
color = cache->lines[subline-1].color;
#ifdef TERM_TRUECOLOR
fg24 = cache->lines[subline-1].fg24;
bg24 = cache->lines[subline-1].bg24;
#endif
} else {
indent_func = NULL;
}
@ -412,12 +443,10 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
xpos = indent_func(view, line, ypos);
}
if (need_move || xpos > 0) {
if (need_move || xpos > 0)
term_move(view->window, xpos, ypos);
}
g_message( "view_line_draw(): color: 0x%08x\n", color);
term_set_color(view->window, color);
term_set_color2(view->window, color, fg24, bg24);
if (subline == cache->count-1) {
text_newline = NULL;
@ -443,11 +472,17 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
text = tmp;
continue;
} else {
update_cmd_color(*text, &color);
g_message( "post update_cmd_color: 0x%08x\n",
color);
term_set_color(view->window, color);
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);
term_set_color2(view->window, color, fg24, bg24);
}
text++;
continue;
@ -476,13 +511,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
term_addch(view->window, *text);
} else {
/* low-ascii */
g_message( "printing inverse char %c\n",
(chr & 127)+'A'-1);
term_set_color(view->window, ATTR_RESET|ATTR_REVERSE);
term_addch(view->window, (chr & 127)+'A'-1);
g_message( "setting color back to: 0x%08x\n",
color);
term_set_color(view->window, color);
term_set_color2(view->window, color, fg24, bg24);
}
}
text = end;

View File

@ -15,6 +15,9 @@ typedef struct {
int indent;
INDENT_FUNC indent_func;
int color;
#ifdef TERM_TRUECOLOR
int fg24, bg24;
#endif
/* first word in line belong to the end of the last word in
previous line */

View File

@ -39,8 +39,8 @@ TEXT_BUFFER_REC *textbuffer_create(void)
buffer = g_slice_new0(TEXT_BUFFER_REC);
buffer->last_eol = TRUE;
buffer->last_fg = LINE_COLOR_DEFAULT;
buffer->last_bg = LINE_COLOR_DEFAULT | LINE_COLOR_BG;
buffer->last_fg = -1;
buffer->last_bg = -1;
return buffer;
}
@ -148,6 +148,7 @@ static void text_chunk_append(TEXT_BUFFER_REC *buffer,
{
TEXT_CHUNK_REC *chunk;
int left;
int i;
if (len == 0)
return;
@ -166,8 +167,12 @@ static void text_chunk_append(TEXT_BUFFER_REC *buffer,
}
}
if (left > 0 && data[left-1] == 0)
left--; /* don't split the commands */
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;
@ -238,84 +243,92 @@ 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[20];
memset(data, 0, 20);
unsigned char data[22];
int pos;
int pos = 0;
int i = 0;
/* get the fg & bg command chars */
/* TODO: These things are adding additional data to colours. */
g_message( "TBLAC1: fg: 0x%08x, bg: 0x%08x, flags: 0x%08x, last_flags: 0x%08x\n",
fg, bg, flags, buffer->last_flags);
/* fg = fg < 0 ? LINE_COLOR_DEFAULT : fg & 0xff; */
/* bg = LINE_COLOR_BG | (bg < 0 ? LINE_COLOR_DEFAULT : bg & 0xff); */
g_message( "TBLAC2: fg: 0x%02x, bg: 0x%02x\n", fg, bg);
if (fg != buffer->last_fg) {
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;
data[pos++] = LINE_CMD_SELECT_FG;
data[pos++] = 0;
data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg;
g_message( "TBLAC2: fg: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
#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 (bg != buffer->last_bg) {
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;
data[pos++] = LINE_CMD_SELECT_BG;
data[pos++] = 0;
data[pos++] = bg;
g_message( "TBLAC2: bg: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
#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;
g_message( "TBLAC2: underline: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
}
if ((flags & GUI_PRINT_FLAG_REVERSE) != (buffer->last_flags & GUI_PRINT_FLAG_REVERSE)) {
data[pos++] = 0;
data[pos++] = LINE_CMD_REVERSE;
g_message( "TBLAC2: reverse: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
}
if ((flags & GUI_PRINT_FLAG_BLINK) != (buffer->last_flags & GUI_PRINT_FLAG_BLINK)) {
data[pos++] = 0;
data[pos++] = LINE_CMD_BLINK;
g_message( "TBLAC2: blink: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
}
if ((flags & GUI_PRINT_FLAG_BOLD) != (buffer->last_flags & GUI_PRINT_FLAG_BOLD)) {
data[pos++] = 0;
data[pos++] = LINE_CMD_BOLD;
g_message( "TBLAC2: bold: data[%d}=%d(0x%02x)\n", pos,data[pos-1],data[pos-1]);
}
if (flags & GUI_PRINT_FLAG_INDENT) {
data[pos++] = 0;
data[pos++] = LINE_CMD_INDENT;
g_message( "TBLAC2: indent: data[%d}=%d(0x%02x)\n", pos-1,data[pos-1],data[pos-1]);
}
g_message( "TBLAC data:\n");
for (i=0; i < 20; i++) {
g_message( "%02x\n", data[i]);
}
g_message( "\n");
if (pos > 0) {
g_message( "calling textbuffer_insert()\n");
if (pos > 0)
*line = textbuffer_insert(buffer, *line, data, pos, NULL);
}
buffer->last_flags = flags;
}
@ -351,14 +364,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) {
buffer->last_fg = LINE_COLOR_DEFAULT;
buffer->last_bg = LINE_COLOR_DEFAULT | LINE_COLOR_BG;
buffer->last_fg = -1;
buffer->last_bg = -1;
buffer->last_flags = 0;
}
g_message( "line created: '%s' %d\n", line->text, line->info.time);
g_message( "Buffer %p\n", buffer);
return line;
}
@ -413,22 +423,18 @@ void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer)
static void set_color(GString *str, int cmd)
{
int color = ATTR_COLOR_UNDEFINED;
int color = -1;
if (!(cmd & LINE_COLOR_DEFAULT))
color = (cmd & 0xff) + '0';
g_message( "textbuffer.c:set_color color: %d (%02x)\n", color, color);
color = (cmd & 0x0f)+'0';
if ((cmd & LINE_COLOR_BG) == 0) {
/* change foreground color */
g_string_append_printf(str, "%c%c%c",
LINE_FORMAT_MARKER,
g_string_append_printf(str, "\004%c%c",
color, FORMAT_COLOR_NOCHANGE);
} else {
/* change background color */
g_string_append_printf(str, "%c%c%c",
LINE_FORMAT_MARKER,
g_string_append_printf(str, "\004%c%c",
FORMAT_COLOR_NOCHANGE, color);
}
}
@ -467,13 +473,17 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
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;
}
/* these magic numbers correspond with some of IS_COLOR_CODE in
* formats.c:843 (31 and 22) */
if ((cmd & 0x80) == 0) {
if ((cmd & LINE_CMD_EOL) == 0) {
/* set color */
set_color(str, cmd);
} else switch (cmd) {
@ -499,6 +509,17 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
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
}
}
}

View File

@ -8,20 +8,20 @@
#define LINE_COLOR_BG 0x20
#define LINE_COLOR_DEFAULT 0x10
/* command values (see _LINE_REC protocol) */
enum {
LINE_CMD_EOL=0x80, /* line ends here */
LINE_CMD_CONTINUE, /* line continues in next block */
/* TODO: no longer needed */
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_SELECT_FG,
LINE_CMD_SELECT_BG
LINE_COLOR_EXT, /* extended color */
LINE_COLOR_EXT_BG, /* extended bg */
#ifdef TERM_TRUECOLOR
LINE_COLOR_24, /* 24bit color */
#endif
};
typedef struct {
@ -29,7 +29,6 @@ typedef struct {
time_t time;
} LINE_INFO_REC;
/* TODO: fixme. */
typedef struct _LINE_REC {
/* Text in the line. \0 means that the next char will be a
color or command.
@ -44,28 +43,6 @@ typedef struct _LINE_REC {
DO NOT ADD BLACK WITH \0\0 - this will break things. Use
LINE_CMD_COLOR0 instead. */
/* NEW COLOUR PROTOCOL:
0x00 - indicates command or colour.
0x01 - command follows (1 byte)
-- following may be omitted if LINE_CMD_USE_DEFAULT_[FB}G is set.
0x02 - BG colour follows (1 byte)
0x04 - FG colour follows (1 byte)
Things that will need to be fixed:
* textbuffer-view.c:update_cmd_color()
* textbuffer-view.c:view_line_draw()
* textbuffer-view.c:view_update_line_cache()
* textbuffer.c:textbuffer_line2text()
* textbuffer.c:mark_temp_eol macro
* gui-printtext.c ?
*/
struct _LINE_REC *prev, *next;
unsigned char *text;

View File

@ -241,8 +241,11 @@ PPCODE:
if (flags == 0) {
ret = theme_format_expand(theme, format);
} else {
ret = theme_format_expand_data(theme, (const char **) &format, 'n', 'n',
NULL, NULL, EXPAND_FLAG_ROOT | flags);
theme_rm_col reset;
strcpy(reset.m, "n");
ret = theme_format_expand_data(theme, (const char **) &format,
reset, reset, NULL, NULL,
EXPAND_FLAG_ROOT | flags);
}
XPUSHs(sv_2mortal(new_pv(ret)));
g_free_not_null(ret);