From cbdaf7d06d021a1072363f1a80ff73c7423c7bd8 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 15 May 2000 08:25:45 +0000 Subject: [PATCH] Lots of changes again. Biggest ones: - window's text buffer should work better - themes are almost working, you can change the text formats with /format - automatically try to rejoin the channel after 5 minutes if the join there failed because it was "temporarily unavailable" (netsplits) - generally cleaning code.. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@216 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- TODO | 22 +- configure.in | 2 +- curses.m4 | 10 +- src/core/commands.c | 20 + src/core/commands.h | 7 +- src/core/core.c | 4 +- src/core/memdebug.c | 19 +- src/core/settings.c | 23 +- src/core/settings.h | 4 + src/fe-common/core/Makefile.am | 3 +- src/fe-common/core/fe-common-core.c | 18 +- src/fe-common/core/fe-core-commands.c | 17 +- src/fe-common/core/fe-log.c | 20 +- src/fe-common/core/hilight-text.c | 6 +- src/fe-common/core/keyboard.c | 10 +- src/fe-common/core/module-formats.c | 116 +-- src/fe-common/core/module-formats.h | 3 - src/fe-common/core/printformat.h | 25 - src/fe-common/core/printtext.c | 918 +++++++++--------- src/fe-common/core/printtext.h | 58 +- src/fe-common/core/themes.c | 396 ++++++-- src/fe-common/core/themes.h | 18 +- src/fe-common/core/window-activity.c | 4 +- src/fe-common/core/window-commands.c | 370 +++++++ src/fe-common/core/window-items.c | 77 +- src/fe-common/core/window-items.h | 5 +- src/fe-common/core/windows.c | 504 ++-------- src/fe-common/core/windows.h | 4 + src/fe-common/irc/dcc/Makefile.am | 1 + src/fe-common/irc/dcc/fe-dcc.c | 5 + src/fe-common/irc/dcc/module-formats.c | 67 +- src/fe-common/irc/dcc/module-formats.h | 3 - src/fe-common/irc/dcc/module.h | 3 + src/fe-common/irc/fe-common-irc.c | 6 + src/fe-common/irc/flood/Makefile.am | 3 +- src/fe-common/irc/flood/fe-flood.c | 6 + src/fe-common/irc/flood/module-formats.c | 12 +- src/fe-common/irc/flood/module-formats.h | 3 - src/fe-common/irc/flood/module.h | 3 + src/fe-common/irc/module-formats.c | 304 +++--- src/fe-common/irc/module-formats.h | 3 - src/fe-common/irc/notifylist/Makefile.am | 3 +- src/fe-common/irc/notifylist/fe-notifylist.c | 6 + src/fe-common/irc/notifylist/module-formats.c | 24 +- src/fe-common/irc/notifylist/module-formats.h | 3 - src/fe-common/irc/notifylist/module.h | 3 + src/fe-text/gui-printtext.c | 425 ++++---- src/fe-text/gui-windows.c | 616 ++++++------ src/fe-text/gui-windows.h | 16 +- src/fe-text/irssi.c | 10 +- src/fe-text/mainwindows.c | 16 + src/fe-text/module-formats.c | 12 +- src/fe-text/module-formats.h | 3 - src/irc/core/Makefile.am | 1 + src/irc/core/channel-events.c | 2 +- src/irc/core/channel-rejoin.c | 104 ++ src/irc/core/channels.c | 21 +- src/irc/core/irc-log.c | 16 - src/irc/core/irc-server.h | 3 + src/irc/core/server-setup.c | 2 +- src/irc/dcc/dcc-chat.c | 4 +- src/irc/dcc/dcc-files.c | 4 +- src/perl/irssi-perl.c | 3 + 63 files changed, 2479 insertions(+), 1920 deletions(-) delete mode 100644 src/fe-common/core/printformat.h create mode 100644 src/fe-common/core/window-commands.c create mode 100644 src/fe-common/irc/dcc/module.h create mode 100644 src/fe-common/irc/flood/module.h create mode 100644 src/fe-common/irc/notifylist/module.h create mode 100644 src/irc/core/channel-rejoin.c diff --git a/TODO b/TODO index f3e34d3f..40bacf2b 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,16 @@ +- teemat + - /rehash + - teeman vaihto + - teemoihin tee jotain pientä selitystä edes! + - irssi can't find new themes in ~/.irssi/ while running - scan for new + themes when opening themes dialog? irssi-text also needs to be restarted + to use new themes.. + - use different themes in different channels/queries? + - logi voisi käyttää omaa teemaa + - /IRCNET ADD/REMOVE - mites se awaylogi? se /cattaamaan myös se /away:n jälkeen - poista se common-setup.h -- quitissa se räpeltää ruutua liikaa.. -- perli kaatui välillä ym. kivaa. [21:48] < santo> [20:51] ¤¤¤ #twiggy,#tanum,#d2mac,#linux.nu,#sweden2k Cannot join channel (illegal name) @@ -19,15 +27,6 @@ lis - gnome versio.. - pluginit -- teemat (toimiiko ne edes?) - - teeman vaihto tekstiversiolla, tekstien muuttaminen tekstiversiolla - - teemoihin tee jotain pientä selitystä edes! - - irssi can't find new themes in ~/.irssi/ while running - scan for new - themes when opening themes dialog? irssi-text also needs to be restarted - to use new themes.. - - use different themes in different channels/queries? - - logi voisi käyttää omaa teemaa - - /set hold_mode, ja /CAT toimimaan sen kanssa jotenkin nerokkaasti.. - curses sijainti jotain rikkoo, ja openbsd:ssä on -lcurses, ei -lncurses @@ -40,7 +39,6 @@ lis - line-split.c: varmista että se 64k limitti toimii eikä esim. kaada! - /exec - autorun.ircnet - - channel not available rejoini *** Bugs diff --git a/configure.in b/configure.in index 82f6d411..b1137282 100644 --- a/configure.in +++ b/configure.in @@ -201,7 +201,7 @@ dnl ** if test "x$want_textui" = "xyes"; then AC_CHECK_CURSES - if test "x$ncurses_version" != "x"; then + if test "x$has_ncurses" != "x"; then AC_CHECK_LIB(ncurses, use_default_colors, [ AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS) ],, $CURSES_LIBS) diff --git a/curses.m4 b/curses.m4 index 07b2b585..595c47b7 100644 --- a/curses.m4 +++ b/curses.m4 @@ -131,13 +131,7 @@ AC_DEFUN(AC_CHECK_CURSES,[ if test x$withval = xno ; then search_ncurses=false elif test x$withval != xyes ; then - CURSES_LIBS="$LIBS -L$withval/lib -lncurses" - CURSES_INCLUDEDIR="-I$withval/include" - search_ncurses=false - screen_manager="ncurses" - AC_DEFINE(USE_NCURSES) - AC_DEFINE(HAS_CURSES) - has_curses=true + AC_NCURSES($withval/include, ncurses.h, -L$withval/lib -lncurses, -I$withval/include, "ncurses on $withval/include") fi ) @@ -222,6 +216,7 @@ AC_DEFUN(AC_NCURSES, [ screen_manager=$5 AC_DEFINE(HAS_CURSES) has_curses=true + has_ncurses=true AC_DEFINE(USE_NCURSES) fi fi @@ -256,6 +251,7 @@ USE_NCURSES CURSES_INCLUDEDIR="$CURSES_INCLUDEDIR -DRENAMED_NCURSES" AC_DEFINE(HAS_CURSES) has_curses=true + has_ncurses=true AC_DEFINE(USE_NCURSES) search_ncurses=false screen_manager="ncurses installed as curses" diff --git a/src/core/commands.c b/src/core/commands.c index 8f02db89..1dfd8b71 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -436,8 +436,24 @@ static void cmd_cd(const char *data) g_free(str); } +static void cmd_rehash(const char *data) +{ + char *fname; + + fname = *data != '\0' ? g_strdup(data) : + g_strdup_printf("%s/.irssi/config", g_get_home_dir()); + settings_reread(fname); + g_free(fname); +} + +static void cmd_save(const char *data) +{ + settings_save(*data != '\0' ? data : NULL); +} + void commands_init(void) { + commands = NULL; cmdget_funcs = NULL; current_command = NULL; @@ -448,6 +464,8 @@ void commands_init(void) command_bind("eval", NULL, (SIGNAL_FUNC) cmd_eval); command_bind("cd", NULL, (SIGNAL_FUNC) cmd_cd); + command_bind("rehash", NULL, (SIGNAL_FUNC) cmd_rehash); + command_bind("save", NULL, (SIGNAL_FUNC) cmd_save); } void commands_deinit(void) @@ -459,4 +477,6 @@ void commands_deinit(void) command_unbind("eval", (SIGNAL_FUNC) cmd_eval); command_unbind("cd", (SIGNAL_FUNC) cmd_cd); + command_unbind("rehash", (SIGNAL_FUNC) cmd_rehash); + command_unbind("save", (SIGNAL_FUNC) cmd_save); } diff --git a/src/core/commands.h b/src/core/commands.h index b4577e70..554a60e5 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -10,16 +10,11 @@ typedef struct { COMMAND_REC; enum { - CMDERR_PARAM, /* invalid parameter */ + CMDERR_ERRNO, /* get the error from errno */ CMDERR_NOT_ENOUGH_PARAMS, /* not enough parameters given */ CMDERR_NOT_CONNECTED, /* not connected to IRC server */ CMDERR_NOT_JOINED, /* not joined to any channels in this window */ - CMDERR_GETSOCKNAME, /* getsockname() failed */ - CMDERR_LISTEN, /* listen() failed */ - CMDERR_MULTIPLE_MATCHES, /* multiple matches found, didn't do anything */ - CMDERR_NICK_NOT_FOUND, /* nick not found */ CMDERR_CHAN_NOT_FOUND, /* channel not found */ - CMDERR_SERVER_NOT_FOUND, /* server not found */ CMDERR_CHAN_NOT_SYNCED, /* channel not fully synchronized yet */ CMDERR_NOT_GOOD_IDEA /* not good idea to do, -yes overrides this */ }; diff --git a/src/core/core.c b/src/core/core.c index c850a572..2102ebcd 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -43,9 +43,9 @@ void core_init(void) net_disconnect_init(); signals_init(); settings_init(); + commands_init(); servers_init(); - commands_init(); log_init(); rawlog_init(); special_vars_init(); @@ -56,9 +56,9 @@ void core_deinit(void) special_vars_deinit(); rawlog_deinit(); log_deinit(); - commands_deinit(); servers_deinit(); + commands_deinit(); settings_deinit(); signals_deinit(); net_disconnect_deinit(); diff --git a/src/core/memdebug.c b/src/core/memdebug.c index 1be7bbd8..fcd92659 100644 --- a/src/core/memdebug.c +++ b/src/core/memdebug.c @@ -132,35 +132,26 @@ static void *data_remove(void *p, const char *file, int line) void *ig_malloc(int size, const char *file, int line) { -#if 1 void *p; size += BUFFER_CHECK_SIZE*2; p = g_malloc(size); data_add(p, size, file, line); return p+BUFFER_CHECK_SIZE; -#else - return g_malloc(size); -#endif } void *ig_malloc0(int size, const char *file, int line) { -#if 1 void *p; size += BUFFER_CHECK_SIZE*2; p = g_malloc0(size); data_add(p, size, file, line); return p+BUFFER_CHECK_SIZE; -#else - return g_malloc0(size); -#endif } void *ig_realloc(void *mem, unsigned long size, const char *file, int line) { -#if 1 void *p; size += BUFFER_CHECK_SIZE*2; @@ -169,9 +160,6 @@ void *ig_realloc(void *mem, unsigned long size, const char *file, int line) p = g_realloc(mem, size); data_add(p, size, file, line); return p+BUFFER_CHECK_SIZE; -#else - return g_realloc(mem, size); -#endif } char *ig_strdup(const char *str, const char *file, int line) @@ -264,12 +252,11 @@ char *ig_strdup_vprintf(const char *file, int line, const char *format, va_list void ig_free(void *p) { -#if 1 + if (p == NULL) g_error("ig_free() : trying to free NULL"); + p -= BUFFER_CHECK_SIZE; p = data_remove(p, "??", 0); - if (p != NULL) -#endif - g_free(p); + if (p != NULL) g_free(p); } GString *ig_string_new(const char *file, int line, const char *str) diff --git a/src/core/settings.c b/src/core/settings.c index a7e27a63..5133dd6b 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -21,6 +21,7 @@ #include "module.h" #include "signals.h" #include "commands.h" +#include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" @@ -278,15 +279,16 @@ static void init_configfile(void) signal(SIGTERM, sig_term); } -static void cmd_rehash(const char *data) +void settings_reread(const char *fname) { CONFIG_REC *tempconfig; - char *str, *fname; + char *str; - fname = *data != '\0' ? g_strdup(data) : - g_strdup_printf("%s/.irssi/config", g_get_home_dir()); - tempconfig = parse_configfile(fname); - g_free(fname); + if (fname == NULL) fname = "~/.irssi/config"; + + str = convert_home(fname); + tempconfig = parse_configfile(str); + g_free(str); if (tempconfig == NULL) { signal_emit("gui dialog", 2, "error", g_strerror(errno)); @@ -310,11 +312,11 @@ static void cmd_rehash(const char *data) signal_emit("setup reread", 0); } -static void cmd_save(const char *data) +void settings_save(const char *fname) { char *str; - if (config_write(mainconfig, *data == '\0' ? NULL : data, 0660) == 0) + if (config_write(mainconfig, fname, 0660) == 0) return; /* error */ @@ -329,8 +331,6 @@ void settings_init(void) settings = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); init_configfile(); - command_bind("rehash", NULL, (SIGNAL_FUNC) cmd_rehash); - command_bind("save", NULL, (SIGNAL_FUNC) cmd_save); } static void settings_hash_free(const char *key, SETTINGS_REC *rec) @@ -340,9 +340,6 @@ static void settings_hash_free(const char *key, SETTINGS_REC *rec) void settings_deinit(void) { - command_unbind("rehash", (SIGNAL_FUNC) cmd_rehash); - command_unbind("save", (SIGNAL_FUNC) cmd_save); - g_free_not_null(last_error_msg); g_hash_table_foreach(settings, (GHFunc) settings_hash_free, NULL); g_hash_table_destroy(settings); diff --git a/src/core/settings.h b/src/core/settings.h index 6f29de6e..583e0dd6 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -53,6 +53,10 @@ GSList *settings_get_sorted(void); /* Get the record of the setting */ SETTINGS_REC *settings_get_record(const char *key); +/* if `fname' is NULL, the default is used */ +void settings_reread(const char *fname); +void settings_save(const char *fname); + void settings_init(void); void settings_deinit(void); diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index c8931435..c8e24dad 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -17,10 +17,11 @@ libfe_common_core_la_SOURCES = \ hilight-text.c \ keyboard.c \ module-formats.c \ - window-activity.c \ printtext.c \ themes.c \ translation.c \ + window-activity.c \ + window-commands.c \ window-items.c \ windows.c diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index a348583d..02c67010 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "module.h" +#include "module-formats.h" #include "levels.h" #include "settings.h" @@ -50,6 +51,9 @@ void fe_settings_deinit(void); void window_activity_init(void); void window_activity_deinit(void); +void window_commands_init(void); +void window_commands_deinit(void); + void fe_core_commands_init(void); void fe_core_commands_deinit(void); @@ -73,8 +77,10 @@ void fe_common_core_init(void) settings_add_int("lookandfeel", "tab_orientation", 3);*/ settings_add_str("lookandfeel", "current_theme", "default"); + themes_init(); + theme_register(fecommon_core_formats); + autorun_init(); - window_activity_init(); hilight_text_init(); command_history_init(); keyboard_init(); @@ -82,9 +88,10 @@ void fe_common_core_init(void) fe_log_init(); fe_server_init(); fe_settings_init(); - themes_init(); translation_init(); windows_init(); + window_activity_init(); + window_commands_init(); window_items_init(); fe_core_commands_init(); } @@ -92,7 +99,6 @@ void fe_common_core_init(void) void fe_common_core_deinit(void) { autorun_deinit(); - window_activity_deinit(); hilight_text_deinit(); command_history_deinit(); keyboard_deinit(); @@ -100,11 +106,15 @@ void fe_common_core_deinit(void) fe_log_deinit(); fe_server_deinit(); fe_settings_deinit(); - themes_deinit(); translation_deinit(); windows_deinit(); + window_activity_deinit(); + window_commands_deinit(); window_items_deinit(); fe_core_commands_deinit(); + + theme_unregister(); + themes_deinit(); } void fe_common_core_finish_init(void) diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index 41320eed..c4af0f7c 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -30,16 +30,11 @@ #include "windows.h" static const char *ret_texts[] = { - "Invalid parameter", + NULL, "Not enough parameters given", "Not connected to IRC server yet", "Not joined to any channels yet", - "Error: getsockname() failed", - "Error: listen() failed", - "Multiple matches found, be more specific", - "Nick not found", "Not joined to such channel", - "Server not found", "Channel not fully synchronized yet, try again after a while", "Doing this is not a good idea. Add -YES if you really mean it", }; @@ -269,9 +264,15 @@ static void cmd_unknown(const char *data, void *server, WI_ITEM_REC *item) signal_stop(); } -static void event_cmderror(gpointer error) +static void event_cmderror(gpointer errorp) { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[GPOINTER_TO_INT(error)]); + int error; + + error = GPOINTER_TO_INT(errorp); + if (error == CMDERR_ERRNO) + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno)); + else + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error]); } void fe_core_commands_init(void) diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index f3fc6f56..58cd28fe 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -297,25 +297,27 @@ static void autolog_log(void *server, const char *target) g_free(fname); } -/* write to logs created with /WINDOW LOG */ -static void sig_printtext_stripped(void *server, const char *target, gpointer levelp, const char *text) +static void sig_printtext_stripped(WINDOW_REC *window, void *server, const char *target, gpointer levelp, const char *text) { char windownum[MAX_INT_STRLEN]; - WINDOW_REC *window; LOG_REC *log; int level; level = GPOINTER_TO_INT(levelp); + if (level == MSGLEVEL_NEVER) return; + + /* let autolog create the log records */ if ((autolog_level & level) && target != NULL && *target != '\0') autolog_log(server, target); - window = window_find_closest(server, target, level); - if (window != NULL) { - ltoa(windownum, window->refnum); + /* save to log created with /WINDOW LOG */ + ltoa(windownum, window->refnum); + log = log_find_item(windownum); + if (log != NULL) log_write_rec(log, text); - log = log_find_item(windownum); - if (log != NULL) log_write_rec(log, text); - } + /* save line to logs */ + if (logs != NULL) + log_write(target, level, text); } static int sig_autoremove(void) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 307f9f02..6b5735b0 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -132,7 +132,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels) return NULL; } -static void sig_print_text(SERVER_REC *server, const char *channel, gpointer level, const char *str) +static void sig_print_text(WINDOW_REC *window, SERVER_REC *server, const char *channel, gpointer level, const char *str) { if (hilight_next) { hilight_next = FALSE; @@ -140,7 +140,7 @@ static void sig_print_text(SERVER_REC *server, const char *channel, gpointer lev } } -static void sig_print_text_stripped(SERVER_REC *server, const char *channel, gpointer plevel, const char *str) +static void sig_print_text_stripped(WINDOW_REC *window, SERVER_REC *server, const char *channel, gpointer plevel, const char *str) { GSList *tmp; char *color, *newstr; @@ -184,7 +184,7 @@ static void sig_print_text_stripped(SERVER_REC *server, const char *channel, gpo if (color == NULL) color = "\00316"; newstr = g_strconcat(isdigit(*color) ? "\003" : "", color, str, NULL); - signal_emit("print text", 4, server, channel, GINT_TO_POINTER(level | MSGLEVEL_HILIGHT), newstr); + signal_emit("print text", 5, window, server, channel, GINT_TO_POINTER(level | MSGLEVEL_HILIGHT), newstr); g_free(newstr); hilight_next = TRUE; diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c index 854d4d7e..0406c758 100644 --- a/src/fe-common/core/keyboard.c +++ b/src/fe-common/core/keyboard.c @@ -258,12 +258,6 @@ static void read_keyboard_config(void) CONFIG_NODE *node; GSList *tmp; - while (keyinfos != NULL) - keyinfo_remove(keyinfos->data); - if (keys != NULL) g_hash_table_destroy(keys); - - keys = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); - node = iconfig_node_traverse("keyboard", FALSE); if (node == NULL) return; @@ -280,7 +274,9 @@ static void read_keyboard_config(void) void keyboard_init(void) { - keyinfos = NULL; keys = NULL; + keys = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); + keyinfos = NULL; + key_bind("command", NULL, "Run any IRC command", NULL, (SIGNAL_FUNC) sig_command); read_keyboard_config(); diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 5a12f6fc..a224a809 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -21,73 +21,75 @@ #include "module.h" #include "printtext.h" -FORMAT_REC fecommon_core_formats[] = -{ - { MODULE_NAME, "Core", 0 }, +FORMAT_REC fecommon_core_formats[] = { + { MODULE_NAME, "Core", 0 }, - /* ---- */ - { NULL, "Windows", 0 }, + /* ---- */ + { NULL, "Windows", 0 }, - { "line_start", "%B-%W!%B-%n ", 0 }, - { "line_start_irssi", "%B-%W!%B- %WIrssi:%n ", 0 }, - { "timestamp", "[$[-2.0]3:$[-2.0]4] ", 6, { 1, 1, 1, 1, 1, 1 } }, - { "daychange", "Day changed to ${[-2.0]1}-$[-2.0]0 $2", 3, { 1, 1, 1 } }, - { "talking_with", "You are now talking with %_$0%_", 1, { 0 } }, - { "refnum_too_low", "Window number must be greater than 1", 0 }, - { "windowlist_header", "Ref Name Active item Server Level", 0 }, - { "windowlist_line", "$[3]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } }, - { "windowlist_footer", "", 0 }, + { "line_start", "%B-%W!%B-%n ", 0 }, + { "line_start_irssi", "%B-%W!%B- %WIrssi:%n ", 0 }, + { "timestamp", "[$[-2.0]3:$[-2.0]4] ", 6, { 1, 1, 1, 1, 1, 1 } }, + { "daychange", "Day changed to $[-2.0]{0}-$[-2.0]1 $2", 3, { 1, 1, 1 } }, + { "talking_with", "You are now talking with %_$0%_", 1, { 0 } }, + { "refnum_too_low", "Window number must be greater than 1", 0 }, + { "refnum_not_found", "No such window: $0", 1, { 0 } }, /*REMOVE!!!!!!!!*/ + { "windowlist_header", "Ref Name Active item Server Level", 0 }, + { "windowlist_line", "$[3]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } }, + { "windowlist_footer", "", 0 }, - /* ---- */ - { NULL, "Server", 0 }, + /* ---- */ + { NULL, "Server", 0 }, - { "looking_up", "Looking up %_$0%_", 1, { 0 } }, - { "connecting", "Connecting to %_$0%_ %K[%n$1%K]%n port %_$2%_", 3, { 0, 0, 1 } }, - { "connection_established", "Connection to %_$0%_ established", 1, { 0 } }, - { "cant_connect", "Unable to connect server %_$0%_ port %_$1%_ %K[%n$2%K]", 3, { 0, 1, 0 } }, - { "connection_lost", "Connection lost to %_$0%_", 1, { 0 } }, - { "server_quit", "Disconnecting from server $0: %K[%n$1%K]", 2, { 0, 0 } }, - { "server_changed", "Changed to %_$2%_ server %_$1%_", 3, { 0, 0, 0 } }, - { "unknown_server_tag", "Unknown server tag %_$0%_", 1, { 0 } }, + { "looking_up", "Looking up %_$0%_", 1, { 0 } }, + { "connecting", "Connecting to %_$0%_ %K[%n$1%K]%n port %_$2%_", 3, { 0, 0, 1 } }, + { "connection_established", "Connection to %_$0%_ established", 1, { 0 } }, + { "cant_connect", "Unable to connect server %_$0%_ port %_$1%_ %K[%n$2%K]", 3, { 0, 1, 0 } }, + { "connection_lost", "Connection lost to %_$0%_", 1, { 0 } }, + { "server_quit", "Disconnecting from server $0: %K[%n$1%K]", 2, { 0, 0 } }, + { "server_changed", "Changed to %_$2%_ server %_$1%_", 3, { 0, 0, 0 } }, + { "unknown_server_tag", "Unknown server tag %_$0%_", 1, { 0 } }, - /* ---- */ - { NULL, "Highlighting", 0 }, + /* ---- */ + { NULL, "Highlighting", 0 }, - { "hilight_header", "Highlights:", 0 }, - { "hilight_line", "$[-4]0 $1 $2 $3$3$4$5", 7, { 1, 0, 0, 0, 0, 0, 0 } }, - { "hilight_footer", "", 0 }, - { "hilight_not_found", "Highlight not found: $0", 1, { 0 } }, - { "hilight_removed", "Highlight removed: $0", 1, { 0 } }, + { "hilight_header", "Highlights:", 0 }, + { "hilight_line", "$[-4]0 $1 $2 $3$3$4$5", 7, { 1, 0, 0, 0, 0, 0, 0 } }, + { "hilight_footer", "", 0 }, + { "hilight_not_found", "Highlight not found: $0", 1, { 0 } }, + { "hilight_removed", "Highlight removed: $0", 1, { 0 } }, - /* ---- */ - { NULL, "Aliases", 0 }, + /* ---- */ + { NULL, "Aliases", 0 }, - { "alias_added", "Alias $0 added", 1, { 0 } }, - { "alias_removed", "Alias $0 removed", 1, { 0 } }, - { "alias_not_found", "No such alias: $0", 1, { 0 } }, - { "aliaslist_header", "Aliases:", 0 }, - { "aliaslist_line", "$[10]0 $1", 2, { 0, 0 } }, - { "aliaslist_footer", "", 0 }, + { "alias_added", "Alias $0 added", 1, { 0 } }, + { "alias_removed", "Alias $0 removed", 1, { 0 } }, + { "alias_not_found", "No such alias: $0", 1, { 0 } }, + { "aliaslist_header", "Aliases:", 0 }, + { "aliaslist_line", "$[10]0 $1", 2, { 0, 0 } }, + { "aliaslist_footer", "", 0 }, - /* ---- */ - { NULL, "Logging", 0 }, + /* ---- */ + { NULL, "Logging", 0 }, - { "log_opened", "Log file %W$0%n opened", 1, { 0 } }, - { "log_closed", "Log file %W$0%n closed", 1, { 0 } }, - { "log_create_failed", "Couldn't create log file %W$0", 1, { 0 } }, - { "log_locked", "Log file %W$0%n is locked, probably by another running Irssi", 1, { 0 } }, - { "log_not_open", "Log file %W$0%n not open", 1, { 0 } }, - { "log_started", "Started logging to file %W$0", 1, { 0 } }, - { "log_stopped", "Stopped logging to file %W$0", 1, { 0 } }, - { "log_list_header", "Logs:", 0 }, - { "log_list", "$0: $1 $2$3$4", 5, { 0, 0, 0, 0, 0 } }, - { "log_list_footer", "", 0 }, - { "windowlog_file", "Window LOGFILE set to $0", 1, { 0 } }, - { "windowlog_file_logging", "Can't change window's logfile while log is on", 0 }, + { "log_opened", "Log file %W$0%n opened", 1, { 0 } }, + { "log_closed", "Log file %W$0%n closed", 1, { 0 } }, + { "log_create_failed", "Couldn't create log file %W$0", 1, { 0 } }, + { "log_locked", "Log file %W$0%n is locked, probably by another running Irssi", 1, { 0 } }, + { "log_not_open", "Log file %W$0%n not open", 1, { 0 } }, + { "log_started", "Started logging to file %W$0", 1, { 0 } }, + { "log_stopped", "Stopped logging to file %W$0", 1, { 0 } }, + { "log_list_header", "Logs:", 0 }, + { "log_list", "$0: $1 $2$3$4", 5, { 0, 0, 0, 0, 0 } }, + { "log_list_footer", "", 0 }, + { "windowlog_file", "Window LOGFILE set to $0", 1, { 0 } }, + { "windowlog_file_logging", "Can't change window's logfile while log is on", 0 }, - /* ---- */ - { NULL, "Misc", 0 }, + /* ---- */ + { NULL, "Misc", 0 }, - { "not_toggle", "Value must be either ON, OFF or TOGGLE", 0 }, - { "perl_error", "Perl error: $0", 1, { 0 } } + { "not_toggle", "Value must be either ON, OFF or TOGGLE", 0 }, + { "perl_error", "Perl error: $0", 1, { 0 } }, + + { NULL, NULL, 0 } }; diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index 94392763..137c718f 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -65,6 +65,3 @@ enum { }; extern FORMAT_REC fecommon_core_formats[]; -#define MODULE_FORMATS fecommon_core_formats - -#include "printformat.h" diff --git a/src/fe-common/core/printformat.h b/src/fe-common/core/printformat.h deleted file mode 100644 index e1dcf761..00000000 --- a/src/fe-common/core/printformat.h +++ /dev/null @@ -1,25 +0,0 @@ -/* printformat(...) = printformat_format(module_formats, ...) - - Could this be any harder? :) With GNU C compiler and C99 compilers, - use #define. With others use either inline functions if they are - supported or static functions if they are not.. - */ -#if defined (__GNUC__) && !defined (__STRICT_ANSI__) -/* GCC */ -# define printformat(server, channel, level, formatnum...) \ - printformat_format(MODULE_FORMATS, server, channel, level, ##formatnum) -#elif defined (_ISOC99_SOURCE) -/* C99 */ -# define printformat(server, channel, level, formatnum, ...) \ - printformat_format(MODULE_FORMATS, server, channel, level, formatnum, __VA_ARGS__) -#else -/* inline/static */ -static -#ifdef G_CAN_INLINE -inline -#endif -void printformat(void *server, const char *channel, int level, int formatnum, ...) -{ - printformat_format(MODULE_FORMATS, server, channel, level, formatnum); -} -#endif diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index 7152e910..c499388f 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -33,251 +33,242 @@ #include "themes.h" #include "windows.h" -static gboolean timestamps, msgs_timestamps, hide_text_style; -static gint printtag; -static gchar ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; +typedef struct { + WINDOW_REC *window; + void *server; + const char *channel; + int level; +} TEXT_DEST_REC; -static gint signal_gui_print_text; -static gint signal_print_text_stripped; -static gint signal_print_text; -static gint signal_print_text_finished; +static int timestamps, msgs_timestamps, hide_text_style; +static int timestamp_timeout; + +static int signal_gui_print_text; +static int signal_print_text_stripped; +static int signal_print_text; +static int signal_print_text_finished; + +static void print_string(TEXT_DEST_REC *dest, const char *text); void printbeep(void) { - signal_emit_id(signal_gui_print_text, 6, active_win, NULL, NULL, - GINT_TO_POINTER(PRINTFLAG_BEEP), "", MSGLEVEL_NEVER); + signal_emit_id(signal_gui_print_text, 6, active_win, NULL, NULL, + GINT_TO_POINTER(PRINTFLAG_BEEP), "", MSGLEVEL_NEVER); +} + +static void skip_mirc_color(char **str) +{ + if (!isdigit((int) **str)) + return; + + /* foreground */ + (*str)++; + if (isdigit((int) **str)) (*str)++; + + if (**str != ',' || !isdigit((int) (*str)[1])) return; + + /* background */ + (*str) += 2; + if (isdigit((int) **str)) (*str)++; +} + +#define is_color_code(c) \ + ((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \ + (c) == 15 || (c) == 22 || (c) == 27 || (c) == 31) + +char *strip_codes(const char *input) +{ + const char *p; + char *str, *out; + + out = str = g_strdup(input); + for (p = input; *p != '\0'; p++) { + if (*p == 3) { + p++; + + if (*p < 17 && *p > 0) { + /* irssi color */ + if (p[1] < 17 && p[1] > 0) p++; + continue; + } + + /* mirc color */ + skip_mirc_color((char **) &p); + p--; + continue; + } + + if (*p == 4 && p[1] != '\0' && p[2] != '\0') { + /* irssi color */ + p += 2; + continue; + } + + if (!is_color_code(*p)) + *out++ = *p; + } + + *out = '\0'; + return str; } /* parse ANSI color string */ static char *convert_ansi(char *str, int *fgcolor, int *bgcolor, int *flags) { - gchar *start; - gint fg, bg, fl, num; + static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + char *start; + int fg, bg, fl, num; - if (*str != '[') return str; + if (*str != '[') + return str; + start = str++; - start = str; + fg = *fgcolor < 0 ? current_theme->default_color : *fgcolor; + bg = *bgcolor < 0 ? -1 : *bgcolor; + fl = *flags; - fg = *fgcolor < 0 ? current_theme->default_color : *fgcolor; - bg = *bgcolor < 0 ? -1 : *bgcolor; - fl = *flags; + num = 0; + for (;; str++) { + if (*str == '\0') return start; - str++; num = 0; - for (;; str++) - { - if (*str == '\0') return start; + if (isdigit((int) *str)) { + num = num*10 + (*str-'0'); + continue; + } - if (isdigit((gint) *str)) - { - num = num*10 + (*str-'0'); - continue; - } + if (*str != ';' && *str != 'm') + return start; - 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; - 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 (!hide_text_style) { + *fgcolor = fg; + *bgcolor = bg == -1 ? -1 : bg; + *flags = fl; + } + str++; + break; + } + } - if (*str == 'm') - { - if (!hide_text_style) - { - *fgcolor = fg; - *bgcolor = bg == -1 ? -1 : bg; - *flags = fl; - } - str++; - break; - } - } - - return str; + return str; } -#define IN_COLOR_CODE 2 -#define IN_SECOND_CODE 4 -char *strip_codes(const char *input) +static int expand_styles(GString *out, char format, TEXT_DEST_REC *dest) { - const char *p; - gchar *str, *out; - gint loop_state; + static const char *backs = "04261537"; + static const char *fores = "kbgcrmyw"; + static const char *boldfores = "KBGCRMYW"; + char *p; - 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; + 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; + /* 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; + /* 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; + g_string_append_c(out, '%'); + break; case ':': - /* Newline */ - printtext(server, channel, level, out->str); - g_string_truncate(out, 0); - break; - + /* Newline */ + print_string(dest, 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; - + /* Indent here */ + g_string_append_c(out, 4); + g_string_append_c(out, -1); + g_string_append_c(out, 4); + break; case 'F': - /* flashing - ignore */ - break; - + /* flashing - ignore */ + break; case 'N': - /* don't put clear-color tag at the end of the output - ignore */ - break; - + /* 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 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 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, (int) (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 foreground color */ + if (format == 'p') format = 'm'; + p = strchr(fores, format); + if (p != NULL) { + g_string_append_c(out, 4); + g_string_append_c(out, (int) (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; - } + /* check if it's a bold foreground color */ + if (format == 'P') format = 'M'; + p = strchr(boldfores, format); + if (p != NULL) { + g_string_append_c(out, 4); + g_string_append_c(out, 8+(int) (p-boldfores)+1); + g_string_append_c(out, -2); + break; + } - return TRUE; + return FALSE; + } + + return TRUE; } static void read_arglist(va_list va, FORMAT_REC *format, @@ -287,12 +278,13 @@ static void read_arglist(va_list va, FORMAT_REC *format, int num, len, bufpos; bufpos = 0; + arglist[format->params] = NULL; 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); + g_warning("read_arglist() : parameter %d is NULL", num); arglist[num] = ""; } break; @@ -342,28 +334,32 @@ static void read_arglist(va_list va, FORMAT_REC *format, } } -static void output_format_text_args(GString *out, void *server, const char *channel, int level, FORMAT_REC *format, const char *text, va_list args) +static char *output_format_text_args(TEXT_DEST_REC *dest, FORMAT_REC *format, const char *text, va_list args) { + GString *out; char *arglist[10]; char buffer[200]; /* should be enough? (won't overflow even if it isn't) */ const char *str; - char code; + char code, *ret; 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.. */ + memset(arglist, 0, sizeof(arglist)); /*REMOVE!!!!!!!*/ read_arglist(args, format, arglist, sizeof(arglist)/sizeof(void*), buffer, sizeof(buffer)); + out = g_string_new(NULL); + code = 0; while (*str != '\0') { if (code == '%') { /* color code */ - if (!expand_styles(out, *str, server, channel, level)) { + if (!expand_styles(out, *str, dest)) { g_string_append_c(out, '%'); g_string_append_c(out, '%'); g_string_append_c(out, *str); @@ -373,7 +369,8 @@ static void output_format_text_args(GString *out, void *server, const char *chan /* argument */ char *ret; - ret = parse_special((char **) &str, active_win->active_server, active_win->active, arglist, &need_free, NULL); + 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); @@ -388,165 +385,233 @@ static void output_format_text_args(GString *out, void *server, const char *chan str++; } + + ret = out->str; + g_string_free(out, FALSE); + return ret; } -static void output_format_text(GString *out, void *server, const char *channel, int level, int formatnum, ...) +static char *output_format_text(TEXT_DEST_REC *dest, int formatnum, ...) { MODULE_THEME_REC *theme; va_list args; + char *ret; - theme = g_hash_table_lookup(current_theme->modules, MODULE_FORMATS->tag); + theme = g_hash_table_lookup(current_theme->modules, MODULE_NAME); va_start(args, formatnum); - output_format_text_args(out, server, channel, level, - &MODULE_FORMATS[formatnum], - theme == NULL ? NULL : theme->format[formatnum], args); + ret = output_format_text_args(dest, &fecommon_core_formats[formatnum], + theme == NULL ? NULL : theme->formats[formatnum], args); va_end(args); + + return ret; } -static void add_timestamp(WINDOW_REC *window, GString *out, void *server, const char *channel, int level) +void printformat_module_args(const char *module, void *server, const char *channel, int level, int formatnum, va_list va) { - time_t t; - struct tm *tm; - GString *tmp; + MODULE_THEME_REC *theme; + TEXT_DEST_REC dest; + FORMAT_REC *formats; + char *str; - if (!(level != MSGLEVEL_NEVER && (timestamps || (msgs_timestamps && (level & MSGLEVEL_MSGS) != 0)))) - return; + dest.window = NULL; + dest.server = server; + dest.channel = channel; + dest.level = level; - t = time(NULL); + theme = g_hash_table_lookup(current_theme->modules, module); + formats = g_hash_table_lookup(default_formats, module); - if ((t - window->last_timestamp) < settings_get_int("timestamp_timeout")) { - window->last_timestamp = t; - return; + str = output_format_text_args(&dest, &formats[formatnum], + theme == NULL ? NULL : theme->formats[formatnum], va); + if (*str != '\0') print_string(&dest, str); + g_free(str); +} + +void printformat_module(const char *module, void *server, const char *channel, int level, int formatnum, ...) +{ + va_list va; + + va_start(va, formatnum); + printformat_module_args(module, server, channel, level, formatnum, va); + va_end(va); +} + +void printformat_module_window_args(const char *module, WINDOW_REC *window, int level, int formatnum, va_list va) +{ + MODULE_THEME_REC *theme; + TEXT_DEST_REC dest; + FORMAT_REC *formats; + char *str; + + dest.window = window; + dest.server = NULL; + dest.channel = NULL; + dest.level = level; + + theme = g_hash_table_lookup(current_theme->modules, module); + formats = g_hash_table_lookup(default_formats, module); + + str = output_format_text_args(&dest, &formats[formatnum], + theme == NULL ? NULL : theme->formats[formatnum], va); + if (*str != '\0') print_string(&dest, str); + g_free(str); +} + +void printformat_module_window(const char *module, WINDOW_REC *window, int level, int formatnum, ...) +{ + va_list va; + + va_start(va, formatnum); + printformat_module_window_args(module, window, level, formatnum, va); + va_end(va); +} + +/* return the "-!- " text at the start of the line */ +static char *get_line_start_text(TEXT_DEST_REC *dest) +{ + if ((dest->level & (MSGLEVEL_CLIENTERROR|MSGLEVEL_CLIENTNOTICE)) != 0) + return output_format_text(dest, IRCTXT_LINE_START_IRSSI); + + if ((dest->level & (MSGLEVEL_MSGS|MSGLEVEL_PUBLIC|MSGLEVEL_NOTICES|MSGLEVEL_SNOTES|MSGLEVEL_CTCPS|MSGLEVEL_ACTIONS|MSGLEVEL_DCC|MSGLEVEL_CLIENTCRAP)) == 0 && dest->level != MSGLEVEL_NEVER) + return output_format_text(dest, IRCTXT_LINE_START); + + return NULL; +} + +static void print_string(TEXT_DEST_REC *dest, const char *text) +{ + gpointer levelp; + char *str, *tmp; + + g_return_if_fail(dest != NULL); + g_return_if_fail(text != NULL); + + if (dest->window == NULL) + dest->window = window_find_closest(dest->server, dest->channel, dest->level); + + tmp = get_line_start_text(dest); + str = tmp == NULL ? (char *) text : + g_strconcat(tmp, text, NULL); + g_free_not_null(tmp); + + levelp = GINT_TO_POINTER(dest->level); + + /* send the plain text version for logging etc.. */ + tmp = strip_codes(str); + signal_emit_id(signal_print_text_stripped, 5, dest->window, dest->server, dest->channel, levelp, tmp); + g_free(tmp); + + signal_emit_id(signal_print_text, 5, dest->window, dest->server, dest->channel, levelp, str); + if (str != text) g_free(str); +} + +static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str, va_list va) +{ + GString *out; + char *ret; + + out = g_string_new(NULL); + for (; *str != '\0'; str++) { + if (*str != '%') { + g_string_append_c(out, *str); + continue; + } + + if (*++str == '\0') + break; + + /* standard parameters */ + switch (*str) { + case 's': { + char *s = (char *) va_arg(va, char *); + if (s && *s) g_string_append(out, s); + break; + } + case 'd': { + int d = (int) va_arg(va, int); + g_string_sprintfa(out, "%d", d); + break; + } + case 'f': { + double f = (double) va_arg(va, double); + g_string_sprintfa(out, "%0.2f", f); + break; + } + case 'u': { + unsigned int d = (unsigned int) va_arg(va, unsigned int); + g_string_sprintfa(out, "%u", d); + break; + } + case 'l': { + long d = (long) va_arg(va, long); + + 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, dest)) { + g_string_append_c(out, '%'); + g_string_append_c(out, *str); + } + break; + } } - 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); + ret = out->str; + g_string_free(out, FALSE); + return ret; } /* Write text to channel - convert color codes */ -void printtext(void *server, const char *channel, int level, const char *str, ...) +void printtext(void *server, const char *channel, int level, const char *text, ...) { - va_list args; - GString *out; - gchar *tmpstr; - gint pros; + TEXT_DEST_REC dest; + char *str; + va_list va; - g_return_if_fail(str != NULL); + g_return_if_fail(text != NULL); - va_start(args, str); + dest.window = NULL; + dest.server = server; + dest.channel = channel; + dest.level = level; - pros = 0; - out = g_string_new(NULL); + va_start(va, text); + str = printtext_get_args(&dest, text, va); + va_end(va); - 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); + print_string(&dest, str); + g_free(str); } -void printformat_format(FORMAT_REC *formats, void *server, const char *channel, int level, int formatnum, ...) +void printtext_window(WINDOW_REC *window, int level, const char *text, ...) { - MODULE_THEME_REC *theme; - GString *out; - va_list args; + TEXT_DEST_REC dest; + char *str; + va_list va; - va_start(args, formatnum); - out = g_string_new(NULL); + g_return_if_fail(text != NULL); - theme = g_hash_table_lookup(current_theme->modules, formats->tag); + dest.window = window != NULL ? window : active_win; + dest.server = NULL; + dest.channel = NULL; + dest.level = level; - 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); + va_start(va, text); + str = printtext_get_args(&dest, text, va); + va_end(va); - g_string_free(out, TRUE); - va_end(args); + print_string(&dest, str); + g_free(str); } static void newline(WINDOW_REC *window) @@ -559,48 +624,74 @@ static void newline(WINDOW_REC *window) } } -static void sig_print_text(void *server, const char *target, gpointer level, const char *text) +#define show_timestamp(level) \ + ((level) != MSGLEVEL_NEVER && \ + (timestamps || (msgs_timestamps && ((level) & MSGLEVEL_MSGS)))) + +static char *get_timestamp(TEXT_DEST_REC *dest) { - WINDOW_REC *window; - GString *out; - gchar *dup, *ptr, type, *str; + struct tm *tm; + time_t t; + int diff; + + if (!show_timestamp(dest->level)) + return NULL; + + t = time(NULL); + + diff = t - dest->window->last_timestamp; + dest->window->last_timestamp = t; + if (diff < timestamp_timeout) + return NULL; + + tm = localtime(&t); + return output_format_text(dest, IRCTXT_TIMESTAMP, + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static char *get_server_tag(WINDOW_REC *window, SERVER_REC *server) +{ + if (server == NULL || servers == NULL || servers->next == NULL || + (window->active != NULL && window->active->server == server)) + return NULL; + + return g_strdup_printf("[%s] ", server->tag); +} + +static void sig_print_text(WINDOW_REC *window, SERVER_REC *server, const char *target, gpointer level, const char *text) +{ + TEXT_DEST_REC dest; + gchar *dup, *ptr, type, *str, *timestamp, *servertag; 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'; + dest.window = window; + dest.server = server; + dest.channel = target; + dest.level = GPOINTER_TO_INT(level); + flags = 0; fgcolor = -1; bgcolor = -1; type = '\0'; window->last_line = time(NULL); 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); + timestamp = get_timestamp(&dest); + servertag = get_server_tag(window, server); + str = g_strconcat(timestamp != NULL ? timestamp : "", + servertag != NULL ? servertag : "", + text, NULL); + g_free_not_null(timestamp); + g_free_not_null(servertag); + dup = str; 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) + if (is_color_code(*ptr)) { type = *ptr; *ptr++ = '\0'; @@ -715,20 +806,7 @@ static void sig_print_text(void *server, const char *target, gpointer level, con if (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++; - } - } - } + skip_mirc_color(&ptr); break; } @@ -770,47 +848,6 @@ static void sig_print_text(void *server, const char *target, gpointer level, con 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 (!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; - - if (win->active == NULL) - continue; /* FIXME: how to print in these windows? */ - - 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; -} - void printtext_multiline(void *server, const char *channel, int level, const char *format, const char *text) { char **lines, **tmp; @@ -837,31 +874,30 @@ static void sig_gui_dialog(const char *type, const char *text) static void read_settings(void) { - timestamps = settings_get_bool("timestamps"); - msgs_timestamps = settings_get_bool("msgs_timestamps"); - hide_text_style = settings_get_bool("hide_text_style"); + timestamps = settings_get_bool("timestamps"); + timestamp_timeout = settings_get_bool("timestamp_timeout"); + msgs_timestamps = settings_get_bool("msgs_timestamps"); + hide_text_style = settings_get_bool("hide_text_style"); } void printtext_init(void) { - settings_add_int("misc", "timestamp_timeout", 0); + 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"); + 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); + read_settings(); + 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); } 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); + 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); } diff --git a/src/fe-common/core/printtext.h b/src/fe-common/core/printtext.h index acd6a03e..71c5d88e 100644 --- a/src/fe-common/core/printtext.h +++ b/src/fe-common/core/printtext.h @@ -1,6 +1,8 @@ #ifndef __PRINTTEXT_H #define __PRINTTEXT_H +#include "windows.h" + enum { FORMAT_STRING, FORMAT_INT, @@ -24,9 +26,14 @@ typedef struct { #define PRINTFLAG_MIRC_COLOR 0x20 #define PRINTFLAG_INDENT 0x40 -void printformat_format(FORMAT_REC *formats, void *server, const char *channel, int level, int formatnum, ...); +void printformat_module(const char *module, void *server, const char *channel, int level, int formatnum, ...); +void printformat_module_window(const char *module, WINDOW_REC *window, int level, int formatnum, ...); -void printtext(void *server, const char *channel, int level, const char *str, ...); +void printformat_module_args(const char *module, void *server, const char *channel, int level, int formatnum, va_list va); +void printformat_module_window_args(const char *module, WINDOW_REC *window, int level, int formatnum, va_list va); + +void printtext(void *server, const char *channel, int level, const char *text, ...); +void printtext_window(WINDOW_REC *window, int level, const char *text, ...); void printtext_multiline(void *server, const char *channel, int level, const char *format, const char *text); void printbeep(void); @@ -36,4 +43,51 @@ char *strip_codes(const char *input); void printtext_init(void); void printtext_deinit(void); +/* printformat(...) = printformat_format(MODULE_NAME, ...) + + Could this be any harder? :) With GNU C compiler and C99 compilers, + use #define. With others use either inline functions if they are + supported or static functions if they are not.. + */ +#if defined (__GNUC__) && !defined (__STRICT_ANSI__) +/* GCC */ +# define printformat(server, channel, level, formatnum...) \ + printformat_module(MODULE_NAME, server, channel, level, ##formatnum) +# define printformat_window(window, level, formatnum...) \ + printformat_module_window(MODULE_NAME, window, level, ##formatnum) +#elif defined (_ISOC99_SOURCE) +/* C99 */ +# define printformat(server, channel, level, formatnum, ...) \ + printformat_module(MODULE_NAME, server, channel, level, formatnum, __VA_ARGS__) +# define printformat_window(window, level, formatnum, ...) \ + printformat_module_window(MODULE_NAME, window, level, formatnum, __VA_ARGS__) +#else +/* inline/static */ +static +#ifdef G_CAN_INLINE +inline +#endif +void printformat(void *server, const char *channel, int level, int formatnum, ...) +{ + va_list va; + + va_start(va, formatnum); + printformat_module_args(MODULE_NAME, server, channel, level, formatnum, va); + va_end(va); +} + +static +#ifdef G_CAN_INLINE +inline +#endif +void printformat_window(WINDOW_REC *window, int level, int formatnum, ...) +{ + va_list va; + + va_start(va, formatnum); + printformat_module_window_args(MODULE_NAME, window, level, formatnum, va); + va_end(va); +} +#endif + #endif diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 0d9735ab..879f558c 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -20,6 +20,8 @@ #include "module.h" #include "signals.h" +#include "commands.h" +#include "levels.h" #include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" @@ -29,6 +31,7 @@ GSList *themes; THEME_REC *current_theme; +GHashTable *default_formats; THEME_REC *theme_create(const char *path, const char *name) { @@ -46,17 +49,15 @@ THEME_REC *theme_create(const char *path, const char *name) return rec; } -static void theme_destroy_hash(const char *key, MODULE_THEME_REC *rec) +static void theme_module_destroy(const char *key, MODULE_THEME_REC *rec) { - int n, max; + int n; - max = strarray_length(rec->formatlist); - for (n = 0; n < max; n++) - if (rec->format[n] != NULL) - g_free(rec->format[n]); - g_free(rec->format); + for (n = 0; n < rec->count; n++) + if (rec->formats[n] != NULL) + g_free(rec->formats[n]); + g_free(rec->formats); - g_strfreev(rec->formatlist); g_free(rec->name); g_free(rec); } @@ -64,7 +65,7 @@ static void theme_destroy_hash(const char *key, MODULE_THEME_REC *rec) void theme_destroy(THEME_REC *rec) { signal_emit("theme destroyed", 1, rec); - g_hash_table_foreach(rec->modules, (GHFunc) theme_destroy_hash, NULL); + g_hash_table_foreach(rec->modules, (GHFunc) theme_module_destroy, NULL); g_hash_table_destroy(rec->modules); if (rec->bg_pixmap != NULL) g_free(rec->bg_pixmap); @@ -74,6 +75,119 @@ void theme_destroy(THEME_REC *rec) g_free(rec); } +static MODULE_THEME_REC *theme_module_create(THEME_REC *theme, const char *module) +{ + MODULE_THEME_REC *rec; + FORMAT_REC *formats; + + rec = g_hash_table_lookup(theme->modules, module); + if (rec != NULL) return rec; + + formats = g_hash_table_lookup(default_formats, module); + g_return_val_if_fail(formats != NULL, NULL); + + rec = g_new0(MODULE_THEME_REC, 1); + rec->name = g_strdup(module); + + for (rec->count = 0; formats[rec->count].def != NULL; rec->count++) ; + rec->formats = g_new0(char *, rec->count); + + g_hash_table_insert(theme->modules, rec->name, rec); + return rec; +} + +static void theme_read_formats(CONFIG_REC *config, THEME_REC *theme, const char *module) +{ + MODULE_THEME_REC *rec; + FORMAT_REC *formats; + CONFIG_NODE *node; + GSList *tmp; + int n; + + formats = g_hash_table_lookup(default_formats, module); + if (formats == NULL) return; + + node = config_node_traverse(config, "formats", FALSE); + if (node == NULL) return; + node = config_node_section(node, module, -1); + if (node == NULL) return; + + rec = theme_module_create(theme, module); + + for (tmp = node->value; tmp != NULL; tmp = tmp->next) { + node = tmp->data; + + if (node->key == NULL || node->value == NULL) + continue; + + for (n = 0; formats[n].def != NULL; n++) { + if (formats[n].tag != NULL && + g_strcasecmp(formats[n].tag, node->key) == 0) { + rec->formats[n] = g_strdup(node->value); + break; + } + } + } +} + +static void theme_read_module(THEME_REC *theme, const char *module) +{ + CONFIG_REC *config; + char *msg; + + config = config_open(theme->path, -1); + if (config == NULL) return; + + config_parse(config); + + if (config_last_error(mainconfig) != NULL) { + msg = g_strdup_printf(_("Ignored errors in theme:\n%s"), + config_last_error(mainconfig)); + signal_emit("gui dialog", 2, "error", msg); + g_free(msg); + } + + theme_read_formats(config, theme, module); + + config_close(config); +} + +static void theme_remove_module(THEME_REC *theme, const char *module) +{ + MODULE_THEME_REC *rec; + + rec = g_hash_table_lookup(theme->modules, module); + if (rec == NULL) return; + + g_hash_table_remove(theme->modules, module); + theme_module_destroy(module, rec); +} + +void theme_register_module(const char *module, FORMAT_REC *formats) +{ + if (g_hash_table_lookup(default_formats, module) != NULL) + return; + + g_hash_table_insert(default_formats, g_strdup(module), formats); + + if (current_theme != NULL) + theme_read_module(current_theme, module); +} + +void theme_unregister_module(const char *module) +{ + gpointer key, value; + + if (!g_hash_table_lookup_extended(default_formats, module, &key, &value)) + return; + + g_hash_table_remove(default_formats, key); + g_free(key); + + if (current_theme != NULL) + theme_remove_module(current_theme, module); +} + static THEME_REC *theme_find(const char *name) { GSList *tmp; @@ -115,49 +229,19 @@ static void find_themes(gchar *path) closedir(dirp); } -/* Read module texts into theme */ -static void theme_read_module_texts(const char *hashkey, MODULE_THEME_REC *rec, CONFIG_REC *config) +static void theme_read(THEME_REC *theme, const char *path) { - CONFIG_NODE *formats; - GSList *tmp; - char **flist; - int n; - - formats = config_node_traverse(config, "moduleformats", FALSE); - if (formats == NULL) return; - - for (tmp = formats->value; tmp != NULL; tmp = tmp->next) { - CONFIG_NODE *node = tmp->data; - - if (node->key == NULL || node->value == NULL) - continue; - - for (n = 0, flist = rec->formatlist; *flist != NULL; flist++, n++) { - if (g_strcasecmp(*flist, node->key) == 0) { - rec->format[n] = g_strdup(node->value); - break; - } - } - } -} - -static int theme_read(THEME_REC *theme, const char *path) -{ - MODULE_THEME_REC *mrec; CONFIG_REC *config; - CONFIG_NODE *formats; - GSList *tmp; char *value; - int errors; config = config_open(path, -1); if (config == NULL) { /* didn't exist or no access? */ theme->default_color = 15; - return FALSE; + return; } - errors = config_parse(config) == -1; + config_parse(config); /* default color */ theme->default_color = config_get_int(config, NULL, "default_color", 15); @@ -175,58 +259,172 @@ static int theme_read(THEME_REC *theme, const char *path) theme->flags |= THEME_FLAG_BG_SCALED; if (config_get_bool(config, NULL, "bg_shaded", FALSE)) theme->flags |= THEME_FLAG_BG_SHADED; - - /* Read modules that are defined in this theme. */ - formats = config_node_traverse(config, "modules", FALSE); - if (formats != NULL) { - for (tmp = formats->value; tmp != NULL; tmp = tmp->next) { - CONFIG_NODE *node = tmp->data; - - if (node->key == NULL || node->value == NULL) - continue; - - mrec = g_new0(MODULE_THEME_REC, 1); - mrec->name = g_strdup(node->key); - mrec->formatlist = g_strsplit(node->value, " ", -1); - mrec->format = g_new0(char*, strarray_length(mrec->formatlist)); - g_hash_table_insert(theme->modules, mrec->name, mrec); - } - } - - /* Read the texts inside the plugin */ - g_hash_table_foreach(theme->modules, (GHFunc) theme_read_module_texts, config); - - if (errors) { - /* errors fixed - save the theme */ - if (config_write(config, NULL, 0660) == -1) { - /* we probably tried to save to global directory - where we didn't have access.. try saving it to - home dir instead. */ - char *str; - - /* check that we really didn't try to save - it to home dir.. */ - str = g_strdup_printf("%s/.irssi/", g_get_home_dir()); - if (strncmp(path, str, strlen(str)) != 0) { - g_free(str); - str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), g_basename(path)); - - config_write(config, str, 0660); - } - g_free(str); - } - } config_close(config); - - return errors; } -static void sig_formats_error(void) +typedef struct { + char *name; + char *short_name; +} THEME_SEARCH_REC; + +static int theme_search_equal(THEME_SEARCH_REC *r1, THEME_SEARCH_REC *r2) { - signal_emit("gui dialog", 2, "warning", - "Your theme(s) had some old format strings, " - "these have been changed back to their default values."); - signal_remove("irssi init finished", (SIGNAL_FUNC) sig_formats_error); + return g_strcasecmp(r1->short_name, r2->short_name); +} + +static void theme_get_modules(char *module, FORMAT_REC *formats, GSList **list) +{ + THEME_SEARCH_REC *rec; + + rec = g_new(THEME_SEARCH_REC, 1); + rec->name = module; + rec->short_name = strrchr(module, '/'); + if (rec->short_name != NULL) + rec->short_name++; else rec->short_name = module; + *list = g_slist_insert_sorted(*list, rec, (GCompareFunc) theme_search_equal); +} + +static GSList *get_sorted_modules(void) +{ + GSList *list; + + list = NULL; + g_hash_table_foreach(default_formats, (GHFunc) theme_get_modules, &list); + return list; +} + +static THEME_SEARCH_REC *theme_search(GSList *list, const char *module) +{ + THEME_SEARCH_REC *rec; + + while (list != NULL) { + rec = list->data; + + if (g_strcasecmp(rec->short_name, module) == 0) + return rec; + list = list->next; + } + + return NULL; +} + +static void theme_show(THEME_SEARCH_REC *rec, const char *key, const char *value) +{ + MODULE_THEME_REC *theme; + FORMAT_REC *formats; + const char *text, *last_title; + int n, first; + + formats = g_hash_table_lookup(default_formats, rec->name); + theme = g_hash_table_lookup(current_theme->modules, rec->name); + + last_title = NULL; first = TRUE; + for (n = 1; formats[n].def != NULL; n++) { + text = theme != NULL && theme->formats[n] != NULL ? + theme->formats[n] : formats[n].def; + + if (formats[n].tag == NULL) + last_title = text; + else if ((value != NULL && key != NULL && g_strcasecmp(formats[n].tag, key) == 0) || + (value == NULL && (key == NULL || stristr(formats[n].tag, key) != NULL))) { + if (first) { + printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, ""); + printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%K[%W%s%K] - [%W%s%K]", rec->short_name, formats[0].def); + printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, ""); + first = FALSE; + } + if (last_title != NULL) + printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%K[%W%s%K]", last_title); + if (value != NULL) { + theme = theme_module_create(current_theme, rec->name); + theme->formats[n] = g_strdup(value); + text = value; + } + printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s %K=%n %s", formats[n].tag, text); + last_title = NULL; + } + } +} + +static void cmd_format(const char *data) +{ + char *params, *module, *key, *value; + GSList *tmp, *modules; + + /* /FORMAT [] [ []] */ + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &module, &key, &value); + + modules = get_sorted_modules(); + if (*module != '\0' && theme_search(modules, module) == NULL) { + /* first argument isn't module.. */ + g_free(params); + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value); + module = ""; + } + + if (*key == '\0') key = NULL; + if (*value == '\0') value = NULL; + + for (tmp = modules; tmp != NULL; tmp = tmp->next) { + THEME_SEARCH_REC *rec = tmp->data; + + if (*module == '\0' || g_strcasecmp(rec->short_name, module) == 0) + theme_show(rec, key, value); + } + g_slist_foreach(modules, (GFunc) g_free, NULL); + g_slist_free(modules); + + g_free(params); +} + +static void module_save(const char *module, MODULE_THEME_REC *rec, CONFIG_NODE *fnode) +{ + CONFIG_NODE *node; + FORMAT_REC *formats; + int n; + + formats = g_hash_table_lookup(default_formats, rec->name); + if (formats == NULL) return; + + node = config_node_section(fnode, rec->name, NODE_TYPE_BLOCK); + for (n = 0; formats[n].def != NULL; n++) { + if (rec->formats[n] != NULL) + iconfig_node_set_str(node, formats[n].tag, rec->formats[n]); + } +} + +/* save changed formats */ +static void cmd_save(void) +{ + CONFIG_REC *config; + CONFIG_NODE *fnode; + + config = config_open(current_theme->path, 0660); + if (config == NULL) return; + + config_parse(config); + + fnode = config_node_traverse(config, "formats", TRUE); + g_hash_table_foreach(current_theme->modules, (GHFunc) module_save, fnode); + + if (config_write(config, NULL, 0660) == -1) { + /* we probably tried to save to global directory + where we didn't have access.. try saving it to + home dir instead. */ + char *str; + + /* check that we really didn't try to save + it to home dir.. */ + str = g_strdup_printf("%s/.irssi/", g_get_home_dir()); + if (strncmp(current_theme->path, str, strlen(str)) != 0) { + g_free(str); + str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), g_basename(current_theme->path)); + + config_write(config, str, 0660); + } + g_free(str); + } + config_close(config); } void themes_init(void) @@ -235,7 +433,8 @@ void themes_init(void) GSList *tmp; const char *value; char *str; - int errors; + + default_formats = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); /* first there's default theme.. */ str = g_strdup_printf("%s/.irssi/default.theme", g_get_home_dir()); @@ -251,22 +450,20 @@ void themes_init(void) find_themes(SYSCONFDIR"/irssi"); /* read formats for all themes */ - errors = FALSE; for (tmp = themes; tmp != NULL; tmp = tmp->next) { rec = tmp->data; - if (theme_read(rec, rec->path)) - errors = TRUE; + theme_read(rec, rec->path); } - if (errors) - signal_add("irssi init finished", (SIGNAL_FUNC) sig_formats_error); - /* find the current theme to use */ value = settings_get_str("current_theme"); rec = theme_find(value); if (rec != NULL) current_theme = rec; + + command_bind("format", NULL, (SIGNAL_FUNC) cmd_format); + command_bind("save", NULL, (SIGNAL_FUNC) cmd_save); } void themes_deinit(void) @@ -275,4 +472,9 @@ void themes_deinit(void) g_slist_foreach(themes, (GFunc) theme_destroy, NULL); g_slist_free(themes); themes = NULL; + + g_hash_table_destroy(default_formats); + + command_unbind("format", (SIGNAL_FUNC) cmd_format); + command_unbind("save", (SIGNAL_FUNC) cmd_save); } diff --git a/src/fe-common/core/themes.h b/src/fe-common/core/themes.h index 7bd4a8f8..5b5331f8 100644 --- a/src/fe-common/core/themes.h +++ b/src/fe-common/core/themes.h @@ -1,18 +1,18 @@ #ifndef __THEMES_H #define __THEMES_H +#include "printtext.h" + #define THEME_FLAG_BG_SCROLLABLE 0x0001 #define THEME_FLAG_BG_SCALED 0x0002 #define THEME_FLAG_BG_SHADED 0x0004 -typedef struct -{ +typedef struct { char *name; - char **formatlist; - char **format; -} -MODULE_THEME_REC; + int count; + char **formats; /* in same order as in module's default formats */ +} MODULE_THEME_REC; typedef struct { char *path; @@ -30,10 +30,16 @@ typedef struct { extern GSList *themes; extern THEME_REC *current_theme; +extern GHashTable *default_formats; THEME_REC *theme_create(const char *path, const char *name); void theme_destroy(THEME_REC *rec); +#define theme_register(formats) theme_register_module(MODULE_NAME, formats) +#define theme_unregister() theme_unregister_module(MODULE_NAME) +void theme_register_module(const char *module, FORMAT_REC *formats); +void theme_unregister_module(const char *module); + void themes_init(void); void themes_deinit(void); diff --git a/src/fe-common/core/window-activity.c b/src/fe-common/core/window-activity.c index ba3adb13..420261a0 100644 --- a/src/fe-common/core/window-activity.c +++ b/src/fe-common/core/window-activity.c @@ -26,13 +26,11 @@ #include "windows.h" #include "window-items.h" -static void sig_hilight_text(SERVER_REC *server, const char *channel, gpointer levelptr, const char *msg) +static void sig_hilight_text(WINDOW_REC *window, SERVER_REC *server, const char *channel, gpointer levelptr, const char *msg) { - WINDOW_REC *window; int level, oldlevel; level = GPOINTER_TO_INT(levelptr); - window = window_find_closest(server, channel, level); if (window == active_win || (level & (MSGLEVEL_NEVER|MSGLEVEL_NO_ACT|MSGLEVEL_MSGS))) return; diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c new file mode 100644 index 00000000..507cfe90 --- /dev/null +++ b/src/fe-common/core/window-commands.c @@ -0,0 +1,370 @@ +/* + window-commands.c : irssi + + Copyright (C) 2000 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 "signals.h" +#include "commands.h" +#include "misc.h" +#include "server.h" + +#include "levels.h" + +#include "windows.h" +#include "window-items.h" + +static void cmd_window(const char *data, void *server, WI_ITEM_REC *item) +{ + command_runsub("window", data, server, item); +} + +static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item) +{ + WINDOW_REC *window; + int type; + + g_return_if_fail(data != NULL); + + type = (g_strncasecmp(data, "hid", 3) == 0 || g_strcasecmp(data, "tab") == 0) ? 1 : + (g_strcasecmp(data, "split") == 0 ? 2 : 0); + signal_emit("gui window create override", 1, GINT_TO_POINTER(type)); + + window = window_create(NULL, FALSE); + window_change_server(window, server); +} + +static void cmd_window_close(const char *data) +{ + /* destroy window unless it's the last one */ + if (windows->next != NULL) + window_destroy(active_win); +} + +static void cmd_window_refnum(const char *data) +{ + WINDOW_REC *window; + + if (!is_numeric(data, 0)) + return; + + window = window_find_refnum(atoi(data)); + if (window != NULL) + window_set_active(window); +} + +/* return the first window number with the highest activity */ +static WINDOW_REC *window_highest_activity(WINDOW_REC *window) +{ + WINDOW_REC *rec, *max_win; + GSList *tmp; + int max_act, through; + + g_return_val_if_fail(window != NULL, NULL); + + max_win = NULL; max_act = 0; through = FALSE; + + tmp = g_slist_find(windows, window); + for (;; tmp = tmp->next) { + if (tmp == NULL) { + tmp = windows; + through = TRUE; + } + + if (through && tmp->data == window) + break; + + rec = tmp->data; + + if (rec->new_data && max_act < rec->new_data) { + max_act = rec->new_data; + max_win = rec; + } + } + + return max_win; +} + +static void cmd_window_goto(const char *data) +{ + WINDOW_REC *window; + + g_return_if_fail(data != NULL); + + if (is_numeric(data, 0)) { + cmd_window_refnum(data); + return; + } + + if (g_strcasecmp(data, "active") == 0) + window = window_highest_activity(active_win); + else + window = window_find_item(active_win, data); + + if (window != NULL) + window_set_active(window); +} + +static void cmd_window_next(void) +{ + int num; + + num = window_refnum_next(active_win->refnum); + if (num < 1) num = windows_refnum_last(); + + window_set_active(window_find_refnum(num)); +} + +static void cmd_window_prev(void) +{ + int num; + + num = window_refnum_prev(active_win->refnum); + if (num < 1) num = window_refnum_next(0); + + window_set_active(window_find_refnum(num)); +} + +static void cmd_window_level(const char *data) +{ + g_return_if_fail(data != NULL); + + window_set_level(active_win, combine_level(active_win->level, data)); + printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Window level is now %s", + bits2level(active_win->level)); +} + +static void cmd_window_server(const char *data) +{ + SERVER_REC *server; + + g_return_if_fail(data != NULL); + + server = server_find_tag(data); + if (server == NULL) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNKNOWN_SERVER_TAG, data); + else if (active_win->active == NULL) { + window_change_server(active_win, server); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SERVER_CHANGED, server->tag, server->connrec->address, + server->connrec->ircnet == NULL ? "" : server->connrec->ircnet); + } +} + +static void cmd_window_item_prev(void) +{ + window_item_prev(active_win); +} + +static void cmd_window_item_next(void) +{ + window_item_next(active_win); +} + +static void cmd_window_number(const char *data) +{ + int num; + + num = atoi(data); + if (num < 1) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_REFNUM_TOO_LOW); + else + window_set_refnum(active_win, num); +} + +static void cmd_window_name(const char *data) +{ + window_set_name(active_win, data); +} + +/* we're moving the first window to last - move the first contiguous block + of refnums to left. Like if there's windows 1..5 and 7..10, move 1 to + 11, 2..5 to 1..4 and leave 7..10 alone */ +static void windows_move_left(WINDOW_REC *move_window) +{ + WINDOW_REC *window; + int refnum; + + window_set_refnum(move_window, windows_refnum_last()+1); + for (refnum = 2;; refnum++) { + window = window_find_refnum(refnum); + if (window == NULL) break; + + window_set_refnum(window, refnum-1); + } +} + +/* we're moving the last window to first - make some space so we can use the + refnum 1 */ +static void windows_move_right(WINDOW_REC *move_window) +{ + WINDOW_REC *window; + int refnum; + + /* find the first unused refnum, like if there's windows + 1..5 and 7..10, we only need to move 1..5 to 2..6 */ + refnum = 1; + while (window_find_refnum(refnum) != NULL) refnum++; + + refnum--; + while (refnum > 0) { + window = window_find_refnum(refnum); + g_return_if_fail(window != NULL); + window_set_refnum(window, window == move_window ? 1 : refnum+1); + + refnum--; + } +} + +static void cmd_window_move_left(void) +{ + int refnum; + + refnum = window_refnum_prev(active_win->refnum); + if (refnum != -1) { + window_set_refnum(active_win, active_win->refnum-1); + return; + } + + windows_move_left(active_win); +} + +static void cmd_window_move_right(void) +{ + int refnum; + + refnum = window_refnum_next(active_win->refnum); + if (refnum != -1) { + window_set_refnum(active_win, active_win->refnum+1); + return; + } + + windows_move_right(active_win); +} + +static void cmd_window_move(const char *data, SERVER_REC *server, WI_ITEM_REC *item) +{ + int new_refnum, refnum; + + if (!is_numeric(data, 0)) { + command_runsub("window move", data, server, item); + return; + } + + new_refnum = atoi(data); + if (new_refnum > active_win->refnum) { + for (;;) { + refnum = window_refnum_next(active_win->refnum); + if (refnum == -1 || refnum > new_refnum) + break; + + window_set_refnum(active_win, refnum); + } + } else { + for (;;) { + refnum = window_refnum_prev(active_win->refnum); + if (refnum == -1 || refnum < new_refnum) + break; + + window_set_refnum(active_win, refnum); + } + } +} + +static int windows_compare(WINDOW_REC *w1, WINDOW_REC *w2) +{ + return w1->refnum < w2->refnum ? -1 : 1; +} + +static GSList *windows_get_sorted(void) +{ + GSList *tmp, *list; + + list = NULL; + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + list = g_slist_insert_sorted(list, tmp->data, (GCompareFunc) windows_compare); + } + + return list; +} + +static void cmd_window_list(void) +{ + GSList *tmp, *sorted; + char *levelstr; + + sorted = windows_get_sorted(); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_HEADER); + for (tmp = sorted; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + levelstr = bits2level(rec->level); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_LINE, + rec->refnum, rec->name == NULL ? "" : rec->name, + rec->active == NULL ? "" : rec->active->name, + rec->active_server == NULL ? "" : ((SERVER_REC *) rec->active_server)->tag, + levelstr); + g_free(levelstr); + } + g_slist_free(sorted); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_FOOTER); +} + +void window_commands_init(void) +{ + command_bind("window", NULL, (SIGNAL_FUNC) cmd_window); + command_bind("window new", NULL, (SIGNAL_FUNC) cmd_window_new); + command_bind("window close", NULL, (SIGNAL_FUNC) cmd_window_close); + command_bind("window kill", NULL, (SIGNAL_FUNC) cmd_window_close); + command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server); + command_bind("window refnum", NULL, (SIGNAL_FUNC) cmd_window_refnum); + command_bind("window goto", NULL, (SIGNAL_FUNC) cmd_window_goto); + command_bind("window prev", NULL, (SIGNAL_FUNC) cmd_window_prev); + command_bind("window next", NULL, (SIGNAL_FUNC) cmd_window_next); + command_bind("window level", NULL, (SIGNAL_FUNC) cmd_window_level); + command_bind("window item prev", NULL, (SIGNAL_FUNC) cmd_window_item_prev); + command_bind("window item next", NULL, (SIGNAL_FUNC) cmd_window_item_next); + command_bind("window number", NULL, (SIGNAL_FUNC) cmd_window_number); + command_bind("window name", NULL, (SIGNAL_FUNC) cmd_window_name); + command_bind("window move", NULL, (SIGNAL_FUNC) cmd_window_move); + command_bind("window move left", NULL, (SIGNAL_FUNC) cmd_window_move_left); + command_bind("window move right", NULL, (SIGNAL_FUNC) cmd_window_move_right); + command_bind("window list", NULL, (SIGNAL_FUNC) cmd_window_list); +} + +void window_commands_deinit(void) +{ + command_unbind("window", (SIGNAL_FUNC) cmd_window); + command_unbind("window new", (SIGNAL_FUNC) cmd_window_new); + command_unbind("window close", (SIGNAL_FUNC) cmd_window_close); + command_unbind("window kill", (SIGNAL_FUNC) cmd_window_close); + command_unbind("window server", (SIGNAL_FUNC) cmd_window_server); + command_unbind("window refnum", (SIGNAL_FUNC) cmd_window_refnum); + command_unbind("window goto", (SIGNAL_FUNC) cmd_window_goto); + command_unbind("window prev", (SIGNAL_FUNC) cmd_window_prev); + command_unbind("window next", (SIGNAL_FUNC) cmd_window_next); + command_unbind("window level", (SIGNAL_FUNC) cmd_window_level); + command_unbind("window item prev", (SIGNAL_FUNC) cmd_window_item_prev); + command_unbind("window item next", (SIGNAL_FUNC) cmd_window_item_next); + command_unbind("window number", (SIGNAL_FUNC) cmd_window_number); + command_unbind("window name", (SIGNAL_FUNC) cmd_window_name); + command_unbind("window move", (SIGNAL_FUNC) cmd_window_move); + command_unbind("window move left", (SIGNAL_FUNC) cmd_window_move_left); + command_unbind("window move right", (SIGNAL_FUNC) cmd_window_move_right); + command_unbind("window list", (SIGNAL_FUNC) cmd_window_list); +} diff --git a/src/fe-common/core/window-items.c b/src/fe-common/core/window-items.c index ac4c30d5..b8633461 100644 --- a/src/fe-common/core/window-items.c +++ b/src/fe-common/core/window-items.c @@ -27,7 +27,6 @@ #include "levels.h" -#include "printtext.h" #include "windows.h" #include "window-items.h" @@ -86,17 +85,6 @@ WINDOW_REC *window_item_window(WI_ITEM_REC *item) return MODULE_DATA(item); } -void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item) -{ - g_return_if_fail(window != NULL); - - if (window->active != item) { - window->active = item; - if (item != NULL) window_change_server(window, window->active_server); - signal_emit("window item changed", 2, window, item); - } -} - void window_item_change_server(WI_ITEM_REC *item, void *server) { WINDOW_REC *window; @@ -110,6 +98,71 @@ void window_item_change_server(WI_ITEM_REC *item, void *server) if (window->active == item) window_change_server(window, item->server); } +void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item) +{ + g_return_if_fail(window != NULL); + + if (window->active != item) { + window->active = item; + if (item != NULL) window_change_server(window, window->active_server); + signal_emit("window item changed", 2, window, item); + } +} + +void window_item_prev(WINDOW_REC *window) +{ + WI_ITEM_REC *last; + GSList *tmp; + + g_return_if_fail(window != NULL); + + last = NULL; + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + WI_ITEM_REC *rec = tmp->data; + + if (rec != window->active) + last = rec; + else { + /* current channel. did we find anything? + if not, go to the last channel */ + if (last != NULL) break; + } + } + + if (last != NULL) + window_item_set_active(window, last); +} + +void window_item_next(WINDOW_REC *window) +{ + WI_ITEM_REC *next; + GSList *tmp; + int gone; + + g_return_if_fail(window != NULL); + + next = NULL; gone = FALSE; + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + WI_ITEM_REC *rec = tmp->data; + + if (rec == window->active) + gone = TRUE; + else { + if (gone) { + /* found the next channel */ + next = rec; + break; + } + + if (next == NULL) + next = rec; /* fallback to first channel */ + } + } + + if (next != NULL) + window_item_set_active(window, next); +} + static WI_ITEM_REC *window_item_find_window(WINDOW_REC *window, void *server, const char *name) { GSList *tmp; diff --git a/src/fe-common/core/window-items.h b/src/fe-common/core/window-items.h index c760ee36..34d61c2e 100644 --- a/src/fe-common/core/window-items.h +++ b/src/fe-common/core/window-items.h @@ -10,9 +10,12 @@ void window_remove_item(WINDOW_REC *window, WI_ITEM_REC *item); void window_item_create(WI_ITEM_REC *item, int automatic); WINDOW_REC *window_item_window(WI_ITEM_REC *item); -void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item); void window_item_change_server(WI_ITEM_REC *item, void *server); +void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item); +void window_item_prev(WINDOW_REC *window); +void window_item_next(WINDOW_REC *window); + /* Find wanted window item by name. `server' can be NULL. */ WI_ITEM_REC *window_item_find(void *server, const char *name); diff --git a/src/fe-common/core/windows.c b/src/fe-common/core/windows.c index bbe6a740..da6de6aa 100644 --- a/src/fe-common/core/windows.c +++ b/src/fe-common/core/windows.c @@ -37,6 +37,8 @@ GSList *windows; /* first in the list is the active window, next is the last active, etc. */ WINDOW_REC *active_win; +static int daytag; + static int window_get_new_refnum(void) { WINDOW_REC *win; @@ -247,117 +249,6 @@ WINDOW_REC *window_find_refnum(int refnum) return NULL; } -static int windows_refnum_last(void) -{ - GSList *tmp; - int max; - - max = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - - if (rec->refnum > max) - max = rec->refnum; - } - - return max; -} - -static int window_refnum_prev(int refnum) -{ - GSList *tmp; - int prev, max; - - max = prev = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - - if (rec->refnum < refnum && (prev == -1 || rec->refnum > prev)) - prev = rec->refnum; - if (max == -1 || rec->refnum > max) - max = rec->refnum; - } - - return prev != -1 ? prev : max; -} - -static int window_refnum_next(int refnum) -{ - GSList *tmp; - int min, next; - - min = next = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - - if (rec->refnum > refnum && (next == -1 || rec->refnum < next)) - next = rec->refnum; - if (min == -1 || rec->refnum < min) - min = rec->refnum; - } - - return next != -1 ? next : min; -} - -static void cmd_window(const char *data, void *server, WI_ITEM_REC *item) -{ - command_runsub("window", data, server, item); -} - -static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item) -{ - WINDOW_REC *window; - int type; - - g_return_if_fail(data != NULL); - - type = (g_strncasecmp(data, "hid", 3) == 0 || g_strcasecmp(data, "tab") == 0) ? 1 : - (g_strcasecmp(data, "split") == 0 ? 2 : 0); - signal_emit("gui window create override", 1, GINT_TO_POINTER(type)); - - window = window_create(NULL, FALSE); - window_change_server(window, server); -} - -static void cmd_window_close(const char *data) -{ - /* destroy window unless it's the last one */ - if (windows->next != NULL) - window_destroy(active_win); -} - -/* return the first window number with the highest activity */ -static WINDOW_REC *window_highest_activity(WINDOW_REC *window) -{ - WINDOW_REC *rec, *max_win; - GSList *tmp; - int max_act, through; - - g_return_val_if_fail(window != NULL, NULL); - - max_win = NULL; max_act = 0; through = FALSE; - - tmp = g_slist_find(windows, window); - for (;; tmp = tmp->next) { - if (tmp == NULL) { - tmp = windows; - through = TRUE; - } - - if (through && tmp->data == window) - break; - - rec = tmp->data; - - if (rec->new_data && max_act < rec->new_data) { - max_act = rec->new_data; - max_win = rec; - } - } - - return max_win; -} - WINDOW_REC *window_find_name(const char *name) { GSList *tmp; @@ -409,288 +300,56 @@ WINDOW_REC *window_find_item(WINDOW_REC *window, const char *name) return MODULE_DATA(item); } -static void cmd_window_refnum(const char *data) +int window_refnum_prev(int refnum) { - WINDOW_REC *window; - - if (!is_numeric(data, 0)) - return; - - window = window_find_refnum(atoi(data)); - if (window != NULL) - window_set_active(window); -} - -static void cmd_window_goto(const char *data) -{ - WINDOW_REC *window; - - g_return_if_fail(data != NULL); - - if (is_numeric(data, 0)) { - cmd_window_refnum(data); - return; - } - - if (g_strcasecmp(data, "active") == 0) - window = window_highest_activity(active_win); - else - window = window_find_item(active_win, data); - - if (window != NULL) - window_set_active(window); -} - -static void cmd_window_next(void) -{ - int num; - - num = window_refnum_next(active_win->refnum); - if (num < 1) num = windows_refnum_last(); - - window_set_active(window_find_refnum(num)); -} - -static void cmd_window_prev(void) -{ - int num; - - num = window_refnum_prev(active_win->refnum); - if (num < 1) num = window_refnum_next(0); - - window_set_active(window_find_refnum(num)); -} - -static void cmd_window_level(const char *data) -{ - g_return_if_fail(data != NULL); - - window_set_level(active_win, combine_level(active_win->level, data)); - printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Window level is now %s", - bits2level(active_win->level)); -} - -static void cmd_window_server(const char *data) -{ - SERVER_REC *server; - - g_return_if_fail(data != NULL); - - server = server_find_tag(data); - if (server == NULL) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNKNOWN_SERVER_TAG, data); - else if (active_win->active == NULL) { - window_change_server(active_win, server); - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SERVER_CHANGED, server->tag, server->connrec->address, - server->connrec->ircnet == NULL ? "" : server->connrec->ircnet); - } -} - -static void cmd_window_item_prev(const char *data, void *server, WI_ITEM_REC *item) -{ - WINDOW_REC *window; - WI_ITEM_REC *last; GSList *tmp; + int prev, max; - window = item == NULL ? NULL : MODULE_DATA(item); - if (window == NULL) return; - - last = NULL; - for (tmp = window->items; tmp != NULL; tmp = tmp->next) { - WI_ITEM_REC *rec = tmp->data; - - if (rec != item) - last = rec; - else { - /* current channel. did we find anything? - if not, go to the last channel */ - if (last != NULL) break; - } - } - - if (last != NULL) - window_item_set_active(window, last); -} - -static void cmd_window_item_next(const char *data, void *server, WI_ITEM_REC *item) -{ - WINDOW_REC *window; - WI_ITEM_REC *next; - GSList *tmp; - int gone; - - window = item == NULL ? NULL : MODULE_DATA(item); - if (window == NULL) return; - - next = NULL; gone = FALSE; - for (tmp = window->items; tmp != NULL; tmp = tmp->next) { - WI_ITEM_REC *rec = tmp->data; - - if (rec == item) - gone = TRUE; - else { - if (gone) { - /* found the next channel */ - next = rec; - break; - } - - if (next == NULL) - next = rec; /* fallback to first channel */ - } - } - - if (next != NULL) - window_item_set_active(window, next); -} - -static void cmd_window_number(const char *data) -{ - int num; - - num = atoi(data); - if (num < 1) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_REFNUM_TOO_LOW); - else - window_set_refnum(active_win, num); -} - -static void cmd_window_name(const char *data) -{ - window_set_name(active_win, data); -} - -/* we're moving the first window to last - move the first contiguous block - of refnums to left. Like if there's windows 1..5 and 7..10, move 1 to - 11, 2..5 to 1..4 and leave 7..10 alone */ -static void windows_move_left(WINDOW_REC *move_window) -{ - WINDOW_REC *window; - int refnum; - - window_set_refnum(move_window, windows_refnum_last()+1); - for (refnum = 2;; refnum++) { - window = window_find_refnum(refnum); - if (window == NULL) break; - - window_set_refnum(window, refnum-1); - } -} - -/* we're moving the last window to first - make some space so we can use the - refnum 1 */ -static void windows_move_right(WINDOW_REC *move_window) -{ - WINDOW_REC *window; - int refnum; - - /* find the first unused refnum, like if there's windows - 1..5 and 7..10, we only need to move 1..5 to 2..6 */ - refnum = 1; - while (window_find_refnum(refnum) != NULL) refnum++; - - refnum--; - while (refnum > 0) { - window = window_find_refnum(refnum); - g_return_if_fail(window != NULL); - window_set_refnum(window, window == move_window ? 1 : refnum+1); - - refnum--; - } -} - -static void cmd_window_move_left(void) -{ - int refnum; - - refnum = window_refnum_prev(active_win->refnum); - if (refnum != -1) { - window_set_refnum(active_win, active_win->refnum-1); - return; - } - - windows_move_left(active_win); -} - -static void cmd_window_move_right(void) -{ - int refnum; - - refnum = window_refnum_next(active_win->refnum); - if (refnum != -1) { - window_set_refnum(active_win, active_win->refnum+1); - return; - } - - windows_move_right(active_win); -} - -static void cmd_window_move(const char *data, SERVER_REC *server, WI_ITEM_REC *item) -{ - int new_refnum, refnum; - - if (!is_numeric(data, 0)) { - command_runsub("window move", data, server, item); - return; - } - - new_refnum = atoi(data); - if (new_refnum > active_win->refnum) { - for (;;) { - refnum = window_refnum_next(active_win->refnum); - if (refnum == -1 || refnum > new_refnum) - break; - - window_set_refnum(active_win, refnum); - } - } else { - for (;;) { - refnum = window_refnum_prev(active_win->refnum); - if (refnum == -1 || refnum < new_refnum) - break; - - window_set_refnum(active_win, refnum); - } - } -} - -static int windows_compare(WINDOW_REC *w1, WINDOW_REC *w2) -{ - return w1->refnum < w2->refnum ? -1 : 1; -} - -GSList *windows_get_sorted(void) -{ - GSList *tmp, *list; - - list = NULL; + max = prev = -1; for (tmp = windows; tmp != NULL; tmp = tmp->next) { - list = g_slist_insert_sorted(list, tmp->data, (GCompareFunc) windows_compare); - } - - return list; -} - -static void cmd_window_list(void) -{ - GSList *tmp, *sorted; - char *levelstr; - - sorted = windows_get_sorted(); - printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_HEADER); - for (tmp = sorted; tmp != NULL; tmp = tmp->next) { WINDOW_REC *rec = tmp->data; - levelstr = bits2level(rec->level); - printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_LINE, - rec->refnum, rec->name == NULL ? "" : rec->name, - rec->active == NULL ? "" : rec->active->name, - rec->active_server == NULL ? "" : ((SERVER_REC *) rec->active_server)->tag, - levelstr); - g_free(levelstr); + if (rec->refnum < refnum && (prev == -1 || rec->refnum > prev)) + prev = rec->refnum; + if (max == -1 || rec->refnum > max) + max = rec->refnum; } - g_slist_free(sorted); - printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLIST_FOOTER); + + return prev != -1 ? prev : max; +} + +int window_refnum_next(int refnum) +{ + GSList *tmp; + int min, next; + + min = next = -1; + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + if (rec->refnum > refnum && (next == -1 || rec->refnum < next)) + next = rec->refnum; + if (min == -1 || rec->refnum < min) + min = rec->refnum; + } + + return next != -1 ? next : min; +} + +int windows_refnum_last(void) +{ + GSList *tmp; + int max; + + max = -1; + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + if (rec->refnum > max) + max = rec->refnum; + } + + return max; } static void sig_server_looking(void *server) @@ -722,29 +381,46 @@ static void sig_server_disconnected(void *server) } } +static int sig_check_daychange(void) +{ + static int lastday = -1; + GSList *tmp; + time_t t; + struct tm *tm; + + if (!settings_get_bool("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) { + printformat_window(tmp->data, MSGLEVEL_NEVER, IRCTXT_DAYCHANGE, + tm->tm_mday, tm->tm_mon+1, 1900+tm->tm_year); + } + + lastday = tm->tm_mday; + return TRUE; +} + void windows_init(void) { active_win = NULL; settings_add_bool("lookandfeel", "window_auto_change", FALSE); - command_bind("window", NULL, (SIGNAL_FUNC) cmd_window); - command_bind("window new", NULL, (SIGNAL_FUNC) cmd_window_new); - command_bind("window close", NULL, (SIGNAL_FUNC) cmd_window_close); - command_bind("window kill", NULL, (SIGNAL_FUNC) cmd_window_close); - command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server); - command_bind("window refnum", NULL, (SIGNAL_FUNC) cmd_window_refnum); - command_bind("window goto", NULL, (SIGNAL_FUNC) cmd_window_goto); - command_bind("window prev", NULL, (SIGNAL_FUNC) cmd_window_prev); - command_bind("window next", NULL, (SIGNAL_FUNC) cmd_window_next); - command_bind("window level", NULL, (SIGNAL_FUNC) cmd_window_level); - command_bind("window item prev", NULL, (SIGNAL_FUNC) cmd_window_item_prev); - command_bind("window item next", NULL, (SIGNAL_FUNC) cmd_window_item_next); - command_bind("window number", NULL, (SIGNAL_FUNC) cmd_window_number); - command_bind("window name", NULL, (SIGNAL_FUNC) cmd_window_name); - command_bind("window move", NULL, (SIGNAL_FUNC) cmd_window_move); - command_bind("window move left", NULL, (SIGNAL_FUNC) cmd_window_move_left); - command_bind("window move right", NULL, (SIGNAL_FUNC) cmd_window_move_right); - command_bind("window list", NULL, (SIGNAL_FUNC) cmd_window_list); + daytag = g_timeout_add(30000, (GSourceFunc) sig_check_daychange, NULL); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_add("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); @@ -752,24 +428,8 @@ void windows_init(void) void windows_deinit(void) { - command_unbind("window", (SIGNAL_FUNC) cmd_window); - command_unbind("window new", (SIGNAL_FUNC) cmd_window_new); - command_unbind("window close", (SIGNAL_FUNC) cmd_window_close); - command_unbind("window kill", (SIGNAL_FUNC) cmd_window_close); - command_unbind("window server", (SIGNAL_FUNC) cmd_window_server); - command_unbind("window refnum", (SIGNAL_FUNC) cmd_window_refnum); - command_unbind("window goto", (SIGNAL_FUNC) cmd_window_goto); - command_unbind("window prev", (SIGNAL_FUNC) cmd_window_prev); - command_unbind("window next", (SIGNAL_FUNC) cmd_window_next); - command_unbind("window level", (SIGNAL_FUNC) cmd_window_level); - command_unbind("window item prev", (SIGNAL_FUNC) cmd_window_item_prev); - command_unbind("window item next", (SIGNAL_FUNC) cmd_window_item_next); - command_unbind("window number", (SIGNAL_FUNC) cmd_window_number); - command_unbind("window name", (SIGNAL_FUNC) cmd_window_name); - command_unbind("window move", (SIGNAL_FUNC) cmd_window_move); - command_unbind("window move left", (SIGNAL_FUNC) cmd_window_move_left); - command_unbind("window move right", (SIGNAL_FUNC) cmd_window_move_right); - command_unbind("window list", (SIGNAL_FUNC) cmd_window_list); + g_source_remove(daytag); + signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking); signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); diff --git a/src/fe-common/core/windows.h b/src/fe-common/core/windows.h index 2b13101b..98ef9425 100644 --- a/src/fe-common/core/windows.h +++ b/src/fe-common/core/windows.h @@ -69,6 +69,10 @@ WINDOW_REC *window_find_refnum(int refnum); WINDOW_REC *window_find_name(const char *name); WINDOW_REC *window_find_item(WINDOW_REC *window, const char *name); +int window_refnum_prev(int refnum); +int window_refnum_next(int refnum); +int windows_refnum_last(void); + void windows_init(void); void windows_deinit(void); diff --git a/src/fe-common/irc/dcc/Makefile.am b/src/fe-common/irc/dcc/Makefile.am index 0424c7b2..54647bc9 100644 --- a/src/fe-common/irc/dcc/Makefile.am +++ b/src/fe-common/irc/dcc/Makefile.am @@ -14,4 +14,5 @@ libfe_common_irc_dcc_la_SOURCES = \ module-formats.c noinst_HEADERS = \ + module.h \ module-formats.h diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index b89e44b9..5cdcd28d 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -30,6 +30,7 @@ #include "irc/dcc/dcc.h" +#include "themes.h" #include "windows.h" static void dcc_connected(DCC_REC *dcc) @@ -427,10 +428,14 @@ void fe_dcc_init(void) command_bind("dcc ", NULL, (SIGNAL_FUNC) cmd_dcc_list); command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list); signal_add("window item remove", (SIGNAL_FUNC) dcc_chat_closed); + + theme_register(fecommon_irc_dcc_formats); } void fe_dcc_deinit(void) { + theme_unregister(); + signal_remove("dcc connected", (SIGNAL_FUNC) dcc_connected); signal_remove("dcc rejected", (SIGNAL_FUNC) dcc_rejected); signal_remove("dcc closed", (SIGNAL_FUNC) dcc_closed); diff --git a/src/fe-common/irc/dcc/module-formats.c b/src/fe-common/irc/dcc/module-formats.c index 40313010..4dee15f7 100644 --- a/src/fe-common/irc/dcc/module-formats.c +++ b/src/fe-common/irc/dcc/module-formats.c @@ -21,39 +21,40 @@ #include "module.h" #include "printtext.h" -FORMAT_REC fecommon_irc_dcc_formats[] = -{ - { MODULE_NAME, "IRC", 0 }, +FORMAT_REC fecommon_irc_dcc_formats[] = { + { MODULE_NAME, "IRC", 0 }, - /* ---- */ - { NULL, "DCC", 0 }, + /* ---- */ + { NULL, "DCC", 0 }, - { "own_dcc", "%K[%rdcc%K(%R$0%K)]%n $1", 2, { 0, 0 } }, - { "own_dcc_me", "%W * $0%n $1", 2, { 0, 0 } }, - { "own_dcc_ctcp", "%K[%rctcp%K(%R$0%K)]%n $1 $2", 3, { 0, 0, 0 } }, - { "dcc_msg", "%K[%G$0%K(%gdcc%K)]%n $1", 2, { 0, 0 } }, - { "action_dcc", "%W (*dcc*) $0%n $1", 2, { 0, 0 } }, - { "dcc_ctcp", "%g>>> DCC CTCP received from %_$0%_%K: %g$1", 2, { 0, 0 } }, - { "dcc_chat", "%gDCC CHAT from %_$0%_ %K[%g$1 port $2%K]", 3, { 0, 0, 1 } }, - { "dcc_chat_not_found", "%gNo DCC CHAT connection open to %_$0", 1, { 0 } }, - { "dcc_chat_connected", "%gDCC %_CHAT%_ connection with %_$0%_ %K%K[%g$1 port $2%K]%g established", 3, { 0, 0, 1 } }, - { "dcc_chat_disconnected", "%gDCC lost chat to %_$0", 1, { 0 } }, - { "dcc_send", "%gDCC SEND from %_$0%_ %K[%g$1 port $2%K]: %g$3 %K[%g$4 bytes%K]", 5, { 0, 0, 1, 0, 2 } }, - { "dcc_send_exists", "%gDCC already sending file %G$0%g for %_$1%_", 2, { 0, 0 } }, - { "dcc_send_not_found", "%gDCC not sending file %G$1%g to %_$0", 2, { 0, 0 } }, - { "dcc_send_file_not_found", "%gDCC file not found: %G$0%g", 1, { 0 } }, - { "dcc_send_connected", "%gDCC sending file %G$0%g for %_$1%_ %K[%g$2 port $3%K]", 4, { 0, 0, 0, 1 } }, - { "dcc_send_complete", "%gDCC sent file $0 %K[%g%_$1%_kb%K]%g for %_$2%_ in %_$3%_ secs %K[%g%_$4kb/s%_%K]", 5, { 0, 2, 0, 2, 3 } }, - { "dcc_send_aborted", "%gDCC aborted sending file $0 for %_$1%_", 2, { 0, 0 } }, - { "dcc_get_not_found", "%gDCC no file offered by %_$0", 1, { 0 } }, - { "dcc_get_connected", "%gDCC receiving file %G$0%g from %_$1%_ %K[%g$2 port $3%K]", 4, { 0, 0, 0, 1 } }, - { "dcc_get_complete", "%gDCC received file %G$0%g %K[%g$1kb%K]%g from %_$2%_ in %_$3%_ secs %K[%g$4kb/s%K]", 5, { 0, 2, 0, 2, 3 } }, - { "dcc_get_aborted", "%gDCC aborted receiving file $0 from %_$1%_", 2, { 0, 0 } }, - { "dcc_unknown_ctcp", "%gDCC unknown ctcp %G$0%g from %_$1%_ %K[%g$2%K]", 3, { 0, 0, 0 } }, - { "dcc_unknown_reply", "%gDCC unknown reply %G$0%g from %_$1%_ %K[%g$2%K]", 3, { 0, 0, 0 } }, - { "dcc_unknown_type", "%gDCC unknown type %_$0", 1, { 0 } }, - { "dcc_connect_error", "%gDCC can't connect to %_$0%_ port %_$1", 2, { 0, 1 } }, - { "dcc_cant_create", "%gDCC can't create file %G$0%g", 1, { 0 } }, - { "dcc_rejected", "%gDCC %G$0%g was rejected by %_$1%_ %K[%G$2%K]", 3, { 0, 0, 0 } }, - { "dcc_close", "%gDCC %G$0%g close for %_$1%_ %K[%G$2%K]", 3, { 0, 0, 0 } } + { "own_dcc", "%K[%rdcc%K(%R$0%K)]%n $1", 2, { 0, 0 } }, + { "own_dcc_me", "%W * $0%n $1", 2, { 0, 0 } }, + { "own_dcc_ctcp", "%K[%rctcp%K(%R$0%K)]%n $1 $2", 3, { 0, 0, 0 } }, + { "dcc_msg", "%K[%G$0%K(%gdcc%K)]%n $1", 2, { 0, 0 } }, + { "action_dcc", "%W (*dcc*) $0%n $1", 2, { 0, 0 } }, + { "dcc_ctcp", "%g>>> DCC CTCP received from %_$0%_%K: %g$1", 2, { 0, 0 } }, + { "dcc_chat", "%gDCC CHAT from %_$0%_ %K[%g$1 port $2%K]", 3, { 0, 0, 1 } }, + { "dcc_chat_not_found", "%gNo DCC CHAT connection open to %_$0", 1, { 0 } }, + { "dcc_chat_connected", "%gDCC %_CHAT%_ connection with %_$0%_ %K%K[%g$1 port $2%K]%g established", 3, { 0, 0, 1 } }, + { "dcc_chat_disconnected", "%gDCC lost chat to %_$0", 1, { 0 } }, + { "dcc_send", "%gDCC SEND from %_$0%_ %K[%g$1 port $2%K]: %g$3 %K[%g$4 bytes%K]", 5, { 0, 0, 1, 0, 2 } }, + { "dcc_send_exists", "%gDCC already sending file %G$0%g for %_$1%_", 2, { 0, 0 } }, + { "dcc_send_not_found", "%gDCC not sending file %G$1%g to %_$0", 2, { 0, 0 } }, + { "dcc_send_file_not_found", "%gDCC file not found: %G$0%g", 1, { 0 } }, + { "dcc_send_connected", "%gDCC sending file %G$0%g for %_$1%_ %K[%g$2 port $3%K]", 4, { 0, 0, 0, 1 } }, + { "dcc_send_complete", "%gDCC sent file $0 %K[%g%_$1%_kb%K]%g for %_$2%_ in %_$3%_ secs %K[%g%_$4kb/s%_%K]", 5, { 0, 2, 0, 2, 3 } }, + { "dcc_send_aborted", "%gDCC aborted sending file $0 for %_$1%_", 2, { 0, 0 } }, + { "dcc_get_not_found", "%gDCC no file offered by %_$0", 1, { 0 } }, + { "dcc_get_connected", "%gDCC receiving file %G$0%g from %_$1%_ %K[%g$2 port $3%K]", 4, { 0, 0, 0, 1 } }, + { "dcc_get_complete", "%gDCC received file %G$0%g %K[%g$1kb%K]%g from %_$2%_ in %_$3%_ secs %K[%g$4kb/s%K]", 5, { 0, 2, 0, 2, 3 } }, + { "dcc_get_aborted", "%gDCC aborted receiving file $0 from %_$1%_", 2, { 0, 0 } }, + { "dcc_unknown_ctcp", "%gDCC unknown ctcp %G$0%g from %_$1%_ %K[%g$2%K]", 3, { 0, 0, 0 } }, + { "dcc_unknown_reply", "%gDCC unknown reply %G$0%g from %_$1%_ %K[%g$2%K]", 3, { 0, 0, 0 } }, + { "dcc_unknown_type", "%gDCC unknown type %_$0", 1, { 0 } }, + { "dcc_connect_error", "%gDCC can't connect to %_$0%_ port %_$1", 2, { 0, 1 } }, + { "dcc_cant_create", "%gDCC can't create file %G$0%g", 1, { 0 } }, + { "dcc_rejected", "%gDCC %G$0%g was rejected by %_$1%_ %K[%G$2%K]", 3, { 0, 0, 0 } }, + { "dcc_close", "%gDCC %G$0%g close for %_$1%_ %K[%G$2%K]", 3, { 0, 0, 0 } }, + + { NULL, NULL, 0 } }; diff --git a/src/fe-common/irc/dcc/module-formats.h b/src/fe-common/irc/dcc/module-formats.h index de01511f..d7fe8eff 100644 --- a/src/fe-common/irc/dcc/module-formats.h +++ b/src/fe-common/irc/dcc/module-formats.h @@ -36,6 +36,3 @@ enum { }; extern FORMAT_REC fecommon_irc_dcc_formats[]; -#define MODULE_FORMATS fecommon_irc_dcc_formats - -#include "printformat.h" diff --git a/src/fe-common/irc/dcc/module.h b/src/fe-common/irc/dcc/module.h new file mode 100644 index 00000000..966a37cb --- /dev/null +++ b/src/fe-common/irc/dcc/module.h @@ -0,0 +1,3 @@ +#include "common.h" + +#define MODULE_NAME "fe-common/irc/dcc" diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index bde1d9fe..87a0655e 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -19,6 +19,7 @@ */ #include "module.h" +#include "module-formats.h" #include "signals.h" #include "args.h" #include "misc.h" @@ -27,6 +28,7 @@ #include "server-setup.h" +#include "themes.h" #include "completion.h" void fe_channels_init(void); @@ -100,6 +102,8 @@ void fe_common_irc_init(void) settings_add_bool("lookandfeel", "show_away_once", TRUE); settings_add_bool("lookandfeel", "show_quit_once", FALSE); + theme_register(fecommon_irc_formats); + fe_channels_init(); fe_irc_commands_init(); fe_irc_server_init(); @@ -132,6 +136,8 @@ void fe_common_irc_deinit(void) fe_query_deinit(); completion_deinit(); irc_window_activity_deinit(); + + theme_unregister(); } void fe_common_irc_finish_init(void) diff --git a/src/fe-common/irc/flood/Makefile.am b/src/fe-common/irc/flood/Makefile.am index c802dfd9..46ca4f25 100644 --- a/src/fe-common/irc/flood/Makefile.am +++ b/src/fe-common/irc/flood/Makefile.am @@ -13,5 +13,6 @@ libfe_common_irc_flood_la_SOURCES = \ fe-flood.c \ module-formats.c -noinst_headers = \ +noinst_HEADERS = \ + module.h \ module-formats.h diff --git a/src/fe-common/irc/flood/fe-flood.c b/src/fe-common/irc/flood/fe-flood.c index d21d6952..b7937fe9 100644 --- a/src/fe-common/irc/flood/fe-flood.c +++ b/src/fe-common/irc/flood/fe-flood.c @@ -26,6 +26,8 @@ #include "irc-server.h" #include "irc/flood/autoignore.h" +#include "themes.h" + static void event_autoignore_new(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore) { g_return_if_fail(ignore != NULL); @@ -45,10 +47,14 @@ void fe_flood_init(void) { signal_add("autoignore new", (SIGNAL_FUNC) event_autoignore_new); signal_add("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); + + theme_register(fecommon_irc_flood_formats); } void fe_flood_deinit(void) { + theme_unregister(); + signal_remove("autoignore new", (SIGNAL_FUNC) event_autoignore_new); signal_remove("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); } diff --git a/src/fe-common/irc/flood/module-formats.c b/src/fe-common/irc/flood/module-formats.c index ea8ec653..2d0293bc 100644 --- a/src/fe-common/irc/flood/module-formats.c +++ b/src/fe-common/irc/flood/module-formats.c @@ -23,11 +23,13 @@ FORMAT_REC fecommon_irc_flood_formats[] = { - { MODULE_NAME, "Flood", 0 }, + { MODULE_NAME, "Flood", 0 }, - /* ---- */ - { NULL, "Autoignore", 0 }, + /* ---- */ + { NULL, "Autoignore", 0 }, - { "autoignore", "Flood detected from %_$0%_, autoignoring for %_$1%_ minutes", 2, { 0, 1 } }, - { "autounignore", "Unignoring %_$0", 1, { 0 } } + { "autoignore", "Flood detected from %_$0%_, autoignoring for %_$1%_ minutes", 2, { 0, 1 } }, + { "autounignore", "Unignoring %_$0", 1, { 0 } }, + + { NULL, NULL, 0 } }; diff --git a/src/fe-common/irc/flood/module-formats.h b/src/fe-common/irc/flood/module-formats.h index 8311b021..7386dd2a 100644 --- a/src/fe-common/irc/flood/module-formats.h +++ b/src/fe-common/irc/flood/module-formats.h @@ -10,6 +10,3 @@ enum { }; extern FORMAT_REC fecommon_irc_flood_formats[]; -#define MODULE_FORMATS fecommon_irc_flood_formats - -#include "printformat.h" diff --git a/src/fe-common/irc/flood/module.h b/src/fe-common/irc/flood/module.h new file mode 100644 index 00000000..a5d9528f --- /dev/null +++ b/src/fe-common/irc/flood/module.h @@ -0,0 +1,3 @@ +#include "common.h" + +#define MODULE_NAME "fe-common/irc/flood" diff --git a/src/fe-common/irc/module-formats.c b/src/fe-common/irc/module-formats.c index 0a76bb22..403c1a52 100644 --- a/src/fe-common/irc/module-formats.c +++ b/src/fe-common/irc/module-formats.c @@ -21,173 +21,173 @@ #include "module.h" #include "printtext.h" -FORMAT_REC fecommon_irc_formats[] = -{ - { MODULE_NAME, "IRC", 0 }, +FORMAT_REC fecommon_irc_formats[] = { + { MODULE_NAME, "IRC", 0 }, - /* ---- */ - { NULL, "Server", 0 }, + /* ---- */ + { NULL, "Server", 0 }, - { "lag_disconnected", "No PONG reply from server %_$0%_ in $1 seconds, disconnecting", 2, { 0, 1 } }, - { "disconnected", "Disconnected from %_$0%_ %K[%n$1%K]", 2, { 0, 0 } }, - { "server_list", "%_$0%_: $1:$2 ($3)", 5, { 0, 0, 1, 0, 0 } }, - { "server_lookup_list", "%_$0%_: $1:$2 ($3) (connecting...)", 5, { 0, 0, 1, 0, 0 } }, - { "server_reconnect_list", "%_$0%_: $1:$2 ($3) ($5 left before reconnecting)", 6, { 0, 0, 1, 0, 0, 0 } }, - { "server_reconnect_removed", "Removed reconnection to server %_$0%_ port %_$1%_", 3, { 0, 1, 0 } }, - { "server_reconnect_not_found", "Reconnection tag %_$0%_ not found", 1, { 0 } }, - { "query_server_changed", "Query with %_$2%_ changed to server %_$1%_", 3, { 0, 0, 0 } }, - { "setupserver_added", "Server $0 saved", 2, { 0, 0 } }, - { "setupserver_removed", "Server $0 removed", 2, { 0, 0 } }, - { "setupserver_not_found", "Server $0 not found", 2, { 0, 0 } }, - { "setupserver_header", "Server Port IRC Net Settings", 0 }, - { "setupserver_line", "%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } }, - { "setupserver_footer", "", 0 }, - { "netsplit", "[%_$2%_] %RNetsplit%n detected between servers %_$0%_ and %_$1%_%:Use /NETSPLIT to see who left", 3, { 0, 0, 0 } }, - { "no_netsplits", "There are no net splits", 0 }, - { "netsplits_header", "Nick Channel Server Splitted server", 0 }, - { "netsplits_line", "$[9]0 $[10]1 $[20]2 $3", 4, { 0, 0, 0, 0 } }, - { "netsplits_footer", "", 0 }, + { "lag_disconnected", "No PONG reply from server %_$0%_ in $1 seconds, disconnecting", 2, { 0, 1 } }, + { "disconnected", "Disconnected from %_$0%_ %K[%n$1%K]", 2, { 0, 0 } }, + { "server_list", "%_$0%_: $1:$2 ($3)", 5, { 0, 0, 1, 0, 0 } }, + { "server_lookup_list", "%_$0%_: $1:$2 ($3) (connecting...)", 5, { 0, 0, 1, 0, 0 } }, + { "server_reconnect_list", "%_$0%_: $1:$2 ($3) ($5 left before reconnecting)", 6, { 0, 0, 1, 0, 0, 0 } }, + { "server_reconnect_removed", "Removed reconnection to server %_$0%_ port %_$1%_", 3, { 0, 1, 0 } }, + { "server_reconnect_not_found", "Reconnection tag %_$0%_ not found", 1, { 0 } }, + { "query_server_changed", "Query with %_$2%_ changed to server %_$1%_", 3, { 0, 0, 0 } }, + { "setupserver_added", "Server $0 saved", 2, { 0, 0 } }, + { "setupserver_removed", "Server $0 removed", 2, { 0, 0 } }, + { "setupserver_not_found", "Server $0 not found", 2, { 0, 0 } }, + { "setupserver_header", "Server Port IRC Net Settings", 0 }, + { "setupserver_line", "%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } }, + { "setupserver_footer", "", 0 }, + { "netsplit", "%RNetsplit%n detected between servers %_$0%_ and %_$1%_%:Use /NETSPLIT to see who left", 2, { 0, 0 } }, + { "no_netsplits", "There are no net splits", 0 }, + { "netsplits_header", "Nick Channel Server Splitted server", 0 }, + { "netsplits_line", "$[9]0 $[10]1 $[20]2 $3", 4, { 0, 0, 0, 0 } }, + { "netsplits_footer", "", 0 }, - /* ---- */ - { NULL, "Channels", 0 }, + /* ---- */ + { NULL, "Channels", 0 }, - { "join", "%c%_$0%_ %K[%c$1%K]%n has joined %_$2", 3, { 0, 0, 0 } }, - { "part", "%c$0 %K[%n$1%K]%n has left %_$2%_ %K[%n$3%K]", 4, { 0, 0, 0, 0 } }, - { "joinerror_toomany", "Cannot join to channel %_$0%_ %K(%nYou have joined to too many channels%K)", 1, { 0 } }, - { "joinerror_full", "Cannot join to channel %_$0%_ %K(%nChannel is full%K)", 1, { 0 } }, - { "joinerror_invite", "Cannot join to channel %_$0%_ %K(%nYou must be invited%K)", 1, { 0 } }, - { "joinerror_banned", "Cannot join to channel %_$0%_ %K(%nYou are banned%K)", 1, { 0 } }, - { "joinerror_bad_key", "Cannot join to channel %_$0%_ %K(%nBad channel key%K)", 1, { 0 } }, - { "joinerror_bad_mask", "Cannot join to channel %_$0%_ %K(%nBad channel mask%K)", 1, { 0 } }, - { "joinerror_unavail", "Cannot join to channel %_$0%_ %K(%nChannel is temporarily unavailable%K)", 1, { 0 } }, - { "kick", "%c$0%n was kicked from %_$1%_ by %_$2%_ %K[%n$3%K]", 4, { 0, 0, 0, 0 } }, - { "quit", "%c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]", 3, { 0, 0, 0 } }, - { "quit_once", "%_$3%_ %c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]", 4, { 0, 0, 0, 0 } }, - { "invite", "%_$0%_ invites you to %_$1", 2, { 0, 0 } }, - { "inviting", "Inviting $0 to %_$1", 2, { 0, 0 } }, - { "not_invited", "You have not been invited to a channel!", 0 }, - { "names", "%K[%g%_Users%_%K(%g$0%K)]%n $1", 2, { 0, 0 } }, - { "endofnames", "%g%_$0%_%K:%n Total of %_$1%_ nicks %K[%n%_$2%_ ops, %_$3%_ voices, %_$4%_ normal%K]", 5, { 0, 1, 1, 1, 1 } }, - { "channel_created", "Channel %_$0%_ created $1", 2, { 0, 0 } }, - { "topic", "Topic for %c$0%K:%n $1", 2, { 0, 0 } }, - { "no_topic", "No topic set for %c$0", 1, { 0 } }, - { "new_topic", "%_$0%_ changed the topic of %c$1%n to%K:%n $2", 3, { 0, 0, 0 } }, - { "topic_unset", "Topic unset by %_$0%_ on %c$1", 2, { 0, 0 } }, - { "topic_info", "Topic set by %_$0%_ %K[%n$1%K]", 2, { 0, 0 } }, - { "chanmode_change", "mode/%c$0 %K[%n$1%K]%n by %_$2", 3, { 0, 0, 0 } }, - { "server_chanmode_change", "%RServerMode/%c$0 %K[%n$1%K]%n by %_$2", 3, { 0, 0, 0 } }, - { "channel_mode", "mode/%c$0 %K[%n$1%K]", 2, { 0, 0 } }, - { "bantype", "Ban type changed to %_$0", 1, { 0 } }, - { "banlist", "%_$0%_: ban %c$1", 2, { 0, 0 } }, - { "banlist_long", "%_$0%_: ban %c$1 %K[%nby %_$2%_, $3 secs ago%K]", 4, { 0, 0, 0, 1 } }, - { "ebanlist", "%_$0%_: ban exception %c$1", 2, { 0, 0 } }, - { "ebanlist_long", "%_$0%_: ban exception %c$1 %K[%nby %_$2%_, $3 secs ago%K]", 4, { 0, 0, 0, 1 } }, - { "invitelist", "%_$0%_: invite %c$1", 2, { 0, 0 } }, - { "no_such_channel", "$0: No such channel", 1, { 0 } }, - { "channel_synced", "Join to %_$0%_ was synced in %_$1%_ secs", 2, { 0, 2 } }, - { "not_in_channels", "You are not on any channels", 0 }, - { "current_channel", "Current channel $0", 1, { 0 } }, - { "chanlist_header", "You are on the following channels:", 0 }, - { "chanlist_line", "$[-10]0 %|+$1 ($2): $3", 4, { 0, 0, 0, 0 } }, - { "chansetup_not_found", "Channel $0 not found", 2, { 0, 0 } }, - { "chansetup_added", "Channel $0 saved", 2, { 0, 0 } }, - { "chansetup_removed", "Channel $0 removed", 2, { 0, 0 } }, - { "chansetup_header", "Channel IRC net Password Settings", 0 }, - { "chansetup_line", "$[15]0 %|$[10]1 $[10]2 $3", 4, { 0, 0, 0, 0 } }, - { "chansetup_footer", "", 0 }, + { "join", "%c%_$0%_ %K[%c$1%K]%n has joined %_$2", 3, { 0, 0, 0 } }, + { "part", "%c$0 %K[%n$1%K]%n has left %_$2%_ %K[%n$3%K]", 4, { 0, 0, 0, 0 } }, + { "joinerror_toomany", "Cannot join to channel %_$0%_ %K(%nYou have joined to too many channels%K)", 1, { 0 } }, + { "joinerror_full", "Cannot join to channel %_$0%_ %K(%nChannel is full%K)", 1, { 0 } }, + { "joinerror_invite", "Cannot join to channel %_$0%_ %K(%nYou must be invited%K)", 1, { 0 } }, + { "joinerror_banned", "Cannot join to channel %_$0%_ %K(%nYou are banned%K)", 1, { 0 } }, + { "joinerror_bad_key", "Cannot join to channel %_$0%_ %K(%nBad channel key%K)", 1, { 0 } }, + { "joinerror_bad_mask", "Cannot join to channel %_$0%_ %K(%nBad channel mask%K)", 1, { 0 } }, + { "joinerror_unavail", "Cannot join to channel %_$0%_ %K(%nChannel is temporarily unavailable%K)", 1, { 0 } }, + { "kick", "%c$0%n was kicked from %_$1%_ by %_$2%_ %K[%n$3%K]", 4, { 0, 0, 0, 0 } }, + { "quit", "%c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]", 3, { 0, 0, 0 } }, + { "quit_once", "%_$3%_ %c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]", 4, { 0, 0, 0, 0 } }, + { "invite", "%_$0%_ invites you to %_$1", 2, { 0, 0 } }, + { "inviting", "Inviting $0 to %_$1", 2, { 0, 0 } }, + { "not_invited", "You have not been invited to a channel!", 0 }, + { "names", "%K[%g%_Users%_%K(%g$0%K)]%n $1", 2, { 0, 0 } }, + { "endofnames", "%g%_$0%_%K:%n Total of %_$1%_ nicks %K[%n%_$2%_ ops, %_$3%_ voices, %_$4%_ normal%K]", 5, { 0, 1, 1, 1, 1 } }, + { "channel_created", "Channel %_$0%_ created $1", 2, { 0, 0 } }, + { "topic", "Topic for %c$0%K:%n $1", 2, { 0, 0 } }, + { "no_topic", "No topic set for %c$0", 1, { 0 } }, + { "new_topic", "%_$0%_ changed the topic of %c$1%n to%K:%n $2", 3, { 0, 0, 0 } }, + { "topic_unset", "Topic unset by %_$0%_ on %c$1", 2, { 0, 0 } }, + { "topic_info", "Topic set by %_$0%_ %K[%n$1%K]", 2, { 0, 0 } }, + { "chanmode_change", "mode/%c$0 %K[%n$1%K]%n by %_$2", 3, { 0, 0, 0 } }, + { "server_chanmode_change", "%RServerMode/%c$0 %K[%n$1%K]%n by %_$2", 3, { 0, 0, 0 } }, + { "channel_mode", "mode/%c$0 %K[%n$1%K]", 2, { 0, 0 } }, + { "bantype", "Ban type changed to %_$0", 1, { 0 } }, + { "banlist", "%_$0%_: ban %c$1", 2, { 0, 0 } }, + { "banlist_long", "%_$0%_: ban %c$1 %K[%nby %_$2%_, $3 secs ago%K]", 4, { 0, 0, 0, 1 } }, + { "ebanlist", "%_$0%_: ban exception %c$1", 2, { 0, 0 } }, + { "ebanlist_long", "%_$0%_: ban exception %c$1 %K[%nby %_$2%_, $3 secs ago%K]", 4, { 0, 0, 0, 1 } }, + { "invitelist", "%_$0%_: invite %c$1", 2, { 0, 0 } }, + { "no_such_channel", "$0: No such channel", 1, { 0 } }, + { "channel_synced", "Join to %_$0%_ was synced in %_$1%_ secs", 2, { 0, 2 } }, + { "not_in_channels", "You are not on any channels", 0 }, + { "current_channel", "Current channel $0", 1, { 0 } }, + { "chanlist_header", "You are on the following channels:", 0 }, + { "chanlist_line", "$[-10]0 %|+$1 ($2): $3", 4, { 0, 0, 0, 0 } }, + { "chansetup_not_found", "Channel $0 not found", 2, { 0, 0 } }, + { "chansetup_added", "Channel $0 saved", 2, { 0, 0 } }, + { "chansetup_removed", "Channel $0 removed", 2, { 0, 0 } }, + { "chansetup_header", "Channel IRC net Password Settings", 0 }, + { "chansetup_line", "$[15]0 %|$[10]1 $[10]2 $3", 4, { 0, 0, 0, 0 } }, + { "chansetup_footer", "", 0 }, - /* ---- */ - { NULL, "Nick", 0 }, + /* ---- */ + { NULL, "Nick", 0 }, - { "usermode_change", "Mode change %K[%n%_$0%_%K]%n for user %c$1", 2, { 0, 0 } }, - { "user_mode", "Your user mode is %K[%n%_$0%_%K]", 1, { 0 } }, - { "away", "You have been marked as being away", 0 }, - { "unaway", "You are no longer marked as being away", 0 }, - { "nick_away", "$0 is away: $1", 2, { 0, 0 } }, - { "no_such_nick", "$0: No such nick/channel", 1, { 0 } }, - { "your_nick", "Your nickname is $0", 1, { 0 } }, - { "your_nick_changed", "You're now known as %c$0", 1, { 0 } }, - { "nick_changed", "%_$0%_ is now known as %c$1", 2, { 0, 0 } }, - { "nick_in_use", "Nick %_$0%_ is already in use", 1, { 0 } }, - { "nick_unavailable", "Nick %_$0%_ is temporarily unavailable", 1, { 0 } }, - { "your_nick_owned", "Your nick is owned by %_$3%_ %K[%n$1@$2%K]", 4, { 0, 0, 0, 0 } }, + { "usermode_change", "Mode change %K[%n%_$0%_%K]%n for user %c$1", 2, { 0, 0 } }, + { "user_mode", "Your user mode is %K[%n%_$0%_%K]", 1, { 0 } }, + { "away", "You have been marked as being away", 0 }, + { "unaway", "You are no longer marked as being away", 0 }, + { "nick_away", "$0 is away: $1", 2, { 0, 0 } }, + { "no_such_nick", "$0: No such nick/channel", 1, { 0 } }, + { "your_nick", "Your nickname is $0", 1, { 0 } }, + { "your_nick_changed", "You're now known as %c$0", 1, { 0 } }, + { "nick_changed", "%_$0%_ is now known as %c$1", 2, { 0, 0 } }, + { "nick_in_use", "Nick %_$0%_ is already in use", 1, { 0 } }, + { "nick_unavailable", "Nick %_$0%_ is temporarily unavailable", 1, { 0 } }, + { "your_nick_owned", "Your nick is owned by %_$3%_ %K[%n$1@$2%K]", 4, { 0, 0, 0, 0 } }, - /* ---- */ - { NULL, "Who queries", 0 }, + /* ---- */ + { NULL, "Who queries", 0 }, - { "whois", "%_$0%_ %K[%n$1@$2%K]%n%: ircname : $3", 4, { 0, 0, 0, 0 } }, - { "whois_idle", " idle : $1 hours $2 mins $3 secs", 4, { 0, 1, 1, 1 } }, - { "whois_idle_signon", " idle : $1 hours $2 mins $3 secs %K[%nsignon: $4%K]", 5, { 0, 1, 1, 1, 0 } }, - { "whois_server", " server : $1 %K[%n$2%K]", 3, { 0, 0, 0 } }, - { "whois_oper", " : %_IRC operator%_", 1, { 0 } }, - { "whois_channels", " channels : $1", 2, { 0, 0 } }, - { "whois_away", " away : $1", 2, { 0, 0 } }, - { "end_of_whois", "End of WHOIS", 1, { 0 } }, - { "who", "$[-10]0 %|%_$[!9]1%_ $[!3]2 $[!2]3 $4@$5 %K(%W$6%K)", 7, { 0, 0, 0, 0, 0, 0, 0 } }, - { "end_of_who", "End of /WHO list", 1, { 0 } }, + { "whois", "%_$0%_ %K[%n$1@$2%K]%n%: ircname : $3", 4, { 0, 0, 0, 0 } }, + { "whois_idle", " idle : $1 hours $2 mins $3 secs", 4, { 0, 1, 1, 1 } }, + { "whois_idle_signon", " idle : $1 hours $2 mins $3 secs %K[%nsignon: $4%K]", 5, { 0, 1, 1, 1, 0 } }, + { "whois_server", " server : $1 %K[%n$2%K]", 3, { 0, 0, 0 } }, + { "whois_oper", " : %_IRC operator%_", 1, { 0 } }, + { "whois_channels", " channels : $1", 2, { 0, 0 } }, + { "whois_away", " away : $1", 2, { 0, 0 } }, + { "end_of_whois", "End of WHOIS", 1, { 0 } }, + { "who", "$[-10]0 %|%_$[!9]1%_ $[!3]2 $[!2]3 $4@$5 %K(%W$6%K)", 7, { 0, 0, 0, 0, 0, 0, 0 } }, + { "end_of_who", "End of /WHO list", 1, { 0 } }, - /* ---- */ - { NULL, "Your messages", 0 }, + /* ---- */ + { NULL, "Your messages", 0 }, - { "own_msg", "%K<%n$2%W$0%K>%n %|$1", 3, { 0, 0, 0 } }, - { "own_msg_channel", "%K<%n$3%W$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, - { "own_msg_private", "%K[%rmsg%K(%R$0%K)]%n $1", 2, { 0, 0 } }, - { "own_msg_private_query", "%K<%W$2%K>%n %|$1", 3, { 0, 0, 0 } }, - { "own_notice", "%K[%rnotice%K(%R$0%K)]%n $1", 2, { 0, 0 } }, - { "own_me", "%W * $0%n $1", 2, { 0, 0 } }, - { "own_ctcp", "%K[%rctcp%K(%R$0%K)]%n $1 $2", 3, { 0, 0, 0 } }, + { "own_msg", "%K<%n$2%W$0%K>%n %|$1", 3, { 0, 0, 0 } }, + { "own_msg_channel", "%K<%n$3%W$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, + { "own_msg_private", "%K[%rmsg%K(%R$0%K)]%n $1", 2, { 0, 0 } }, + { "own_msg_private_query", "%K<%W$2%K>%n %|$1", 3, { 0, 0, 0 } }, + { "own_notice", "%K[%rnotice%K(%R$0%K)]%n $1", 2, { 0, 0 } }, + { "own_me", "%W * $0%n $1", 2, { 0, 0 } }, + { "own_ctcp", "%K[%rctcp%K(%R$0%K)]%n $1 $2", 3, { 0, 0, 0 } }, - /* ---- */ - { NULL, "Received messages", 0 }, + /* ---- */ + { NULL, "Received messages", 0 }, - { "pubmsg_me", "%K<%n$2%Y$0%K>%n %|$1", 3, { 0, 0, 0 } }, - { "pubmsg_me_channel", "%K<%n$3%Y$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, - { "pubmsg_hilight", "%K<%n$3$0$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, - { "pubmsg_hilight_channel", "%K<%n$4$0$1%K:%c$2%K>%n %|$3", 5, { 0, 0, 0, 0, 0 } }, - { "pubmsg", "%K<%n$2$0%K>%n %|$1", 3, { 0, 0, 0 } }, - { "pubmsg_channel", "%K<%n$3$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, - { "msg_private", "%K[%R$0%K(%r$1%K)]%n $2", 3, { 0, 0, 0 } }, - { "msg_private_query", "%K<%R$0%K>%n %|$2", 3, { 0, 0, 0 } }, - { "notice_server", "%g!$0%n $1", 2, { 0, 0 } }, - { "notice_public", "%K-%M$0%K:%m$1%K-%n $2", 3, { 0, 0, 0 } }, - { "notice_public_ops", "%K-%M$0%K:%m@$1%K-%n $2", 3, { 0, 0, 0 } }, - { "notice_private", "%K-%M$0%K(%m$1%K)-%n $2", 3, { 0, 0, 0 } }, - { "action_private", "%W (*) $0%n $2", 3, { 0, 0, 0 } }, - { "action_private_query", "%W * $0%n $2", 3, { 0, 0, 0 } }, - { "action_public", "%W * $0%n $1", 2, { 0, 0 } }, - { "action_public_channel", "%W * $0%K:%c$1%n $2", 3, { 0, 0, 0 } }, + { "pubmsg_me", "%K<%n$2%Y$0%K>%n %|$1", 3, { 0, 0, 0 } }, + { "pubmsg_me_channel", "%K<%n$3%Y$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, + { "pubmsg_hilight", "%K<%n$3$0$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, + { "pubmsg_hilight_channel", "%K<%n$4$0$1%K:%c$2%K>%n %|$3", 5, { 0, 0, 0, 0, 0 } }, + { "pubmsg", "%K<%n$2$0%K>%n %|$1", 3, { 0, 0, 0 } }, + { "pubmsg_channel", "%K<%n$3$0%K:%c$1%K>%n %|$2", 4, { 0, 0, 0, 0 } }, + { "msg_private", "%K[%R$0%K(%r$1%K)]%n $2", 3, { 0, 0, 0 } }, + { "msg_private_query", "%K<%R$0%K>%n %|$2", 3, { 0, 0, 0 } }, + { "notice_server", "%g!$0%n $1", 2, { 0, 0 } }, + { "notice_public", "%K-%M$0%K:%m$1%K-%n $2", 3, { 0, 0, 0 } }, + { "notice_public_ops", "%K-%M$0%K:%m@$1%K-%n $2", 3, { 0, 0, 0 } }, + { "notice_private", "%K-%M$0%K(%m$1%K)-%n $2", 3, { 0, 0, 0 } }, + { "action_private", "%W (*) $0%n $2", 3, { 0, 0, 0 } }, + { "action_private_query", "%W * $0%n $2", 3, { 0, 0, 0 } }, + { "action_public", "%W * $0%n $1", 2, { 0, 0 } }, + { "action_public_channel", "%W * $0%K:%c$1%n $2", 3, { 0, 0, 0 } }, - /* ---- */ - { NULL, "CTCPs", 0 }, + /* ---- */ + { NULL, "CTCPs", 0 }, - { "ctcp_reply", "CTCP %_$0%_ reply from %_$1%_%K:%n $2", 3, { 0, 0, 0 } }, - { "ctcp_reply_channel", "CTCP %_$0%_ reply from %_$1%_ in channel %_$4%_%K:%n $2", 4, { 0, 0, 0, 0 } }, - { "ctcp_ping_reply", "CTCP %_PING%_ reply from %_$0%_: $1.$2 seconds", 3, { 0, 2, 2 } }, - { "ctcp_requested", "%g>>> %_$0%_ %K[%g$1%K] %grequested %_$2%_ from %_$3", 4, { 0, 0, 0, 0 } }, + { "ctcp_reply", "CTCP %_$0%_ reply from %_$1%_%K:%n $2", 3, { 0, 0, 0 } }, + { "ctcp_reply_channel", "CTCP %_$0%_ reply from %_$1%_ in channel %_$4%_%K:%n $2", 4, { 0, 0, 0, 0 } }, + { "ctcp_ping_reply", "CTCP %_PING%_ reply from %_$0%_: $1.$2 seconds", 3, { 0, 2, 2 } }, + { "ctcp_requested", "%g>>> %_$0%_ %K[%g$1%K] %grequested %_$2%_ from %_$3", 4, { 0, 0, 0, 0 } }, - /* ---- */ - { NULL, "Other server events", 0 }, + /* ---- */ + { NULL, "Other server events", 0 }, - { "online", "Users online: %_$0", 1, { 0 } }, - { "pong", "PONG received from $0: $1", 2, { 0, 0 } }, - { "wallops", "%WWALLOP%n $0: $1", 2, { 0, 0 } }, - { "action_wallops", "%WWALLOP * $0%n $1", 2, { 0, 0 } }, - { "error", "%_ERROR%_ $0", 1, { 0 } }, - { "unknown_mode", "Unknown mode character $0", 1, { 0 } }, - { "not_chanop", "You're not channel operator in $0", 1, { 0 } }, + { "online", "Users online: %_$0", 1, { 0 } }, + { "pong", "PONG received from $0: $1", 2, { 0, 0 } }, + { "wallops", "%WWALLOP%n $0: $1", 2, { 0, 0 } }, + { "action_wallops", "%WWALLOP * $0%n $1", 2, { 0, 0 } }, + { "error", "%_ERROR%_ $0", 1, { 0 } }, + { "unknown_mode", "Unknown mode character $0", 1, { 0 } }, + { "not_chanop", "You're not channel operator in $0", 1, { 0 } }, - /* ---- */ - { NULL, "Misc", 0 }, + /* ---- */ + { NULL, "Misc", 0 }, - { "ignored", "Ignoring %_$1%_ from %_$0%_", 2, { 0, 0 } }, - { "unignored", "Unignored %_$0%_", 1, { 0 } }, - { "ignore_not_found", "%_$0%_ is not being ignored", 1, { 0 } }, - { "ignore_no_ignores", "There are no ignores", 0 }, - { "ignore_header", "Ignorance List:", 0 }, - { "ignore_line", "$[-4]0 $1: $2 $3 $4", 5, { 1, 0, 0, 0, 0 } }, - { "ignore_footer", "", 0 }, - { "talking_in", "You are now talking in %_$0%_", 1, { 0 } }, - { "no_query", "No query with %_$0%_", 1, { 0 } }, - { "no_msgs_got", "You have not received a message from anyone yet", 0 }, - { "no_msgs_sent", "You have not sent a message to anyone yet", 0 } -}; + { "ignored", "Ignoring %_$1%_ from %_$0%_", 2, { 0, 0 } }, + { "unignored", "Unignored %_$0%_", 1, { 0 } }, + { "ignore_not_found", "%_$0%_ is not being ignored", 1, { 0 } }, + { "ignore_no_ignores", "There are no ignores", 0 }, + { "ignore_header", "Ignorance List:", 0 }, + { "ignore_line", "$[-4]0 $1: $2 $3 $4", 5, { 1, 0, 0, 0, 0 } }, + { "ignore_footer", "", 0 }, + { "talking_in", "You are now talking in %_$0%_", 1, { 0 } }, + { "no_query", "No query with %_$0%_", 1, { 0 } }, + { "no_msgs_got", "You have not received a message from anyone yet", 0 }, + { "no_msgs_sent", "You have not sent a message to anyone yet", 0 }, + + { NULL, NULL, 0 } diff --git a/src/fe-common/irc/module-formats.h b/src/fe-common/irc/module-formats.h index ea615d2d..b811a2de 100644 --- a/src/fe-common/irc/module-formats.h +++ b/src/fe-common/irc/module-formats.h @@ -162,6 +162,3 @@ enum { }; extern FORMAT_REC fecommon_irc_formats[]; -#define MODULE_FORMATS fecommon_irc_formats - -#include "printformat.h" diff --git a/src/fe-common/irc/notifylist/Makefile.am b/src/fe-common/irc/notifylist/Makefile.am index c44da278..53dd7374 100644 --- a/src/fe-common/irc/notifylist/Makefile.am +++ b/src/fe-common/irc/notifylist/Makefile.am @@ -13,5 +13,6 @@ libfe_common_irc_notifylist_la_SOURCES = \ fe-notifylist.c \ module-formats.c -noinst_headers = \ +noinst_HEADERS = \ + module.h \ module-formats.h diff --git a/src/fe-common/irc/notifylist/fe-notifylist.c b/src/fe-common/irc/notifylist/fe-notifylist.c index 7520cdb8..3a799de3 100644 --- a/src/fe-common/irc/notifylist/fe-notifylist.c +++ b/src/fe-common/irc/notifylist/fe-notifylist.c @@ -31,6 +31,8 @@ #include "ircnet-setup.h" #include "irc/notifylist/notifylist.h" +#include "themes.h" + /* add the nick of a hostmask to list if it isn't there already */ static GSList *mask_add_once(GSList *list, const char *mask) { @@ -224,6 +226,8 @@ static void notifylist_unidle(IRC_SERVER_REC *server, const char *nick, void fe_notifylist_init(void) { + theme_register(fecommon_irc_notifylist_formats); + command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify); signal_add("notifylist joined", (SIGNAL_FUNC) notifylist_joined); signal_add("notifylist left", (SIGNAL_FUNC) notifylist_left); @@ -233,6 +237,8 @@ void fe_notifylist_init(void) void fe_notifylist_deinit(void) { + theme_unregister(); + command_unbind("notify", (SIGNAL_FUNC) cmd_notify); signal_remove("notifylist joined", (SIGNAL_FUNC) notifylist_joined); signal_remove("notifylist left", (SIGNAL_FUNC) notifylist_left); diff --git a/src/fe-common/irc/notifylist/module-formats.c b/src/fe-common/irc/notifylist/module-formats.c index 7a673457..e369d52c 100644 --- a/src/fe-common/irc/notifylist/module-formats.c +++ b/src/fe-common/irc/notifylist/module-formats.c @@ -23,17 +23,19 @@ FORMAT_REC fecommon_irc_notifylist_formats[] = { - { MODULE_NAME, "Notifylist", 0 }, + { MODULE_NAME, "Notifylist", 0 }, - /* ---- */ - { NULL, "Notifylist", 0 }, + /* ---- */ + { NULL, "Notifylist", 0 }, - { "notify_join", "%_$0%_ %K[%n$1@$2%K] [%n%_$3%_%K]%n has joined to $4", 5, { 0, 0, 0, 0, 0 } }, - { "notify_part", "%_$0%_ has left $4", 5, { 0, 0, 0, 0, 0 } }, - { "notify_away", "%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now away: $4", 6, { 0, 0, 0, 0, 0, 0 } }, - { "notify_unaway", "%_$0%_ %K[%n$4%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now unaway", 5, { 0, 0, 0, 0, 0 } }, - { "notify_unidle", "%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n just stopped idling", 6, { 0, 0, 0, 0, 0, 0 } }, - { "notify_online", "On $0: %_$1%_", 2, { 0, 0 } }, - { "notify_offline", "Offline: $0", 1, { 0 } }, - { "notify_list", "$0: $1 $2 $3", 4, { 0, 0, 0, 0 } } + { "notify_join", "%_$0%_ %K[%n$1@$2%K] [%n%_$3%_%K]%n has joined to $4", 5, { 0, 0, 0, 0, 0 } }, + { "notify_part", "%_$0%_ has left $4", 5, { 0, 0, 0, 0, 0 } }, + { "notify_away", "%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now away: $4", 6, { 0, 0, 0, 0, 0, 0 } }, + { "notify_unaway", "%_$0%_ %K[%n$4%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now unaway", 5, { 0, 0, 0, 0, 0 } }, + { "notify_unidle", "%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n just stopped idling", 6, { 0, 0, 0, 0, 0, 0 } }, + { "notify_online", "On $0: %_$1%_", 2, { 0, 0 } }, + { "notify_offline", "Offline: $0", 1, { 0 } }, + { "notify_list", "$0: $1 $2 $3", 4, { 0, 0, 0, 0 } }, + + { NULL, NULL, 0 }, }; diff --git a/src/fe-common/irc/notifylist/module-formats.h b/src/fe-common/irc/notifylist/module-formats.h index f5f855dc..e37045f1 100644 --- a/src/fe-common/irc/notifylist/module-formats.h +++ b/src/fe-common/irc/notifylist/module-formats.h @@ -16,6 +16,3 @@ enum { }; extern FORMAT_REC fecommon_irc_notifylist_formats[]; -#define MODULE_FORMATS fecommon_irc_notifylist_formats - -#include "printformat.h" diff --git a/src/fe-common/irc/notifylist/module.h b/src/fe-common/irc/notifylist/module.h new file mode 100644 index 00000000..00aa01e3 --- /dev/null +++ b/src/fe-common/irc/notifylist/module.h @@ -0,0 +1,3 @@ +#include "common.h" + +#define MODULE_NAME "fe-common/irc/notifylist" diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 59e00d52..c68b257d 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -35,277 +35,272 @@ static gint mirc_colors[] = { 15, 0, 1, 2, 4, 6, 5, 4, 14, 10, 3, 11, 9, 13, 8, 7, 15 }; static gint max_textwidget_lines; -static LINE_REC *create_line(GUI_WINDOW_REC *gui, gint level) +#define mark_temp_eol(text) \ + memcpy((text)->buffer + (text)->pos, "\0\x80", 2); + +static LINE_REC *create_line(GUI_WINDOW_REC *gui, int level) { - g_return_val_if_fail(gui != NULL, NULL); - g_return_val_if_fail(gui->cur_text != NULL, NULL); + g_return_val_if_fail(gui != NULL, NULL); + g_return_val_if_fail(gui->cur_text != NULL, NULL); - gui->cur_line = g_mem_chunk_alloc(gui->line_chunk); - gui->cur_line->text = gui->cur_text->buffer+gui->cur_text->pos; - gui->cur_line->level = (gint32) GPOINTER_TO_INT(level); - gui->cur_line->time = time(NULL); + gui->cur_line = g_mem_chunk_alloc(gui->line_chunk); + gui->cur_line->text = gui->cur_text->buffer+gui->cur_text->pos; + gui->cur_line->level = GPOINTER_TO_INT(level); + gui->cur_line->time = time(NULL); - /* temporarily mark the end of line. */ - memcpy(gui->cur_text->buffer+gui->cur_text->pos, "\0\x80", 2); + mark_temp_eol(gui->cur_text); - gui->last_color = -1; - gui->last_flags = 0; + gui->last_color = -1; + gui->last_flags = 0; - gui->lines = g_list_append(gui->lines, gui->cur_line); - if (gui->startline == NULL) - { - gui->startline = gui->lines; - gui->bottom_startline = gui->lines; - } - return gui->cur_line; + gui->lines = g_list_append(gui->lines, gui->cur_line); + if (gui->startline == NULL) { + /* first line */ + gui->startline = gui->lines; + gui->bottom_startline = gui->lines; + } + return gui->cur_line; } static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui) { - TEXT_CHUNK_REC *rec; - guchar *buffer; - gchar *ptr; + TEXT_CHUNK_REC *rec; + char *buffer, *ptr; - g_return_val_if_fail(gui != NULL, NULL); + g_return_val_if_fail(gui != NULL, NULL); - rec = g_new(TEXT_CHUNK_REC, 1); - rec->overflow[0] = 0; - rec->overflow[1] = (char) LINE_CMD_OVERFLOW; - rec->pos = 0; - rec->lines = 0; + rec = g_new(TEXT_CHUNK_REC, 1); + rec->overflow[0] = 0; + rec->overflow[1] = (char) LINE_CMD_OVERFLOW; + rec->pos = 0; + rec->lines = 0; - if (gui->cur_line != NULL && gui->cur_line->text != NULL) - { - /* mark the next block text block position.. */ - buffer = (guchar *) gui->cur_text->buffer+gui->cur_text->pos; - if (gui->cur_text->pos+2+sizeof(gchar *) > LINE_TEXT_CHUNK_SIZE) - g_error("create_text_chunk() : buffer overflow?!"); - *buffer++ = 0; *buffer++ = LINE_CMD_CONTINUE; - ptr = rec->buffer; - memcpy(buffer, &ptr, sizeof(gchar *)); - } - gui->cur_text = rec; - gui->text_chunks = g_slist_append(gui->text_chunks, rec); - return rec; + if (gui->cur_line != NULL && gui->cur_line->text != NULL) { + /* create a link to new block from the old block */ + buffer = gui->cur_text->buffer + gui->cur_text->pos; + *buffer++ = 0; *buffer++ = (char) LINE_CMD_CONTINUE; + + ptr = rec->buffer; + memcpy(buffer, &ptr, sizeof(char *)); + } + + gui->cur_text = rec; + gui->text_chunks = g_slist_append(gui->text_chunks, rec); + return rec; } static void text_chunk_free(GUI_WINDOW_REC *gui, TEXT_CHUNK_REC *chunk) { - g_return_if_fail(gui != NULL); - g_return_if_fail(chunk != NULL); + g_return_if_fail(gui != NULL); + g_return_if_fail(chunk != NULL); - gui->text_chunks = g_slist_remove(gui->text_chunks, chunk); - g_free(chunk); + gui->text_chunks = g_slist_remove(gui->text_chunks, chunk); + g_free(chunk); } static void remove_first_line(WINDOW_REC *window) { - GUI_WINDOW_REC *gui; - TEXT_CHUNK_REC *chunk; + GUI_WINDOW_REC *gui; + TEXT_CHUNK_REC *chunk; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - gui = WINDOW_GUI(window); - chunk = gui->text_chunks->data; + gui = WINDOW_GUI(window); + chunk = gui->text_chunks->data; - if (--chunk->lines == 0) - text_chunk_free(gui, chunk); + if (--chunk->lines == 0) + text_chunk_free(gui, chunk); - if (gui->startline->prev == NULL) - { - gui->startline = gui->startline->next; - gui->subline = 0; - } - if (gui->bottom_startline->prev == NULL) - { - gui->bottom_startline = gui->bottom_startline->next; - gui->bottom_subline = 0; - } + if (gui->startline->prev == NULL) { + /* first line in screen removed */ + gui->startline = gui->startline->next; + gui->subline = 0; + } + if (gui->bottom_startline->prev == NULL) { + /* bottom line removed (shouldn't happen?) */ + gui->bottom_startline = gui->bottom_startline->next; + gui->bottom_subline = 0; + } - window->lines--; - g_mem_chunk_free(gui->line_chunk, gui->lines->data); - gui->lines = g_list_remove(gui->lines, gui->lines->data); + window->lines--; + g_mem_chunk_free(gui->line_chunk, gui->lines->data); + gui->lines = g_list_remove(gui->lines, gui->lines->data); - if (gui->startline->prev == NULL && is_window_visible(window)) - gui_window_redraw(window); + if (gui->startline->prev == NULL && is_window_visible(window)) + gui_window_redraw(window); } -static void get_colors(gint flags, gint *fg, gint *bg) +static void get_colors(int flags, int *fg, int *bg) { - if (flags & PRINTFLAG_MIRC_COLOR) - { - /* mirc colors */ - *fg = *fg < 0 || *fg > 16 ? - current_theme->default_color : mirc_colors[*fg]; - *bg = *bg < 0 || *bg > 16 ? 0 : mirc_colors[*bg]; - } - else - { - /* default colors */ - *fg = *fg < 0 || *fg > 15 ? - current_theme->default_color : *fg; - *bg = *bg < 0 || *bg > 15 ? 0 : *bg; + if (flags & PRINTFLAG_MIRC_COLOR) { + /* mirc colors */ + *fg = *fg < 0 || *fg > 16 ? + current_theme->default_color : mirc_colors[*fg]; + *bg = *bg < 0 || *bg > 16 ? 0 : mirc_colors[*bg]; + } else { + /* default colors */ + *fg = *fg < 0 || *fg > 15 ? + current_theme->default_color : *fg; + *bg = *bg < 0 || *bg > 15 ? 0 : *bg; - if (*fg > 8) *fg -= 8; - } + if (*fg > 8) *fg -= 8; + } - if (flags & PRINTFLAG_REVERSE) - { - gint tmp; + if (flags & PRINTFLAG_REVERSE) { + int tmp; - tmp = *fg; *fg = *bg; *bg = tmp; - } + tmp = *fg; *fg = *bg; *bg = tmp; + } - if (*fg == 8) *fg |= ATTR_COLOR8; - if (flags & PRINTFLAG_BOLD) *fg |= 8; - if (flags & PRINTFLAG_UNDERLINE) *fg |= ATTR_UNDERLINE; - if (flags & PRINTFLAG_BLINK) *bg |= 0x80; + if (*fg == 8) *fg |= ATTR_COLOR8; + if (flags & PRINTFLAG_BOLD) *fg |= 8; + if (flags & PRINTFLAG_UNDERLINE) *fg |= ATTR_UNDERLINE; + if (flags & PRINTFLAG_BLINK) *bg |= 0x80; } -static void linebuf_add(GUI_WINDOW_REC *gui, gchar *str, gint len) +static void linebuf_add(GUI_WINDOW_REC *gui, char *str, int len) { - gint left; + int left; - if (len == 0) return; + if (len == 0) return; - while (gui->cur_text->pos+len >= TEXT_CHUNK_USABLE_SIZE) - { - left = TEXT_CHUNK_USABLE_SIZE-gui->cur_text->pos; - if (str[left-1] == 0) left--; /* don't split the command! */ - memcpy(gui->cur_text->buffer+gui->cur_text->pos, str, left); - gui->cur_text->pos += left; - create_text_chunk(gui); - len -= left; str += left; - } + while (gui->cur_text->pos + len >= TEXT_CHUNK_USABLE_SIZE) { + left = TEXT_CHUNK_USABLE_SIZE - gui->cur_text->pos; + if (str[left-1] == 0) left--; /* don't split the commands */ - memcpy(gui->cur_text->buffer+gui->cur_text->pos, str, len); - gui->cur_text->pos += len; + memcpy(gui->cur_text->buffer + gui->cur_text->pos, str, left); + gui->cur_text->pos += left; + + create_text_chunk(gui); + len -= left; str += left; + } + + memcpy(gui->cur_text->buffer + gui->cur_text->pos, str, len); + gui->cur_text->pos += len; } -static void line_add_colors(GUI_WINDOW_REC *gui, gint fg, gint bg, gint flags) +static void line_add_colors(GUI_WINDOW_REC *gui, int fg, int bg, int flags) { - guchar buffer[12]; - gint color, pos; + unsigned char buffer[12]; + int color, pos; - color = (fg & 0x0f) | (bg << 4); - pos = 0; + color = (fg & 0x0f) | (bg << 4); + pos = 0; - if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != gui->last_color) || - ((fg & ATTR_COLOR8) && (fg & 0xf0) != (gui->last_color & 0xf0))) - { - buffer[pos++] = 0; - buffer[pos++] = (gchar) color; - } + if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != gui->last_color) || + ((fg & ATTR_COLOR8) && (fg & 0xf0) != (gui->last_color & 0xf0))) { + buffer[pos++] = 0; + buffer[pos++] = color; + } - if ((flags & PRINTFLAG_UNDERLINE) != (gui->last_flags & PRINTFLAG_UNDERLINE)) - { - buffer[pos++] = 0; - buffer[pos++] = LINE_CMD_UNDERLINE; - } - if (fg & ATTR_COLOR8) - { - buffer[pos++] = 0; - buffer[pos++] = LINE_CMD_COLOR8; - } - if (flags & PRINTFLAG_BEEP) - { - buffer[pos++] = 0; - buffer[pos++] = LINE_CMD_BEEP; - } - if (flags & PRINTFLAG_INDENT) - { - buffer[pos++] = 0; - buffer[pos++] = LINE_CMD_INDENT; - } + if ((flags & PRINTFLAG_UNDERLINE) != (gui->last_flags & PRINTFLAG_UNDERLINE)) { + buffer[pos++] = 0; + buffer[pos++] = LINE_CMD_UNDERLINE; + } + if (fg & ATTR_COLOR8) { + buffer[pos++] = 0; + buffer[pos++] = LINE_CMD_COLOR8; + } + if (flags & PRINTFLAG_BEEP) { + buffer[pos++] = 0; + buffer[pos++] = LINE_CMD_BEEP; + } + if (flags & PRINTFLAG_INDENT) { + buffer[pos++] = 0; + buffer[pos++] = LINE_CMD_INDENT; + } - linebuf_add(gui, (gchar *) buffer, pos); + linebuf_add(gui, (char *) buffer, pos); - gui->last_flags = flags; - gui->last_color = fg | (bg << 4); + gui->last_flags = flags; + gui->last_color = fg | (bg << 4); } -static void gui_printtext(WINDOW_REC *window, gpointer fgcolor, gpointer bgcolor, gpointer pflags, gchar *str, gpointer level) +static void gui_printtext(WINDOW_REC *window, gpointer fgcolor, gpointer bgcolor, gpointer pflags, char *str, gpointer level) { - GUI_WINDOW_REC *gui; - LINE_REC *line; - gboolean visible; - gint fg, bg, flags, lines, n; + GUI_WINDOW_REC *gui; + LINE_REC *line; + int fg, bg, flags, new_lines, n, visible, ypos; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - gui = WINDOW_GUI(window); - if (max_textwidget_lines > 0 && max_textwidget_lines <= window->lines) - remove_first_line(window); + gui = WINDOW_GUI(window); + if (max_textwidget_lines > 0 && max_textwidget_lines <= window->lines) + remove_first_line(window); - visible = is_window_visible(window) && gui->bottom; - flags = GPOINTER_TO_INT(pflags); - fg = GPOINTER_TO_INT(fgcolor); - bg = GPOINTER_TO_INT(bgcolor); + visible = is_window_visible(window) && gui->bottom; + flags = GPOINTER_TO_INT(pflags); + fg = GPOINTER_TO_INT(fgcolor); + bg = GPOINTER_TO_INT(bgcolor); - if (gui->cur_text == NULL) - create_text_chunk(gui); + if (gui->cur_text == NULL) + create_text_chunk(gui); - /* \n can be only at the start of the line.. */ - if (*str == '\n') - { - linebuf_add(gui, "\0\x80", 2); /* mark EOL */ - line = create_line(gui, 0); - gui_window_newline(gui, visible); - str++; - gui->cur_text->lines++; - gui->last_subline = 0; - } - else - { - line = gui->cur_line != NULL ? gui->cur_line : - create_line(gui, 0); - if (line->level == 0) line->level = GPOINTER_TO_INT(level); - } + /* \n can be only at the start of the line.. */ + if (*str == '\n') { + str++; + linebuf_add(gui, "\0\x80", 2); /* mark EOL */ - get_colors(flags, &fg, &bg); - line_add_colors(gui, fg, bg, flags); - linebuf_add(gui, str, strlen(str)); + line = create_line(gui, 0); + gui_window_newline(gui, visible); - /* temporarily mark the end of line. */ - memcpy(gui->cur_text->buffer+gui->cur_text->pos, "\0\x80", 2); + gui->cur_text->lines++; + gui->last_subline = 0; + } else { + line = gui->cur_line != NULL ? gui->cur_line : + create_line(gui, 0); + if (line->level == 0) line->level = GPOINTER_TO_INT(level); + } - if (visible) - { - /* draw the line to screen. */ - lines = gui_window_line_draw(gui, line, gui->parent->first_line+gui->ypos, gui->last_subline, -1); - } - else - { - /* we still need to update the bottom's position */ - lines = gui_window_get_linecount(gui, line)-1-gui->last_subline; - for (n = 0; n < lines; n++) - gui_window_newline(gui, visible); - } - if (lines > 0) gui->last_subline += lines; + get_colors(flags, &fg, &bg); + line_add_colors(gui, fg, bg, flags); + linebuf_add(gui, str, strlen(str)); + mark_temp_eol(gui->cur_text); + + gui_window_cache_remove(gui, line); + new_lines = gui_window_get_linecount(gui, line)-1 - gui->last_subline; + + for (n = 0; n < new_lines; n++) + gui_window_newline(gui, visible); + + if (visible) { + /* draw the line to screen. */ + ypos = gui->parent->first_line+gui->ypos-new_lines; + if (new_lines > 0) { + set_color(0); + move(ypos, 0); clrtoeol(); + } + gui_window_line_draw(gui, line, ypos, gui->last_subline, -1); + } + + gui->last_subline += new_lines; } -static void cmd_clear(gchar *data) +static void window_clear(GUI_WINDOW_REC *gui) { - GUI_WINDOW_REC *gui; - gint n; + int n; - gui = WINDOW_GUI(active_win); + for (n = gui->parent->first_line; n <= gui->parent->last_line; n++) { + move(n, 0); + clrtoeol(); + } + screen_refresh(); +} - if (is_window_visible(active_win)) - { - for (n = gui->parent->first_line; n <= gui->parent->last_line; n++) - { - move(n, 0); - clrtoeol(); - } - screen_refresh(); - } +static void cmd_clear(void) +{ + GUI_WINDOW_REC *gui; - gui->ypos = -1; - gui->bottom_startline = gui->startline = g_list_last(gui->lines); - gui->bottom_subline = gui->subline = gui->last_subline+1; - gui->empty_linecount = gui->parent->last_line-gui->parent->first_line+1; - gui->bottom = TRUE; + gui = WINDOW_GUI(active_win); + + if (is_window_visible(active_win)) + window_clear(gui); + + gui->ypos = -1; + gui->bottom_startline = gui->startline = g_list_last(gui->lines); + gui->bottom_subline = gui->subline = gui->last_subline+1; + gui->empty_linecount = gui->parent->last_line-gui->parent->first_line+1; + gui->bottom = TRUE; } static void sig_printtext_finished(WINDOW_REC *window) @@ -321,18 +316,18 @@ static void read_settings(void) void gui_printtext_init(void) { - signal_add("gui print text", (SIGNAL_FUNC) gui_printtext); - command_bind("clear", NULL, (SIGNAL_FUNC) cmd_clear); - signal_add("print text finished", (SIGNAL_FUNC) sig_printtext_finished); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); + signal_add("gui print text", (SIGNAL_FUNC) gui_printtext); + signal_add("print text finished", (SIGNAL_FUNC) sig_printtext_finished); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); + command_bind("clear", NULL, (SIGNAL_FUNC) cmd_clear); - read_settings(); + read_settings(); } void gui_printtext_deinit(void) { - signal_remove("gui print text", (SIGNAL_FUNC) gui_printtext); - command_unbind("clear", (SIGNAL_FUNC) cmd_clear); - signal_remove("print text finished", (SIGNAL_FUNC) sig_printtext_finished); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + signal_remove("gui print text", (SIGNAL_FUNC) gui_printtext); + signal_remove("print text finished", (SIGNAL_FUNC) sig_printtext_finished); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + command_unbind("clear", (SIGNAL_FUNC) cmd_clear); } diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c index 60956cce..64d06e98 100644 --- a/src/fe-text/gui-windows.c +++ b/src/fe-text/gui-windows.c @@ -46,6 +46,7 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window, MAIN_WINDOW_REC *pare gui->parent = parent; gui->bottom = TRUE; + gui->line_cache = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); gui->line_chunk = g_mem_chunk_new("line chunk", sizeof(LINE_REC), sizeof(LINE_REC)*100, G_ALLOC_AND_FREE); gui->empty_linecount = parent->last_line-parent->first_line; @@ -53,8 +54,19 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window, MAIN_WINDOW_REC *pare return gui; } +int line_cache_destroy(void *key, LINE_CACHE_REC *cache) +{ + g_free_not_null(cache->lines); + g_free(cache); + + return TRUE; +} + static void gui_window_deinit(GUI_WINDOW_REC *gui) { + g_hash_table_foreach(gui->line_cache, (GHFunc) line_cache_destroy, NULL); + g_hash_table_destroy(gui->line_cache); + g_slist_foreach(gui->text_chunks, (GFunc) g_free, NULL); g_slist_free(gui->text_chunks); @@ -106,7 +118,7 @@ static void gui_window_destroyed(WINDOW_REC *window) gui_window_deinit(gui); window->gui_data = NULL; - if (mainwindows->next != NULL && parent->active == window) + if (parent->active == window && mainwindows->next != NULL) mainwindow_destroy(parent); } @@ -126,322 +138,337 @@ void gui_window_clear(WINDOW_REC *window) gui_window_redraw(window); } -int gui_window_update_bottom(GUI_WINDOW_REC *gui, int lines) +/* update bottom_startline and bottom_subline of window. */ +static int gui_window_update_bottom(GUI_WINDOW_REC *gui, int lines) { - int linecount, last_linecount; + int linecount, last_linecount; - if (gui->bottom_startline == NULL) - return -1; - - while (lines < 0) - { - if (gui->bottom_subline > 0) - gui->bottom_subline--; - else - { - if (gui->bottom_startline->prev == NULL) + if (gui->bottom_startline == NULL) return -1; - gui->bottom_startline = gui->bottom_startline->prev; - linecount = gui_window_get_linecount(gui, gui->bottom_startline->data); - gui->bottom_subline = linecount-1; - } - lines++; - } - - last_linecount = linecount = -1; - while (lines > 0) - { - if (linecount == -1) - last_linecount = linecount = gui_window_get_linecount(gui, gui->bottom_startline->data); - - if (linecount > gui->bottom_subline+1) - gui->bottom_subline++; - else - { - gui->bottom_subline = 0; - linecount = -1; - - if (gui->bottom_startline->next == NULL) - break; - gui->bottom_startline = gui->bottom_startline->next; - } - lines--; - } - - return last_linecount; -} - -void gui_window_newline(GUI_WINDOW_REC *gui, gboolean visible) -{ - gboolean last_line; - gint linecount; - - g_return_if_fail(gui != NULL); - - gui->xpos = 0; - last_line = gui->ypos >= gui->parent->last_line-gui->parent->first_line; - - if (gui->empty_linecount > 0) - { - /* window buffer height isn't even the size of the screen yet */ - gui->empty_linecount--; - linecount = gui_window_get_linecount(gui, gui->startline->data); - } - else - { - linecount = gui_window_update_bottom(gui, 1); - } - - if (!last_line || !gui->bottom) - { - gui->ypos++; - } - else if (gui->bottom) - { - if (gui->subline >= linecount) - { - /* after screen gets full after /CLEAR we end up here.. */ - gui->startline = gui->startline->next; - gui->subline = 0; - - linecount = gui_window_update_bottom(gui, 1); - } - - if (linecount > 1+gui->subline) - gui->subline++; - else - { - gui->startline = gui->startline->next; - gui->subline = 0; - } - - if (visible) - { - scroll_up(gui->parent->first_line, gui->parent->last_line); - move(gui->parent->last_line, 0); clrtoeol(); - } - } -} - -/* get number of real lines that line record takes - this really should share - at least some code with gui_window_line_draw().. */ -gint gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line) -{ - gchar *ptr, *last_space_ptr, *tmp; - gint lines, xpos, indent_pos, last_space; - - g_return_val_if_fail(gui != NULL, -1); - g_return_val_if_fail(line != NULL, -1); - - if (line->text == NULL) - return 0; - - xpos = 0; lines = 1; indent_pos = DEFAULT_INDENT_POS; - last_space = 0; last_space_ptr = NULL; - for (ptr = line->text;; ptr++) - { - if (*ptr == '\0') - { - /* command */ - ptr++; - switch ((guchar) *ptr) - { - case LINE_CMD_OVERFLOW: - g_error("buffer overflow!"); - case LINE_CMD_EOL: - return lines; - case LINE_CMD_CONTINUE: - memcpy(&tmp, ptr+1, sizeof(gchar *)); - ptr = tmp-1; - break; - case LINE_CMD_INDENT: - indent_pos = xpos; - break; - } - continue; - } - - if (xpos == COLS) - { - xpos = indent_pos >= COLS-5 ? DEFAULT_INDENT_POS : indent_pos; - - if (last_space > indent_pos && last_space > 10) - { - ptr = last_space_ptr; - while (*ptr == ' ') ptr++; - } - - last_space = 0; - lines++; - ptr--; - continue; - } - - xpos++; - if (*ptr == ' ') - { - last_space = xpos-1; - last_space_ptr = ptr+1; - } - } -} - -/* draw line - ugly code.. */ -gint gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, gint ypos, gint skip, gint max) -{ - gchar *ptr, *last_space_ptr, *tmp; - gint lines, xpos, color, indent_pos, last_space, last_space_color; - - g_return_val_if_fail(gui != NULL, -1); - g_return_val_if_fail(line != NULL, -1); - - if (line->text == NULL) - return 0; - - move(ypos, 0); - xpos = 0; color = 0; lines = -1; indent_pos = DEFAULT_INDENT_POS; - last_space = last_space_color = 0; last_space_ptr = NULL; - for (ptr = line->text;; ptr++) - { - if (*ptr == '\0') - { - /* command */ - ptr++; - if ((*ptr & 0x80) == 0) - { - /* set color */ - color = (color & ATTR_UNDERLINE) | *ptr; - } - else switch ((guchar) *ptr) - { - case LINE_CMD_OVERFLOW: - g_error("buffer overflow!"); - case LINE_CMD_EOL: - return lines; - case LINE_CMD_CONTINUE: - memcpy(&tmp, ptr+1, sizeof(gchar *)); - ptr = tmp-1; - break; - case LINE_CMD_UNDERLINE: - color ^= ATTR_UNDERLINE; - break; - case LINE_CMD_COLOR8: - color &= 0xfff0; - color |= 8|ATTR_COLOR8; - break; - case LINE_CMD_BEEP: - beep(); - break; - case LINE_CMD_INDENT: - indent_pos = xpos; - break; - } - set_color(color); - continue; - } - - if (xpos == COLS) - { - xpos = indent_pos >= COLS-5 ? DEFAULT_INDENT_POS : indent_pos; - - if (last_space > indent_pos && last_space > 10) - { - /* remove the last word */ - if (!skip) - { - move(ypos, last_space); - set_color(0); - clrtoeol(); + for (; lines < 0; lines++) { + if (gui->bottom_subline > 0) { + gui->bottom_subline--; + continue; } - /* skip backwards to draw the line again. */ - ptr = last_space_ptr; - color = last_space_color; - if (!skip) set_color(color); - while (*ptr == ' ') ptr++; - } - last_space = 0; + if (gui->bottom_startline->prev == NULL) + return -1; + gui->bottom_startline = gui->bottom_startline->prev; - if (skip > 0) - { - if (--skip == 0) set_color(color); - } - else - { - if (lines == max) - return lines; - if (max != -1) - ypos++; - else - { - gui_window_newline(gui, TRUE); - ypos = gui->parent->first_line+gui->ypos; + linecount = gui_window_get_linecount(gui, gui->bottom_startline->data); + gui->bottom_subline = linecount-1; + } + + last_linecount = -1; + for (; lines > 0; lines--) { + last_linecount = linecount = + gui_window_get_linecount(gui, gui->bottom_startline->data); + + if (linecount > gui->bottom_subline+1) + gui->bottom_subline++; + else { + gui->bottom_subline = 0; + if (gui->bottom_startline->next == NULL) + break; + gui->bottom_startline = gui->bottom_startline->next; } - lines++; - } - move(ypos, indent_pos); - - /* we could have \0.. */ - ptr--; - continue; + lines--; } - xpos++; - if (*ptr == ' ') - { - last_space = xpos-1; - last_space_color = color; - last_space_ptr = ptr+1; + return last_linecount; +} + +void gui_window_newline(GUI_WINDOW_REC *gui, int visible) +{ + int lines; + + g_return_if_fail(gui != NULL); + + gui->xpos = 0; + + if (gui->empty_linecount > 0) { + /* window buffer height isn't even the size of the screen yet */ + gui->empty_linecount--; + gui->ypos++; + return; } - if (skip) continue; - if (lines == -1) lines = 0; + lines = gui_window_update_bottom(gui, 1); - if ((guchar) *ptr >= 32) - addch((guchar) *ptr); - else - { - /* low-ascii */ - set_color(ATTR_REVERSE); - addch(*ptr+'A'-1); - set_color(color); + if (!gui->bottom) { + gui->ypos++; + return; } - } + + if (gui->subline >= lines) { + /* after screen gets full after /CLEAR we end up here.. */ + gui->startline = gui->startline->next; + gui->subline = 0; + + lines = gui_window_update_bottom(gui, 1); + } + + if (lines > 1+gui->subline) + gui->subline++; + else { + gui->startline = gui->startline->next; + gui->subline = 0; + } + + if (visible) { + scroll_up(gui->parent->first_line, gui->parent->last_line); + move(gui->parent->last_line, 0); clrtoeol(); + } +} + +static LINE_CACHE_REC *gui_window_line_cache(GUI_WINDOW_REC *gui, LINE_REC *line) +{ + LINE_CACHE_REC *rec; + LINE_CACHE_SUB_REC *sub; + GSList *lines; + unsigned char *ptr, *last_space_ptr; + int xpos, pos, indent_pos, last_space, color; + + g_return_val_if_fail(line->text != NULL, NULL); + + rec = g_new(LINE_CACHE_REC, 1); + + xpos = 0; color = 0; indent_pos = DEFAULT_INDENT_POS; + last_space = 0; last_space_ptr = NULL; + + rec->count = 1; lines = NULL; + for (ptr = (unsigned char *) line->text;;) { + if (*ptr == '\0') { + /* command */ + ptr++; + if (*ptr == LINE_CMD_EOL) + break; + + if (*ptr == LINE_CMD_CONTINUE) { + char *tmp; + + memcpy(&tmp, ptr+1, sizeof(char *)); + ptr = tmp; + continue; + } + + if ((*ptr & 0x80) == 0) { + /* set color */ + color = (color & ATTR_UNDERLINE) | *ptr; + } else switch (*ptr) { + case LINE_CMD_OVERFLOW: + g_error("buffer overflow!"); + case LINE_CMD_UNDERLINE: + color ^= ATTR_UNDERLINE; + break; + case LINE_CMD_COLOR8: + color &= 0xfff0; + color |= 8|ATTR_COLOR8; + break; + case LINE_CMD_INDENT: + /* set indentation position here - don't do + it if we're too close to right border */ + if (xpos < COLS-5) indent_pos = xpos; + break; + } + + ptr++; + continue; + } + + if (xpos == COLS) { + xpos = indent_pos; + + if (last_space > indent_pos && last_space > 10) { + /* go back to last space */ + ptr = last_space_ptr; + while (*ptr == ' ') ptr++; + } + + sub = g_new(LINE_CACHE_SUB_REC, 1); + sub->start = ptr; + sub->indent = indent_pos; + sub->color = color; + + lines = g_slist_append(lines, sub); + rec->count++; + + last_space = 0; + continue; + } + + xpos++; + if (*ptr++ == ' ') { + last_space = xpos-1; + last_space_ptr = ptr; + } + } + + if (rec->count < 2) + rec->lines = NULL; + else { + rec->lines = g_new(LINE_CACHE_SUB_REC, rec->count-1); + for (pos = 0; lines != NULL; pos++) { + memcpy(&rec->lines[pos], lines->data, sizeof(LINE_CACHE_SUB_REC)); + + g_free(lines->data); + lines = g_slist_remove(lines, lines->data); + } + } + + g_hash_table_insert(gui->line_cache, line, rec); + return rec; +} + +void gui_window_cache_remove(GUI_WINDOW_REC *gui, LINE_REC *line) +{ + LINE_CACHE_REC *cache; + + g_return_if_fail(gui != NULL); + g_return_if_fail(line != NULL); + + cache = g_hash_table_lookup(gui->line_cache, line); + if (cache != NULL) { + g_hash_table_remove(gui->line_cache, line); + g_free_not_null(cache->lines); + g_free(cache); + } +} + +int gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line) +{ + LINE_CACHE_REC *cache; + + g_return_val_if_fail(gui != NULL, -1); + g_return_val_if_fail(line != NULL, -1); + + cache = g_hash_table_lookup(gui->line_cache, line); + if (cache == NULL) + cache = gui_window_line_cache(gui, line); + + return cache->count; +} + +static void single_line_draw(GUI_WINDOW_REC *gui, int ypos, LINE_CACHE_SUB_REC *rec, const char *text, const char *text_end) +{ + char *tmp; + int xpos, color; + + if (rec == NULL) { + xpos = 0; color = 0; + } else { + xpos = rec->indent; + color = rec->color; + } + + move(ypos, xpos); + while (text != text_end) { + if (*text == '\0') { + /* command */ + text++; + if ((*text & 0x80) == 0) { + /* set color */ + color = (color & ATTR_UNDERLINE) | *text; + } else if (*text == (char) LINE_CMD_CONTINUE) { + /* jump to next block */ + memcpy(&tmp, text+1, sizeof(char *)); + text = tmp; + continue; + } else switch ((unsigned char) *text) { + case LINE_CMD_OVERFLOW: + g_error("buffer overflow!"); + case LINE_CMD_EOL: + return; + case LINE_CMD_UNDERLINE: + color ^= ATTR_UNDERLINE; + break; + case LINE_CMD_COLOR8: + color &= 0xfff0; + color |= 8|ATTR_COLOR8; + break; + } + set_color(color); + text++; + continue; + } + + if (xpos == COLS) { + /* there should be only spaces left */ + text++; + continue; + } + + if ((unsigned char) *text >= 32) + addch((unsigned char) *text); + else { + /* low-ascii */ + set_color(ATTR_REVERSE); + addch(*text+'A'-1); + set_color(color); + } + text++; + } +} + +int gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, int ypos, int skip, int max) +{ + LINE_CACHE_REC *cache; + LINE_CACHE_SUB_REC *sub; + char *pos, *next_pos; + int n; + + g_return_val_if_fail(gui != NULL, -1); + g_return_val_if_fail(line != NULL, -1); + + cache = g_hash_table_lookup(gui->line_cache, line); + if (cache == NULL) + cache = gui_window_line_cache(gui, line); + + if (max < 0) max = cache->count; + + for (n = skip; n < cache->count && max > 0; n++, ypos++, max--) { + sub = n == 0 ? NULL : &cache->lines[n-1]; + pos = sub == NULL ? line->text : sub->start; + next_pos = (n+1 < cache->count) ? + cache->lines[n].start : NULL; + single_line_draw(gui, ypos, sub, pos, next_pos); + } + + return cache->count; } void gui_window_redraw(WINDOW_REC *window) { - GUI_WINDOW_REC *gui; - GList *line; - gint ypos, lines, skip, max; + GUI_WINDOW_REC *gui; + GList *line; + int ypos, lines, skip, max; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - gui = WINDOW_GUI(window); + gui = WINDOW_GUI(window); - for (ypos = gui->parent->first_line; ypos <= gui->parent->last_line; ypos++) - { + /* clear the lines first */ set_color(0); - move(ypos, 0); - clrtoeol(); - } + for (ypos = gui->parent->first_line; ypos <= gui->parent->last_line; ypos++) { + move(ypos, 0); + clrtoeol(); + } - skip = gui->subline; - ypos = gui->parent->first_line; - for (line = gui->startline; line != NULL; line = line->next) - { - LINE_REC *rec = line->data; + skip = gui->subline; + ypos = gui->parent->first_line; + for (line = gui->startline; line != NULL; line = line->next) { + LINE_REC *rec = line->data; - max = gui->parent->last_line - ypos; - if (max < 0) break; + max = gui->parent->last_line - ypos+1; + if (max < 0) break; - lines = gui_window_line_draw(gui, rec, ypos, skip, max); - skip = 0; + lines = gui_window_line_draw(gui, rec, ypos, skip, max); + ypos += lines-skip; + skip = 0; + } - ypos += lines+1; - } - screen_refresh(); + screen_refresh(); } static void gui_window_scroll_up(GUI_WINDOW_REC *gui, gint lines) @@ -579,6 +606,8 @@ static void signal_window_changed(WINDOW_REC *window) { g_return_if_fail(window != NULL); + if (quitting) return; + if (is_window_visible(window)) { /* already visible, great! */ active_mainwin = WINDOW_GUI(window)->parent; @@ -674,6 +703,8 @@ static void gui_window_horiz_resize(WINDOW_REC *window) gui = WINDOW_GUI(window); if (gui->lines == NULL) return; + g_hash_table_foreach_remove(gui->line_cache, (GHRFunc) line_cache_destroy, NULL); + linecount = gui_window_get_linecount(gui, g_list_last(gui->lines)->data); gui->last_subline = linecount-1; @@ -703,7 +734,8 @@ void gui_window_resize(WINDOW_REC *window, int ychange, int xchange) gui = WINDOW_GUI(window); if (xchange) { - /* window width changed, we'll need to recalculate a few things.. */ + /* window width changed, we'll need to recalculate a + few things.. */ gui_window_horiz_resize(window); return; } diff --git a/src/fe-text/gui-windows.h b/src/fe-text/gui-windows.h index 28dde1e9..622b5f4a 100644 --- a/src/fe-text/gui-windows.h +++ b/src/fe-text/gui-windows.h @@ -22,6 +22,17 @@ enum { LINE_CMD_INDENT /* if line is split, indent it at this position */ }; +typedef struct { + char *start; + int indent; + int color; +} LINE_CACHE_SUB_REC; + +typedef struct { + int count; /* number of real lines */ + LINE_CACHE_SUB_REC *lines; +} LINE_CACHE_REC; + typedef struct { /* text in the line. \0 means that the next char will be a color or command. <= 127 = color or if 8.bit is set, the @@ -45,6 +56,7 @@ typedef struct { GMemChunk *line_chunk; GSList *text_chunks; GList *lines; + GHashTable *line_cache; LINE_REC *cur_line; TEXT_CHUNK_REC *cur_text; @@ -74,6 +86,7 @@ GList *gui_window_find_text(WINDOW_REC *window, char *text, GList *startline, in /* get number of real lines that line record takes */ int gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line); +void gui_window_cache_remove(GUI_WINDOW_REC *gui, LINE_REC *line); int gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, int ypos, int skip, int max); void gui_window_clear(WINDOW_REC *window); @@ -82,8 +95,7 @@ void gui_window_resize(WINDOW_REC *window, int ychange, int xchange); void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent); void window_update_prompt(WINDOW_REC *window); -void gui_window_newline(GUI_WINDOW_REC *gui, gboolean visible); -int gui_window_update_bottom(GUI_WINDOW_REC *gui, int lines); +void gui_window_newline(GUI_WINDOW_REC *gui, int visible); void gui_window_scroll(WINDOW_REC *window, int lines); #endif diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 2c95b87d..ee8e3bf5 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -19,6 +19,7 @@ */ #include "module.h" +#include "module-formats.h" #include "args.h" #include "signals.h" #include "core.h" @@ -26,6 +27,7 @@ #include "irc-core.h" #include "fe-common-core.h" #include "fe-common-irc.h" +#include "themes.h" #include "screen.h" #include "gui-entry.h" @@ -82,6 +84,8 @@ static void textui_init(void) irc_init(); fe_common_core_init(); fe_common_irc_init(); + + theme_register(gui_text_formats); signal_add("gui exit", (SIGNAL_FUNC) sig_exit); } @@ -91,11 +95,11 @@ static void textui_finish_init(void) screen_refresh_freeze(); gui_entry_init(); - mainwindows_init(); gui_printtext_init(); gui_readline_init(); gui_special_vars_init(); gui_textwidget_init(); + mainwindows_init(); gui_windows_init(); statusbar_init(); @@ -123,11 +127,13 @@ static void textui_deinit(void) statusbar_deinit(); gui_printtext_deinit(); gui_readline_deinit(); - mainwindows_deinit(); gui_windows_deinit(); + mainwindows_deinit(); gui_entry_deinit(); deinit_screen(); + theme_unregister(); + fe_common_irc_deinit(); fe_common_core_deinit(); irc_deinit(); diff --git a/src/fe-text/mainwindows.c b/src/fe-text/mainwindows.c index 35bf4ecd..e30c0eb4 100644 --- a/src/fe-text/mainwindows.c +++ b/src/fe-text/mainwindows.c @@ -347,6 +347,17 @@ static void mainwindows_resize_bigger(int ychange, int xchange) g_slist_free(sorted); } +void mainwindows_resize_horiz(int xchange) +{ + GSList *tmp; + + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + mainwindow_resize(rec, 0, xchange); + } +} + void mainwindows_resize(int ychange, int xchange) { screen_refresh_freeze(); @@ -354,6 +365,8 @@ void mainwindows_resize(int ychange, int xchange) mainwindows_resize_smaller(ychange, xchange); else if (ychange > 0) mainwindows_resize_bigger(ychange, xchange); + else if (xchange != 0) + mainwindows_resize_horiz(xchange); irssi_redraw(); screen_refresh_thaw(); @@ -595,6 +608,9 @@ void mainwindows_init(void) void mainwindows_deinit(void) { + while (mainwindows != NULL) + mainwindow_destroy(mainwindows->data); + command_unbind("window grow", (SIGNAL_FUNC) cmd_window_grow); command_unbind("window shrink", (SIGNAL_FUNC) cmd_window_shrink); command_unbind("window size", (SIGNAL_FUNC) cmd_window_size); diff --git a/src/fe-text/module-formats.c b/src/fe-text/module-formats.c index 9b38fecb..f81088df 100644 --- a/src/fe-text/module-formats.c +++ b/src/fe-text/module-formats.c @@ -23,11 +23,13 @@ FORMAT_REC gui_text_formats[] = { - { MODULE_NAME, "Text user interface", 0 }, + { MODULE_NAME, "Text user interface", 0 }, - { "lastlog_start", "%_Lastlog:", 0 }, - { "lastlog_end", "%_End of Lastlog", 0 }, + { "lastlog_start", "%_Lastlog:", 0 }, + { "lastlog_end", "%_End of Lastlog", 0 }, - { "window_too_small", "Not enough room to resize this window", 0 }, - { "cant_hide_last", "You can't hide the last window", 0 } + { "window_too_small", "Not enough room to resize this window", 0 }, + { "cant_hide_last", "You can't hide the last window", 0 }, + + { NULL, NULL, 0 } }; diff --git a/src/fe-text/module-formats.h b/src/fe-text/module-formats.h index 39d29182..2af040eb 100644 --- a/src/fe-text/module-formats.h +++ b/src/fe-text/module-formats.h @@ -11,6 +11,3 @@ enum { }; extern FORMAT_REC gui_text_formats[]; -#define MODULE_FORMATS gui_text_formats - -#include "printformat.h" diff --git a/src/irc/core/Makefile.am b/src/irc/core/Makefile.am index e0d49197..fa5f5f1f 100644 --- a/src/irc/core/Makefile.am +++ b/src/irc/core/Makefile.am @@ -12,6 +12,7 @@ libirc_core_la_SOURCES = \ channels-query.c \ channels-setup.c \ channel-events.c \ + channel-rejoin.c \ ignore.c \ irc.c \ irc-core.c \ diff --git a/src/irc/core/channel-events.c b/src/irc/core/channel-events.c index 8de80cbd..02af3c0f 100644 --- a/src/irc/core/channel-events.c +++ b/src/irc/core/channel-events.c @@ -54,7 +54,7 @@ static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) params = event_get_params(data, 2, NULL, &channel); if (ischannel(*channel)) { - /* channel is unavailable. */ + /* channel is unavailable - try to join again a bit later */ event_cannot_join(data, server); } diff --git a/src/irc/core/channel-rejoin.c b/src/irc/core/channel-rejoin.c new file mode 100644 index 00000000..89abae0c --- /dev/null +++ b/src/irc/core/channel-rejoin.c @@ -0,0 +1,104 @@ +/* + channel-rejoin.c : rejoin to channel if it's "temporarily unavailable" + this has nothing to do with autorejoin if kicked + + Copyright (C) 2000 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 "signals.h" + +#include "misc.h" +#include "channels.h" +#include "irc.h" + +#define REJOIN_TIMEOUT (1000*60*5) /* try to rejoin every 5 minutes */ + +static int rejoin_tag; + +static void channel_rejoin(IRC_SERVER_REC *server, const char *channel) +{ + CHANNEL_REC *chanrec; + char *str; + + chanrec = channel_find(server, channel); + str = chanrec == NULL || chanrec->key == NULL || *chanrec->key == '\0' ? + g_strdup(channel) : g_strdup_printf("%s %s", channel, chanrec->key); + + server->rejoin_channels = g_slist_append(server->rejoin_channels, str); +} + +static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) +{ + char *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + if (ischannel(*channel)) { + /* channel is unavailable - try to join again a bit later */ + channel_rejoin(server, channel); + } + + g_free(params); +} + +static void sig_disconnected(IRC_SERVER_REC *server) +{ + g_slist_foreach(server->rejoin_channels, (GFunc) g_free, NULL); + g_slist_free(server->rejoin_channels); +} + +static void server_rejoin_channels(IRC_SERVER_REC *server) +{ + while (server->rejoin_channels != NULL) { + char *channel = server->rejoin_channels->data; + + channels_join(server, channel, TRUE); + server->rejoin_channels = g_slist_remove(server->rejoin_channels, channel); + } +} + +static int sig_rejoin(void) +{ + GSList *tmp; + + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + IRC_SERVER_REC *rec = tmp->data; + + if (irc_server_check(rec)) + server_rejoin_channels(rec); + } + + return TRUE; +} + +void channel_rejoin_init(void) +{ + rejoin_tag = g_timeout_add(REJOIN_TIMEOUT, (GSourceFunc) sig_rejoin, NULL); + + signal_add_first("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); +} + +void channel_rejoin_deinit(void) +{ + g_source_remove(rejoin_tag); + + signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); +} diff --git a/src/irc/core/channels.c b/src/irc/core/channels.c index 4c50ab7b..6943952e 100644 --- a/src/irc/core/channels.c +++ b/src/irc/core/channels.c @@ -38,6 +38,9 @@ void channels_query_deinit(void); void channel_events_init(void); void channel_events_deinit(void); +void channel_rejoin_init(void); +void channel_rejoin_deinit(void); + void massjoin_init(void); void massjoin_deinit(void); @@ -159,7 +162,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) SETUP_CHANNEL_REC *schannel; CHANNEL_REC *chanrec; GString *outchans, *outkeys; - char *params, *channels, *keys; + char *params, *channels, *keys, *key; char **chanlist, **keylist, **tmp, **tmpkey, *channel; int use_keys; @@ -187,15 +190,17 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) schannel = channels_setup_find(channel, server->connrec->ircnet); g_string_sprintfa(outchans, "%s,", channel); - if (schannel == NULL || schannel->password == NULL) - g_string_sprintfa(outkeys, "%s,", get_join_key(*tmpkey)); - else { + if (schannel == NULL || schannel->password == NULL) { + key = *tmpkey == NULL || **tmpkey == '\0' ? NULL : *tmpkey; + } else { /* get password from setup record */ use_keys = TRUE; - g_string_sprintfa(outkeys, "%s,", schannel->password); + key = schannel->password; } - channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic); + g_string_sprintfa(outkeys, "%s,", get_join_key(key)); + chanrec = channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic); + if (key != NULL) chanrec->key = g_strdup(key); } g_free(channel); @@ -204,6 +209,8 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) } if (outchans->len > 0) { + g_string_truncate(outchans, outchans->len-1); + g_string_truncate(outkeys, outkeys->len-1); irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s", outchans->str, outkeys->str); } @@ -220,6 +227,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) void channels_init(void) { channel_events_init(); + channel_rejoin_init(); channels_query_init(); channels_setup_init(); @@ -233,6 +241,7 @@ void channels_init(void) void channels_deinit(void) { channel_events_deinit(); + channel_rejoin_deinit(); channels_query_deinit(); channels_setup_deinit(); diff --git a/src/irc/core/irc-log.c b/src/irc/core/irc-log.c index 9871ee64..accf6014 100644 --- a/src/irc/core/irc-log.c +++ b/src/irc/core/irc-log.c @@ -26,20 +26,6 @@ #include "irc-server.h" -static void sig_log(SERVER_REC *server, const char *channel, gpointer level, const char *str) -{ - int loglevel; - - g_return_if_fail(str != NULL); - - loglevel = GPOINTER_TO_INT(level); - if (loglevel == MSGLEVEL_NEVER || logs == NULL) return; - - /* Check if line should be saved in logs */ - log_write(channel, loglevel, str); -} - - static void event_away(const char *data, IRC_SERVER_REC *server) { const char *fname, *levelstr; @@ -93,14 +79,12 @@ void irc_log_init(void) settings_add_str("log", "awaylog_file", "~/.irssi/away.log"); settings_add_str("log", "awaylog_level", "msgs hilight"); - signal_add("print text stripped", (SIGNAL_FUNC) sig_log); signal_add("event 306", (SIGNAL_FUNC) event_away); signal_add("event 305", (SIGNAL_FUNC) event_unaway); } void irc_log_deinit(void) { - signal_remove("print text stripped", (SIGNAL_FUNC) sig_log); signal_remove("event 306", (SIGNAL_FUNC) event_away); signal_remove("event 305", (SIGNAL_FUNC) event_unaway); } diff --git a/src/irc/core/irc-server.h b/src/irc/core/irc-server.h index 11172bea..8d780e30 100644 --- a/src/irc/core/irc-server.h +++ b/src/irc/core/irc-server.h @@ -129,6 +129,9 @@ typedef struct { GSList *channels; GSList *queries; + GSList *rejoin_channels; /* try to join to these channels after a while - + channels go here if they're "temporarily unavailable" + because of netsplits */ gpointer chanqueries; } IRC_SERVER_REC; diff --git a/src/irc/core/server-setup.c b/src/irc/core/server-setup.c index 9c27c101..91bafd81 100644 --- a/src/irc/core/server-setup.c +++ b/src/irc/core/server-setup.c @@ -293,7 +293,7 @@ static void setupserver_destroy(SETUP_SERVER_REC *rec) g_free_not_null(rec->own_ip); g_free(rec->ircnet); g_free(rec->address); - g_free(rec->password); + g_free_not_null(rec->password); g_free(rec); } diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index c01077d3..6a38e93c 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -308,12 +308,12 @@ static void cmd_dcc_chat(gchar *data, IRC_SERVER_REC *server) cmd_return_error(CMDERR_NOT_CONNECTED); if (net_getsockname(server->handle, &addr, NULL) == -1) - cmd_return_error(CMDERR_GETSOCKNAME); + cmd_return_error(CMDERR_ERRNO); port = settings_get_int("dcc_port"); handle = net_listen(&addr, &port); if (handle == -1) - cmd_return_error(CMDERR_LISTEN); + cmd_return_error(CMDERR_ERRNO); dcc = dcc_create(DCC_TYPE_CHAT, handle, data, "chat", server, NULL); dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c index 8ccdb11a..5acd35c9 100644 --- a/src/irc/dcc/dcc-files.c +++ b/src/irc/dcc/dcc-files.c @@ -513,7 +513,7 @@ static void cmd_dcc_send(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (net_getsockname(chat != NULL ? chat->handle : server->handle, &addr, NULL) == -1) { close(fh); - cmd_param_error(CMDERR_GETSOCKNAME); + cmd_param_error(CMDERR_ERRNO); } /* start listening */ @@ -522,7 +522,7 @@ static void cmd_dcc_send(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (h == -1) { close(fh); - cmd_param_error(CMDERR_LISTEN); + cmd_param_error(CMDERR_ERRNO); } /* skip path */ diff --git a/src/perl/irssi-perl.c b/src/perl/irssi-perl.c index e4f616e9..edf4ea5e 100644 --- a/src/perl/irssi-perl.c +++ b/src/perl/irssi-perl.c @@ -143,6 +143,9 @@ static void signal_destroy_hash(void *key, GSList *list) while (list != NULL) { PERL_SIGNAL_REC *rec = list->data; + if (strncmp(rec->signal, "command ", 8) == 0) + command_unbind(rec->signal+8, NULL); + list = g_slist_remove(list, rec); g_free(rec->signal);