~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/content/html/content/src/nsHTMLTableElement.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
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
 *
 
25
 * Alternatively, the contents of this file may be used under the terms of
 
26
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
27
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
28
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
29
 * of those above. If you wish to allow use of your version of this file only
 
30
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
31
 * use your version of this file under the terms of the NPL, indicate your
 
32
 * decision by deleting the provisions above and replace them with the notice
 
33
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
34
 * the provisions above, a recipient may use your version of this file under
 
35
 * the terms of any one of the NPL, the GPL or the LGPL.
 
36
 *
 
37
 * ***** END LICENSE BLOCK ***** */
 
38
#include "nsIDOMHTMLTableElement.h"
 
39
#include "nsIDOMHTMLTableCaptionElem.h"
 
40
#include "nsIDOMHTMLTableSectionElem.h"
 
41
#include "nsCOMPtr.h"
 
42
#include "nsIDOMEventReceiver.h"
 
43
#include "nsDOMError.h"
 
44
#include "GenericElementCollection.h"
 
45
#include "nsIHTMLContent.h"
 
46
#include "nsMappedAttributes.h"
 
47
#include "nsGenericHTMLElement.h"
 
48
#include "nsHTMLAtoms.h"
 
49
#include "nsStyleConsts.h"
 
50
#include "nsIPresContext.h"
 
51
#include "nsHTMLParts.h"
 
52
#include "nsRuleNode.h"
 
53
#include "nsStyleContext.h"
 
54
#include "nsIDocument.h"
 
55
 
 
56
/* for collections */
 
57
#include "nsIDOMElement.h"
 
58
#include "nsGenericHTMLElement.h"
 
59
/* end for collections */
 
60
 
 
61
class GenericElementCollection;
 
62
class TableRowsCollection;
 
63
 
 
64
class nsHTMLTableElement :  public nsGenericHTMLElement,
 
65
                            public nsIDOMHTMLTableElement
 
66
{
 
67
public:
 
68
  nsHTMLTableElement();
 
69
  virtual ~nsHTMLTableElement();
 
70
 
 
71
  // nsISupports
 
72
  NS_DECL_ISUPPORTS_INHERITED
 
73
 
 
74
  // nsIDOMNode
 
75
  NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
 
76
 
 
77
  // nsIDOMElement
 
78
  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
79
 
 
80
  // nsIDOMHTMLElement
 
81
  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
82
 
 
83
  // nsIDOMHTMLTableElement
 
84
  NS_DECL_NSIDOMHTMLTABLEELEMENT
 
85
 
 
86
  virtual PRBool ParseAttribute(nsIAtom* aAttribute,
 
87
                                const nsAString& aValue,
 
88
                                nsAttrValue& aResult);
 
89
  NS_IMETHOD AttributeToString(nsIAtom* aAttribute,
 
90
                               const nsHTMLValue& aValue,
 
91
                               nsAString& aResult) const;
 
92
  NS_IMETHOD GetAttributeMappingFunction(nsMapRuleToAttributesFunc& aMapRuleFunc) const;
 
93
  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
94
 
 
95
protected:
 
96
  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
 
97
 
 
98
  GenericElementCollection *mTBodies;
 
99
  TableRowsCollection *mRows;
 
100
};
 
101
 
 
102
 
 
103
/* ------------------------------ TableRowsCollection -------------------------------- */
 
104
/**
 
105
 * This class provides a late-bound collection of rows in a table.
 
106
 * mParent is NOT ref-counted to avoid circular references
 
107
 */
 
108
class TableRowsCollection : public nsGenericDOMHTMLCollection 
 
109
{
 
110
public:
 
111
  TableRowsCollection(nsHTMLTableElement *aParent);
 
112
  virtual ~TableRowsCollection();
 
113
 
 
114
  NS_IMETHOD    GetLength(PRUint32* aLength);
 
115
  NS_IMETHOD    Item(PRUint32 aIndex, nsIDOMNode** aReturn);
 
116
  NS_IMETHOD    NamedItem(const nsAString& aName,
 
117
                          nsIDOMNode** aReturn);
 
118
 
 
119
  NS_IMETHOD    ParentDestroyed();
 
120
 
 
121
protected:
 
122
  nsHTMLTableElement * mParent;
 
123
};
 
124
 
 
125
 
 
126
TableRowsCollection::TableRowsCollection(nsHTMLTableElement *aParent)
 
127
  : nsGenericDOMHTMLCollection()
 
128
{
 
129
  mParent = aParent;
 
130
}
 
131
 
 
132
TableRowsCollection::~TableRowsCollection()
 
133
{
 
134
  // we do NOT have a ref-counted reference to mParent, so do NOT
 
135
  // release it!  this is to avoid circular references.  The
 
136
  // instantiator who provided mParent is responsible for managing our
 
137
  // reference for us.
 
138
}
 
139
 
 
140
// we re-count every call.  A better implementation would be to set
 
141
// ourselves up as an observer of contentAppended, contentInserted,
 
142
// and contentDeleted
 
143
NS_IMETHODIMP 
 
144
TableRowsCollection::GetLength(PRUint32* aLength)
 
145
{
 
146
  NS_ENSURE_ARG_POINTER(aLength);
 
147
 
 
148
  *aLength=0;
 
149
  nsresult rv = NS_OK;
 
150
 
 
151
  if (mParent) {
 
152
    // count the rows in the thead, tfoot, and all tbodies
 
153
    nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;
 
154
 
 
155
    mParent->GetTHead(getter_AddRefs(rowGroup));
 
156
 
 
157
    if (rowGroup) {
 
158
      nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
 
159
 
 
160
      GenericElementCollection head(content, nsHTMLAtoms::tr);
 
161
 
 
162
      PRUint32 rows;
 
163
      head.GetLength(&rows);
 
164
 
 
165
      *aLength = rows;
 
166
    }
 
167
 
 
168
    mParent->GetTFoot(getter_AddRefs(rowGroup));
 
169
 
 
170
    if (rowGroup) {
 
171
      nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
 
172
 
 
173
      GenericElementCollection foot(content, nsHTMLAtoms::tr);
 
174
 
 
175
      PRUint32 rows;
 
176
      foot.GetLength(&rows);
 
177
      *aLength += rows;
 
178
    }
 
179
 
 
180
    nsCOMPtr<nsIDOMHTMLCollection> tbodies;
 
181
 
 
182
    mParent->GetTBodies(getter_AddRefs(tbodies));
 
183
 
 
184
    if (tbodies) {
 
185
      nsCOMPtr<nsIDOMNode> node;
 
186
 
 
187
      rowGroup = nsnull;
 
188
 
 
189
      PRUint32 theIndex=0;
 
190
 
 
191
      tbodies->Item(theIndex, getter_AddRefs(node));
 
192
 
 
193
      while (node) {
 
194
        nsCOMPtr<nsIContent> content(do_QueryInterface(node));
 
195
 
 
196
        GenericElementCollection body(content, nsHTMLAtoms::tr);
 
197
 
 
198
        PRUint32 rows;
 
199
        body.GetLength(&rows);
 
200
 
 
201
        *aLength += rows;
 
202
 
 
203
        theIndex++;
 
204
 
 
205
        tbodies->Item(theIndex, getter_AddRefs(node));
 
206
      }
 
207
    }
 
208
  }
 
209
 
 
210
  return rv;
 
211
}
 
212
 
 
213
// increments aReturn refcnt by 1
 
214
NS_IMETHODIMP 
 
