@Nullable("null means we were unable to calculate")
  LogicalPosition hostToInjectedInVirtualSpace(@NotNull LogicalPosition hPos) {
    // beware the virtual space
    int hLineStartOffset =
        hPos.line >= myDelegate.getLineCount()
            ? myDelegate.getTextLength()
            : myDelegate.getLineStartOffset(hPos.line);
    int iLineStartOffset = hostToInjected(hLineStartOffset);
    int iLine = getLineNumber(iLineStartOffset);

    synchronized (myLock) {
      for (int i = myShreds.size() - 1; i >= 0; i--) {
        PsiLanguageInjectionHost.Shred shred = myShreds.get(i);
        if (!shred.isValid()) continue;
        Segment hostRangeMarker = shred.getHostRangeMarker();
        if (hostRangeMarker == null) continue;
        int hShredEndOffset = hostRangeMarker.getEndOffset();
        int hShredStartOffset = hostRangeMarker.getStartOffset();

        int hShredStartLine = myDelegate.getLineNumber(hShredStartOffset);
        int hShredEndLine = myDelegate.getLineNumber(hShredEndOffset);

        if (hShredStartLine <= hPos.line && hPos.line <= hShredEndLine) {
          int hColumnOfShredEnd = hShredEndOffset - hLineStartOffset;
          int iColumnOfShredEnd = hostToInjected(hShredEndOffset) - iLineStartOffset;
          int iColumn = iColumnOfShredEnd + hPos.column - hColumnOfShredEnd;
          return new LogicalPosition(iLine, iColumn);
        }
      }
    }

    return null;
  }
  @Override
  public int injectedToHostLine(int line) {
    if (line < myPrefixLineCount) {
      synchronized (myLock) {
        Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker();
        return hostRangeMarker == null
            ? 0
            : myDelegate.getLineNumber(hostRangeMarker.getStartOffset());
      }
    }
    int lineCount = getLineCount();
    if (line > lineCount - mySuffixLineCount) {
      return lineCount;
    }
    int offset = getLineStartOffset(line);
    int hostOffset = injectedToHost(offset);

    return myDelegate.getLineNumber(hostOffset);
  }
 /**
  * @return position <code>x</code> for which <code>
  *     myDocument.getText().substring(x, startOffset)</code> contains <code>blankLinesNumber
  *     </code> line feeds and <code>myDocument.getText.charAt(x-1) == '\n'</code>
  */
 private int getBlankLineOffset(int blankLinesNumber, int startOffset) {
   int startLine = myDocument.getLineNumber(startOffset);
   if (startLine <= 0) {
     return 0;
   }
   CharSequence text = myDocument.getCharsSequence();
   for (int i = myDocument.getLineStartOffset(startLine - 1) - 1;
       i >= 0;
       i = CharArrayUtil.lastIndexOf(text, "\n", i - 1)) {
     if (--blankLinesNumber <= 0) {
       return i + 1;
     }
   }
   return 0;
 }