Skip to content

Commit

Permalink
fix: fixed incorrect CURSOR ON impl, and compiler.lua CURSOR codegen. (
Browse files Browse the repository at this point in the history
…#436)

Also changed how opl.lua CURSOR() API works, similarly iohandler
textEditor(), so the CURSOR OPL API actually works (rather than just the
opl.lua CURSOR() API).
  • Loading branch information
tomsci authored Sep 30, 2024
1 parent 327f41a commit 03f3951
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 67 deletions.
Binary file added examples/Tests/cursor.opo
Binary file not shown.
17 changes: 17 additions & 0 deletions examples/Tests/cursor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
DECLARE EXTERNAL
INCLUDE "const.oph"

PROC main:
REM text cursor
PRINT "Hello";
CURSOR ON
GET

REM graphics cursor
gAT 50, 50
gFONT KFontArialNormal32&
gPRINT "Hello"
CURSOR gIDENTITY
gUPDATE
GET
ENDP
Binary file modified examples/Tests/dialog.opo
Binary file not shown.
13 changes: 12 additions & 1 deletion examples/Tests/dialog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ PROC fileDlg:
GET
ENDP

PROC emptyChoiceDlg:
LOCAL ch%
dINIT "Empty choice list dialog"
dCHOICE ch%, "Choose", ""
PRINT DIALOG
GET
ENDP


PROC loop%:
LOCAL dlg%
EXTERNAL choice%
Expand All @@ -236,7 +245,7 @@ PROC loop%:
dCHOICE choice%, "Choose", "long,float,edit,checkbox,text,..."
dCHOICE choice%, "", "password,empty,date,time,..."
dCHOICE choice%, "", "buttons,bareButtons,cancelDlg,..."
dCHOICE choice%, "", "editmulti,file"
dCHOICE choice%, "", "editmulti,file,emptychoice"
dBUTTONS "OK", 13, "Cancel", -(512 + %q)
choice% = 2
dlg% = DIALOG
Expand Down Expand Up @@ -274,6 +283,8 @@ PROC loop%:
editMultiDlg:
ELSEIF choice% = 14
fileDlg:
ELSEIF choice% = 15
emptyChoiceDlg:
ENDIF

RETURN 1
Expand Down
7 changes: 6 additions & 1 deletion src/compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2271,7 +2271,12 @@ function handleOp_CURSOR(procState)
for i, arg in ipairs(args) do
procState:emitExpression(arg, declArgs[i])
end
qualifier = #args - 1
-- This command is unusual in how qualifier is used...
if #args == 1 then
qualifier = 2
else
qualifier = #args - 1 -- ie 3 or 4
end
end
procState:emit("BB", opcodes.Cursor, qualifier)
if args then
Expand Down
35 changes: 20 additions & 15 deletions src/dialog.lua
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,8 @@ end

function DialogItemEdit:updateCursorIfFocussed()
if self.hasFocus then
gAT(self:getCursorPos())
local _, h, ascent = gTWIDTH("", kDialogFont)
CURSOR(gIDENTITY(), ascent + 1, self.cursorWidth, h + 1)
local x, y = self:getCursorPos()
CURSOR(gIDENTITY(), x, y, self.cursorWidth, self.charh + 1)
end
end

Expand Down Expand Up @@ -450,7 +449,7 @@ function DialogItemEdit:setFocus(flag)
-- When focussed, the draw call triggered by View.setFocus takes care of calling CURSOR (via updateCursorIfFocussed)
self:updateIohandler()
else
CURSOR(false)
CURSOR(nil)
runtime:iohandler().textEditor(nil)
end
end
Expand All @@ -467,19 +466,27 @@ function DialogItemEdit:onEditorChanged()
end

function DialogItemEdit:updateIohandler()
local origx, origy = gORIGINX(), gORIGINY()
local rect = {
x = origx + self.x + self.promptWidth,
y = origy + self.y,
x = self.x + self.promptWidth,
y = self.y,
w = self.w - self.promptWidth,
h = self.h,
}
local cursorx, cursory = self:getCursorPos()
-- The cursor might not actually be showing at this point (eg when DialogItemPartEditor supresses the cursor) but
-- this is where it _should_ be.
local cursorRect = {
x = cursorx,
y = cursory,
w = self.cursorWidth,
h = self.charh + 1, -- This is not quite correct for DialogItemEditMulti but it doesn't really matter
}
runtime:iohandler().textEditor({
id = gIDENTITY(),
rect = rect,
contents = self.editor.value,
type = self:inputType(),
cursorPos = self.editor.cursorPos - 1, -- Zero based for native code
cursorRect = cursorRect,
})
end

Expand Down Expand Up @@ -801,7 +808,7 @@ function DialogItemPartEditor:updateCursorIfFocussed()
if self.editor:hasSelection() then
-- We don't show a cursor when there's a selection (because a selection is used to indicate the entry is
-- complete).
CURSOR(false)
CURSOR(nil)
else
DialogItemEdit.updateCursorIfFocussed(self)
end
Expand Down Expand Up @@ -1349,12 +1356,10 @@ function DialogItemEditMulti:updateCursorIfFocussed()
if self.hasFocus then
local x, y = self:getCursorPos()
if x then
gAT(x, y)
local _, _, ascent = gTWIDTH("", kDialogFont)
CURSOR(gIDENTITY(), ascent + 1, self.cursorWidth, self:lineHeight())
CURSOR(gIDENTITY(), x, y, self.cursorWidth, self:lineHeight())
else
-- Cursor not visible in the currently shown lines
CURSOR(false)
CURSOR(nil)
end
end
end
Expand Down Expand Up @@ -1543,8 +1548,8 @@ function DialogChoiceList:draw()
black()

if self.typeable and self.hasFocus then
gAT(x + self.choiceTextSpace + gTWIDTH(text:sub(1, self.cursorPos - 1)), texty)
CURSOR(gIDENTITY(), nil, gTWIDTH(text:sub(self.cursorPos, self.cursorPos)))
local cursorx = x + self.choiceTextSpace + gTWIDTH(text:sub(1, self.cursorPos - 1))
CURSOR(gIDENTITY(), cursorx, texty, gTWIDTH(text:sub(self.cursorPos, self.cursorPos)))
end

View.draw(self)
Expand Down
53 changes: 17 additions & 36 deletions src/opl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -695,46 +695,27 @@ function BUSY(text, corner, delay)
runtime:restoreGraphicsState(state)
end

function CURSOR(id, asc, w, h, t)
-- printf("CURSOR id=%s, asc=%s, w=%s, h=%s, t=%s\n", id, asc, w, h, t)
-- Unlike the OPL CURSOR command, the x and y coordinates are explicit and indicate the top left of the cursor.
-- Therefore, no ascent parameter is necessary.
function CURSOR(id, x, y, w, h, t)
-- printf("CURSOR id=%s, x=%s, y=%s, w=%s, h=%s, t=%s\n", id, x, y, w, h, t)
runtime:flushGraphicsOps()
local cursor = runtime:getResource("cursor")
if id == false then
if id == nil then
if cursor then
cursor.shown = false
end
runtime:iohandler().graphicsop("cursor", nil)
elseif id == true then
if cursor == nil then
-- What happens if you get a CURSOR ON without any previous config?
return
end
if not cursor.shown then
cursor.shown = true
runtime:iohandler().graphicsop("cursor", cursor)
end
else
local fontw, fonth, fontAscent
if not h or not asc then
fontw, fonth, fontAscent = runtime:gTWIDTH("0")
end
if not asc then
asc = fontAscent
end
if not w then
w = 2
end
if not h then
h = fonth
end
if not t then
t = 0
end
local win = assert(runtime:getGraphicsContext(id), "Bad id for CURSOR")
assert(win.isWindow, "Cannot call CURSOR on a bitmap")

if cursor and cursor.shown and id == cursor.id and asc == cursor.ascent
and win.pos.x == cursor.rect.x and win.pos.y == cursor.rect.y
if t == nil then
t = 0
end

if cursor and cursor.shown and id == cursor.id
and x == cursor.rect.x and y == cursor.rect.y
and w == cursor.rect.w and h == cursor.rect.h and t == cursor.flags then
-- Cursor has not moved or changed, don't interrupt the timing
return
Expand All @@ -745,14 +726,14 @@ function CURSOR(id, asc, w, h, t)
runtime:setResource("cursor", cursor)
end
cursor.id = id
cursor.ascent = asc or fontAscent
cursor.shown = true
cursor.rect = {
x = win.pos.x,
y = win.pos.y,
w = w or 2,
h = h or fonth,
x = x,
y = y,
w = w,
h = h,
}
cursor.flags = t or 0
cursor.flags = t
runtime:iohandler().graphicsop("cursor", cursor)
end
end
Expand Down
38 changes: 27 additions & 11 deletions src/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1471,21 +1471,37 @@ function Create_dump(runtime)
end

function Cursor(stack, runtime) -- 0xA6
local numParams = runtime:IP8()
if numParams == 0 then
runtime:CURSOR(false)
elseif numParams == 1 then
runtime:CURSOR(true)
local immediate = runtime:IP8()
if immediate == 0 then
-- CURSOR OFF
runtime:CURSOR(nil)
elseif immediate == 1 then
-- CURSOR ON means text cursor, in the default window
local screen = runtime:getGraphics().screen
local x = screen.x + (screen.cursorx * screen.charw)
local y = screen.y + (screen.cursory * screen.charh)
runtime:CURSOR(KDefaultWin, x, y, screen.charw, screen.charh)
else
-- CURSOR <window> [, ascent, width, height [, type]
local t = nil
if numParams == 4 then
if immediate == 4 then
t = stack:pop()
else
assert(numParams == 3, "Bad immediate after Cursor!")
end
-- numParams doesn't include id...
local id, asc, w, h = stack:pop(4)
runtime:CURSOR(id, asc, w, h, t)
local asc, w, h
if immediate >= 3 then
asc, w, h = stack:pop(3)
end
local id = stack:pop()

if asc == nil then
local _
_, h, asc = runtime:gTWIDTH("")
w = 2
end
local context = runtime:getGraphicsContext(id)
local x = context.pos.x
local y = context.pos.y - asc
runtime:CURSOR(id, x, y, w, h, t)
end
end

Expand Down
5 changes: 2 additions & 3 deletions swift/OpoIoHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,6 @@ public struct Graphics {
public struct Cursor: Codable {
let id: DrawableId
let rect: Rect
let ascent: Int
let flags: FlagSet<CursorFlag>
}

Expand Down Expand Up @@ -544,9 +543,9 @@ public struct TextFieldInfo: Codable {
}
let id: Graphics.DrawableId
let type: InputType
let rect: Graphics.Rect
let rect: Graphics.Rect? // bounding rect of the whole text field, in id's coords, if available
let contents: String
let cursorPos: Int
let cursorRect: Graphics.Rect // location of cursor, in coords of id
}

public protocol FileSystemIoHandler {
Expand Down

0 comments on commit 03f3951

Please sign in to comment.