diff --git a/src/ui/buffer.c b/src/ui/buffer.c index 9ba489b5..ad115986 100644 --- a/src/ui/buffer.c +++ b/src/ui/buffer.c @@ -30,6 +30,7 @@ */ #include "config.h" +#include "ui/window_list.h" #include #include @@ -51,12 +52,6 @@ #define STRDUP_OR_NULL(str) ((str) ? strdup(str) : NULL) -struct prof_buff_t -{ - GSList* entries; - int lines; -}; - static void _free_entry(ProfBuffEntry* entry); static ProfBuffEntry* _create_entry(const char* show_char, int pad_indent, GDateTime* time, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message, DeliveryReceipt* receipt, const char* const id, int y_start_pos, int y_end_pos); static void _buffer_add(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* time, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message, DeliveryReceipt* receipt, const char* const id, int y_start_pos, int y_end_pos, gboolean append); @@ -102,23 +97,24 @@ _buffer_add(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* t buffer->lines += e->_lines; - while (buffer->lines >= PAD_SIZE) { + // With 10% margin to ensure overflow prevention + while (buffer->lines >= PAD_SIZE - (PAD_SIZE / 10) && g_slist_length(buffer->entries) > 1) { // Delete message from the opposite size to free buffer GSList* buffer_entry_to_delete = append ? buffer->entries : g_slist_last(buffer->entries); ProfBuffEntry* entry_to_delete = (ProfBuffEntry*)buffer_entry_to_delete->data; + // log_debug("(Messages left in buffer: %d) DELETING: %s", g_slist_length(buffer->entries), entry_to_delete->id); buffer->lines -= entry_to_delete->_lines; _free_entry(entry_to_delete); buffer->entries = g_slist_delete_link(buffer->entries, buffer_entry_to_delete); } if (from_jid && y_end_pos == y_start_pos) { - log_warning("Ncurses Overflow! From: %s, position: %d, ID: %s, append: %s, used message buffer size: %d, rendered lines buffer size: %d", - from_jid, y_start_pos, id, append ? "TRUE" : "FALSE", g_slist_length(buffer->entries), PAD_SIZE); - // At this point we have a message that caused overflow of the render buffer. - // Ideally, we want to clean other messages to rerender everything properly. To do so, - // first we need to determine the size of the message that we are trying to display, - // then we need to print the message. - // However, _buffer_add is too late in the code to do this, therefore it has to be done in the win_print_old_history. + // win_redraw will redraw with entries above removed, + // it will also recalculate actual size of the message that caused overflow + int old_lines = buffer->lines; + win_redraw(wins_get_current()); + log_debug("Ncurses Overflow! From: %s, position: %d, ID: %s, append: %s, used message buffer size: %d, rendered lines: (old: %d/ actual: %d/ max: %d)", + from_jid, y_start_pos, id, append ? "TRUE" : "FALSE", g_slist_length(buffer->entries), old_lines, buffer->lines, PAD_SIZE); } buffer->entries = append ? g_slist_append(buffer->entries, e) : g_slist_prepend(buffer->entries, e); diff --git a/src/ui/buffer.h b/src/ui/buffer.h index 2e4a7be3..27989bed 100644 --- a/src/ui/buffer.h +++ b/src/ui/buffer.h @@ -68,6 +68,12 @@ typedef struct prof_buff_entry_t char* id; } ProfBuffEntry; +struct prof_buff_t +{ + GSList* entries; + int lines; +}; + typedef struct prof_buff_t* ProfBuff; ProfBuff buffer_create(); diff --git a/src/ui/window.c b/src/ui/window.c index fad8535c..b2dba5a5 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -2003,6 +2003,10 @@ win_redraw(ProfWin* window) _win_print_internal(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->display_from, e->message, e->receipt); } e->y_end_pos = getcury(window->layout->win); + // Recalculate lines (might be incorrect in case of NCurses overflow) + window->layout->buffer->lines -= e->_lines; + e->_lines = e->y_end_pos - e->y_start_pos; + window->layout->buffer->lines += e->_lines; } }