/* Move to the beginning of the current line. If the SMART_HOME flag is * set, move to the first non-whitespace character of the current line * if we aren't already there, or to the beginning of the current line * if we are. */ void do_home(void) { size_t pww_save = openfile->placewewant; #ifndef NANO_TINY if (ISSET(SMART_HOME)) { size_t current_x_save = openfile->current_x; openfile->current_x = indent_length(openfile->current->data); if (openfile->current_x == current_x_save || openfile->current->data[openfile->current_x] == '\0') openfile->current_x = 0; openfile->placewewant = xplustabs(); } else { #endif openfile->current_x = 0; openfile->placewewant = 0; #ifndef NANO_TINY } #endif if (need_screen_update(pww_save)) update_line(openfile->current, openfile->current_x); }
/* Move to the end of the current line. */ void do_end(void) { size_t pww_save = openfile->placewewant; openfile->current_x = strlen(openfile->current->data); openfile->placewewant = xplustabs(); if (need_screen_update(pww_save)) update_line(openfile->current, openfile->current_x); }
/* If scroll_only is FALSE, move up one line. If scroll_only is TRUE, * scroll up one line without scrolling the cursor. */ void do_up( #ifndef NANO_TINY bool scroll_only #else void #endif ) { /* If we're at the top of the file, or if scroll_only is TRUE and * the top of the file is onscreen, get out. */ if (openfile->current == openfile->fileage #ifndef NANO_TINY || (scroll_only && openfile->edittop == openfile->fileage) #endif ) return; assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno); /* Move the current line of the edit window up. */ openfile->current = openfile->current->prev; openfile->current_x = actual_x(openfile->current->data, openfile->placewewant); /* If scroll_only is FALSE and if we're on the first line of the * edit window, scroll the edit window up one line if we're in * smooth scrolling mode, or up half a page if we're not. If * scroll_only is TRUE, scroll the edit window up one line * unconditionally. */ if (openfile->current_y == 0 #ifndef NANO_TINY || (ISSET(SOFTWRAP) && openfile->edittop->lineno == openfile->current->next->lineno) || scroll_only #endif ) edit_scroll(UPWARD, #ifndef NANO_TINY (ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 : #endif editwinrows / 2 + 1); /* If we're below the first line of the edit window, update 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 unconditionally. */ if (openfile->current_y > 0) { if (need_screen_update(0)) update_line(openfile->current->next, 0); update_line(openfile->current, openfile->current_x); } }
/* Move left one character. */ void do_left(void) { size_t pww_save = openfile->placewewant; if (openfile->current_x > 0) openfile->current_x = move_mbleft(openfile->current->data, openfile->current_x); else if (openfile->current != openfile->fileage) { do_up_void(); openfile->current_x = strlen(openfile->current->data); } openfile->placewewant = xplustabs(); if (need_screen_update(pww_save)) update_line(openfile->current, openfile->current_x); }
/* Move right one character. */ void do_right(void) { size_t pww_save = openfile->placewewant; assert(openfile->current_x <= strlen(openfile->current->data)); if (openfile->current->data[openfile->current_x] != '\0') openfile->current_x = move_mbright(openfile->current->data, openfile->current_x); else if (openfile->current != openfile->filebot) { do_down_void(); openfile->current_x = 0; } openfile->placewewant = xplustabs(); if (need_screen_update(pww_save)) update_line(openfile->current, openfile->current_x); }
/* If scroll_only is FALSE, move down one line. If scroll_only is TRUE, * scroll down one line without scrolling the cursor. */ void do_down( #ifndef NANO_TINY bool scroll_only #else void #endif ) { #ifndef NANO_TINY int amount = 0, enough; filestruct *topline; #endif /* If we're at the bottom of the file, get out. */ if (openfile->current == openfile->filebot || !openfile->current->next) return; assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno); /* Move the current line of the edit window down. */ openfile->current = openfile->current->next; openfile->current_x = actual_x(openfile->current->data, openfile->placewewant); #ifndef NANO_TINY if (ISSET(SOFTWRAP)) { /* Compute the amount to scroll. */ amount = (strlenpt(openfile->current->data) / COLS + openfile->current_y + 2 + strlenpt(openfile->current->prev->data) / COLS - editwinrows); topline = openfile->edittop; /* Reduce the amount when there are overlong lines at the top. */ for (enough = 1; enough < amount; enough++) { if (amount <= strlenpt(topline->data) / COLS) { amount = enough; break; } amount -= strlenpt(topline->data) / COLS; topline = topline->next; } } #endif /* If scroll_only is FALSE and if we're on the last line of the * edit window, scroll the edit window down one line if we're in * smooth scrolling mode, or down half a page if we're not. If * scroll_only is TRUE, scroll the edit window down one line * unconditionally. */ if (openfile->current_y == editwinrows - 1 #ifndef NANO_TINY || amount > 0 || scroll_only #endif ) { #ifndef NANO_TINY if (amount < 1 || scroll_only) amount = 1; #endif edit_scroll(DOWNWARD, #ifndef NANO_TINY (ISSET(SMOOTH_SCROLL) || scroll_only) ? amount : #endif editwinrows / 2 + 1); edit_refresh_needed = TRUE; } /* If we're above the last line of the edit window, update 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 unconditionally. */ if (openfile->current_y < editwinrows - 1 #ifndef NANO_TINY || ISSET(SOFTWRAP) #endif ) { if (need_screen_update(0)) update_line(openfile->current->prev, 0); update_line(openfile->current, openfile->current_x); } }
/* Update any lines between old_current and current that need to be * updated. Use this if we've moved without changing any text. */ void edit_redraw(filestruct *old_current, size_t pww_save) { filestruct *foo = NULL; bool do_redraw = need_screen_update(0) || need_screen_update(pww_save); /* If either old_current or current is offscreen, scroll the edit * window until it's onscreen and get out. */ if (old_current->lineno < openfile->edittop->lineno || old_current->lineno >= openfile->edittop->lineno + maxrows || openfile->current->lineno < openfile->edittop->lineno || openfile->current->lineno >= openfile->edittop->lineno + maxrows) { DEBUG_LOG("edit_redraw(): line " << openfile->current->lineno << " was offscreen, oldcurrent = " << old_current->lineno << " edittop = " << openfile->edittop->lineno); /* If the mark is on, update all the lines between old_current * and either the old first line or old last line (depending on * whether we've scrolled up or down) of the edit window. */ if (openfile->mark_set) { ssize_t old_lineno; filestruct *old_edittop = openfile->edittop; if (old_edittop->lineno < openfile->edittop->lineno) { old_lineno = old_edittop->lineno; } else old_lineno = (old_edittop->lineno + maxrows <= openfile->filebot->lineno) ? old_edittop->lineno + editwinrows : openfile->filebot->lineno; foo = old_current; while (foo->lineno != old_lineno) { update_line(foo, 0); foo = (foo->lineno > old_lineno) ? foo->prev : foo->next; } } /* Make sure the current line is on the screen. */ edit_update(CENTER); /* Update old_current if we're not on the same page as * before. */ if (do_redraw) { update_line(old_current, 0); } /* If the mark is on, update all the lines between the old first * line or old last line of the edit window (depending on * whether we've scrolled up or down) and current. */ if (openfile->mark_set) { while (foo->lineno != openfile->current->lineno) { update_line(foo, 0); foo = (foo->lineno > openfile->current->lineno) ? foo->prev : foo->next; } } return; } /* Update old_current and current if we're not on the same page as * before. If the mark is on, update all the lines between * old_current and current too. */ foo = old_current; while (foo != openfile->current) { if (do_redraw) { update_line(foo, 0); } if (!openfile->mark_set) { break; } foo = (foo->lineno > openfile->current->lineno) ? foo->prev : foo->next; } if (do_redraw) { update_line(openfile->current, openfile->current_x); } }
/* 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 UPWARD or * DOWNWARD, and nlines is the number of lines to scroll. We change * edittop, and assume that current and current_x are up to date. We * also assume that scrollok(edit) is false. */ void edit_scroll(ScrollDir direction, ssize_t nlines) { filestruct *foo; ssize_t i; bool do_redraw = need_screen_update(0); /* Don't bother scrolling less than one line. */ if (nlines < 1) { return; } /* Part 1: nlines is the number of lines we're going to scroll the * text of the edit window. */ /* Move the top line of the edit window up or down (depending on the * value of direction) nlines lines, or as many lines as we can if * there are fewer than nlines lines available. */ for (i = nlines; i > 0; i--) { if (direction == UPWARD) { if (openfile->edittop == openfile->fileage) { break; } openfile->edittop = openfile->edittop->prev; } else { if (openfile->edittop == openfile->filebot) { break; } openfile->edittop = openfile->edittop->next; } /* Don't over-scroll on long lines */ if (ISSET(SOFTWRAP) && (direction == UPWARD)) { ssize_t len = strlenpt(openfile->edittop->data) / COLS; i -= len; if (len > 0) { do_redraw = true; } } } /* Limit nlines to the number of lines we could scroll. */ nlines -= i; /* Don't bother scrolling zero lines or more than the number of * lines in the edit window minus one; in both cases, get out, and * call edit_refresh() beforehand if we need to. */ if (nlines == 0 || do_redraw || nlines >= editwinrows) { if (do_redraw || nlines >= editwinrows) { edit_refresh_needed = true; } return; } /* Scroll the text of the edit window up or down nlines lines, * depending on the value of direction. */ scrollok(edit, true); wscrl(edit, (direction == UPWARD) ? -nlines : nlines); scrollok(edit, false); /* Part 2: nlines is the number of lines in the scrolled region of * the edit window that we need to draw. */ /* If the top or bottom line of the file is now visible in the edit * window, we need to draw the entire edit window. */ if ((direction == UPWARD && openfile->edittop == openfile->fileage) || (direction == DOWNWARD && openfile->edittop->lineno + editwinrows - 1 >= openfile->filebot->lineno)) { nlines = editwinrows; } /* If the scrolled region contains only one line, and the line * before it is visible in the edit window, we need to draw it too. * If the scrolled region contains more than one line, and the lines * before and after the scrolled region are visible in the edit * window, we need to draw them too. */ nlines += (nlines == 1) ? 1 : 2; if (nlines > editwinrows) { nlines = editwinrows; } /* If we scrolled up, we're on the line before the scrolled region. */ foo = openfile->edittop; /* If we scrolled down, move down to the line before the scrolled region. */ if (direction == DOWNWARD) { for (i = editwinrows - nlines; i > 0 && foo != NULL; i--) { foo = foo->next; } } /* Draw new lines on any blank lines before or inside the scrolled * region. If we scrolled down and we're on the top line, or if we * scrolled up and we're on the bottom line, the line won't be * blank, so we don't need to draw it unless the mark is on or we're * not on the first page. */ for (i = nlines; i > 0 && foo != NULL; i--) { if ((i == nlines && direction == DOWNWARD) || (i == 1 && direction == UPWARD)) { if (do_redraw) update_line(foo, (foo == openfile->current) ? openfile->current_x : 0); } else { update_line(foo, (foo == openfile->current) ? openfile->current_x : 0); } foo = foo->next; } compute_maxrows(); }