@NotNull
  private int[] fixRanges(@NotNull DocumentEvent e, int line1, int line2) {
    CharSequence document = myDocument.getCharsSequence();
    int offset = e.getOffset();

    if (e.getOldLength() == 0 && e.getNewLength() != 0) {
      if (StringUtil.endsWithChar(e.getNewFragment(), '\n') && isNewline(offset - 1, document)) {
        return new int[] {line1, line2 - 1};
      }
      if (StringUtil.startsWithChar(e.getNewFragment(), '\n')
          && isNewline(offset + e.getNewLength(), document)) {
        return new int[] {line1 + 1, line2};
      }
    }
    if (e.getOldLength() != 0 && e.getNewLength() == 0) {
      if (StringUtil.endsWithChar(e.getOldFragment(), '\n') && isNewline(offset - 1, document)) {
        return new int[] {line1, line2 - 1};
      }
      if (StringUtil.startsWithChar(e.getOldFragment(), '\n')
          && isNewline(offset + e.getNewLength(), document)) {
        return new int[] {line1 + 1, line2};
      }
    }

    return new int[] {line1, line2};
  }
Ejemplo n.º 2
0
  public void documentChanged(DocumentEvent e) {
    finishUpdate();

    DocumentEventImpl event = (DocumentEventImpl) e;
    final Document document = myEditor.getDocument();
    boolean performSoftWrapAdjustment =
        e.getNewLength() > 0 // We want to put caret just after the last added symbol
            // There is a possible case that the user removes text just before the soft wrap. We
            // want to keep caret
            // on a visual line with soft wrap start then.
            || myEditor.getSoftWrapModel().getSoftWrap(e.getOffset()) != null;

    if (event.isWholeTextReplaced()) {
      int newLength = document.getTextLength();
      if (myOffset == newLength - e.getNewLength() + e.getOldLength() || newLength == 0) {
        moveToOffset(newLength, performSoftWrapAdjustment);
      } else {
        final int line;
        try {
          line = event.translateLineViaDiff(myLogicalCaret.line);
          moveToLogicalPosition(
              new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment);
        } catch (FilesTooBigForDiffException e1) {
          LOG.info(e1);
          moveToOffset(0);
        }
      }
    } else {
      if (document instanceof DocumentEx && ((DocumentEx) document).isInBulkUpdate()) return;
      int startOffset = e.getOffset();
      int oldEndOffset = startOffset + e.getOldLength();

      int newOffset = myOffset;

      if (myOffset > oldEndOffset || myOffset == oldEndOffset && needToShiftWhiteSpaces(e)) {
        newOffset += e.getNewLength() - e.getOldLength();
      } else if (myOffset >= startOffset && myOffset <= oldEndOffset) {
        newOffset = Math.min(newOffset, startOffset + e.getNewLength());
      }

      newOffset = Math.min(newOffset, document.getTextLength());

      // if (newOffset != myOffset) {
      moveToOffset(newOffset, performSoftWrapAdjustment);
      // }
      // else {
      //  moveToVisualPosition(oldPosition);
      // }
    }

    myVisualLineStart =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
    myVisualLineEnd =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));
  }
Ejemplo n.º 3
0
 @Override
 public final void documentChanged(@NotNull DocumentEvent e) {
   int oldStart = intervalStart();
   int oldEnd = intervalEnd();
   int docLength = myDocument.getTextLength();
   if (!isValid()) {
     LOG.error(
         "Invalid range marker "
             + (isGreedyToLeft() ? "[" : "(")
             + oldStart
             + ", "
             + oldEnd
             + (isGreedyToRight() ? "]" : ")")
             + ". Event = "
             + e
             + ". Doc length="
             + docLength
             + "; "
             + getClass());
     return;
   }
   if (intervalStart() > intervalEnd()
       || intervalStart() < 0
       || intervalEnd() > docLength - e.getNewLength() + e.getOldLength()) {
     LOG.error(
         "RangeMarker"
             + (isGreedyToLeft() ? "[" : "(")
             + oldStart
             + ", "
             + oldEnd
             + (isGreedyToRight() ? "]" : ")")
             + " is invalid before update. Event = "
             + e
             + ". Doc length="
             + docLength
             + "; "
             + getClass());
     invalidate(e);
     return;
   }
   changedUpdateImpl(e);
   if (isValid()
       && (intervalStart() > intervalEnd() || intervalStart() < 0 || intervalEnd() > docLength)) {
     LOG.error(
         "Update failed. Event = "
             + e
             + ". "
             + "old doc length="
             + docLength
             + "; real doc length = "
             + myDocument.getTextLength()
             + "; "
             + getClass()
             + "."
             + " After update: '"
             + this
             + "'");
     invalidate(e);
   }
 }
