Commit Diff


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);
 	}