aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.def.h20
-rw-r--r--vis.c44
-rw-r--r--window.c46
-rw-r--r--window.h2
4 files changed, 72 insertions, 40 deletions
diff --git a/config.def.h b/config.def.h
index d21b603..b502135 100644
--- a/config.def.h
+++ b/config.def.h
@@ -93,8 +93,8 @@ static KeyBinding basic_movement[] = {
{ { KEY(SRIGHT) }, movement, { .i = MOVE_WORD_START_NEXT } },
{ { KEY(UP) }, movement, { .i = MOVE_LINE_UP } },
{ { KEY(DOWN) }, movement, { .i = MOVE_LINE_DOWN } },
- { { KEY(PPAGE) }, cursor, { .m = window_page_up } },
- { { KEY(NPAGE) }, cursor, { .m = window_page_down } },
+ { { KEY(PPAGE) }, wscroll, { .i = -PAGE } },
+ { { KEY(NPAGE) }, wscroll, { .i = +PAGE } },
{ { KEY(HOME) }, movement, { .i = MOVE_LINE_START } },
{ { KEY(END) }, movement, { .i = MOVE_LINE_FINISH } },
{ /* empty last element, array terminator */ },
@@ -347,8 +347,12 @@ static KeyBinding vis_mode_normal[] = {
{ { CONTROL('w'), NONE('s') }, winsplit, { .b = false } },
{ { CONTROL('w'), NONE('j') }, call, { .f = editor_window_next } },
{ { CONTROL('w'), NONE('k') }, call, { .f = editor_window_prev } },
- { { CONTROL('F') }, cursor, { .m = window_page_up } },
- { { CONTROL('B') }, cursor, { .m = window_page_down } },
+ { { CONTROL('F') }, wscroll, { .i = -PAGE } },
+ { { CONTROL('B') }, wscroll, { .i = +PAGE } },
+ { { CONTROL('U') }, wscroll, { .i = -PAGE_HALF } },
+ { { CONTROL('D') }, wscroll, { .i = +PAGE_HALF } },
+ { { CONTROL('E') }, wslide, { .i = -1 } },
+ { { CONTROL('Y') }, wslide, { .i = +1 } },
{ { NONE('A') }, insertmode, { .i = MOVE_LINE_END } },
{ { NONE('C') }, change, { .i = MOVE_LINE_END } },
{ { NONE('D') }, delete, { .i = MOVE_LINE_END } },
@@ -675,10 +679,10 @@ static KeyBinding nano_keys[] = {
{ { CONTROL('F') }, movement, { .i = MOVE_CHAR_NEXT } },
{ { CONTROL('P') }, movement, { .i = MOVE_LINE_UP } },
{ { CONTROL('N') }, movement, { .i = MOVE_LINE_DOWN } },
- { { CONTROL('Y') }, cursor, { .m = window_page_up } },
- { { KEY(F(7)) }, cursor, { .m = window_page_up } },
- { { CONTROL('V') }, cursor, { .m = window_page_down } },
- { { KEY(F(8)) }, cursor, { .m = window_page_down } },
+ { { CONTROL('Y') }, wscroll, { .i = -PAGE } },
+ { { KEY(F(7)) }, wscroll, { .i = -PAGE } },
+ { { CONTROL('V') }, wscroll, { .i = +PAGE } },
+ { { KEY(F(8)) }, wscroll, { .i = +PAGE } },
#if 0
// CONTROL(' ') == 0 which signals the end of array
{ { CONTROL(' ') }, movement, { .i = MOVE_WORD_START_NEXT } },
diff --git a/vis.c b/vis.c
index 3a6a3a3..05bcb40 100644
--- a/vis.c
+++ b/vis.c
@@ -21,6 +21,7 @@
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -41,7 +42,7 @@ int ESCDELAY;
typedef union {
bool b;
- size_t i;
+ int i;
const char *s;
size_t (*m)(Win*); /* cursor movement based on window content */
void (*f)(Editor*); /* generic editor commands */
@@ -163,6 +164,9 @@ static Operator ops[] = {
[OP_PUT] = { op_put, true },
};
+#define PAGE INT_MAX
+#define PAGE_HALF (INT_MAX-1)
+
/* these can be passed as int argument to movement(&(const Arg){ .i = MOVE_* }) */
enum {
MOVE_LINE_UP,
@@ -384,9 +388,12 @@ static void prompt_up(const Arg *arg);
static void prompt_down(const Arg *arg);
/* blocks to read 3 consecutive digits and inserts the corresponding byte value */
static void insert_verbatim(const Arg *arg);
-/* cursor movement based on the current window content as indicated by arg->m
- * which should point to a function from window.h */
-static void cursor(const Arg *arg);
+/* scroll window content according to arg->i which can be either PAGE, PAGE_HALF,
+ * or an arbitrary number of lines. a multiplier overrides what is given in arg->i.
+ * negative values scroll back, positive forward. */
+static void wscroll(const Arg *arg);
+/* similar to scroll, but do only move window content not cursor position */
+static void wslide(const Arg *arg);
/* call editor function as indicated by arg->f */
static void call(const Arg *arg);
/* quit editor, discard all changes */
@@ -734,8 +741,33 @@ static void winsplit(const Arg *arg) {
editor_window_split(vis, NULL);
}
-static void cursor(const Arg *arg) {
- arg->m(vis->win->win);
+static int argi2lines(const Arg *arg) {
+ switch (arg->i) {
+ case -PAGE:
+ case +PAGE:
+ return vis->win->height-1;
+ case -PAGE_HALF:
+ case +PAGE_HALF:
+ return vis->win->height/2;
+ default:
+ if (action.count > 0)
+ return action.count;
+ return arg->i < 0 ? -arg->i : arg->i;
+ }
+}
+
+static void wscroll(const Arg *arg) {
+ if (arg->i >= 0)
+ window_scroll_down(vis->win->win, argi2lines(arg));
+ else
+ window_scroll_up(vis->win->win, argi2lines(arg));
+}
+
+static void wslide(const Arg *arg) {
+ if (arg->i >= 0)
+ window_slide_down(vis->win->win, argi2lines(arg));
+ else
+ window_slide_up(vis->win->win, argi2lines(arg));
}
static void call(const Arg *arg) {
diff --git a/window.c b/window.c
index 8ed4767..db35c4d 100644
--- a/window.c
+++ b/window.c
@@ -619,52 +619,50 @@ static bool window_viewport_up(Win *win, int n) {
size_t window_slide_up(Win *win, int lines) {
Cursor *cursor = &win->cursor;
- if (window_viewport_up(win, lines)) {
- if (cursor->line == win->lastline)
- window_cursor_set(win, win->lastline, cursor->col);
+ if (window_viewport_down(win, lines)) {
+ if (cursor->line == win->topline)
+ window_cursor_set(win, win->topline, cursor->col);
else
window_cursor_to(win, cursor->pos);
} else {
- window_cursor_to(win, 0);
+ window_line_down(win);
}
return cursor->pos;
}
size_t window_slide_down(Win *win, int lines) {
Cursor *cursor = &win->cursor;
- if (window_viewport_down(win, lines)) {
- if (cursor->line == win->topline)
- window_cursor_set(win, win->topline, cursor->col);
+ if (window_viewport_up(win, lines)) {
+ if (cursor->line == win->lastline)
+ window_cursor_set(win, win->lastline, cursor->col);
else
window_cursor_to(win, cursor->pos);
} else {
- window_cursor_to(win, text_size(win->text));
+ window_line_up(win);
}
return cursor->pos;
}
size_t window_scroll_up(Win *win, int lines) {
- if (window_viewport_up(win, lines))
- window_cursor_set(win, win->topline, win->cursor.col);
- else
+ Cursor *cursor = &win->cursor;
+ if (window_viewport_up(win, lines)) {
+ Line *line = cursor->line < win->lastline ? cursor->line : win->lastline;
+ window_cursor_set(win, line, win->cursor.col);
+ } else {
window_cursor_to(win, 0);
- return win->cursor.pos;
+ }
+ return cursor->pos;
}
size_t window_scroll_down(Win *win, int lines) {
- if (window_viewport_down(win, lines))
- window_cursor_set(win, win->lastline, win->cursor.col);
- else
+ Cursor *cursor = &win->cursor;
+ if (window_viewport_down(win, lines)) {
+ Line *line = cursor->line > win->topline ? cursor->line : win->topline;
+ window_cursor_set(win, line, cursor->col);
+ } else {
window_cursor_to(win, text_size(win->text));
- return win->cursor.pos;
-}
-
-size_t window_page_up(Win *win) {
- return window_scroll_up(win, win->height);
-}
-
-size_t window_page_down(Win *win) {
- return window_scroll_down(win, win->height);
+ }
+ return cursor->pos;
}
size_t window_line_up(Win *win) {
diff --git a/window.h b/window.h
index 602c962..46322aa 100644
--- a/window.h
+++ b/window.h
@@ -27,8 +27,6 @@ void window_update(Win*);
/* cursor movements which also update selection if one is active.
* they return new cursor postion */
-size_t window_page_down(Win*);
-size_t window_page_up(Win*);
size_t window_char_next(Win*);
size_t window_char_prev(Win*);
size_t window_line_down(Win*);