215
TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 
216
{
 
217
  *aReturn = nsnull;
 
218
  nsresult rv = NS_OK;
 
219
  PRUint32 count = 0;
 
220
 
 
221
  if (mParent) {
 
222
    nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;
 
223
 
 
224
    // check the thead
 
225
    mParent->GetTHead(getter_AddRefs(rowGroup));
 
226
 
 
227
    if (rowGroup) {
 
228
      nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
 
229
 
 
230
      GenericElementCollection head(content, nsHTMLAtoms::tr);
 
231
 
 
232
      PRUint32 rowsInHead;
 
233
      head.GetLength(&rowsInHead);
 
234
 
 
235
      count = rowsInHead;
 
236
 
 
237
      if (count > aIndex) {
 
238
        head.Item(aIndex, aReturn);
 
239
        return NS_OK; 
 
240
      }
 
241
    }
 
242
 
 
243
    // check the tbodies
 
244
    nsCOMPtr<nsIDOMHTMLCollection> tbodies;
 
245
 
 
246
    mParent->GetTBodies(getter_AddRefs(tbodies));
 
247
 
 
248
    if (tbodies) {
 
249
      rowGroup = nsnull;
 
250
      nsCOMPtr<nsIDOMNode> node;
 
251
      PRUint32 theIndex=0;
 
252
 
 
253
      tbodies->Item(theIndex, getter_AddRefs(node));
 
254
 
 
255
      while (node) {
 
256
        nsCOMPtr<nsIContent> content(do_QueryInterface(node));
 
257
 
 
258
        GenericElementCollection body(content, nsHTMLAtoms::tr);
 
259
 
 
260
        PRUint32 rows;
 
261
        body.GetLength(&rows);
 
262
 
 
263
        if ((count+rows) > aIndex) {
 
264
          body.Item(aIndex-count, aReturn);
 
265
 
 
266
                      return NS_OK;
 
267
        }
 
268
 
 
269
        count += rows;
 
270
        theIndex++;
 
271
        tbodies->Item(theIndex, getter_AddRefs(node));
 
272
      }
 
273
    }
 
274
 
 
275
    // check the tfoot
 
276
    mParent->GetTFoot(getter_AddRefs(rowGroup));
 
277
 
 
278
    if (rowGroup) {
 
279
      nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
 
280
 
 
281
      GenericElementCollection foot(content, nsHTMLAtoms::tr);
 
282
      foot.Item(aIndex-count, aReturn);
 
283
    }
 
284
  }
 
285
 
 
286
  return rv;
 
287
}
 
288
 
 
289
NS_IMETHODIMP 
 
290
TableRowsCollection::NamedItem(const nsAString& aName,
 
291
                               nsIDOMNode** aReturn)
 
292
{
 
293
  NS_ENSURE_ARG_POINTER(aReturn);
 
294
 
 
295
  // FIXME: Implement this!
 
296
 
 
297
  *aReturn = nsnull;
 
298
 
 
299
  return NS_OK;
 
300
}
 
301
 
 
302
NS_IMETHODIMP
 
303
TableRowsCollection::ParentDestroyed()
 
304
{
 
305
  // see comment in destructor, do NOT release mParent!
 
306
  mParent = nsnull;
 
307
 
 
308
  return NS_OK;
 
309
}
 
310
 
 
311
/* -------------------------- nsHTMLTableElement --------------------------- */
 
312
// the class declaration is at the top of this file
 
313
 
 
314
nsresult
 
315
NS_NewHTMLTableElement(nsIHTMLContent** aInstancePtrResult,
 
316
                       nsINodeInfo *aNodeInfo, PRBool aFromParser)
 
317
{
 
318
  NS_ENSURE_ARG_POINTER(aInstancePtrResult);
 
319
 
 
320
  nsHTMLTableElement* it = new nsHTMLTableElement();
 
321
 
 
322
  if (!it) {
 
323
    return NS_ERROR_OUT_OF_MEMORY;
 
324
  }
 
325
 
 
326
  nsresult rv = it->Init(aNodeInfo);
 
327
 
 
328
  if (NS_FAILED(rv)) {
 
329
    delete it;
 
330
 
 
331
    return rv;
 
332
  }
 
333
 
 
334
  *aInstancePtrResult = NS_STATIC_CAST(nsIHTMLContent *, it);
 
335
  NS_ADDREF(*aInstancePtrResult);
 
336
 
 
337
  return NS_OK;
 
338
}
 
339
 
 
340
 
 
341
nsHTMLTableElement::nsHTMLTableElement()
 
342
{
 
343
  mTBodies=nsnull;
 
344
  mRows=nsnull;
 
345
}
 
346
 
 
347
nsHTMLTableElement::~nsHTMLTableElement()
 
348
{
 
349
  if (mTBodies) {
 
350
    mTBodies->ParentDestroyed();
 
351
    NS_RELEASE(mTBodies);
 
352
  }
 
353
 
 
354
  if (mRows) {
 
355
    mRows->ParentDestroyed();
 
356
    NS_RELEASE(mRows);
 
357
  }
 
358
}
 
359
 
 
360
 
 
361
NS_IMPL_ADDREF_INHERITED(nsHTMLTableElement, nsGenericElement) 
 
362
NS_IMPL_RELEASE_INHERITED(nsHTMLTableElement, nsGenericElement) 
 
363
 
 
364
 
 
365
// QueryInterface implementation for nsHTMLTableElement
 
366
NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLTableElement, nsGenericHTMLElement)
 
367
  NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLTableElement)
 
368
  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLTableElement)
 
369
NS_HTML_CONTENT_INTERFACE_MAP_END
 
370
 
 
371
 
 
372
nsresult
 
373
nsHTMLTableElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
 
374
{
 
375
  NS_ENSURE_ARG_POINTER(aReturn);
 
376
  *aReturn = nsnull;
 
377
 
 
378
  nsHTMLTableElement* it = new nsHTMLTableElement();
 
379
 
 
380
  if (!it) {
 
381
    return NS_ERROR_OUT_OF_MEMORY;
 
382
  }
 
383
 
 
384
  nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
 
385
 
 
386
  nsresult rv = it->Init(mNodeInfo);
 
387
 
 
388
  if (NS_FAILED(rv))
 
389
    return rv;
 
390
 
 
391
  CopyInnerTo(it, aDeep);
 
392
 
 
393
  *aReturn = NS_STATIC_CAST(nsIDOMNode *, it);
 
394
 
 
395
  NS_ADDREF(*aReturn);
 
396
 
 
397
  return NS_OK;
 
398
}
 
399
 
 
400
 
 
401
// the DOM spec says border, cellpadding, cellSpacing are all "wstring"
 
402
// in fact, they are integers or they are meaningless.  so we store them
 
403
// here as ints.
 
404
 
 
405
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Align, align)
 
406
NS_IMPL_STRING_ATTR(nsHTMLTableElement, BgColor, bgcolor)
 
407
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Border, border)
 
408
NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellPadding, cellpadding)
 
409
NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellSpacing, cellspacing)
 
410
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Frame, frame)
 
411
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Rules, rules)
 
412
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Summary, summary)
 
413
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Width, width)
 
414
 
 
415
 
 
416
NS_IMETHODIMP
 
417
nsHTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
 
418
{
 
419
  *aValue = nsnull;
 
420
  nsCOMPtr<nsIDOMNode> child;
 
421
  GetFirstChild(getter_AddRefs(child));
 
422
 
 
423
  while (child) {
 
424
    nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption(do_QueryInterface(child));
 
425
 
 
426
    if (caption) {
 
427
      *aValue = caption;
 
428
      NS_ADDREF(*aValue);
 
429
 
 
430
      break;
 
431
    }
 
432
 
 
433
    nsIDOMNode *temp = child.get();
 
434
    temp->GetNextSibling(getter_AddRefs(child));
 
435
  }
 
436
 
 
437
  return NS_OK;
 
438
}
 
439
 
 
440
NS_IMETHODIMP
 
441
nsHTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
 
442
{
 
443
  nsresult rv = DeleteCaption();
 
444
 
 
445
  if (NS_SUCCEEDED(rv)) {
 
446
    if (aValue) {
 
447
      nsCOMPtr<nsIDOMNode> resultingChild;
 
448
      AppendChild(aValue, getter_AddRefs(resultingChild));
 
449
    }
 
450
  }
 
451
 
 
452
  return rv;
 
453
}
 
454
 
 
455
already_AddRefed<nsIDOMHTMLTableSectionElement>
 
456
nsHTMLTableElement::GetSection(nsIAtom *aTag)
 
