Skip to content

Commit

Permalink
Fix line wrapping/padding issues
Browse files Browse the repository at this point in the history
It should now parse messages with newlines properly as well as messages that
contain long sequences of characters with no spaces
  • Loading branch information
JFreegman committed Nov 24, 2020
1 parent 6ceb358 commit 5a67660
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 33 deletions.
103 changes: 71 additions & 32 deletions src/line_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void line_info_reset_start(ToxWindow *self, struct history *hst)
do {
curlines += line->format_lines;
line = line->prev;
} while (line->prev && curlines + line->format_lines < max_y);
} while (line->prev && curlines + line->format_lines <= max_y);

hst->line_start = line;
}
Expand Down Expand Up @@ -165,6 +165,36 @@ static int rspace_index(const char *s, int limit)
return -1;
}

/* Returns the first index in `s` containing a newline byte found before `limit`.
* Returns -1 if no newline is found.
*/
static int newline_index(const char *s, int limit)
{
char ch;

for (int i = 0; i < limit && (ch = s[i]); ++i) {
if (ch == '\n') {
return i;
}
}

return -1;
}

/* Returns the number of newline bytes in `s` */
static unsigned int newline_count(const char *s)
{
char ch;
unsigned int count = 0;

for (size_t i = 0; (ch = s[i]); ++i) {
if (ch == '\n') {
++count;
}
}

return count;
}

/* Prints `line` message to window, wrapping at the last word that fits on the current line.
* This function updates the `format_lines` field of `line` according to current window dimensions.
Expand All @@ -176,49 +206,61 @@ static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
{
const char *msg = line->msg;
uint16_t length = line->msg_len;
uint16_t lines = line->newlines;
uint16_t lines = 0;
const int x_start = line->len - line->msg_len - 1; // manually keep track of x position because ncurses sucks
int x_limit = max_x - x_start;

while (msg) {
++lines;

int x_limit = max_x - x_start;
if (x_limit <= 0) {
fprintf(stderr, "Warning: x_limit <= 0 in print_wrap(): %d\n", x_limit);
return;
}

if (length < x_limit || x_limit <= 0) {
if (win) {
wprintw(win, "%s", msg);
while (msg) {
if (length < x_limit) {
if (print_n_chars(win, msg, length)) {
lines += newline_count(msg);
}

++lines;
break;
}

int newline_idx = newline_index(msg, x_limit - 1);

if (newline_idx >= 0) {
print_n_chars(win, msg, newline_idx + 1);
msg += newline_idx + 1;
length -= (newline_idx + 1);
x_limit = max_x; // if we find a newline we stop adding column padding for rest of message
++lines;
continue;
}

int space_idx = rspace_index(msg, x_limit - 1);

if (space_idx >= 1) {
bool newline = print_n_chars(win, msg, space_idx);

msg += space_idx;
length -= space_idx;
x_limit -= space_idx;
print_n_chars(win, msg, space_idx);
msg += space_idx + 1;
length -= (space_idx + 1);

// replace last space on current line with newline if we intend to split it
if (length >= x_limit && !newline) {
--length;
++msg;

if (win) {
waddch(win, '\n');

for (size_t i = 0; i < x_start; ++i) {
waddch(win, ' '); // Add padding to the start of the next line
}
}
if (length >= x_limit - space_idx) {
waddch(win, '\n');
}
} else {
print_n_chars(win, msg, x_limit);
msg += x_limit;
length -= x_limit;
}

// Add padding to the start of the next line
if (win && x_limit < max_x) {
for (size_t i = 0; i < x_start; ++i) {
waddch(win, ' ');
}
}

++lines;
}

line->format_lines = lines;
Expand Down Expand Up @@ -259,7 +301,8 @@ int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const
exit_toxic_err("failed in line_info_add", FATALERR_MEMORY);
}

char frmt_msg[MAX_LINE_INFO_MSG_SIZE] = {0};
char frmt_msg[MAX_LINE_INFO_MSG_SIZE];
frmt_msg[0] = 0;

va_list args;
va_start(args, msg);
Expand Down Expand Up @@ -314,12 +357,6 @@ int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const
snprintf(new_line->msg, sizeof(new_line->msg), "%s", frmt_msg);
msg_len = strlen(new_line->msg);
len += msg_len;

for (size_t i = 0; frmt_msg[i]; ++i) {
if (frmt_msg[i] == '\n') {
++new_line->newlines;
}
}
}

if (timestr) {
Expand Down Expand Up @@ -493,6 +530,7 @@ void line_info_print(ToxWindow *self)
if (line->noread_flag == false) {
line->noread_flag = true;
line->len += 2;
line->msg_len += 2;
}
}

Expand Down Expand Up @@ -523,6 +561,7 @@ void line_info_print(ToxWindow *self)
if (line->noread_flag == false) {
line->noread_flag = true;
line->len += 2;
line->msg_len += 2;
}
}

Expand Down
1 change: 0 additions & 1 deletion src/line_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ struct line_info {
uint32_t id;
uint16_t len; /* combined length of entire line */
uint16_t msg_len; /* length of the message */
uint8_t newlines;
uint16_t format_lines; /* number of lines the combined string takes up (dynamically set) */

struct line_info *prev;
Expand Down
1 change: 1 addition & 0 deletions src/message_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ static void cqueue_mark_read(ToxWindow *self, struct cqueue_msg *msg)

if (line->noread_flag == true) {
line->len -= 2;
line->msg_len -= 2;
line->noread_flag = false;
}

Expand Down

0 comments on commit 5a67660

Please sign in to comment.