summaryrefslogtreecommitdiff
path: root/src/gui/gui-chat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/gui-chat.c')
-rw-r--r--src/gui/gui-chat.c574
1 files changed, 335 insertions, 239 deletions
diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c
index 9af2d2371..b0b18ec7d 100644
--- a/src/gui/gui-chat.c
+++ b/src/gui/gui-chat.c
@@ -55,7 +55,7 @@ int gui_chat_time_length = 0; /* length of time for each line (in chars) */
int gui_chat_mute = GUI_CHAT_MUTE_DISABLED; /* mute mode */
struct t_gui_buffer *gui_chat_mute_buffer = NULL; /* mute buffer */
int gui_chat_display_tags = 0; /* display tags? */
-char *gui_chat_lines_waiting_buffer = NULL; /* lines waiting for core */
+char **gui_chat_lines_waiting_buffer = NULL; /* lines waiting for core */
/* buffer */
@@ -635,6 +635,278 @@ gui_chat_build_string_message_tags (struct t_gui_line *line)
}
/*
+ * Checks if the buffer pointer is valid for printing a chat message,
+ * according to buffer type.
+ *
+ * Returns:
+ * 1: buffer is valid
+ * 0: buffer is not valid
+ */
+
+int
+gui_chat_buffer_valid (struct t_gui_buffer *buffer,
+ int buffer_type)
+{
+ /* check buffer pointer, closing and type */
+ if (!buffer || !gui_buffer_valid (buffer)
+ || buffer->closing
+ || ((int)(buffer->type) != buffer_type))
+ {
+ return 0;
+ }
+
+ /* check if mute is enabled */
+ if ((buffer_type == GUI_BUFFER_TYPE_FORMATTED)
+ && ((gui_chat_mute == GUI_CHAT_MUTE_ALL_BUFFERS)
+ || ((gui_chat_mute == GUI_CHAT_MUTE_BUFFER)
+ && (gui_chat_mute_buffer == buffer))))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Displays a message in a buffer with optional date and tags.
+ * This function is called internally by the function
+ * gui_chat_printf_date_tags.
+ */
+
+void
+gui_chat_printf_date_tags_internal (struct t_gui_buffer *buffer,
+ time_t date,
+ time_t date_printed,
+ const char *tags,
+ char *message)
+{
+ int display_time, length_data, length_str;
+ char *ptr_msg, *pos_prefix, *pos_tab;
+ char *modifier_data, *string, *new_string;
+ struct t_gui_line *new_line;
+
+ new_line = NULL;
+ string = NULL;
+ modifier_data = NULL;
+ new_string = NULL;
+
+ display_time = 1;
+
+ pos_prefix = NULL;
+ ptr_msg = message;
+
+ /* space followed by tab => prefix ignored */
+ if ((ptr_msg[0] == ' ') && (ptr_msg[1] == '\t'))
+ {
+ ptr_msg += 2;
+ }
+ else
+ {
+ /* if two first chars are tab, then do not display time */
+ if ((ptr_msg[0] == '\t') && (ptr_msg[1] == '\t'))
+ {
+ display_time = 0;
+ ptr_msg += 2;
+ }
+ else
+ {
+ /* if tab found, use prefix (before tab) */
+ pos_tab = strchr (ptr_msg, '\t');
+ if (pos_tab)
+ {
+ pos_tab[0] = '\0';
+ pos_prefix = ptr_msg;
+ ptr_msg = pos_tab + 1;
+ }
+ }
+ }
+
+ new_line = gui_line_new (buffer,
+ -1,
+ (display_time) ? date : 0,
+ date_printed,
+ tags,
+ pos_prefix,
+ ptr_msg);
+ if (!new_line)
+ goto no_print;
+
+ hook_line_exec (new_line);
+
+ if (!new_line->data->buffer)
+ goto no_print;
+
+ /* call modifier for message printed ("weechat_print") */
+ if (buffer)
+ {
+ length_data = strlen (gui_buffer_get_plugin_name (new_line->data->buffer)) +
+ 1 +
+ strlen (new_line->data->buffer->name) +
+ 1 +
+ ((tags) ? strlen (tags) : 0) +
+ 1;
+ modifier_data = malloc (length_data);
+ length_str = ((new_line->data->prefix) ? strlen (new_line->data->prefix) + 1 : 0) +
+ (new_line->data->message ? strlen (new_line->data->message) : 0) +
+ 1;
+ string = malloc (length_str);
+ if (modifier_data && string)
+ {
+ snprintf (modifier_data, length_data,
+ "%s;%s;%s",
+ gui_buffer_get_plugin_name (new_line->data->buffer),
+ new_line->data->buffer->name,
+ (tags) ? tags : "");
+ snprintf (string, length_str,
+ "%s%s%s",
+ (new_line->data->prefix) ? new_line->data->prefix : "",
+ (new_line->data->prefix) ? "\t" : "",
+ (new_line->data->message) ? new_line->data->message : "");
+ new_string = hook_modifier_exec (NULL,
+ "weechat_print",
+ modifier_data,
+ string);
+ if (new_string)
+ {
+ if (!new_string[0] && message[0])
+ {
+ /*
+ * modifier returned empty message, then we'll not
+ * print anything
+ */
+ goto no_print;
+ }
+ else if (strcmp (message, new_string) != 0)
+ {
+ /* use new message if there are changes */
+ pos_prefix = NULL;
+ ptr_msg = new_string;
+ pos_tab = strchr (new_string, '\t');
+ if (pos_tab)
+ {
+ pos_tab[0] = '\0';
+ pos_prefix = ptr_msg;
+ ptr_msg = pos_tab + 1;
+ }
+ if (pos_prefix)
+ {
+ if (new_line->data->prefix)
+ string_shared_free (new_line->data->prefix);
+ new_line->data->prefix = (char *)string_shared_get (pos_prefix);
+ new_line->data->prefix_length = gui_chat_strlen_screen (pos_prefix);
+ }
+ else
+ {
+ if (new_line->data->prefix)
+ {
+ free (new_line->data->prefix);
+ new_line->data->prefix = NULL;
+ }
+ new_line->data->prefix_length = 0;
+ }
+ if (new_line->data->message)
+ free (new_line->data->message);
+ new_line->data->message = strdup (ptr_msg);
+ }
+ }
+ }
+ }
+
+ gui_line_add (new_line);
+ if (new_line->data->buffer && buffer->print_hooks_enabled)
+ hook_print_exec (new_line->data->buffer, new_line);
+
+ gui_buffer_ask_chat_refresh (new_line->data->buffer, 1);
+
+ if (string)
+ free (string);
+ if (modifier_data)
+ free (modifier_data);
+ if (new_string)
+ free (new_string);
+
+ return;
+
+no_print:
+ if (new_line)
+ {
+ gui_line_free_data (new_line);
+ free (new_line);
+ }
+ if (string)
+ free (string);
+ if (modifier_data)
+ free (modifier_data);
+ if (new_string)
+ free (new_string);
+}
+
+/*
+ * Adds a line when WeeChat is waiting for the core buffer.
+ *
+ * The line is stored in an internal buffer area and will be displayed later
+ * in the core buffer.
+ */
+
+void
+gui_chat_add_line_waiting_buffer (const char *message)
+{
+ if (!gui_chat_lines_waiting_buffer)
+ {
+ gui_chat_lines_waiting_buffer = string_dyn_alloc (1024);
+ if (!gui_chat_lines_waiting_buffer)
+ return;
+ }
+
+ if (*gui_chat_lines_waiting_buffer[0])
+ string_dyn_concat (gui_chat_lines_waiting_buffer, "\n");
+
+ string_dyn_concat (gui_chat_lines_waiting_buffer, message);
+}
+
+/*
+ * Displays lines that are waiting for buffer.
+ *
+ * If "f" is not NULL, the lines are written in this file (which is commonly
+ * stdout or stderr).
+ * If "f" is NULL, the lines are displayed in core buffer if the GUI is
+ * initialized (gui_init_ok == 1), otherwise on stdout.
+ */
+
+void
+gui_chat_print_lines_waiting_buffer (FILE *f)
+{
+ char **lines;
+ int num_lines, i;
+
+ if (gui_chat_lines_waiting_buffer)
+ {
+ lines = string_split (*gui_chat_lines_waiting_buffer, "\n", 0, 0,
+ &num_lines);
+ if (lines)
+ {
+ for (i = 0; i < num_lines; i++)
+ {
+ if (!f && gui_init_ok)
+ gui_chat_printf (NULL, "%s", lines[i]);
+ else
+ string_fprintf ((f) ? f : stdout, "%s\n", lines[i]);
+ }
+ string_free_split (lines);
+ }
+ /*
+ * gui_chat_lines_waiting_buffer may be NULL after call to
+ * gui_chat_printf (if not enough memory)
+ */
+ }
+ if (gui_chat_lines_waiting_buffer)
+ {
+ string_dyn_free (gui_chat_lines_waiting_buffer, 1);
+ gui_chat_lines_waiting_buffer = NULL;
+ }
+}
+
+/*
* Displays a message in a buffer with optional date and tags.
*
* Note: this function works only with formatted buffers (not buffers with free
@@ -646,38 +918,19 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date,
const char *tags, const char *message, ...)
{
time_t date_printed;
- int display_time, length, at_least_one_message_printed, msg_discarded;
- char *pos, *pos_prefix, *pos_tab, *pos_end, *pos_lines;
- char *modifier_data, *new_msg, *ptr_msg, *lines_waiting;
- struct t_gui_line *ptr_line;
+ char *pos, *pos_end;
if (!message)
return;
- if (!gui_buffer_valid (buffer))
- return;
-
if (gui_init_ok)
{
if (!buffer)
buffer = gui_buffer_search_main ();
-
- if (!buffer || buffer->closing)
- return;
-
- if (buffer->type != GUI_BUFFER_TYPE_FORMATTED)
- buffer = gui_buffers;
-
- if (buffer->type != GUI_BUFFER_TYPE_FORMATTED)
+ if (!gui_chat_buffer_valid (buffer, GUI_BUFFER_TYPE_FORMATTED))
return;
}
- /* if mute is enabled for buffer (or all buffers), then just return */
- if ((gui_chat_mute == GUI_CHAT_MUTE_ALL_BUFFERS)
- || ((gui_chat_mute == GUI_CHAT_MUTE_BUFFER)
- && (gui_chat_mute_buffer == buffer)))
- return;
-
weechat_va_format (message);
if (!vbuffer)
return;
@@ -688,8 +941,6 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date,
if (date <= 0)
date = date_printed;
- at_least_one_message_printed = 0;
-
pos = vbuffer;
while (pos)
{
@@ -698,145 +949,19 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date,
if (pos_end)
pos_end[0] = '\0';
- /* call modifier for message printed ("weechat_print") */
- new_msg = NULL;
- msg_discarded = 0;
- if (buffer)
+ if (gui_init_ok)
{
- length = strlen (gui_buffer_get_plugin_name (buffer)) + 1 +
- strlen (buffer->name) + 1 + ((tags) ? strlen (tags) : 0) + 1;
- modifier_data = malloc (length);
- if (modifier_data)
- {
- snprintf (modifier_data, length, "%s;%s;%s",
- gui_buffer_get_plugin_name (buffer),
- buffer->name,
- (tags) ? tags : "");
- new_msg = hook_modifier_exec (NULL,
- "weechat_print",
- modifier_data,
- pos);
- free (modifier_data);
- if (new_msg)
- {
- if (!new_msg[0] && pos[0])
- {
- /*
- * modifier returned empty message, then we'll not
- * print anything
- */
- free (new_msg);
- new_msg = NULL;
- msg_discarded = 1;
- }
- else if (strcmp (message, new_msg) == 0)
- {
- /* no changes in new message */
- free (new_msg);
- new_msg = NULL;
- }
- }
- }
+ gui_chat_printf_date_tags_internal (buffer, date, date_printed,
+ tags, pos);
}
-
- if (!msg_discarded)
+ else
{
- pos_prefix = NULL;
- display_time = 1;
- ptr_msg = (new_msg) ? new_msg : pos;
-
- /* space followed by tab => prefix ignored */
- if ((ptr_msg[0] == ' ') && (ptr_msg[1] == '\t'))
- {
- ptr_msg += 2;
- }
- else
- {
- /* if two first chars are tab, then do not display time */
- if ((ptr_msg[0] == '\t') && (ptr_msg[1] == '\t'))
- {
- display_time = 0;
- ptr_msg += 2;
- }
- else
- {
- /* if tab found, use prefix (before tab) */
- pos_tab = strchr (ptr_msg, '\t');
- if (pos_tab)
- {
- pos_tab[0] = '\0';
- pos_prefix = ptr_msg;
- ptr_msg = pos_tab + 1;
- }
- }
- }
-
- if (gui_init_ok)
- {
- ptr_line = gui_line_add (buffer, (display_time) ? date : 0,
- date_printed, tags, pos_prefix, ptr_msg);
- if (ptr_line)
- {
- if (buffer && buffer->print_hooks_enabled)
- hook_print_exec (buffer, ptr_line);
- if (ptr_line->data->displayed)
- at_least_one_message_printed = 1;
- }
- }
- else
- {
- length = ((pos_prefix) ? strlen (pos_prefix) + 1 : 0) +
- strlen (ptr_msg) + 1;
- if (gui_chat_lines_waiting_buffer)
- {
- length += strlen (gui_chat_lines_waiting_buffer) + 1;
- lines_waiting = realloc (gui_chat_lines_waiting_buffer, length);
- if (lines_waiting)
- {
- gui_chat_lines_waiting_buffer = lines_waiting;
- }
- else
- {
- free (gui_chat_lines_waiting_buffer);
- gui_chat_lines_waiting_buffer = NULL;
- }
- }
- else
- {
- gui_chat_lines_waiting_buffer = malloc (length);
- if (gui_chat_lines_waiting_buffer)
- gui_chat_lines_waiting_buffer[0] = '\0';
- }
- if (gui_chat_lines_waiting_buffer)
- {
- pos_lines = gui_chat_lines_waiting_buffer +
- strlen (gui_chat_lines_waiting_buffer);
- if (pos_lines > gui_chat_lines_waiting_buffer)
- {
- pos_lines[0] = '\n';
- pos_lines++;
- }
- if (pos_prefix)
- {
- memcpy (pos_lines, pos_prefix, strlen (pos_prefix));
- pos_lines += strlen (pos_prefix);
- pos_lines[0] = '\t';
- pos_lines++;
- }
- memcpy (pos_lines, ptr_msg, strlen (ptr_msg) + 1);
- }
- }
+ gui_chat_add_line_waiting_buffer (pos);
}
- if (new_msg)
- free (new_msg);
-
pos = (pos_end && pos_end[1]) ? pos_end + 1 : NULL;
}
- if (gui_init_ok && at_least_one_message_printed)
- gui_buffer_ask_chat_refresh (buffer, 1);
-
free (vbuffer);
}
@@ -850,25 +975,17 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date,
void
gui_chat_printf_y (struct t_gui_buffer *buffer, int y, const char *message, ...)
{
- struct t_gui_line *ptr_line;
- int i, num_lines_to_add;
+ struct t_gui_line *ptr_line, *new_line, *new_line_empty;
+ int i, last_y, num_lines_to_add;
- if (!gui_buffer_valid (buffer))
+ if (gui_init_ok && !gui_chat_buffer_valid (buffer, GUI_BUFFER_TYPE_FREE))
return;
- if (gui_init_ok)
+ /* if y is negative, add a line -N lines after the last line */
+ if (y < 0)
{
- if (!buffer)
- buffer = gui_buffer_search_main ();
-
- if (!buffer || buffer->closing)
- return;
-
- if (buffer->type != GUI_BUFFER_TYPE_FREE)
- buffer = gui_buffers;
-
- if (buffer->type != GUI_BUFFER_TYPE_FREE)
- return;
+ y = (buffer->own_lines && buffer->own_lines->last_line) ?
+ buffer->own_lines->last_line->data->y - y : (-1 * y) - 1;
}
weechat_va_format (message);
@@ -877,42 +994,33 @@ gui_chat_printf_y (struct t_gui_buffer *buffer, int y, const char *message, ...)
utf8_normalize (vbuffer, '?');
- /* no message: delete line */
- if (!vbuffer[0])
+ new_line = gui_line_new (buffer, y, 0, 0, NULL, NULL, vbuffer);
+ if (!new_line)
+ goto end;
+
+ hook_line_exec (new_line);
+
+ if (!new_line->data->buffer)
{
- if (gui_init_ok && (y >= 0))
- {
- for (ptr_line = buffer->own_lines->first_line; ptr_line;
- ptr_line = ptr_line->next_line)
- {
- if (ptr_line->data->y >= y)
- break;
- }
- if (ptr_line && (ptr_line->data->y == y))
- {
- if (ptr_line->next_line)
- gui_line_clear (ptr_line);
- else
- gui_line_free (buffer, ptr_line);
- gui_buffer_ask_chat_refresh (buffer, 2);
- }
- }
+ gui_line_free_data (new_line);
+ free (new_line);
+ goto end;
}
- else
+
+ if (new_line->data->message && new_line->data->message[0])
{
if (gui_init_ok)
{
- /* if y is negative, add a line -N lines after the last line */
- if (y < 0)
+ /* compute the number of lines to add before y */
+ if (new_line->data->buffer->own_lines
+ && new_line->data->buffer->own_lines->last_line)
{
- y = (buffer->own_lines && buffer->own_lines->last_line) ?
- buffer->own_lines->last_line->data->y - y : (-1 * y) - 1;
+ num_lines_to_add = y - new_line->data->buffer->own_lines->last_line->data->y - 1;
}
- /* compute the number of lines to add before y */
- if (buffer->own_lines && buffer->own_lines->last_line)
- num_lines_to_add = y - buffer->own_lines->last_line->data->y - 1;
else
+ {
num_lines_to_add = y;
+ }
if (num_lines_to_add > 0)
{
/*
@@ -922,59 +1030,47 @@ gui_chat_printf_y (struct t_gui_buffer *buffer, int y, const char *message, ...)
*/
for (i = y - num_lines_to_add; i < y; i++)
{
- gui_line_add_y (buffer, i, "");
+ new_line_empty = gui_line_new (new_line->data->buffer,
+ i, 0, 0, NULL, NULL, "");
+ if (new_line_empty)
+ gui_line_add_y (new_line_empty);
}
}
- gui_line_add_y (buffer, y, vbuffer);
- gui_buffer_ask_chat_refresh (buffer, 1);
+ gui_line_add_y (new_line);
}
else
- string_fprintf (stdout, "%s\n", vbuffer);
+ {
+ string_fprintf (stdout, "%s\n", new_line->data->message);
+ gui_line_free_data (new_line);
+ free (new_line);
+ }
}
-
- free (vbuffer);
-}
-
-/*
- * Displays lines that are waiting for buffer.
- *
- * If "f" is not NULL, the lines are written in this file (which is commonly
- * stdout or stderr).
- * If "f" is NULL, the lines are displayed in core buffer if the GUI is
- * initialized (gui_init_ok == 1), otherwise on stdout.
- */
-
-void
-gui_chat_print_lines_waiting_buffer (FILE *f)
-{
- char **lines;
- int num_lines, i;
-
- if (gui_chat_lines_waiting_buffer)
+ else if (gui_init_ok)
{
- lines = string_split (gui_chat_lines_waiting_buffer, "\n", 0, 0,
- &num_lines);
- if (lines)
+ /* delete line */
+ last_y = (new_line->data->buffer->own_lines->last_line) ?
+ new_line->data->buffer->own_lines->last_line->data->y : 0;
+ if (y <= last_y)
{
- for (i = 0; i < num_lines; i++)
+ for (ptr_line = new_line->data->buffer->own_lines->first_line;
+ ptr_line; ptr_line = ptr_line->next_line)
{
- if (!f && gui_init_ok)
- gui_chat_printf (NULL, "%s", lines[i]);
+ if (ptr_line->data->y >= y)
+ break;
+ }
+ if (ptr_line && (ptr_line->data->y == y))
+ {
+ if (ptr_line->next_line)
+ gui_line_clear (ptr_line);
else
- string_fprintf ((f) ? f : stdout, "%s\n", lines[i]);
+ gui_line_free (new_line->data->buffer, ptr_line);
+ gui_buffer_ask_chat_refresh (new_line->data->buffer, 2);
}
- string_free_split (lines);
}
- /*
- * gui_chat_lines_waiting_buffer may be NULL after call to
- * gui_chat_printf (if not enough memory)
- */
- }
- if (gui_chat_lines_waiting_buffer)
- {
- free (gui_chat_lines_waiting_buffer);
- gui_chat_lines_waiting_buffer = NULL;
}
+
+end:
+ free (vbuffer);
}
/*
@@ -1106,7 +1202,7 @@ gui_chat_end ()
/* free lines waiting for buffer (should always be NULL here) */
if (gui_chat_lines_waiting_buffer)
{
- free (gui_chat_lines_waiting_buffer);
+ string_dyn_free (gui_chat_lines_waiting_buffer, 1);
gui_chat_lines_waiting_buffer = NULL;
}
}