457
{
 
458
  PRUint32 childCount = GetChildCount();
 
459
 
 
460
  nsCOMPtr<nsIDOMHTMLTableSectionElement> section;
 
461
 
 
462
  for (PRUint32 i = 0; i < childCount; ++i) {
 
463
    nsIContent *child = GetChildAt(i);
 
464
 
 
465
    section = do_QueryInterface(child);
 
466
 
 
467
    if (section && child->GetNodeInfo()->Equals(aTag)) {
 
468
      nsIDOMHTMLTableSectionElement *result = section;
 
469
      NS_ADDREF(result);
 
470
 
 
471
      return result;
 
472
    }
 
473
  }
 
474
 
 
475
  return nsnull;
 
476
}
 
477
 
 
478
NS_IMETHODIMP
 
479
nsHTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
 
480
{
 
481
  *aValue = GetSection(nsHTMLAtoms::thead).get();
 
482
 
 
483
  return NS_OK;
 
484
}
 
485
 
 
486
NS_IMETHODIMP
 
487
nsHTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
 
488
{
 
489
  nsresult rv = DeleteTHead();
 
490
  if (NS_FAILED(rv)) {
 
491
    return rv;
 
492
  }
 
493
 
 
494
  if (aValue) {
 
495
    nsCOMPtr<nsIDOMNode> child;
 
496
    rv = GetFirstChild(getter_AddRefs(child));
 
497
    if (NS_FAILED(rv)) {
 
498
      return rv;
 
499
    }
 
500
     
 
501
    nsCOMPtr<nsIDOMNode> resultChild;
 
502
    rv = InsertBefore(aValue, child, getter_AddRefs(resultChild));
 
503
  }
 
504
 
 
505
  return rv;
 
506
}
 
507
 
 
508
NS_IMETHODIMP
 
509
nsHTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
 
510
{
 
511
  *aValue = GetSection(nsHTMLAtoms::tfoot).get();
 
512
 
 
513
  return NS_OK;
 
514
}
 
515
 
 
516
NS_IMETHODIMP
 
517
nsHTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
 
518
{
 
519
  nsresult rv = DeleteTFoot();
 
520
  if (NS_SUCCEEDED(rv)) {
 
521
    if (aValue) {
 
522
      nsCOMPtr<nsIDOMNode> resultingChild;
 
523
      AppendChild(aValue, getter_AddRefs(resultingChild));
 
524
    }
 
525
  }
 
526
 
 
527
  return rv;
 
528
}
 
529
 
 
530
NS_IMETHODIMP
 
531
nsHTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
 
532
{
 
533
  if (!mRows) {
 
534
    // XXX why was this here NS_ADDREF(nsHTMLAtoms::tr);
 
535
    mRows = new TableRowsCollection(this);
 
536
    NS_ENSURE_TRUE(mRows, NS_ERROR_OUT_OF_MEMORY);
 
537
 
 
538
    NS_ADDREF(mRows); // this table's reference, released in the destructor
 
539
  }
 
540
 
 
541
  *aValue = mRows;
 
542
  NS_ADDREF(*aValue);
 
543
 
 
544
  return NS_OK;
 
545
}
 
546
 
 
547
NS_IMETHODIMP
 
548
nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
 
549
{
 
550
  if (!mTBodies) {
 
551
    mTBodies = new GenericElementCollection((nsIContent*)this,
 
552
                                            nsHTMLAtoms::tbody);
 
553
 
 
554
    NS_ENSURE_TRUE(mTBodies, NS_ERROR_OUT_OF_MEMORY);
 
555
 
 
556
    NS_ADDREF(mTBodies); // this table's reference, released in the destructor
 
557
  }
 
558
 
 
559
  return CallQueryInterface(mTBodies, aValue);
 
560
}
 
561
 
 
562
NS_IMETHODIMP
 
563
nsHTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
 
564
{
 
565
  *aValue = nsnull;
 
566
  nsresult rv = NS_OK;
 
567
  nsCOMPtr<nsIDOMHTMLTableSectionElement> head;
 
568
 
 
569
  GetTHead(getter_AddRefs(head));
 
570
 
 
571
  if (head) { // return the existing thead
 
572
    CallQueryInterface(head, aValue);
 
573
 
 
574
    NS_ASSERTION(*aValue, "head must be a DOMHTMLElement");
 
575
  }
 
576
  else
 
577
  { // create a new head rowgroup
 
578
    nsCOMPtr<nsIHTMLContent> newHead;
 
579
    nsCOMPtr<nsINodeInfo> nodeInfo;
 
580
 
 
581
    mNodeInfo->NameChanged(nsHTMLAtoms::thead, getter_AddRefs(nodeInfo));
 
582
 
 
583
    rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newHead),nodeInfo);
 
584
 
 
585
    if (NS_SUCCEEDED(rv) && newHead) {
 
586
      nsCOMPtr<nsIDOMNode> child;
 
587
 
 
588
      rv = GetFirstChild(getter_AddRefs(child));
 
589
 
 
590
      if (NS_FAILED(rv)) {
 
591
        return rv;
 
592
      }
 
593
 
 
594
      CallQueryInterface(newHead, aValue);
 
595
 
 
596
      nsCOMPtr<nsIDOMNode> resultChild;
 
597
      rv = InsertBefore(*aValue, child, getter_AddRefs(resultChild));
 
598
    }
 
599
  }
 
600
 
 
601
  return NS_OK;
 
602
}
 
603
 
 
604
NS_IMETHODIMP
 
605
nsHTMLTableElement::DeleteTHead()
 
606
{
 
607
  nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
 
608
  nsresult rv = GetTHead(getter_AddRefs(childToDelete));
 
609
 
 
610
  if ((NS_SUCCEEDED(rv)) && childToDelete) {
 
611
    nsCOMPtr<nsIDOMNode> resultingChild;
 
612
    // mInner does the notification
 
613
    RemoveChild(childToDelete, getter_AddRefs(resultingChild));
 
614
  }
 
615
 
 
616
  return NS_OK;
 
617
}
 
618
 
 
619
NS_IMETHODIMP
 
620
nsHTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
 
621
{
 
622
  *aValue = nsnull;
 
623
  nsresult rv = NS_OK;
 
624
  nsCOMPtr<nsIDOMHTMLTableSectionElement> foot;
 
625
 
 
626
  GetTFoot(getter_AddRefs(foot));
 
627
 
 
628
  if (foot) { // return the existing tfoot
 
629
    CallQueryInterface(foot, aValue);
 
630
 
 
631
    NS_ASSERTION(*aValue, "foot must be a DOMHTMLElement");
 
632
  }
 
633
  else
 
634
  { // create a new foot rowgroup
 
635
    nsCOMPtr<nsIHTMLContent> newFoot;
 
636
 
 
637
    nsCOMPtr<nsINodeInfo> nodeInfo;
 
638
    mNodeInfo->NameChanged(nsHTMLAtoms::tfoot, getter_AddRefs(nodeInfo));
 
639
 
 
640
    rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newFoot),nodeInfo);
 
641
 
 
642
    if (NS_SUCCEEDED(rv) && newFoot) {
 
643
      rv = AppendChildTo(newFoot, PR_TRUE, PR_FALSE);
 
644
      CallQueryInterface(newFoot, aValue);
 
645
    }
 
646
  }
 
647
 
 
648
  return NS_OK;
 
649
}
 
650
 
 
651
NS_IMETHODIMP
 
652
nsHTMLTableElement::DeleteTFoot()
 
653
{
 
654
  nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
 
655
  nsresult rv = GetTFoot(getter_AddRefs(childToDelete));
 
656
 
 
657
  if ((NS_SUCCEEDED(rv)) && childToDelete) {
 
658
    nsCOMPtr<nsIDOMNode> resultingChild;
 
659
    // mInner does the notification
 
660
    RemoveChild(childToDelete, getter_AddRefs(resultingChild));
 
661
  }
 
662
 
 
663
  return NS_OK;
 
664
}
 
665
 
 
666
NS_IMETHODIMP
 
667
nsHTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
 
