diff --git a/src/global.c b/src/global.c index a6999e72..63f396f6 100644 --- a/src/global.c +++ b/src/global.c @@ -125,6 +125,8 @@ WINDOW *edit = NULL; WINDOW *bottomwin = NULL; /* The bottom portion of the screen, where we display statusbar * messages, the status-bar prompt, and a list of shortcuts. */ +WINDOW *scrollbarwin = NULL; + /* The last column of the screen. It is used to display the scrollbar. */ int editwinrows = 0; /* How many rows does the edit window take up? */ int editwincols = -1; diff --git a/src/nano.c b/src/nano.c index 024a5f19..4b2462c1 100644 --- a/src/nano.c +++ b/src/nano.c @@ -239,11 +239,13 @@ void finish(void) wrefresh(bottomwin); #ifndef NANO_TINY - /* Deallocate the two or three subwindows. */ + /* Deallocate the two or three or four subwindows. */ if (topwin != NULL) delwin(topwin); delwin(edit); delwin(bottomwin); + if (scrollbarwin) + delwin(scrollbarwin); #endif /* Switch the cursor on, exit from curses, and restore terminal settings. */ restore_terminal(); @@ -351,6 +353,8 @@ void window_init(void) delwin(topwin); delwin(edit); delwin(bottomwin); + if (scrollbarwin) + delwin(scrollbarwin); } /* If the terminal is very flat, don't set up a title bar. */ @@ -361,6 +365,7 @@ void window_init(void) * edit window and status-bar window will cover each other. */ edit = newwin(1, COLS, 0, 0); bottomwin = newwin(1, COLS, LINES - 1, 0); + scrollbarwin = NULL; } else { int toprows = (!ISSET(EMPTY_LINE) ? 1 : (LINES < 6) ? 1 : 2); int bottomrows = (ISSET(NO_HELP) ? 1 : (LINES < 5) ? 1 : 3); @@ -369,8 +374,14 @@ void window_init(void) /* Set up the normal three subwindows. */ topwin = newwin(toprows, COLS, 0, 0); - edit = newwin(editwinrows, COLS, toprows, 0); + edit = newwin(editwinrows, COLS - (ISSET(SHOW_SCROLLBAR) ? 1 : 0), + toprows, 0); bottomwin = newwin(bottomrows, COLS, toprows + editwinrows, 0); + /* If the terminal is too thin, don't set up a scrollbar. */ + if (ISSET(SHOW_SCROLLBAR) && COLS >= 3) + scrollbarwin = newwin(editwinrows, 1, toprows, COLS - 1); + else + scrollbarwin = NULL; } /* In case the terminal shrunk, make sure the status line is clear. */ @@ -1041,7 +1052,7 @@ void regenerate_screen(void) COLS = win.ws_col; LINES = win.ws_row; #endif - editwincols = COLS - margin; + editwincols = COLS - margin - (ISSET(SHOW_SCROLLBAR) ? 1 : 0); /* Ensure that firstcolumn is the starting column of its chunk. */ ensure_firstcolumn_is_aligned(); @@ -1245,7 +1256,7 @@ void confirm_margin(void) if (needed_margin != margin) { margin = needed_margin; - editwincols = COLS - margin; + editwincols = COLS - margin - (ISSET(SHOW_SCROLLBAR) ? 1 : 0); #ifndef NANO_TINY /* Ensure that firstcolumn is the starting column of its chunk. */ @@ -2273,7 +2284,7 @@ int main(int argc, char **argv) window_init(); curs_set(0); - editwincols = COLS; + editwincols = COLS - (ISSET(SHOW_SCROLLBAR) ? 1 : 0); /* Set up the signal handlers. */ signal_init(); diff --git a/src/nano.h b/src/nano.h index 75f6f3c7..4bebc506 100644 --- a/src/nano.h +++ b/src/nano.h @@ -540,7 +540,8 @@ enum LET_THEM_ZAP, BREAK_LONG_LINES, JUMPY_SCROLLING, - EMPTY_LINE + EMPTY_LINE, + SHOW_SCROLLBAR }; /* Flags for the menus in which a given function should be present. */ diff --git a/src/proto.h b/src/proto.h index 9ee22d6d..1f565c12 100644 --- a/src/proto.h +++ b/src/proto.h @@ -90,6 +90,7 @@ extern size_t wrap_at; extern WINDOW *topwin; extern WINDOW *edit; extern WINDOW *bottomwin; +extern WINDOW *scrollbarwin; extern int editwinrows; extern int editwincols; extern int margin; diff --git a/src/rcfile.c b/src/rcfile.c index 0e090f1c..5c52e78c 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -86,6 +86,7 @@ static const rcoption rcopts[] = { {"rawsequences", RAW_SEQUENCES}, {"rebinddelete", REBIND_DELETE}, {"regexp", USE_REGEXP}, + {"scrollbar", SHOW_SCROLLBAR}, #ifdef ENABLE_SPELLER {"speller", 0}, #endif diff --git a/src/winio.c b/src/winio.c index eb89e16d..5578a856 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2367,6 +2367,33 @@ void place_the_cursor(void) openfile->current_y = row; } +/* Draws a scroll bar on the left side of the screen. */ +void draw_scrollbar(void) +{ + int style; + int last_lineno = openfile->filebot->lineno; + int inf = (openfile->edittop->lineno * editwinrows) / (last_lineno + 1); + int sup = inf + (editwinrows * editwinrows) / (last_lineno + 1); + + /* Consider that we'll have no scrollbar if window is too thin. */ + if (scrollbarwin == NULL) + return; + + if (editwinrows >= last_lineno) { + inf = 0; + sup = last_lineno - 1; + } + + for (int current_lineno = 0; current_lineno < editwinrows; current_lineno++) { + style = (current_lineno >= inf && current_lineno <= sup) ? + A_REVERSE : A_REVERSE|A_DIM; + wattron(scrollbarwin, style); + mvwaddch(scrollbarwin, current_lineno, 0, ' '); + wattroff(scrollbarwin, style); + } + wrefresh(scrollbarwin); +} + /* Draw the given text on the given row of the edit window. line is the * line to be drawn, and converted is the actual string to be written with * tabs and control characters replaced by strings of regular characters. @@ -2780,7 +2807,7 @@ int update_line(linestruct *line, size_t index) } if (has_more) { wattron(edit, hilite_attribute); - mvwaddch(edit, row, COLS - 1, '>'); + mvwaddch(edit, row, COLS - 1 - (ISSET(SHOW_SCROLLBAR) ? 1 : 0), '>'); wattroff(edit, hilite_attribute); } @@ -3010,6 +3037,8 @@ void edit_scroll(bool direction) openfile->current_x : 0); line = line->next; } + + draw_scrollbar(); } #ifndef NANO_TINY @@ -3280,6 +3309,7 @@ void edit_refresh(void) while (row < editwinrows) blank_row(edit, row++); + draw_scrollbar(); place_the_cursor(); wnoutrefresh(edit); @@ -3426,7 +3456,8 @@ void spotlight(size_t from_col, size_t to_col) wattron(edit, interface_color_pair[SELECTED_TEXT]); waddnstr(edit, word, actual_x(word, to_col)); if (overshoots) - mvwaddch(edit, openfile->current_y, COLS - 1, '>'); + mvwaddch(edit, openfile->current_y, + COLS - 1 - (ISSET(SHOW_SCROLLBAR) ? 1 : 0), '>'); wattroff(edit, interface_color_pair[SELECTED_TEXT]); free(word);