I found the relevant and buggy code in
HostCFrames.HandleCommand/Update
and I also found THE solution (after extensively trying dead ends).
Any Update of a selection box while it is performing a sequence of notifier calls to
sync with an editing operation must be delayed, i.e. there must be an Update after the
editing operation has been finished. This also improves the runtime behavior from quadratic to linear!
Two boolean flags need to be introduced in the SelectionBox:
Code: Select all
SelectionBox = POINTER TO RECORD (StdCFrames.SelectionBox)
i: Info;
num: INTEGER;
delayUpdate, needsUpdate: BOOLEAN <== new code required
END;
Update must be delayed:
Code: Select all
PROCEDURE (f: SelectionBox) Update;
VAR res, i, j, a, b: INTEGER; sel: BOOLEAN;
BEGIN
IF f.delayUpdate THEN f.needsUpdate := TRUE; RETURN END; <== new code required
...
The notifier loop must be protected from Update in HandleCommand for SelectionBox:
Code: Select all
c.delayUpdate := TRUE; c.needsUpdate := FALSE; <== new code required
i := 0;
WHILE i < c.num DO
j := i;
res := WinApi.SendMessageW(c.i.ctrl, WinApi.LB_GETSEL, j, 0);
IF c.sorted THEN j := WinApi.SendMessageW(c.i.ctrl, WinApi.LB_GETITEMDATA, j, 0) END;
c.Get(c, j, b);
IF (res # 0) & ~b THEN c.Incl(c, j, j)
ELSIF (res = 0) & b THEN c.Excl(c, j, j)
END;
INC(i)
END;
c.delayUpdate := FALSE; <== new code required
IF c.needsUpdate THEN c.Update END <== new code required
This change is not a workaround as my previous proposal was and also luowy's improvement is.
It is a true fix of the problem that works for any selection box and it does not require the special
rule that a selection box notifier must not call Dialog.Update for its own interactor.
With the solution found I think it is time to file an issue.
- Josef