668
{
 
669
  *aValue = nsnull;
 
670
  nsresult rv = NS_OK;
 
671
  nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption;
 
672
 
 
673
  GetCaption(getter_AddRefs(caption));
 
674
 
 
675
  if (caption) { // return the existing thead
 
676
    CallQueryInterface(caption, aValue);
 
677
 
 
678
    NS_ASSERTION(*aValue, "caption must be a DOMHTMLElement");
 
679
  }
 
680
  else
 
681
  { // create a new head rowgroup
 
682
    nsCOMPtr<nsIHTMLContent> newCaption;
 
683
 
 
684
    nsCOMPtr<nsINodeInfo> nodeInfo;
 
685
    mNodeInfo->NameChanged(nsHTMLAtoms::caption, getter_AddRefs(nodeInfo));
 
686
 
 
687
    rv = NS_NewHTMLTableCaptionElement(getter_AddRefs(newCaption),nodeInfo);
 
688
 
 
689
    if (NS_SUCCEEDED(rv) && newCaption) {
 
690
      rv = AppendChildTo(newCaption, PR_TRUE, PR_FALSE);
 
691
      CallQueryInterface(newCaption, aValue);
 
692
    }
 
693
  }
 
694
 
 
695
  return NS_OK;
 
696
}
 
697
 
 
698
NS_IMETHODIMP
 
699
nsHTMLTableElement::DeleteCaption()
 
700
{
 
701
  nsCOMPtr<nsIDOMHTMLTableCaptionElement> childToDelete;
 
702
  nsresult rv = GetCaption(getter_AddRefs(childToDelete));
 
703
 
 
704
  if ((NS_SUCCEEDED(rv)) && childToDelete) {
 
705
    nsCOMPtr<nsIDOMNode> resultingChild;
 
706
    RemoveChild(childToDelete, getter_AddRefs(resultingChild));
 
707
  }
 
708
 
 
709
  return NS_OK;
 
710
}
 
711
 
 
712
NS_IMETHODIMP
 
713
nsHTMLTableElement::InsertRow(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
 
714
{
 
715
  /* get the ref row at aIndex
 
716
     if there is one, 
 
717
       get it's parent
 
718
       insert the new row just before the ref row
 
719
     else
 
720
       get the first row group
 
721
       insert the new row as its first child
 
722
  */
 
723
  *aValue = nsnull;
 
724
 
 
725
  if (aIndex < -1) {
 
726
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
727
  }
 
728
 
 
729
  nsresult rv;
 
730
 
 
731
  nsCOMPtr<nsIDOMHTMLCollection> rows;
 
732
  GetRows(getter_AddRefs(rows));
 
733
 
 
734
  PRUint32 rowCount;
 
735
  rows->GetLength(&rowCount);
 
736
 
 
737
  if ((PRUint32)aIndex > rowCount && aIndex != -1) {
 
738
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
739
  }
 
740
 
 
741
  // use local variable refIndex so we can remember original aIndex
 
742
  PRUint32 refIndex = (PRUint32)aIndex;
 
743
 
 
744
  if (rowCount > 0) {
 
745
    if (refIndex == rowCount || aIndex == -1) {
 
746
      // we set refIndex to the last row so we can get the last row's
 
747
      // parent we then do an AppendChild below if (rowCount<aIndex)
 
748
 
 
749
      refIndex = rowCount - 1;
 
750
    }
 
751
 
 
752
    nsCOMPtr<nsIDOMNode> refRow;
 
753
    rows->Item(refIndex, getter_AddRefs(refRow));
 
754
 
 
755
    nsCOMPtr<nsIDOMNode> parent;
 
756
 
 
757
    refRow->GetParentNode(getter_AddRefs(parent));
 
758
    // create the row
 
759
 
 
760
    nsCOMPtr<nsIHTMLContent> newRow;
 
761
 
 
762
    nsCOMPtr<nsINodeInfo> nodeInfo;
 
763
    mNodeInfo->NameChanged(nsHTMLAtoms::tr, getter_AddRefs(nodeInfo));
 
764
 
 
765
    rv = NS_NewHTMLTableRowElement(getter_AddRefs(newRow), nodeInfo);
 
766
 
 
767
    if (NS_SUCCEEDED(rv) && newRow) {
 
768
      nsCOMPtr<nsIDOMNode> newRowNode(do_QueryInterface(newRow));
 
769
      nsCOMPtr<nsIDOMNode> retChild;
 
770
 
 
771
      // If index is -1 or equal to the number of rows, the new row
 
772
      // is appended.
 
773
      if (aIndex == -1 || PRUint32(aIndex) == rowCount) {
 
774
        rv = parent->AppendChild(newRowNode, getter_AddRefs(retChild));
 
775
      }
 
776
      else
 
777
      {
 
778
        // insert the new row before the reference row we found above
 
779
        rv = parent->InsertBefore(newRowNode, refRow,
 
780
                                  getter_AddRefs(retChild));
 
781
      }
 
782
 
 
783
      if (retChild) {
 
784
        CallQueryInterface(retChild, aValue);
 
785
      }
 
786
    }
 
787
  }
 
788
  else
 
789
  { // the row count was 0, so 
 
790
    // find the first row group and insert there as first child
 
791
    nsCOMPtr<nsIDOMNode> rowGroup;
 
792
 
 
793
    GenericElementCollection head(this, nsHTMLAtoms::thead);
 
794
 
 
795
    PRUint32 length = 0;
 
796
 
 
797
    head.GetLength(&length);
 
798
 
 
799
    if (0 != length) {
 
800
      head.Item(0, getter_AddRefs(rowGroup));
 
801
    }
 
802
    else
 
803
    {
 
804
      GenericElementCollection body(this, nsHTMLAtoms::tbody);
 
805
      length = 0;
 
806
 
 
807
      body.GetLength(&length);
 
808
 
 
809
      if (length > 0) {
 
810
        body.Item(0, getter_AddRefs(rowGroup));
 
811
      }
 
812
      else
 
813
      {
 
814
        GenericElementCollection foot(this, nsHTMLAtoms::tfoot);
 
815
 
 
816
        length = 0;
 
817
 
 
818
        foot.GetLength(&length);
 
819
 
 
820
        if (length > 0) {
 
821
          foot.Item(0, getter_AddRefs(rowGroup));
 
822
        }
 
823
      }
 
824
    }
 
825
 
 
826
    if (!rowGroup) { // need to create a TBODY
 
827
      nsCOMPtr<nsIHTMLContent> newRowGroup;
 
828
 
 
829
      nsCOMPtr<nsINodeInfo> nodeInfo;
 
830
      mNodeInfo->NameChanged(nsHTMLAtoms::tbody, getter_AddRefs(nodeInfo));
 
831
 
 
832
      rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newRowGroup),
 
833
                                         nodeInfo);
 
834
 
 
835
      if (NS_SUCCEEDED(rv) && newRowGroup) {
 
836
        rv = AppendChildTo(newRowGroup, PR_TRUE, PR_FALSE);
 
837
 
 
838
        rowGroup = do_QueryInterface(newRowGroup);
 
839
      }
 
840
    }
 
841
 
 
842
    if (rowGroup) {
 
843
      nsCOMPtr<nsIHTMLContent> newRow;
 
844
 
 
845
      nsCOMPtr<nsINodeInfo> nodeInfo;
 
846
      mNodeInfo->NameChanged(nsHTMLAtoms::tr, getter_AddRefs(nodeInfo));
 
847
 
 
848
      rv = NS_NewHTMLTableRowElement(getter_AddRefs(newRow), nodeInfo);
 
849
      nsCOMPtr<nsIContent> rowGroupContent(do_QueryInterface(rowGroup));
 
850
 
 
851
      GenericElementCollection rowGroupRows(rowGroupContent, nsHTMLAtoms::tr);
 
852
 
 
853
      nsCOMPtr<nsIDOMNode> firstRow;
 
854
 
 
855
      // it's ok if this returns nsnull
 
856
      rowGroupRows.Item(0, getter_AddRefs(firstRow));
 
857
 
 
858
      if (newRow) {
 
859
        nsCOMPtr<nsIDOMNode> retNode, newRowNode(do_QueryInterface(newRow));
 
860
 
 
861
        rowGroup->InsertBefore(newRowNode, firstRow, getter_AddRefs(retNode));
 
862
 
 
863
        if (retNode) {
 
864
          CallQueryInterface(retNode, aValue);
 
865
        }
 
866
      }
 
867
    }
 
868
  }
 
