private void getNearestHighlighters(
     MarkupModelEx markupModel,
     MouseEvent e,
     final double width,
     final Collection<RangeHighlighter> nearest) {
   if (0 > e.getX() || e.getX() >= width) return;
   int startOffset = yPositionToOffset(e.getY() - getMinHeight(), true);
   int endOffset = yPositionToOffset(e.getY() + getMinHeight(), false);
   markupModel.processHighlightsOverlappingWith(
       startOffset,
       endOffset,
       new Processor<RangeHighlighterEx>() {
         public boolean process(RangeHighlighterEx highlighter) {
           if (highlighter.getErrorStripeMarkColor() != null) nearest.add(highlighter);
           return true;
         }
       });
 }
    private void drawMarkup(
        final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) {
      final Queue<PositionedStripe> thinEnds =
          new PriorityQueue<PositionedStripe>(
              5,
              new Comparator<PositionedStripe>() {
                public int compare(PositionedStripe o1, PositionedStripe o2) {
                  return o1.yEnd - o2.yEnd;
                }
              });
      final Queue<PositionedStripe> wideEnds =
          new PriorityQueue<PositionedStripe>(
              5,
              new Comparator<PositionedStripe>() {
                public int compare(PositionedStripe o1, PositionedStripe o2) {
                  return o1.yEnd - o2.yEnd;
                }
              });
      // sorted by layer
      final List<PositionedStripe> thinStripes = new ArrayList<PositionedStripe>();
      final List<PositionedStripe> wideStripes = new ArrayList<PositionedStripe>();
      final int[] thinYStart = new int[1]; // in range 0..yStart all spots are drawn
      final int[] wideYStart = new int[1]; // in range 0..yStart all spots are drawn

      markup.processHighlightsOverlappingWith(
          startOffset,
          endOffset,
          new Processor<RangeHighlighterEx>() {
            public boolean process(RangeHighlighterEx highlighter) {
              Color color = highlighter.getErrorStripeMarkColor();
              if (color == null) return true;
              boolean isThin = highlighter.isThinErrorStripeMark();
              int[] yStart = isThin ? thinYStart : wideYStart;
              List<PositionedStripe> stripes = isThin ? thinStripes : wideStripes;
              Queue<PositionedStripe> ends = isThin ? thinEnds : wideEnds;

              ProperTextRange range =
                  offsetToYPosition(highlighter.getStartOffset(), highlighter.getEndOffset());
              final int ys = range.getStartOffset();
              int ye = range.getEndOffset();
              if (ye - ys < getMinHeight()) ye = ys + getMinHeight();

              yStart[0] = drawStripesEndingBefore(ys, ends, stripes, g, width, yStart[0]);

              final int layer = highlighter.getLayer();

              PositionedStripe stripe = null;
              int i;
              for (i = 0; i < stripes.size(); i++) {
                PositionedStripe s = stripes.get(i);
                if (s.layer == layer) {
                  stripe = s;
                  break;
                }
                if (s.layer < layer) {
                  break;
                }
              }
              if (stripe == null) {
                // started new stripe, draw previous above
                if (yStart[0] != ys) {
                  if (!stripes.isEmpty()) {
                    PositionedStripe top = stripes.get(0);
                    drawSpot(g, width, top.thin, yStart[0], ys, top.color, true, true);
                  }
                  yStart[0] = ys;
                }
                stripe = new PositionedStripe(color, ys, ye, isThin, layer);
                stripes.add(i, stripe);
                ends.offer(stripe);
              } else {
                // key changed, reinsert into queue
                if (stripe.yEnd != ye) {
                  ends.remove(stripe);
                  stripe.yEnd = ye;
                  ends.offer(stripe);
                }
              }

              return true;
            }
          });

      drawStripesEndingBefore(Integer.MAX_VALUE, thinEnds, thinStripes, g, width, thinYStart[0]);
      drawStripesEndingBefore(Integer.MAX_VALUE, wideEnds, wideStripes, g, width, wideYStart[0]);
    }