Discussion:
Iterating over indicators using IndicatorStart and IndicatorEnd
Paul K
2014-01-21 06:44:20 UTC
Permalink
Hi All,

I've been trying to iterate over a particular indicator and ran into an
issue most likely caused by my misunderstanding of the API. I see that
there are SCI_INDICATORSTART(int indicator, int position) and SCI_INDICATOREND(int
indicator, int position) messages, and I thought that
indicatorstart/indicatorend would give me start/end position of the next
indicator location, but this is not what I'm getting (e is the instance of
e:SetText('0123456789')
e:SetIndicatorCurrent(0)
e:IndicatorFillRange(1, 2)
e:IndicatorStart(0, 0) --<-- I expect here to get the start of the next
indicator from 0, which is 1
0
e:IndicatorEnd(0, 0) --<-- I expect here to get the end of the next
indicator from 0, which is 2
1
e:IndicatorEnd(0, 1) --<-- I expect 2 here, but get 3, which seems to be
the start of the next partition
3
e:IndicatorStart(0, e:GetLength())
10
e:IndicatorStart(0, 9)
3
e:IndicatorStart(0, 2) --<-- I expect 1 here and this is what I get
1

It seems like IteratorEnd gives me the next indicator boundary (start and
end) after the specified position and IteratorStart gives me the same
boundary, but at or before the specified position.

I checked the logic of DecorationList::Start and ::End calls and it does
seem like they iterate over partitions based on the specified position, but
if the position is outside of the indicator of interest, then start/end
mark the beginning and end of *that* partition (0,0 in my example), even
though I'm interested in the next one (1,2 in my example).

