/**
   * Enter a block where the selection will be preserved against the adverse effects of dom
   * mutation.
   *
   * <p>Must be balanced with a call to either {@link #restoreSelection()} or {@link
   * #restoreSelection(DocOp)}
   *
   * <p>Code that mutates the HTML dom must be guarded by calls to save and restore.
   */
  public void saveSelection() {
    if (editingConcerns != null && savedSelectionDepth == 0) {
      needToRestoreSelection = false;
      SelectionHelper helper = editingConcerns.getSelectionHelper();

      // Sometimes the document is not in an editing context, in which
      // case there is no selection helper.
      if (helper != null) {
        FocusedPointRange<Node> htmlSelection = NativeSelectionUtil.get();
        if (htmlSelection != null) {
          savedSelectionAnchor = htmlSelection.getAnchor();
          if (savedSelectionAnchor.isInTextNode()) {
            savedSelectionAnchorTextNodelet = savedSelectionAnchor.getContainer().cast();
            savedSelectionAnchorOffset = savedSelectionAnchor.getTextOffset();
          }
          savedSelectionFocus = htmlSelection.getFocus();
          if (savedSelectionFocus.isInTextNode()) {
            savedSelectionFocusTextNodelet = savedSelectionFocus.getContainer().cast();
            savedSelectionFocusOffset = savedSelectionFocus.getTextOffset();
          }
          savedSelection = helper.getSelectionRange();
        }
      }
    }

    savedSelectionDepth++;
  }
  /**
   * Checks if the selection has been removed, or is somewhere where we are not expecting it to be.
   */
  private boolean selectionChangedInappropriately() {

    // The selection got lost. We need to restore it
    if (!NativeSelectionUtil.selectionExists()) {
      return true;
    }

    NativeSelectionUtil.cacheClear();

    FocusedPointRange<Node> htmlSelection = NativeSelectionUtil.get();

    Point<Node> newAnchor = htmlSelection.getAnchor();
    if (savedSelectionAnchor.isInTextNode()) {
      if (savedSelectionAnchorTextNodelet != newAnchor.getContainer()
          || savedSelectionAnchorOffset != newAnchor.getTextOffset()) {
        return true;
      }
    } else {
      if (savedSelectionAnchor.getContainer() != newAnchor.getContainer()) {
        return true;
      }
    }

    Point<Node> newFocus = htmlSelection.getFocus();
    if (savedSelectionFocus.isInTextNode()) {
      if (savedSelectionFocusTextNodelet != newFocus.getContainer()
          || savedSelectionFocusOffset != newFocus.getTextOffset()) {
        return true;
      }
    } else {
      if (savedSelectionFocus.getContainer() != newFocus.getContainer()) {
        return true;
      }
    }

    return false;
  }