commit bd4a08a74023593128f1f6fac9e0f4a093a8441f from: Omar Polo date: Mon Nov 07 18:18:53 2022 UTC start to refactor the rendering Previously each vline (visual line) had a full copy of its associated string, this changes it so it only slices a part of the parent line. Reduces significantly the memory usage. This actually worsen the emojify-link glitch reported by Freezr after the some recent refactoring in the wrapping code. Not a big deal since I'm about to restructure the whole rendering bit by bit (hopefully!) commit - ab33b604325fbc2681cc43df16dd6bc97c4699fd commit + bd4a08a74023593128f1f6fac9e0f4a093a8441f blob - 2854b26f492bf692171735a33230c519c4799aba blob + b1c1869a631091efc16c273c6ad6e09c2b747f10 --- cmd.c +++ cmd.c @@ -110,15 +110,10 @@ cmd_backward_char(struct buffer *buffer) void cmd_forward_char(struct buffer *buffer) { - size_t len = 0; - if (buffer->current_line == NULL) return; - - if (buffer->current_line->line != NULL) - len = utf8_cplen(buffer->current_line->line); - if (++buffer->cpoff > len) - buffer->cpoff = len; + if (buffer->current_line->cplen > buffer->cpoff) + buffer->cpoff++; } void @@ -129,7 +124,7 @@ cmd_backward_paragraph(struct buffer *buffer) message("No previous paragraph"); return; } - } while (buffer->current_line->line != NULL || + } while (buffer->current_line->len != 0 || buffer->current_line->parent->type != LINE_TEXT); } @@ -141,7 +136,7 @@ cmd_forward_paragraph(struct buffer *buffer) message("No next paragraph"); return; } - } while (buffer->current_line->line != NULL || + } while (buffer->current_line->len != 0 || buffer->current_line->parent->type != LINE_TEXT); } @@ -157,9 +152,9 @@ cmd_move_end_of_line(struct buffer *buffer) struct vline *vl; vl = buffer->current_line; - if (vl == NULL || vl->line == NULL) + if (vl == NULL) return; - buffer->cpoff = utf8_cplen(vl->line); + buffer->cpoff = vl->cplen; } void @@ -707,13 +702,14 @@ cmd_olivetti_mode(struct buffer *buffer) void cmd_mini_delete_char(struct buffer *buffer) { - char *c, *n; + char *line, *c, *n; GUARD_READ_ONLY(); minibuffer_taint_hist(); - c = utf8_nth(buffer->current_line->line, buffer->cpoff); + line = buffer->current_line->parent->line + buffer->current_line->from; + c = utf8_nth(line, buffer->cpoff); if (*c == '\0') return; n = utf8_next_cp(c); @@ -726,17 +722,17 @@ cmd_mini_delete_char(struct buffer *buffer) void cmd_mini_delete_backward_char(struct buffer *buffer) { - char *c, *p, *start; + char *line, *c, *p; GUARD_READ_ONLY(); minibuffer_taint_hist(); - c = utf8_nth(buffer->current_line->line, buffer->cpoff); - start = buffer->current_line->line; - if (c == start) + line = buffer->current_line->parent->line + buffer->current_line->from; + c = utf8_nth(line, buffer->cpoff); + if (c == line) return; - p = utf8_prev_cp(c-1, start); + p = utf8_prev_cp(c-1, line); memmove(p, c, strlen(c)+1); buffer->cpoff--; @@ -747,12 +743,14 @@ cmd_mini_delete_backward_char(struct buffer *buffer) void cmd_mini_kill_line(struct buffer *buffer) { - char *c; + char *line, *c; GUARD_READ_ONLY(); minibuffer_taint_hist(); - c = utf8_nth(buffer->current_line->line, buffer->cpoff); + + line = buffer->current_line->parent->line + buffer->current_line->from; + c = utf8_nth(line, buffer->cpoff); *c = '\0'; recompute_completions(0); @@ -764,7 +762,7 @@ cmd_mini_kill_whole_line(struct buffer *buffer) GUARD_READ_ONLY(); minibuffer_taint_hist(); - *buffer->current_line->line = '\0'; + *buffer->current_line->parent->line = '\0'; buffer->cpoff = 0; } @@ -817,7 +815,7 @@ cmd_mini_previous_history_element(struct buffer *buffe } if (ministate.hist_cur != NULL) { - buffer->current_line->line = ministate.hist_cur->h; + buffer->current_line->parent->line = ministate.hist_cur->h; recompute_completions(0); } } @@ -841,7 +839,7 @@ cmd_mini_next_history_element(struct buffer *buffer) } if (ministate.hist_cur != NULL) { - buffer->current_line->line = ministate.hist_cur->h; + buffer->current_line->parent->line = ministate.hist_cur->h; recompute_completions(0); } } blob - 8793d03eda3d404e665223439754a4253e93b1e3 blob + f8af6a1ebae1f826a846270292e2c6071ea7e54c --- include/telescope.h +++ include/telescope.h @@ -114,7 +114,9 @@ struct line { struct vline { struct line *parent; - char *line; + size_t from; + size_t len; + size_t cplen; int flags; TAILQ_ENTRY(vline) vlines; }; blob - 8f05942c15dbe9f9e528175f4043bb86791acb67 blob + 2c6273046d618fe14d98dc139adee0409a99cf42 --- include/utf8.h +++ include/utf8.h @@ -25,6 +25,7 @@ uint32_t utf8_decode(uint32_t*restrict, uint32_t*rest size_t utf8_encode(uint32_t, char*); char *utf8_nth(char*, size_t); size_t utf8_cplen(char*); +size_t utf8_ncplen(const char *, size_t); size_t utf8_chwidth(uint32_t); size_t utf8_snwidth(const char*, size_t); size_t utf8_swidth(const char*); blob - a386f9e2a59d33470142e32733c51808f8ac17bc blob + aca82a24187775201b6e0deb3994b792c18c9099 --- minibuffer.c +++ minibuffer.c @@ -217,7 +217,7 @@ minibuffer_taint_hist(void) strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf)); ministate.hist_cur = NULL; - ministate.buffer.current_line->line = ministate.buf; + ministate.buffer.current_line->parent->line = ministate.buf; } void @@ -232,7 +232,8 @@ minibuffer_self_insert(void) return; len = utf8_encode(thiskey.cp, tmp); - c = utf8_nth(ministate.buffer.current_line->line, ministate.buffer.cpoff); + c = utf8_nth(ministate.buffer.current_line->parent->line, + ministate.buffer.cpoff); if (c + len > ministate.buf + sizeof(ministate.buf) - 1) return; @@ -527,7 +528,7 @@ enter_minibuffer(void (*self_insert_fn)(void), void (* ministate.abortfn = abortfn; memset(ministate.buf, 0, sizeof(ministate.buf)); ministate.buffer.current_line = &ministate.vline; - ministate.buffer.current_line->line = ministate.buf; + ministate.buffer.current_line->parent->line = ministate.buf; ministate.buffer.cpoff = 0; strlcpy(ministate.buf, "", sizeof(ministate.prompt)); blob - 8e6dd746aea8a63e569114dfec05728e7205b391 blob + 4adfaa3b7a6413ca9bb67aa3bfe386ea6e8aa9f7 --- u/utf8.c +++ u/utf8.c @@ -129,6 +129,18 @@ utf8_cplen(char *s) len = 0; for (; *s; ++s) + if (!decode(&state, &cp, *s)) + len++; + return len; +} + +size_t +utf8_ncplen(const char *s, size_t slen) +{ + uint32_t cp = 0, state = 0; + size_t len = 0; + + for (; slen > 0 && *s; ++s, --slen) if (!decode(&state, &cp, *s)) len++; return len; blob - ce6dcfb01915c498fe54b1eb3d6d22c4b205dca9 blob + d86351e71dc259ed782b0251ba92d069e6cc4f82 --- u/wrap.c +++ u/wrap.c @@ -64,7 +64,6 @@ empty_vlist(struct buffer *buffer) TAILQ_FOREACH_SAFE(vl, &buffer->head, vlines, t) { TAILQ_REMOVE(&buffer->head, vl, vlines); - free(vl->line); free(vl); } } @@ -89,14 +88,12 @@ push_line(struct buffer *buffer, struct line *l, const if ((vl = calloc(1, sizeof(*vl))) == NULL) return 0; - if (len != 0 && (vl->line = calloc(1, len+1)) == NULL) { - free(vl); - return 0; - } - vl->parent = l; - if (len != 0) - memcpy(vl->line, buf, len); + if (len != 0) { + vl->from = buf - l->line; + vl->len = len; + vl->cplen = utf8_ncplen(buf, vl->len); + } vl->flags = flags; TAILQ_INSERT_TAIL(&buffer->head, vl, vlines); @@ -125,7 +122,7 @@ wrap_text(struct buffer *buffer, const char *prfx, str if (l->type == LINE_LINK && emojify_link && emojied_line(l->line, &space)) { - prfxwidth = utf8_swidth_between(l->line, space); + prfxwidth = utf8_swidth_between(l->line, space); cur = prfxwidth; line = space + 1; } blob - a7027a900ad35ef00aa79dd94069de4f2190e7fe blob + eebb8a986913e785c7ad8f3a30e521e1a221e69a --- ui.c +++ ui.c @@ -60,7 +60,7 @@ static void handle_resize(int, short, void*); static void handle_resize_nodelay(int, short, void*); static void handle_download_refresh(int, short, void *); static void rearrange_windows(void); -static void line_prefix_and_text(struct vline *, char *, size_t, const char **, const char **); +static void line_prefix_and_text(struct vline *, char *, size_t, const char **, const char **, int *); static void print_vline(int, int, WINDOW*, struct vline*); static void redraw_tabline(void); static void redraw_window(WINDOW *, int, int, int, int, struct buffer *); @@ -214,13 +214,15 @@ restore_curs_x(struct buffer *buffer) const char *prfx, *text; vl = buffer->current_line; - if (vl == NULL || vl->line == NULL) + if (vl == NULL || vl->len == 0) buffer->curs_x = buffer->cpoff = 0; else if (vl->parent->data != NULL) { text = vl->parent->data; buffer->curs_x = utf8_snwidth(text + 1, buffer->cpoff) + 1; - } else - buffer->curs_x = utf8_snwidth(vl->line, buffer->cpoff); + } else { + text = vl->parent->line + vl->from; + buffer->curs_x = utf8_snwidth(text, buffer->cpoff); + } /* small hack: don't olivetti-mode the download pane */ if (buffer != &downloadwin) @@ -456,13 +458,15 @@ rearrange_windows(void) static void line_prefix_and_text(struct vline *vl, char *buf, size_t len, - const char **prfx_ret, const char **text_ret) + const char **prfx_ret, const char **text_ret, int *text_len) { int type, i, cont, width; char *space, *t; - if ((*text_ret = vl->line) == NULL) + if (vl->len == 0) { *text_ret = ""; + *text_len = 0; + } cont = vl->flags & L_CONTINUATION; type = vl->parent->type; @@ -472,8 +476,11 @@ line_prefix_and_text(struct vline *vl, char *buf, size *prfx_ret = line_prefixes[type].prfx2; space = vl->parent->data; - if (!emojify_link || type != LINE_LINK || space == NULL) + if (!emojify_link || type != LINE_LINK || space == NULL) { + *text_ret = vl->parent->line + vl->from; + *text_len = MIN(INT_MAX, vl->len); return; + } if (cont) { memset(buf, 0, len); @@ -491,6 +498,7 @@ line_prefix_and_text(struct vline *vl, char *buf, size } *prfx_ret = buf; + *text_len = INT_MAX; } static inline void @@ -546,7 +554,7 @@ print_vline(int off, int width, WINDOW *window, struct char emojibuf[41] = {0}; const char *text, *prfx; struct line_face *f; - int i, left, x, y; + int i, left, x, y, textlen; f = &line_faces[vl->parent->type]; @@ -556,7 +564,8 @@ print_vline(int off, int width, WINDOW *window, struct if (vl->parent->type == LINE_FRINGE && fringe_ignore_offset) off = 0; - line_prefix_and_text(vl, emojibuf, sizeof(emojibuf), &prfx, &text); + line_prefix_and_text(vl, emojibuf, sizeof(emojibuf), &prfx, + &text, &textlen); wattr_on(window, body_face.left, NULL); for (i = 0; i < off; i++) @@ -568,7 +577,7 @@ print_vline(int off, int width, WINDOW *window, struct wattr_off(window, f->prefix, NULL); wattr_on(window, f->text, NULL); - wprintw(window, "%s", text); + wprintw(window, "%.*s", textlen, text); print_vline_descr(width, window, vl); wattr_off(window, f->text, NULL); @@ -913,6 +922,7 @@ do_redraw_minibuffer(void) struct buffer *cmplbuf, *buffer; size_t off_y, off_x = 0; const char *start, *c; + char *line; cmplbuf = &ministate.compl.buffer; buffer = &ministate.buffer; @@ -935,7 +945,8 @@ do_redraw_minibuffer(void) start = ministate.hist_cur != NULL ? ministate.hist_cur->h : ministate.buf; - c = utf8_nth(buffer->current_line->line, buffer->cpoff); + line = buffer->current_line->parent->line + buffer->current_line->from; + c = utf8_nth(line, buffer->cpoff); while (utf8_swidth_between(start, c) > (size_t)COLS/2) { start = utf8_next_cp(start); }