summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpgen <p.gen.progs@gmail.com>2019-03-24 18:23:18 +0100
committerpgen <p.gen.progs@gmail.com>2019-03-25 00:14:28 +0100
commit01ea40a6cffccd89f97fa59c0a056df496a1ed3a (patch)
tree4ee8b458cc29cfe3f2e5dd6320e7f45beb41cc69
parentc464effa80ed83d4e146dabd6b8bd6bb9dacb3f9 (diff)
Improve the PgUp/PgDn scrolling
When on the first/last line containing a selectable word, PgUp/PgDn will move the window to show the maximum number of non selectable lines while keeping the cursor in the window.
-rw-r--r--smenu.c240
-rw-r--r--tests/scrolling/data720
-rw-r--r--tests/scrolling/t0005.good10
-rw-r--r--tests/scrolling/t0006.good10
-rw-r--r--tests/scrolling/t0011.good19
l---------tests/scrolling/t0011.in1
-rw-r--r--tests/scrolling/t0011.tst4
7 files changed, 216 insertions, 88 deletions
diff --git a/smenu.c b/smenu.c
index ecaa8fd..e159df2 100644
--- a/smenu.c
+++ b/smenu.c
@@ -4525,6 +4525,7 @@ move_up(win_t * win, term_t * term, toggle_t * toggle,
long line; /* The line being processed (the target line) */
long start_line; /* The first line of the window */
long cur_line; /* The line of the cursor */
+ long nlines; /* Number of line in the window */
long first_selectable_line; /* the line containing the first *
* selectable word */
long lines_skipped; /* The number of line between the target line and the *
@@ -4548,52 +4549,92 @@ move_up(win_t * win, term_t * term, toggle_t * toggle,
first_selectable_line = line_nb_of_word_a[first_selectable];
lines_skipped = 0;
found = 0;
+ nlines = win->max_lines < last_line + 1 ? win->max_lines : last_line + 1;
/* initialise the target line */
/* """""""""""""""""""""""""" */
line = cur_line;
- if (line - page < 0)
- {
- /* Trivial case, we are already on the first page */
- /* just jump to the first selectable line */
- /* """""""""""""""""""""""""""""""""""""""""""""" */
- line = first_selectable_line;
- last_word = get_line_last_word(line, last_line);
- find_best_word_upward(win, term, line, last_word, s, e);
+ /* Special case if the cursor is already in the line containing the */
+ /* first selectable word. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (line == first_selectable_line)
+ {
+ /* we can't move the cursor up but we still can try to show the */
+ /* more non selectable words as we can. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (line <= start_line + nlines - 1 - page)
+ {
+ /* We are scrolling one line at a time and the cursor is not in */
+ /* the last line of the window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (start_line - page > 0)
+ /* There is enough remaining line to fill a window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''' */
+ start_line -= page;
+ else
+ /* We cannot scroll further */
+ /* '''''''''''''''''''''''' */
+ start_line = 0;
+ }
+ else
+ {
+ /* The cursor is already in the last line of the windows. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (line >= nlines)
+ /* There is enough remaining line to fill a window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''' */
+ start_line = line - nlines + 1;
+ else
+ /* We cannot scroll further */
+ /* '''''''''''''''''''''''' */
+ start_line = 0;
+ }
}
else
{
- /* Temporarily move up one page */
- /* """""""""""""""""""""""""""" */
- line -= page;
-
- /* The target line cannot be before the line containing the first */
- /* selectable word. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (line < first_selectable_line)
+ if (line - page < 0)
{
+ /* Trivial case, we are already on the first page */
+ /* just jump to the first selectable line */
+ /* """""""""""""""""""""""""""""""""""""""""""""" */
line = first_selectable_line;
last_word = get_line_last_word(line, last_line);
find_best_word_upward(win, term, line, last_word, s, e);
}
else
{
- /* If this is not the case, search upward for the line with a */
- /* selectable word. This line is guaranteed to exist. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- while (line >= first_selectable_line)
+ /* Temporarily move up one page */
+ /* """""""""""""""""""""""""""" */
+ line -= page;
+
+ /* The target line cannot be before the line containing the first */
+ /* selectable word. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (line < first_selectable_line)
{
+ line = first_selectable_line;
last_word = get_line_last_word(line, last_line);
-
- if (find_best_word_upward(win, term, line, last_word, s, e))
+ find_best_word_upward(win, term, line, last_word, s, e);
+ }
+ else
+ {
+ /* If this is not the case, search upward for the line with a */
+ /* selectable word. This line is guaranteed to exist. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ while (line >= first_selectable_line)
{
- found = 1;
- break;
- }
+ last_word = get_line_last_word(line, last_line);
- line--;
- lines_skipped++;
+ if (find_best_word_upward(win, term, line, last_word, s, e))
+ {
+ found = 1;
+ break;
+ }
+
+ line--;
+ lines_skipped++;
+ }
}
}
}
@@ -4606,7 +4647,7 @@ move_up(win_t * win, term_t * term, toggle_t * toggle,
/* There is enough place to scroll up a page but only scrolls */
/* up if the cursor remains in the window */
/* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (start_line + win->max_lines - line > page)
+ if (start_line + nlines - line > page)
start_line -= page;
}
else if (line < start_line)
@@ -4647,6 +4688,7 @@ move_down(win_t * win, term_t * term, toggle_t * toggle,
long line; /* The line being processed (the target line) */
long start_line; /* The first line of the window */
long cur_line; /* The line of the cursor */
+ long nlines; /* Number of line in the window */
long last_selectable_line; /* the line containing the last *
* selectable word */
long lines_skipped; /* The number of line between the target line and the *
@@ -4670,78 +4712,120 @@ move_down(win_t * win, term_t * term, toggle_t * toggle,
last_selectable_line = line_nb_of_word_a[last_selectable];
lines_skipped = 0;
found = 0;
+ nlines = win->max_lines < last_line + 1 ? win->max_lines : last_line + 1;
/* initialise the target line */
/* """""""""""""""""""""""""" */
line = cur_line;
- if (last_line - line - page < 0)
- {
- /* Trivial case, we are already on the last page */
- /* just jump to the last selectable line */
- /* """""""""""""""""""""""""""""""""""""""""""""" */
- line = last_selectable_line;
- last_word = get_line_last_word(line, last_line);
- find_best_word_downward(win, term, line, last_word, s, e);
+ /* Special case if the cursor is already in the line containing the */
+ /* last selectable word. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (line == last_selectable_line)
+ {
+ /* we can't move the cursor down but we still can try to show the */
+ /* more non selectable words as we can. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (line >= start_line + page)
+ {
+ /* We are scrolling one line at a time and the cursor is not in */
+ /* the first line of the window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (start_line + page + nlines - 1 <= last_line)
+ /* There is enough remaining line to fill a window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''' */
+ start_line += page;
+ else
+ /* We cannot scroll further */
+ /* '''''''''''''''''''''''' */
+ start_line = last_line - nlines + 1;
+ }
+ else
+ {
+ /* The cursor is already in the first line of the windows. */
+ /* ''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ if (last_line - line + 1 > nlines)
+ /* There is enough remaining line to fill a window. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''' */
+ start_line = line;
+ else
+ /* We cannot scroll further */
+ /* '''''''''''''''''''''''' */
+ start_line = last_line - nlines + 1;
+ }
}
else
{
- /* Temporarily move down one page */
- /* """""""""""""""""""""""""""""" */
- line += page;
-
- /* The target line cannot be before the line containing the first */
- /* selectable word. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (line > last_selectable_line)
+ /* The cursor is above the line containing the last selectable word. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (last_line - line - page < 0)
{
+ /* Trivial case, we are already on the last page */
+ /* just jump to the last selectable line */
+ /* """""""""""""""""""""""""""""""""""""""""""""" */
line = last_selectable_line;
last_word = get_line_last_word(line, last_line);
find_best_word_downward(win, term, line, last_word, s, e);
}
else
{
- /* If this is not the case, search upward for the line with a */
- /* selectable word. This line is guaranteed to exist. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- while (line <= last_selectable_line)
+ /* Temporarily move down one page */
+ /* """""""""""""""""""""""""""""" */
+ line += page;
+
+ /* The target line cannot be before the line containing the first */
+ /* selectable word. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (line > last_selectable_line)
{
+ line = last_selectable_line;
last_word = get_line_last_word(line, last_line);
-
- if (find_best_word_downward(win, term, line, last_word, s, e))
+ find_best_word_downward(win, term, line, last_word, s, e);
+ }
+ else
+ {
+ /* If this is not the case, search upward for the line with a */
+ /* selectable word. This line is guaranteed to exist. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ while (line <= last_selectable_line)
{
- found = 1;
- break;
- }
+ last_word = get_line_last_word(line, last_line);
- line++;
- lines_skipped++;
+ if (find_best_word_downward(win, term, line, last_word, s, e))
+ {
+ found = 1;
+ break;
+ }
+
+ line++;
+ lines_skipped++;
+ }
}
}
- }
- /* Look if we need to adjust the window to follow the cursor */
- /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (!found && start_line + win->max_lines - 1 + page <= last_line)
- {
- /* We are on the last line containing a selectable word and */
- /* There is enough place to scroll down a page but only scrolls */
- /* down if the cursor remains in the window */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (line - start_line >= page)
- start_line += page;
- }
- else if (line > start_line + win->max_lines - 1)
- {
- /* The target line is below the windows */
- /* """""""""""""""""""""""""""""""""""" */
- if (start_line + win->max_lines + page + lines_skipped - 1 > last_line)
- /* There isn't enough remaining lines to scroll down */
- /* a page size. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""" */
- start_line = last_line - win->max_lines + 1;
- else
- start_line += page + lines_skipped;
+ /* Look if we need to adjust the window to follow the cursor */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (!found && start_line + nlines - 1 + page <= last_line)
+ {
+ /* We are on the last line containing a selectable word and */
+ /* There is enough place to scroll down a page but only scrolls */
+ /* down if the cursor remains in the window */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (line - start_line >= page)
+ start_line += page;
+ }
+ else if (line > start_line + nlines - 1)
+ {
+ /* The target line is below the windows */
+ /* """""""""""""""""""""""""""""""""""" */
+ if (start_line + nlines + page + lines_skipped - 1 > last_line)
+ /* There isn't enough remaining lines to scroll down */
+ /* a page size. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""" */
+ start_line = last_line - nlines + 1;
+ else
+ start_line += page + lines_skipped;
+ }
}
/* And set the new value of the starting word of the window */
diff --git a/tests/scrolling/data7 b/tests/scrolling/data7
new file mode 100644
index 0000000..dd80bc8
--- /dev/null
+++ b/tests/scrolling/data7
@@ -0,0 +1,20 @@
+ 0 a a a a a
+ 1 a a a a a
+ 2 a a a a a
+ 3 a a a a a
+ 4 a a a a a
+ 5 a a a a a
+ 6 b b b a a
+ 7 a a a a a
+ 8 b b b b b
+ 9 b b b b b
+ 10 b b b b b
+ 11 b b b b b
+ 12 a a a a a
+ 13 b b b b b
+ 14 a a a a a
+ 15 a a a a a
+ 16 a a a a a
+ 17 a a a a a
+ 18 a a a a a
+ 19 a a a a a
diff --git a/tests/scrolling/t0005.good b/tests/scrolling/t0005.good
index bd94555..fe06086 100644
--- a/tests/scrolling/t0005.good
+++ b/tests/scrolling/t0005.good
@@ -1,14 +1,14 @@
$ OUT=$(LC_ALL=en_US smenu -R 7,13 -c t0005.in)
-10 b b b b b ^
-0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
-11 a a a a a |
+11 a a a a a ^
0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
12 a a a a a |
5:07 14:20
-13 a a a a a +
+13 a a a a a |
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
+14 a a a a a +
0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
-14 a a a a a v
+15 a a a a a /
0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
$
diff --git a/tests/scrolling/t0006.good b/tests/scrolling/t0006.good
index bb2c605..704583c 100644
--- a/tests/scrolling/t0006.good
+++ b/tests/scrolling/t0006.good
@@ -1,14 +1,14 @@
$ OUT=$(LC_ALL=en_US smenu -R 6,18,20 -c t0006.in)
-4 a a a a a a a a ^
+3 a a a a a a a a ^
0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20
-5 a a a a a a a a +
+4 a a a a a a a a +
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20
+5 a a a a a a a a |
5:07 20:20
6 a a a a a a a a |
0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20
-7 a a a a a a a a |
-0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20
-8 a a a a a a a a v
+7 a a a a a a a a v
0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20
$
diff --git a/tests/scrolling/t0011.good b/tests/scrolling/t0011.good
new file mode 100644
index 0000000..5716b76
--- /dev/null
+++ b/tests/scrolling/t0011.good
@@ -0,0 +1,19 @@
+$ OUT=$(LC_ALL=en_US smenu -c -e a -e '[0-9]' t0011.in)
+
+2 a a a a a ^
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
+3 a a a a a +
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
+4 a a a a a |
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
+5 a a a a a |
+0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20
+6 b b b a a v
+0:24 1:24 3:07 9:24 11:24 14:20
+$
+
+$ echo ":$OUT:"
+
+:b:
+
+$ exit 0
diff --git a/tests/scrolling/t0011.in b/tests/scrolling/t0011.in
new file mode 120000
index 0000000..592b7e2
--- /dev/null
+++ b/tests/scrolling/t0011.in
@@ -0,0 +1 @@
+data7 \ No newline at end of file
diff --git a/tests/scrolling/t0011.tst b/tests/scrolling/t0011.tst
new file mode 100644
index 0000000..2bb67c5
--- /dev/null
+++ b/tests/scrolling/t0011.tst
@@ -0,0 +1,4 @@
+\S[150]\s[10]OUT=$(LC_ALL=en_US smenu -c -e a -e '[0-9]' t0011.in)
+\S[150]\s[150]JJJJKKKKK\r
+\S[150]\s[10]echo ":$\s[10]OUT:"
+exit 0