As you can see the combination “nxxn” works fine but in “oxxn” the second “x” is wrong.
Funnily, with “s” everything works as it should, even though I don’t think I did anything different there.
Any ideas what I might have done wrong?
Thanks!

# BEGIN POSITIONAL ALTERNATES
lookup IsolForms {
ignore sub @isolDef' @AllLetters, @AllLetters @isolDef';
sub @isolDef' by @isolSub;
} IsolForms;
lookup InitForms {
ignore sub @AllLetters @initDef';
sub @initDef' by @initSub;
} InitForms;
lookup InitForms2 {
sub @Uppercase @initDef' by @initSub;
} InitForms2;
lookup InitForms3 {
sub @DisconnectedLowercase @initDef' by @initSub;
} InitForms3;
lookup FinaForms {
ignore sub @finaDef' @AllLetters;
sub @finaDef' by @finaSub;
} FinaForms;
lookup Finaforms2 {
sub @finaDef' @Uppercase by @finaSub;
} Finaforms2;
# END POSITIONAL ALTERNATES

When you’re going through the sequence n x x n, first the renderer deals with a sequence n x, subsituting, say, x.connectedonleft for x. Then the next sequence is x.connectedonleft x, and you don’t want a substitution there, and you’re (correctly) not getting one.

In the sequence o x x o, I suppose o is not in @DisconnectedLowercase, so you get no substitution of x. So the next sequence dealt with is x x, and if x is in @DisconnectedLowercase you’ll get the substitution of the second x–which you don’t want.

What I don’t understand is also why this doesn’t happen with “s”.
“o” is in @DisconnectedLowercase.
Let me show you what else is there.

@DisconnectedLowercase:
b eng eth f f_j.liga g gbreve gcommaaccent gdotaccent j ldot o oacute ocircumflex odieresis ograve ohungarumlaut omacron oslash otilde p q s sacute scaron scedilla scommaaccent s.init s.isol sacute.init scaron.init scommaaccent.init v w wacute wcircumflex wdieresis wgrave x y yacute ydieresis ycircumflex ygrave z zacute zcaron zdotaccent z.init zacute.init zcaron.init zdotaccent.init

So these glyphs are in @DisconnectedLowercase: o x

And these are not: a n

In the sequence o x x o the renderer will first encounter the pair o x and, applying your InitForms3 lookup, will make it (say) o x.alt.

Then the renderer moves along not to x x but to x.alt x. Since x.alt is not in @DisconnectedLowercase, InitForms3 will not make a substitution for the second x. But all the other lookups are also consulted for x.alt x. So a lot depends on what is in @AllLetters, @isolDef and @initDef. For example, if x.alt is not in @AllLetters and xis in @initDef, a substitution will be made for the second x by your InitForms lookup.

More abstractly, remember that given a sequence

1 2 3 4

The renderer will (a) deal with 1 2, sorting through the lookups till it finds one that applies, then will (b) deal with 2 3 as modified by (a), then deal with 3 4 as modified by (a) and (b), and so on.

I can’t be sure how these considerations apply without seeing all your classes, but it seems to me that everything depends on what’s in those classes.