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 Communicator client 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
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 "mozilla/Util.h"
39 :
40 : #include "nsIDOMHTMLTableRowElement.h"
41 : #include "nsIDOMHTMLTableElement.h"
42 : #include "nsIDOMHTMLTableSectionElem.h"
43 : #include "nsIDOMHTMLTableCellElement.h"
44 : #include "nsIDOMEventTarget.h"
45 : #include "nsDOMError.h"
46 : #include "nsMappedAttributes.h"
47 : #include "nsGenericHTMLElement.h"
48 : #include "nsContentList.h"
49 : #include "nsGkAtoms.h"
50 : #include "nsStyleConsts.h"
51 : #include "nsHTMLParts.h"
52 : #include "nsRuleData.h"
53 : #include "nsContentUtils.h"
54 :
55 : using namespace mozilla;
56 :
57 : class nsHTMLTableRowElement : public nsGenericHTMLElement,
58 : public nsIDOMHTMLTableRowElement
59 0 : {
60 : public:
61 : nsHTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo);
62 :
63 : // nsISupports
64 : NS_DECL_ISUPPORTS_INHERITED
65 :
66 : // nsIDOMNode
67 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
68 :
69 : // nsIDOMElement
70 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
71 :
72 : // nsIDOMHTMLElement
73 0 : NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
74 :
75 : // nsIDOMHTMLTableRowElement
76 : NS_DECL_NSIDOMHTMLTABLEROWELEMENT
77 :
78 : virtual bool ParseAttribute(PRInt32 aNamespaceID,
79 : nsIAtom* aAttribute,
80 : const nsAString& aValue,
81 : nsAttrValue& aResult);
82 : virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
83 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
84 :
85 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
86 :
87 : virtual nsXPCClassInfo* GetClassInfo();
88 :
89 1464 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableRowElement,
90 : nsGenericHTMLElement)
91 :
92 : protected:
93 : nsresult GetSection(nsIDOMHTMLTableSectionElement** aSection);
94 : nsresult GetTable(nsIDOMHTMLTableElement** aTable);
95 : nsRefPtr<nsContentList> mCells;
96 : };
97 :
98 :
99 0 : NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow)
100 :
101 :
102 0 : nsHTMLTableRowElement::nsHTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
103 0 : : nsGenericHTMLElement(aNodeInfo)
104 : {
105 0 : }
106 :
107 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTableRowElement)
108 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTableRowElement,
109 : nsGenericHTMLElement)
110 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mCells,
111 : nsIDOMNodeList)
112 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
113 :
114 0 : NS_IMPL_ADDREF_INHERITED(nsHTMLTableRowElement, nsGenericElement)
115 0 : NS_IMPL_RELEASE_INHERITED(nsHTMLTableRowElement, nsGenericElement)
116 :
117 :
118 0 : DOMCI_NODE_DATA(HTMLTableRowElement, nsHTMLTableRowElement)
119 :
120 : // QueryInterface implementation for nsHTMLTableRowElement
121 0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLTableRowElement)
122 0 : NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLTableRowElement,
123 : nsIDOMHTMLTableRowElement)
124 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLTableRowElement,
125 : nsGenericHTMLElement)
126 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTableRowElement)
127 :
128 :
129 0 : NS_IMPL_ELEMENT_CLONE(nsHTMLTableRowElement)
130 :
131 :
132 : // protected method
133 : nsresult
134 0 : nsHTMLTableRowElement::GetSection(nsIDOMHTMLTableSectionElement** aSection)
135 : {
136 0 : NS_ENSURE_ARG_POINTER(aSection);
137 : nsCOMPtr<nsIDOMHTMLTableSectionElement> section =
138 0 : do_QueryInterface(GetParent());
139 0 : section.forget(aSection);
140 0 : return NS_OK;
141 : }
142 :
143 : // protected method
144 : nsresult
145 0 : nsHTMLTableRowElement::GetTable(nsIDOMHTMLTableElement** aTable)
146 : {
147 0 : NS_ENSURE_ARG_POINTER(aTable);
148 0 : *aTable = nsnull;
149 :
150 0 : nsIContent* parent = GetParent();
151 0 : if (!parent) {
152 0 : return NS_OK;
153 : }
154 :
155 : // We may not be in a section
156 0 : nsCOMPtr<nsIDOMHTMLTableElement> table = do_QueryInterface(parent);
157 0 : if (table) {
158 0 : table.forget(aTable);
159 0 : return NS_OK;
160 : }
161 :
162 0 : parent = parent->GetParent();
163 0 : if (!parent) {
164 0 : return NS_OK;
165 : }
166 0 : table = do_QueryInterface(parent);
167 0 : table.forget(aTable);
168 0 : return NS_OK;
169 : }
170 :
171 : NS_IMETHODIMP
172 0 : nsHTMLTableRowElement::GetRowIndex(PRInt32* aValue)
173 : {
174 0 : *aValue = -1;
175 0 : nsCOMPtr<nsIDOMHTMLTableElement> table;
176 0 : nsresult rv = GetTable(getter_AddRefs(table));
177 0 : if (NS_FAILED(rv) || !table) {
178 0 : return rv;
179 : }
180 :
181 0 : nsCOMPtr<nsIDOMHTMLCollection> rows;
182 0 : table->GetRows(getter_AddRefs(rows));
183 :
184 : PRUint32 numRows;
185 0 : rows->GetLength(&numRows);
186 :
187 0 : for (PRUint32 i = 0; i < numRows; i++) {
188 0 : if (rows->GetNodeAt(i) == static_cast<nsIContent*>(this)) {
189 0 : *aValue = i;
190 0 : break;
191 : }
192 : }
193 0 : return NS_OK;
194 : }
195 :
196 : NS_IMETHODIMP
197 0 : nsHTMLTableRowElement::GetSectionRowIndex(PRInt32* aValue)
198 : {
199 0 : *aValue = -1;
200 0 : nsCOMPtr<nsIDOMHTMLTableSectionElement> section;
201 0 : nsresult rv = GetSection(getter_AddRefs(section));
202 0 : if (NS_FAILED(rv) || !section) {
203 0 : return rv;
204 : }
205 :
206 0 : nsCOMPtr<nsIDOMHTMLCollection> rows;
207 0 : section->GetRows(getter_AddRefs(rows));
208 :
209 : PRUint32 numRows;
210 0 : rows->GetLength(&numRows);
211 0 : for (PRUint32 i = 0; i < numRows; i++) {
212 0 : if (rows->GetNodeAt(i) == static_cast<nsIContent*>(this)) {
213 0 : *aValue = i;
214 0 : break;
215 : }
216 : }
217 :
218 0 : return NS_OK;
219 : }
220 :
221 : static bool
222 0 : IsCell(nsIContent *aContent, PRInt32 aNamespaceID,
223 : nsIAtom* aAtom, void *aData)
224 : {
225 0 : nsIAtom* tag = aContent->Tag();
226 :
227 : return ((tag == nsGkAtoms::td || tag == nsGkAtoms::th) &&
228 0 : aContent->IsHTML());
229 : }
230 :
231 : NS_IMETHODIMP
232 0 : nsHTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
233 : {
234 0 : if (!mCells) {
235 : mCells = new nsContentList(this,
236 : IsCell,
237 : nsnull, // destroy func
238 : nsnull, // closure data
239 : false,
240 : nsnull,
241 : kNameSpaceID_XHTML,
242 0 : false);
243 : }
244 :
245 0 : NS_ADDREF(*aValue = mCells);
246 0 : return NS_OK;
247 : }
248 :
249 : NS_IMETHODIMP
250 0 : nsHTMLTableRowElement::InsertCell(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
251 : {
252 0 : *aValue = nsnull;
253 :
254 0 : if (aIndex < -1) {
255 0 : return NS_ERROR_DOM_INDEX_SIZE_ERR;
256 : }
257 :
258 : // Make sure mCells is initialized.
259 0 : nsCOMPtr<nsIDOMHTMLCollection> cells;
260 0 : nsresult rv = GetCells(getter_AddRefs(cells));
261 0 : if (NS_FAILED(rv)) {
262 0 : return rv;
263 : }
264 :
265 0 : NS_ASSERTION(mCells, "How did that happen?");
266 :
267 0 : nsCOMPtr<nsIDOMNode> nextSibling;
268 : // -1 means append, so should use null nextSibling
269 0 : if (aIndex != -1) {
270 0 : cells->Item(aIndex, getter_AddRefs(nextSibling));
271 : // Check whether we're inserting past end of list. We want to avoid doing
272 : // this unless we really have to, since this has to walk all our kids. If
273 : // we have a nextSibling, we're clearly not past end of list.
274 0 : if (!nextSibling) {
275 : PRUint32 cellCount;
276 0 : cells->GetLength(&cellCount);
277 0 : if (aIndex > PRInt32(cellCount)) {
278 0 : return NS_ERROR_DOM_INDEX_SIZE_ERR;
279 : }
280 : }
281 : }
282 :
283 : // create the cell
284 0 : nsCOMPtr<nsINodeInfo> nodeInfo;
285 : nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::td,
286 0 : getter_AddRefs(nodeInfo));
287 :
288 0 : nsCOMPtr<nsIContent> cellContent = NS_NewHTMLTableCellElement(nodeInfo.forget());
289 0 : if (!cellContent) {
290 0 : return NS_ERROR_OUT_OF_MEMORY;
291 : }
292 :
293 0 : nsCOMPtr<nsIDOMNode> cellNode(do_QueryInterface(cellContent));
294 0 : NS_ASSERTION(cellNode, "Should implement nsIDOMNode!");
295 :
296 0 : nsCOMPtr<nsIDOMNode> retChild;
297 0 : InsertBefore(cellNode, nextSibling, getter_AddRefs(retChild));
298 :
299 0 : if (retChild) {
300 0 : CallQueryInterface(retChild, aValue);
301 : }
302 :
303 0 : return NS_OK;
304 : }
305 :
306 :
307 : NS_IMETHODIMP
308 0 : nsHTMLTableRowElement::DeleteCell(PRInt32 aValue)
309 : {
310 0 : if (aValue < -1) {
311 0 : return NS_ERROR_DOM_INDEX_SIZE_ERR;
312 : }
313 :
314 0 : nsCOMPtr<nsIDOMHTMLCollection> cells;
315 0 : GetCells(getter_AddRefs(cells));
316 :
317 : nsresult rv;
318 : PRUint32 refIndex;
319 0 : if (aValue == -1) {
320 0 : rv = cells->GetLength(&refIndex);
321 0 : NS_ENSURE_SUCCESS(rv, rv);
322 :
323 0 : if (refIndex == 0) {
324 0 : return NS_OK;
325 : }
326 :
327 0 : --refIndex;
328 : }
329 : else {
330 0 : refIndex = (PRUint32)aValue;
331 : }
332 :
333 0 : nsCOMPtr<nsIDOMNode> cell;
334 0 : rv = cells->Item(refIndex, getter_AddRefs(cell));
335 0 : NS_ENSURE_SUCCESS(rv, rv);
336 :
337 0 : if (!cell) {
338 0 : return NS_ERROR_DOM_INDEX_SIZE_ERR;
339 : }
340 :
341 0 : nsCOMPtr<nsIDOMNode> retChild;
342 0 : return RemoveChild(cell, getter_AddRefs(retChild));
343 : }
344 :
345 0 : NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, Align, align)
346 0 : NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, BgColor, bgcolor)
347 0 : NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, Ch, _char)
348 0 : NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, ChOff, charoff)
349 0 : NS_IMPL_STRING_ATTR(nsHTMLTableRowElement, VAlign, valign)
350 :
351 :
352 : bool
353 0 : nsHTMLTableRowElement::ParseAttribute(PRInt32 aNamespaceID,
354 : nsIAtom* aAttribute,
355 : const nsAString& aValue,
356 : nsAttrValue& aResult)
357 : {
358 : /*
359 : * ignore these attributes, stored simply as strings
360 : *
361 : * ch
362 : */
363 :
364 0 : if (aNamespaceID == kNameSpaceID_None) {
365 0 : if (aAttribute == nsGkAtoms::charoff) {
366 0 : return aResult.ParseIntWithBounds(aValue, 0);
367 : }
368 0 : if (aAttribute == nsGkAtoms::height) {
369 0 : return aResult.ParseSpecialIntValue(aValue);
370 : }
371 0 : if (aAttribute == nsGkAtoms::width) {
372 0 : return aResult.ParseSpecialIntValue(aValue);
373 : }
374 0 : if (aAttribute == nsGkAtoms::align) {
375 0 : return ParseTableCellHAlignValue(aValue, aResult);
376 : }
377 0 : if (aAttribute == nsGkAtoms::bgcolor) {
378 0 : return aResult.ParseColor(aValue);
379 : }
380 0 : if (aAttribute == nsGkAtoms::valign) {
381 0 : return ParseTableVAlignValue(aValue, aResult);
382 : }
383 : }
384 :
385 : return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
386 0 : aResult);
387 : }
388 :
389 : static
390 0 : void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
391 : {
392 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
393 : // height: value
394 0 : nsCSSValue* height = aData->ValueForHeight();
395 0 : if (height->GetUnit() == eCSSUnit_Null) {
396 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
397 0 : if (value && value->Type() == nsAttrValue::eInteger)
398 0 : height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
399 0 : else if (value && value->Type() == nsAttrValue::ePercent)
400 0 : height->SetPercentValue(value->GetPercentValue());
401 : }
402 : }
403 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
404 0 : nsCSSValue* textAlign = aData->ValueForTextAlign();
405 0 : if (textAlign->GetUnit() == eCSSUnit_Null) {
406 : // align: enum
407 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
408 0 : if (value && value->Type() == nsAttrValue::eEnum)
409 0 : textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
410 : }
411 : }
412 0 : if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TextReset)) {
413 0 : nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
414 0 : if (verticalAlign->GetUnit() == eCSSUnit_Null) {
415 : // valign: enum
416 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
417 0 : if (value && value->Type() == nsAttrValue::eEnum)
418 0 : verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
419 : }
420 : }
421 :
422 0 : nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
423 0 : nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
424 0 : }
425 :
426 : NS_IMETHODIMP_(bool)
427 0 : nsHTMLTableRowElement::IsAttributeMapped(const nsIAtom* aAttribute) const
428 : {
429 : static const MappedAttributeEntry attributes[] = {
430 : { &nsGkAtoms::align },
431 : { &nsGkAtoms::valign },
432 : { &nsGkAtoms::height },
433 : { nsnull }
434 : };
435 :
436 : static const MappedAttributeEntry* const map[] = {
437 : attributes,
438 : sCommonAttributeMap,
439 : sBackgroundAttributeMap,
440 : };
441 :
442 0 : return FindAttributeDependence(aAttribute, map);
443 : }
444 :
445 : nsMapRuleToAttributesFunc
446 0 : nsHTMLTableRowElement::GetAttributeMappingFunction() const
447 : {
448 0 : return &MapAttributesIntoRule;
449 4392 : }
|