public void advance() {
   if (mySegmentIterator.atEnd()) {
     myRangeIterator.advance();
     TextAttributes textAttributes = myRangeIterator.getTextAttributes();
     myCurrentFontStyle = textAttributes == null ? Font.PLAIN : textAttributes.getFontType();
     myCurrentForegroundColor =
         textAttributes == null ? null : textAttributes.getForegroundColor();
     myCurrentBackgroundColor =
         textAttributes == null ? null : textAttributes.getBackgroundColor();
     mySegmentIterator.reset(
         myRangeIterator.getRangeStart(), myRangeIterator.getRangeEnd(), myCurrentFontStyle);
   }
   mySegmentIterator.advance();
 }
 @Override
 public boolean atEnd() {
   boolean validIteratorExists = false;
   for (int i = 0; i < myIterators.length; i++) {
     IteratorWrapper wrapper = myIterators[i];
     if (wrapper == null) {
       continue;
     }
     RangeIterator iterator = wrapper.iterator;
     if (!iterator.atEnd()
         || overlappingRangesCount > 0
             && (i >= overlappingRangesCount || iterator.getRangeEnd() > myCurrentEnd)) {
       validIteratorExists = true;
     }
   }
   return !validIteratorExists;
 }
 @Override
 public void advance() {
   int max = overlappingRangesCount == 0 ? myIterators.length : overlappingRangesCount;
   for (int i = 0; i < max; i++) {
     IteratorWrapper wrapper = myIterators[i];
     if (wrapper == null) {
       continue;
     }
     RangeIterator iterator = wrapper.iterator;
     if (overlappingRangesCount > 0 && iterator.getRangeEnd() > myCurrentEnd) {
       continue;
     }
     if (iterator.atEnd()) {
       iterator.dispose();
       myIterators[i] = null;
     } else {
       iterator.advance();
     }
   }
   Arrays.sort(myIterators, RANGE_SORTER);
   myCurrentStart = Math.max(myIterators[0].iterator.getRangeStart(), myCurrentEnd);
   myCurrentEnd = Integer.MAX_VALUE;
   //noinspection ForLoopReplaceableByForEach
   for (int i = 0; i < myIterators.length; i++) {
     IteratorWrapper wrapper = myIterators[i];
     if (wrapper == null) {
       break;
     }
     RangeIterator iterator = wrapper.iterator;
     int nearestBound;
     if (iterator.getRangeStart() > myCurrentStart) {
       nearestBound = iterator.getRangeStart();
     } else {
       nearestBound = iterator.getRangeEnd();
     }
     myCurrentEnd = Math.min(myCurrentEnd, nearestBound);
   }
   myCurrentEnd = getRangeEnd();
   for (overlappingRangesCount = 1;
       overlappingRangesCount < myIterators.length;
       overlappingRangesCount++) {
     IteratorWrapper wrapper = myIterators[overlappingRangesCount];
     if (wrapper == null || wrapper.iterator.getRangeStart() > myCurrentStart) {
       break;
     }
   }
 }
 public void paintHighlighters(EditorHighlighter highlighter) {
   int startOffset = startOfLineByOffset(myStartOffset);
   if (startOffset < 0 || startOffset >= myEditor.getDocument().getTextLength()) return;
   RangeIterator iterator =
       new RangeIterator(
           new FoldingOrNewLineGaps(myEditor),
           SAME_COLOR_BOXES,
           highlighter.createIterator(startOffset),
           BOX_FILTER);
   iterator.init(myRange);
   while (!iterator.atEnd()) {
     iterator.advance();
     paintBorder(
         myGraphics,
         myEditor,
         iterator.getStart(),
         iterator.getEnd(),
         iterator.getTextAttributes().getEffectColor(),
         iterator.getTextAttributes().getEffectType());
   }
 }
 public void dispose() {
   myRangeIterator.dispose();
 }
 public boolean atEnd() {
   return myRangeIterator.atEnd() && mySegmentIterator.atEnd();
 }