softwrap: add new functions for chunks of varying width

get_chunk_row() replaces the formula "column / editwincols".

get_chunk_leftedge() replaces "(column / editwincols) * editwincols".

get_last_chunk_row() replaces "strlenpt() / editwincols".

get_last_chunk_leftedge() replaces "(strlenpt() / editwincols) * editwincols".

This prepares us for any changes in those formulas, and for more such
functions later.
This commit is contained in:
David Lawrence Ramsey 2017-02-19 11:51:50 -06:00 committed by Benno Schulenberg
parent 35f6a1767a
commit e375995d98
8 changed files with 73 additions and 35 deletions

View File

@ -270,7 +270,7 @@ void do_uncut_text(void)
add_undo(PASTE); add_undo(PASTE);
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP))
was_leftedge = (xplustabs() / editwincols) * editwincols; was_leftedge = get_chunk_leftedge(openfile->current, xplustabs());
#endif #endif
/* Add a copy of the text in the cutbuffer to the current buffer /* Add a copy of the text in the cutbuffer to the current buffer

View File

@ -777,7 +777,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
add_undo(INSERT); add_undo(INSERT);
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP))
was_leftedge = (xplustabs() / editwincols) * editwincols; was_leftedge = get_chunk_leftedge(openfile->current, xplustabs());
#endif #endif
/* Create an empty buffer. */ /* Create an empty buffer. */

View File

