aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--src/core-commands.c29
-rw-r--r--src/core-commands.h4
-rw-r--r--src/glob.c15
-rw-r--r--src/qreg-commands.c5
-rw-r--r--src/search.c33
-rw-r--r--src/spawn.c5
-rw-r--r--tests/testsuite.at4
8 files changed, 65 insertions, 31 deletions
diff --git a/TODO b/TODO
index ffaf95a..ab0702e 100644
--- a/TODO
+++ b/TODO
@@ -8,7 +8,6 @@ Tasks:
https://github.com/Bill-Gray/PDCursesMod/issues/330
Known Bugs:
- * <FD> returns the deleted length-1, which also breaks <^S>.
* Gtk: The control characters in tutorial.woman are still styled with
the variable-width font since its rendered in STYLE_CONTROLCHAR (36),
which is reset in woman.tes.
diff --git a/src/core-commands.c b/src/core-commands.c
index 4f3ed94..b8918ef 100644
--- a/src/core-commands.c
+++ b/src/core-commands.c
@@ -225,8 +225,13 @@ teco_state_start_backslash(teco_machine_main_t *ctx, GError **error)
g_assert(*str != '\0');
gsize len = strlen(str);
- teco_undo_gsize(teco_ranges[0].from) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
- teco_undo_gsize(teco_ranges[0].to) = teco_ranges[0].from + len;
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos);
+ /*
+ * We can assume that `len` is already in glyphs,
+ * i.e. formatted numbers will never use multi-byte/Unicode characters.
+ */
+ teco_undo_int(teco_ranges[0].to) = teco_ranges[0].from + len;
teco_undo_guint(teco_ranges_count) = 1;
teco_interface_ssm(SCI_BEGINUNDOACTION, 0, 0);
@@ -1465,8 +1470,8 @@ teco_ranges_init(void)
* The default value 0 specifies the entire matched pattern,
* while higher numbers refer to \fB^E[\fI...\fB]\fR subpatterns.
* \fB^Y\fP can also be used to return the buffer range of the
- * last text insertion by any \*(ST command (\fBI\fP, \fBEI\fP, \fB^I\fP, \fBG\fIq\fR,
- * \fB\\\fP, \fBEC\fP, \fBEN\fP, etc).
+ * last text insertion by any \*(ST command (\fBI\fP, \fB^I\fP, \fBG\fIq\fR,
+ * \fB\\\fP, \fBEC\fP, \fBEN\fP, search replacements, etc).
* In this case <n> is only allowed to be 0 or missing.
*
* For instance, \(lq^YXq\(rq copies the entire matched pattern or text
@@ -1489,8 +1494,8 @@ teco_state_control_last_range(teco_machine_main_t *ctx, GError **error)
return;
}
- teco_expressions_push(teco_interface_bytes2glyphs(teco_ranges[n].from));
- teco_expressions_push(teco_interface_bytes2glyphs(teco_ranges[n].to));
+ teco_expressions_push(teco_ranges[n].from);
+ teco_expressions_push(teco_ranges[n].to);
}
/*$ ^S
@@ -1527,8 +1532,7 @@ teco_state_control_last_length(teco_machine_main_t *ctx, GError **error)
return;
}
- teco_expressions_push(teco_interface_bytes2glyphs(teco_ranges[n].from) -
- teco_interface_bytes2glyphs(teco_ranges[n].to));
+ teco_expressions_push(teco_ranges[n].from - teco_ranges[n].to);
}
static void TECO_DEBUG_CLEANUP
@@ -2671,7 +2675,8 @@ teco_state_insert_initial(teco_machine_main_t *ctx, GError **error)
if (ctx->flags.mode > TECO_MODE_NORMAL)
return TRUE;
- teco_undo_gsize(teco_ranges[0].from) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos);
teco_undo_guint(teco_ranges_count) = 1;
/*
@@ -2753,9 +2758,11 @@ teco_state_insert_process(teco_machine_main_t *ctx, const teco_string_t *str,
teco_state_t *
teco_state_insert_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error)
{
- if (ctx->flags.mode == TECO_MODE_NORMAL)
- teco_undo_gsize(teco_ranges[0].to) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ if (ctx->flags.mode > TECO_MODE_NORMAL)
+ return &teco_state_start;
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos);
return &teco_state_start;
}
diff --git a/src/core-commands.h b/src/core-commands.h
index 432ec38..9f62da8 100644
--- a/src/core-commands.h
+++ b/src/core-commands.h
@@ -44,8 +44,8 @@ TECO_DECLARE_STATE(teco_state_ctlc_control);
TECO_DECLARE_STATE(teco_state_ecommand);
typedef struct {
- gsize from; /*< start position in bytes */
- gsize to; /*< end position in bytes */
+ teco_int_t from; /*< start position in glyphs */
+ teco_int_t to; /*< end position in glyphs */
} teco_range_t;
extern guint teco_ranges_count;
diff --git a/src/glob.c b/src/glob.c
index 5e013e4..c7013b1 100644
--- a/src/glob.c
+++ b/src/glob.c
@@ -515,8 +515,9 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, const teco_string_t *str
if (!colon_modified) {
gsize len = strlen(filename);
- teco_undo_gsize(teco_ranges[0].from) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
- teco_undo_gsize(teco_ranges[0].to) = teco_ranges[0].from + len + 1;
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos);
+ teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos + len + 1);
teco_undo_guint(teco_ranges_count) = 1;
/*
@@ -550,16 +551,15 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, const teco_string_t *str
g_auto(teco_globber_t) globber;
teco_globber_init(&globber, pattern_str.data, file_flags);
- teco_undo_gsize(teco_ranges[0].from) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
- teco_undo_gsize(teco_ranges[0].to) = teco_ranges[0].from;
- teco_undo_guint(teco_ranges_count) = 1;
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos);
teco_interface_ssm(SCI_BEGINUNDOACTION, 0, 0);
gchar *globbed_filename;
while ((globbed_filename = teco_globber_next(&globber))) {
gsize len = strlen(globbed_filename);
- teco_ranges[0].to += len+1;
+ pos += len+1;
/*
* FIXME: Filenames may contain linefeeds.
@@ -573,6 +573,9 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, const teco_string_t *str
}
teco_interface_ssm(SCI_ENDUNDOACTION, 0, 0);
+
+ teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos);
+ teco_undo_guint(teco_ranges_count) = 1;
}
if (colon_modified) {
diff --git a/src/qreg-commands.c b/src/qreg-commands.c
index 09c3549..0457e92 100644
--- a/src/qreg-commands.c
+++ b/src/qreg-commands.c
@@ -534,8 +534,9 @@ teco_state_getqregstring_got_register(teco_machine_main_t *ctx, teco_qreg_t *qre
if (!qreg->vtable->get_string(qreg, &str.data, &str.len, NULL, error))
return NULL;
- teco_undo_gsize(teco_ranges[0].from) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
- teco_undo_gsize(teco_ranges[0].to) = teco_ranges[0].from + str.len;
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos);
+ teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos + str.len);
teco_undo_guint(teco_ranges_count) = 1;
if (str.len > 0) {
diff --git a/src/search.c b/src/search.c
index b02e178..d5387da 100644
--- a/src/search.c
+++ b/src/search.c
@@ -548,6 +548,16 @@ TECO_DEFINE_UNDO_OBJECT_OWN(ranges, teco_range_t *, g_free);
#define teco_undo_ranges_own(VAR) \
(*teco_undo_object_ranges_push(&(VAR)))
+/**
+ * Extract the ranges of the given GMatchInfo.
+ *
+ * @param match_info The result of g_regex_match().
+ * @param offset The beginning of the match operation in bytes.
+ * Match results will be relative to this offset.
+ * @param count Where to store the number of ranges (subpatterns).
+ * @returns Ranges (subpatterns) in absolute byte positions.
+ * They \b must still be converted to glyph positions afterwards.
+ */
static teco_range_t *
teco_get_ranges(const GMatchInfo *match_info, gsize offset, guint *count)
{
@@ -661,7 +671,7 @@ teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error)
matched[i].ranges = NULL;
}
- for (int i = 0; i < matched_num; i++)
+ for (gint i = 0; i < matched_num; i++)
g_free(matched[i].ranges);
}
@@ -671,7 +681,16 @@ teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error)
teco_undo_guint(teco_ranges_count) = num_ranges;
g_assert(teco_ranges_count > 0);
- teco_interface_ssm(SCI_SETSEL, matched_ranges[0].from, matched_ranges[0].to);
+ teco_interface_ssm(SCI_SETSEL, teco_ranges[0].from, teco_ranges[0].to);
+
+ /*
+ * teco_get_ranges() returned byte positions,
+ * while everything else expects glyph offsets.
+ */
+ for (guint i = 0; i < teco_ranges_count; i++) {
+ teco_ranges[i].from = teco_interface_bytes2glyphs(teco_ranges[i].from);
+ teco_ranges[i].to = teco_interface_bytes2glyphs(teco_ranges[i].to);
+ }
}
return TRUE;
@@ -1083,13 +1102,15 @@ teco_state_search_kill_done(teco_machine_main_t *ctx, const teco_string_t *str,
if (teco_search_parameters.dot < dot) {
/* kill forwards */
sptr_t anchor = teco_interface_ssm(SCI_GETANCHOR, 0, 0);
- gsize len = anchor - teco_search_parameters.dot;
+ teco_int_t len_glyphs = teco_interface_bytes2glyphs(anchor) -
+ teco_interface_bytes2glyphs(teco_search_parameters.dot);
if (teco_current_doc_must_undo())
undo__teco_interface_ssm(SCI_GOTOPOS, dot, 0);
teco_interface_ssm(SCI_GOTOPOS, anchor, 0);
- teco_interface_ssm(SCI_DELETERANGE, teco_search_parameters.dot, len);
+ teco_interface_ssm(SCI_DELETERANGE, teco_search_parameters.dot,
+ anchor - teco_search_parameters.dot);
/* NOTE: An undo action is not always created. */
if (teco_current_doc_must_undo() &&
@@ -1098,8 +1119,8 @@ teco_state_search_kill_done(teco_machine_main_t *ctx, const teco_string_t *str,
/* fix up ranges (^Y) */
for (guint i = 0; i < teco_ranges_count; i++) {
- teco_ranges[i].from -= len;
- teco_ranges[i].to -= len;
+ teco_ranges[i].from -= len_glyphs;
+ teco_ranges[i].to -= len_glyphs;
}
} else {
/* kill backwards */
diff --git a/src/spawn.c b/src/spawn.c
index d51dbb1..187de27 100644
--- a/src/spawn.c
+++ b/src/spawn.c
@@ -420,8 +420,9 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
teco_interface_ssm(SCI_DELETERANGE, teco_spawn_ctx.from,
teco_spawn_ctx.to - teco_spawn_ctx.from);
- teco_undo_gsize(teco_ranges[0].from) = teco_spawn_ctx.from;
- teco_undo_gsize(teco_ranges[0].to) = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
+ teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(teco_spawn_ctx.from);
+ teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos);
teco_undo_guint(teco_ranges_count) = 1;
}
teco_interface_ssm(SCI_ENDUNDOACTION, 0, 0);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 8155ce4..96d4978 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -211,8 +211,10 @@ TE_CHECK([[@I/XYZ/J @EB/foo/ @I/XZY/J @:FN/Z/0/"F(0/0)' Q*-2"N(0/0)'
AT_CLEANUP
AT_SETUP([Search and insertion ranges])
-TE_CHECK([[@I/XXYYZZ/^SC ."N(0/0)' C @S/YY/^YU1U0 Q0-2"N(0/0)' Q1-4"N(0/0)']], 0, ignore, ignore)
+# When deleting characters, the result of ^S/^Y must not change.
+TE_CHECK([[@I/XXYYZZ/^SC ."N(0/0)' C @S/YY/ HK ^YU1U0 Q0-2"N(0/0)' Q1-4"N(0/0)']], 0, ignore, ignore)
TE_CHECK([[@I/XXYYZZ/J @S/XX^E[^EMY]/ 1^YXa :Qa-2"N(0/0)']], 0, ignore, ignore)
+TE_CHECK([[@I/XXYYZZ/J @FD/^EMZ/ ^S+2"N(0/0)']], 0, ignore, ignore)
AT_CLEANUP
AT_SETUP([Editing local registers in macro calls])