Refactor movement code in editor(1).
Firstly, lots of places in editor(1) would do a move from (x₀,y₀) to (x,y) by first moving to (x,y₀) or (x₀,y) and only then (x,y). If the intermediate positions were not valid cursor positions, this might cause out of bounds access. Categorically fixed this by removing functions for moving only horizontally or only vertically. Secondly, editor_select_set() would set the column before setting the line. Since the code for setting the column accesses the currently set line at the new cursor position, it might cause out of bounds access even on valid cursor positions. Fixed this by swapping the order in which column and row are set. Thirdly, the order of arguments passed to row_column_smallest() and row_column_biggest() was wrong, with column being passed before the row, even though they were defined the other way. However, this did not result in out of bounds memory accesses due to the parameters to editor_cursor_set() also being swapped at relevant callsites. Finally, the boundary condition for control-down was off by one.
This commit is contained in:
parent
2e193b6014
commit
7e5a816749
173
editor/command.c
173
editor/command.c
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2021 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -134,8 +135,9 @@ void editor_type_backspace(struct editor* editor)
|
||||||
editor->dirty = true;
|
editor->dirty = true;
|
||||||
|
|
||||||
current_line->used--;
|
current_line->used--;
|
||||||
for ( size_t i = editor_cursor_column_dec(editor); i < current_line->used; i++ )
|
for ( size_t i = editor->cursor_column - 1; i < current_line->used; i++ )
|
||||||
current_line->data[i] = current_line->data[i+1];
|
current_line->data[i] = current_line->data[i+1];
|
||||||
|
editor_cursor_set(editor, editor->cursor_row, editor->cursor_column - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_combine_with_next(struct editor* editor)
|
void editor_type_combine_with_next(struct editor* editor)
|
||||||
|
@ -157,7 +159,7 @@ void editor_type_combine_with_next(struct editor* editor)
|
||||||
memcpy(new_data, keep_line_data, sizeof(wchar_t) * keep_line->used);
|
memcpy(new_data, keep_line_data, sizeof(wchar_t) * keep_line->used);
|
||||||
memcpy(new_data + keep_line->used, gone_line_data, sizeof(wchar_t) * gone_line->used);
|
memcpy(new_data + keep_line->used, gone_line_data, sizeof(wchar_t) * gone_line->used);
|
||||||
|
|
||||||
editor_cursor_column_set(editor, keep_line->used);
|
editor_cursor_set(editor, editor->cursor_row, keep_line->used);
|
||||||
|
|
||||||
keep_line->data = new_data;
|
keep_line->data = new_data;
|
||||||
keep_line->used = new_length;
|
keep_line->used = new_length;
|
||||||
|
@ -227,8 +229,8 @@ void editor_type_exit_select_left(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +242,8 @@ void editor_type_exit_select_right(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,23 +252,21 @@ void editor_type_left(struct editor* editor)
|
||||||
{
|
{
|
||||||
editor_type_exit_select_left(editor);
|
editor_type_exit_select_left(editor);
|
||||||
if ( editor->cursor_column )
|
if ( editor->cursor_column )
|
||||||
editor_cursor_column_dec(editor);
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->cursor_column - 1);
|
||||||
else if ( editor->cursor_row )
|
else if ( editor->cursor_row )
|
||||||
{
|
editor_cursor_set(editor, editor->cursor_row - 1,
|
||||||
editor_cursor_row_dec(editor);
|
editor->lines[editor->cursor_row - 1].used);
|
||||||
editor_cursor_column_set(editor, editor->lines[editor->cursor_row].used);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_left(struct editor* editor)
|
void editor_type_select_left(struct editor* editor)
|
||||||
{
|
{
|
||||||
if ( editor->select_column )
|
if ( editor->select_column )
|
||||||
editor_select_column_dec(editor);
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->select_column - 1);
|
||||||
else if ( editor->select_row )
|
else if ( editor->select_row )
|
||||||
{
|
editor_select_set(editor, editor->select_row - 1,
|
||||||
editor_select_row_dec(editor);
|
editor->lines[editor->select_row - 1].used);
|
||||||
editor_select_column_set(editor, editor->lines[editor->select_row].used);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_left(struct editor* editor)
|
void editor_type_control_left(struct editor* editor)
|
||||||
|
@ -313,20 +313,20 @@ void editor_type_right(struct editor* editor)
|
||||||
editor_type_exit_select_right(editor);
|
editor_type_exit_select_right(editor);
|
||||||
struct line* current_line = &editor->lines[editor->cursor_row];
|
struct line* current_line = &editor->lines[editor->cursor_row];
|
||||||
if ( editor->cursor_column != current_line->used )
|
if ( editor->cursor_column != current_line->used )
|
||||||
editor_cursor_column_inc(editor);
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->cursor_column + 1);
|
||||||
else if ( editor->cursor_row + 1 != editor->lines_used )
|
else if ( editor->cursor_row + 1 != editor->lines_used )
|
||||||
editor_cursor_row_inc(editor),
|
editor_cursor_set(editor, editor->cursor_row + 1, 0);
|
||||||
editor_cursor_column_set(editor, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_right(struct editor* editor)
|
void editor_type_select_right(struct editor* editor)
|
||||||
{
|
{
|
||||||
struct line* current_line = &editor->lines[editor->select_row];
|
struct line* current_line = &editor->lines[editor->select_row];
|
||||||
if ( editor->select_column != current_line->used )
|
if ( editor->select_column != current_line->used )
|
||||||
editor_select_column_inc(editor);
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->select_column + 1);
|
||||||
else if ( editor->select_row + 1 != editor->lines_used )
|
else if ( editor->select_row + 1 != editor->lines_used )
|
||||||
editor_select_row_inc(editor),
|
editor_select_set(editor, editor->select_row + 1, 0);
|
||||||
editor_select_column_set(editor, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_right(struct editor* editor)
|
void editor_type_control_right(struct editor* editor)
|
||||||
|
@ -371,43 +371,45 @@ void editor_type_up(struct editor* editor)
|
||||||
editor_type_exit_select_left(editor);
|
editor_type_exit_select_left(editor);
|
||||||
if ( !editor->cursor_row )
|
if ( !editor->cursor_row )
|
||||||
{
|
{
|
||||||
editor_cursor_column_set(editor, 0);
|
editor_cursor_set(editor, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct line* old_line = &editor->lines[editor->cursor_row];
|
struct line* old_line = &editor->lines[editor->cursor_row];
|
||||||
struct line* new_line = &editor->lines[editor_cursor_row_dec(editor)];
|
struct line* new_line = &editor->lines[editor->cursor_row - 1];
|
||||||
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->cursor_column);
|
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->cursor_column);
|
||||||
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
||||||
editor_cursor_column_set(editor, new_offset);
|
editor_cursor_set(editor, editor->cursor_row - 1, new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_up(struct editor* editor)
|
void editor_type_select_up(struct editor* editor)
|
||||||
{
|
{
|
||||||
if ( !editor->select_row )
|
if ( !editor->select_row )
|
||||||
{
|
{
|
||||||
editor_select_column_set(editor, 0);
|
editor_select_set(editor, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct line* old_line = &editor->lines[editor->select_row];
|
struct line* old_line = &editor->lines[editor->select_row];
|
||||||
struct line* new_line = &editor->lines[editor_select_row_dec(editor)];
|
struct line* new_line = &editor->lines[editor->select_row - 1];
|
||||||
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->select_column);
|
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->select_column);
|
||||||
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
||||||
editor_select_column_set(editor, new_offset);
|
editor_select_set(editor, editor->select_row - 1, new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_up(struct editor* editor)
|
void editor_type_control_up(struct editor* editor)
|
||||||
{
|
{
|
||||||
editor_type_exit_select_left(editor);
|
editor_type_exit_select_left(editor);
|
||||||
if ( editor->cursor_row )
|
if ( editor->cursor_row )
|
||||||
editor_cursor_row_dec(editor);
|
editor_cursor_set(editor, editor->cursor_row - 1, 0);
|
||||||
editor_cursor_column_set(editor, 0);
|
else
|
||||||
|
editor_cursor_set(editor, editor->cursor_row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_select_up(struct editor* editor)
|
void editor_type_control_select_up(struct editor* editor)
|
||||||
{
|
{
|
||||||
if ( editor->select_row )
|
if ( editor->select_row )
|
||||||
editor_select_row_dec(editor);
|
editor_select_set(editor, editor->select_row - 1, 0);
|
||||||
editor_select_column_set(editor, 0);
|
else
|
||||||
|
editor_select_set(editor, editor->select_row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_down(struct editor* editor)
|
void editor_type_down(struct editor* editor)
|
||||||
|
@ -415,51 +417,60 @@ void editor_type_down(struct editor* editor)
|
||||||
editor_type_exit_select_right(editor);
|
editor_type_exit_select_right(editor);
|
||||||
if ( editor->cursor_row + 1 == editor->lines_used )
|
if ( editor->cursor_row + 1 == editor->lines_used )
|
||||||
{
|
{
|
||||||
editor_cursor_column_set(editor, editor->lines[editor->cursor_row].used);
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->lines[editor->cursor_row].used);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct line* old_line = &editor->lines[editor->cursor_row];
|
struct line* old_line = &editor->lines[editor->cursor_row];
|
||||||
struct line* new_line = &editor->lines[editor_cursor_row_inc(editor)];
|
struct line* new_line = &editor->lines[editor->cursor_row + 1];
|
||||||
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->cursor_column);
|
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->cursor_column);
|
||||||
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
||||||
editor_cursor_column_set(editor, new_offset);
|
editor_cursor_set(editor, editor->cursor_row + 1, new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_down(struct editor* editor)
|
void editor_type_select_down(struct editor* editor)
|
||||||
{
|
{
|
||||||
if ( editor->select_row+1 == editor->lines_used )
|
if ( editor->select_row+1 == editor->lines_used )
|
||||||
{
|
{
|
||||||
editor_select_column_set(editor, editor->lines[editor->select_row].used);
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->lines[editor->select_row].used);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct line* old_line = &editor->lines[editor->select_row];
|
struct line* old_line = &editor->lines[editor->select_row];
|
||||||
struct line* new_line = &editor->lines[editor_select_row_inc(editor)];
|
struct line* new_line = &editor->lines[editor->select_row + 1];
|
||||||
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->select_column);
|
size_t old_column = editor_display_column_of_line_offset(editor, old_line, editor->select_column);
|
||||||
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
size_t new_offset = editor_line_offset_of_display_column(editor, new_line, old_column);
|
||||||
editor_select_column_set(editor, new_offset);
|
editor_select_set(editor, editor->select_row + 1, new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_down(struct editor* editor)
|
void editor_type_control_down(struct editor* editor)
|
||||||
{
|
{
|
||||||
editor_type_exit_select_right(editor);
|
editor_type_exit_select_right(editor);
|
||||||
if ( editor->cursor_row < editor->lines_used )
|
if ( editor->cursor_row + 1 < editor->lines_used )
|
||||||
editor_cursor_row_inc(editor);
|
editor_cursor_set(editor, editor->cursor_row + 1,
|
||||||
editor_cursor_column_set(editor, editor->lines[editor->cursor_row].used);
|
editor->lines[editor->cursor_row + 1].used);
|
||||||
|
else
|
||||||
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->lines[editor->cursor_row].used);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_control_select_down(struct editor* editor)
|
void editor_type_control_select_down(struct editor* editor)
|
||||||
{
|
{
|
||||||
if ( editor->select_row < editor->lines_used )
|
if ( editor->select_row + 1 < editor->lines_used )
|
||||||
editor_select_row_inc(editor);
|
editor_select_set(editor, editor->select_row + 1,
|
||||||
editor_select_column_set(editor, editor->lines[editor->select_row].used);
|
editor->lines[editor->select_row + 1].used);
|
||||||
|
else
|
||||||
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->lines[editor->select_row].used);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_skip_leading(struct editor* editor)
|
void editor_skip_leading(struct editor* editor)
|
||||||
{
|
{
|
||||||
struct line* current_line = &editor->lines[editor->cursor_row];
|
struct line* current_line = &editor->lines[editor->cursor_row];
|
||||||
for ( editor_cursor_column_set(editor, 0);
|
for ( editor_cursor_set(editor, editor->cursor_row, 0);
|
||||||
editor->cursor_column < current_line->used;
|
editor->cursor_column < current_line->used;
|
||||||
editor_cursor_column_inc(editor) )
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->cursor_column + 1) )
|
||||||
if ( !iswspace(current_line->data[editor->cursor_column]) )
|
if ( !iswspace(current_line->data[editor->cursor_column]) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -467,9 +478,10 @@ void editor_skip_leading(struct editor* editor)
|
||||||
void editor_select_skip_leading(struct editor* editor)
|
void editor_select_skip_leading(struct editor* editor)
|
||||||
{
|
{
|
||||||
struct line* current_line = &editor->lines[editor->select_row];
|
struct line* current_line = &editor->lines[editor->select_row];
|
||||||
for ( editor_select_column_set(editor, 0);
|
for ( editor_select_set(editor, editor->select_row, 0);
|
||||||
editor->select_column < current_line->used;
|
editor->select_column < current_line->used;
|
||||||
editor_select_column_inc(editor) )
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->select_column + 1) )
|
||||||
if ( !iswspace(current_line->data[editor->select_column]) )
|
if ( !iswspace(current_line->data[editor->select_column]) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -481,15 +493,15 @@ void editor_type_home(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
}
|
}
|
||||||
if ( !editor->cursor_column )
|
if ( !editor->cursor_column )
|
||||||
{
|
{
|
||||||
editor_skip_leading(editor);
|
editor_skip_leading(editor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_column_set(editor, 0);
|
editor_cursor_set(editor, editor->cursor_row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_home(struct editor* editor)
|
void editor_type_select_home(struct editor* editor)
|
||||||
|
@ -499,15 +511,16 @@ void editor_type_select_home(struct editor* editor)
|
||||||
editor_select_skip_leading(editor);
|
editor_select_skip_leading(editor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_select_column_set(editor, 0);
|
editor_select_set(editor, editor->select_row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_skip_ending(struct editor* editor)
|
void editor_skip_ending(struct editor* editor)
|
||||||
{
|
{
|
||||||
struct line* current_line = &editor->lines[editor->cursor_row];
|
struct line* current_line = &editor->lines[editor->cursor_row];
|
||||||
for ( editor_cursor_column_set(editor, current_line->used);
|
for ( editor_cursor_set(editor, editor->cursor_row, current_line->used);
|
||||||
editor->cursor_column;
|
editor->cursor_column;
|
||||||
editor_cursor_column_dec(editor) )
|
editor_cursor_set(editor, editor->cursor_row,
|
||||||
|
editor->cursor_column - 1) )
|
||||||
if ( !iswspace(current_line->data[editor->cursor_column-1]) )
|
if ( !iswspace(current_line->data[editor->cursor_column-1]) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -515,9 +528,10 @@ void editor_skip_ending(struct editor* editor)
|
||||||
void editor_select_skip_ending(struct editor* editor)
|
void editor_select_skip_ending(struct editor* editor)
|
||||||
{
|
{
|
||||||
struct line* current_line = &editor->lines[editor->select_row];
|
struct line* current_line = &editor->lines[editor->select_row];
|
||||||
for ( editor_select_column_set(editor, current_line->used);
|
for ( editor_select_set(editor, editor->select_row, current_line->used);
|
||||||
editor->select_column;
|
editor->select_column;
|
||||||
editor_select_column_dec(editor) )
|
editor_select_set(editor, editor->select_row,
|
||||||
|
editor->select_column - 1) )
|
||||||
if ( !iswspace(current_line->data[editor->select_column-1]) )
|
if ( !iswspace(current_line->data[editor->select_column-1]) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -529,8 +543,8 @@ void editor_type_end(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
}
|
}
|
||||||
struct line* current_line = &editor->lines[editor->cursor_row];
|
struct line* current_line = &editor->lines[editor->cursor_row];
|
||||||
if ( editor->cursor_column == current_line->used )
|
if ( editor->cursor_column == current_line->used )
|
||||||
|
@ -538,7 +552,7 @@ void editor_type_end(struct editor* editor)
|
||||||
editor_skip_ending(editor);
|
editor_skip_ending(editor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_column_set(editor, current_line->used);
|
editor_cursor_set(editor, editor->cursor_row, current_line->used);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_end(struct editor* editor)
|
void editor_type_select_end(struct editor* editor)
|
||||||
|
@ -549,7 +563,7 @@ void editor_type_select_end(struct editor* editor)
|
||||||
editor_select_skip_ending(editor);
|
editor_select_skip_ending(editor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_select_column_set(editor, current_line->used);
|
editor_select_set(editor, editor->select_row, current_line->used);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_page_up(struct editor* editor)
|
void editor_type_page_up(struct editor* editor)
|
||||||
|
@ -559,8 +573,8 @@ void editor_type_page_up(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
row_column_smallest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
}
|
}
|
||||||
if ( editor->cursor_row < editor->viewport_height )
|
if ( editor->cursor_row < editor->viewport_height )
|
||||||
{
|
{
|
||||||
|
@ -568,10 +582,11 @@ void editor_type_page_up(struct editor* editor)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t new_line = editor->cursor_row - editor->viewport_height;
|
size_t new_line = editor->cursor_row - editor->viewport_height;
|
||||||
editor_cursor_row_set(editor, new_line);
|
|
||||||
size_t new_line_len = editor->lines[new_line].used;
|
size_t new_line_len = editor->lines[new_line].used;
|
||||||
if ( new_line_len < editor->cursor_column )
|
if ( new_line_len < editor->cursor_column )
|
||||||
editor_cursor_column_set(editor, new_line_len);
|
editor_cursor_set(editor, new_line, new_line_len);
|
||||||
|
else
|
||||||
|
editor_cursor_set(editor, new_line, editor->cursor_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_page_up(struct editor* editor)
|
void editor_type_select_page_up(struct editor* editor)
|
||||||
|
@ -582,10 +597,11 @@ void editor_type_select_page_up(struct editor* editor)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t new_line = editor->select_row - editor->viewport_height;
|
size_t new_line = editor->select_row - editor->viewport_height;
|
||||||
editor_select_row_set(editor, new_line);
|
|
||||||
size_t new_line_len = editor->lines[new_line].used;
|
size_t new_line_len = editor->lines[new_line].used;
|
||||||
if ( new_line_len < editor->select_column )
|
if ( new_line_len < editor->select_column )
|
||||||
editor_select_column_set(editor, new_line_len);
|
editor_select_set(editor, new_line, new_line_len);
|
||||||
|
else
|
||||||
|
editor_select_set(editor, new_line, editor->select_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_page_down(struct editor* editor)
|
void editor_type_page_down(struct editor* editor)
|
||||||
|
@ -595,20 +611,21 @@ void editor_type_page_down(struct editor* editor)
|
||||||
size_t column, row;
|
size_t column, row;
|
||||||
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
row_column_biggest(editor->cursor_row, editor->cursor_column,
|
||||||
editor->select_row, editor->select_column,
|
editor->select_row, editor->select_column,
|
||||||
&column, &row);
|
&row, &column);
|
||||||
editor_cursor_set(editor, column, row);
|
editor_cursor_set(editor, row, column);
|
||||||
}
|
}
|
||||||
size_t new_line = editor->cursor_row + editor->viewport_height;
|
size_t new_line = editor->cursor_row + editor->viewport_height;
|
||||||
if ( editor->lines_used <= new_line )
|
if ( editor->lines_used <= new_line )
|
||||||
{
|
{
|
||||||
editor_cursor_row_set(editor, editor->lines_used - 1);
|
editor_cursor_set(editor, editor->lines_used - 1,
|
||||||
editor_cursor_column_set(editor, editor->lines[editor->cursor_row].used);
|
editor->lines[editor->lines_used - 1].used);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_row_set(editor, new_line);
|
|
||||||
size_t new_line_len = editor->lines[new_line].used;
|
size_t new_line_len = editor->lines[new_line].used;
|
||||||
if ( new_line_len < editor->cursor_column )
|
if ( new_line_len < editor->cursor_column )
|
||||||
editor_cursor_column_set(editor, new_line_len);
|
editor_cursor_set(editor, new_line, new_line_len);
|
||||||
|
else
|
||||||
|
editor_cursor_set(editor, new_line, editor->cursor_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_select_page_down(struct editor* editor)
|
void editor_type_select_page_down(struct editor* editor)
|
||||||
|
@ -616,14 +633,15 @@ void editor_type_select_page_down(struct editor* editor)
|
||||||
size_t new_line = editor->select_row + editor->viewport_height;
|
size_t new_line = editor->select_row + editor->viewport_height;
|
||||||
if ( editor->lines_used <= new_line )
|
if ( editor->lines_used <= new_line )
|
||||||
{
|
{
|
||||||
editor_select_row_set(editor, editor->lines_used - 1);
|
editor_select_set(editor, editor->lines_used - 1,
|
||||||
editor_select_column_set(editor, editor->lines[editor->select_row].used);
|
editor->lines[editor->lines_used - 1].used);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_select_row_set(editor, new_line);
|
|
||||||
size_t new_line_len = editor->lines[new_line].used;
|
size_t new_line_len = editor->lines[new_line].used;
|
||||||
if ( new_line_len < editor->select_column )
|
if ( new_line_len < editor->select_column )
|
||||||
editor_select_column_set(editor, new_line_len);
|
editor_select_set(editor, new_line, new_line_len);
|
||||||
|
else
|
||||||
|
editor_select_set(editor, new_line, editor->select_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_edit(struct editor* editor)
|
void editor_type_edit(struct editor* editor)
|
||||||
|
@ -718,7 +736,8 @@ void editor_type_raw_character(struct editor* editor, wchar_t c)
|
||||||
for ( size_t i = current_line->used; editor->cursor_column < i; i-- )
|
for ( size_t i = current_line->used; editor->cursor_column < i; i-- )
|
||||||
current_line->data[i] = current_line->data[i-1];
|
current_line->data[i] = current_line->data[i-1];
|
||||||
current_line->used++;
|
current_line->used++;
|
||||||
current_line->data[editor_cursor_column_inc(editor)-1] = c;
|
current_line->data[editor->cursor_column] = c;
|
||||||
|
editor_cursor_set(editor, editor->cursor_row, editor->cursor_column + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_type_copy(struct editor* editor)
|
void editor_type_copy(struct editor* editor)
|
||||||
|
|
101
editor/cursor.c
101
editor/cursor.c
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2021 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -25,8 +26,19 @@
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
size_t editor_select_column_set(struct editor* editor, size_t x)
|
void editor_select_set(struct editor* editor, size_t y, size_t x)
|
||||||
{
|
{
|
||||||
|
assert(y < editor->lines_used);
|
||||||
|
assert(x <= editor->lines[y].used);
|
||||||
|
if ( editor->viewport_height )
|
||||||
|
{
|
||||||
|
if ( y < editor->page_y_offset )
|
||||||
|
editor->page_y_offset = y;
|
||||||
|
if ( editor->page_y_offset + editor->viewport_height <= y )
|
||||||
|
editor->page_y_offset = y + 1 - editor->viewport_height;
|
||||||
|
}
|
||||||
|
editor->select_row = y;
|
||||||
|
|
||||||
if ( editor->viewport_width )
|
if ( editor->viewport_width )
|
||||||
{
|
{
|
||||||
struct line* line = &editor->lines[editor->select_row];
|
struct line* line = &editor->lines[editor->select_row];
|
||||||
|
@ -36,91 +48,12 @@ size_t editor_select_column_set(struct editor* editor, size_t x)
|
||||||
if ( editor->page_x_offset + editor->viewport_width <= rx )
|
if ( editor->page_x_offset + editor->viewport_width <= rx )
|
||||||
editor->page_x_offset = rx + 1 - editor->viewport_width;
|
editor->page_x_offset = rx + 1 - editor->viewport_width;
|
||||||
}
|
}
|
||||||
return editor->select_column = x;
|
editor->select_column = x;
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_select_row_set(struct editor* editor, size_t y)
|
|
||||||
{
|
|
||||||
if ( editor->viewport_height )
|
|
||||||
{
|
|
||||||
if ( y < editor->page_y_offset )
|
|
||||||
editor->page_y_offset = y;
|
|
||||||
if ( editor->page_y_offset + editor->viewport_height <= y )
|
|
||||||
editor->page_y_offset = y + 1 - editor->viewport_height;
|
|
||||||
}
|
|
||||||
return editor->select_row = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void editor_select_set(struct editor* editor, size_t y, size_t x)
|
|
||||||
{
|
|
||||||
editor_select_column_set(editor, x);
|
|
||||||
editor_select_row_set(editor, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_select_column_dec(struct editor* editor)
|
|
||||||
{
|
|
||||||
assert(editor->select_column);
|
|
||||||
return editor_select_column_set(editor, editor->select_column-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_select_column_inc(struct editor* editor)
|
|
||||||
{
|
|
||||||
// TODO: Assert line doesn't overflow!
|
|
||||||
return editor_select_column_set(editor, editor->select_column+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_select_row_dec(struct editor* editor)
|
|
||||||
{
|
|
||||||
assert(editor->select_row);
|
|
||||||
return editor_select_row_set(editor, editor->select_row-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_select_row_inc(struct editor* editor)
|
|
||||||
{
|
|
||||||
// TODO: Assert line doesn't overflow!
|
|
||||||
return editor_select_row_set(editor, editor->select_row+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_cursor_column_set(struct editor* editor, size_t x)
|
|
||||||
{
|
|
||||||
editor_select_column_set(editor, x);
|
|
||||||
editor_select_row_set(editor, editor->cursor_row);
|
|
||||||
return editor->cursor_column = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_cursor_row_set(struct editor* editor, size_t y)
|
|
||||||
{
|
|
||||||
editor_select_column_set(editor, editor->cursor_column);
|
|
||||||
editor_select_row_set(editor, y);
|
|
||||||
return editor->cursor_row = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_cursor_set(struct editor* editor, size_t y, size_t x)
|
void editor_cursor_set(struct editor* editor, size_t y, size_t x)
|
||||||
{
|
{
|
||||||
editor_cursor_column_set(editor, x);
|
editor_select_set(editor, y, x);
|
||||||
editor_cursor_row_set(editor, y);
|
editor->cursor_column = x;
|
||||||
}
|
editor->cursor_row = y;
|
||||||
|
|
||||||
size_t editor_cursor_column_dec(struct editor* editor)
|
|
||||||
{
|
|
||||||
assert(editor->cursor_column);
|
|
||||||
return editor_cursor_column_set(editor, editor->cursor_column-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_cursor_column_inc(struct editor* editor)
|
|
||||||
{
|
|
||||||
// TODO: Assert line doesn't overflow!
|
|
||||||
return editor_cursor_column_set(editor, editor->cursor_column+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_cursor_row_dec(struct editor* editor)
|
|
||||||
{
|
|
||||||
assert(editor->cursor_row);
|
|
||||||
return editor_cursor_row_set(editor, editor->cursor_row-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t editor_cursor_row_inc(struct editor* editor)
|
|
||||||
{
|
|
||||||
// TODO: Assert line doesn't overflow!
|
|
||||||
return editor_cursor_row_set(editor, editor->cursor_row+1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,20 +24,7 @@
|
||||||
|
|
||||||
struct editor;
|
struct editor;
|
||||||
|
|
||||||
size_t editor_select_column_set(struct editor* editor, size_t x);
|
|
||||||
size_t editor_select_row_set(struct editor* editor, size_t y);
|
|
||||||
void editor_select_set(struct editor* editor, size_t y, size_t x);
|
void editor_select_set(struct editor* editor, size_t y, size_t x);
|
||||||
size_t editor_select_column_dec(struct editor* editor);
|
|
||||||
size_t editor_select_column_inc(struct editor* editor);
|
|
||||||
size_t editor_select_row_dec(struct editor* editor);
|
|
||||||
size_t editor_select_row_inc(struct editor* editor);
|
|
||||||
|
|
||||||
size_t editor_cursor_column_set(struct editor* editor, size_t x);
|
|
||||||
size_t editor_cursor_row_set(struct editor* editor, size_t y);
|
|
||||||
void editor_cursor_set(struct editor* editor, size_t y, size_t x);
|
void editor_cursor_set(struct editor* editor, size_t y, size_t x);
|
||||||
size_t editor_cursor_column_dec(struct editor* editor);
|
|
||||||
size_t editor_cursor_column_inc(struct editor* editor);
|
|
||||||
size_t editor_cursor_row_dec(struct editor* editor);
|
|
||||||
size_t editor_cursor_row_inc(struct editor* editor);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||||
|
* Copyright (c) 2021 Juhani 'nortti' Krekelä.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -200,7 +201,7 @@ void editor_modal_goto_line(struct editor* editor, const char* linestr)
|
||||||
editor->modal_error = true;
|
editor->modal_error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_row_set(editor, editor->cursor_row - line);
|
editor_cursor_set(editor, editor->cursor_row - line, 0);
|
||||||
}
|
}
|
||||||
else if ( go_forward )
|
else if ( go_forward )
|
||||||
{
|
{
|
||||||
|
@ -209,7 +210,7 @@ void editor_modal_goto_line(struct editor* editor, const char* linestr)
|
||||||
editor->modal_error = true;
|
editor->modal_error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_row_set(editor, editor->cursor_row + line);
|
editor_cursor_set(editor, editor->cursor_row + line, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -218,9 +219,8 @@ void editor_modal_goto_line(struct editor* editor, const char* linestr)
|
||||||
editor->modal_error = true;
|
editor->modal_error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor_cursor_row_set(editor, line ? line - 1 : 0);
|
editor_cursor_set(editor, line ? line - 1 : 0, 0);
|
||||||
}
|
}
|
||||||
editor_cursor_column_set(editor, 0);
|
|
||||||
}
|
}
|
||||||
editor_type_edit(editor);
|
editor_type_edit(editor);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue