Commit: 11430fa3a841a123d3b8369a119971d58902b454
Parent: 806951a9deed6716eec91a919d01e70aafb84b8e
Author: Randy Palamar
Date:   Wed,  6 Nov 2024 08:10:16 -0700
use a Stream for selection copying
Diffstat:
| M | vtgl.c | | | 89 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- | 
1 file changed, 43 insertions(+), 46 deletions(-)
diff --git a/vtgl.c b/vtgl.c
@@ -455,6 +455,44 @@ mouse_to_cell_space(Term *t, v2 mouse)
 }
 
 static void
+stream_push_selection(Stream *s, TermView *tv, Range sel, u32 term_width)
+{
+	iv2 curs = sel.start;
+	iv2 end  = sel.end;
+
+	s->errors |= !is_valid_range(sel);
+	if (s->errors) return;
+
+	/* NOTE: do full rows first */
+	u32 last_non_space_idx = 0;
+	for (; curs.y < end.y; curs.y++) {
+		for (; curs.x < term_width; curs.x++) {
+			Cell c = tv->fb.rows[curs.y][curs.x];
+			if (c.bg & ATTR_WDUMMY)
+				continue;
+			stream_push_s8(s, utf8_encode(c.cp));
+			if (!ISSPACE(c.cp))
+				last_non_space_idx = s->widx;
+		}
+		s->widx = last_non_space_idx;
+		stream_push_byte(s, '\n');
+		curs.x = 0;
+	}
+
+	/* NOTE: do the last row */
+	for (; curs.x <= end.x; curs.x++) {
+		Cell c = tv->fb.rows[curs.y][curs.x];
+		if (c.bg & ATTR_WDUMMY)
+			continue;
+		stream_push_s8(s, utf8_encode(c.cp));
+		if (!ISSPACE(c.cp))
+			last_non_space_idx = s->widx;
+	}
+	s->widx = last_non_space_idx;
+	stream_push_byte(s, '\n');
+}
+
+static void
 update_selection(Term *t)
 {
 	Selection *sel = &t->selection;
@@ -511,53 +549,12 @@ update_selection(Term *t)
 
 KEYBIND_FN(copy)
 {
-	if (!is_valid_range(t->selection.range))
-		return 1;
-
-	TermView *tv = t->views + t->view_idx;
-	Range sel    = t->selection.range;
-	iv2 curs     = sel.start;
-	iv2 end      = sel.end;
-	i32 buf_curs = 0;
-
-	/* NOTE: super piggy but we are only holding onto it for the function duration */
-	Arena arena    = t->arena_for_frame;
-	size  buf_size = 1 * MEGABYTE;
-	char *buf      = alloc(&arena, char, buf_size);
-
-	/* NOTE: do full rows first */
-	u32 last_non_space_idx = 0;
-	for (; curs.y < end.y; curs.y++) {
-		for (; curs.x < t->size.w && buf_curs != buf_size; curs.x++) {
-			Cell c = tv->fb.rows[curs.y][curs.x];
-			if (c.bg & ATTR_WDUMMY)
-				continue;
-			s8 enc = utf8_encode(c.cp);
-			for (size i = 0; i < enc.len && buf_curs != buf_size; i++)
-				buf[buf_curs++] = enc.data[i];
-			if (!ISSPACE(c.cp))
-				last_non_space_idx = buf_curs;
-		}
-		buf[last_non_space_idx + 1] = '\n';
-		buf_curs = last_non_space_idx + 2;
-		curs.x = 0;
-	}
-
-	/* NOTE: do the last row */
-	for (; curs.x <= end.x && buf_curs != buf_size; curs.x++) {
-		Cell c = tv->fb.rows[curs.y][curs.x];
-		if (c.bg & ATTR_WDUMMY)
-			continue;
-		s8 enc = utf8_encode(c.cp);
-		for (size i = 0; i < enc.len && buf_curs != buf_size; i++)
-			buf[buf_curs++] = enc.data[i];
-		if (!ISSPACE(c.cp))
-			last_non_space_idx = buf_curs;
-	}
+	Stream buf = arena_stream(t->arena_for_frame);
+	stream_push_selection(&buf, t->views + t->view_idx, t->selection.range, t->size.w);
+	stream_push_byte(&buf, 0);
 
-	CLAMP(buf_curs, 0, buf_size - 1);
-	buf[buf_curs] = 0;
-	glfwSetClipboardString(0, buf);
+	if (!buf.errors)
+		glfwSetClipboardString(0, (c8 *)buf.buf);
 
 	return 1;
 }