fix: the search label no longer claims an off-screen selected hit is in view

place_search_marks() places the selected hit unconditionally to keep it marked when stepping
to it, but the label must distinguish this case from hits that are actually visible on screen,
so it does not lie about what is in view. add sel_off_view to track when the selected hit is
off screen, introduce a shown count that excludes it, and emit a third label case when only
the selected hit is off screen.
This commit is contained in:
Martino Ferrari committed 2026-10-08 10:25:27 +02:00
1 parent 5bb4bd207d
commit 4a58887cb1
1 file changed
+15 -3
+15 -3
View File
@@ -3358,6 +3358,7 @@ void place_search_marks(App& app) {
std::vector<double> xs;
int current = -1;
std::size_t in_view = 0;
bool sel_off_view = false;
const std::vector<double>& hits = app.search.hits();
if (!hits.empty()) {
const double s0 = app.model->stream_at_x0();
@@ -3377,22 +3378,33 @@ void place_search_marks(App& app) {
std::sort(cand.begin(), cand.end());
const std::size_t cap = static_cast<std::size_t>(RowSet::kSearchMarks);
// xs.reserve(cap) is only a hint; the actual cap is enforced by xs.size() < cap in the fill loop.
xs.reserve(cap);
if (sel >= 0 && sel < static_cast<int>(hits.size())) {
current = 0;
xs.push_back(hits[static_cast<std::size_t>(sel)] - s0);
const double x = hits[static_cast<std::size_t>(sel)] - s0;
// The selected hit is placed whether or not it is on screen, so the label must not fold it
// into the in-view count: it is the one mark `in_view` above deliberately did not see.
sel_off_view = x < view.min || x > view.max;
xs.push_back(x);
}
for (std::size_t i = 0; i < cand.size() && xs.size() < cap; ++i) xs.push_back(cand[i].second);
}
if (app.search_marks_label != nullptr) {
// The marks that are *in view*: `xs` also carries the selected hit when it is off screen.
const std::size_t shown = xs.size() - (sel_off_view ? 1u : 0u);
char text[128];
if (hits.empty()) {
std::snprintf(text, sizeof(text), " ");
} else if (in_view > xs.size()) {
} else if (in_view > shown) {
// A truncated display says so: "16 of 38" with no qualifier reads as "there are 38 and you
// are seeing 16 of them *everywhere*", which is not the claim.
std::snprintf(text, sizeof(text), "%zu of %zu marks shown \xE2\x80\x94 zoom in to see the rest",
xs.size(), in_view);
shown, in_view);
} else if (sel_off_view) {
std::snprintf(text, sizeof(text),
"%zu of %zu in view \xE2\x80\x94 the selected hit is outside the window", shown,
hits.size());
} else {
std::snprintf(text, sizeof(text), "%zu of %zu in view", xs.size(), hits.size());
}