This is probably not a big deal as I can come up with the logic to iterate
over indicators using this API, but it's a bit different from my reading of
the documentation and from some of the examples I've seen
(https://groups.google.com/d/msg/scintilla-interest/KIetTCwFGhU/P0jht7bgQ9YJ),
so I'd like to confirm that I understand the API correctly. This is using
wxSTC based on Scintilla 3.2.1.

Paul.
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2014-01-21 09:16:44 UTC
Permalink
Paul K:

Note that positions are between characters, not at characters. A range thus includes the characters between its start and end positions.
e:SetText('0123456789')
e:SetIndicatorCurrent(0)
e:IndicatorFillRange(1, 2)
The situation here looks like
0123456789

There are three ranges 0..1, 1..3, and 3..10 with 1..3 having value 1 and the other ranges value 0.
e:IndicatorStart(0, 0) --<-- I expect here to get the start of the next indicator from 0, which is 1
0
Its the end of the range that is 1, not the start.
e:IndicatorEnd(0, 0) --<-- I expect here to get the end of the next indicator from 0, which is 2
1
No range starts or ends at 2.
e:IndicatorEnd(0, 1) --<-- I expect 2 here, but get 3, which seems to be the start of the next partition
3
The end of one partition is the start of the next.
e:IndicatorStart(0, e:GetLength())
10
I see 3 here, even with SciTE 3.2.1.

Here’s a translation of the test script for SciTE:

function testind()
editor:SetText('0123456789')
editor.IndicatorCurrent = 0
editor:IndicatorFillRange(1, 2)
print(editor:IndicatorStart(0, 0)) --<-- I expect here to get the start of the next indicator from 0, which is 1
print(editor:IndicatorEnd(0, 0)) --<-- I expect here to get the end of the next indicator from 0, which is 2
print(editor:IndicatorEnd(0, 1)) --<-- I expect 2 here, but get 3, which seems to be the start of the next partition
print(editor:IndicatorStart(0, editor.Length))
print(editor:IndicatorStart(0, 9))
print(editor:IndicatorStart(0, 2)) --<-- I expect 1 here and this is what I get
end

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Paul K
2014-01-21 17:10:11 UTC
Permalink
Post by Neil Hodgson
Note that positions are between characters, not at characters. A range thus includes the characters between its start and end positions.
There are three ranges 0..1, 1..3, and 3..10 with 1..3 having value 1 and the other ranges value 0.
Thank you for the explanation; I now understand the logic and just
have one small question. How do I know what value (1 or 0) each range
has? Do I simply check IndicatorValueAt inside the first range and
then assume that they always change at the boundary?
Post by Neil Hodgson
e:IndicatorStart(0, e:GetLength())
10
I see 3 here, even with SciTE 3.2.1.
I just rechecked and I get 10; I think this is because the large
character has position 9, so it should be e:GetLength()-1, which
correctly returns 3. If I'm checking for 10, it means I check after
the last partition, no?

Does this mean that the last range is 3..9, not 3..10?

Paul.
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2014-01-21 21:53:12 UTC
Permalink
Post by Paul K
Thank you for the explanation; I now understand the logic and just
have one small question. How do I know what value (1 or 0) each range
has? Do I simply check IndicatorValueAt inside the first range and
then assume that they always change at the boundary?
They do always change at each boundary and, if you are only setting the value to 0 or 1, then there is no need to check each time. However it is possible to set different values for each range.
Post by Paul K
I just rechecked and I get 10; I think this is because the large
character has position 9, so it should be e:GetLength()-1, which
correctly returns 3.
The length of the document is 10 since there are 10 characters and the last position in the document is 10 which is after all characters. Add ‘print(editor.Length)’ and it should show 10.
Post by Paul K
If I'm checking for 10, it means I check after
the last partition, no?
It would if you were calling IndicatorEnd instead of IndicatorStart.
Post by Paul K
Does this mean that the last range is 3..9, not 3..10?
No.

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Paul K
2014-01-21 23:14:28 UTC
Permalink
Post by Neil Hodgson
They do always change at each boundary and, if you are only setting the
value to 0 or 1, then there is no need to check each time. However it is
possible to set different values for each range.

Right; somehow I assumed that partitions where the indicators are not set
at all are not going to be included, but it seems like they are included
and I just need to handle that.
Post by Neil Hodgson
Add ‘print(editor.Length)’ and it should show 10.
It does show 10 as expected.
Post by Neil Hodgson
It would if you were calling IndicatorEnd instead of IndicatorStart.
They both seem to return 10; everything looks correct except
IndicatorStart(0, 10) == 10 (which should be 3 according to your earlier
message)
Post by Neil Hodgson
e:GetLength()
10
Post by Neil Hodgson
e:IndicatorStart(0, 10)
10
Post by Neil Hodgson
e:IndicatorEnd(0, 10)
10
Post by Neil Hodgson
e:IndicatorStart(0, 9)
3
Post by Neil Hodgson
e:IndicatorEnd(0, 9)
10

Not a big deal, as this is always the last partition, but I thought it was
interesting.

Paul.
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Neil Hodgson
2014-01-21 23:34:11 UTC
Permalink
They both seem to return 10; everything looks correct except IndicatorStart(0, 10) == 10 (which should be 3 according to your earlier message)
e:GetLength()
10
e:IndicatorStart(0, 10)
10
I see 3 here with both SciTE 3.2.1 and 3.3.7.

The updated script:

function testind()
editor:SetText('0123456789')
editor.IndicatorCurrent = 0
editor:IndicatorFillRange(1, 2)
print(editor:IndicatorStart(0, 0)) --<-- I expect here to get the start of the next indicator from 0, which is 1
print(editor:IndicatorEnd(0, 0)) --<-- I expect here to get the end of the next indicator from 0, which is 2
print(editor:IndicatorEnd(0, 1)) --<-- I expect 2 here, but get 3, which seems to be the start of the next partition
print(editor:IndicatorStart(0, editor.Length))
print(editor:IndicatorStart(0, 9))
print(editor:IndicatorStart(0, 2)) --<-- I expect 1 here and this is what I get
print(editor.Length)
print(editor:IndicatorStart(0, 10))
print(editor:IndicatorEnd(0, 10))
print(editor:IndicatorStart(0, 9))
print(editor:IndicatorEnd(0, 9))
end

produces:

0
1
3
3
3
1
10
3
10
3
10

There were bugs before 3.3.2 which could corrupt the data structures implementing indicators but these were caused when adding zero length indicators or indicators that spanned the document end and should not occur when creating a new document and then performing editor:IndicatorFillRange(1, 2).

Neil
--
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scintilla-interest+***@googlegroups.com.
To post to this group, send email to scintilla-***@googlegroups.com.
Visit this group at http://groups.google.com/group/scintilla-interest.
For more options, visit https://groups.google.com/groups/opt_out.
Loading...