Some of this was working in assumptions about the menu bar, but it was also just wrong before, not taking the zoom factor into account. As before, I'm not very good at reasoning in pixels.
MAUOADNV62ZEWXWUTNJPVNWE6IFEDN23F6S5YVWW743EQJQ6NNVAC
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
-- Compute screen_top1 in viewport coordinates because the editor's font takes scaling into account.
if vy(node.y) > 0 then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, -vy(node.y))
end
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"scale":7,"on.mouse_press":179,"on.mouse_release":367,"font":353,"initialize_editor":450,"copy_shape":396,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on":1,"on.draw":452,"Page":444,"vx":5,"on.initialize":350,"Viewport":459,"update_editor_box":473,"vy":462,"on.update":368,"y_of_schema1":364,"on.text_input":388,"parent":472,"Surface":422,"on.code_change":306,"sy":469,"B":379,"line_height":365,"to_text":180,"add_thick_line":400,"Cursor_node":172,"schema1_of_y":467,"A":433}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
-- Compute screen_top1 in viewport coordinates because the editor's font takes scaling into account.
if vy(node.y) > 0 then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, vy(node.y))
end
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"A":433,"on.draw":452,"B":379,"y_of_schema1":364,"font":353,"copy_shape":396,"Cursor_node":172,"scale":7,"add_thick_line":400,"parent":471,"Viewport":459,"on":1,"on.update":368,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"initialize_editor":450,"Page":444,"box_height":345,"on.keychord_press":391,"compute_layout":385,"sy":469,"vx":5,"on.code_change":306,"update_editor_box":472,"on.text_input":388,"line_height":365,"to_text":180,"vy":462,"Surface":422,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
-- Compute screen_top1 in viewport coordinates because the editor's font takes scaling into account.
if vy(node.y) > Menu_bar_height - 5 then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, vy(node.y))
end
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"A":433,"on.draw":452,"B":379,"y_of_schema1":364,"font":353,"copy_shape":396,"Cursor_node":172,"scale":7,"add_thick_line":400,"parent":470,"Viewport":459,"on":1,"on.update":368,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"initialize_editor":450,"Page":444,"box_height":345,"on.keychord_press":391,"compute_layout":385,"sy":469,"vx":5,"on.code_change":306,"update_editor_box":471,"on.text_input":388,"line_height":365,"to_text":180,"vy":462,"Surface":422,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, vy(node.y))
end
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"sy":469,"Surface":422,"Page":444,"parent":469,"to_text":180,"update_editor_box":470,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
sy = function(vy)
-- turn viewport coordinates into surface coordinates
-- vy = Menu_bar_height + scale(sy-Viewport.y)
return (vy-Menu_bar_height)/Viewport.zoom + Viewport.y
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"sy":469,"Surface":422,"Page":444,"parent":468,"to_text":180,"update_editor_box":468,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":467,"to_text":180,"update_editor_box":468,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
print(y)
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#editor.lines+1, pos=1}, y_offset -- positive value
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":466,"to_text":180,"update_editor_box":466,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":467,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":465,"to_text":180,"update_editor_box":466,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top
print(node.y, Viewport.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":464,"to_text":180,"update_editor_box":465,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y - Menu_bar_height)
end
node.editor.top = node.editor.top
print(node.y, Viewport.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":463,"to_text":180,"update_editor_box":464,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y + Menu_bar_height)
end
node.editor.top = node.editor.top
print(node.y, Viewport.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":462,"to_text":180,"update_editor_box":463,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
vy = function(y)
return Menu_bar_height + scale(y-Viewport.y)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":461,"to_text":180,"update_editor_box":458,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":462,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
vy = function(y)
return Menu_bar_height + Margin_top + scale(y-Viewport.y)
end
{"line_height":365,"on.text_input":388,"box_height":345,"compute_layout":385,"font":353,"on.code_change":306,"Surface":422,"Page":444,"parent":460,"to_text":180,"update_editor_box":458,"on.initialize":350,"y_of_schema1":364,"initialize_editor":450,"on.draw":452,"copy_shape":396,"vx":5,"Viewport":459,"vy":461,"schema1_of_y":366,"on.mouse_press":179,"on.mouse_release":367,"on.update":368,"on":1,"on.keychord_press":391,"add_thick_line":400,"A":433,"scale":7,"Cursor_node":172,"B":379}
vy = function(y)
return Menu_bar_height + scale(y-Viewport.y)
end
{"line_height":365,"on.mouse_press":179,"Viewport":459,"on.text_input":388,"on":1,"on.mouse_release":367,"box_height":345,"on.update":368,"scale":7,"Cursor_node":172,"on.code_change":306,"B":379,"update_editor_box":458,"vy":460,"A":433,"schema1_of_y":366,"on.keychord_press":391,"compute_layout":385,"on.draw":452,"add_thick_line":400,"Page":444,"copy_shape":396,"initialize_editor":450,"y_of_schema1":364,"Surface":422,"on.initialize":350,"to_text":180,"parent":459,"font":353,"vx":5}
{"line_height":365,"on.mouse_press":179,"Viewport":459,"on.text_input":388,"on":1,"on.mouse_release":367,"box_height":345,"on.update":368,"scale":7,"Cursor_node":172,"on.code_change":306,"B":379,"update_editor_box":458,"vy":457,"A":433,"schema1_of_y":366,"on.keychord_press":391,"compute_layout":385,"on.draw":452,"add_thick_line":400,"Page":444,"copy_shape":396,"initialize_editor":450,"y_of_schema1":364,"Surface":422,"on.initialize":350,"to_text":180,"parent":458,"font":353,"vx":5}
Viewport = {x=0, y=0, w=800,h=600, zoom=1.0}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top
print(node.y, Viewport.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":457,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":458,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":457,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}
vy = function(y)
return scale(y-Viewport.y)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":456,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":456,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":457,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top + Menu_bar_height
print(node.y, Viewport.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":455,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":456,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":448,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top + Menu_bar_height
print(node.y, node.editor.top)
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":454,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":455,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":448,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top + Menu_bar_height
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":453,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":454,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":448,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y >= Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
end
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
node.editor.top = node.editor.top + Menu_bar_height
node.editor.left = math.floor(vx(node.x+Line_number_width))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"y_of_schema1":364,"A":433,"line_height":365,"scale":7,"B":379,"on.text_input":388,"on.mouse_release":367,"copy_shape":396,"to_text":180,"box_height":345,"parent":452,"on":1,"on.keychord_press":391,"on.update":368,"Page":444,"on.code_change":306,"update_editor_box":453,"font":353,"on.mouse_press":179,"compute_layout":385,"vy":448,"Surface":422,"add_thick_line":400,"initialize_editor":450,"on.draw":452,"schema1_of_y":366,"vx":5,"Cursor_node":172,"Viewport":439,"on.initialize":350}