Sean Healy wrote:
I tracked down the extra spaces problem. It turned out to be a space at
the end of the line (after the EOL character(s)), not at the beginning,
which is why it doesn't show up on the first line.
Here's the cause of the problem:
# How many characters are on a line, not including end of line characters?
sub LineLength {
my ($self, $line) = @_;
return $self->SendMessage (2350, $line, 0);
}
Scintilla's documentation says:
SCI_LINELENGTH(int line)
This returns the length of the line, including any line end characters. If
line is negative or beyond the last line in the document, the result is 0.
If you want the length of the line not including any end of line
characters, use SCI_GETLINEENDPOSITION(line) - SCI_POSITIONFROMLINE(line).
This confusion actually comes from the scintilla scintilla.iface
document, from which the comment in the code is extracted.
Laurent's code makes an incorrect assumption about EOL markers and
SCI_LINELENGTH. (Although it may have been correct when it was coded, and
Scintilla later changed.) Everywhere Laurent has used LineLength to get
the text at a line, he has done the following:
my $lenght = $self->LineLength($line);
my $text = " " x ($lenght + 1);
$self->SendMessageNP (2153, $line, $text);
Having had a look, I don't think it's an incorrect assumption about line
lenghts, but an incorrect assumption about terminating NUL's. Often
when calling SnedMessage to get a string it will be NUL terminated, and
so you need to make the buffer large enough toinclude this NUL, but in
this case SCI_GETLINE does not NUL terminate the string.
He has to create the buffer first, because SendMessage requires the memory
to be already allocated, so he creates a buffer of spaces. But he creates
it one byte too long, so there's a trailing space in the returned text.
I agree that the buffer is allocated one byte too long, and this is the
cause of the problems being seen.
The intermediate solution is to go to line 196 in Scintilla.pm (in the
GetLine() sub) and take out the '+1'. Then when SaveFile calls GetLine,
you won't get a trailing space.
Fine short term fix for those who want a solution before the next release.
The long-term solution is to find every place Laurent has used LineLength,
and fix it. I am willing to do this and email the fixed file to someone
with CVS access, so it will be correct in the next version. I'll test it
via SaveFile, with differrent combinations of EOL markers in source and
destination files, to make sure it really works. (I'll also fix that
annoying little misspelling in the local variable while I'm at it.)
Scintilla.pm is actually (mostly) autogenerated from scintilla.iface by
a script called Scintilla.PL, which you'll find in the source
distribution. I've patched up my local copy (there were 2 places that
this was a problem), and while doing so found a couple of other buffer
'over allocation' problems.
I'll make sure these fixes get into the next release.
Many thanks for taking the time to track down the problem and letting us
know.
Regards,