aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-27 18:14:35 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-27 18:14:35 +0300
commite94dce1f9770abde689314fb993a23800e2bcc9f (patch)
tree8560e117a799b6b48b9408c9cd9cc775663351af
parent0ea082b74414696a7800455a437656fca2886f6d (diff)
downloadsciteco-e94dce1f9770abde689314fb993a23800e2bcc9f.tar.gz
fixed a,b,c^Uq...$: The arguments where written in the wrong (reverse) order
* When writing UTF-8, we must first peek in reverse order since we can only write from left to right. * When writing in raw ANSI, we can immediately pop the values from the stack but must write in reverse.
-rw-r--r--src/qreg-commands.c29
-rw-r--r--tests/testsuite.at4
2 files changed, 20 insertions, 13 deletions
diff --git a/src/qreg-commands.c b/src/qreg-commands.c
index bec2ca8..83a45b1 100644
--- a/src/qreg-commands.c
+++ b/src/qreg-commands.c
@@ -387,39 +387,46 @@ teco_state_setqregstring_nobuilding_done(teco_machine_main_t *ctx,
return NULL;
g_autofree gchar *buffer = NULL;
+ const gchar *start;
gsize len = 0;
if (codepage == SC_CP_UTF8) {
- /* the glib docs wrongly claim that one character can take 6 bytes */
- buffer = g_malloc(4*args);
+ /* 4 bytes should be enough for UTF-8, but we better follow the documentation */
+ start = buffer = g_malloc(args*6);
+
for (gint i = args; i > 0; i--) {
- teco_int_t v = teco_expressions_pop_num(0);
- if (v < 0 || !g_unichar_validate(v)) {
+ teco_int_t chr = teco_expressions_peek_num(i-1);
+ if (chr < 0 || !g_unichar_validate(chr)) {
teco_error_codepoint_set(error, "^U");
return NULL;
}
- len += g_unichar_to_utf8(v, buffer+len);
+ len += g_unichar_to_utf8(chr, buffer+len);
}
+ /* we pop only now since we had to peek in reverse order */
+ for (gint i = 0; i < args; i++)
+ teco_expressions_pop_num(0);
} else {
buffer = g_malloc(args);
- for (gint i = args; i > 0; i--) {
- teco_int_t v = teco_expressions_pop_num(0);
- if (v < 0 || v > 0xFF) {
+
+ for (gint i = 0; i < args; i++) {
+ teco_int_t chr = teco_expressions_pop_num(0);
+ if (chr < 0 || chr > 0xFF) {
teco_error_codepoint_set(error, "^U");
return NULL;
}
- buffer[len++] = v;
+ buffer[args-(++len)] = chr;
}
+ start = buffer+args-len;
}
if (colon_modified) {
/* append to register */
- if (!qreg->vtable->append_string(qreg, buffer, len, error))
+ if (!qreg->vtable->append_string(qreg, start, len, error))
return NULL;
} else {
/* set register */
if (!qreg->vtable->undo_set_string(qreg, error) ||
- !qreg->vtable->set_string(qreg, buffer, len,
+ !qreg->vtable->set_string(qreg, start, len,
codepage, error))
return NULL;
}
diff --git a/tests/testsuite.at b/tests/testsuite.at
index f24b58b..132684b 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -305,8 +305,8 @@ AT_CHECK([[$SCITECO -8e "194Ua Qa@I//J :@S/^EUa/\"F(0/0)'"]], 0, ignore, ignore)
AT_CLEANUP
AT_SETUP([Unicode])
-TE_CHECK([[8594@I/Здравствуй, мир!/ Z-17"N(0/0)' J0A-8594"N(0/0)']], 0, ignore, ignore)
-TE_CHECK([[8594@^Ua/Здравствуй, мир!/ :Qa-17"N(0/0)' 0Qa-8594"N(0/0)']], 0, ignore, ignore)
+TE_CHECK([[8594,8592@I/Здравствуй, мир!/ Z-18"N(0/0)' J0A-8594"N(0/0)']], 0, ignore, ignore)
+TE_CHECK([[8594,8592@^Ua/Здравствуй, мир!/ :Qa-18"N(0/0)' 0Qa-8594"N(0/0)']], 0, ignore, ignore)
TE_CHECK([[@I/Здравствуй, мир!/ JW .-12"N(0/0)' ^E-22"N(0/0)' 204:EE .-12"N(0/0)']], 0, ignore, ignore)
TE_CHECK([[@I/TEST/ @EW/юникод.txt/]], 0, ignore, ignore)
AT_CHECK([[test -f юникод.txt]], 0, ignore, ignore)