diff --git a/src/main.odin b/src/main.odin index d63c6bc..a00053c 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,7 +1,7 @@ /* - DONE implement movement up and down by paragraph - DONE implement scrolling/viewport -- TODO implement deletion by word +- DONE implement deletion by word - TODO implement selection - TODO implement duplicate selection/line - TODO implement move selection/line up/down @@ -37,6 +37,14 @@ Cursor :: struct { char: int, } +Selection :: struct { + active: bool, + start_line: int, + end_line: int, + start_char: int, + end_char: int, +} + window_width := 800 window_height := 600 font_size: f32 = 20.0 @@ -48,6 +56,7 @@ viewport := Viewport { start = 0, end = viewport_size, } +selection := Selection{} main :: proc() { r.InitWindow(i32(window_width), i32(window_height), "odit") @@ -76,78 +85,7 @@ main :: proc() { cursor.char += 1 } - if repeatable_key_pressed(r.KeyboardKey.RIGHT) { - preferred_position := cursor.char + 1 - if cursor.char == len(current_line()) && cursor.line != len(lines) - 1 { - cursor.char = 0 - cursor.line += 1 - } - if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && cursor.char + 1 < len(current_line()) { - seen_space := false - for c, c_index in current_line()[cursor.char + 1:] { - if seen_space && !is_whitespace(c) { - preferred_position = cursor.char + c_index - break - } - if is_whitespace(c) { - seen_space = true - } - } - if !seen_space { - preferred_position = len(current_line()) - } - } - cursor.char = min(preferred_position, len(current_line())) - } - - if repeatable_key_pressed(r.KeyboardKey.LEFT) { - preferred_position := cursor.char - 1 - if cursor.char == 0 && cursor.line != 0 { - cursor.line -= 1 - cursor.char = len(current_line()) - } - if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && 0 < cursor.char { - found := false - preferred_position, found = find_previous_space(cursor.char, current_line()[:]) - } - cursor.char = max(preferred_position, 0) - } - - if repeatable_key_pressed(r.KeyboardKey.UP) { - preferred_line := cursor.line - 1 - - if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && 0 < cursor.line { - #reverse for l, l_index in lines[:cursor.line] { - if len(l) == 0 || all_whitespace(l[:]) { - preferred_line = l_index - break - } - } - } - - cursor.line = max(0, preferred_line) - if len(current_line()) < cursor.char { - cursor.char = len(current_line()) - } - } - - if repeatable_key_pressed(r.KeyboardKey.DOWN) { - preferred_line := cursor.line + 1 - - if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && cursor.line + 1 < len(lines) { - for l, l_index in lines[cursor.line + 1:] { - if len(l) == 0 || all_whitespace(l[:]) { - preferred_line = cursor.line + l_index + 1 - break - } - } - } - - cursor.line = min(preferred_line, len(lines) - 1) - if len(current_line()) < cursor.char { - cursor.char = len(current_line()) - } - } + move_cursor() if repeatable_key_pressed(r.KeyboardKey.ENTER) { new_line_cap := len(current_line()) - cursor.char @@ -288,3 +226,105 @@ find_previous_space :: proc(current_position: int, line: []u8) -> (result: int, return result, found } + +handle_selection_start :: proc() { + was_active := selection.active + if r.IsKeyDown(r.KeyboardKey.LEFT_SHIFT) { + selection.active = true + } else { + selection = {} + return + } + if selection.active && was_active do return + selection.start_line = cursor.line + selection.start_char = cursor.char +} + +handle_selection_end :: proc() { + if !selection.active do return + selection.end_char = cursor.char + selection.end_line = cursor.line +} + +move_cursor :: proc() { + if repeatable_key_pressed(r.KeyboardKey.RIGHT) { + handle_selection_start() + defer handle_selection_end() + preferred_position := cursor.char + 1 + if cursor.char == len(current_line()) && cursor.line != len(lines) - 1 { + cursor.char = 0 + cursor.line += 1 + } + if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && cursor.char + 1 < len(current_line()) { + seen_space := false + for c, c_index in current_line()[cursor.char + 1:] { + if seen_space && !is_whitespace(c) { + preferred_position = cursor.char + c_index + break + } + if is_whitespace(c) { + seen_space = true + } + } + if !seen_space { + preferred_position = len(current_line()) + } + } + cursor.char = min(preferred_position, len(current_line())) + } + + if repeatable_key_pressed(r.KeyboardKey.LEFT) { + handle_selection_start() + defer handle_selection_end() + preferred_position := cursor.char - 1 + if cursor.char == 0 && cursor.line != 0 { + cursor.line -= 1 + cursor.char = len(current_line()) + } + if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && 0 < cursor.char { + found := false + preferred_position, found = find_previous_space(cursor.char, current_line()[:]) + } + cursor.char = max(preferred_position, 0) + } + + if repeatable_key_pressed(r.KeyboardKey.UP) { + handle_selection_start() + defer handle_selection_end() + preferred_line := cursor.line - 1 + + if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && 0 < cursor.line { + #reverse for l, l_index in lines[:cursor.line] { + if len(l) == 0 || all_whitespace(l[:]) { + preferred_line = l_index + break + } + } + } + + cursor.line = max(0, preferred_line) + if len(current_line()) < cursor.char { + cursor.char = len(current_line()) + } + } + + if repeatable_key_pressed(r.KeyboardKey.DOWN) { + handle_selection_start() + defer handle_selection_end() + preferred_line := cursor.line + 1 + + if r.IsKeyDown(r.KeyboardKey.LEFT_ALT) && cursor.line + 1 < len(lines) { + for l, l_index in lines[cursor.line + 1:] { + if len(l) == 0 || all_whitespace(l[:]) { + preferred_line = cursor.line + l_index + 1 + break + } + } + } + + cursor.line = min(preferred_line, len(lines) - 1) + if len(current_line()) < cursor.char { + cursor.char = len(current_line()) + } + } +}