mirror of
https://github.com/irssi/irssi.git
synced 2026-08-16 15:12:11 +02:00
This patch implements some 256 colour support for Irssi up from the previous 16 colours. Initial parsing of the %x/%X format codes is implemented and the parser accounts in advances the char* for that. The colour attributes are widened from 4 to 8 bit. The colour protocol is changed to a new format. Some pointers to remaining work are written in the comment in textbuffer.h. Note that Irssi already does support requesting 256 colours from the terminal in the original source code, so this part did not have to be touched.
308 lines
8.5 KiB
C
308 lines
8.5 KiB
C
/*
|
|
gui-printtext.c : irssi
|
|
|
|
Copyright (C) 1999 Timo Sirainen
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "module.h"
|
|
#include "signals.h"
|
|
#include "settings.h"
|
|
|
|
#include "formats.h"
|
|
#include "printtext.h"
|
|
|
|
#include "term.h"
|
|
#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 };
|
|
static int scrollback_lines, scrollback_time, scrollback_burst_remove;
|
|
|
|
static int next_xpos, next_ypos;
|
|
|
|
static GHashTable *indent_functions;
|
|
static INDENT_FUNC default_indent_func;
|
|
|
|
void gui_register_indent_func(const char *name, INDENT_FUNC func)
|
|
{
|
|
gpointer key, value;
|
|
GSList *list;
|
|
|
|
if (g_hash_table_lookup_extended(indent_functions, name, &key, &value)) {
|
|
list = value;
|
|
g_hash_table_remove(indent_functions, key);
|
|
} else {
|
|
key = g_strdup(name);
|
|
list = NULL;
|
|
}
|
|
|
|
list = g_slist_append(list, (void *) func);
|
|
g_hash_table_insert(indent_functions, key, list);
|
|
}
|
|
|
|
void gui_unregister_indent_func(const char *name, INDENT_FUNC func)
|
|
{
|
|
gpointer key, value;
|
|
GSList *list;
|
|
|
|
if (g_hash_table_lookup_extended(indent_functions, name, &key, &value)) {
|
|
list = value;
|
|
|
|
list = g_slist_remove(list, (void *) func);
|
|
g_hash_table_remove(indent_functions, key);
|
|
if (list == NULL)
|
|
g_free(key);
|
|
else
|
|
g_hash_table_insert(indent_functions, key, list);
|
|
}
|
|
|
|
if (default_indent_func == func)
|
|
gui_set_default_indent(NULL);
|
|
|
|
textbuffer_views_unregister_indent_func(func);
|
|
}
|
|
|
|
void gui_set_default_indent(const char *name)
|
|
{
|
|
GSList *list;
|
|
|
|
list = name == NULL ? NULL :
|
|
g_hash_table_lookup(indent_functions, name);
|
|
default_indent_func = list == NULL ? NULL :
|
|
(INDENT_FUNC) list->data;
|
|
gui_windows_reset_settings();
|
|
}
|
|
|
|
INDENT_FUNC get_default_indent_func(void)
|
|
{
|
|
return default_indent_func;
|
|
}
|
|
|
|
void gui_printtext(int xpos, int ypos, const char *str)
|
|
{
|
|
next_xpos = xpos;
|
|
next_ypos = ypos;
|
|
|
|
printtext_gui(str);
|
|
|
|
next_xpos = next_ypos = -1;
|
|
}
|
|
|
|
void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time)
|
|
{
|
|
GUI_WINDOW_REC *gui;
|
|
|
|
gui = WINDOW_GUI(dest->window);
|
|
|
|
gui->use_insert_after = TRUE;
|
|
gui->insert_after = prev;
|
|
gui->insert_after_time = time;
|
|
format_send_to_gui(dest, str);
|
|
gui->use_insert_after = FALSE;
|
|
}
|
|
|
|
void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str)
|
|
{
|
|
gui_printtext_after_time(dest, prev, str, 0);
|
|
}
|
|
|
|
static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
|
|
{
|
|
LINE_REC *line;
|
|
time_t old_time;
|
|
|
|
old_time = time(NULL)-scrollback_time+1;
|
|
if (view->buffer->lines_count >=
|
|
scrollback_lines+scrollback_burst_remove) {
|
|
/* remove lines by line count */
|
|
while (view->buffer->lines_count > scrollback_lines) {
|
|
line = view->buffer->first_line;
|
|
if (line->info.time >= old_time ||
|
|
scrollback_lines == 0) {
|
|
/* too new line, don't remove yet - also
|
|
if scrollback_lines is 0, we want to check
|
|
only scrollback_time setting. */
|
|
break;
|
|
}
|
|
textbuffer_view_remove_line(view, line);
|
|
}
|
|
}
|
|
}
|
|
|
|
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_BOLD) {
|
|
*attr |= ATTR_BOLD;
|
|
g_message( "getcolor: setting flag_bold\n");
|
|
}
|
|
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");
|
|
}
|
|
}
|
|
|
|
static void view_add_eol(TEXT_BUFFER_VIEW_REC *view, LINE_REC **line)
|
|
{
|
|
static const unsigned char eol[] = { 0, LINE_CMD_EOL };
|
|
|
|
*line = textbuffer_insert(view->buffer, *line, eol, 2, NULL);
|
|
textbuffer_view_insert_line(view, *line);
|
|
}
|
|
|
|
static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
|
|
void *bgcolor, void *pflags,
|
|
char *str, TEXT_DEST_REC *dest)
|
|
{
|
|
GUI_WINDOW_REC *gui;
|
|
TEXT_BUFFER_VIEW_REC *view;
|
|
LINE_REC *insert_after;
|
|
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_move(root_window, next_xpos, next_ypos);
|
|
if (flags & GUI_PRINT_FLAG_CLRTOEOL)
|
|
term_clrtoeol(root_window);
|
|
term_addstr(root_window, str);
|
|
next_xpos += strlen(str); /* FIXME utf8 or big5 */
|
|
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);
|
|
|
|
view = gui->view;
|
|
insert_after = gui->use_insert_after ?
|
|
gui->insert_after : view->buffer->cur_line;
|
|
|
|
if (flags & GUI_PRINT_FLAG_NEWLINE) {
|
|
view_add_eol(view, &insert_after);
|
|
}
|
|
textbuffer_line_add_colors(view->buffer, &insert_after, fg, bg, flags);
|
|
|
|
insert_after = textbuffer_insert(view->buffer, insert_after,
|
|
(unsigned char *) str,
|
|
strlen(str), &lineinfo);
|
|
if (gui->use_insert_after)
|
|
gui->insert_after = insert_after;
|
|
}
|
|
|
|
static void sig_gui_printtext_finished(WINDOW_REC *window)
|
|
{
|
|
TEXT_BUFFER_VIEW_REC *view;
|
|
LINE_REC *insert_after;
|
|
|
|
view = WINDOW_GUI(window)->view;
|
|
insert_after = WINDOW_GUI(window)->use_insert_after ?
|
|
WINDOW_GUI(window)->insert_after : view->buffer->cur_line;
|
|
|
|
view_add_eol(view, &insert_after);
|
|
remove_old_lines(view);
|
|
}
|
|
|
|
static void read_settings(void)
|
|
{
|
|
scrollback_lines = settings_get_int("scrollback_lines");
|
|
scrollback_time = settings_get_time("scrollback_time")/1000;
|
|
scrollback_burst_remove = settings_get_int("scrollback_burst_remove");
|
|
}
|
|
|
|
void gui_printtext_init(void)
|
|
{
|
|
next_xpos = next_ypos = -1;
|
|
default_indent_func = NULL;
|
|
indent_functions = g_hash_table_new((GHashFunc) g_str_hash,
|
|
(GCompareFunc) g_str_equal);
|
|
|
|
settings_add_int("history", "scrollback_lines", 500);
|
|
settings_add_time("history", "scrollback_time", "1day");
|
|
settings_add_int("history", "scrollback_burst_remove", 10);
|
|
|
|
signal_add("gui print text", (SIGNAL_FUNC) sig_gui_print_text);
|
|
signal_add("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished);
|
|
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
|
|
|
read_settings();
|
|
}
|
|
|
|
void gui_printtext_deinit(void)
|
|
{
|
|
g_hash_table_destroy(indent_functions);
|
|
|
|
signal_remove("gui print text", (SIGNAL_FUNC) sig_gui_print_text);
|
|
signal_remove("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished);
|
|
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
|
}
|