869
 
 
870
  return NS_OK;
 
871
}
 
872
 
 
873
NS_IMETHODIMP
 
874
nsHTMLTableElement::DeleteRow(PRInt32 aValue)
 
875
{
 
876
  if (aValue < -1) {
 
877
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
878
  }
 
879
 
 
880
  nsCOMPtr<nsIDOMHTMLCollection> rows;
 
881
  GetRows(getter_AddRefs(rows));
 
882
 
 
883
  nsresult rv;
 
884
  PRUint32 refIndex;
 
885
  if (aValue == -1) {
 
886
    rv = rows->GetLength(&refIndex);
 
887
    NS_ENSURE_SUCCESS(rv, rv);
 
888
 
 
889
    if (refIndex == 0) {
 
890
      return NS_OK;
 
891
    }
 
892
 
 
893
    --refIndex;
 
894
  }
 
895
  else {
 
896
    refIndex = (PRUint32)aValue;
 
897
  }
 
898
 
 
899
  nsCOMPtr<nsIDOMNode> row;
 
900
  rv = rows->Item(refIndex, getter_AddRefs(row));
 
901
  NS_ENSURE_SUCCESS(rv, rv);
 
902
 
 
903
  if (!row) {
 
904
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
 
905
  }
 
906
 
 
907
  nsCOMPtr<nsIDOMNode> parent;
 
908
  row->GetParentNode(getter_AddRefs(parent));
 
909
  NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
 
910
 
 
911
  nsCOMPtr<nsIDOMNode> deleted_row;
 
912
  return parent->RemoveChild(row, getter_AddRefs(deleted_row));
 
913
}
 
914
 
 
915
static const nsHTMLValue::EnumTable kFrameTable[] = {
 
916
  { "void",   NS_STYLE_TABLE_FRAME_NONE },
 
917
  { "above",  NS_STYLE_TABLE_FRAME_ABOVE },
 
918
  { "below",  NS_STYLE_TABLE_FRAME_BELOW },
 
919
  { "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
 
920
  { "lhs",    NS_STYLE_TABLE_FRAME_LEFT },
 
921
  { "rhs",    NS_STYLE_TABLE_FRAME_RIGHT },
 
922
  { "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
 
923
  { "box",    NS_STYLE_TABLE_FRAME_BOX },
 
924
  { "border", NS_STYLE_TABLE_FRAME_BORDER },
 
925
  { 0 }
 
926
};
 
927
 
 
928
static const nsHTMLValue::EnumTable kRulesTable[] = {
 
929
  { "none",   NS_STYLE_TABLE_RULES_NONE },
 
930
  { "groups", NS_STYLE_TABLE_RULES_GROUPS },
 
931
  { "rows",   NS_STYLE_TABLE_RULES_ROWS },
 
932
  { "cols",   NS_STYLE_TABLE_RULES_COLS },
 
933
  { "all",    NS_STYLE_TABLE_RULES_ALL },
 
934
  { 0 }
 
935
};
 
936
 
 
937
static const nsHTMLValue::EnumTable kLayoutTable[] = {
 
938
  { "auto",   NS_STYLE_TABLE_LAYOUT_AUTO },
 
939
  { "fixed",  NS_STYLE_TABLE_LAYOUT_FIXED },
 
940
  { 0 }
 
941
};
 
942
 
 
943
 
 
944
PRBool
 
945
nsHTMLTableElement::ParseAttribute(nsIAtom* aAttribute,
 
946
                                   const nsAString& aValue,
 
947
                                   nsAttrValue& aResult)
 
948
{
 
949
  /* ignore summary, just a string */
 
950
  if (aAttribute == nsHTMLAtoms::cellspacing ||
 
951
      aAttribute == nsHTMLAtoms::cellpadding) {
 
952
    return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
 
953
  }
 
954
  if (aAttribute == nsHTMLAtoms::cols) {
 
955
    return aResult.ParseIntWithBounds(aValue, 0);
 
956
  }
 
957
  if (aAttribute == nsHTMLAtoms::border) {
 
958
    if (!aResult.ParseIntWithBounds(aValue, 0)) {
 
959
      // XXX this should really be NavQuirks only to allow non numeric value
 
960
      aResult.SetTo(1, nsAttrValue::eInteger);
 
961
    }
 
962
 
 
963
    return PR_TRUE;
 
964
  }
 
965
  if (aAttribute == nsHTMLAtoms::height) {
 
966
    return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
 
967
  }
 
968
  if (aAttribute == nsHTMLAtoms::width) {
 
969
    if (aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE)) {
 
970
      // treat 0 width as auto
 
971
      nsAttrValue::ValueType type = aResult.Type();
 
972
      if ((type == nsAttrValue::eInteger && aResult.GetIntegerValue() == 0) ||
 
973
          (type == nsAttrValue::ePercent && aResult.GetPercentValue() == 0.0f)) {
 
974
        return PR_FALSE;
 
975
      }
 
976
    }
 
977
    return PR_TRUE;
 
978
  }
 
979
  if (aAttribute == nsHTMLAtoms::align) {
 
980
    return ParseTableHAlignValue(aValue, aResult);
 
981
  }
 
982
  if (aAttribute == nsHTMLAtoms::bgcolor ||
 
983
           aAttribute == nsHTMLAtoms::bordercolor) {
 
984
    return aResult.ParseColor(aValue, nsGenericHTMLElement::GetOwnerDocument());
 
985
  }
 
986
  if (aAttribute == nsHTMLAtoms::frame) {
 
987
    return aResult.ParseEnumValue(aValue, kFrameTable);
 
988
  }
 
989
  if (aAttribute == nsHTMLAtoms::layout) {
 
990
    return aResult.ParseEnumValue(aValue, kLayoutTable);
 
991
  }
 
992
  if (aAttribute == nsHTMLAtoms::rules) {
 
993
    return aResult.ParseEnumValue(aValue, kRulesTable);
 
994
  }
 
995
  if (aAttribute == nsHTMLAtoms::hspace ||
 
996
           aAttribute == nsHTMLAtoms::vspace) {
 
997
    return aResult.ParseIntWithBounds(aValue, 0);
 
998
  }
 
999
 
 
1000
  return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
 
1001
}
 
1002
 
 
1003
NS_IMETHODIMP
 
1004
nsHTMLTableElement::AttributeToString(nsIAtom* aAttribute,
 
1005
                               const nsHTMLValue& aValue,
 
1006
                               nsAString& aResult) const
 
1007
{
 
1008
  /* ignore summary, just a string */
 
1009
  /* ignore attributes that are of standard types border, cellpadding,
 
1010
     cellspacing, cols, height, width, background, bgcolor */
 
1011
  if (aAttribute == nsHTMLAtoms::align) {
 
1012
    if (TableHAlignValueToString(aValue, aResult)) {
 
1013
      return NS_CONTENT_ATTR_HAS_VALUE;
 
1014
    }
 
1015
  }
 
1016
  else if (aAttribute == nsHTMLAtoms::frame) {
 
1017
    if (aValue.EnumValueToString(kFrameTable, aResult)) {
 
1018
      return NS_CONTENT_ATTR_HAS_VALUE;
 
1019
    }
 
1020
  }
 
1021
  else if (aAttribute == nsHTMLAtoms::layout) {
 
1022
    if (aValue.EnumValueToString(kLayoutTable, aResult)) {
 
1023
      return NS_CONTENT_ATTR_HAS_VALUE;
 
1024
    }
 
1025
  }
 
1026
  else if (aAttribute == nsHTMLAtoms::rules) {
 
1027
    if (aValue.EnumValueToString(kRulesTable, aResult)) {
 
1028
      return NS_CONTENT_ATTR_HAS_VALUE;
 
1029
    }
 
1030
  }
 
1031
 
 
1032
  return nsGenericHTMLElement::AttributeToString(aAttribute, aValue, aResult);
 
1033
}
 
1034
 
 
1035
static void 
 
1036
MapTableFrameInto(const nsMappedAttributes* aAttributes,
 
1037
                  nsRuleData* aData, PRUint8 aBorderStyle)
 
1038
{
 
1039
  if (!aData->mMarginData)
 
1040
    return;
 
1041
 
 
1042
  // set up defaults
 
1043
  if (aData->mMarginData->mBorderStyle.mLeft.GetUnit() == eCSSUnit_Null)
 
1044
    aData->mMarginData->mBorderStyle.mLeft.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
 
1045
  if (aData->mMarginData->mBorderStyle.mRight.GetUnit() == eCSSUnit_Null)
 
1046
    aData->mMarginData->mBorderStyle.mRight.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
 
1047
  if (aData->mMarginData->mBorderStyle.mTop.GetUnit() == eCSSUnit_Null)
 
1048
    aData->mMarginData->mBorderStyle.mTop.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
 
1049
  if (aData->mMarginData->mBorderStyle.mBottom.GetUnit() == eCSSUnit_Null)
 
1050
    aData->mMarginData->mBorderStyle.mBottom.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
 
1051
 
 
1052
  nsHTMLValue frameValue;
 
1053
  // 0 out the sides that we want to hide based on the frame attribute
 
1054
  aAttributes->GetAttribute(nsHTMLAtoms::frame, frameValue);
 
1055
 
 
1056
  if (frameValue.GetUnit() == eHTMLUnit_Enumerated) {
 
1057
    // adjust the border style based on the value of frame
 
1058
    switch (frameValue.GetIntValue())
 
1059
    {
 
1060
    case NS_STYLE_TABLE_FRAME_NONE:
 
1061
      aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1062
      aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1063
      aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1064
      aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1065
      break;
 
1066
    case NS_STYLE_TABLE_FRAME_ABOVE:
 
1067
      aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1068
      aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1069
      aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1070
      break;
 
1071
    case NS_STYLE_TABLE_FRAME_BELOW: 
 
1072
      aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1073
      aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1074
      aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1075
      break;
 
1076
    case NS_STYLE_TABLE_FRAME_HSIDES:
 
1077
      aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1078
      aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1079
      break;
 
1080
    case NS_STYLE_TABLE_FRAME_LEFT:
 
1081
      aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1082
      aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1083
      aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1084
      break;
 
1085
    case NS_STYLE_TABLE_FRAME_RIGHT:
 
1086
      aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1087
      aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1088
      aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1089
      break;
 
1090
    case NS_STYLE_TABLE_FRAME_VSIDES:
 
1091
      aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1092
      aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
 
1093
      break;
 
1094
    // BOX and BORDER are ignored, the caller has already set all the border sides
 
1095
    // any illegal value is also ignored
 
1096
    }
 
1097
  }
 
1098
}
 
1099
 
 
1100
static void 
 
1101
MapTableBorderInto(const nsMappedAttributes* aAttributes,
 
1102
                   nsRuleData* aData, PRUint8 aBorderStyle)
 
1103
{
 
1104
  nsHTMLValue borderValue;
 
1105
  if (aAttributes->GetAttribute(nsHTMLAtoms::border, borderValue) ==
 
1106
      NS_CONTENT_ATTR_NOT_THERE) {
 
1107
    // the absence of "border" with the presence of "frame" implies
 
1108
    // border = 1 pixel
 
1109
    if (!aAttributes->GetAttr(nsHTMLAtoms::frame)) {
 
1110
      return;
 
1111
    }
 
1112
    borderValue.SetIntValue(1, eHTMLUnit_Integer);
 
1113
  }
 
1114
 
 
1115
  if (borderValue.GetUnit() != eHTMLUnit_Integer) {
 
1116
    // empty values of border get rules=all and frame=border
 
1117
    if (aData->mTableData) {
 
1118
      aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_ALL, eCSSUnit_Enumerated);
 
1119
      aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_BORDER, eCSSUnit_Enumerated);
 
1120
    }
 
1121
    borderValue.SetIntValue(1, eHTMLUnit_Integer);
 
1122
  }
 
