]> git.wh0rd.org Git - nano.git/commitdiff
overhaul the routines for movement and related things to eliminate
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 28 May 2004 20:44:09 +0000 (20:44 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 28 May 2004 20:44:09 +0000 (20:44 +0000)
unneeded screen redraws

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1774 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
src/global.c
src/move.c
src/nano.c
src/nano.h
src/proto.h
src/search.c
src/winio.c

index 5273868e4b5b31a84868e939ea38bf472d94ec10..83795fd8a558d48bacafa72277676e2a1b3d833c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -76,6 +76,21 @@ CVS code -
          to do_verbatim_input(), handle_sigwinch(), get_kbinput(),
          get_ascii_kbinput(), get_escape_seq_kbinput(), and
          get_verbatim_kbinput(). (DLR)
+       - Overhaul all the movement functions in order to avoid
+         redundant screen redraws (and regexec()s when color support is
+         available) whenever possible during ordinary cursor movement
+         when the text doesn't change.  Do the same for moving in
+         do_char(), do_delete(), do_next_word(), do_prev_word(),
+         do_search(), do_research(), and do_replace_loop.  Changes to
+         do_first_line(), do_last_line(), do_home(), do_end(),
+         do_page_up(), do_page_down(), do_up(), do_down(), do_left(),
+         do_right(), do_delete(), do_backspace(), do_search(),
+         do_research(), do_replace_loop(), do_find_bracket(), and
+         edit_refresh().  New functions do_left_void(),
+         do_right_void(), need_horizontal_update(),
+         need_vertical_update(), edit_scroll(), and edit_redraw().
+         Also rename the int refresh in do_delete() and do_backspace()
+         to do_refresh so as not to conflict with refresh(). (DLR)
 - files.c:
   add_open_file()
        - Rearrange the NANO_SMALL #ifdef so that the code to set the
@@ -196,6 +211,7 @@ CVS code -
        - Since REGEXP_COMPILED is only used in search.c, convert it
          from a flag to a static int there. (DLR)
        - Add justbegend enum, used in do_para_search(). (DLR)
+       - Add updown enum, used in edit_scroll(). (DLR)
 - proto.h:
        - Remove unused xpt() and add_marked_sameline() prototypes.
          (DLR)
index 445b87d8f2aba6e28865226f38b7a5022ac8808c..fbe3e823c19b4a61bcb17592c3db49ec69cad152 100644 (file)
@@ -557,11 +557,11 @@ void shortcut_init(int unjustify)
 
     sc_init_one(&main_list, NANO_FORWARD_KEY, _("Forward"),
                IFHELP(nano_forward_msg, NANO_NO_KEY), NANO_NO_KEY,
-               NANO_NO_KEY, VIEW, do_right);
+               NANO_NO_KEY, VIEW, do_right_void);
 
     sc_init_one(&main_list, NANO_BACK_KEY, _("Back"),
                IFHELP(nano_back_msg, NANO_NO_KEY), NANO_NO_KEY,
-               NANO_NO_KEY, VIEW, do_left);
+               NANO_NO_KEY, VIEW, do_left_void);
 
     sc_init_one(&main_list, NANO_HOME_KEY, _("Home"),
                IFHELP(nano_home_msg, NANO_NO_KEY), NANO_NO_KEY,
index ac1e7a7aad962b0c7c28a38e61b8ecad15008343..77365b1896c43dee8a7aeb8bba789fae366af9ed 100644 (file)
 
 int do_first_line(void)
 {
+    int old_pww = placewewant;
     current = fileage;
     placewewant = 0;
     current_x = 0;
-    edit_update(current, TOP);
+    if (edittop != fileage || need_vertical_update(old_pww))
+       edit_update(current, TOP);
     return 1;
 }
 
 int do_last_line(void)
 {
+    int old_pww = placewewant;
     current = filebot;
     placewewant = 0;
     current_x = 0;
-    edit_update(current, CENTER);
+    if (edittop->lineno + (editwinrows / 2) != filebot->lineno ||
+       need_vertical_update(old_pww))
+       edit_update(current, CENTER);
     return 1;
 }
 
 int do_home(void)
 {
+    int old_pww = placewewant;
 #ifndef NANO_SMALL
     if (ISSET(SMART_HOME)) {
        int old_current_x = current_x;
@@ -68,58 +74,66 @@ int do_home(void)
     }
 #endif
     check_statblank();
-    update_line(current, current_x);
+    if (need_horizontal_update(old_pww))
+       update_line(current, current_x);
     return 1;
 }
 
 int do_end(void)
 {
+    int old_pww = placewewant;
     current_x = strlen(current->data);
     placewewant = xplustabs();
     check_statblank();
-    update_line(current, current_x);
+    if (need_horizontal_update(old_pww))
+       update_line(current, current_x);
     return 1;
 }
 
 int do_page_up(void)
 {
-    int i;
-
+    int new_pww = placewewant;
+    const filestruct *old_current = current;
 #ifndef DISABLE_WRAPPING
     wrap_reset();
 #endif
 
-    /* If edittop is the first line of the file, move current up there
+    /* If the first line of the file is onscreen, move current up there
      * and put the cursor at the beginning of the line. */
     if (edittop == fileage) {
        current = fileage;
-       placewewant = 0;
+       new_pww = 0;
     } else {
-       /* Move the top line of the edit window up a page. */
-       for (i = 0; i < editwinrows - 2 && edittop->prev != NULL; i++)
-           edittop = edittop->prev;
+       edit_scroll(UP, editwinrows - 2);
+
 #ifndef NANO_SMALL
-       /* If we're in smooth scrolling mode and there was at least one
+       /* If we're in smooth scrolling mode and there's at least one
         * page of text left, move the current line of the edit window
         * up a page. */
-       if (ISSET(SMOOTHSCROLL) && current->lineno > editwinrows - 2)
+       if (ISSET(SMOOTHSCROLL) && current->lineno > editwinrows - 2) {
+           int i;
            for (i = 0; i < editwinrows - 2; i++)
                current = current->prev;
-       /* If we're not in smooth scrolling mode and there was at least
+       }
+       /* If we're not in smooth scrolling mode or there isn't at least
         * one page of text left, put the cursor at the beginning of the
         * top line of the edit window, as Pico does. */
        else {
 #endif
            current = edittop;
-           placewewant = 0;
+           new_pww = 0;
 #ifndef NANO_SMALL
        }
 #endif
     }
+
     /* Get the equivalent x-coordinate of the new line. */
-    current_x = actual_x(current->data, placewewant);
+    current_x = actual_x(current->data, new_pww);
 
-    edit_refresh();
+    /* Update all the lines that need to be updated, and then set
+     * placewewant, so that the update will work properly. */
+    edit_redraw(old_current);
+    placewewant = new_pww;
 
     check_statblank();
     return 1;
@@ -127,8 +141,8 @@ int do_page_up(void)
 
 int do_page_down(void)
 {
-    int i;
-
+    int new_pww = placewewant;
+    const filestruct *old_current = current;
 #ifndef DISABLE_WRAPPING
     wrap_reset();
 #endif
@@ -137,33 +151,39 @@ int do_page_down(void)
      * there and put the cursor at the beginning of the line. */
     if (edittop->lineno + editwinrows > filebot->lineno) {
        current = filebot;
-       placewewant = 0;
+       new_pww = 0;
     } else {
-       /* Move the top line of the edit window down a page. */
-       for (i = 0; i < editwinrows - 2; i++)
-           edittop = edittop->next;
+       edit_scroll(DOWN, editwinrows - 2);
+
 #ifndef NANO_SMALL
-       /* If we're in smooth scrolling mode and there was at least one
+       /* If we're in smooth scrolling mode and there's at least one
         * page of text left, move the current line of the edit window
         * down a page. */
-       if (ISSET(SMOOTHSCROLL) && current->lineno + editwinrows - 2 <= filebot->lineno)
+       if (ISSET(SMOOTHSCROLL) && current->lineno + editwinrows - 2 <=
+               filebot->lineno) {
+           int i;
            for (i = 0; i < editwinrows - 2; i++)
                current = current->next;
-       /* If we're not in smooth scrolling mode and there was at least
+       }
+       /* If we're not in smooth scrolling mode or there isn't at least
         * one page of text left, put the cursor at the beginning of the
         * top line of the edit window, as Pico does. */
        else {
 #endif
            current = edittop;
-           placewewant = 0;
+           new_pww = 0;
 #ifndef NANO_SMALL
        }
 #endif
     }
+
     /* Get the equivalent x-coordinate of the new line. */
-    current_x = actual_x(current->data, placewewant);
+    current_x = actual_x(current->data, new_pww);
 
-    edit_refresh();
+    /* Update all the lines that need to be updated, and then set
+     * placewewant, so that the update will work properly. */
+    edit_redraw(old_current);
+    placewewant = new_pww;
 
     check_statblank();
     return 1;
@@ -182,18 +202,25 @@ int do_up(void)
     assert(current_y == current->lineno - edittop->lineno);
     current = current->prev;
     current_x = actual_x(current->data, placewewant);
-    if (current_y > 0) {
-       update_line(current->next, 0);
-           /* It was necessary to change current first, so that the
-            * mark display will change! */
-       update_line(current, current_x);
-    } else
+
+    /* If we're on the first row of the edit window, scroll up one line
+     * if we're in smooth scrolling mode, or up half a page if we're
+     * not. */
+    if (current_y == 0)
+       edit_scroll(UP,
 #ifndef NANO_SMALL
-    if (ISSET(SMOOTHSCROLL))
-       edit_update(current, TOP);
-    else
+               ISSET(SMOOTHSCROLL) ? 1 :
 #endif
-       edit_update(current, CENTER);
+               editwinrows / 2);
+
+    /* Update the lines left alone by edit_scroll(): the line we were on
+     * before and the line we're on now.  The former needs to be redrawn
+     * if we're not on the first page, and the latter needs to be
+     * drawn. */
+    if (need_vertical_update(0))
+       update_line(current->next, 0);
+    update_line(current, current_x);
+
     return 1;
 }
 
@@ -213,25 +240,30 @@ int do_down(void)
     current = current->next;
     current_x = actual_x(current->data, placewewant);
 
-    /* Note that current_y is zero-based.  This test checks for the
-     * cursor's being not on the last row of the edit window. */
-    if (current_y != editwinrows - 1) {
-       update_line(current->prev, 0);
-       update_line(current, current_x);
-    } else
+    /* If we're on the last row of the edit window, scroll down one line
+     * if we're in smooth scrolling mode, or down half a page if we're
+     * not. */
+    if (current_y == editwinrows - 1)
+       edit_scroll(DOWN,
 #ifndef NANO_SMALL
-    if (ISSET(SMOOTHSCROLL))
-       /* In this case current_y does not change.  The cursor remains
-        * at the bottom of the edit window. */
-       edit_update(edittop->next, TOP);
-    else
+               ISSET(SMOOTHSCROLL) ? 1 :
 #endif
-       edit_update(current, CENTER);
+               editwinrows / 2);
+
+    /* Update the lines left alone by edit_scroll(): the line we were on
+     * before and the line we're on now.  The former needs to be redrawn
+     * if we're not on the first page, and the latter needs to be
+     * drawn. */
+    if (need_vertical_update(0))
+       update_line(current->prev, 0);
+    update_line(current, current_x);
+
     return 1;
 }
 
-int do_left(void)
+int do_left(int allow_update)
 {
+    int old_pww = placewewant;
     if (current_x > 0)
        current_x--;
     else if (current != fileage) {
@@ -240,12 +272,19 @@ int do_left(void)
     }
     placewewant = xplustabs();
     check_statblank();
-    update_line(current, current_x);
+    if (allow_update && need_horizontal_update(old_pww))
+       update_line(current, current_x);
     return 1;
 }
 
-int do_right(void)
+int do_left_void(void)
+{
+    return do_left(TRUE);
+}
+
+int do_right(int allow_update)
 {
+    int old_pww = placewewant;
     assert(current_x <= strlen(current->data));
 
     if (current->data[current_x] != '\0')
@@ -256,6 +295,12 @@ int do_right(void)
     }
     placewewant = xplustabs();
     check_statblank();
-    update_line(current, current_x);
+    if (allow_update && need_horizontal_update(old_pww))
+       update_line(current, current_x);
     return 1;
 }
+
+int do_right_void(void)
+{
+    return do_right(TRUE);
+}
index 6e084bd93af92875fd59217018a0580a1379ea83..1362890e69a5a0f725d7a264dbcf9c733df6b0b2 100644 (file)
@@ -928,8 +928,8 @@ void do_char(char ch)
 {
     size_t current_len = strlen(current->data);
 #if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
-    int refresh = FALSE;
-       /* Do we have to run edit_refresh(), or can we get away with
+    int do_refresh = FALSE;
+       /* Do we have to call edit_refresh(), or can we get away with
         * update_line()? */
 #endif
 
@@ -962,22 +962,27 @@ void do_char(char ch)
        mark_beginx++;
 #endif
 
-    do_right();
+    do_right(FALSE);
 
 #ifndef DISABLE_WRAPPING
+    /* If we're wrapping text, we need to call edit_refresh(). */
     if (!ISSET(NO_WRAP) && ch != '\t')
-       refresh = do_wrap(current);
+       do_refresh = do_wrap(current);
 #endif
 
 #ifdef ENABLE_COLOR
+    /* If color syntaxes are turned on, we need to call
+     * edit_refresh(). */
     if (ISSET(COLOR_SYNTAX))
-       refresh = TRUE;
+       do_refresh = TRUE;
 #endif
 
 #if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
-    if (refresh)
+    if (do_refresh)
        edit_refresh();
+    else
 #endif
+       update_line(current, current_x);
 }
 
 int do_verbatim_input(void)
@@ -1006,7 +1011,7 @@ int do_verbatim_input(void)
 int do_backspace(void)
 {
     if (current != fileage || current_x > 0) {
-       do_left();
+       do_left(FALSE);
        do_delete();
     }
     return 1;
@@ -1014,6 +1019,10 @@ int do_backspace(void)
 
 int do_delete(void)
 {
+    int do_refresh = FALSE;
+       /* Do we have to call edit_refresh(), or can we get away with
+        * update_line()? */
+
     assert(current != NULL && current->data != NULL && current_x <=
        strlen(current->data));
 
@@ -1040,6 +1049,12 @@ int do_delete(void)
        filestruct *foo = current->next;
 
        assert(current_x == strlen(current->data));
+
+       /* If we're deleting at the end of a line, we need to call
+        * edit_refresh(). */
+       if (current->data[current_x] == '\0')
+           do_refresh = TRUE;
+
        current->data = charealloc(current->data, current_x +
                strlen(foo->data) + 1);
        strcpy(current->data + current_x, foo->data);
@@ -1062,7 +1077,19 @@ int do_delete(void)
 
     totsize--;
     set_modified();
-    edit_refresh();
+
+#ifdef ENABLE_COLOR
+    /* If color syntaxes are turned on, we need to call
+     * edit_refresh(). */
+    if (ISSET(COLOR_SYNTAX))
+       do_refresh = TRUE;
+#endif
+
+    if (do_refresh)
+       edit_refresh();
+    else
+       update_line(current, current_x);
+
     return 1;
 }
 
@@ -1136,6 +1163,7 @@ int do_enter(void)
 #ifndef NANO_SMALL
 int do_next_word(void)
 {
+    const filestruct *current_save = current;
     assert(current != NULL && current->data != NULL);
 
     /* Skip letters in this word first. */
@@ -1160,7 +1188,7 @@ int do_next_word(void)
 
     /* Refresh the screen.  If current has run off the bottom, this
      * call puts it at the center line. */
-    edit_refresh();
+    edit_redraw(current_save);
 
     return 0;
 }
@@ -1168,6 +1196,7 @@ int do_next_word(void)
 /* The same thing for backwards. */
 int do_prev_word(void)
 {
+    const filestruct *current_save = current;
     assert(current != NULL && current->data != NULL);
 
     /* Skip letters in this word first. */
@@ -1197,7 +1226,7 @@ int do_prev_word(void)
 
     /* Refresh the screen.  If current has run off the top, this call
      * puts it at the center line. */
-    edit_refresh();
+    edit_redraw(current_save);
 
     return 0;
 }
@@ -1429,8 +1458,8 @@ int do_int_spell_fix(const char *word)
 {
     char *save_search;
     char *save_replace;
-    filestruct *current_save = current;
     size_t current_x_save = current_x;
+    filestruct *current_save = current;
     filestruct *edittop_save = edittop;
        /* Save where we are. */
     int i = 0;
@@ -2131,19 +2160,16 @@ int break_line(const char *line, int goal, int force)
 int do_para_search(justbegend search_type, size_t *quote, size_t *par,
        size_t *indent, int do_refresh)
 {
+    const filestruct *current_save = current;
     size_t quote_len;
        /* Length of the initial quotation of the paragraph we
         * search. */
     size_t par_len;
        /* Number of lines in that paragraph. */
-
-    /* We save this global variable to see if we're where we started
-     * when searching for the beginning of the paragraph. */
-    filestruct *current_save = current;
-
-    size_t indent_len; /* Generic indentation length. */
-    filestruct *line;  /* Generic line of text. */
-
+    size_t indent_len;
+       /* Generic indentation length. */
+    filestruct *line;
+       /* Generic line of text. */
     static int do_restart = 1;
        /* Whether we're restarting when searching for the beginning
         * line of the paragraph. */
@@ -2209,7 +2235,7 @@ int do_para_search(justbegend search_type, size_t *quote, size_t *par,
            if (current->prev == NULL) {
                placewewant = 0;
                if (do_refresh)
-                   edit_refresh();
+                   edit_redraw(current_save);
 #ifdef HAVE_REGEX_H
                if (!do_restart)
                    regfree(&qreg);
@@ -2230,7 +2256,7 @@ int do_para_search(justbegend search_type, size_t *quote, size_t *par,
            if (current->next == NULL) {
                placewewant = 0;
                if (do_refresh)
-                   edit_refresh();
+                   edit_redraw(current_save);
 #ifdef HAVE_REGEX_H
                regfree(&qreg);
 #endif
@@ -2321,7 +2347,7 @@ int do_para_search(justbegend search_type, size_t *quote, size_t *par,
 
     /* Refresh the screen if needed. */
     if (do_refresh)
-       edit_refresh();
+       edit_redraw(current_save);
 
     /* Save the values of quote_len, par_len, and indent_len if
      * needed. */
@@ -2368,9 +2394,9 @@ int do_justify(int full_justify)
      * unjustifies.  Note we don't need to save totlines. */
     int current_x_save = current_x;
     int current_y_save = current_y;
-    filestruct *current_save = current;
     int flags_save = flags;
     long totsize_save = totsize;
+    filestruct *current_save = current;
     filestruct *edittop_save = edittop;
 #ifndef NANO_SMALL
     filestruct *mark_beginbuf_save = mark_beginbuf;
index 096bdb959928ef30c90e4b18b5734b52a7862fe3..f727ab7176d407c28df66fbcea02547cc6ec36b3 100644 (file)
@@ -463,6 +463,10 @@ typedef enum {
     JUSTIFY, BEGIN, END
 } justbegend;
 
+typedef enum {
+    UP, DOWN
+} updown;
+
 typedef enum {
     TOP, CENTER, NONE
 } topmidnone;
index 1c7b8fe474b0eb293357af11bcacc4e385e0cf82..f6cf80af514387b7133db68b524a5cbe17fff1f0 100644 (file)
@@ -240,8 +240,10 @@ int do_page_up(void);
 int do_page_down(void);
 int do_up(void);
 int do_down(void);
-int do_left(void);
-int do_right(void);
+int do_left(int allow_update);
+int do_left_void(void);
+int do_right(int allow_update);
+int do_right_void(void);
 
 /* Public functions in nano.c */
 void finish(void);
@@ -528,6 +530,10 @@ void reset_cursor(void);
 void edit_add(const filestruct *fileptr, const char *converted, int
        yval, size_t start);
 void update_line(const filestruct *fileptr, size_t index);
+int need_horizontal_update(int old_placewewant);
+int need_vertical_update(int old_placewewant);
+void edit_scroll(updown direction, int nlines);
+void edit_redraw(const filestruct *old_current);
 void edit_refresh(void);
 void edit_update(filestruct *fileptr, topmidnone location);
 int statusq(int allowtabs, const shortcut *s, const char *def,
index f0d187f40425e8bc20305ae820781697b9047abd..15341fd7df7b81918e1f155a6bf8eee0499dd17b 100644 (file)
@@ -354,9 +354,8 @@ int findnextstr(int can_display_wrap, int wholeword, const filestruct
 /* Search for a string. */
 int do_search(void)
 {
-    int i;
+    int i, fileptr_x = current_x, didfind;
     filestruct *fileptr = current;
-    int fileptr_x = current_x, didfind;
 
 #ifndef DISABLE_WRAPPING
     wrap_reset();
@@ -391,8 +390,6 @@ int do_search(void)
 
     search_last_line = FALSE;
     didfind = findnextstr(TRUE, FALSE, current, current_x, answer, FALSE);
-    edit_refresh();
-    placewewant = xplustabs();
 
     /* Check to see if there's only one occurrence of the string and
      * we're on it now. */
@@ -415,6 +412,8 @@ int do_search(void)
 #endif
     }
 
+    edit_redraw(fileptr);
+    placewewant = xplustabs();
     search_abort();
 
     return 1;
@@ -424,8 +423,8 @@ int do_search(void)
 /* Search for the next string without prompting. */
 int do_research(void)
 {
-    filestruct *fileptr = current;
     int fileptr_x = current_x, didfind;
+    filestruct *fileptr = current;
 
 #ifndef DISABLE_WRAPPING
     wrap_reset();
@@ -442,8 +441,6 @@ int do_research(void)
 
        search_last_line = FALSE;
        didfind = findnextstr(TRUE, FALSE, current, current_x, last_search, FALSE);
-       edit_refresh();
-       placewewant = xplustabs();
 
        /* Check to see if there's only one occurrence of the string and
         * we're on it now. */
@@ -468,6 +465,8 @@ int do_research(void)
     } else
         statusbar(_("No current search pattern"));
 
+    edit_redraw(fileptr);
+    placewewant = xplustabs();
     search_abort();
 
     return 1;
@@ -582,8 +581,8 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
        size_t *real_current_x, int wholewords)
 {
     int replaceall = 0, numreplaced = -1;
-    const filestruct *current_save = current;
     size_t current_x_save = current_x;
+    const filestruct *current_save = current;
 #ifdef HAVE_REGEX_H
     /* The starting-line match and bol/eol regex flags. */
     int begin_line = FALSE, bol_or_eol = FALSE;
@@ -628,7 +627,8 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
        }
 #endif
 
-       edit_refresh();
+       if (!replaceall)
+           edit_redraw(current_save);
 
 #ifdef HAVE_REGEX_H
        if (ISSET(USE_REGEXP))
@@ -709,7 +709,15 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
            free(current->data);
            current->data = copy;
 
-           edit_refresh();
+           if (!replaceall) {
+#ifdef ENABLE_COLOR
+               if (ISSET(COLOR_SYNTAX))
+                   edit_refresh();
+               else
+#endif
+                   update_line(current, current_x);
+           }
+
            set_modified();
            numreplaced++;
        }
@@ -890,7 +898,7 @@ int do_find_bracket(void)
     char ch_under_cursor, wanted_ch;
     const char *pos, *brackets = "([{<>}])";
     char regexp_pat[] = "[  ]";
-    int flagsave, current_x_save, count = 1;
+    int current_x_save, flagsave, count = 1;
     filestruct *current_save;
 
     ch_under_cursor = current->data[current_x];
@@ -934,7 +942,7 @@ int do_find_bracket(void)
                count++;
            /* Found complementary bracket. */
            else if (--count == 0) {
-               edit_refresh();
+               edit_redraw(current_save);
                placewewant = xplustabs();
                break;
            }
index 76cbc39df6746b65e25bccf667f93aae423d1bc4..ab0d0dd12d7e8948414fd7932f9f8c6850cbae07 100644 (file)
@@ -2483,6 +2483,138 @@ void update_line(const filestruct *fileptr, size_t index)
        mvwaddch(edit, line, COLS - 1, '$');
 }
 
+/* Return a nonzero value if we need an update after moving
+ * horizontally.  We need one if the mark is on or if old_pww and
+ * placewewant are on different pages.  Assume none of the text has
+ * changed since the last update. */
+int need_horizontal_update(int old_pww)
+{
+    return
+#ifndef NANO_SMALL
+       ISSET(MARK_ISSET) ||
+#endif
+       get_page_start(old_pww) != get_page_start(placewewant);
+}
+
+/* Return a nonzero value if we need an update after moving vertically.
+ * We need one if the mark is on or if old_pww and placewewant
+ * are on different pages.  Assume none of the text has changed since
+ * the last update. */
+int need_vertical_update(int old_pww)
+{
+    return
+#ifndef NANO_SMALL
+       ISSET(MARK_ISSET) ||
+#endif
+       get_page_start(old_pww) != get_page_start(placewewant);
+}
+
+/* Scroll the edit window in the given direction and the given number
+ * of lines, and draw new lines on the blank lines left after the
+ * scrolling.  direction is the direction to scroll, either UP or DOWN,
+ * and nlines is the number of lines to scroll.  Don't redraw the old
+ * topmost or bottommost line (where we assume current is) before
+ * scrolling or draw the new topmost or bottommost line after scrolling
+ * (where we assume current will be), since we don't know where we are
+ * on the page or whether we'll stay there.  Assume none of the text has
+ * changed since the last update. */
+void edit_scroll(updown direction, int nlines)
+{
+    filestruct *foo;
+    int i, scroll_rows = 0;
+
+    /* Scrolling less than one line or more than editwinrows lines is
+     * redundant, so don't allow it. */
+    if (nlines < 1 || nlines > editwinrows)
+       return;
+
+    /* Move the top line of the edit window up or down (depending on the
+     * value of direction) nlines lines.  If there are fewer lines of
+     * text than that left, move it to the top or bottom line of the
+     * file (depending on the value of direction).  Keep track of
+     * how many lines we moved in scroll_rows. */
+    for (i = nlines; i > 0; i--) {
+       if (direction == UP) {
+           if (edittop->prev == NULL)
+               break;
+           edittop = edittop->prev;
+           scroll_rows--;
+       } else {
+           if (edittop->next == NULL)
+               break;
+           edittop = edittop->next;
+           scroll_rows++;
+       }
+    }
+
+    /* Scroll the text on the screen up or down scroll_rows lines,
+     * depending on the value of direction. */
+    scrollok(edit, TRUE);
+    wscrl(edit, scroll_rows);
+    scrollok(edit, FALSE);
+
+    foo = edittop;
+    if (direction != UP) {
+       int slines = editwinrows - nlines;
+       for (; slines > 0 && foo != NULL; slines--)
+           foo = foo->next;
+    }
+
+    /* And draw new lines on the blank top or bottom lines of the edit
+     * window, depending on the value of direction.  Don't draw the new
+     * topmost or new bottommost line. */
+    while (scroll_rows != 0 && foo != NULL) {
+       if (foo->next != NULL)
+           update_line(foo, 0);
+       if (direction == UP)
+           scroll_rows++;
+       else
+           scroll_rows--;
+       foo = foo->next;
+    }
+}
+
+/* Update any lines between old_current and current that need to be
+ * updated.  Note that we use placewewant to determine whether we need
+ * updates and current_x to update current, so if placewewant needs to
+ * be changed, it should be changed after calling this, and if current_x
+ * needs to be changed, it should be changed before calling this.
+ * Assume none of the text has changed since the last update. */
+void edit_redraw(const filestruct *old_current)
+{
+    int do_refresh = need_vertical_update(0);
+    const filestruct *foo;
+
+    /* If either old_current or current is offscreen, refresh the screen
+     * and get out. */
+    if (old_current->lineno < edittop->lineno || old_current->lineno >=
+       edittop->lineno + editwinrows || current->lineno <
+       edittop->lineno || current->lineno >= edittop->lineno +
+       editwinrows) {
+       edit_refresh();
+       return;
+    }
+
+    /* Update old_current and current if we're not on the first page.
+     * If the mark is on, update all the lines between old_current and
+     * current too. */
+    foo = old_current;
+    while (foo != current) {
+       if (do_refresh)
+           update_line(foo, 0);
+#ifndef NANO_SMALL
+       if (!ISSET(MARK_ISSET))
+#endif
+           break;
+       if (foo->lineno > current->lineno)
+           foo = foo->prev;
+       else
+           foo = foo->next;
+    }
+    if (do_refresh)
+       update_line(current, current_x);
+}
+
 /* Refresh the screen without changing the position of lines. */
 void edit_refresh(void)
 {
@@ -2510,7 +2642,7 @@ void edit_refresh(void)
 #endif
 
        while (nlines < editwinrows) {
-           update_line(foo, current_x);
+           update_line(foo, (foo == current) ? current_x : 0);
            nlines++;
            if (foo->next == NULL)
                break;