Ejemplo n.º 4
0
 protected void onCopyChanged(DocumentEvent event, Document original) {
   final int originalOffset = event.getOffset() + myRangeMarker.getStartOffset();
   LOG.assertTrue(originalOffset >= 0);
   if (!original.isWritable()) return;
   final String newText = subText(event.getDocument(), event.getOffset(), event.getNewLength());
   final int originalEnd = originalOffset + event.getOldLength();
   replaceString(original, originalOffset, originalEnd, newText);
 }
Ejemplo n.º 5
0
 private boolean needToShiftWhiteSpaces(final DocumentEvent e) {
   if (!CharArrayUtil.containsOnlyWhiteSpaces(e.getNewFragment())
       || CharArrayUtil.containLineBreaks(e.getNewFragment())) return e.getOldLength() > 0;
   if (e.getOffset() == 0) return false;
   final char charBefore = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() - 1);
   // final char charAfter = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() +
   // e.getNewLength());
   return Character.isWhitespace(charBefore) /* || !Character.isWhitespace(charAfter)*/;
 }
    @Override
    public void beforeDocumentChange(DocumentEvent e) {
      myApplication.assertIsDispatchThread();

      synchronized (myLock) {
        if (myReleased) return;
        if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || !myInitialized) return;
        assert myDocument == e.getDocument();

        try {
          myLine1 = myDocument.getLineNumber(e.getOffset());
          if (e.getOldLength() == 0) {
            myBeforeChangedLines = 1;
          } else {
            int line1 = myLine1;
            int line2 = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
            myBeforeChangedLines = line2 - line1 + 1;
          }

          myBeforeTotalLines = getLineCount(myDocument);
        } catch (ProcessCanceledException ignore) {
        }
      }
    }
Ejemplo n.º 7
0
  @Nullable
  static ProperTextRange applyChange(
      @NotNull DocumentEvent e,
      int intervalStart,
      int intervalEnd,
      boolean isGreedyToLeft,
      boolean isGreedyToRight) {
    if (intervalStart == intervalEnd) {
      return processIfOnePoint(e, intervalStart, intervalEnd, isGreedyToRight);
    }

    final int offset = e.getOffset();
    final int oldLength = e.getOldLength();
    final int newLength = e.getNewLength();

    // changes after the end.
    if (intervalEnd < offset || !isGreedyToRight && intervalEnd == offset) {
      return new ProperTextRange(intervalStart, intervalEnd);
    }

    // changes before start
    if (intervalStart > offset + oldLength
        || !isGreedyToLeft && intervalStart == offset + oldLength) {
      return new ProperTextRange(
          intervalStart + newLength - oldLength, intervalEnd + newLength - oldLength);
    }

    // Changes inside marker's area. Expand/collapse.
    if (intervalStart <= offset && intervalEnd >= offset + oldLength) {
      return new ProperTextRange(intervalStart, intervalEnd + newLength - oldLength);
    }

    // At this point we either have (myStart xor myEnd inside changed area) or whole area changed.

    // Replacing prefix or suffix...
    if (intervalStart >= offset
        && intervalStart <= offset + oldLength
        && intervalEnd > offset + oldLength) {
      return new ProperTextRange(offset + newLength, intervalEnd + newLength - oldLength);
    }

    if (intervalEnd >= offset && intervalEnd <= offset + oldLength && intervalStart < offset) {
      return new ProperTextRange(intervalStart, offset);
    }

    return null;
  }