1123
  else {
 
1124
    PRInt32 borderThickness = borderValue.GetIntValue();
 
1125
 
 
1126
    if (0 != borderThickness) {
 
1127
      // border != 0 implies rules=all and frame=border
 
1128
      if (aData->mTableData) {
 
1129
        aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_ALL, eCSSUnit_Enumerated);
 
1130
        aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_BORDER, eCSSUnit_Enumerated);
 
1131
      }
 
1132
    }
 
1133
    else {
 
1134
      // border = 0 implies rules=none and frame=void
 
1135
      if (aData->mTableData) {
 
1136
        aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_NONE, eCSSUnit_Enumerated);
 
1137
        aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_NONE, eCSSUnit_Enumerated);
 
1138
      }
 
1139
    }
 
1140
  }
 
1141
 
 
1142
  PRInt32 borderThickness = borderValue.GetIntValue();
 
1143
 
 
1144
  if (aData->mMarginData) {
 
1145
    // by default, set all border sides to the specified width
 
1146
    if (aData->mMarginData->mBorderWidth.mLeft.GetUnit() == eCSSUnit_Null)
 
1147
      aData->mMarginData->mBorderWidth.mLeft.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
 
1148
    if (aData->mMarginData->mBorderWidth.mRight.GetUnit() == eCSSUnit_Null)
 
1149
      aData->mMarginData->mBorderWidth.mRight.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
 
1150
    if (aData->mMarginData->mBorderWidth.mTop.GetUnit() == eCSSUnit_Null)
 
1151
      aData->mMarginData->mBorderWidth.mTop .SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
 
1152
    if (aData->mMarginData->mBorderWidth.mBottom.GetUnit() == eCSSUnit_Null)
 
1153
      aData->mMarginData->mBorderWidth.mBottom.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
 
1154
 
 
1155
    // now account for the frame attribute
 
1156
    MapTableFrameInto(aAttributes, aData, aBorderStyle);
 
1157
  }
 
1158
}
 
1159
 
 
1160
static void
 
1161
MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
 
1162
                      nsRuleData* aData)
 
1163
{
 
1164
  // XXX Bug 211636:  This function is used by a single style rule
 
1165
  // that's used to match two different type of elements -- tables, and
 
1166
  // table cells.  (nsHTMLTableCellElement overrides
 
1167
  // WalkContentStyleRules so that this happens.)  This violates the
 
1168
  // nsIStyleRule contract, since it's the same style rule object doing
 
1169
  // the mapping in two different ways.  It's also incorrect since it's
 
1170
  // testing the display type of the style context rather than checking
 
1171
  // which *element* it's matching (style rules should not stop matching
 
1172
  // when the display type is changed).
 
1173
 
 
1174
  nsCompatibility mode = aData->mPresContext->CompatibilityMode();
 
1175
 
 
1176
  if (aData->mSID == eStyleStruct_TableBorder) {
 
1177
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1178
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
 
1179
      // cellspacing 
 
1180
      nsHTMLValue value;
 
1181
      aAttributes->GetAttribute(nsHTMLAtoms::cellspacing, value);
 
1182
      if (value.GetUnit() == eHTMLUnit_Integer) {
 
1183
        if (aData->mTableData->mBorderSpacingX.GetUnit() == eCSSUnit_Null)
 
1184
          aData->mTableData->mBorderSpacingX.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1185
        if (aData->mTableData->mBorderSpacingY.GetUnit() == eCSSUnit_Null)
 
1186
          aData->mTableData->mBorderSpacingY.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1187
      }
 
1188
      else if ((value.GetUnit() == eHTMLUnit_Percent) && (eCompatibility_NavQuirks == mode)) {
 
1189
        // in quirks mode, treat a % cellspacing value a pixel value.
 
1190
        if (aData->mTableData->mBorderSpacingX.GetUnit() == eCSSUnit_Null)
 
1191
          aData->mTableData->mBorderSpacingX.SetFloatValue(100.0f * value.GetPercentValue(), eCSSUnit_Pixel);
 
1192
        if (aData->mTableData->mBorderSpacingY.GetUnit() == eCSSUnit_Null)
 
1193
          aData->mTableData->mBorderSpacingY.SetFloatValue(100.0f * value.GetPercentValue(), eCSSUnit_Pixel);
 
1194
      }
 
1195
    }
 
1196
  } 
 
