about summary refs log tree commit diff stats
path: root/edit.lua
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2023-09-20 13:39:29 -0700
committerKartik K. Agaram <vc@akkartik.com>2023-09-20 13:39:29 -0700
commitbd6f7d48e76182218877564e8ca672e657f4ef56 (patch)
treee2ed5bd8592ad604612fb2d8f1b49079b0103ae0 /edit.lua
parentc43d884b6ffb94803bee9f9e788e4b3a2f74f23b (diff)
downloadview.love-bd6f7d48e76182218877564e8ca672e657f4ef56.tar.gz
bugfix: clear selection when clicking above or below lines
Matt Wynne pointed out that snap.love would crash when a node went off
screen. While debugging it I noticed that selection1 was being set when
it shouldn't be.

Turns out I introduced a bug when I fixed the inscript bug back in June
(commit 9656e137742). One invariant I want to preserve is: selection1
should be unset after a mouse click (press and release without
intervening drag). This invariant was violated in my bugfix back in
June. I was concerned only with selection back then, and I didn't
realize I was breaking the mouse click case (in a fairly subtle way; you
can have selection set, and when it's set identically to the cursor
everything looks the same).

I think there might still be an issue in snap.love after this fix. I
noticed screen_bottom1.pos was nil, and as far as I recall that should
never happen.
Diffstat (limited to 'edit.lua')
-rw-r--r--edit.lua40
1 files changed, 27 insertions, 13 deletions
diff --git a/edit.lua b/edit.lua
index 45588df..7d3c26f 100644
--- a/edit.lua
+++ b/edit.lua
@@ -291,7 +291,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()
@@ -313,6 +313,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
@@ -322,25 +328,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}