@ -58,7 +58,7 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
if (realspan > openfile->placewewant) if (realspan > openfile->placewewant)
realspan = openfile->placewewant; realspan = openfile->placewewant;
*leftedge = (realspan / editwincols) * editwincols; *leftedge = get_chunk_leftedge(openfile->current, realspan);
*target_column = openfile->placewewant % editwincols; *target_column = openfile->placewewant % editwincols;
} else } else
#endif #endif
@ -352,9 +352,11 @@ void do_home(bool be_clever)
bool moved = FALSE; bool moved = FALSE;
size_t leftedge_x = 0; size_t leftedge_x = 0;
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP)) {
leftedge_x = actual_x(openfile->current->data, size_t leftedge = get_chunk_leftedge(openfile->current, was_column);
(was_column / editwincols) * editwincols);
leftedge_x = actual_x(openfile->current->data, leftedge);
}
if (ISSET(SMART_HOME) && be_clever) { if (ISSET(SMART_HOME) && be_clever) {
size_t indent_x = indent_length(openfile->current->data); size_t indent_x = indent_length(openfile->current->data);
@ -417,9 +419,9 @@ void do_end(bool be_clever)
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
size_t leftedge = get_chunk_leftedge(openfile->current, was_column);
size_t rightedge_x = actual_x(openfile->current->data, size_t rightedge_x = actual_x(openfile->current->data,
((was_column / editwincols) * editwincols) + leftedge + (editwincols - 1));
(editwincols - 1));
/* If already at the right edge of the screen, move fully to /* If already at the right edge of the screen, move fully to
* the end of the line. Otherwise, move to the right edge. */ * the end of the line. Otherwise, move to the right edge. */
@ -562,8 +564,8 @@ void do_left(void)
{ {
size_t was_column = xplustabs(); size_t was_column = xplustabs();
#ifndef NANO_TINY #ifndef NANO_TINY
size_t was_chunk = (was_column / editwincols);
filestruct *was_current = openfile->current; filestruct *was_current = openfile->current;
size_t was_chunk = get_chunk_row(was_current, was_column);
#endif #endif
if (openfile->current_x > 0) if (openfile->current_x > 0)
@ -582,7 +584,8 @@ void do_left(void)
* we're now above the first line of the edit window, so scroll up. */ * we're now above the first line of the edit window, so scroll up. */
if (ISSET(SOFTWRAP) && openfile->current_y == 0 && if (ISSET(SOFTWRAP) && openfile->current_y == 0 &&
openfile->current == was_current && openfile->current == was_current &&
openfile->placewewant / editwincols != was_chunk) { get_chunk_row(openfile->current,
openfile->placewewant) != was_chunk) {
edit_scroll(UPWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1); edit_scroll(UPWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
return; return;
} }
@ -598,8 +601,8 @@ void do_right(void)
{ {
size_t was_column = xplustabs(); size_t was_column = xplustabs();
#ifndef NANO_TINY #ifndef NANO_TINY
size_t was_chunk = (was_column / editwincols);
filestruct *was_current = openfile->current; filestruct *was_current = openfile->current;
size_t was_chunk = get_chunk_row(was_current, was_column);
#endif #endif
if (openfile->current->data[openfile->current_x] != '\0') if (openfile->current->data[openfile->current_x] != '\0')
@ -618,7 +621,8 @@ void do_right(void)
* we're now below the first line of the edit window, so scroll down. */ * we're now below the first line of the edit window, so scroll down. */
if (ISSET(SOFTWRAP) && openfile->current_y == editwinrows - 1 && if (ISSET(SOFTWRAP) && openfile->current_y == editwinrows - 1 &&
openfile->current == was_current && openfile->current == was_current &&
openfile->placewewant / editwincols != was_chunk) { get_chunk_row(openfile->current,
openfile->placewewant) != was_chunk) {
edit_scroll(DOWNWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1); edit_scroll(DOWNWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
return; return;
} }

View File

@ -1759,7 +1759,7 @@ int do_mouse(void)
/* Whether the click was on the row where the cursor is. */ /* Whether the click was on the row where the cursor is. */
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP))
leftedge = (xplustabs() / editwincols) * editwincols; leftedge = get_chunk_leftedge(openfile->current, xplustabs());
else else
#endif #endif
leftedge = get_page_start(xplustabs()); leftedge = get_page_start(xplustabs());
@ -1809,8 +1809,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
if (openfile->current_y == editwinrows - 1) if (openfile->current_y == editwinrows - 1)
original_row = xplustabs() / editwincols; original_row = get_chunk_row(openfile->current, xplustabs());
orig_rows = strlenpt(openfile->current->data) / editwincols; orig_rows = get_last_chunk_row(openfile->current);
} }
#endif #endif
@ -1875,9 +1875,9 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
* of the edit window, and we moved one screen row, we're now below * of the edit window, and we moved one screen row, we're now below
* the last line of the edit window, so we need a full refresh too. */ * the last line of the edit window, so we need a full refresh too. */
if (ISSET(SOFTWRAP) && refresh_needed == FALSE && if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
(strlenpt(openfile->current->data) / editwincols != orig_rows || (get_last_chunk_row(openfile->current) != orig_rows ||
(openfile->current_y == editwinrows - 1 && (openfile->current_y == editwinrows - 1 &&
xplustabs() / editwincols != original_row))) get_chunk_row(openfile->current, xplustabs()) != original_row)))
refresh_needed = TRUE; refresh_needed = TRUE;
#endif #endif

View File

@ -666,6 +666,10 @@ void edit_scroll(scroll_dir direction, int nrows);
size_t get_softwrap_breakpoint(const char *text, size_t leftedge, size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
bool *end_of_line); bool *end_of_line);
size_t get_chunk(filestruct *line, size_t column, size_t *leftedge); size_t get_chunk(filestruct *line, size_t column, size_t *leftedge);
size_t get_chunk_row(filestruct *line, size_t column);
size_t get_chunk_leftedge(filestruct *line, size_t column);
size_t get_last_chunk_row(filestruct *line);
size_t get_last_chunk_leftedge(filestruct *line);
void ensure_firstcolumn_is_aligned(void); void ensure_firstcolumn_is_aligned(void);
#endif #endif
void edit_redraw(filestruct *old_current); void edit_redraw(filestruct *old_current);

View File

@ -903,7 +903,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
filestruct *line = openfile->current; filestruct *line = openfile->current;
size_t leftedge = (xplustabs() / editwincols) * editwincols; size_t leftedge = get_chunk_leftedge(openfile->current, xplustabs());
rows_from_tail = (editwinrows / 2) - rows_from_tail = (editwinrows / 2) -
go_forward_chunks(editwinrows / 2, &line, &leftedge); go_forward_chunks(editwinrows / 2, &line, &leftedge);

View File

@ -112,7 +112,7 @@ void do_deletion(undo_type action)
update_undo(action); update_undo(action);
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP))
orig_rows = strlenpt(openfile->current->data) / editwincols; orig_rows = get_last_chunk_row(openfile->current);
#endif #endif
/* Move the remainder of the line "in", over the current character. */ /* Move the remainder of the line "in", over the current character. */
@ -181,7 +181,7 @@ void do_deletion(undo_type action)
/* If the number of screen rows that a softwrapped line occupies /* If the number of screen rows that a softwrapped line occupies
* has changed, we need a full refresh. */ * has changed, we need a full refresh. */
if (ISSET(SOFTWRAP) && refresh_needed == FALSE && if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
strlenpt(openfile->current->data) / editwincols != orig_rows) get_last_chunk_row(openfile->current) != orig_rows)
refresh_needed = TRUE; refresh_needed = TRUE;
#endif #endif

