From 0ee4b27a9d685ce3058347c12742270a083d84d6 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 2 Dec 2016 22:21:35 -0500 Subject: [PATCH] added logic for centering the cursor on search, set line, and jump to ctag. Also fixed a bug allowing scrolling past the end of the buffer --- TODO.md | 4 ++-- inc/edit.h | 3 ++- libedit/view.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index db2af2d..8ebac84 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,9 @@ # Implementation Tweaks and Bug Fixes -* center find results and jumped to line on screen +* bug when jumping to ctag from tag view instead of edit view +* add a shortcut to autocomplete ctag * Use select to check for error strings in exec.c * Should not be able to undo initial tag line text insertion -* Disallow scrolling past end of buffer * track down double click bug for selecting whole line * Add tag for ctags lookup * Implement minimal regex search (per Kernighan article) diff --git a/inc/edit.h b/inc/edit.h index 97def27..2058cb4 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -114,7 +114,8 @@ typedef struct { } Row; typedef struct { - bool sync_needed; /* determines whether the view needs to be synced with cursor */ + bool sync_needed; /* whether the view needs to be synced with cursor */ + bool sync_center; /* cursor should be centered on screen if possible */ size_t nrows; /* number of rows in the view */ size_t ncols; /* number of columns in the view */ Row** rows; /* array of row data structures */ diff --git a/libedit/view.c b/libedit/view.c index c043cfb..426ee35 100644 --- a/libedit/view.c +++ b/libedit/view.c @@ -92,6 +92,7 @@ static unsigned scroll_up(View* view) { unsigned first = view->rows[0]->off; unsigned bol = buf_bol(&(view->buffer), first); unsigned prevln = (first == bol ? buf_byline(&(view->buffer), bol, -1) : bol); + if (!first) return first; prevln = prev_screen_line(view, prevln, first); /* delete the last row and shift the others */ free(view->rows[view->nrows - 1]); @@ -105,6 +106,7 @@ static unsigned scroll_up(View* view) { static unsigned scroll_dn(View* view) { unsigned last = view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen - 1; + if (last >= buf_end(&(view->buffer))) return last; /* delete the first row and shift the others */ if (view->nrows > 1) { free(view->rows[0]); @@ -120,6 +122,26 @@ static unsigned scroll_dn(View* view) { return view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen - 1; } +static void sync_center(View* view, size_t csr) { + /* determine the screenline containing the cursor */ + size_t scrln = 0; + for (; scrln < view->nrows; scrln++) { + unsigned first = view->rows[scrln]->off; + unsigned last = first + view->rows[scrln]->rlen - 1; + if (csr >= first && csr <= last) + break; + } + /* find the middle row and scroll until the cursor is on that row */ + unsigned midrow = view->nrows / 2; + int move = (scrln - midrow); + unsigned count = (move < 0 ? -move : move); + for (; count > 0; count--) + if (move < 0) + scroll_up(view); + else + scroll_dn(view); +} + static void sync_view(View* view, size_t csr) { unsigned first = view->rows[0]->off; unsigned last = view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen - 1; @@ -128,6 +150,10 @@ static void sync_view(View* view, size_t csr) { while (csr > last && last < buf_end(&(view->buffer))) last = scroll_dn(view); view->sync_needed = false; + if (view->sync_center) { + sync_center(view, csr); + view->sync_center = false; + } } static size_t getoffset(View* view, size_t row, size_t col) { @@ -157,6 +183,7 @@ void view_init(View* view, char* file) { view->selection.end = buf_load(&(view->buffer), file); view->selection.beg = view->selection.end; view->sync_needed = true; + view->sync_center = true; } } @@ -359,6 +386,7 @@ void view_find(View* view, size_t row, size_t col) { } view->selection = sel; view->sync_needed = true; + view->sync_center = true; } } @@ -367,6 +395,7 @@ void view_findstr(View* view, char* str) { buf_findstr(&(view->buffer), str, &sel.beg, &sel.end); view->selection = sel; view->sync_needed = true; + view->sync_center = true; } void view_insert(View* view, bool indent, Rune rune) { @@ -523,4 +552,5 @@ void view_setln(View* view, size_t line) { view->selection.end = buf_setln(&(view->buffer), line); view->selection.beg = view->selection.end; view->sync_needed = true; + view->sync_center = true; } -- 2.54.0