summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/CMakeLists.txt10
-rw-r--r--src/gui/Makefile.am2
-rw-r--r--src/gui/curses/gui-curses-bar.c2
-rw-r--r--src/gui/curses/gui-curses-chat.c21
-rw-r--r--src/gui/curses/gui-curses-color.c15
-rw-r--r--src/gui/curses/gui-curses-keyboard.c1
-rw-r--r--src/gui/curses/gui-curses-main.c6
-rw-r--r--src/gui/curses/gui-curses-window.c2
-rw-r--r--src/gui/curses/gui-curses.h1
-rw-r--r--src/gui/gtk/gui-gtk-color.c15
-rw-r--r--src/gui/gtk/gui-gtk.h1
-rw-r--r--src/gui/gui-action.c2
-rw-r--r--src/gui/gui-bar-item.c48
-rw-r--r--src/gui/gui-bar-item.h1
-rw-r--r--src/gui/gui-buffer.c120
-rw-r--r--src/gui/gui-buffer.h12
-rw-r--r--src/gui/gui-chat.c203
-rw-r--r--src/gui/gui-chat.h21
-rw-r--r--src/gui/gui-color.c13
-rw-r--r--src/gui/gui-color.h1
-rw-r--r--src/gui/gui-completion.c24
-rw-r--r--src/gui/gui-filter.c426
-rw-r--r--src/gui/gui-filter.h63
-rw-r--r--src/gui/gui-keyboard.c17
-rw-r--r--src/gui/gui-keyboard.h1
-rw-r--r--src/gui/gui-window.c46
26 files changed, 1011 insertions, 63 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index fef192a8f..6b6757ab6 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -20,11 +20,11 @@ ENDIF(NOT DISABLE_NCURSES)
SET(LIB_GUI_COMMON_SRC gui-action.c gui-action.h gui-bar.c gui-bar.h
gui-bar-item.c gui-bar-item.h gui-buffer.c gui-buffer.h gui-chat.c gui-chat.h
-gui-color.c gui-color.h gui-completion.c gui-completion.h gui-history.c
-gui-history.h gui-hotlist.c gui-hotlist.h gui-infobar.c gui-infobar.h
-gui-input.c gui-input.h gui-keyboard.c gui-keyboard.h gui-main.h
-gui-nicklist.c gui-nicklist.h gui-status.c gui-status.h gui-window.c
-gui-window.h)
+gui-color.c gui-color.h gui-filter.c gui-filter.h gui-completion.c
+gui-completion.h gui-history.c gui-history.h gui-hotlist.c gui-hotlist.h
+gui-infobar.c gui-infobar.h gui-input.c gui-input.h gui-keyboard.c
+gui-keyboard.h gui-main.h gui-nicklist.c gui-nicklist.h gui-status.c
+gui-status.h gui-window.c gui-window.h)
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
ADD_LIBRARY(weechat_gui_common STATIC ${LIB_GUI_COMMON_SRC})
diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
index 12c4575fa..916a4dc08 100644
--- a/src/gui/Makefile.am
+++ b/src/gui/Makefile.am
@@ -32,6 +32,8 @@ lib_weechat_gui_common_a_SOURCES = gui-action.c \
gui-color.h \
gui-completion.c \
gui-completion.h \
+ gui-filter.c \
+ gui-filter.h \
gui-history.c \
gui-history.h \
gui-hotlist.c \
diff --git a/src/gui/curses/gui-curses-bar.c b/src/gui/curses/gui-curses-bar.c
index 2166542ad..bf167b092 100644
--- a/src/gui/curses/gui-curses-bar.c
+++ b/src/gui/curses/gui-curses-bar.c
@@ -352,6 +352,8 @@ gui_bar_window_draw (struct t_gui_window *window,
}
if (item_value2)
free (item_value2);
+ if (items)
+ string_free_exploded (items);
}
free (item_value);
}
diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c
index 6adbb13f6..2e7375e1f 100644
--- a/src/gui/curses/gui-curses-chat.c
+++ b/src/gui/curses/gui-curses-chat.c
@@ -837,7 +837,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line,
{
/* display read marker if needed */
if (window->buffer->last_read_line &&
- (window->buffer->last_read_line == line->prev_line))
+ (window->buffer->last_read_line == gui_chat_get_prev_line_displayed (line)))
{
gui_chat_set_weechat_color (window,
GUI_COLOR_CHAT_READ_MARKER);
@@ -874,7 +874,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window,
/* if looking backward, start at last line of buffer */
if (backward)
{
- *line = window->buffer->last_line;
+ *line = gui_chat_get_last_line_displayed (window->buffer);
if (!(*line))
return;
current_size = gui_chat_display_line (window, *line, 0, 1);
@@ -885,7 +885,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window,
/* if looking forward, start at first line of buffer */
else
{
- *line = window->buffer->lines;
+ *line = gui_chat_get_first_line_displayed (window->buffer);
if (!(*line))
return;
*line_pos = 0;
@@ -904,7 +904,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window,
(*line_pos)--;
else
{
- *line = (*line)->prev_line;
+ *line = gui_chat_get_prev_line_displayed (*line);
if (*line)
{
current_size = gui_chat_display_line (window, *line, 0, 1);
@@ -922,7 +922,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window,
(*line_pos)++;
else
{
- *line = (*line)->next_line;
+ *line = gui_chat_get_next_line_displayed (*line);
if (*line)
{
current_size = gui_chat_display_line (window, *line, 0, 1);
@@ -941,7 +941,7 @@ gui_chat_calculate_line_diff (struct t_gui_window *window,
if (backward)
{
/* first line reached */
- *line = window->buffer->lines;
+ *line = gui_chat_get_first_line_displayed (window->buffer);
*line_pos = 0;
}
else
@@ -1158,19 +1158,19 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase)
ptr_line,
0, 1) -
line_pos, 0);
- ptr_line = ptr_line->next_line;
+ ptr_line = gui_chat_get_next_line_displayed (ptr_line);
ptr_win->first_line_displayed = 0;
}
else
ptr_win->first_line_displayed =
- (ptr_line == ptr_win->buffer->lines);
+ (ptr_line == gui_chat_get_first_line_displayed (ptr_win->buffer));
/* display lines */
count = 0;
while (ptr_line && (ptr_win->win_chat_cursor_y <= ptr_win->win_chat_height - 1))
{
count = gui_chat_display_line (ptr_win, ptr_line, 0, 0);
- ptr_line = ptr_line->next_line;
+ ptr_line = gui_chat_get_next_line_displayed (ptr_line);
}
old_scroll = ptr_win->scroll;
@@ -1191,7 +1191,8 @@ gui_chat_draw (struct t_gui_buffer *buffer, int erase)
WEECHAT_HOOK_SIGNAL_POINTER, ptr_win);
}
- if (!ptr_win->scroll && (ptr_win->start_line == ptr_win->buffer->lines))
+ if (!ptr_win->scroll
+ && (ptr_win->start_line == gui_chat_get_first_line_displayed (ptr_win->buffer)))
{
ptr_win->start_line = NULL;
ptr_win->start_line_pos = 0;
diff --git a/src/gui/curses/gui-curses-color.c b/src/gui/curses/gui-curses-color.c
index a642cfebf..1adb758ee 100644
--- a/src/gui/curses/gui-curses-color.c
+++ b/src/gui/curses/gui-curses-color.c
@@ -459,3 +459,18 @@ gui_color_init ()
gui_color_init_pairs ();
gui_color_init_weechat ();
}
+
+/*
+ * gui_color_end: end GUI colors
+ */
+
+void
+gui_color_end ()
+{
+ int i;
+
+ for (i = 0; i < GUI_NUM_COLORS; i++)
+ {
+ gui_color_free (gui_color[i]);
+ }
+}
diff --git a/src/gui/curses/gui-curses-keyboard.c b/src/gui/curses/gui-curses-keyboard.c
index d6353a50f..62be0e4c1 100644
--- a/src/gui/curses/gui-curses-keyboard.c
+++ b/src/gui/curses/gui-curses-keyboard.c
@@ -135,6 +135,7 @@ gui_keyboard_default_bindings ()
gui_keyboard_bind (/* m-w,m-down */ "meta-wmeta-meta2-B", "/window down");
gui_keyboard_bind (/* m-w,m-left */ "meta-wmeta-meta2-D", "/window left");
gui_keyboard_bind (/* m-w,m-right */ "meta-wmeta-meta2-C", "/window right");
+ gui_keyboard_bind (/* m-= */ "meta-=", "/filter toggle");
gui_keyboard_bind (/* m-0 */ "meta-0", "/buffer 10");
gui_keyboard_bind (/* m-1 */ "meta-1", "/buffer 1");
gui_keyboard_bind (/* m-2 */ "meta-2", "/buffer 2");
diff --git a/src/gui/curses/gui-curses-main.c b/src/gui/curses/gui-curses-main.c
index ff459062c..bf842dfcf 100644
--- a/src/gui/curses/gui-curses-main.c
+++ b/src/gui/curses/gui-curses-main.c
@@ -263,8 +263,9 @@ gui_main_loop ()
void
gui_main_end ()
{
- /* remove bar items */
+ /* remove bar items and bars */
gui_bar_item_end ();
+ gui_bar_free_all ();
/* free clipboard buffer */
if (gui_input_clipboard)
@@ -290,6 +291,9 @@ gui_main_end ()
if (CONFIG_BOOLEAN(config_look_set_title))
gui_window_title_reset ();
+ /* end color */
+ gui_color_end ();
+
/* end of Curses output */
refresh ();
endwin ();
diff --git a/src/gui/curses/gui-curses-window.c b/src/gui/curses/gui-curses-window.c
index a23128f10..550d2a909 100644
--- a/src/gui/curses/gui-curses-window.c
+++ b/src/gui/curses/gui-curses-window.c
@@ -726,7 +726,7 @@ gui_window_scroll_top (struct t_gui_window *window)
if (!window->first_line_displayed)
{
- window->start_line = window->buffer->lines;
+ window->start_line = gui_chat_get_first_line_displayed (window->buffer);
window->start_line_pos = 0;
gui_chat_draw (window->buffer, 0);
if (!window->scroll)
diff --git a/src/gui/curses/gui-curses.h b/src/gui/curses/gui-curses.h
index 663b4963c..b5899ceb7 100644
--- a/src/gui/curses/gui-curses.h
+++ b/src/gui/curses/gui-curses.h
@@ -62,6 +62,7 @@ extern struct t_gui_color gui_weechat_colors[];
/* color functions */
extern int gui_color_get_pair (int num_color);
extern void gui_color_init ();
+extern void gui_color_end ();
/* bar functions */
extern void gui_bar_window_calculate_pos_size (struct t_gui_bar_window *bar_window,
diff --git a/src/gui/gtk/gui-gtk-color.c b/src/gui/gtk/gui-gtk-color.c
index f2a622212..e441a05b3 100644
--- a/src/gui/gtk/gui-gtk-color.c
+++ b/src/gui/gtk/gui-gtk-color.c
@@ -170,3 +170,18 @@ gui_color_init ()
gui_color_init_pairs ();
gui_color_init_weechat ();
}
+
+/*
+ * gui_color_end: end GUI colors
+ */
+
+void
+gui_color_end ()
+{
+ int i;
+
+ for (i = 0; i < GUI_NUM_COLORS; i++)
+ {
+ gui_color_free (gui_color[i]);
+ }
+}
diff --git a/src/gui/gtk/gui-gtk.h b/src/gui/gtk/gui-gtk.h
index 3909230b7..71cfc2e04 100644
--- a/src/gui/gtk/gui-gtk.h
+++ b/src/gui/gtk/gui-gtk.h
@@ -92,6 +92,7 @@ extern GtkWidget *gui_gtk_label1;
/* color functions */
extern int gui_color_get_pair (int num_color);
extern void gui_color_init ();
+extern void gui_color_end ();
/* chat functions */
extern void gui_chat_calculate_line_diff (struct t_gui_window *window,
diff --git a/src/gui/gui-action.c b/src/gui/gui-action.c
index aee963680..396de1ffd 100644
--- a/src/gui/gui-action.c
+++ b/src/gui/gui-action.c
@@ -1369,7 +1369,7 @@ gui_action_scroll_unread (char *args)
gui_current_window->buffer->last_read_line->next_line;
gui_current_window->start_line_pos = 0;
gui_current_window->first_line_displayed =
- (gui_current_window->start_line == gui_current_window->buffer->lines);
+ (gui_current_window->start_line == gui_chat_get_first_line_displayed (gui_current_window->buffer));
gui_current_window->buffer->chat_refresh_needed = 1;
gui_status_refresh_needed = 1;
}
diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c
index f99191864..5bac05335 100644
--- a/src/gui/gui-bar-item.c
+++ b/src/gui/gui-bar-item.c
@@ -36,6 +36,7 @@
#include "gui-bar.h"
#include "gui-buffer.h"
#include "gui-color.h"
+#include "gui-filter.h"
#include "gui-hotlist.h"
#include "gui-window.h"
@@ -43,8 +44,8 @@
struct t_gui_bar_item *gui_bar_items = NULL; /* first bar item */
struct t_gui_bar_item *last_gui_bar_item = NULL; /* last bar item */
char *gui_bar_item_names[GUI_BAR_NUM_ITEMS] =
-{ "buffer_count", "buffer_plugin", "buffer_name", "nicklist_count", "scroll",
- "hotlist"
+{ "buffer_count", "buffer_plugin", "buffer_name", "buffer_filter",
+ "nicklist_count", "scroll", "hotlist"
};
struct t_gui_bar_item_hook *gui_bar_item_hooks = NULL;
@@ -326,6 +327,40 @@ gui_bar_item_default_buffer_name (void *data, struct t_gui_bar_item *item,
}
/*
+ * gui_bar_item_default_buffer_filter: default item for buffer filter
+ */
+
+char *
+gui_bar_item_default_buffer_filter (void *data, struct t_gui_bar_item *item,
+ struct t_gui_window *window,
+ int max_width, int max_height)
+{
+ char buf[256];
+
+ /* make C compiler happy */
+ (void) data;
+ (void) item;
+ (void) max_width;
+ (void) max_height;
+
+ if (!window)
+ window = gui_current_window;
+
+ if (!gui_filters_enabled)
+ return NULL;
+
+ snprintf (buf, sizeof (buf),
+ _("%s[%sF%s%s%s]"),
+ GUI_COLOR(GUI_COLOR_STATUS_DELIMITERS),
+ GUI_COLOR(GUI_COLOR_STATUS_NAME),
+ (window->buffer->lines_hidden) ? "," : "",
+ (window->buffer->lines_hidden) ? _("filtered") : "",
+ GUI_COLOR(GUI_COLOR_STATUS_DELIMITERS));
+
+ return strdup (buf);
+}
+
+/*
* gui_bar_item_default_nicklist_count: default item for number of nicks in
* buffer nicklist
*/
@@ -549,6 +584,15 @@ gui_bar_item_init ()
gui_bar_item_hook ("buffer_moved",
gui_bar_item_names[GUI_BAR_ITEM_WEECHAT_BUFFER_NAME]);
+ /* buffer filter */
+ gui_bar_item_new (NULL,
+ gui_bar_item_names[GUI_BAR_ITEM_WEECHAT_BUFFER_FILTER],
+ &gui_bar_item_default_buffer_filter, NULL);
+ gui_bar_item_hook ("buffer_lines_hidden",
+ gui_bar_item_names[GUI_BAR_ITEM_WEECHAT_BUFFER_FILTER]);
+ gui_bar_item_hook ("filters_*",
+ gui_bar_item_names[GUI_BAR_ITEM_WEECHAT_BUFFER_FILTER]);
+
/* nicklist count */
gui_bar_item_new (NULL,
gui_bar_item_names[GUI_BAR_ITEM_WEECHAT_NICKLIST_COUNT],
diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h
index d0f878557..80324e3d4 100644
--- a/src/gui/gui-bar-item.h
+++ b/src/gui/gui-bar-item.h
@@ -25,6 +25,7 @@ enum t_gui_bar_item_weechat
GUI_BAR_ITEM_WEECHAT_BUFFER_COUNT = 0,
GUI_BAR_ITEM_WEECHAT_BUFFER_PLUGIN,
GUI_BAR_ITEM_WEECHAT_BUFFER_NAME,
+ GUI_BAR_ITEM_WEECHAT_BUFFER_FILTER,
GUI_BAR_ITEM_WEECHAT_NICKLIST_COUNT,
GUI_BAR_ITEM_WEECHAT_SCROLL,
GUI_BAR_ITEM_WEECHAT_HOTLIST,
diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c
index 0948439bd..c02ef92dc 100644
--- a/src/gui/gui-buffer.c
+++ b/src/gui/gui-buffer.c
@@ -55,7 +55,6 @@
struct t_gui_buffer *gui_buffers = NULL; /* first buffer */
struct t_gui_buffer *last_gui_buffer = NULL; /* last buffer */
struct t_gui_buffer *gui_previous_buffer = NULL; /* previous buffer */
-struct t_gui_buffer *gui_buffer_before_dcc = NULL; /* buffer before dcc */
/*
@@ -89,7 +88,8 @@ gui_buffer_new (struct t_weechat_plugin *plugin, char *category, char *name,
}
/* create new buffer */
- if ((new_buffer = (struct t_gui_buffer *)(malloc (sizeof (struct t_gui_buffer)))))
+ new_buffer = (struct t_gui_buffer *)(malloc (sizeof (struct t_gui_buffer)));
+ if (new_buffer)
{
/* init buffer */
new_buffer->plugin = plugin;
@@ -113,6 +113,7 @@ gui_buffer_new (struct t_weechat_plugin *plugin, char *category, char *name,
new_buffer->last_line = NULL;
new_buffer->last_read_line = NULL;
new_buffer->lines_count = 0;
+ new_buffer->lines_hidden = 0;
new_buffer->prefix_max_length = 0;
new_buffer->chat_refresh_needed = 1;
@@ -219,14 +220,14 @@ gui_buffer_valid (struct t_gui_buffer *buffer)
}
/*
- * gui_buffer_get: get a buffer property
+ * gui_buffer_get_string: get a buffer property as string
*/
-void *
-gui_buffer_get (struct t_gui_buffer *buffer, char *property)
+char *
+gui_buffer_get_string (struct t_gui_buffer *buffer, char *property)
{
- if (string_strcasecmp (property, "plugin") == 0)
- return buffer->plugin;
+ static char value[32];
+
if (string_strcasecmp (property, "category") == 0)
return buffer->category;
else if (string_strcasecmp (property, "name") == 0)
@@ -235,6 +236,24 @@ gui_buffer_get (struct t_gui_buffer *buffer, char *property)
return buffer->title;
else if (string_strcasecmp (property, "nick") == 0)
return buffer->input_nick;
+ else if (string_strcasecmp (property, "lines_hidden") == 0)
+ {
+ snprintf (value, sizeof (value), "%d", buffer->lines_hidden);
+ return value;
+ }
+
+ return NULL;
+}
+
+/*
+ * gui_buffer_get_pointer: get a buffer property as pointer
+ */
+
+void *
+gui_buffer_get_pointer (struct t_gui_buffer *buffer, char *property)
+{
+ if (string_strcasecmp (property, "plugin") == 0)
+ return buffer->plugin;
return NULL;
}
@@ -370,21 +389,21 @@ gui_buffer_set (struct t_gui_buffer *buffer, char *property, char *value)
{
error = NULL;
number = strtol (value, &error, 10);
- if (error && (error[0] == '\0'))
+ if (error && !error[0])
gui_buffer_set_nicklist (buffer, number);
}
else if (string_strcasecmp (property, "nicklist_case_sensitive") == 0)
{
error = NULL;
number = strtol (value, &error, 10);
- if (error && (error[0] == '\0'))
+ if (error && !error[0])
gui_buffer_set_nicklist_case_sensitive (buffer, number);
}
else if (string_strcasecmp (property, "nicklist_display_groups") == 0)
{
error = NULL;
number = strtol (value, &error, 10);
- if (error && (error[0] == '\0'))
+ if (error && !error[0])
gui_buffer_set_nicklist_display_groups (buffer, number);
}
else if (string_strcasecmp (property, "nick") == 0)
@@ -401,7 +420,7 @@ gui_buffer_set (struct t_gui_buffer *buffer, char *property, char *value)
{
error = NULL;
number = strtol (value, &error, 10);
- if (error && (error[0] == '\0'))
+ if (error && !error[0])
gui_hotlist_add (buffer, number, NULL, 1);
}
}
@@ -533,6 +552,54 @@ gui_buffer_is_scrolled (struct t_gui_buffer *buffer)
}
/*
+ * gui_buffer_match_category_name: return 1 if buffer matches category.name
+ * otherwise 0
+ * category or name may begin or end with "*"
+ * examples:
+ * *.#weechat
+ * freenode.*
+ * freenode.#weechat*
+ * freenode.*chat*
+ */
+
+int
+gui_buffer_match_category_name (struct t_gui_buffer *buffer, char *mask,
+ int case_sensitive)
+{
+ char *pos_point, *category, *pos_name;
+ int rc;
+
+ if (!mask || !mask[0])
+ return 0;
+
+ pos_point = strchr (mask, '.');
+ if (pos_point)
+ {
+ category = string_strndup (mask, pos_point - mask);
+ pos_name = pos_point + 1;
+ }
+ else
+ {
+ category = NULL;
+ pos_name = mask;
+ }
+
+ rc = 1;
+
+ if (category && buffer->category
+ && !string_match (buffer->category, category, case_sensitive))
+ rc = 0;
+
+ if (rc && !string_match (buffer->name, pos_name, case_sensitive))
+ rc = 0;
+
+ if (category)
+ free (category);
+
+ return rc;
+}
+
+/*
* gui_buffer_get_dcc: get pointer to DCC buffer (DCC buffer created if not existing)
*/
@@ -657,13 +724,6 @@ gui_buffer_close (struct t_gui_buffer *buffer, int switch_to_another)
if (gui_previous_buffer == buffer)
gui_previous_buffer = NULL;
- if (gui_buffer_before_dcc == buffer)
- gui_buffer_before_dcc = NULL;
-
- /* free title */
- if (buffer->title)
- free (buffer->title);
-
if (buffer->type == GUI_BUFFER_TYPE_FORMATED)
{
/* decrease buffer number for all next buffers */
@@ -681,7 +741,14 @@ gui_buffer_close (struct t_gui_buffer *buffer, int switch_to_another)
buffer->lines = ptr_line;
}
}
-
+
+ /* free some data */
+ if (buffer->title)
+ free (buffer->title);
+ if (buffer->category)
+ free (buffer->category);
+ if (buffer->name)
+ free (buffer->name);
if (buffer->input_buffer)
free (buffer->input_buffer);
if (buffer->input_buffer_color_mask)
@@ -988,6 +1055,7 @@ gui_buffer_print_log ()
{
struct t_gui_buffer *ptr_buffer;
struct t_gui_line *ptr_line;
+ char *tags;
int num;
for (ptr_buffer = gui_buffers; ptr_buffer;
@@ -1007,6 +1075,7 @@ gui_buffer_print_log ()
log_printf (" last_line. . . . . . . : 0x%x", ptr_buffer->last_line);
log_printf (" last_read_line . . . . : 0x%x", ptr_buffer->last_read_line);
log_printf (" lines_count. . . . . . : %d", ptr_buffer->lines_count);
+ log_printf (" lines_hidden . . . . . : %d", ptr_buffer->lines_hidden);
log_printf (" prefix_max_length. . . : %d", ptr_buffer->prefix_max_length);
log_printf (" chat_refresh_needed. . : %d", ptr_buffer->chat_refresh_needed);
log_printf (" nicklist . . . . . . . : %d", ptr_buffer->nicklist);
@@ -1060,10 +1129,17 @@ gui_buffer_print_log ()
while (ptr_line)
{
num--;
- log_printf (" line N-%05d: str_time:'%s', prefix:'%s'",
- num, ptr_line->str_time, ptr_line->prefix);
+ tags = string_build_with_exploded (ptr_line->tags_array, ",");
+ log_printf (" line N-%05d: str_time:'%s', tags:'%s', "
+ "displayed:%d, prefix:'%s'",
+ num, ptr_line->str_time,
+ (tags) ? tags : "",
+ (int)(ptr_line->displayed),
+ ptr_line->prefix);
log_printf (" data: '%s'",
- ptr_line->message);
+ ptr_line->message);
+ if (tags)
+ free (tags);
ptr_line = ptr_line->next_line;
}
diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h
index 6460fbd57..2ffced80d 100644
--- a/src/gui/gui-buffer.h
+++ b/src/gui/gui-buffer.h
@@ -43,6 +43,9 @@ struct t_gui_line
time_t date; /* date/time of line (may be past) */
time_t date_printed; /* date/time when weechat print it */
char *str_time; /* time string (for display) */
+ int tags_count; /* number of tags for line */
+ char **tags_array; /* tags for line */
+ char displayed; /* 1 if line is displayed */
char *prefix; /* prefix for line (may be NULL) */
int prefix_length; /* prefix length (on screen) */
char *message; /* line content (after prefix) */
@@ -78,6 +81,7 @@ struct t_gui_buffer
struct t_gui_line *last_line; /* last line of chat window */
struct t_gui_line *last_read_line; /* last read line before jump */
int lines_count; /* number of lines in the buffer */
+ int lines_hidden; /* 1 if at least one line is hidden */
int prefix_max_length; /* length for prefix align */
int chat_refresh_needed; /* refresh for chat is needed ? */
@@ -132,7 +136,6 @@ struct t_gui_buffer
extern struct t_gui_buffer *gui_buffers;
extern struct t_gui_buffer *last_gui_buffer;
extern struct t_gui_buffer *gui_previous_buffer;
-extern struct t_gui_buffer *gui_buffer_before_dcc;
/* buffer functions */
@@ -146,7 +149,10 @@ extern struct t_gui_buffer *gui_buffer_new (struct t_weechat_plugin *plugin,
struct t_gui_buffer *buffer),
void *close_callback_data);
extern int gui_buffer_valid (struct t_gui_buffer *buffer);
-extern void *gui_buffer_get (struct t_gui_buffer *buffer, char *property);
+extern char *gui_buffer_get_string (struct t_gui_buffer *buffer,
+ char *property);
+extern void *gui_buffer_get_pointer (struct t_gui_buffer *buffer,
+ char *property);
extern void gui_buffer_set_category (struct t_gui_buffer *buffer,
char *category);
extern void gui_buffer_set_name (struct t_gui_buffer *buffer, char *name);
@@ -165,6 +171,8 @@ extern struct t_gui_buffer *gui_buffer_search_by_category_name (char *category,
extern struct t_gui_buffer *gui_buffer_search_by_number (int number);
extern struct t_gui_window *gui_buffer_find_window (struct t_gui_buffer *buffer);
extern int gui_buffer_is_scrolled (struct t_gui_buffer *buffer);
+extern int gui_buffer_match_category_name (struct t_gui_buffer *buffer,
+ char *mask, int case_sensitive);
extern struct t_gui_buffer *gui_buffer_get_dcc (struct t_gui_window *window);
extern void gui_buffer_clear (struct t_gui_buffer *buffer);
extern void gui_buffer_clear_all ();
diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c
index e8899c11f..b06bee0b7 100644
--- a/src/gui/gui-chat.c
+++ b/src/gui/gui-chat.c
@@ -27,6 +27,7 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+#include <regex.h>
#include "../core/weechat.h"
#include "../core/wee-config.h"
@@ -34,9 +35,11 @@
#include "../core/wee-log.h"
#include "../core/wee-string.h"
#include "../core/wee-utf8.h"
+#include "../plugins/plugin.h"
#include "gui-chat.h"
#include "gui-buffer.h"
#include "gui-color.h"
+#include "gui-filter.h"
#include "gui-hotlist.h"
#include "gui-main.h"
#include "gui-status.h"
@@ -375,6 +378,94 @@ gui_chat_get_line_align (struct t_gui_buffer *buffer, struct t_gui_line *line,
}
/*
+ * gui_chat_line_displayed: return 1 if line is displayed (no filter on line,
+ * or filters disabled), 0 if line is hidden
+ */
+
+int
+gui_chat_line_displayed (struct t_gui_line *line)
+{
+ /* line is hidden if filters are enabled and flag "displayed" is not set */
+ if (gui_filters_enabled && !line->displayed)
+ return 0;
+
+ /* in all other cases, line is displayed */
+ return 1;
+}
+
+/*
+ * gui_chat_get_first_line_displayed: get first line displayed of a buffer
+ */
+
+struct t_gui_line *
+gui_chat_get_first_line_displayed (struct t_gui_buffer *buffer)
+{
+ struct t_gui_line *ptr_line;
+
+ ptr_line = buffer->lines;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->next_line;
+ }
+
+ return ptr_line;
+}
+
+/*
+ * gui_chat_get_last_line_displayed: get last line displayed of a buffer
+ */
+
+struct t_gui_line *
+gui_chat_get_last_line_displayed (struct t_gui_buffer *buffer)
+{
+ struct t_gui_line *ptr_line;
+
+ ptr_line = buffer->last_line;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->prev_line;
+ }
+
+ return ptr_line;
+}
+
+/*
+ * gui_chat_get_prev_line_displayed: get previous line displayed
+ */
+
+struct t_gui_line *
+gui_chat_get_prev_line_displayed (struct t_gui_line *line)
+{
+ if (line)
+ {
+ line = line->prev_line;
+ while (line && !gui_chat_line_displayed (line))
+ {
+ line = line->prev_line;
+ }
+ }
+ return line;
+}
+
+/*
+ * gui_chat_get_next_line_displayed: get next line displayed
+ */
+
+struct t_gui_line *
+gui_chat_get_next_line_displayed (struct t_gui_line *line)
+{
+ if (line)
+ {
+ line = line->next_line;
+ while (line && !gui_chat_line_displayed (line))
+ {
+ line = line->next_line;
+ }
+ }
+ return line;
+}
+
+/*
* gui_chat_line_search: search for text in a line
*/
@@ -400,6 +491,78 @@ gui_chat_line_search (struct t_gui_line *line, char *text, int case_sensitive)
}
/*
+ * gui_chat_line_match_regex: return 1 if message matches regex
+ * 0 if it doesn't match
+ */
+
+int
+gui_chat_line_match_regex (struct t_gui_line *line, regex_t *regex_prefix,
+ regex_t *regex_message)
+{
+ char *prefix, *message;
+ int match_prefix, match_message;
+
+ if (!line || (!regex_prefix && !regex_message))
+ return 0;
+
+ match_prefix = 1;
+ match_message = 1;
+
+ prefix = (char *)gui_color_decode ((unsigned char *)line->prefix);
+ if (prefix && regex_prefix)
+ {
+ if (regexec (regex_prefix, prefix, 0, NULL, 0) != 0)
+ match_prefix = 0;
+ }
+
+ message = (char *)gui_color_decode ((unsigned char *)line->message);
+ if (message && regex_message)
+ {
+ if (regexec (regex_message, message, 0, NULL, 0) != 0)
+ match_message = 0;
+ }
+
+ if (prefix)
+ free (prefix);
+ if (message)
+ free (message);
+
+ return (match_prefix && match_message);
+}
+
+/*
+ * gui_chat_line_match_tags: return 1 if line matches tags
+ * 0 if it doesn't match any tag in array
+ */
+
+int
+gui_chat_line_match_tags (struct t_gui_line *line, int tags_count,
+ char **tags_array)
+{
+ int i, j;
+
+ if (!line)
+ return 0;
+
+ if (line->tags_count == 0)
+ return 0;
+
+ for (i = 0; i < tags_count; i++)
+ {
+ for (j = 0; j < line->tags_count; j++)
+ {
+ /* check tag */
+ if (string_match (line->tags_array[j],
+ tags_array[i],
+ 0))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
* gui_chat_line_free: delete a line from a buffer
*/
@@ -420,6 +583,8 @@ gui_chat_line_free (struct t_gui_line *line)
}
if (line->str_time)
free (line->str_time);
+ if (line->tags_array)
+ string_free_exploded (line->tags_array);
if (line->prefix)
free (line->prefix);
if (line->message)
@@ -433,7 +598,8 @@ gui_chat_line_free (struct t_gui_line *line)
void
gui_chat_line_add (struct t_gui_buffer *buffer, time_t date,
- time_t date_printed, char *prefix, char *message)
+ time_t date_printed, char *tags,
+ char *prefix, char *message)
{
struct t_gui_line *new_line, *ptr_line;
@@ -449,6 +615,16 @@ gui_chat_line_add (struct t_gui_buffer *buffer, time_t date,
new_line->date_printed = date_printed;
new_line->str_time = (date == 0) ?
NULL : gui_chat_get_time_string (date);
+ if (tags)
+ {
+ new_line->tags_array = string_explode (tags, ",", 0, 0,
+ &new_line->tags_count);
+ }
+ else
+ {
+ new_line->tags_count = 0;
+ new_line->tags_array = NULL;
+ }
new_line->prefix = (prefix) ?
strdup (prefix) : ((date != 0) ? strdup ("") : NULL);
new_line->prefix_length = (prefix) ?
@@ -465,6 +641,18 @@ gui_chat_line_add (struct t_gui_buffer *buffer, time_t date,
buffer->last_line = new_line;
buffer->lines_count++;
+ /* check if line is filtered or not */
+ new_line->displayed = gui_filter_check_line (buffer, new_line);
+ if (!new_line->displayed)
+ {
+ if (!buffer->lines_hidden)
+ {
+ buffer->lines_hidden = 1;
+ hook_signal_send ("buffer_lines_hidden",
+ WEECHAT_HOOK_SIGNAL_POINTER, buffer);
+ }
+ }
+
/* remove one line if necessary */
if ((CONFIG_INTEGER(config_history_max_lines) > 0)
&& (buffer->lines_count > CONFIG_INTEGER(config_history_max_lines)))
@@ -480,12 +668,13 @@ gui_chat_line_add (struct t_gui_buffer *buffer, time_t date,
}
/*
- * gui_chat_printf_date: display a message in a buffer
+ * gui_chat_printf_date_tags: display a message in a buffer with optional
+ * date and tags
*/
void
-gui_chat_printf_date (struct t_gui_buffer *buffer, time_t date,
- char *message, ...)
+gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date,
+ char *tags, char *message, ...)
{
char buf[8192];
time_t date_printed;
@@ -552,11 +741,15 @@ gui_chat_printf_date (struct t_gui_buffer *buffer, time_t date,
{
gui_chat_line_add (buffer, (display_time) ? date : 0,
(display_time) ? date_printed : 0,
- pos_prefix, pos);
+ tags, pos_prefix, pos);
if (buffer->last_line)
+ {
hook_print_exec (buffer, buffer->last_line->date,
+ buffer->last_line->tags_count,
+ buffer->last_line->tags_array,
buffer->last_line->prefix,
buffer->last_line->message);
+ }
}
else
{
diff --git a/src/gui/gui-chat.h b/src/gui/gui-chat.h
index b7abda270..f63d0ae4e 100644
--- a/src/gui/gui-chat.h
+++ b/src/gui/gui-chat.h
@@ -20,12 +20,14 @@
#ifndef __WEECHAT_GUI_CHAT_H
#define __WEECHAT_GUI_CHAT_H 1
+#include <regex.h>
+
struct t_gui_window;
struct t_gui_buffer;
struct t_gui_line;
-#define gui_chat_printf(buffer, argz...) \
- gui_chat_printf_date(buffer, 0, ##argz) \
+#define gui_chat_printf(buffer, argz...) \
+ gui_chat_printf_date_tags(buffer, 0, NULL, ##argz)
enum t_gui_prefix
{
@@ -58,11 +60,22 @@ extern void gui_chat_change_time_format ();
extern int gui_chat_get_line_align (struct t_gui_buffer *buffer,
struct t_gui_line *line,
int with_suffix);
+extern int gui_chat_line_displayed (struct t_gui_line *line);
+extern struct t_gui_line *gui_chat_get_first_line_displayed (struct t_gui_buffer *buffer);
+extern struct t_gui_line *gui_chat_get_last_line_displayed (struct t_gui_buffer *buffer);
+extern struct t_gui_line *gui_chat_get_prev_line_displayed (struct t_gui_line *line);
+extern struct t_gui_line *gui_chat_get_next_line_displayed (struct t_gui_line *line);
extern int gui_chat_line_search (struct t_gui_line *line, char *text,
int case_sensitive);
+extern int gui_chat_line_match_regex (struct t_gui_line *line,
+ regex_t *regex_prefix,
+ regex_t *regex_message);
+extern int gui_chat_line_match_tags (struct t_gui_line *line, int tags_count,
+ char **tags_array);
extern void gui_chat_line_free (struct t_gui_line *line);
-extern void gui_chat_printf_date (struct t_gui_buffer *buffer, time_t date,
- char *message, ...);
+extern void gui_chat_printf_date_tags (struct t_gui_buffer *buffer,
+ time_t date, char *tags,
+ char *message, ...);
/* chat functions (GUI dependent) */
diff --git a/src/gui/gui-color.c b/src/gui/gui-color.c
index 6b34b758c..c267b1200 100644
--- a/src/gui/gui-color.c
+++ b/src/gui/gui-color.c
@@ -116,3 +116,16 @@ gui_color_decode (unsigned char *string)
out[out_pos] = '\0';
return out;
}
+
+/*
+ * gui_color_free: free a color
+ */
+
+void
+gui_color_free (struct t_gui_color *color)
+{
+ if (color->string)
+ free (color->string);
+
+ free (color);
+}
diff --git a/src/gui/gui-color.h b/src/gui/gui-color.h
index 55e437034..ff6d431cd 100644
--- a/src/gui/gui-color.h
+++ b/src/gui/gui-color.h
@@ -147,6 +147,7 @@ extern struct t_gui_color *gui_color[GUI_NUM_COLORS];
extern int gui_color_search_config (char *color_name);
extern unsigned char *gui_color_decode (unsigned char *string);
+extern void gui_color_free (struct t_gui_color *color);
/* color functions (GUI dependent) */
diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c
index 9d8b5a974..7c41879b0 100644
--- a/src/gui/gui-completion.c
+++ b/src/gui/gui-completion.c
@@ -262,6 +262,27 @@ gui_completion_list_add_buffers_names (struct t_gui_completion *completion)
}
/*
+ * gui_completion_list_add_buffers_categories_names: add buffers categories
+ * and names to completion
+ * list
+ */
+
+void
+gui_completion_list_add_buffers_categories_names (struct t_gui_completion *completion)
+{
+ struct t_gui_buffer *ptr_buffer;
+ char name[256];
+
+ for (ptr_buffer = gui_buffers; ptr_buffer;
+ ptr_buffer = ptr_buffer->next_buffer)
+ {
+ snprintf (name, sizeof (name), "%s.%s",
+ ptr_buffer->category, ptr_buffer->name);
+ gui_completion_list_add (completion, name, 0, WEECHAT_LIST_POS_SORT);
+ }
+}
+
+/*
* gui_completion_list_add_buffers_categories: add buffers categories to
* completion list
*/
@@ -728,6 +749,9 @@ gui_completion_build_list_template (struct t_gui_completion *completion,
case 'b': /* buffers names */
gui_completion_list_add_buffers_names (completion);
break;
+ case 'B': /* buffers categories + names */
+ gui_completion_list_add_buffers_categories_names (completion);
+ break;
case 'c': /* buffers categories */
gui_completion_list_add_buffers_categories (completion);
break;
diff --git a/src/gui/gui-filter.c b/src/gui/gui-filter.c
new file mode 100644
index 000000000..b5259a788
--- /dev/null
+++ b/src/gui/gui-filter.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* gui-filter.c: filter functions, used by all GUI */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+
+#include "../core/weechat.h"
+#include "../core/wee-hook.h"
+#include "../core/wee-log.h"
+#include "../core/wee-string.h"
+#include "../plugins/plugin.h"
+#include "gui-filter.h"
+#include "gui-buffer.h"
+#include "gui-chat.h"
+
+
+struct t_gui_filter *gui_filters = NULL; /* first filter */
+struct t_gui_filter *last_gui_filter = NULL; /* last filter */
+int gui_filters_enabled = 1; /* filters enabled? */
+
+
+/*
+ * gui_filter_enable: enable filters
+ */
+
+void
+gui_filter_enable ()
+{
+ struct t_gui_buffer *ptr_buffer;
+
+ if (!gui_filters_enabled)
+ {
+ gui_filters_enabled = 1;
+
+ /* ask refresh for buffer with hidden lines */
+ for (ptr_buffer = gui_buffers; ptr_buffer;
+ ptr_buffer = ptr_buffer->next_buffer)
+ {
+ if (ptr_buffer->lines_hidden)
+ {
+ hook_signal_send ("buffer_lines_hidden",
+ WEECHAT_HOOK_SIGNAL_POINTER, ptr_buffer);
+ }
+ if (ptr_buffer->lines_hidden)
+ ptr_buffer->chat_refresh_needed = 1;
+ }
+ }
+
+ hook_signal_send ("filters_enabled",
+ WEECHAT_HOOK_SIGNAL_STRING, NULL);
+}
+
+/*
+ * gui_filter_disable: disable filters
+ */
+
+void
+gui_filter_disable ()
+{
+ struct t_gui_buffer *ptr_buffer;
+
+ if (gui_filters_enabled)
+ {
+ gui_filters_enabled = 0;
+
+ /* ask refresh for buffer with hidden lines */
+ for (ptr_buffer = gui_buffers; ptr_buffer;
+ ptr_buffer = ptr_buffer->next_buffer)
+ {
+ if (ptr_buffer->lines_hidden)
+ {
+ hook_signal_send ("buffer_lines_hidden",
+ WEECHAT_HOOK_SIGNAL_POINTER, ptr_buffer);
+ }
+ if (ptr_buffer->lines_hidden)
+ ptr_buffer->chat_refresh_needed = 1;
+ }
+ }
+
+ hook_signal_send ("filters_disabled",
+ WEECHAT_HOOK_SIGNAL_STRING, NULL);
+}
+
+/*
+ * gui_filter_check_line: return 1 if a line should be displayed, or
+ * 0 if line is hidden (tag or regex found)
+ */
+
+int
+gui_filter_check_line (struct t_gui_buffer *buffer, struct t_gui_line *line)
+{
+ struct t_gui_filter *ptr_filter;
+
+ /* make C compiler happy */
+ (void) buffer;
+
+ for (ptr_filter = gui_filters; ptr_filter;
+ ptr_filter = ptr_filter->next_filter)
+ {
+ /* check buffer name */
+ if (gui_buffer_match_category_name (buffer,
+ ptr_filter->buffer, 0))
+ {
+ /* check line with regex */
+ if (gui_chat_line_match_regex (line,
+ ptr_filter->regex_prefix,
+ ptr_filter->regex_message))
+ return 0;
+
+ if ((strcmp (ptr_filter->tags, "*") != 0)
+ && (gui_chat_line_match_tags (line,
+ ptr_filter->tags_count,
+ ptr_filter->tags_array)))
+ return 0;
+ }
+ }
+
+ /* no tag or regex matching, then line is displayed */
+ return 1;
+}
+
+/*
+ * gui_filter_buffer: filter a buffer, using message filters
+ */
+
+void
+gui_filter_buffer (struct t_gui_buffer *buffer)
+{
+ struct t_gui_line *ptr_line;
+ int line_displayed, lines_hidden;
+
+ lines_hidden = 0;
+
+ for (ptr_line = buffer->lines; ptr_line;
+ ptr_line = ptr_line->next_line)
+ {
+ line_displayed = gui_filter_check_line (buffer, ptr_line);
+
+ /* force chat refresh if at least one line changed */
+ if (ptr_line->displayed != line_displayed)
+ buffer->chat_refresh_needed = 1;
+
+ ptr_line->displayed = line_displayed;
+
+ if (!line_displayed)
+ lines_hidden = 1;
+ }
+
+ if (buffer->lines_hidden != lines_hidden)
+ {
+ buffer->lines_hidden = lines_hidden;
+ hook_signal_send ("buffer_lines_hidden",
+ WEECHAT_HOOK_SIGNAL_POINTER, buffer);
+ }
+}
+
+/*
+ * gui_filter_all_buffers: filter all buffers, using message filters
+ */
+
+void
+gui_filter_all_buffers ()
+{
+ struct t_gui_buffer *ptr_buffer;
+
+ for (ptr_buffer = gui_buffers; ptr_buffer;
+ ptr_buffer = ptr_buffer->next_buffer)
+ {
+ gui_filter_buffer (ptr_buffer);
+ }
+}
+
+/*
+ * gui_filter_search: search a filter
+ */
+
+struct t_gui_filter *
+gui_filter_search (char *buffer, char *tags, char *regex)
+{
+ struct t_gui_filter *ptr_filter;
+
+ for (ptr_filter = gui_filters; ptr_filter;
+ ptr_filter = ptr_filter->next_filter)
+ {
+ if ((strcmp (ptr_filter->buffer, buffer) == 0)
+ && (strcmp (ptr_filter->tags, tags) == 0)
+ && (strcmp (ptr_filter->regex, regex) == 0))
+ return ptr_filter;
+ }
+
+ /* no filter found */
+ return NULL;
+}
+
+/*
+ * gui_filter_search_by_number: search a filter by number (first is #1)
+ */
+
+struct t_gui_filter *
+gui_filter_search_by_number (int number)
+{
+ struct t_gui_filter *ptr_filter;
+ int i;
+
+ i = 1;
+ for (ptr_filter = gui_filters; ptr_filter;
+ ptr_filter = ptr_filter->next_filter)
+ {
+ if (i == number)
+ return ptr_filter;
+ i++;
+ }
+
+ /* no filter found */
+ return NULL;
+}
+
+/*
+ * gui_filter_new: create a new filter
+ */
+
+struct t_gui_filter *
+gui_filter_new (char *buffer, char *tags, char *regex)
+{
+ struct t_gui_filter *new_filter;
+ regex_t *regex1, *regex2;
+ char *pos_tab, *regex_prefix, *pos_regex_message;
+
+ if (!buffer || !tags || !regex)
+ return NULL;
+
+ regex1 = NULL;
+ regex2 = NULL;
+ if (strcmp (regex, "*") != 0)
+ {
+ pos_tab = strstr (regex, "\\t");
+ if (pos_tab)
+ {
+ regex_prefix = string_strndup (regex, pos_tab - regex);
+ pos_regex_message = pos_tab + 2;
+ }
+ else
+ {
+ regex_prefix = strdup (regex);
+ pos_regex_message = regex;
+ }
+
+ if (!regex_prefix)
+ return NULL;
+
+ regex1 = (regex_t *)malloc (sizeof (regex_t));
+ if (regex1)
+ {
+ if (regcomp (regex1, regex_prefix,
+ REG_NOSUB | REG_ICASE) != 0)
+ {
+ free (regex_prefix);
+ free (regex1);
+ return NULL;
+ }
+ }
+
+ regex2 = (regex_t *)malloc (sizeof (regex_t));
+ if (regex2)
+ {
+ if (regcomp (regex2, pos_regex_message,
+ REG_NOSUB | REG_ICASE) != 0)
+ {
+ free (regex_prefix);
+ if (regex1)
+ free (regex1);
+ free (regex2);
+ return NULL;
+ }
+ }
+
+ free (regex_prefix);
+ }
+
+ /* create new filter */
+ new_filter = (struct t_gui_filter *)(malloc (sizeof (struct t_gui_filter)));
+ if (new_filter)
+ {
+ /* init filter */
+ new_filter->buffer = (buffer) ? strdup (buffer) : strdup ("*");
+ if (tags)
+ {
+ new_filter->tags = (tags) ? strdup (tags) : NULL;
+ new_filter->tags_array = string_explode (tags, ",", 0, 0,
+ &new_filter->tags_count);
+ }
+ else
+ {
+ new_filter->tags = NULL;
+ new_filter->tags_count = 0;
+ new_filter->tags_array = NULL;
+ }
+ new_filter->regex = strdup (regex);
+ new_filter->regex_prefix = regex1;
+ new_filter->regex_message = regex2;
+
+ /* add filter to filters list */
+ new_filter->prev_filter = last_gui_filter;
+ if (gui_filters)
+ last_gui_filter->next_filter = new_filter;
+ else
+ gui_filters = new_filter;
+ last_gui_filter = new_filter;
+ new_filter->next_filter = NULL;
+
+ gui_filter_all_buffers ();
+
+ hook_signal_send ("filter_added",
+ WEECHAT_HOOK_SIGNAL_POINTER, new_filter);
+ }
+
+ return new_filter;
+}
+
+/*
+ * gui_filter_free: remove a filter
+ */
+
+void
+gui_filter_free (struct t_gui_filter *filter)
+{
+ hook_signal_send ("filter_removing",
+ WEECHAT_HOOK_SIGNAL_POINTER, filter);
+
+ /* free data */
+ if (filter->buffer)
+ free (filter->buffer);
+ if (filter->tags)
+ free (filter->tags);
+ if (filter->regex)
+ free (filter->regex);
+ if (filter->regex_prefix)
+ {
+ regfree (filter->regex_prefix);
+ free (filter->regex_prefix);
+ }
+ if (filter->regex_message)
+ {
+ regfree (filter->regex_message);
+ free (filter->regex_message);
+ }
+
+ /* remove filter from filters list */
+ if (filter->prev_filter)
+ filter->prev_filter->next_filter = filter->next_filter;
+ if (filter->next_filter)
+ filter->next_filter->prev_filter = filter->prev_filter;
+ if (gui_filters == filter)
+ gui_filters = filter->next_filter;
+ if (last_gui_filter == filter)
+ last_gui_filter = filter->prev_filter;
+
+ free (filter);
+
+ gui_filter_all_buffers ();
+
+ hook_signal_send ("filter_removed", WEECHAT_HOOK_SIGNAL_STRING, NULL);
+}
+
+/*
+ * gui_filter_free_all: remove all filters
+ */
+
+void
+gui_filter_free_all ()
+{
+ while (gui_filters)
+ {
+ gui_filter_free (gui_filters);
+ }
+}
+
+/*
+ * gui_filter_print_log: print filter infos in log (usually for crash dump)
+ */
+
+void
+gui_filter_print_log ()
+{
+ struct t_gui_filter *ptr_filter;
+
+ log_printf ("");
+ log_printf ("gui_filters_enabled = %d", gui_filters_enabled);
+
+ for (ptr_filter = gui_filters; ptr_filter;
+ ptr_filter = ptr_filter->next_filter)
+ {
+ log_printf ("");
+ log_printf ("[filter (addr:0x%x)]", ptr_filter);
+ log_printf (" buffer . . . . . . . . : '%s'", ptr_filter->buffer);
+ log_printf (" tags . . . . . . . . . : '%s'", ptr_filter->tags);
+ log_printf (" regex. . . . . . . . . : '%s'", ptr_filter->regex);
+ log_printf (" regex_prefix . . . . . : 0x%x", ptr_filter->regex_prefix);
+ log_printf (" regex_message. . . . . : 0x%x", ptr_filter->regex_message);
+ log_printf (" prev_filter. . . . . . : 0x%x", ptr_filter->prev_filter);
+ log_printf (" next_filter. . . . . . : 0x%x", ptr_filter->next_filter);
+ }
+}
diff --git a/src/gui/gui-filter.h b/src/gui/gui-filter.h
new file mode 100644
index 000000000..ef900a889
--- /dev/null
+++ b/src/gui/gui-filter.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __WEECHAT_GUI_FILTER_H
+#define __WEECHAT_GUI_FILTER_H 1
+
+#include <regex.h>
+
+/* filter structures */
+
+struct t_gui_line;
+
+struct t_gui_filter
+{
+ char *buffer; /* name of buffer */
+ char *tags; /* tags */
+ int tags_count; /* number of tags */
+ char **tags_array; /* array of tags */
+ char *regex; /* regex */
+ regex_t *regex_prefix; /* regex for line prefix */
+ regex_t *regex_message; /* regex for line message */
+ struct t_gui_filter *prev_filter; /* link to previous line */
+ struct t_gui_filter *next_filter; /* link to next line */
+};
+
+/* filter variables */
+
+extern struct t_gui_filter *gui_filters;
+extern struct t_gui_filter *last_gui_filter;
+extern int gui_filters_enabled;
+
+/* filter functions */
+
+extern void gui_filter_enable ();
+extern void gui_filter_disable ();
+extern int gui_filter_check_line (struct t_gui_buffer *buffer,
+ struct t_gui_line *line);
+extern struct t_gui_filter *gui_filter_search (char *buffer, char *tags,
+ char *regex);
+extern struct t_gui_filter *gui_filter_search_by_number (int number);
+extern struct t_gui_filter *gui_filter_new (char *buffer, char *tags,
+ char *regex);
+extern void gui_filter_free (struct t_gui_filter *filter);
+extern void gui_filter_free_all ();
+extern void gui_filter_print_log ();
+
+#endif /* gui-filter.h */
diff --git a/src/gui/gui-keyboard.c b/src/gui/gui-keyboard.c
index b0e6784b2..d32acb99e 100644
--- a/src/gui/gui-keyboard.c
+++ b/src/gui/gui-keyboard.c
@@ -714,7 +714,9 @@ void
gui_keyboard_free_all ()
{
while (gui_keys)
+ {
gui_keyboard_free (gui_keys);
+ }
}
/*
@@ -827,3 +829,18 @@ gui_keyboard_paste_cancel ()
gui_keyboard_buffer_reset ();
gui_keyboard_paste_pending = 0;
}
+
+/*
+ * gui_keyboard_end: end keyboard (free some data)
+ */
+
+void
+gui_keyboard_end ()
+{
+ /* free keyboard buffer */
+ if (gui_keyboard_buffer)
+ free (gui_keyboard_buffer);
+
+ /* free all keys */
+ gui_keyboard_free_all ();
+}
diff --git a/src/gui/gui-keyboard.h b/src/gui/gui-keyboard.h
index 8971963b9..065d59f54 100644
--- a/src/gui/gui-keyboard.h
+++ b/src/gui/gui-keyboard.h
@@ -76,6 +76,7 @@ extern void gui_keyboard_buffer_add (int key);
extern int gui_keyboard_get_paste_lines ();
extern void gui_keyboard_paste_accept ();
extern void gui_keyboard_paste_cancel ();
+extern void gui_keyboard_end ();
/* keyboard functions (GUI dependent) */
diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c
index f2ee25a40..85c285d66 100644
--- a/src/gui/gui-window.c
+++ b/src/gui/gui-window.c
@@ -39,6 +39,7 @@
#include "gui-window.h"
#include "gui-buffer.h"
#include "gui-chat.h"
+#include "gui-filter.h"
#include "gui-input.h"
#include "gui-hotlist.h"
#include "gui-status.h"
@@ -280,7 +281,11 @@ gui_window_free (struct t_gui_window *window)
window->buffer->num_displayed--;
/* free data */
- gui_window_objects_free (window, 1);
+ if (window->gui_objects)
+ {
+ gui_window_objects_free (window, 1);
+ free (window->gui_objects);
+ }
/* remove window from windows list */
if (window->prev_window)
@@ -448,7 +453,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
number = 0;
time_letter = ' ';
- // search direction
+ /* search direction */
if (scroll[0] == '-')
{
direction = -1;
@@ -460,7 +465,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
scroll++;
}
- // search number and letter
+ /* search number and letter */
char *pos = scroll;
while (pos && pos[0] && isdigit (pos[0]))
{
@@ -481,7 +486,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
pos[0] = '\0';
error = NULL;
number = strtol (scroll, &error, 10);
- if (!error || (error[0] != '\0'))
+ if (!error || error[0])
number = 0;
pos[0] = saved_char;
}
@@ -491,15 +496,27 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
if ((number == 0) && (time_letter == ' '))
return;
- // do the scroll!
+ /* do the scroll! */
stop = 0;
count_msg = 0;
if (direction < 0)
+ {
ptr_line = (window->start_line) ?
window->start_line : window->buffer->last_line;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->prev_line;
+ }
+ }
else
+ {
ptr_line = (window->start_line) ?
window->start_line : window->buffer->lines;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->next_line;
+ }
+ }
old_date = ptr_line->date;
date_tmp = localtime (&old_date);
@@ -507,7 +524,8 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
while (ptr_line)
{
- ptr_line = (direction < 0) ? ptr_line->prev_line : ptr_line->next_line;
+ ptr_line = (direction < 0) ?
+ gui_chat_get_prev_line_displayed (ptr_line) : gui_chat_get_next_line_displayed (ptr_line);
if (ptr_line)
{
@@ -614,7 +632,7 @@ gui_window_scroll (struct t_gui_window *window, char *scroll)
window->start_line = ptr_line;
window->start_line_pos = 0;
window->first_line_displayed =
- (window->start_line == window->buffer->lines);
+ (window->start_line == gui_chat_get_first_line_displayed (window->buffer));
window->buffer->chat_refresh_needed = 1;
gui_status_refresh_needed = 1;
return;
@@ -644,6 +662,10 @@ gui_window_search_text (struct t_gui_window *window)
{
ptr_line = (window->start_line) ?
window->start_line->prev_line : window->buffer->last_line;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->prev_line;
+ }
while (ptr_line)
{
if (gui_chat_line_search (ptr_line,
@@ -653,12 +675,12 @@ gui_window_search_text (struct t_gui_window *window)
window->start_line = ptr_line;
window->start_line_pos = 0;
window->first_line_displayed =
- (window->start_line == window->buffer->lines);
+ (window->start_line == gui_chat_get_first_line_displayed (window->buffer));
window->buffer->chat_refresh_needed = 1;
gui_status_refresh_needed = 1;
return 1;
}
- ptr_line = ptr_line->prev_line;
+ ptr_line = gui_chat_get_prev_line_displayed (ptr_line);
}
}
}
@@ -669,6 +691,10 @@ gui_window_search_text (struct t_gui_window *window)
{
ptr_line = (window->start_line) ?
window->start_line->next_line : window->buffer->lines->next_line;
+ while (ptr_line && !gui_chat_line_displayed (ptr_line))
+ {
+ ptr_line = ptr_line->next_line;
+ }
while (ptr_line)
{
if (gui_chat_line_search (ptr_line,
@@ -683,7 +709,7 @@ gui_window_search_text (struct t_gui_window *window)
gui_status_refresh_needed = 1;
return 1;
}
- ptr_line = ptr_line->next_line;
+ ptr_line = gui_chat_get_next_line_displayed (ptr_line);
}
}
}