Browse Source

text_edit: better handle failure to resize underlying buffer

Håkon Stormo 1 year ago
parent
commit
d3bbe29faa
1 changed files with 31 additions and 13 deletions
  1. 31 13
      core/text/edit/text_edit.odin

+ 31 - 13
core/text/edit/text_edit.odin

@@ -7,6 +7,7 @@ package text_edit
 */
 */
 
 
 import "base:runtime"
 import "base:runtime"
+import "core:fmt"
 import "core:time"
 import "core:time"
 import "core:mem"
 import "core:mem"
 import "core:strings"
 import "core:strings"
@@ -183,16 +184,17 @@ undo_check :: proc(s: ^State) {
 }
 }
 
 
 // insert text into the edit state - deletes the current selection
 // insert text into the edit state - deletes the current selection
-input_text :: proc(s: ^State, text: string) {
+input_text :: proc(s: ^State, text: string) -> int {
 	if len(text) == 0 {
 	if len(text) == 0 {
-		return
+		return 0
 	}
 	}
 	if has_selection(s) {
 	if has_selection(s) {
 		selection_delete(s)
 		selection_delete(s)
 	}
 	}
-	insert(s, s.selection[0], text)
-	offset := s.selection[0] + len(text)
+	n := insert(s, s.selection[0], text)
+	offset := s.selection[0] + n
 	s.selection = {offset, offset}
 	s.selection = {offset, offset}
+	return n
 }
 }
 
 
 // insert slice of runes into the edit state - deletes the current selection
 // insert slice of runes into the edit state - deletes the current selection
@@ -206,8 +208,11 @@ input_runes :: proc(s: ^State, text: []rune) {
 	offset := s.selection[0]
 	offset := s.selection[0]
 	for r in text {
 	for r in text {
 		b, w := utf8.encode_rune(r)
 		b, w := utf8.encode_rune(r)
-		insert(s, offset, string(b[:w]))
-		offset += w
+		n := insert(s, offset, string(b[:w]))
+		offset += n
+		if n != w {
+			break
+		}
 	}
 	}
 	s.selection = {offset, offset}
 	s.selection = {offset, offset}
 }
 }
@@ -219,17 +224,29 @@ input_rune :: proc(s: ^State, r: rune) {
 	}
 	}
 	offset := s.selection[0]
 	offset := s.selection[0]
 	b, w := utf8.encode_rune(r)
 	b, w := utf8.encode_rune(r)
-	insert(s, offset, string(b[:w]))
-	offset += w
+	n := insert(s, offset, string(b[:w]))
+	offset += n
 	s.selection = {offset, offset}
 	s.selection = {offset, offset}
 }
 }
 
 
 // insert a single rune into the edit state - deletes the current selection
 // insert a single rune into the edit state - deletes the current selection
-insert :: proc(s: ^State, at: int, text: string) {
+insert :: proc(s: ^State, at: int, text: string) -> int {
 	undo_check(s)
 	undo_check(s)
 	if s.builder != nil {
 	if s.builder != nil {
-		inject_at(&s.builder.buf, at, text)
+		if ok, _ := inject_at(&s.builder.buf, at, text); !ok {
+			n := cap(s.builder.buf) - len(s.builder.buf)
+			assert(n < len(text))
+			for is_continuation_byte(text[n]) {
+				n -= 1
+			}
+			if ok, _ := inject_at(&s.builder.buf, at, text[:n]); !ok {
+				n = 0
+			}
+			return n
+		}
+		return len(text)
 	}
 	}
+	return 0
 }
 }
 
 
 // remove the wanted range withing, usually the selection within byte indices
 // remove the wanted range withing, usually the selection within byte indices
@@ -263,11 +280,12 @@ selection_delete :: proc(s: ^State) {
 	s.selection = {lo, lo}
 	s.selection = {lo, lo}
 }
 }
 
 
+is_continuation_byte :: proc(b: byte) -> bool {
+	return b >= 0x80 && b < 0xc0
+}
+
 // translates the caret position 
 // translates the caret position 
 translate_position :: proc(s: ^State, t: Translation) -> int {
 translate_position :: proc(s: ^State, t: Translation) -> int {
-	is_continuation_byte :: proc(b: byte) -> bool {
-		return b >= 0x80 && b < 0xc0
-	}
 	is_space :: proc(b: byte) -> bool {
 	is_space :: proc(b: byte) -> bool {
 		return b == ' ' || b == '\t' || b == '\n'
 		return b == ' ' || b == '\t' || b == '\n'
 	}
 	}