@@ -5677,6 +5677,89 @@ MCTextChunkIterator::MCTextChunkIterator(Chunk_term p_chunk_type, MCStringRef p_
56775677 MCLocaleBreakIteratorRelease (break_iterator);
56785678}
56795679
5680+ // AL-2015-02-10: [[ Bug 14532 ]] Add text chunk iterator constructor for restricted range chunk operations.
5681+ MCTextChunkIterator::MCTextChunkIterator (Chunk_term p_chunk_type, MCStringRef p_text, MCRange p_restriction)
5682+ {
5683+ /* UNCHECKED */ MCStringCopy (p_text, text);
5684+ type = p_chunk_type;
5685+
5686+ if (type == CT_CHARACTER && (MCStringIsNative (text) || (MCStringIsSimple (text) && MCStringIsUncombined (text))))
5687+ type = CT_CODEUNIT;
5688+
5689+ MCBreakIteratorRef break_iterator;
5690+
5691+ break_iterator = nil;
5692+ sp = nil;
5693+ range = MCRangeMake (p_restriction . offset, 0 );
5694+ length = p_restriction . length == UINDEX_MAX ? MCStringGetLength (text) : p_restriction . offset + p_restriction . length;
5695+ // AL-2014-10-24: [[ Bug 13783 ]] Set exhausted to true if the string is immediately exhausted
5696+ exhausted = (p_restriction . length == 0 || p_restriction . offset>= MCStringGetLength (text));
5697+ first_chunk = true ;
5698+ break_position = 0 ;
5699+ delimiter_length = 0 ;
5700+
5701+ switch (type)
5702+ {
5703+ case CT_TOKEN:
5704+ {
5705+ MCAutoStringRef t_substring;
5706+ MCStringCopySubstring (text, p_restriction, &t_substring);
5707+ MCValueAssign (text, *t_substring);
5708+ sp = new MCScriptPoint (text);
5709+ }
5710+ break ;
5711+ case CT_CHARACTER:
5712+ case CT_SENTENCE:
5713+ {
5714+ MCAutoStringRef t_substring;
5715+ MCStringCopySubstring (text, p_restriction, &t_substring);
5716+ MCRange t_range;
5717+ uindex_t t_end;
5718+ /* UNCHECKED */ MCLocaleBreakIteratorCreate (kMCBasicLocale , p_chunk_type == CT_SENTENCE ? kMCBreakIteratorTypeSentence : kMCBreakIteratorTypeCharacter , break_iterator);
5719+ /* UNCHECKED */ MCLocaleBreakIteratorSetText (break_iterator, *t_substring);
5720+ t_range . length = p_restriction . length;
5721+ t_range . offset = p_restriction . offset;
5722+
5723+ while ((t_end = MCLocaleBreakIteratorAdvance (break_iterator)) != kMCLocaleBreakIteratorDone )
5724+ {
5725+ t_range . offset += t_range . length;
5726+ t_range . length = t_end - t_range . offset;
5727+ breaks . Push (t_range);
5728+ }
5729+ }
5730+ break ;
5731+ case CT_TRUEWORD:
5732+ {
5733+ MCAutoStringRef t_substring;
5734+ MCStringCopySubstring (text, p_restriction, &t_substring);
5735+ MCAutoArray<uindex_t > t_breaks;
5736+ /* UNCHECKED */ MCLocaleBreakIteratorCreate (kMCBasicLocale , kMCBreakIteratorTypeWord , break_iterator);
5737+ /* UNCHECKED */ MCLocaleBreakIteratorSetText (break_iterator, *t_substring);
5738+ MCRange t_range;
5739+ t_range . length = p_restriction . length;
5740+ t_range . offset = p_restriction . offset;
5741+
5742+ while (MCLocaleWordBreakIteratorAdvance (*t_substring, break_iterator, t_range)
5743+ && t_range . offset + t_range . length != kMCLocaleBreakIteratorDone )
5744+ {
5745+ breaks . Push (t_range);
5746+ }
5747+ }
5748+ break ;
5749+ case CT_LINE:
5750+ case CT_ITEM:
5751+ case CT_PARAGRAPH:
5752+ // delimiter length may vary for line and item.
5753+ delimiter_length = 1 ;
5754+ default :
5755+ break ;
5756+ }
5757+
5758+ if (break_iterator != nil)
5759+ MCLocaleBreakIteratorRelease (break_iterator);
5760+ }
5761+
5762+
56805763MCTextChunkIterator::~MCTextChunkIterator ()
56815764{
56825765 MCValueRelease (text);
@@ -5743,7 +5826,8 @@ bool MCTextChunkIterator::next(MCExecContext& ctxt)
57435826
57445827 MCRange t_found_range;
57455828 // calculate the length of the line / item
5746- if (!MCStringFind (text, MCRangeMake (t_offset, UINDEX_MAX), t_delimiter, ctxt . GetStringComparisonType (), &t_found_range))
5829+ // AL-2015-02-10: [[ Bug 14532 ]] Use restricted range for delimiter search
5830+ if (!MCStringFind (text, MCRangeMake (t_offset, length - t_offset), t_delimiter, ctxt . GetStringComparisonType (), &t_found_range))
57475831 {
57485832 range . length = length - range . offset;
57495833 exhausted = true ;
@@ -5763,8 +5847,9 @@ bool MCTextChunkIterator::next(MCExecContext& ctxt)
57635847 uindex_t t_pg_offset;
57645848 bool t_newline_found, t_pg_found;
57655849
5850+ // AL-2015-02-10: [[ Bug 14532 ]] Use restricted range for delimiter search
57665851 t_pg_offset = t_offset;
5767- t_newline_found = MCStringFirstIndexOfChar (text, ' \n ' , t_offset, kMCCompareExact , t_offset);
5852+ t_newline_found = MCStringFirstIndexOfCharInRange (text, ' \n ' , MCRangeMake ( t_offset, length - t_offset) , kMCCompareExact , t_offset);
57685853 // AL-2014-07-21: [[ Bug 12162 ]] Ignore PS when calculating paragraph chunk.
57695854 t_pg_found = false ; /* MCStringFirstIndexOfChar(text, 0x2029, t_pg_offset, kMCCompareExact, t_pg_offset);*/
57705855
@@ -5795,7 +5880,8 @@ bool MCTextChunkIterator::next(MCExecContext& ctxt)
57955880
57965881 MCStringsSkipWord (ctxt, text, false , t_offset);
57975882
5798- if (t_offset == length)
5883+ // AL-2015-02-10: [[ Bug 14532 ]] Use restricted range for exhaustion check
5884+ if (t_offset >= length)
57995885 exhausted = true ;
58005886
58015887 range . length = t_offset - range . offset;
@@ -5851,11 +5937,11 @@ bool MCTextChunkIterator::isamong(MCExecContext& ctxt, MCStringRef p_needle)
58515937 // Otherwise we need to find p_needle and check to see if there is a delimiter either side.
58525938 // This is because of the case where the delimiter is within p_needle - e.g.
58535939 // "a,b" is among the items of "a,b,c,d" should return true.
5854-
5940+ // AL-2015-02-10: [[ Bug 14532 ]] Use restricted range for isamong search
58555941 if (type == CT_PARAGRAPH)
5856- return MCStringsIsAmongTheParagraphsOfRange (ctxt, p_needle, text, ctxt . GetStringComparisonType (), MCRangeMake (0 , length));
5942+ return MCStringsIsAmongTheParagraphsOfRange (ctxt, p_needle, text, ctxt . GetStringComparisonType (), MCRangeMake (range . offset , length));
58575943
5858- return MCStringsIsAmongTheChunksOfRange (ctxt, p_needle, text, type, ctxt . GetStringComparisonType (), MCRangeMake (0 , length));
5944+ return MCStringsIsAmongTheChunksOfRange (ctxt, p_needle, text, type, ctxt . GetStringComparisonType (), MCRangeMake (range . offset , length));
58595945 }
58605946 default :
58615947 if (MCStringIsEmpty (p_needle))
0 commit comments