commit 4f7b4022bfe76c4f8d38327cca695a595f00ca11
parent f2fe0c0dc5a4ba4fa80f6798e29c3637e98727eb
Author: Louis Burda <quent.burda@gmail.com>
Date: Tue, 20 Jun 2023 16:59:13 +0200
Fix PGUP/PGDN seeking
Diffstat:
M | tmenu.c | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
1 file changed, 46 insertions(+), 32 deletions(-)
diff --git a/tmenu.c b/tmenu.c
@@ -69,7 +69,7 @@ struct mode {
struct searchmode {
char c;
- ssize_t (*match)(ssize_t, int, bool, size_t, ssize_t);
+ ssize_t (*match)(ssize_t, int, size_t, ssize_t, bool, bool);
};
static void browse_prompt(void);
@@ -81,11 +81,11 @@ static bool search_handlekey(int c);
static void search_cleanup(void);
static ssize_t search_match(ssize_t start, int dir,
- bool new, size_t cnt, ssize_t fallback);
+ size_t cnt, ssize_t fallback, bool new, bool closest);
static ssize_t search_match_substr(ssize_t start, int dir,
- bool new, size_t cnt, ssize_t fallback);
+ size_t cnt, ssize_t fallback, bool new, bool closest);
static ssize_t search_match_fuzzy(ssize_t start, int dir,
- bool new, size_t cnt, ssize_t fallback);
+ size_t cnt, ssize_t fallback, bool new, bool closest);
static const struct searchmode searchmodes[] = {
[SEARCH_SUBSTR] = {
@@ -388,11 +388,11 @@ search_prompt(void)
if (selected < 0) selected = 0;
- index = search_match(selected, FWD, 0, 1, -1);
+ index = search_match(selected, FWD, 1, -1, false, true);
if (index != -1) {
selected = index;
} else {
- selected = search_match(selected, BWD, 1, 1, -1);
+ selected = search_match(selected, BWD, 1, -1, true, true);
}
if (show_prompt && top_prompt) {
@@ -408,12 +408,12 @@ search_prompt(void)
if (selected >= 0) {
if (i < 0) {
index = search_match(selected,
- BWD, 1, (size_t) -i, -1);
+ BWD, (size_t) -i, -1, true, false);
} else if (i == 0) {
index = selected;
} else if (i > 0) {
index = search_match(selected,
- FWD, 1, (size_t) i, -1);
+ FWD, (size_t) i, -1, true, false);
}
} else {
index = -1;
@@ -468,19 +468,19 @@ search_handlekey(int c)
break;
case KEY_PGUP:
cnt = fwdctx + bwdctx + 1;
- selected = search_match(selected, BWD, 1, cnt, selected);
+ selected = search_match(selected, BWD, cnt, selected, true, true);
break;
case KEY_PGDN:
cnt = fwdctx + bwdctx + 1;
- selected = search_match(selected, FWD, 1, cnt, selected);
+ selected = search_match(selected, FWD, cnt, selected, true, true);
break;
case KEY_CTRL('K'):
case KEY_UP:
- selected = search_match(selected, BWD, 1, 1, selected);
+ selected = search_match(selected, BWD, 1, selected, true, true);
break;
case KEY_CTRL('L'):
case KEY_DOWN:
- selected = search_match(selected, FWD, 1, 1, selected);
+ selected = search_match(selected, FWD, 1, selected, true, true);
break;
case 0x20 ... 0x7e:
if (searchlen < sizeof(searchbuf) - 1)
@@ -506,26 +506,40 @@ search_cleanup(void)
}
static ssize_t
-search_match(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback)
+search_match(ssize_t start, int dir,
+ size_t cnt, ssize_t fallback, bool new, bool closest)
{
- return searchmodes[searchmode].match(start, dir, new, cnt, fallback);
+ return searchmodes[searchmode].match(start, dir,
+ cnt, fallback, new, closest);
+}
+
+static ssize_t
+search_match_linear(ssize_t start, int dir,
+ size_t cnt, ssize_t fallback, bool new, bool closest)
+{
+ ssize_t index;
+
+ index = start + dir * (ssize_t) (new + cnt - 1);
+ if (index < 0) return closest ? 0 : fallback;
+ if (index >= delims_cnt)
+ return closest ? (ssize_t) delims_cnt - 1 : fallback;
+
+ return index;
}
static ssize_t
search_match_substr(ssize_t start, int dir,
- bool new, size_t cnt, ssize_t fallback)
+ size_t cnt, ssize_t fallback, bool new, bool closest)
{
const char *end, *bp;
size_t i, found;
- ssize_t index;
+ ssize_t index, prev;
- if (!searchlen) {
- index = start + dir * (ssize_t) (new + cnt - 1);
- if (index < 0 || index >= delims_cnt)
- return fallback;
- return index;
- }
+ if (!searchlen)
+ return search_match_linear(start, dir,
+ cnt, fallback, new, closest);
+ prev = -1;
found = 0;
for (i = new; i < delims_cnt; i++) {
index = start + dir * (ssize_t) i;
@@ -540,29 +554,28 @@ search_match_substr(ssize_t start, int dir,
if (search_eq(bp, searchbuf, searchlen)) {
if (++found == cnt)
return index;
+ prev = index;
break;
}
}
}
- return fallback;
+ return closest ? prev : fallback;
}
static ssize_t
search_match_fuzzy(ssize_t start, int dir,
- bool new, size_t cnt, ssize_t fallback)
+ size_t cnt, ssize_t fallback, bool new, bool closest)
{
const char *end, *pos, *c;
size_t i, found;
- ssize_t index;
+ ssize_t index, prev;
- if (!searchlen) {
- index = start + dir * (ssize_t) (new + cnt - 1);
- if (index < 0 || index >= delims_cnt)
- return fallback;
- return index;
- }
+ if (!searchlen)
+ return search_match_linear(start, dir,
+ cnt, fallback, new, closest);
+ prev = -1;
found = 0;
for (i = new; i < delims_cnt; i++) {
index = start + dir * (ssize_t) i;
@@ -581,10 +594,11 @@ search_match_fuzzy(ssize_t start, int dir,
if (c == searchbuf + searchlen) {
if (++found == cnt)
return index;
+ prev = index;
}
}
- return fallback;
+ return closest ? prev : fallback;
}
static void