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);
if (ISSET(SOFTWRAP))
was_leftedge = (xplustabs() / editwincols) * editwincols;
was_leftedge = get_chunk_leftedge(openfile->current, xplustabs());
#endif
/* 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);
if (ISSET(SOFTWRAP))
was_leftedge = (xplustabs() / editwincols) * editwincols;
was_leftedge = get_chunk_leftedge(openfile->current, xplustabs());
#endif
/* 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)
realspan = openfile->placewewant;
*leftedge = (realspan / editwincols) * editwincols;
*leftedge = get_chunk_leftedge(openfile->current, realspan);
*target_column = openfile->placewewant % editwincols;
} else
#endif
@ -352,9 +352,11 @@ void do_home(bool be_clever)
bool moved = FALSE;
size_t leftedge_x = 0;
if (ISSET(SOFTWRAP))
leftedge_x = actual_x(openfile->current->data,
(was_column / editwincols) * editwincols);
if (ISSET(SOFTWRAP)) {
size_t leftedge = get_chunk_leftedge(openfile->current, was_column);
leftedge_x = actual_x(openfile->current->data, leftedge);
}
if (ISSET(SMART_HOME) && be_clever) {
size_t indent_x = indent_length(openfile->current->data);
@ -417,9 +419,9 @@ void do_end(bool be_clever)
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
size_t leftedge = get_chunk_leftedge(openfile->current, was_column);
size_t rightedge_x = actual_x(openfile->current->data,
((was_column / editwincols) * editwincols) +
(editwincols - 1));
leftedge + (editwincols - 1));
/* If already at the right edge of the screen, move fully to
* the end of the line. Otherwise, move to the right edge. */
@ -562,8 +564,8 @@ void do_left(void)
{
size_t was_column = xplustabs();
#ifndef NANO_TINY
size_t was_chunk = (was_column / editwincols);
filestruct *was_current = openfile->current;
size_t was_chunk = get_chunk_row(was_current, was_column);
#endif
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. */
if (ISSET(SOFTWRAP) && openfile->current_y == 0 &&
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);
return;
}
@ -598,8 +601,8 @@ void do_right(void)
{
size_t was_column = xplustabs();
#ifndef NANO_TINY
size_t was_chunk = (was_column / editwincols);
filestruct *was_current = openfile->current;
size_t was_chunk = get_chunk_row(was_current, was_column);
#endif
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. */
if (ISSET(SOFTWRAP) && openfile->current_y == editwinrows - 1 &&
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);
return;
}

View File

@ -1759,7 +1759,7 @@ int do_mouse(void)
/* Whether the click was on the row where the cursor is. */
if (ISSET(SOFTWRAP))
leftedge = (xplustabs() / editwincols) * editwincols;
leftedge = get_chunk_leftedge(openfile->current, xplustabs());
else
#endif
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 (openfile->current_y == editwinrows - 1)
original_row = xplustabs() / editwincols;
orig_rows = strlenpt(openfile->current->data) / editwincols;
original_row = get_chunk_row(openfile->current, xplustabs());
orig_rows = get_last_chunk_row(openfile->current);
}
#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
* the last line of the edit window, so we need a full refresh too. */
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 &&
xplustabs() / editwincols != original_row)))
get_chunk_row(openfile->current, xplustabs()) != original_row)))
refresh_needed = TRUE;
#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,
bool *end_of_line);
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);
#endif
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
if (ISSET(SOFTWRAP)) {
filestruct *line = openfile->current;
size_t leftedge = (xplustabs() / editwincols) * editwincols;
size_t leftedge = get_chunk_leftedge(openfile->current, xplustabs());
rows_from_tail = (editwinrows / 2) -
go_forward_chunks(editwinrows / 2, &line, &leftedge);

View File

@ -112,7 +112,7 @@ void do_deletion(undo_type action)
update_undo(action);
if (ISSET(SOFTWRAP))
orig_rows = strlenpt(openfile->current->data) / editwincols;
orig_rows = get_last_chunk_row(openfile->current);
#endif
/* 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
* has changed, we need a full refresh. */
if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
strlenpt(openfile->current->data) / editwincols != orig_rows)
get_last_chunk_row(openfile->current) != orig_rows)
refresh_needed = TRUE;
#endif

View File

@ -2295,16 +2295,16 @@ void place_the_cursor(bool forreal)
if (ISSET(SOFTWRAP)) {
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. */
while (line != NULL && line != openfile->current) {
row += strlenpt(line->data) / editwincols + 1;
row += get_last_chunk_row(line) + 1;
line = line->next;
}
/* 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;
/* 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)
from_col = openfile->firstcolumn;
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. */
while (line != fileptr && line != NULL) {
row += (strlenpt(line->data) / editwincols) + 1;
row += get_last_chunk_row(line) + 1;
line = line->next;
}
@ -2813,7 +2813,7 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge)
#ifndef NANO_TINY
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. */
for (i = nrows; i > 0; i--) {
@ -2826,7 +2826,7 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge)
break;
*line = (*line)->prev;
current_chunk = strlenpt((*line)->data) / editwincols;
current_chunk = get_last_chunk_row(*line);
}
/* 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
if (ISSET(SOFTWRAP)) {
size_t current_chunk = (*leftedge) / editwincols;
size_t last_chunk = strlenpt((*line)->data) / editwincols;
size_t current_chunk = get_chunk_row(*line, *leftedge);
size_t last_chunk = get_last_chunk_row(*line);
/* Advance through the requested number of chunks. */
for (i = nrows; i > 0; i--) {
@ -2869,7 +2869,7 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge)
*line = (*line)->next;
current_chunk = 0;
last_chunk = strlenpt((*line)->data) / editwincols;
last_chunk = get_last_chunk_row(*line);
}
/* 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
if (ISSET(SOFTWRAP)) {
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);
return (rows_left > 0 || line->lineno < was_lineno ||
@ -2957,11 +2957,11 @@ void edit_scroll(scroll_dir direction, int nrows)
#ifndef NANO_TINY
/* 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. */
if (line == openfile->edittop)
nrows -= openfile->firstcolumn / editwincols;
nrows -= get_chunk_row(line, openfile->firstcolumn);
#endif
/* 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
* 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. */
@ -3082,7 +3110,8 @@ bool current_is_below_screen(void)
return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 &&
(line->lineno < openfile->current->lineno ||
(line->lineno == openfile->current->lineno &&
leftedge < (xplustabs() / editwincols) * editwincols)));
leftedge < get_chunk_leftedge(openfile->current,
xplustabs()))));
} else
#endif
return (openfile->current->lineno >=
@ -3201,7 +3230,8 @@ void adjust_viewport(update_type manner)
openfile->edittop = openfile->current;
#ifndef NANO_TINY
if (ISSET(SOFTWRAP))
openfile->firstcolumn = (xplustabs() / editwincols) * editwincols;
openfile->firstcolumn = get_chunk_leftedge(openfile->current,
xplustabs());
#endif
/* Move edittop back goal rows, starting at current[current_x]. */