use super::{scroll_editor_content, SelectMode};
use crate::{caret_locate::{self,
locate_col,
CaretColLocationInLine,
CaretRowLocationInBuffer},
caret_mut,
caret_scr_adj,
caret_scroll_index,
col,
empty_check_early_return,
multiline_disabled_check_early_return,
row,
CaretDirection,
EditorArgsMut,
EditorBuffer,
EditorEngine};
pub fn up(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: SelectMode) {
empty_check_early_return!(buffer, @Nothing);
multiline_disabled_check_early_return!(engine, @Nothing);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
match caret_locate::locate_row(buffer) {
CaretRowLocationInBuffer::AtTop => {
if buffer.get_caret_scr_adj().col_index != col(0) {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::reset_caret_col(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
);
}
}
}
CaretRowLocationInBuffer::AtBottom | CaretRowLocationInBuffer::InMiddle => {
{
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::dec_caret_row(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
);
}
scroll_editor_content::clip_caret_to_content_width(EditorArgsMut {
buffer,
engine,
});
}
}
}
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.update_selection_based_on_caret_movement_in_multiple_lines(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
}
pub fn page_up(
buffer: &mut EditorBuffer,
engine: &mut EditorEngine,
sel_mod: SelectMode,
) {
empty_check_early_return!(buffer, @Nothing);
multiline_disabled_check_early_return!(engine, @Nothing);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
let viewport_height = engine.viewport().row_height;
scroll_editor_content::change_caret_row_by(
EditorArgsMut { engine, buffer },
viewport_height,
CaretDirection::Up,
);
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.update_selection_based_on_caret_movement_in_multiple_lines(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
}
pub fn down(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: SelectMode) {
empty_check_early_return!(buffer, @Nothing);
multiline_disabled_check_early_return!(engine, @Nothing);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
if buffer.next_line_below_caret_to_string().is_some() {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::inc_caret_row(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
buffer_mut.inner.vp.row_height,
);
}
scroll_editor_content::clip_caret_to_content_width(EditorArgsMut {
buffer,
engine,
});
} else {
caret_mut::to_end_of_line(buffer, engine, sel_mod);
}
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.update_selection_based_on_caret_movement_in_multiple_lines(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
}
pub fn page_down(
buffer: &mut EditorBuffer,
engine: &mut EditorEngine,
sel_mod: SelectMode,
) {
empty_check_early_return!(buffer, @Nothing);
multiline_disabled_check_early_return!(engine, @Nothing);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
let viewport_height = engine.viewport().row_height;
scroll_editor_content::change_caret_row_by(
EditorArgsMut { engine, buffer },
viewport_height,
CaretDirection::Down,
);
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.update_selection_based_on_caret_movement_in_multiple_lines(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
}
pub fn to_start_of_line(
buffer: &mut EditorBuffer,
engine: &mut EditorEngine,
sel_mod: SelectMode,
) {
empty_check_early_return!(buffer, @Nothing);
match sel_mod {
SelectMode::Enabled => {
let caret = buffer.get_caret_scr_adj();
for _ in 0..caret.col_index.value {
left(buffer, engine, sel_mod);
}
}
SelectMode::Disabled => {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::reset_caret_col(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
);
}
}
}
}
pub fn to_end_of_line(
buffer: &mut EditorBuffer,
engine: &mut EditorEngine,
sel_mod: SelectMode,
) {
empty_check_early_return!(buffer, @Nothing);
match sel_mod {
SelectMode::Enabled => {
let caret = buffer.get_caret_scr_adj();
let line_display_width = buffer.get_line_display_width_at_caret_scr_adj();
for _ in caret.col_index.value..line_display_width.value {
right(buffer, engine, sel_mod);
}
}
SelectMode::Disabled => {
let line_display_width = buffer.get_line_display_width_at_row_index(
buffer.get_caret_scr_adj().row_index,
);
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::set_caret_col_to(
caret_scroll_index::col_index_for_width(line_display_width),
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
buffer_mut.inner.vp.col_width,
line_display_width,
);
}
}
}
}
pub fn select_all(buffer: &mut EditorBuffer, sel_mod: SelectMode) {
empty_check_early_return!(buffer, @Nothing);
let max_row_index = buffer.get_max_row_index();
let max_col_index = {
let last_line_display_width =
buffer.get_line_display_width_at_row_index(max_row_index);
caret_scroll_index::col_index_for_width(last_line_display_width)
};
buffer.clear_selection();
sel_mod.update_selection_based_on_caret_movement_in_multiple_lines(
buffer,
Some(caret_scr_adj(col(0) + row(0))),
Some(caret_scr_adj(max_col_index + max_row_index)),
);
}
pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: SelectMode) {
empty_check_early_return!(buffer, @Nothing);
let line_is_empty = buffer.line_at_caret_is_empty();
let caret_col_loc_in_line = locate_col(buffer);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
match caret_col_loc_in_line {
CaretColLocationInLine::AtStart if line_is_empty => {
inner::right_at_end(buffer, engine);
}
CaretColLocationInLine::AtStart | CaretColLocationInLine::InMiddle => {
inner::right_normal(buffer, engine);
}
CaretColLocationInLine::AtEnd => {
inner::right_at_end(buffer, engine);
}
};
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.handle_selection_single_line_caret_movement(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
return;
mod inner {
use super::*;
use crate::{wide_segments::ContainsWideSegments, width, SegString};
pub fn right_normal(
buffer: &mut EditorBuffer,
engine: &mut EditorEngine,
) -> Option<()> {
let SegString {
width: unicode_width_at_caret,
..
} = buffer.string_at_caret()?;
let max_display_width = buffer.get_line_display_width_at_caret_scr_adj();
let maybe_char_to_right_of_caret = buffer.string_to_right_of_caret();
match maybe_char_to_right_of_caret {
Some(right_of_caret_seg_string) => {
let chunk_to_right_of_caret_gcs = right_of_caret_seg_string.string;
match chunk_to_right_of_caret_gcs.contains_wide_segments() {
ContainsWideSegments::Yes => {
let jump_by_col_width = chunk_to_right_of_caret_gcs
.display_width
+ unicode_width_at_caret;
let move_left_by_amt =
chunk_to_right_of_caret_gcs.display_width;
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::inc_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
jump_by_col_width,
max_display_width,
buffer_mut.inner.vp.col_width,
);
}
if move_left_by_amt > width(0) {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::dec_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
move_left_by_amt,
);
}
}
}
ContainsWideSegments::No => {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::inc_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
unicode_width_at_caret,
max_display_width,
buffer_mut.inner.vp.col_width,
);
}
}
}
}
None => {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::inc_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
unicode_width_at_caret,
max_display_width,
buffer_mut.inner.vp.col_width,
);
}
}
}
None
}
pub fn right_at_end(buffer: &mut EditorBuffer, engine: &mut EditorEngine) {
if buffer.next_line_below_caret_to_string().is_some() {
{
let buffer_mut = buffer.get_mut(engine.viewport());
scroll_editor_content::inc_caret_row(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
buffer_mut.inner.vp.row_height,
);
scroll_editor_content::reset_caret_col(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
);
}
}
}
}
}
pub fn left(
buffer: &mut EditorBuffer,
editor: &mut EditorEngine,
sel_mod: SelectMode,
) -> Option<()> {
empty_check_early_return!(buffer, @None);
let maybe_prev_caret = sel_mod.get_caret_scr_adj(buffer);
match locate_col(buffer) {
CaretColLocationInLine::AtStart => {
if buffer.prev_line_above_caret().is_some() {
{
let buffer_mut = buffer.get_mut(editor.viewport());
scroll_editor_content::dec_caret_row(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
);
}
caret_mut::to_end_of_line(buffer, editor, SelectMode::Disabled);
}
}
CaretColLocationInLine::AtEnd => {
let seg_slice = buffer.string_at_end_of_line_at_caret_scr_adj()?;
{
let buffer_mut = buffer.get_mut(editor.viewport());
scroll_editor_content::dec_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
seg_slice.width,
);
}
}
CaretColLocationInLine::InMiddle => {
let left_seg_string = buffer.string_to_left_of_caret()?;
{
let buffer_mut = buffer.get_mut(editor.viewport());
scroll_editor_content::dec_caret_col_by(
buffer_mut.inner.caret_raw,
buffer_mut.inner.scr_ofs,
left_seg_string.width,
);
}
}
}
let maybe_curr_caret = sel_mod.get_caret_scr_adj(buffer);
sel_mod.handle_selection_single_line_caret_movement(
buffer,
maybe_prev_caret,
maybe_curr_caret,
);
None
}