1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998-1999
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "CreateElementTxn.h"
39 : #include "nsEditor.h"
40 : #include "nsIDOMDocument.h"
41 : #include "nsIDOMNodeList.h"
42 : #include "nsISelection.h"
43 : #include "nsIDOMElement.h"
44 : #include "nsReadableUtils.h"
45 :
46 : //included for new nsEditor::CreateContent()
47 : #include "nsIContent.h"
48 :
49 : #ifdef NS_DEBUG
50 : static bool gNoisy = false;
51 : #endif
52 :
53 0 : CreateElementTxn::CreateElementTxn()
54 0 : : EditTxn()
55 : {
56 0 : }
57 :
58 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(CreateElementTxn)
59 :
60 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CreateElementTxn, EditTxn)
61 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
62 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNewNode)
63 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRefNode)
64 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
65 :
66 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CreateElementTxn, EditTxn)
67 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
68 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNewNode)
69 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRefNode)
70 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
71 :
72 0 : NS_IMPL_ADDREF_INHERITED(CreateElementTxn, EditTxn)
73 0 : NS_IMPL_RELEASE_INHERITED(CreateElementTxn, EditTxn)
74 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTxn)
75 0 : NS_INTERFACE_MAP_END_INHERITING(EditTxn)
76 0 : NS_IMETHODIMP CreateElementTxn::Init(nsEditor *aEditor,
77 : const nsAString &aTag,
78 : nsIDOMNode *aParent,
79 : PRUint32 aOffsetInParent)
80 : {
81 0 : NS_ASSERTION(aEditor&&aParent, "null args");
82 0 : if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; }
83 :
84 0 : mEditor = aEditor;
85 0 : mTag = aTag;
86 0 : mParent = do_QueryInterface(aParent);
87 0 : mOffsetInParent = aOffsetInParent;
88 : #ifdef NS_DEBUG
89 : {
90 0 : nsCOMPtr<nsIDOMNodeList> testChildNodes;
91 0 : nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes));
92 0 : NS_ASSERTION(testChildNodes, "bad parent type, can't have children.");
93 0 : NS_ASSERTION(NS_SUCCEEDED(testResult), "bad result.");
94 : }
95 : #endif
96 0 : return NS_OK;
97 : }
98 :
99 :
100 0 : NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
101 : {
102 : #ifdef NS_DEBUG
103 0 : if (gNoisy)
104 : {
105 0 : char* nodename = ToNewCString(mTag);
106 : printf("Do Create Element parent = %p <%s>, offset = %d\n",
107 0 : static_cast<void*>(mParent.get()), nodename, mOffsetInParent);
108 0 : nsMemory::Free(nodename);
109 : }
110 : #endif
111 :
112 0 : NS_ASSERTION(mEditor && mParent, "bad state");
113 0 : NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
114 :
115 0 : nsCOMPtr<nsIContent> newContent;
116 :
117 : //new call to use instead to get proper HTML element, bug# 39919
118 0 : nsresult result = mEditor->CreateHTMLContent(mTag, getter_AddRefs(newContent));
119 0 : NS_ENSURE_SUCCESS(result, result);
120 0 : nsCOMPtr<nsIDOMElement>newElement = do_QueryInterface(newContent);
121 0 : NS_ENSURE_TRUE(newElement, NS_ERROR_NULL_POINTER);
122 0 : mNewNode = do_QueryInterface(newElement);
123 : // Try to insert formatting whitespace for the new node:
124 0 : mEditor->MarkNodeDirty(mNewNode);
125 :
126 0 : NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
127 0 : NS_ENSURE_TRUE(mNewNode, NS_ERROR_NULL_POINTER);
128 :
129 : #ifdef NS_DEBUG
130 0 : if (gNoisy)
131 : {
132 0 : printf(" newNode = %p\n", static_cast<void*>(mNewNode.get()));
133 : }
134 : #endif
135 :
136 : // insert the new node
137 0 : nsCOMPtr<nsIDOMNode> resultNode;
138 0 : if (CreateElementTxn::eAppend==(PRInt32)mOffsetInParent)
139 : {
140 0 : result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
141 : }
142 : else
143 : {
144 0 : nsCOMPtr<nsIDOMNodeList> childNodes;
145 0 : result = mParent->GetChildNodes(getter_AddRefs(childNodes));
146 0 : if ((NS_SUCCEEDED(result)) && (childNodes))
147 : {
148 : PRUint32 count;
149 0 : childNodes->GetLength(&count);
150 0 : if (mOffsetInParent>count)
151 0 : mOffsetInParent = count;
152 0 : result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
153 0 : NS_ENSURE_SUCCESS(result, result); // note, it's ok for mRefNode to be null. that means append
154 :
155 0 : result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
156 0 : NS_ENSURE_SUCCESS(result, result);
157 :
158 : // only set selection to insertion point if editor gives permission
159 : bool bAdjustSelection;
160 0 : mEditor->ShouldTxnSetSelection(&bAdjustSelection);
161 0 : if (bAdjustSelection)
162 : {
163 0 : nsCOMPtr<nsISelection> selection;
164 0 : result = mEditor->GetSelection(getter_AddRefs(selection));
165 0 : NS_ENSURE_SUCCESS(result, result);
166 0 : NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
167 :
168 0 : PRInt32 offset=0;
169 0 : result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
170 0 : NS_ENSURE_SUCCESS(result, result);
171 :
172 0 : result = selection->Collapse(mParent, offset+1);
173 0 : NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
174 : }
175 : else
176 : {
177 : // do nothing - dom range gravity will adjust selection
178 : }
179 : }
180 : }
181 0 : return result;
182 : }
183 :
184 0 : NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
185 : {
186 : #ifdef NS_DEBUG
187 0 : if (gNoisy)
188 : {
189 : printf("Undo Create Element, mParent = %p, node = %p\n",
190 0 : static_cast<void*>(mParent.get()),
191 0 : static_cast<void*>(mNewNode.get()));
192 : }
193 : #endif
194 :
195 0 : NS_ASSERTION(mEditor && mParent, "bad state");
196 0 : NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
197 :
198 0 : nsCOMPtr<nsIDOMNode> resultNode;
199 0 : return mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
200 : }
201 :
202 0 : NS_IMETHODIMP CreateElementTxn::RedoTransaction(void)
203 : {
204 : #ifdef NS_DEBUG
205 0 : if (gNoisy) { printf("Redo Create Element\n"); }
206 : #endif
207 :
208 0 : NS_ASSERTION(mEditor && mParent, "bad state");
209 0 : NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
210 :
211 : // first, reset mNewNode so it has no attributes or content
212 0 : nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(mNewNode);
213 0 : if (nodeAsText)
214 : {
215 0 : nodeAsText->SetData(EmptyString());
216 : }
217 :
218 : // now, reinsert mNewNode
219 0 : nsCOMPtr<nsIDOMNode> resultNode;
220 0 : return mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
221 : }
222 :
223 0 : NS_IMETHODIMP CreateElementTxn::GetTxnDescription(nsAString& aString)
224 : {
225 0 : aString.AssignLiteral("CreateElementTxn: ");
226 0 : aString += mTag;
227 0 : return NS_OK;
228 : }
229 :
230 0 : NS_IMETHODIMP CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode)
231 : {
232 0 : NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER);
233 0 : NS_ENSURE_TRUE(mNewNode, NS_ERROR_NOT_INITIALIZED);
234 0 : *aNewNode = mNewNode;
235 0 : NS_ADDREF(*aNewNode);
236 0 : return NS_OK;
237 4392 : }
|