In forms.IsAccel I suspect an bug, which manifests in very rare cases only:
position := UTF8Pos(AmpersandChar, ACaption);
This is the position of the &...
UTF8Delete(ACaption, 1, position+1);This IMO removes the character *after* the ampersand, so that
position := UTF8Pos(AmpersandChar, ACaption);finds the same & over and over again, while it should find the next one.
Now for some questionable constructs:
A simple Pos would be sufficient, because '&' is an ASCII character.
It would be sufficient to replace the found '&' by something else, in place.
Or a loop until the last char could be used, which eliminates any string time and memory consuming string manipulation.
DoDi
