M edit.lua => edit.lua +26 -13
@@ 192,7 192,7 @@ function edit.mouse_press(State, x,y, mouse_button)
end
end
- -- still here? click is below all screen lines
+ -- still here? mouse press is below all screen lines
State.old_cursor1 = State.cursor1
State.old_selection1 = State.selection1
State.mousepress_shift = App.shift_down()
@@ 205,6 205,11 @@ end
function edit.mouse_release(State, x,y, mouse_button)
if State.search_term then return end
--? print_and_log(('edit.mouse_release(%d,%d): cursor at %d,%d'):format(x,y, State.cursor1.line, State.cursor1.pos))
+ if y < State.top then
+ State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
+ edit.clean_up_mouse_press(State)
+ return
+ end
for line_index,line in ipairs(State.lines) do
if Text.in_line(State, line_index, x,y) then
--? print_and_log(('edit.mouse_release: in line %d'):format(line_index))
@@ 213,23 218,31 @@ function edit.mouse_release(State, x,y, mouse_button)
pos=Text.to_pos_on_line(State, line_index, x, y),
}
--? print_and_log(('edit.mouse_release: cursor now %d,%d'):format(State.cursor1.line, State.cursor1.pos))
- if State.mousepress_shift then
- if State.old_selection1.line == nil then
- State.selection1 = State.old_cursor1
- else
- State.selection1 = State.old_selection1
- end
- end
- State.old_cursor1, State.old_selection1, State.mousepress_shift = nil
- if eq(State.cursor1, State.selection1) then
- State.selection1 = {}
- end
- break
+ edit.clean_up_mouse_press(State)
+ return
end
end
+
+ -- still here? mouse release is below all screen lines
+ State.cursor1.line, State.cursor1.pos = State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
+ edit.clean_up_mouse_press(State)
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
end
+function edit.clean_up_mouse_press(State)
+ if State.mousepress_shift then
+ if State.old_selection1.line == nil then
+ State.selection1 = State.old_cursor1
+ else
+ State.selection1 = State.old_selection1
+ end
+ end
+ State.old_cursor1, State.old_selection1, State.mousepress_shift = nil
+ if eq(State.cursor1, State.selection1) then
+ State.selection1 = {}
+ end
+end
+
function edit.mouse_wheel_move(State, dx,dy)
if dy > 0 then
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
M source_edit.lua => source_edit.lua +27 -13
@@ 295,7 295,7 @@ function edit.mouse_press(State, x,y, mouse_button)
end
end
- -- still here? click is below all screen lines
+ -- still here? mouse press is below all screen lines
State.old_cursor1 = State.cursor1
State.old_selection1 = State.selection1
State.mousepress_shift = App.shift_down()
@@ 317,6 317,12 @@ function edit.mouse_release(State, x,y, mouse_button)
end
else
--? print_and_log('edit.mouse_release: no current drawing')
+ if y < State.top then
+ State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
+ edit.clean_up_mouse_press(State)
+ return
+ end
+
for line_index,line in ipairs(State.lines) do
if line.mode == 'text' then
if Text.in_line(State, line_index, x,y) then
@@ 326,25 332,33 @@ function edit.mouse_release(State, x,y, mouse_button)
pos=Text.to_pos_on_line(State, line_index, x, y),
}
--? print_and_log(('edit.mouse_release: cursor now %d,%d'):format(State.cursor1.line, State.cursor1.pos))
- if State.mousepress_shift then
- if State.old_selection1.line == nil then
- State.selection1 = State.old_cursor1
- else
- State.selection1 = State.old_selection1
- end
- end
- State.old_cursor1, State.old_selection1, State.mousepress_shift = nil
- if eq(State.cursor1, State.selection1) then
- State.selection1 = {}
- end
- break
+ edit.clean_up_mouse_press(State)
+ return
end
end
end
+
+ -- still here? mouse release is below all screen lines
+ State.cursor1.line, State.cursor1.pos = State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
+ edit.clean_up_mouse_press(State)
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
end
end
+function edit.clean_up_mouse_press(State)
+ if State.mousepress_shift then
+ if State.old_selection1.line == nil then
+ State.selection1 = State.old_cursor1
+ else
+ State.selection1 = State.old_selection1
+ end
+ end
+ State.old_cursor1, State.old_selection1, State.mousepress_shift = nil
+ if eq(State.cursor1, State.selection1) then
+ State.selection1 = {}
+ end
+end
+
function edit.mouse_wheel_move(State, dx,dy)
if dy > 0 then
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
M source_text_tests.lua => source_text_tests.lua +24 -0
@@ 275,6 275,7 @@ function test_click_to_left_of_line()
Editor_state.cursor1 = {line=1, pos=3}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click to the left of the line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left-4,Editor_state.top+5, 1)
@@ 294,6 295,7 @@ function test_click_takes_margins_into_account()
Editor_state.cursor1 = {line=2, pos=1}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click on the other line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
@@ 312,11 314,33 @@ function test_click_on_empty_line()
Editor_state.cursor1 = {line=2, pos=1}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click on the empty line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
-- cursor moves
check_eq(Editor_state.cursor1.line, 1, 'cursor')
+ -- selection remains empty
+ check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
+end
+
+function test_click_below_all_lines()
+ -- display one line
+ App.screen.init{width=50, height=80}
+ Editor_state = edit.initialize_test_state()
+ Editor_state.lines = load_array{'abc'}
+ Text.redraw_all(Editor_state)
+ Editor_state.cursor1 = {line=1, pos=1}
+ Editor_state.screen_top1 = {line=1, pos=1}
+ Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
+ -- click below first line
+ edit.draw(Editor_state)
+ edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+50, 1)
+ -- cursor doesn't move
+ check_eq(Editor_state.cursor1.line, 1, 'cursor')
+ -- selection remains empty
+ check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
end
function test_draw_text()
M text_tests => text_tests +1 -0
@@ 23,6 23,7 @@ click on wrapping line rendered from partway at top of screen
click past end of wrapping line
click past end of wrapping line containing non ascii
click past end of word wrapping line
+click below final line does nothing
# cursor movement
move left
M text_tests.lua => text_tests.lua +24 -0
@@ 249,6 249,7 @@ function test_click_to_left_of_line()
Editor_state.cursor1 = {line=1, pos=3}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click to the left of the line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left-4,Editor_state.top+5, 1)
@@ 268,6 269,7 @@ function test_click_takes_margins_into_account()
Editor_state.cursor1 = {line=2, pos=1}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click on the other line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
@@ 286,11 288,33 @@ function test_click_on_empty_line()
Editor_state.cursor1 = {line=2, pos=1}
Editor_state.screen_top1 = {line=1, pos=1}
Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
-- click on the empty line
edit.draw(Editor_state)
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
-- cursor moves
check_eq(Editor_state.cursor1.line, 1, 'cursor')
+ -- selection remains empty
+ check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
+end
+
+function test_click_below_all_lines()
+ -- display one line
+ App.screen.init{width=50, height=80}
+ Editor_state = edit.initialize_test_state()
+ Editor_state.lines = load_array{'abc'}
+ Text.redraw_all(Editor_state)
+ Editor_state.cursor1 = {line=1, pos=1}
+ Editor_state.screen_top1 = {line=1, pos=1}
+ Editor_state.screen_bottom1 = {}
+ Editor_state.selection1 = {}
+ -- click below first line
+ edit.draw(Editor_state)
+ edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+50, 1)
+ -- cursor doesn't move
+ check_eq(Editor_state.cursor1.line, 1, 'cursor')
+ -- selection remains empty
+ check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
end
function test_draw_text()