NS_IMETHODIMP
InsertNodeTransaction::DoTransaction()
{
  if (NS_WARN_IF(!mEditorBase) ||
      NS_WARN_IF(!mContentToInsert) ||
      NS_WARN_IF(!mPointToInsert.IsSet())) {
    return NS_ERROR_NOT_INITIALIZED;
  }

  if (!mPointToInsert.IsSetAndValid()) {
    // It seems that DOM tree has been changed after first DoTransaction()
    // and current RedoTranaction() call.
    if (mPointToInsert.GetChild()) {
      EditorDOMPoint newPointToInsert(mPointToInsert.GetChild());
      if (!newPointToInsert.IsSet()) {
        // The insertion point has been removed from the DOM tree.
        // In this case, we should append the node to the container instead.
        newPointToInsert.SetToEndOf(mPointToInsert.GetContainer());
        if (NS_WARN_IF(!newPointToInsert.IsSet())) {
          return NS_ERROR_FAILURE;
        }
      }
      mPointToInsert = newPointToInsert;
    } else {
      mPointToInsert.SetToEndOf(mPointToInsert.GetContainer());
      if (NS_WARN_IF(!mPointToInsert.IsSet())) {
        return NS_ERROR_FAILURE;
      }
    }
  }

  mEditorBase->MarkNodeDirty(GetAsDOMNode(mContentToInsert));

  ErrorResult error;
  mPointToInsert.GetContainer()->InsertBefore(*mContentToInsert,
                                              mPointToInsert.GetChild(),
                                              error);
  error.WouldReportJSException();
  if (NS_WARN_IF(error.Failed())) {
    return error.StealNSResult();
  }

  // Only set selection to insertion point if editor gives permission
  if (mEditorBase->GetShouldTxnSetSelection()) {
    RefPtr<Selection> selection = mEditorBase->GetSelection();
    if (NS_WARN_IF(!selection)) {
      return NS_ERROR_FAILURE;
    }
    // Place the selection just after the inserted element
    EditorRawDOMPoint afterInsertedNode(mContentToInsert);
    DebugOnly<bool> advanced = afterInsertedNode.AdvanceOffset();
    NS_WARNING_ASSERTION(advanced,
      "Failed to advance offset after the inserted node");
    selection->Collapse(afterInsertedNode, error);
    if (NS_WARN_IF(error.Failed())) {
      error.SuppressException();
    }
  }
  return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::GetResizedObject(nsIDOMElement** aResizedObject)
{
  nsCOMPtr<nsIDOMElement> ret = static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject));
  ret.forget(aResizedObject);
  return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::DoInlineTableEditingAction(nsIDOMElement* aElement)
{
  NS_ENSURE_ARG_POINTER(aElement);
  bool anonElement = false;
  if (aElement &&
      NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
      anonElement) {
    nsAutoString anonclass;
    nsresult rv =
      aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable")))
      return NS_OK;

    nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
    nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
    int32_t rowCount, colCount;
    rv = GetTableSize(tableElement, &rowCount, &colCount);
    NS_ENSURE_SUCCESS(rv, rv);

    bool hideUI = false;
    bool hideResizersWithInlineTableUI = (GetAsDOMNode(mResizedObject) == tableElement);

    if (anonclass.EqualsLiteral("mozTableAddColumnBefore"))
      InsertTableColumn(1, false);
    else if (anonclass.EqualsLiteral("mozTableAddColumnAfter"))
      InsertTableColumn(1, true);
    else if (anonclass.EqualsLiteral("mozTableAddRowBefore"))
      InsertTableRow(1, false);
    else if (anonclass.EqualsLiteral("mozTableAddRowAfter"))
      InsertTableRow(1, true);
    else if (anonclass.EqualsLiteral("mozTableRemoveColumn")) {
      DeleteTableColumn(1);
#ifndef DISABLE_TABLE_DELETION
      hideUI = (colCount == 1);
#endif
    }
    else if (anonclass.EqualsLiteral("mozTableRemoveRow")) {
      DeleteTableRow(1);
#ifndef DISABLE_TABLE_DELETION
      hideUI = (rowCount == 1);
#endif
    }
    else
      return NS_OK;

    if (hideUI) {
      HideInlineTableEditingUI();
      if (hideResizersWithInlineTableUI)
        HideResizers();
    }
  }

  return NS_OK;
}
Example #4
0
NS_IMETHODIMP
TextEditRules::AfterEdit(EditAction action,
                         nsIEditor::EDirection aDirection)
{
  if (mLockRulesSniffing) {
    return NS_OK;
  }

  AutoLockRulesSniffing lockIt(this);

  NS_PRECONDITION(mActionNesting>0, "bad action nesting!");
  if (!--mActionNesting) {
    NS_ENSURE_STATE(mTextEditor);
    RefPtr<Selection> selection = mTextEditor->GetSelection();
    NS_ENSURE_STATE(selection);

    NS_ENSURE_STATE(mTextEditor);
    nsresult rv =
      mTextEditor->HandleInlineSpellCheck(action, selection,
                                          GetAsDOMNode(mCachedSelectionNode),
                                          mCachedSelectionOffset,
                                          nullptr, 0, nullptr, 0);
    NS_ENSURE_SUCCESS(rv, rv);

    // no longer uses mCachedSelectionNode, so release it.
    mCachedSelectionNode = nullptr;

    // if only trailing <br> remaining remove it
    rv = RemoveRedundantTrailingBR();
    if (NS_FAILED(rv)) {
      return rv;
    }

    // detect empty doc
    rv = CreateBogusNodeIfNeeded(selection);
    NS_ENSURE_SUCCESS(rv, rv);

    // ensure trailing br node
    rv = CreateTrailingBRIfNeeded();
    NS_ENSURE_SUCCESS(rv, rv);

    // collapse the selection to the trailing BR if it's at the end of our text node
    CollapseSelectionToTrailingBRIfNeeded(selection);
  }
  return NS_OK;
}