Ejemplo n.º 8
0
  @Nullable
  private static ProperTextRange processIfOnePoint(
      @NotNull DocumentEvent e, int intervalStart, int intervalEnd, boolean greedyRight) {
    int offset = e.getOffset();
    int oldLength = e.getOldLength();
    int oldEnd = offset + oldLength;
    if (offset < intervalStart && intervalStart < oldEnd) {
      return null;
    }

    if (offset == intervalStart && oldLength == 0 && greedyRight) {
      return new ProperTextRange(intervalStart, intervalEnd + e.getNewLength());
    }

    if (intervalStart > oldEnd || intervalStart == oldEnd && oldLength > 0) {
      return new ProperTextRange(
          intervalStart + e.getNewLength() - oldLength, intervalEnd + e.getNewLength() - oldLength);
    }

    return new ProperTextRange(intervalStart, intervalEnd);
  }
  @Override
  public synchronized void documentChanged(DocumentEvent e) {
    final Document document = e.getDocument();

    if (document instanceof DocumentEx && ((DocumentEx) document).isInBulkUpdate()) {
      mySegments.removeAll();
      return;
    }

    if (mySegments.getSegmentCount() == 0) {
      setText(document.getCharsSequence());
      return;
    }

    CharSequence text = document.getCharsSequence();
    int oldStartOffset = e.getOffset();

    final int segmentIndex;
    try {
      segmentIndex = mySegments.findSegmentIndex(oldStartOffset) - 2;
    } catch (IndexOutOfBoundsException ex) {
      throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer);
    }
    final int oldStartIndex = Math.max(0, segmentIndex);
    int startIndex = oldStartIndex;

    int data;
    do {
      data = mySegments.getSegmentData(startIndex);
      if (isInitialState(data) || startIndex == 0) break;
      startIndex--;
    } while (true);

    int startOffset = mySegments.getSegmentStart(startIndex);
    int newEndOffset = e.getOffset() + e.getNewLength();

    myLexer.start(text, startOffset, text.length(), myInitialState);

    int lastTokenStart = -1;
    int lastLexerState = -1;

    while (myLexer.getTokenType() != null) {
      if (startIndex >= oldStartIndex) break;

      int tokenStart = myLexer.getTokenStart();
      int lexerState = myLexer.getState();

      if (tokenStart == lastTokenStart && lexerState == lastLexerState) {
        throw new IllegalStateException(
            "Error while updating lexer: " + e + " document text: " + document.getText());
      }

      int tokenEnd = myLexer.getTokenEnd();
      data = packData(myLexer.getTokenType(), lexerState);
      if (mySegments.getSegmentStart(startIndex) != tokenStart
          || mySegments.getSegmentEnd(startIndex) != tokenEnd
          || mySegments.getSegmentData(startIndex) != data) {
        break;
      }
      startIndex++;
      myLexer.advance();
      lastTokenStart = tokenStart;
      lastLexerState = lexerState;
    }

    startOffset = mySegments.getSegmentStart(startIndex);
    int repaintEnd = -1;
    int insertSegmentCount = 0;
    int oldEndIndex = -1;
    SegmentArrayWithData insertSegments = new SegmentArrayWithData();

    while (myLexer.getTokenType() != null) {
      int tokenStart = myLexer.getTokenStart();
      int lexerState = myLexer.getState();

      if (tokenStart == lastTokenStart && lexerState == lastLexerState) {
        throw new IllegalStateException(
            "Error while updating lexer: " + e + " document text: " + document.getText());
      }

      lastTokenStart = tokenStart;
      lastLexerState = lexerState;

      int tokenEnd = myLexer.getTokenEnd();
      data = packData(myLexer.getTokenType(), lexerState);
      if (tokenStart >= newEndOffset && lexerState == myInitialState) {
        int shiftedTokenStart = tokenStart - e.getNewLength() + e.getOldLength();
        int index = mySegments.findSegmentIndex(shiftedTokenStart);
        if (mySegments.getSegmentStart(index) == shiftedTokenStart
            && mySegments.getSegmentData(index) == data) {
          repaintEnd = tokenStart;
          oldEndIndex = index;
          break;
        }
      }
      insertSegments.setElementAt(insertSegmentCount, tokenStart, tokenEnd, data);
      insertSegmentCount++;
      myLexer.advance();
    }

    final int shift = e.getNewLength() - e.getOldLength();
    if (repaintEnd > 0) {
      while (insertSegmentCount > 0 && oldEndIndex > startIndex) {
        if (!segmentsEqual(
            mySegments, oldEndIndex - 1, insertSegments, insertSegmentCount - 1, shift)) {
          break;
        }
        insertSegmentCount--;
        oldEndIndex--;
        repaintEnd = insertSegments.getSegmentStart(insertSegmentCount);
        insertSegments.remove(insertSegmentCount, insertSegmentCount + 1);
      }
    }

    if (repaintEnd == -1) {
      repaintEnd = text.length();
    }

    if (oldEndIndex < 0) {
      oldEndIndex = mySegments.getSegmentCount();
    }
    mySegments.shiftSegments(oldEndIndex, shift);
    mySegments.replace(startIndex, oldEndIndex, insertSegments);

    if (insertSegmentCount == 0
        || oldEndIndex == startIndex + 1
            && insertSegmentCount == 1
            && data == mySegments.getSegmentData(startIndex)) {
      return;
    }

    myEditor.repaint(startOffset, repaintEnd);
  }