View File

@ -2295,16 +2295,16 @@ void place_the_cursor(bool forreal)
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
filestruct *line = openfile->edittop; filestruct *line = openfile->edittop;
row -= (openfile->firstcolumn / editwincols); row -= get_chunk_row(openfile->edittop, openfile->firstcolumn);
/* Calculate how many rows the lines from edittop to current use. */ /* Calculate how many rows the lines from edittop to current use. */
while (line != NULL && line != openfile->current) { while (line != NULL && line != openfile->current) {
row += strlenpt(line->data) / editwincols + 1; row += get_last_chunk_row(line) + 1;
line = line->next; line = line->next;
} }
/* Add the number of wraps in the current line before the cursor. */ /* Add the number of wraps in the current line before the cursor. */
row += xpt / editwincols; row += get_chunk_row(openfile->current, xpt);
col = xpt % editwincols; col = xpt % editwincols;
/* If the cursor ought to be in column zero, nudge it there. */ /* If the cursor ought to be in column zero, nudge it there. */
@ -2753,11 +2753,11 @@ int update_softwrapped_line(filestruct *fileptr)
if (fileptr == openfile->edittop) if (fileptr == openfile->edittop)
from_col = openfile->firstcolumn; from_col = openfile->firstcolumn;
else else
row -= (openfile->firstcolumn / editwincols); row -= get_chunk_row(openfile->edittop, openfile->firstcolumn);
/* Find out on which screen row the target line should be shown. */ /* Find out on which screen row the target line should be shown. */
while (line != fileptr && line != NULL) { while (line != fileptr && line != NULL) {
row += (strlenpt(line->data) / editwincols) + 1; row += get_last_chunk_row(line) + 1;
line = line->next; line = line->next;
} }
@ -2813,7 +2813,7 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge)
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
size_t current_chunk = (*leftedge) / editwincols; size_t current_chunk = get_chunk_row(*line, *leftedge);
/* Recede through the requested number of chunks. */ /* Recede through the requested number of chunks. */
for (i = nrows; i > 0; i--) { for (i = nrows; i > 0; i--) {
@ -2826,7 +2826,7 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge)
break; break;
*line = (*line)->prev; *line = (*line)->prev;
current_chunk = strlenpt((*line)->data) / editwincols; current_chunk = get_last_chunk_row(*line);
} }
/* Only change leftedge when we actually could move. */ /* Only change leftedge when we actually could move. */
@ -2854,8 +2854,8 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge)
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
size_t current_chunk = (*leftedge) / editwincols; size_t current_chunk = get_chunk_row(*line, *leftedge);
size_t last_chunk = strlenpt((*line)->data) / editwincols; size_t last_chunk = get_last_chunk_row(*line);
/* Advance through the requested number of chunks. */ /* Advance through the requested number of chunks. */
for (i = nrows; i > 0; i--) { for (i = nrows; i > 0; i--) {
@ -2869,7 +2869,7 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge)
*line = (*line)->next; *line = (*line)->next;
current_chunk = 0; current_chunk = 0;
last_chunk = strlenpt((*line)->data) / editwincols; last_chunk = get_last_chunk_row(*line);
} }
/* Only change leftedge when we actually could move. */ /* Only change leftedge when we actually could move. */
@ -2891,7 +2891,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge)
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
filestruct *line = openfile->current; filestruct *line = openfile->current;
size_t leftedge = (xplustabs() / editwincols) * editwincols; size_t leftedge = get_chunk_leftedge(openfile->current, xplustabs());
int rows_left = go_back_chunks(editwinrows - 1, &line, &leftedge); int rows_left = go_back_chunks(editwinrows - 1, &line, &leftedge);
return (rows_left > 0 || line->lineno < was_lineno || return (rows_left > 0 || line->lineno < was_lineno ||
@ -2957,11 +2957,11 @@ void edit_scroll(scroll_dir direction, int nrows)
#ifndef NANO_TINY #ifndef NANO_TINY
/* Compensate for the earlier chunks of a softwrapped line. */ /* Compensate for the earlier chunks of a softwrapped line. */
nrows += leftedge / editwincols; nrows += get_chunk_row(line, leftedge);
/* Don't compensate for the chunks that are offscreen. */ /* Don't compensate for the chunks that are offscreen. */
if (line == openfile->edittop) if (line == openfile->edittop)
nrows -= openfile->firstcolumn / editwincols; nrows -= get_chunk_row(line, openfile->firstcolumn);
#endif #endif
/* Draw new content on the blank rows inside the scrolled region /* Draw new content on the blank rows inside the scrolled region
@ -3039,6 +3039,34 @@ size_t get_chunk(filestruct *line, size_t column, size_t *leftedge)
} }
} }
/* Return the row of the softwrapped chunk of the given line that column is on,
* relative to the first row (zero-based). */
size_t get_chunk_row(filestruct *line, size_t column)
{
return strnlenpt(line->data, column) / editwincols;
}
/* Return the leftmost column of the softwrapped chunk of the given line that
* column is on. */
size_t get_chunk_leftedge(filestruct *line, size_t column)
{
return (strnlenpt(line->data, column) / editwincols) * editwincols;
}
/* Return the row of the last softwrapped chunk of the given line, relative to
* the first row (zero-based). */
size_t get_last_chunk_row(filestruct *line)
{
return get_chunk_row(line, (size_t)-1);
}
/* Return the leftmost column of the last softwrapped chunk of the given
* line. */
size_t get_last_chunk_leftedge(filestruct *line)
{
return get_chunk_leftedge(line, (size_t)-1);
}
/* Ensure that firstcolumn is at the starting column of the softwrapped chunk /* Ensure that firstcolumn is at the starting column of the softwrapped chunk
* it's on. We need to do this when the number of columns of the edit window * it's on. We need to do this when the number of columns of the edit window
* has changed, because then the width of softwrapped chunks has changed. */ * has changed, because then the width of softwrapped chunks has changed. */
@ -3082,7 +3110,8 @@ bool current_is_below_screen(void)
return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 && return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 &&
(line->lineno < openfile->current->lineno || (line->lineno < openfile->current->lineno ||
(line->lineno == openfile->current->lineno && (line->lineno == openfile->current->lineno &&
leftedge < (xplustabs() / editwincols) * editwincols))); leftedge < get_chunk_leftedge(openfile->current,
xplustabs()))));
} else } else
#endif #endif
return (openfile->current->lineno >= return (openfile->current->lineno >=
@ -3201,7 +3230,8 @@ void adjust_viewport(update_type manner)
openfile->edittop = openfile->current; openfile->edittop = openfile->current;
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) if (ISSET(SOFTWRAP))
openfile->firstcolumn = (xplustabs() / editwincols) * editwincols; openfile->firstcolumn = get_chunk_leftedge(openfile->current,
xplustabs());
#endif #endif
/* Move edittop back goal rows, starting at current[current_x]. */ /* Move edittop back goal rows, starting at current[current_x]. */