1197
  else if (aData->mSID == eStyleStruct_Table) {
 
1198
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1199
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
 
1200
      MapTableBorderInto(aAttributes, aData, 0);
 
1201
 
 
1202
      nsHTMLValue value;
 
1203
      // layout
 
1204
      if (aData->mTableData->mLayout.GetUnit() == eCSSUnit_Null) {
 
1205
        aAttributes->GetAttribute(nsHTMLAtoms::layout, value);
 
1206
        if (value.GetUnit() == eHTMLUnit_Enumerated)
 
1207
          aData->mTableData->mLayout.SetIntValue(value.GetIntValue(), eCSSUnit_Enumerated);
 
1208
      }
 
1209
      
 
1210
      // cols
 
1211
      if (aAttributes->GetAttribute(nsHTMLAtoms::cols, value) !=
 
1212
          NS_CONTENT_ATTR_NOT_THERE) {
 
1213
        if (value.GetUnit() == eHTMLUnit_Integer) 
 
1214
          aData->mTableData->mCols.SetIntValue(value.GetIntValue(), eCSSUnit_Integer);
 
1215
        else // COLS had no value, so it refers to all columns
 
1216
          aData->mTableData->mCols.SetIntValue(NS_STYLE_TABLE_COLS_ALL, eCSSUnit_Enumerated);
 
1217
      }
 
1218
 
 
1219
      // rules
 
1220
      aAttributes->GetAttribute(nsHTMLAtoms::rules, value);
 
1221
      if (value.GetUnit() == eHTMLUnit_Enumerated)
 
1222
        aData->mTableData->mRules.SetIntValue(value.GetIntValue(), eCSSUnit_Enumerated);
 
1223
    }
 
1224
  }
 
1225
  else if (aData->mSID == eStyleStruct_Margin) {
 
1226
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1227
  
 
1228
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
 
1229
      // align; Check for enumerated type (it may be another type if
 
1230
      // illegal)
 
1231
      nsHTMLValue value;
 
1232
      aAttributes->GetAttribute(nsHTMLAtoms::align, value);
 
1233
 
 
1234
      if (value.GetUnit() == eHTMLUnit_Enumerated) {
 
1235
        if ((NS_STYLE_TEXT_ALIGN_CENTER == value.GetIntValue()) ||
 
1236
            (NS_STYLE_TEXT_ALIGN_MOZ_CENTER == value.GetIntValue())) {
 
1237
          nsCSSRect& margin = aData->mMarginData->mMargin;
 
1238
          if (margin.mLeft.GetUnit() == eCSSUnit_Null)
 
1239
            margin.mLeft.SetAutoValue();
 
1240
          if (margin.mRight.GetUnit() == eCSSUnit_Null)
 
1241
            margin.mRight.SetAutoValue();
 
1242
        }
 
1243
      }
 
1244
 
 
1245
      // hspace is mapped into left and right margin, 
 
1246
      // vspace is mapped into top and bottom margins
 
1247
      // - *** Quirks Mode only ***
 
1248
      if (eCompatibility_NavQuirks == mode) {
 
1249
        aAttributes->GetAttribute(nsHTMLAtoms::hspace, value);
 
1250
 
 
1251
        if (value.GetUnit() == eHTMLUnit_Integer) {
 
1252
          nsCSSRect& margin = aData->mMarginData->mMargin;
 
1253
          if (margin.mLeft.GetUnit() == eCSSUnit_Null)
 
1254
            margin.mLeft.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel); 
 
1255
          if (margin.mRight.GetUnit() == eCSSUnit_Null)
 
1256
            margin.mRight.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1257
        }
 
1258
 
 
1259
        aAttributes->GetAttribute(nsHTMLAtoms::vspace, value);
 
1260
 
 
1261
        if (value.GetUnit() == eHTMLUnit_Integer) {
 
1262
          nsCSSRect& margin = aData->mMarginData->mMargin;
 
1263
          if (margin.mTop.GetUnit() == eCSSUnit_Null)
 
1264
            margin.mTop.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel); 
 
1265
          if (margin.mBottom.GetUnit() == eCSSUnit_Null)
 
1266
            margin.mBottom.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel); 
 
1267
        }
 
1268
      }
 
1269
    }
 
1270
  }
 
1271
  else if (aData->mSID == eStyleStruct_Padding) {
 
1272
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1273
  
 
1274
    if (readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
 
1275
      nsHTMLValue value;
 
1276
      aAttributes->GetAttribute(nsHTMLAtoms::cellpadding, value);
 
1277
      if (value.GetUnit() == eHTMLUnit_Integer || value.GetUnit() == eHTMLUnit_Percent) {
 
1278
        // We have cellpadding.  This will override our padding values if we don't
 
1279
        // have any set.
 
1280
        nsCSSValue padVal;
 
1281
        if (value.GetUnit() == eHTMLUnit_Integer)
 
1282
          padVal.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1283
        else {
 
1284
          // when we support % cellpadding in standard mode, uncomment the following
 
1285
          float pctVal = value.GetPercentValue();
 
1286
          //if (eCompatibility_NavQuirks == mode) {
 
1287
            // in quirks mode treat a pct cellpadding value as a pixel value
 
1288
            padVal.SetFloatValue(100.0f * pctVal, eCSSUnit_Pixel);
 
1289
          //}
 
1290
          //else {
 
1291
          //  padVal.SetPercentValue(pctVal);
 
1292
          //}
 
1293
        }
 
1294
        if (aData->mMarginData->mPadding.mLeft.GetUnit() == eCSSUnit_Null)
 
1295
          aData->mMarginData->mPadding.mLeft = padVal;
 
1296
        if (aData->mMarginData->mPadding.mRight.GetUnit() == eCSSUnit_Null)
 
1297
          aData->mMarginData->mPadding.mRight = padVal;
 
1298
        if (aData->mMarginData->mPadding.mTop.GetUnit() == eCSSUnit_Null)
 
1299
          aData->mMarginData->mPadding.mTop = padVal;
 
1300
        if (aData->mMarginData->mPadding.mBottom.GetUnit() == eCSSUnit_Null)
 
1301
          aData->mMarginData->mPadding.mBottom = padVal;
 
1302
      }
 
1303
    }
 
1304
  }
 
1305
  else if (aData->mSID == eStyleStruct_Position) {
 
1306
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1307
  
 
1308
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
 
1309
      nsHTMLValue value;
 
1310
      // width: value
 
1311
      if (aData->mPositionData->mWidth.GetUnit() == eCSSUnit_Null) {
 
1312
        aAttributes->GetAttribute(nsHTMLAtoms::width, value);
 
1313
        if (value.GetUnit() == eHTMLUnit_Integer) 
 
1314
          aData->mPositionData->mWidth.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1315
        else if (value.GetUnit() == eHTMLUnit_Percent)
 
1316
          aData->mPositionData->mWidth.SetPercentValue(value.GetPercentValue());
 
1317
      }
 
1318
 
 
1319
      // height: value
 
1320
      if (aData->mPositionData->mHeight.GetUnit() == eCSSUnit_Null) {
 
1321
        aAttributes->GetAttribute(nsHTMLAtoms::height, value);
 
1322
        if (value.GetUnit() == eHTMLUnit_Integer) 
 
1323
          aData->mPositionData->mHeight.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
 
1324
        else if (value.GetUnit() == eHTMLUnit_Percent)
 
1325
          aData->mPositionData->mHeight.SetPercentValue(value.GetPercentValue()); 
 
1326
      }
 
1327
    }
 
1328
  }
 
1329
  else if (aData->mSID == eStyleStruct_Visibility) {
 
1330
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1331
  
 
1332
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
 
1333
      nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 
1334
  }
 
