summaryrefslogtreecommitdiff
path: root/src/fe-common/core/printtext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-common/core/printtext.c')
-rw-r--r--src/fe-common/core/printtext.c858
1 files changed, 858 insertions, 0 deletions
diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c
new file mode 100644
index 00000000..b03658b1
--- /dev/null
+++ b/src/fe-common/core/printtext.c
@@ -0,0 +1,858 @@
+/*
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "module.h"
+#include "module-formats.h"
+#include "modules.h"
+#include "signals.h"
+#include "commands.h"
+#include "special-vars.h"
+#include "settings.h"
+
+#include "levels.h"
+#include "server.h"
+
+#include "translation.h"
+#include "themes.h"
+#include "windows.h"
+
+static gboolean toggle_show_timestamps, toggle_show_msgs_timestamps, toggle_hide_text_style;
+static gint printtag;
+static gchar ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+
+static gint signal_gui_print_text;
+static gint signal_print_text_stripped;
+static gint signal_print_text;
+static gint signal_print_text_finished;
+
+void printbeep(void)
+{
+ signal_emit_id(signal_gui_print_text, 6, active_win, NULL, NULL,
+ GINT_TO_POINTER(PRINTFLAG_BEEP), "", MSGLEVEL_NEVER);
+}
+
+/* parse ANSI color string */
+static char *convert_ansi(char *str, int *fgcolor, int *bgcolor, int *flags)
+{
+ gchar *start;
+ gint fg, bg, fl, num;
+
+ if (*str != '[') return str;
+
+ start = str;
+
+ fg = *fgcolor < 0 ? current_theme->default_color : *fgcolor;
+ bg = *bgcolor < 0 ? -1 : *bgcolor;
+ fl = *flags;
+
+ str++; num = 0;
+ for (;; str++)
+ {
+ if (*str == '\0') return start;
+
+ if (isdigit((gint) *str))
+ {
+ num = num*10 + (*str-'0');
+ continue;
+ }
+
+ if (*str != ';' && *str != 'm') return start;
+
+ switch (num)
+ {
+ case 0:
+ /* reset colors back to default */
+ fg = current_theme->default_color;
+ bg = -1;
+ break;
+ case 1:
+ /* hilight */
+ fg |= 8;
+ break;
+ case 5:
+ /* blink */
+ bg = bg == -1 ? 8 : bg | 8;
+ break;
+ case 7:
+ /* reverse */
+ fl |= PRINTFLAG_REVERSE;
+ break;
+ default:
+ if (num >= 30 && num <= 37)
+ fg = (fg & 0xf8) + ansitab[num-30];
+ if (num >= 40 && num <= 47)
+ {
+ if (bg == -1) bg = 0;
+ bg = (bg & 0xf8) + ansitab[num-40];
+ }
+ break;
+ }
+ num = 0;
+
+ if (*str == 'm')
+ {
+ if (!toggle_hide_text_style)
+ {
+ *fgcolor = fg;
+ *bgcolor = bg == -1 ? -1 : bg;
+ *flags = fl;
+ }
+ str++;
+ break;
+ }
+ }
+
+ return str;
+}
+
+#define IN_COLOR_CODE 2
+#define IN_SECOND_CODE 4
+char *strip_codes(const char *input)
+{
+ const char *p;
+ gchar *str, *out;
+ gint loop_state;
+
+ loop_state = 0;
+ out = str = g_strdup(input);
+ for (p = input; *p != '\0'; p++) /* Going through the string till the end k? */
+ {
+ if (*p == '\003')
+ {
+ if (p[1] < 17 && p[1] > 0)
+ {
+ p++;
+ if (p[1] < 17 && p[1] > 0) p++;
+ continue;
+ }
+ loop_state = IN_COLOR_CODE;
+ continue;
+ }
+
+ if (loop_state & IN_COLOR_CODE)
+ {
+ if (isdigit( (gint) *p )) continue;
+ if (*p != ',' || (loop_state & IN_SECOND_CODE))
+ {
+ /* we're no longer in a color code */
+ *out++ = *p;
+ loop_state &= ~IN_COLOR_CODE|IN_SECOND_CODE;
+ continue;
+ }
+
+ /* we're in the second code */
+ loop_state |= IN_SECOND_CODE;
+ continue;
+
+ }
+
+ /* we're not in a color code that means we should add the character */
+ if (*p == 4 && p[1] != '\0' && p[2] != '\0')
+ {
+ p += 2;
+ continue;
+ }
+
+ if (*p == 2 || *p == 22 || *p == 27 || *p == 31 || *p == 15)
+ continue;
+ *out++ = *p;
+ }
+
+ *out = '\0';
+ return str;
+}
+
+static gboolean expand_styles(GString *out, char format, void *server, const char *channel, int level)
+{
+ static const char *backs = "01234567";
+ static const char *fores = "krgybmcw";
+ static const char *boldfores = "KRGYBMCW";
+ gchar *p;
+
+ /* p/P -> m/M */
+ if (format == 'p')
+ format = 'm';
+ else if (format == 'P')
+ format = 'M';
+
+ switch (format)
+ {
+ case 'U':
+ /* Underline on/off */
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -1);
+ g_string_append_c(out, 2);
+ break;
+ case '9':
+ case '_':
+ /* bold on/off */
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -1);
+ g_string_append_c(out, 1);
+ break;
+ case '8':
+ /* reverse */
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -1);
+ g_string_append_c(out, 3);
+ break;
+ case '%':
+ g_string_append_c(out, '%');
+ break;
+ case ':':
+ /* Newline */
+ printtext(server, channel, level, out->str);
+ g_string_truncate(out, 0);
+ break;
+
+ case '|':
+ /* Indent here mark */
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -1);
+ g_string_append_c(out, 4);
+ break;
+
+ case 'F':
+ /* flashing - ignore */
+ break;
+
+ case 'N':
+ /* don't put clear-color tag at the end of the output - ignore */
+ break;
+
+ case 'n':
+ /* default color */
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -1);
+ g_string_append_c(out, -1);
+ break;
+
+ default:
+ /* check if it's a background color */
+ p = strchr(backs, format);
+ if (p != NULL)
+ {
+ g_string_append_c(out, 4);
+ g_string_append_c(out, -2);
+ g_string_append_c(out, ansitab[(gint) (p-backs)]+1);
+ break;
+ }
+
+ /* check if it's a foreground color */
+ p = strchr(fores, format);
+ if (p != NULL)
+ {
+ g_string_append_c(out, 4);
+ g_string_append_c(out, ansitab[(gint) (p-fores)]+1);
+ g_string_append_c(out, -2);
+ break;
+ }
+
+ /* check if it's a bold foreground color */
+ p = strchr(boldfores, format);
+ if (p != NULL)
+ {
+ g_string_append_c(out, 4);
+ g_string_append_c(out, 8+ansitab[(gint) (p-boldfores)]+1);
+ g_string_append_c(out, -2);
+ break;
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void read_arglist(va_list va, FORMAT_REC *format,
+ char **arglist, int arglist_size,
+ char *buffer, int buffer_size)
+{
+ int num, len, bufpos;
+
+ bufpos = 0;
+ for (num = 0; num < format->params && num < arglist_size; num++) {
+ switch (format->paramtypes[num]) {
+ case FORMAT_STRING:
+ arglist[num] = (char *) va_arg(va, char *);
+ if (arglist[num] == NULL) {
+ g_warning("output_format_text_args() : parameter %d is NULL", num);
+ arglist[num] = "";
+ }
+ break;
+ case FORMAT_INT: {
+ int d = (int) va_arg(va, int);
+
+ if (bufpos >= buffer_size) {
+ arglist[num] = "";
+ break;
+ }
+
+ arglist[num] = buffer+bufpos;
+ len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
+ "%d", d);
+ bufpos += len+1;
+ break;
+ }
+ case FORMAT_LONG: {
+ long l = (long) va_arg(va, long);
+
+ if (bufpos >= buffer_size) {
+ arglist[num] = "";
+ break;
+ }
+
+ arglist[num] = buffer+bufpos;
+ len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
+ "%ld", l);
+ bufpos += len+1;
+ break;
+ }
+ case FORMAT_FLOAT: {
+ double f = (double) va_arg(va, double);
+
+ if (bufpos >= buffer_size) {
+ arglist[num] = "";
+ break;
+ }
+
+ arglist[num] = buffer+bufpos;
+ len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
+ "%0.2f", f);
+ bufpos += len+1;
+ break;
+ }
+ }
+ }
+}
+
+static void output_format_text_args(GString *out, void *server, const char *channel, int level, FORMAT_REC *format, const char *text, va_list args)
+{
+ char *arglist[10];
+ char buffer[200]; /* should be enough? (won't overflow even if it isn't) */
+
+ const char *str;
+ char code;
+ int need_free;
+
+ str = current_theme != NULL && text != NULL ? text : format->def;
+
+ /* read all optional arguments to arglist[] list
+ so they can be used in any order.. */
+ read_arglist(args, format,
+ arglist, sizeof(arglist)/sizeof(void*),
+ buffer, sizeof(buffer));
+
+ code = 0;
+ while (*str != '\0') {
+ if (code == '%') {
+ /* color code */
+ if (!expand_styles(out, *str, server, channel, level)) {
+ g_string_append_c(out, '%');
+ g_string_append_c(out, '%');
+ g_string_append_c(out, *str);
+ }
+ code = 0;
+ } else if (code == '$') {
+ /* argument */
+ char *ret;
+
+ ret = parse_special((char **) &str, active_win->active_server, active_win->active, arglist, &need_free, NULL);
+ if (ret != NULL) {
+ g_string_append(out, ret);
+ if (need_free) g_free(ret);
+ }
+ code = 0;
+ } else {
+ if (*str == '%' || *str == '$')
+ code = *str;
+ else
+ g_string_append_c(out, *str);
+ }
+
+ str++;
+ }
+}
+
+static void output_format_text(GString *out, void *server, const char *channel, int level, int formatnum, ...)
+{
+ MODULE_THEME_REC *theme;
+ va_list args;
+
+ theme = g_hash_table_lookup(current_theme->modules, MODULE_FORMATS->tag);
+
+ va_start(args, formatnum);
+ output_format_text_args(out, server, channel, level,
+ &MODULE_FORMATS[formatnum],
+ theme == NULL ? NULL : theme->format[formatnum], args);
+ va_end(args);
+}
+
+static void add_timestamp(WINDOW_REC *window, GString *out, void *server, const char *channel, int level)
+{
+ time_t t;
+ struct tm *tm;
+ GString *tmp;
+
+ if (!(level != MSGLEVEL_NEVER && (toggle_show_timestamps || (toggle_show_msgs_timestamps && (level & MSGLEVEL_MSGS) != 0))))
+ return;
+
+ t = time(NULL);
+
+ if ((t - window->last_timestamp) < settings_get_int("timestamp_timeout")) {
+ window->last_timestamp = t;
+ return;
+ }
+ window->last_timestamp = t;
+
+ tmp = g_string_new(NULL);
+ tm = localtime(&t);
+ output_format_text(tmp, server, channel, level, IRCTXT_TIMESTAMP,
+ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ /* insert the timestamp right after \n */
+ g_string_prepend(out, tmp->str);
+ g_string_free(tmp, TRUE);
+}
+
+static void new_line_stuff(GString *out, void *server, const char *channel, int level)
+{
+ if ((level & (MSGLEVEL_CLIENTERROR|MSGLEVEL_CLIENTNOTICE)) != 0)
+ output_format_text(out, server, channel, level, IRCTXT_LINE_START_IRSSI);
+ else if ((level & (MSGLEVEL_MSGS|MSGLEVEL_PUBLIC|MSGLEVEL_NOTICES|MSGLEVEL_SNOTES|MSGLEVEL_CTCPS|MSGLEVEL_ACTIONS|MSGLEVEL_DCC|MSGLEVEL_CLIENTCRAP)) == 0 && level != MSGLEVEL_NEVER)
+ output_format_text(out, server, channel, level, IRCTXT_LINE_START);
+}
+
+/* Write text to channel - convert color codes */
+void printtext(void *server, const char *channel, int level, const char *str, ...)
+{
+ va_list args;
+ GString *out;
+ gchar *tmpstr;
+ gint pros;
+
+ g_return_if_fail(str != NULL);
+
+ va_start(args, str);
+
+ pros = 0;
+ out = g_string_new(NULL);
+
+ new_line_stuff(out, server, channel, level);
+ for (; *str != '\0'; str++)
+ {
+ if (*str != '%')
+ {
+ g_string_append_c(out, *str);
+ continue;
+ }
+
+ if (*++str == '\0') break;
+ switch (*str)
+ {
+ /* standard parameters */
+ case 's':
+ {
+ gchar *s = (gchar *) va_arg(args, gchar *);
+ if (s && *s) g_string_append(out, s);
+ break;
+ }
+ case 'd':
+ {
+ gint d = (gint) va_arg(args, gint);
+ g_string_sprintfa(out, "%d", d);
+ break;
+ }
+ case 'f':
+ {
+ gdouble f = (gdouble) va_arg(args, gdouble);
+ g_string_sprintfa(out, "%0.2f", f);
+ break;
+ }
+ case 'u':
+ {
+ guint d = (guint) va_arg(args, guint);
+ g_string_sprintfa(out, "%u", d);
+ break;
+ }
+ case 'l':
+ {
+ gulong d = (gulong) va_arg(args, gulong);
+ if (*++str != 'd' && *str != 'u')
+ {
+ g_string_sprintfa(out, "%ld", d);
+ str--;
+ }
+ else
+ {
+ if (*str == 'd')
+ g_string_sprintfa(out, "%ld", d);
+ else
+ g_string_sprintfa(out, "%lu", d);
+ }
+ break;
+ }
+ default:
+ if (!expand_styles(out, *str, server, channel, level))
+ {
+ g_string_append_c(out, '%');
+ g_string_append_c(out, *str);
+ }
+ break;
+ }
+ }
+ va_end(args);
+
+ /* send the plain text version for logging.. */
+ tmpstr = strip_codes(out->str);
+ signal_emit_id(signal_print_text_stripped, 4, server, channel, GINT_TO_POINTER(level), tmpstr);
+ g_free(tmpstr);
+
+ signal_emit_id(signal_print_text, 4, server, channel, GINT_TO_POINTER(level), out->str);
+
+ g_string_free(out, TRUE);
+}
+
+void printformat_format(FORMAT_REC *formats, void *server, const char *channel, int level, int formatnum, ...)
+{
+ MODULE_THEME_REC *theme;
+ GString *out;
+ va_list args;
+
+ va_start(args, formatnum);
+ out = g_string_new(NULL);
+
+ theme = g_hash_table_lookup(current_theme->modules, formats->tag);
+
+ output_format_text_args(out, server, channel, level,
+ &formats[formatnum],
+ theme == NULL ? NULL : theme->format[formatnum], args);
+ if (out->len > 0) printtext(server, channel, level, "%s", out->str);
+
+ g_string_free(out, TRUE);
+ va_end(args);
+}
+
+static void newline(WINDOW_REC *window)
+{
+ window->lines++;
+ if (window->lines != 1) {
+ signal_emit_id(signal_gui_print_text, 6, window,
+ GINT_TO_POINTER(-1), GINT_TO_POINTER(-1),
+ GINT_TO_POINTER(0), "\n", GINT_TO_POINTER(-1));
+ }
+}
+
+static void sig_print_text(void *server, const char *target, gpointer level, const char *text)
+{
+ WINDOW_REC *window;
+ GString *out;
+ gchar *dup, *ptr, type, *str;
+ gint fgcolor, bgcolor;
+ gint flags;
+
+ g_return_if_fail(text != NULL);
+
+ window = window_find_closest(server, target, GPOINTER_TO_INT(level));
+ g_return_if_fail(window != NULL);
+
+ flags = 0; fgcolor = -1; bgcolor = -1; type = '\0';
+
+ newline(window);
+
+ out = g_string_new(text);
+ if (server != NULL && servers != NULL && servers->next != NULL &&
+ (window->active == NULL || window->active->server != server))
+ {
+ /* connected to more than one server and active server isn't the
+ same where the message came or we're in status/msgs/empty window -
+ prefix with a [server tag] */
+ gchar *str;
+
+ str = g_strdup_printf("[%s] ", ((SERVER_REC *) server)->tag);
+ g_string_prepend(out, str);
+ g_free(str);
+ }
+
+ add_timestamp(window, out, server, target, GPOINTER_TO_INT(level));
+
+ dup = str = out->str;
+ g_string_free(out, FALSE);
+
+ while (*str != '\0')
+ {
+ for (ptr = str; *ptr != '\0'; ptr++)
+ {
+ if (*ptr == 2 || *ptr == 3 || *ptr == 4 || *ptr == 6 || *ptr == 7 || *ptr == 15 || *ptr == 22 || *ptr == 27 || *ptr == 31)
+ {
+ type = *ptr;
+ *ptr++ = '\0';
+ break;
+ }
+
+ *ptr = (gchar) translation_in[(gint) (guchar) *ptr];
+ }
+
+ if (type == 7)
+ {
+ /* bell */
+ if (settings_get_bool("toggle_bell_beeps"))
+ flags |= PRINTFLAG_BEEP;
+ }
+ if (*str != '\0' || flags & PRINTFLAG_BEEP)
+ {
+ signal_emit_id(signal_gui_print_text, 6, window,
+ GINT_TO_POINTER(fgcolor), GINT_TO_POINTER(bgcolor),
+ GINT_TO_POINTER(flags), str, level);
+ flags &= ~(PRINTFLAG_BEEP|PRINTFLAG_INDENT);
+ }
+ if (*ptr == '\0') break;
+
+ switch (type)
+ {
+ case 2:
+ /* bold */
+ if (!toggle_hide_text_style)
+ flags ^= PRINTFLAG_BOLD;
+ break;
+ case 6:
+ /* blink */
+ if (!toggle_hide_text_style)
+ flags ^= PRINTFLAG_BLINK;
+ break;
+ case 15:
+ /* remove all styling */
+ flags &= PRINTFLAG_BEEP;
+ fgcolor = bgcolor = -1;
+ break;
+ case 22:
+ /* reverse */
+ if (!toggle_hide_text_style)
+ flags ^= PRINTFLAG_REVERSE;
+ break;
+ case 31:
+ /* underline */
+ if (!toggle_hide_text_style)
+ flags ^= PRINTFLAG_UNDERLINE;
+ case 27:
+ /* ansi color code */
+ ptr = convert_ansi(ptr, &fgcolor, &bgcolor, &flags);
+ break;
+ case 4:
+ /* user specific colors */
+ flags &= ~PRINTFLAG_MIRC_COLOR;
+ if ((signed char) *ptr == -1)
+ {
+ ptr++;
+ if ((signed char) *ptr == -1)
+ {
+ fgcolor = bgcolor = -1;
+ flags &= PRINTFLAG_INDENT;
+ }
+ else if (*ptr == 1)
+ flags ^= PRINTFLAG_BOLD;
+ else if (*ptr == 2)
+ flags ^= PRINTFLAG_UNDERLINE;
+ else if (*ptr == 3)
+ flags ^= PRINTFLAG_REVERSE;
+ else if (*ptr == 4)
+ flags |= PRINTFLAG_INDENT;
+ }
+ else
+ {
+ if ((signed char) *ptr != -2)
+ {
+ fgcolor = (guchar) *ptr-1;
+ if (fgcolor <= 7)
+ flags &= ~PRINTFLAG_BOLD;
+ else
+ {
+ /* bold */
+ if (fgcolor != 8) fgcolor -= 8;
+ flags |= PRINTFLAG_BOLD;
+ }
+ }
+ ptr++;
+ if ((signed char) *ptr != -2)
+ bgcolor = (signed char) *ptr == -1 ? -1 : *ptr-1;
+ }
+ ptr++;
+ break;
+ case 3:
+ if (*ptr < 17)
+ {
+ /* mostly just for irssi's internal use.. */
+ fgcolor = (*ptr++)-1;
+ if (*ptr == 0 || *ptr >= 17)
+ bgcolor = -1;
+ else
+ bgcolor = (*ptr++)-1;
+ if (fgcolor & 8)
+ flags |= PRINTFLAG_BOLD;
+ else
+ flags &= ~PRINTFLAG_BOLD;
+ break;
+ }
+
+ /* MIRC color */
+ if (toggle_hide_text_style)
+ {
+ /* don't show them. */
+ if (isdigit((gint) *ptr))
+ {
+ ptr++;
+ if (isdigit((gint) *ptr)) ptr++;
+ if (*ptr == ',')
+ {
+ ptr++;
+ if (isdigit((gint) *ptr))
+ {
+ ptr++;
+ if (isdigit((gint) *ptr)) ptr++;
+ }
+ }
+ }
+ break;
+ }
+
+ flags |= PRINTFLAG_MIRC_COLOR;
+ if (!isdigit((gint) *ptr) && *ptr != ',')
+ {
+ fgcolor = -1;
+ bgcolor = -1;
+ }
+ else
+ {
+ /* foreground color */
+ if (*ptr != ',')
+ {
+ fgcolor = *ptr++-'0';
+ if (isdigit((gint) *ptr))
+ fgcolor = fgcolor*10 + (*ptr++-'0');
+ }
+ if (*ptr == ',')
+ {
+ /* back color */
+ bgcolor = 0;
+ if (!isdigit((gint) *++ptr))
+ bgcolor = -1;
+ else
+ {
+ bgcolor = *ptr++-'0';
+ if (isdigit((gint) *ptr))
+ bgcolor = bgcolor*10 + (*ptr++-'0');
+ }
+ }
+ }
+ break;
+ }
+
+ str = ptr;
+ }
+ g_free(dup);
+ signal_emit_id(signal_print_text_finished, 1, window);
+}
+
+static int sig_check_daychange(void)
+{
+ static gint lastday = -1;
+ GSList *tmp;
+ time_t t;
+ struct tm *tm;
+
+ if (!toggle_show_timestamps)
+ {
+ /* display day change notice only when using timestamps */
+ return TRUE;
+ }
+
+ t = time(NULL);
+ tm = localtime(&t);
+
+ if (lastday == -1)
+ {
+ /* First check, don't display. */
+ lastday = tm->tm_mday;
+ return TRUE;
+ }
+
+ if (tm->tm_mday == lastday)
+ return TRUE;
+
+ /* day changed, print notice about it to every window */
+ for (tmp = windows; tmp != NULL; tmp = tmp->next)
+ {
+ WINDOW_REC *win = tmp->data;
+
+ printformat(win->active->server, win->active->name, MSGLEVEL_NEVER,
+ IRCTXT_DAYCHANGE, tm->tm_mday, tm->tm_mon+1, 1900+tm->tm_year);
+ }
+ lastday = tm->tm_mday;
+ return TRUE;
+}
+
+static void sig_gui_dialog(const char *type, const char *text)
+{
+ char **lines, **tmp;
+
+ if (g_strcasecmp(type, "warning") == 0)
+ type = _("%_Warning:%_ %s");
+ else if (g_strcasecmp(type, "error") == 0)
+ type = _("%_Error:%_ %s");
+ else
+ type = "%s";
+
+ lines = g_strsplit(text, "\n", -1);
+ for (tmp = lines; *tmp != NULL; tmp++)
+ printtext(NULL, NULL, MSGLEVEL_NEVER, type, *tmp);
+ g_strfreev(lines);
+}
+
+static void read_settings(void)
+{
+ toggle_show_timestamps = settings_get_bool("toggle_show_timestamps");
+ toggle_show_msgs_timestamps = settings_get_bool("toggle_show_msgs_timestamps");
+ toggle_hide_text_style = settings_get_bool("toggle_hide_text_style");
+}
+
+void printtext_init(void)
+{
+ settings_add_int("misc", "timestamp_timeout", 0);
+
+ signal_gui_print_text = module_get_uniq_id_str("signals", "gui print text");
+ signal_print_text_stripped = module_get_uniq_id_str("signals", "print text stripped");
+ signal_print_text = module_get_uniq_id_str("signals", "print text");
+ signal_print_text_finished = module_get_uniq_id_str("signals", "print text finished");
+
+ read_settings();
+ printtag = g_timeout_add(30000, (GSourceFunc) sig_check_daychange, NULL);
+ signal_add("print text", (SIGNAL_FUNC) sig_print_text);
+ signal_add("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
+ signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+ command_bind("beep", NULL, (SIGNAL_FUNC) printbeep);
+}
+
+void printtext_deinit(void)
+{
+ g_source_remove(printtag);
+ signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
+ signal_remove("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
+ signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
+ command_unbind("beep", (SIGNAL_FUNC) printbeep);
+}