// SPDX-License-Identifier: MIT // Copyright (c) 2021 KikooDX // This file is part of [KBLE](https://sr.ht/~kikoodx/kble), which is // MIT licensed. The MIT license requires this copyright notice to be // included in all copies and substantial portions of the software. //! Movement functions. const std = @import("std"); const expect = std.testing.expect; const maxInt = std.math.maxInt; const Parameter = @import("parameter.zig"); const Vec2 = @import("vec2.zig"); const Rect = @import("rect.zig"); const maxIntVec2 = comptime maxInt(Vec2.int_type); /// Describe changes to make on selection. pub const SelectionUpdate = struct { active: bool, area: Rect, state: bool, }; /// Universal move system, prefer direction wrappers. fn move(cursor: *Vec2, arg: Parameter.buffer_type, dx: i2, dy: i2) SelectionUpdate { const before: Vec2 = cursor.*; if (dx > 0) { var i: Parameter.buffer_type= 0; while (i != arg and cursor.x < maxIntVec2) : (i += 1) { cursor.x += 1; } } else if (dx < 0) { var i: Parameter.buffer_type= 0; while (i != arg and cursor.x > 0) : (i += 1) { cursor.x -= 1; } } if (dy > 0) { var i: Parameter.buffer_type= 0; while (i != arg and cursor.y < maxIntVec2) : (i += 1) { cursor.y += 1; } } else if (dy < 0) { var i: Parameter.buffer_type= 0; while (i != arg and cursor.y > 0) : (i += 1) { cursor.y -= 1; } } return SelectionUpdate{ .active = true, .area = Rect.init_from_vec2(before, cursor.*), .state = true, }; } /// Just don't move. pub fn move_but_dont(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 0, 0); } /// Try to move the cursor `n` times left. pub fn move_left(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, -1, 0); } /// Try to move the cursor `n` times right. pub fn move_right(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 1, 0); } /// Try to move the cursor `n` times up. pub fn move_up(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 0, -1); } /// Try to move the cursor `n` times down. pub fn move_down(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 0, 1); } /// Try to move the cursor `n` times up and left. pub fn move_up_left(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, -1, -1); } /// Try to move the cursor `n` times up and right. pub fn move_up_right(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 1, -1); } /// Try to move the cursor `n` times down and left. pub fn move_down_left(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, -1, 1); } /// Try to move the cursor `n` times down and right. pub fn move_down_right(cursor: *Vec2, arg: Parameter.buffer_type) SelectionUpdate { return move(cursor, arg, 1, 1); } test "move left" { var cursor = Vec2.init(42, 51); _ = move_left(&cursor, 2, false); expect(cursor.x == 40); _ = move_left(&cursor, 38, false); expect(cursor.x == 2); _ = move_left(&cursor, maxIntVec2, false); expect(cursor.x == 0); } test "move right" { var cursor = Vec2.init(564, 42); _ = move_right(&cursor, 51, false); expect(cursor.x == 615); _ = move_right(&cursor, maxIntVec2, false); expect(cursor.x == maxIntVec2); }