Skip to content

Commit

Permalink
Fix scrolling (work in progress, poc)
Browse files Browse the repository at this point in the history
Calculate amount of displayed lines in buffer to avoid overflow in the curses.

It has a few issues to be resolved before eventual clean up and readiness status.

Fix #1934
  • Loading branch information
H3rnand3zzz committed Nov 23, 2023
1 parent 9ef05f4 commit cc67d05
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 28 deletions.
6 changes: 4 additions & 2 deletions src/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ log_database_get_previous_chat(const gchar* const contact_barejid, const char* s
GDateTime* now = g_date_time_new_now_local();
auto_gchar gchar* end_date_fmt = end_time ? end_time : g_date_time_format_iso8601(now);
auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM ("
"SELECT COALESCE(B.`message`, A.`message`) AS message, "
"A.`timestamp`, A.`from_jid`, A.`to_jid`, A.`type`, A.`encryption` FROM `ChatLogs` AS A "
"SELECT CONCAT_WS('-', COALESCE(B.`message`, A.`message`), A.`id`) AS message, "
"A.`timestamp`, A.`from_jid`, A.`to_jid`, A.`type`, A.`encryption`, A.`id` FROM `ChatLogs` AS A "
"LEFT JOIN `ChatLogs` AS B ON (A.`replaced_by_db_id` = B.`id` AND A.`from_jid` = B.`from_jid`) "
"WHERE (A.`replaces_db_id` IS NULL) "
"AND ((A.`from_jid` = %Q AND A.`to_jid` = %Q) OR (A.`from_jid` = %Q AND A.`to_jid` = %Q)) "
Expand Down Expand Up @@ -371,6 +371,8 @@ log_database_get_previous_chat(const gchar* const contact_barejid, const char* s
char* to_jid = (char*)sqlite3_column_text(stmt, 3);
char* type = (char*)sqlite3_column_text(stmt, 4);
char* encryption = (char*)sqlite3_column_text(stmt, 5);
char* mid = (char*)sqlite3_column_text(stmt, 6);
log_warning(mid);

ProfMessage* msg = message_init();
msg->from_jid = jid_create(from);
Expand Down
50 changes: 34 additions & 16 deletions src/ui/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@
#include "ui/window.h"
#include "ui/buffer.h"

#define BUFF_SIZE 200
#define BUFF_SIZE 200
#define BUFF_SIZE_LINES 500

struct prof_buff_t
{
GSList* entries;
int lines;
};

static void _free_entry(ProfBuffEntry* entry);
static int _count_lines(const char* const message);

ProfBuff
buffer_create(void)
Expand Down Expand Up @@ -96,14 +99,14 @@ buffer_append(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime*
e->from_jid = from_jid ? strdup(from_jid) : NULL;
e->message = strdup(message);
e->receipt = receipt;
if (id) {
e->id = strdup(id);
} else {
e->id = NULL;
}

if (g_slist_length(buffer->entries) == BUFF_SIZE) {
_free_entry(buffer->entries->data);
e->id = id ? strdup(id) : NULL;
e->lines = _count_lines(message);
buffer->lines += e->lines;

while (g_slist_length(buffer->entries) > 1 && (g_slist_length(buffer->entries) >= BUFF_SIZE || buffer->lines > BUFF_SIZE_LINES)) {
ProfBuffEntry* entry_to_delete = (ProfBuffEntry*)buffer->entries->data;
buffer->lines -= entry_to_delete->lines;
_free_entry(entry_to_delete);
buffer->entries = g_slist_delete_link(buffer->entries, buffer->entries);
}

Expand All @@ -123,15 +126,15 @@ buffer_prepend(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime
e->from_jid = from_jid ? strdup(from_jid) : NULL;
e->message = strdup(message);
e->receipt = receipt;
if (id) {
e->id = strdup(id);
} else {
e->id = NULL;
}
e->id = id ? strdup(id) : NULL;
e->lines = _count_lines(message);
buffer->lines += e->lines;

if (g_slist_length(buffer->entries) == BUFF_SIZE) {
while (g_slist_length(buffer->entries) > 1 && (g_slist_length(buffer->entries) >= BUFF_SIZE || buffer->lines > BUFF_SIZE_LINES)) {
GSList* last = g_slist_last(buffer->entries);
_free_entry(last->data);
ProfBuffEntry* entry_to_delete = (ProfBuffEntry*)last->data;
buffer->lines -= entry_to_delete->lines;
_free_entry(entry_to_delete);
buffer->entries = g_slist_delete_link(buffer->entries, last);
}

Expand All @@ -145,6 +148,7 @@ buffer_remove_entry_by_id(ProfBuff buffer, const char* const id)
while (entries) {
ProfBuffEntry* entry = entries->data;
if (entry->id && (g_strcmp0(entry->id, id) == 0)) {
buffer->lines -= entry->lines;
_free_entry(entry);
buffer->entries = g_slist_delete_link(buffer->entries, entries);
break;
Expand All @@ -157,6 +161,7 @@ void
buffer_remove_entry(ProfBuff buffer, int entry)
{
GSList* node = g_slist_nth(buffer->entries, entry);
buffer->lines -= ((ProfBuffEntry*)(node->data))->lines;
_free_entry(node->data);
buffer->entries = g_slist_delete_link(buffer->entries, node);
}
Expand Down Expand Up @@ -201,6 +206,19 @@ buffer_get_entry_by_id(ProfBuff buffer, const char* const id)
return NULL;
}

static int
_count_lines(const char* const message)
{
int lines = 0;
for (int i = 0; message[i]; i++) {
if (message[i] == '\n') {
lines++;
}
}

return lines;
}

static void
_free_entry(ProfBuffEntry* entry)
{
Expand Down
1 change: 1 addition & 0 deletions src/ui/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ typedef struct prof_buff_entry_t
// pointer because it could be a unicode symbol as well
gchar* show_char;
int pad_indent;
int lines;
GDateTime* time;
int flags;
theme_item_t theme_item;
Expand Down
27 changes: 17 additions & 10 deletions src/ui/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,14 +626,14 @@ void
win_page_up(ProfWin* window)
{
_reached_bottom_of_database = FALSE;
int rows = getmaxy(stdscr);
int y = getcury(window->layout->win);
int page_space = rows - 4;
int* page_start = &(window->layout->y_pos);
int page_space = getmaxy(stdscr) - 4;
int curses_lines_buffer_size = getcury(window->layout->win);
int* pos_in_curses_buffer = &(window->layout->y_pos);
log_warning("page_up-1; page_space=%d, curses_lines_buffer_size=%d, pos_in_curses_buffer=%d, buffer_size=%d", page_space, curses_lines_buffer_size, *pos_in_curses_buffer, buffer_size(window->layout->buffer));

*page_start -= page_space;
*pos_in_curses_buffer -= page_space;

if (*page_start == -page_space && window->type == WIN_CHAT) {
if (*pos_in_curses_buffer == -page_space && window->type == WIN_CHAT) {
ProfChatWin* chatwin = (ProfChatWin*)window;
ProfBuffEntry* first_entry = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0) : NULL;

Expand All @@ -651,14 +651,15 @@ win_page_up(ProfWin* window)
}

// went past beginning, show first page
if (*page_start < 0)
*page_start = 0;
if (*pos_in_curses_buffer < 0)
*pos_in_curses_buffer = 0;

log_warning("page_up-2; page_space=%d, curses_lines_buffer_size=%d, pos_in_curses_buffer=%d, buffer_size=%d", page_space, curses_lines_buffer_size, *pos_in_curses_buffer, buffer_size(window->layout->buffer));
window->layout->paged = 1;
win_update_virtual(window);

// switch off page if last line and space line visible
if ((y) - *page_start == page_space) {
if ((curses_lines_buffer_size) - *pos_in_curses_buffer == page_space) {
window->layout->paged = 0;
}
}
Expand All @@ -671,6 +672,7 @@ win_page_down(ProfWin* window)
int y = getcury(window->layout->win);
int page_space = rows - 4;
int* page_start = &(window->layout->y_pos);
log_warning("page_down-1; page_space=%d, lines_ncurses_buffered=%d, pos_in_buffer=%d, buffer_size=%d", page_space, y, *page_start, buffer_size(window->layout->buffer));

*page_start += page_space;

Expand Down Expand Up @@ -698,6 +700,8 @@ win_page_down(ProfWin* window)
else if (*page_start >= y)
*page_start = y - page_space - 1;

log_warning("page_down-2; page_space=%d, lines_ncurses_buffered=%d, pos_in_buffer=%d, buffer_size=%d", page_space, y, *page_start, buffer_size(window->layout->buffer));

window->layout->paged = 1;
win_update_virtual(window);

Expand Down Expand Up @@ -1490,7 +1494,10 @@ win_print_old_history(ProfWin* window, const ProfMessage* const message)
buffer_prepend(window->layout->buffer, ch, 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, NULL, message->plain, NULL, NULL);
wins_add_urls_ac(window, message, TRUE);
wins_add_quotes_ac(window, message->plain, TRUE);
_win_print_internal(window, ch, 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, message->plain, NULL);
// window is getting redrawn later in the only place where this function is getting called `chatwin.c`
// thus it's getting printed again, so to reduce load, we can as well remove this line (but it's a subject for a different PR)
// it's to be removed after clean up
// _win_print_internal(window, ch, 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, message->plain, NULL);

inp_nonblocking(TRUE);
g_date_time_unref(message->timestamp);
Expand Down

0 comments on commit cc67d05

Please sign in to comment.