aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/search.c
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2025-06-08 20:54:29 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2025-06-08 20:54:29 +0200
commitaaa1d51a4c85fcc627e88ef7cf5292d9c5f5f840 (patch)
tree34da0d4a3218c622dbd34816607a93e2227157ac /src/search.c
parent36448a42917560ce00c13c1ad4d56f46c3614937 (diff)
downloadsciteco-aaa1d51a4c85fcc627e88ef7cf5292d9c5f5f840.tar.gz
^S/^Y calculates the glyph offsets earlier
* Previously, deleting text after a text match or insertion could result in wrong ^S/^Y results. In particular, the amount of characters deleted by <FD> at the end of a buffer couldn't be queried. * This also fixes the M#rf (reflow paragraph) macro.
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c33
1 files changed, 27 insertions, 6 deletions
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 */