about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--edit.lua39
-rw-r--r--source_edit.lua40
-rw-r--r--source_text_tests.lua24
-rw-r--r--text_tests1
-rw-r--r--text_tests.lua24
5 files changed, 102 insertions, 26 deletions
diff --git a/edit.lua b/edit.lua
index 446d76d..56f3f10 100644
--- a/edit.lua
+++ b/edit.lua
@@ -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}
diff --git a/source_edit.lua b/source_edit.lua
index 310853a..2bf0697 100644
--- a/source_edit.lua
+++ b/source_edit.lua
@@ -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}
diff --git a/source_text_tests.lua b/source_text_tests.lua
index c2e054a..2dc3adb 100644
--- a/source_text_tests.lua
+++ b/source_text_tests.lua
@@ -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()
diff --git a/text_tests b/text_tests
index f39d47e..2a31131 100644
--- a/text_tests
+++ b/text_tests
@@ -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
diff --git a/text_tests.lua b/text_tests.lua
index ccbc9be..86d602b 100644
--- a/text_tests.lua
+++ b/text_tests.lua
@@ -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()