1335
  else if (aData->mSID == eStyleStruct_Border) {
 
1336
    if (!aData->mStyleContext) return;
 
1337
    const nsStyleTableBorder* tableStyle = aData->mStyleContext->GetStyleTableBorder();
 
1338
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1339
    if (readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
 
1340
      if (NS_STYLE_BORDER_SEPARATE == tableStyle->mBorderCollapse) {
 
1341
        // Set the cell's border from the table in the separate border model. If there is a border
 
1342
        // on the table, then the mapping to rules=all will take care of borders in the collapsing model.
 
1343
        nsHTMLValue value;
 
1344
        if (aAttributes->GetAttribute(nsHTMLAtoms::border, value) !=
 
1345
            NS_CONTENT_ATTR_NOT_THERE &&
 
1346
            ((value.GetUnit() == eHTMLUnit_Integer &&
 
1347
              value.GetIntValue() > 0) ||
 
1348
             value.IsEmptyString())) {
 
1349
          if (aData->mMarginData->mBorderWidth.mLeft.GetUnit() == eCSSUnit_Null)
 
1350
            aData->mMarginData->mBorderWidth.mLeft.SetFloatValue(1.0f, eCSSUnit_Pixel);
 
1351
          if (aData->mMarginData->mBorderWidth.mRight.GetUnit() == eCSSUnit_Null)
 
1352
            aData->mMarginData->mBorderWidth.mRight.SetFloatValue(1.0f, eCSSUnit_Pixel);
 
1353
          if (aData->mMarginData->mBorderWidth.mTop.GetUnit() == eCSSUnit_Null)
 
1354
            aData->mMarginData->mBorderWidth.mTop.SetFloatValue(1.0f, eCSSUnit_Pixel);
 
1355
          if (aData->mMarginData->mBorderWidth.mBottom.GetUnit() == eCSSUnit_Null)
 
1356
            aData->mMarginData->mBorderWidth.mBottom.SetFloatValue(1.0f, eCSSUnit_Pixel);
 
1357
 
 
1358
          PRUint8 borderStyle = (eCompatibility_NavQuirks == mode) 
 
1359
                                ? NS_STYLE_BORDER_STYLE_BG_INSET : NS_STYLE_BORDER_STYLE_INSET;
 
1360
          // BG_INSET results in a border color based on background colors
 
1361
          // used for NavQuirks only...
 
1362
 
 
1363
          if (aData->mMarginData->mBorderStyle.mLeft.GetUnit() == eCSSUnit_Null)
 
1364
            aData->mMarginData->mBorderStyle.mLeft.SetIntValue(borderStyle, eCSSUnit_Enumerated);
 
1365
          if (aData->mMarginData->mBorderStyle.mRight.GetUnit() == eCSSUnit_Null)
 
1366
            aData->mMarginData->mBorderStyle.mRight.SetIntValue(borderStyle, eCSSUnit_Enumerated);
 
1367
          if (aData->mMarginData->mBorderStyle.mTop.GetUnit() == eCSSUnit_Null)
 
1368
            aData->mMarginData->mBorderStyle.mTop.SetIntValue(borderStyle, eCSSUnit_Enumerated);
 
1369
          if (aData->mMarginData->mBorderStyle.mBottom.GetUnit() == eCSSUnit_Null)
 
1370
            aData->mMarginData->mBorderStyle.mBottom.SetIntValue(borderStyle, eCSSUnit_Enumerated);
 
1371
        }
 
1372
      }
 
1373
    }
 
1374
    else {
 
1375
      // default border style is the Nav4.6 extension which uses the
 
1376
      // background color as the basis of the outset border. If the
 
1377
      // table has a transparent background then it finds the closest
 
1378
      // ancestor that has a non-transparent
 
1379
      // background. NS_STYLE_BORDER_OUTSET uses the border color of
 
1380
      // the table and if that is not set, then it uses the color.
 
1381
 
 
1382
      PRUint8 borderStyle = (eCompatibility_NavQuirks == mode) 
 
1383
                            ? NS_STYLE_BORDER_STYLE_BG_OUTSET :
 
1384
                              NS_STYLE_BORDER_STYLE_OUTSET;
 
1385
      // bordercolor
 
1386
      nsHTMLValue value;
 
1387
      nscolor color;
 
1388
      if (aAttributes->GetAttribute(nsHTMLAtoms::bordercolor, value) !=
 
1389
          NS_CONTENT_ATTR_NOT_THERE &&
 
1390
          value.GetColorValue(color)) {
 
1391
        if (aData->mMarginData->mBorderColor.mLeft.GetUnit() == eCSSUnit_Null)
 
1392
          aData->mMarginData->mBorderColor.mLeft.SetColorValue(color);
 
1393
        if (aData->mMarginData->mBorderColor.mRight.GetUnit() == eCSSUnit_Null)
 
1394
          aData->mMarginData->mBorderColor.mRight.SetColorValue(color);
 
1395
        if (aData->mMarginData->mBorderColor.mTop.GetUnit() == eCSSUnit_Null)
 
1396
          aData->mMarginData->mBorderColor.mTop.SetColorValue(color);
 
1397
        if (aData->mMarginData->mBorderColor.mBottom.GetUnit() == eCSSUnit_Null)
 
1398
          aData->mMarginData->mBorderColor.mBottom.SetColorValue(color);
 
1399
 
 
1400
        borderStyle = NS_STYLE_BORDER_STYLE_OUTSET; // use css outset
 
1401
      }
 
1402
      else if (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse) {
 
1403
        // make the color grey
 
1404
        nscolor color = NS_RGB(80, 80, 80);
 
1405
        if (aData->mMarginData->mBorderColor.mLeft.GetUnit() == eCSSUnit_Null)
 
1406
          aData->mMarginData->mBorderColor.mLeft.SetColorValue(color);
 
1407
        if (aData->mMarginData->mBorderColor.mRight.GetUnit() == eCSSUnit_Null)
 
1408
          aData->mMarginData->mBorderColor.mRight.SetColorValue(color);
 
1409
        if (aData->mMarginData->mBorderColor.mTop.GetUnit() == eCSSUnit_Null)
 
1410
          aData->mMarginData->mBorderColor.mTop.SetColorValue(color);
 
1411
        if (aData->mMarginData->mBorderColor.mBottom.GetUnit() == eCSSUnit_Null)
 
1412
          aData->mMarginData->mBorderColor.mBottom.SetColorValue(color);
 
1413
      }
 
1414
 
 
1415
      // border and frame
 
1416
      MapTableBorderInto(aAttributes, aData, borderStyle);
 
1417
    }
 
1418
  }
 
1419
  else if (aData->mSID == eStyleStruct_Background) {
 
1420
    const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
 
1421
  
 
1422
    if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
 
1423
      nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
 
1424
  }
 
1425
}
 
1426
 
 
1427
NS_IMETHODIMP_(PRBool)
 
1428
nsHTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 
1429
{
 
1430
  static const MappedAttributeEntry attributes[] = {
 
1431
    { &nsHTMLAtoms::layout },
 
1432
    { &nsHTMLAtoms::cellpadding },
 
1433
    { &nsHTMLAtoms::cellspacing },
 
1434
    { &nsHTMLAtoms::cols },
 
1435
    { &nsHTMLAtoms::border },
 
1436
    { &nsHTMLAtoms::frame },
 
1437
    { &nsHTMLAtoms::width },
 
1438
    { &nsHTMLAtoms::height },
 
1439
    { &nsHTMLAtoms::hspace },
 
1440
    { &nsHTMLAtoms::vspace },
 
1441
    
 
1442
    { &nsHTMLAtoms::bordercolor },
 
1443
    
 
1444
    { &nsHTMLAtoms::align },
 
1445
    { &nsHTMLAtoms::rules },
 
1446
    { nsnull }
 
1447
  };
 
1448
 
 
1449
  static const MappedAttributeEntry* const map[] = {
 
1450
    attributes,
 
1451
    sCommonAttributeMap,
 
1452
    sBackgroundAttributeMap,
 
1453
  };
 
1454
 
 
1455
  return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
 
1456
}
 
1457
 
 
1458
NS_IMETHODIMP
 
1459
nsHTMLTableElement::GetAttributeMappingFunction(nsMapRuleToAttributesFunc& aMapRuleFunc) const
 
1460
{
 
1461
  aMapRuleFunc = &MapAttributesIntoRule;
 
1462
  return NS_OK;
 
1463
}