Skip to content

Commit 680cfca

Browse files
committed
fix clipboard UTF8 handling
Changes: (1) length as byte count in copy callback (instead of glyph count) (2) fix nk_str_insert_text_char and nk_str_insert_str_char (3) correct UTF-8 cursor handling Fixes: #840 Fixes: #764 Obsoletes: #543 BREAKING CHANGE: If your custom backed has a workaround for this issue, it will break.
1 parent b5f67b8 commit 680cfca

6 files changed

Lines changed: 44 additions & 30 deletions

File tree

clib.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nuklear",
3-
"version": "4.12.8",
3+
"version": "4.13.1",
44
"repo": "Immediate-Mode-UI/Nuklear",
55
"description": "A small ANSI C gui toolkit",
66
"keywords": ["gl", "ui", "toolkit"],

nuklear.h

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8931,12 +8931,12 @@ nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
89318931
NK_API int
89328932
nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
89338933
{
8934-
return nk_str_insert_text_utf8(str, pos, text, len);
8934+
return nk_str_insert_at_rune(str, pos, text, len) ? len : 0;
89358935
}
89368936
NK_API int
89378937
nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
89388938
{
8939-
return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
8939+
return nk_str_insert_text_char(str, pos, text, nk_strlen(text));
89408940
}
89418941
NK_API int
89428942
nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
@@ -27155,7 +27155,7 @@ nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
2715527155
glyphs = nk_utf_len(ctext, len);
2715627156
if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
2715727157
nk_textedit_makeundo_insert(state, state->cursor, glyphs);
27158-
state->cursor += len;
27158+
state->cursor += glyphs;
2715927159
state->has_preferred_x = 0;
2716027160
return 1;
2716127161
}
@@ -28114,17 +28114,19 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
2811428114
int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
2811528115
if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
2811628116
{
28117-
int glyph_len;
28118-
nk_rune unicode;
28119-
const char *text;
28120-
int b = edit->select_start;
28121-
int e = edit->select_end;
28122-
28123-
int begin = NK_MIN(b, e);
28124-
int end = NK_MAX(b, e);
28125-
text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
28126-
if (edit->clip.copy)
28127-
edit->clip.copy(edit->clip.userdata, text, end - begin);
28117+
int begin = NK_MIN(edit->select_start, edit->select_end);
28118+
int end = NK_MAX(edit->select_start, edit->select_end);
28119+
28120+
if (edit->clip.copy) {
28121+
int glyph_len;
28122+
nk_rune unicode;
28123+
const char *text_begin, *text_end;
28124+
text_begin = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
28125+
/*Reuse temporary variables (unicode, glyph_len)*/
28126+
text_end = nk_str_at_const(&edit->string, end, &unicode, &glyph_len);
28127+
28128+
edit->clip.copy(edit->clip.userdata, text_begin, text_end - text_begin);
28129+
}
2812828130
if (cut && !(flags & NK_EDIT_READ_ONLY)){
2812928131
nk_textedit_cut(edit);
2813028132
cursor_follow = nk_true;
@@ -30736,6 +30738,11 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
3073630738
/// - [y]: Minor version with non-breaking API and library changes
3073730739
/// - [z]: Patch version with no direct changes to the API
3073830740
///
30741+
/// - 2025/10/18 (4.13.1) - Fix UTF-8 clipboard handling
30742+
/// POSSIBLE BREAKING CHANGE for custom backend (copy/paste)
30743+
/// (1) length as byte count in copy callback(nk_do_edit)
30744+
/// (2) Fix nk_str_insert_text_char and nk_str_insert_str_char
30745+
/// (3) Fix UTF-8 cursor(nk_textedit_paste)
3073930746
/// - 2025/11/15 (4.13.0) - Fix: nk_property not updating 'win->edit.active'
3074030747
/// Add new updated demo: sdl3_renderer
3074130748
/// - 2025/10/08 (4.12.8) - Fix nk_widget_text to use NK_TEXT_ALIGN_LEFT by default,
@@ -30747,7 +30754,7 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
3074730754
/// - 2025/04/06 (4.12.7) - Fix text input navigation and mouse scrolling
3074830755
/// - 2025/03/29 (4.12.6) - Fix unitialized data in nk_input_char
3074930756
/// - 2025/03/05 (4.12.5) - Fix scrolling knob also scrolling parent window, remove dead code
30750-
/// - 2024/12/11 (4.12.4) - Fix array subscript [0, 0] is outside array bounds of char[1]
30757+
/// - 2024/12/11 (4.12.4) - Fix array subscript [0, 0] is outside array bounds of char[1]
3075130758
/// - 2024/12/11 (4.12.3) - Fix border color for property widgets
3075230759
/// - 2024/11/20 (4.12.2) - Fix int/float type conversion warnings in `nk_roundf`
3075330760
/// - 2024/03/07 (4.12.1) - Fix bitwise operations warnings in C++20

src/CHANGELOG

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
/// - [y]: Minor version with non-breaking API and library changes
88
/// - [z]: Patch version with no direct changes to the API
99
///
10+
/// - 2025/10/18 (4.13.1) - Fix UTF-8 clipboard handling
11+
/// POSSIBLE BREAKING CHANGE for custom backend (copy/paste)
12+
/// (1) length as byte count in copy callback(nk_do_edit)
13+
/// (2) Fix nk_str_insert_text_char and nk_str_insert_str_char
14+
/// (3) Fix UTF-8 cursor(nk_textedit_paste)
1015
/// - 2025/11/15 (4.13.0) - Fix: nk_property not updating 'win->edit.active'
1116
/// Add new updated demo: sdl3_renderer
1217
/// - 2025/10/08 (4.12.8) - Fix nk_widget_text to use NK_TEXT_ALIGN_LEFT by default,

src/nuklear_edit.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,19 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
278278
int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
279279
if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
280280
{
281-
int glyph_len;
282-
nk_rune unicode;
283-
const char *text;
284-
int b = edit->select_start;
285-
int e = edit->select_end;
286-
287-
int begin = NK_MIN(b, e);
288-
int end = NK_MAX(b, e);
289-
text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
290-
if (edit->clip.copy)
291-
edit->clip.copy(edit->clip.userdata, text, end - begin);
281+
int begin = NK_MIN(edit->select_start, edit->select_end);
282+
int end = NK_MAX(edit->select_start, edit->select_end);
283+
284+
if (edit->clip.copy) {
285+
int glyph_len;
286+
nk_rune unicode;
287+
const char *text_begin, *text_end;
288+
text_begin = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
289+
/*Reuse temporary variables (unicode, glyph_len)*/
290+
text_end = nk_str_at_const(&edit->string, end, &unicode, &glyph_len);
291+
292+
edit->clip.copy(edit->clip.userdata, text_begin, text_end - text_begin);
293+
}
292294
if (cut && !(flags & NK_EDIT_READ_ONLY)){
293295
nk_textedit_cut(edit);
294296
cursor_follow = nk_true;

src/nuklear_string.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,12 @@ nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
167167
NK_API int
168168
nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
169169
{
170-
return nk_str_insert_text_utf8(str, pos, text, len);
170+
return nk_str_insert_at_rune(str, pos, text, len) ? len : 0;
171171
}
172172
NK_API int
173173
nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
174174
{
175-
return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
175+
return nk_str_insert_text_char(str, pos, text, nk_strlen(text));
176176
}
177177
NK_API int
178178
nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)

src/nuklear_text_editor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
355355
glyphs = nk_utf_len(ctext, len);
356356
if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
357357
nk_textedit_makeundo_insert(state, state->cursor, glyphs);
358-
state->cursor += len;
358+
state->cursor += glyphs;
359359
state->has_preferred_x = 0;
360360
return 1;
361361
}

0 commit comments

Comments
 (0)