Merged Irssi 0.8.2 from irssi.org cvs.
[silc.git] / apps / irssi / src / fe-text / gui-printtext.c
index 5faae0fa3b53b2d025a726dae523ff5124081aaa..429937a52c1bc79a6b73306267e9967816df7b0d 100644 (file)
 #include "formats.h"
 #include "printtext.h"
 
-#include "screen.h"
+#include "term.h"
+#include "gui-printtext.h"
 #include "gui-windows.h"
 
-int mirc_colors[] = { 15, 0, 1, 2, 12, 6, 5, 4, 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 };
 static int scrollback_lines, scrollback_hours, scrollback_burst_remove;
 
-static int scrollback_save_formats;
-static GString *format;
-
-static int last_color, last_flags;
+static int last_fg, last_bg, last_flags;
 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;
@@ -47,6 +103,18 @@ void gui_printtext(int xpos, int ypos, const char *str)
        next_xpos = next_ypos = -1;
 }
 
+void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str)
+{
+       GUI_WINDOW_REC *gui;
+
+       gui = WINDOW_GUI(dest->window);
+
+       gui->use_insert_after = TRUE;
+       gui->insert_after = prev;
+       format_send_to_gui(dest, str);
+       gui->use_insert_after = FALSE;
+}
+
 static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
 {
        LINE_REC *line;
@@ -57,9 +125,12 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
            scrollback_lines+scrollback_burst_remove) {
                 /* remove lines by line count */
                while (view->buffer->lines_count > scrollback_lines) {
-                       line = view->buffer->lines->data;
-                       if (line->info.time >= old_time) {
-                               /* too new line, don't remove yet */
+                       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_hours setting. */
                                break;
                        }
                        textbuffer_view_remove_line(view, line);
@@ -67,77 +138,87 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
        }
 }
 
-static void get_colors(int flags, int *fg, int *bg)
+static void get_colors(int flags, int *fg, int *bg, int *attr)
 {
-       if (flags & PRINTFLAG_MIRC_COLOR) {
+       if (flags & GUI_PRINT_FLAG_MIRC_COLOR) {
                /* mirc colors - real range is 0..15, but after 16
                   colors wrap to 0, 1, ... */
-               *bg = *bg < 0 ? 0 : mirc_colors[*bg % 16];
-               if (*fg > 0) *fg = mirc_colors[*fg % 16];
-       } else {
-               /* default colors */
-               *bg = *bg < 0 || *bg > 15 ? 0 : *bg;
-                if (*fg > 8) *fg &= ~8;
+                if (*bg >= 0) *bg = mirc_colors[*bg % 16];
+               if (*fg >= 0) *fg = mirc_colors[*fg % 16];
+               if (settings_get_bool("mirc_blink_fix"))
+                       *bg &= ~0x08;
        }
 
-       if (*fg < 0 || *fg > 15) {
-               *fg = *bg == 0 ? current_theme->default_color :
-                       current_theme->default_real_color;
-       }
-
-       if (flags & PRINTFLAG_REVERSE) {
-               int tmp;
-
-               tmp = *fg; *fg = *bg; *bg = tmp;
-       }
+       if (*fg < 0 || *fg > 15)
+               *fg = -1;
+       if (*bg < 0 || *bg > 15)
+                *bg = -1;
 
-       if (*fg == 8) *fg |= ATTR_COLOR8;
-       if (flags & PRINTFLAG_BOLD) {
-               if (*fg == 0) *fg = current_theme->default_real_color;
-               *fg |= 8;
-       }
-       if (flags & PRINTFLAG_UNDERLINE) *fg |= ATTR_UNDERLINE;
-       if (flags & PRINTFLAG_BLINK) *bg |= 0x08;
+       *attr = 0;
+       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 line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
                            int fg, int bg, int flags)
 {
-       unsigned char data[12];
-       int color, pos;
+       unsigned char data[20];
+       int pos;
 
-       /* color should never have last bit on or it would be treated as a
-          command! */
-       color = (fg & 0x0f) | ((bg & 0x07) << 4);
-       pos = 0;
+        /* get the fg & bg command chars */
+       fg = fg < 0 ? LINE_COLOR_DEFAULT : fg & 0x0f;
+       bg = LINE_COLOR_BG | (bg < 0 ? LINE_COLOR_DEFAULT : bg & 0x0f);
+       if (flags & GUI_PRINT_FLAG_BOLD)
+               fg |= LINE_COLOR_BOLD;
+       if (flags & GUI_PRINT_FLAG_BLINK)
+                bg |= LINE_COLOR_BLINK;
 
-       if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != last_color) ||
-           ((fg & ATTR_COLOR8) && (fg & 0xf0) != (last_color & 0xf0))) {
+       pos = 0;
+       if (fg != last_fg) {
+               last_fg = fg;
                data[pos++] = 0;
-               data[pos++] = color == 0 ? LINE_CMD_COLOR0 : color;
+               data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg;
        }
-
-       if ((flags & PRINTFLAG_UNDERLINE) != (last_flags & PRINTFLAG_UNDERLINE)) {
+       if (bg != last_bg) {
+                last_bg = bg;
                data[pos++] = 0;
-               data[pos++] = LINE_CMD_UNDERLINE;
+               data[pos++] = bg;
        }
-       if (fg & ATTR_COLOR8) {
+
+       if ((flags & GUI_PRINT_FLAG_UNDERLINE) != (last_flags & GUI_PRINT_FLAG_UNDERLINE)) {
                data[pos++] = 0;
-               data[pos++] = LINE_CMD_COLOR8;
+               data[pos++] = LINE_CMD_UNDERLINE;
        }
-       if (bg & 0x08) {
+       if ((flags & GUI_PRINT_FLAG_REVERSE) != (last_flags & GUI_PRINT_FLAG_REVERSE)) {
                data[pos++] = 0;
-               data[pos++] = LINE_CMD_BLINK;
+               data[pos++] = LINE_CMD_REVERSE;
        }
-       if (flags & PRINTFLAG_INDENT) {
+       if (flags & GUI_PRINT_FLAG_INDENT) {
                data[pos++] = 0;
                data[pos++] = LINE_CMD_INDENT;
        }
 
-       *line = textbuffer_insert(buffer, *line, data, pos, NULL);
+        if (pos > 0)
+               *line = textbuffer_insert(buffer, *line, data, pos, NULL);
 
        last_flags = flags;
-       last_color = fg | (bg << 4);
+}
+
+static void line_add_indent_func(TEXT_BUFFER_REC *buffer, LINE_REC **line,
+                                const char *function)
+{
+        GSList *list;
+        unsigned char data[1+sizeof(INDENT_FUNC)];
+
+        list = g_hash_table_lookup(indent_functions, function);
+       if (list != NULL) {
+               data[0] = LINE_CMD_INDENT_FUNC;
+               memcpy(data+1, list->data, sizeof(INDENT_FUNC));
+               *line = textbuffer_insert(buffer, *line,
+                                         data, sizeof(data), NULL);
+       }
 }
 
 static void view_add_eol(TEXT_BUFFER_VIEW_REC *view, LINE_REC **line)
@@ -152,22 +233,28 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
                               void *bgcolor, void *pflags,
                               char *str, void *level)
 {
+        GUI_WINDOW_REC *gui;
         TEXT_BUFFER_VIEW_REC *view;
        LINE_REC *insert_after;
         LINE_INFO_REC lineinfo;
-       int fg, bg, flags;
+       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);
+       get_colors(flags, &fg, &bg, &attr);
 
        if (window == NULL) {
                 g_return_if_fail(next_xpos != -1);
 
-               wmove(stdscr, next_ypos, next_xpos);
-               set_color(stdscr, fg | (bg << 4));
-                addstr(str);
+               attr |= fg >= 0 ? fg : ATTR_RESETFG;
+               attr |= bg >= 0 ? (bg << 4) : ATTR_RESETBG;
+               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);
                 return;
        }
@@ -175,23 +262,33 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
        lineinfo.level = GPOINTER_TO_INT(level);
         lineinfo.time = time(NULL);
 
-       view = WINDOW_GUI(window)->view;
-       insert_after = WINDOW_GUI(window)->use_insert_after ?
-               WINDOW_GUI(window)->insert_after : view->buffer->cur_line;
+        gui = WINDOW_GUI(window);
+       view = gui->view;
+       insert_after = gui->use_insert_after ?
+               gui->insert_after : view->buffer->cur_line;
 
-       if (flags & PRINTFLAG_NEWLINE)
+       if (flags & GUI_PRINT_FLAG_NEWLINE)
                 view_add_eol(view, &insert_after);
        line_add_colors(view->buffer, &insert_after, fg, bg, flags);
-       textbuffer_insert(view->buffer, insert_after,
-                         str, strlen(str), &lineinfo);
+
+       if (flags & GUI_PRINT_FLAG_INDENT_FUNC) {
+               /* specify the indentation function */
+                line_add_indent_func(view->buffer, &insert_after, str);
+       } else {
+               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_printtext_finished(WINDOW_REC *window)
+static void sig_gui_printtext_finished(WINDOW_REC *window)
 {
        TEXT_BUFFER_VIEW_REC *view;
        LINE_REC *insert_after;
 
-        last_color = 0;
+        last_fg = last_bg = -1;
        last_flags = 0;
 
        view = WINDOW_GUI(window)->view;
@@ -202,74 +299,36 @@ static void sig_printtext_finished(WINDOW_REC *window)
        remove_old_lines(view);
 }
 
-static void sig_print_format(THEME_REC *theme, const char *module,
-                            TEXT_DEST_REC *dest, void *formatnump,
-                            char **args)
-{
-       FORMAT_REC *formats;
-       int formatnum, n;
-
-       if (!scrollback_save_formats)
-               return;
-
-       formatnum = GPOINTER_TO_INT(formatnump);
-       formats = g_hash_table_lookup(default_formats, module);
-
-       /* <module><format_name><arg...> */
-       g_string_truncate(format, 0);
-
-       g_string_append_c(format, '\0');
-       g_string_append_c(format, (char)LINE_CMD_FORMAT);
-
-        g_string_append(format, module);
-
-       g_string_append_c(format, '\0');
-       g_string_append_c(format, (char)LINE_CMD_FORMAT);
-
-       g_string_append(format, formats[formatnum].tag);
-
-       for (n = 0; n < formats[formatnum].params; n++) {
-               g_string_append_c(format, '\0');
-               g_string_append_c(format, (char)LINE_CMD_FORMAT);
-
-               g_string_append(format, args[n]);
-       }
-}
-
 static void read_settings(void)
 {
        scrollback_lines = settings_get_int("scrollback_lines");
        scrollback_hours = settings_get_int("scrollback_hours");
         scrollback_burst_remove = settings_get_int("scrollback_burst_remove");
-        scrollback_save_formats = settings_get_bool("scrollback_save_formats");
 }
 
 void gui_printtext_init(void)
 {
        next_xpos = next_ypos = -1;
-       format = g_string_new(NULL);
+       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_int("history", "scrollback_hours", 24);
        settings_add_int("history", "scrollback_burst_remove", 10);
-       settings_add_bool("history", "scrollback_save_formats", FALSE);
 
        signal_add("gui print text", (SIGNAL_FUNC) sig_gui_print_text);
-       signal_add("print text finished", (SIGNAL_FUNC) sig_printtext_finished);
-       signal_add("print format", (SIGNAL_FUNC) sig_print_format);
+       signal_add("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished);
        signal_add("setup changed", (SIGNAL_FUNC) read_settings);
-       signal_add("beep", (SIGNAL_FUNC) beep);
 
        read_settings();
 }
 
 void gui_printtext_deinit(void)
 {
-       g_string_free(format, TRUE);
+       g_hash_table_destroy(indent_functions);
 
        signal_remove("gui print text", (SIGNAL_FUNC) sig_gui_print_text);
-       signal_remove("print text finished", (SIGNAL_FUNC) sig_printtext_finished);
-       signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
+       signal_remove("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished);
        signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
-       signal_remove("beep", (SIGNAL_FUNC) beep);
 }