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

« back to all changes in this revision

Viewing changes to mozilla/htmlparser/src/nsLoggingSink.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 "nsIAtom.h"
 
39
#include "nsLoggingSink.h"
 
40
#include "nsHTMLTags.h"
 
41
#include "nsString.h"
 
42
#include "nsReadableUtils.h"
 
43
#include "prprf.h"
 
44
 
 
45
 
 
46
static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
 
47
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
 
48
static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID);
 
49
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
 
50
 
 
51
// list of tags that have skipped content
 
52
static const char gSkippedContentTags[] = {
 
53
  eHTMLTag_style,
 
54
  eHTMLTag_script,
 
55
  eHTMLTag_server,
 
56
  eHTMLTag_textarea,
 
57
  eHTMLTag_title,
 
58
  0
 
59
};
 
60
 
 
61
 
 
62
nsresult
 
63
NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
 
64
{
 
65
  NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
 
66
  if (nsnull == aInstancePtrResult) {
 
67
    return NS_ERROR_NULL_POINTER;
 
68
  }
 
69
  nsLoggingSink* it = new nsLoggingSink();
 
70
  if (nsnull == it) {
 
71
    return NS_ERROR_OUT_OF_MEMORY;
 
72
  }
 
73
  return it->QueryInterface(kIContentSinkIID, (void**) aInstancePtrResult);
 
74
}
 
75
 
 
76
nsLoggingSink::nsLoggingSink() {
 
77
  mOutput = 0;
 
78
        mLevel=-1;
 
79
  mSink=0;
 
80
  mParser=0;
 
81
}
 
82
 
 
83
nsLoggingSink::~nsLoggingSink() { 
 
84
  mSink=0;
 
85
  if(mOutput && mAutoDeleteOutput) {
 
86
    delete mOutput;
 
87
  }
 
88
  mOutput=0;
 
89
}
 
90
 
 
91
NS_IMPL_ADDREF(nsLoggingSink)
 
92
NS_IMPL_RELEASE(nsLoggingSink)
 
93
 
 
94
nsresult
 
95
nsLoggingSink::QueryInterface(const nsIID& aIID, void** aInstancePtr)
 
96
{
 
97
  NS_PRECONDITION(nsnull != aInstancePtr, "null ptr");
 
98
  if (nsnull == aInstancePtr) {                                            
 
99
    return NS_ERROR_NULL_POINTER;                                        
 
100
  }                                                                      
 
101
  if (aIID.Equals(kISupportsIID)) {
 
102
    nsISupports* tmp = this;
 
103
    *aInstancePtr = (void*) tmp;
 
104
  }
 
105
  else if (aIID.Equals(kIContentSinkIID)) {
 
106
    nsIContentSink* tmp = this;
 
107
    *aInstancePtr = (void*) tmp;
 
108
  }
 
109
  else if (aIID.Equals(kIHTMLContentSinkIID)) {
 
110
    nsIHTMLContentSink* tmp = this;
 
111
    *aInstancePtr = (void*) tmp;
 
112
  }
 
113
  else if (aIID.Equals(kILoggingSinkIID)) {
 
114
    nsILoggingSink* tmp = this;
 
115
    *aInstancePtr = (void*) tmp;
 
116
  }
 
117
  else {
 
118
    *aInstancePtr = nsnull;
 
119
    return NS_NOINTERFACE;
 
120
  }
 
121
  NS_ADDREF(this);
 
122
  return NS_OK;
 
123
}
 
124
 
 
125
NS_IMETHODIMP
 
126
nsLoggingSink::SetOutputStream(PRFileDesc *aStream,PRBool autoDeleteOutput) {
 
127
  mOutput = aStream;
 
128
  mAutoDeleteOutput=autoDeleteOutput;
 
129
  return NS_OK;
 
130
}
 
131
 
 
132
static
 
133
void WriteTabs(PRFileDesc * out,int aTabCount) {
 
134
  int tabs;
 
135
  for(tabs=0;tabs<aTabCount;++tabs)
 
136
    PR_fprintf(out, "  ");
 
137
}
 
138
 
 
139
 
 
140
NS_IMETHODIMP
 
141
nsLoggingSink::WillBuildModel() {
 
142
  
 
143
  WriteTabs(mOutput,++mLevel);
 
144
  PR_fprintf(mOutput, "<begin>\n");
 
145
  
 
146
  //proxy the call to the real sink if you have one.
 
147
  if(mSink) {
 
148
    mSink->WillBuildModel();
 
149
  }
 
150
 
 
151
  return NS_OK;
 
152
}
 
153
 
 
154
NS_IMETHODIMP
 
155
nsLoggingSink::DidBuildModel() {
 
156
  
 
157
  WriteTabs(mOutput,--mLevel);
 
158
  PR_fprintf(mOutput, "</begin>\n");
 
159
 
 
160
  //proxy the call to the real sink if you have one.
 
161
  nsresult theResult=NS_OK;
 
162
  if(mSink) {
 
163
    theResult=mSink->DidBuildModel();
 
164
  }
 
165
 
 
166
  return theResult;
 
167
}
 
168
 
 
169
NS_IMETHODIMP
 
170
nsLoggingSink::WillInterrupt() {
 
171
  nsresult theResult=NS_OK;
 
172
 
 
173
  //proxy the call to the real sink if you have one.
 
174
  if(mSink) {
 
175
    theResult=mSink->WillInterrupt();
 
176
  }
 
177
  
 
178
  return theResult;
 
179
}
 
180
 
 
181
NS_IMETHODIMP
 
182
nsLoggingSink::WillResume() {
 
183
  nsresult theResult=NS_OK;
 
184
 
 
185
  //proxy the call to the real sink if you have one.
 
186
  if(mSink) {
 
187
    theResult=mSink->WillResume();
 
188
  }
 
189
  
 
190
  return theResult;
 
191
}
 
192
 
 
193
NS_IMETHODIMP
 
194
nsLoggingSink::SetParser(nsIParser* aParser)  {
 
195
  nsresult theResult=NS_OK;
 
196
 
 
197
  //proxy the call to the real sink if you have one.
 
198
  if(mSink) {
 
199
    theResult=mSink->SetParser(aParser);
 
200
  }
 
201
  
 
202
  NS_IF_RELEASE(mParser);
 
203
  
 
204
  mParser = aParser;
 
205
  
 
206
  NS_IF_ADDREF(mParser);
 
207
 
 
208
  return theResult;
 
209
}
 
210
 
 
211
NS_IMETHODIMP
 
212
nsLoggingSink::OpenContainer(const nsIParserNode& aNode) {
 
213
 
 
214
  OpenNode("container", aNode); //do the real logging work...
 
215
 
 
216
  nsresult theResult=NS_OK;
 
217
 
 
218
  //then proxy the call to the real sink if you have one.
 
219
  if(mSink) {
 
220
    theResult=mSink->OpenContainer(aNode);
 
221
  }
 
222
  
 
223
  return theResult;
 
224
 
 
225
}
 
226
 
 
227
NS_IMETHODIMP
 
228
nsLoggingSink::CloseContainer(const nsHTMLTag aTag) {
 
229
 
 
230
  nsresult theResult=NS_OK;
 
231
 
 
232
  nsHTMLTag nodeType = nsHTMLTag(aTag);
 
233
  if ((nodeType >= eHTMLTag_unknown) &&
 
234
      (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
 
235
    const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
 
236
    theResult = CloseNode(NS_ConvertUCS2toUTF8(tag).get());
 
237
  }
 
238
  else theResult= CloseNode("???");
 
239
 
 
240
  //then proxy the call to the real sink if you have one.
 
241
  if(mSink) {
 
242
    theResult=mSink->CloseContainer(aTag);
 
243
  }
 
244
  
 
245
  return theResult;
 
246
 
 
247
}
 
248
 
 
249
NS_IMETHODIMP
 
250
nsLoggingSink::AddHeadContent(const nsIParserNode& aNode) {
 
251
  LeafNode(aNode);
 
252
 
 
253
  nsresult theResult=NS_OK;
 
254
 
 
255
  //then proxy the call to the real sink if you have one.
 
256
  if(mSink) {
 
257
    theResult=mSink->AddHeadContent(aNode);
 
258
  }
 
259
  
 
260
  return theResult;
 
261
 
 
262
}
 
263
 
 
264
NS_IMETHODIMP
 
265
nsLoggingSink::AddLeaf(const nsIParserNode& aNode) {
 
266
  LeafNode(aNode);
 
267
 
 
268
  nsresult theResult=NS_OK;
 
269
 
 
270
  //then proxy the call to the real sink if you have one.
 
271
  if(mSink) {
 
272
    theResult=mSink->AddLeaf(aNode);
 
273
  }
 
274
  
 
275
  return theResult;
 
276
 
 
277
 
278
 
 
279
/**
 
280
 *  This gets called by the parser when you want to add
 
281
 *  a PI node to the current container in the content
 
282
 *  model.
 
283
 *  
 
284
 *  @updated gess 3/25/98
 
285
 *  @param   
 
286
 *  @return  
 
287
 */
 
288
NS_IMETHODIMP
 
289
nsLoggingSink::AddProcessingInstruction(const nsIParserNode& aNode){
 
290
 
 
291
#ifdef VERBOSE_DEBUG
 
292
  DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
 
293
#endif
 
294
 
 
295
  nsresult theResult=NS_OK;
 
296
 
 
297
  //then proxy the call to the real sink if you have one.
 
298
  if(mSink) {
 
299
    theResult=mSink->AddProcessingInstruction(aNode);
 
300
  }
 
301
  
 
302
  return theResult;
 
303
}
 
304
 
 
305
/**
 
306
 *  This gets called by the parser when it encounters
 
307
 *  a DOCTYPE declaration in the HTML document.
 
308
 */
 
309
 
 
310
NS_IMETHODIMP
 
311
nsLoggingSink::AddDocTypeDecl(const nsIParserNode& aNode) {
 
312
 
 
313
#ifdef VERBOSE_DEBUG
 
314
  DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
 
315
#endif
 
316
 
 
317
  nsresult theResult=NS_OK;
 
318
 
 
319
  //then proxy the call to the real sink if you have one.
 
320
  if(mSink) {
 
321
    theResult=mSink->AddDocTypeDecl(aNode);
 
322
  }
 
323
  
 
324
  return theResult;
 
325
 
 
326
}
 
327
 
 
328
/**
 
329
 *  This gets called by the parser when you want to add
 
330
 *  a comment node to the current container in the content
 
331
 *  model.
 
332
 *  
 
333
 *  @updated gess 3/25/98
 
334
 *  @param   
 
335
 *  @return  
 
336
 */
 
337
NS_IMETHODIMP
 
338
nsLoggingSink::AddComment(const nsIParserNode& aNode){
 
339
 
 
340
#ifdef VERBOSE_DEBUG
 
341
  DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
 
342
#endif
 
343
 
 
344
  nsresult theResult=NS_OK;
 
345
 
 
346
  //then proxy the call to the real sink if you have one.
 
347
  if(mSink) {
 
348
    theResult=mSink->AddComment(aNode);
 
349
  }
 
350
  
 
351
  return theResult;
 
352
 
 
353
}
 
354
 
 
355
 
 
356
NS_IMETHODIMP
 
357
nsLoggingSink::SetTitle(const nsString& aValue) {
 
358
   
 
359
  char* tmp = nsnull;
 
360
  GetNewCString(aValue, &tmp);
 
361
        WriteTabs(mOutput,++mLevel);
 
362
  if(tmp) {
 
363
    PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp);
 
364
    nsMemory::Free(tmp);
 
365
  }
 
366
  --mLevel;
 
367
  
 
368
  nsresult theResult=NS_OK;
 
369
 
 
370
  //then proxy the call to the real sink if you have one.
 
371
  if(mSink) {
 
372
    theResult=mSink->SetTitle(aValue);
 
373
  }
 
374
  
 
375
  return theResult;
 
376
 
 
377
}
 
378
 
 
379
 
 
380
NS_IMETHODIMP
 
381
nsLoggingSink::OpenHTML(const nsIParserNode& aNode) {
 
382
  OpenNode("html", aNode);
 
383
 
 
384
  nsresult theResult=NS_OK;
 
385
 
 
386
  //then proxy the call to the real sink if you have one.
 
387
  if(mSink) {
 
388
    theResult=mSink->OpenHTML(aNode);
 
389
  }
 
390
  
 
391
  return theResult;
 
392
 
 
393
}
 
394
 
 
395
NS_IMETHODIMP
 
396
nsLoggingSink::CloseHTML() {
 
397
  CloseNode("html");
 
398
 
 
399
  nsresult theResult=NS_OK;
 
400
 
 
401
  //then proxy the call to the real sink if you have one.
 
402
  if(mSink) {
 
403
    theResult=mSink->CloseHTML();
 
404
  }
 
405
  
 
406
  return theResult;
 
407
 
 
408
}
 
409
 
 
410
NS_IMETHODIMP
 
411
nsLoggingSink::OpenHead(const nsIParserNode& aNode) {
 
412
  OpenNode("head", aNode);
 
413
 
 
414
  nsresult theResult=NS_OK;
 
415
 
 
416
  //then proxy the call to the real sink if you have one.
 
417
  if(mSink) {
 
418
    theResult=mSink->OpenHead(aNode);
 
419
  }
 
420
  
 
421
  return theResult;
 
422
}
 
423
 
 
424
NS_IMETHODIMP
 
425
nsLoggingSink::CloseHead() {
 
426
  CloseNode("head");
 
427
 
 
428
  nsresult theResult=NS_OK;
 
429
 
 
430
  //then proxy the call to the real sink if you have one.
 
431
  if(mSink) {
 
432
    theResult=mSink->CloseHead();
 
433
  }
 
434
  
 
435
  return theResult;
 
436
}
 
437
 
 
438
NS_IMETHODIMP
 
439
nsLoggingSink::OpenBody(const nsIParserNode& aNode) {
 
440
  OpenNode("body", aNode);
 
441
 
 
442
  nsresult theResult=NS_OK;
 
443
 
 
444
  //then proxy the call to the real sink if you have one.
 
445
  if(mSink) {
 
446
    theResult=mSink->OpenBody(aNode);
 
447
  }
 
448
  
 
449
  return theResult;
 
450
}
 
451
 
 
452
NS_IMETHODIMP
 
453
nsLoggingSink::CloseBody() {
 
454
  CloseNode("body");
 
455
 
 
456
  nsresult theResult=NS_OK;
 
457
 
 
458
  //then proxy the call to the real sink if you have one.
 
459
  if(mSink) {
 
460
    theResult=mSink->CloseBody();
 
461
  }
 
462
  
 
463
  return theResult;
 
464
}
 
465
 
 
466
NS_IMETHODIMP
 
467
nsLoggingSink::OpenForm(const nsIParserNode& aNode) {
 
468
  OpenNode("form", aNode);
 
469
 
 
470
  nsresult theResult=NS_OK;
 
471
 
 
472
  //then proxy the call to the real sink if you have one.
 
473
  if(mSink) {
 
474
    theResult=mSink->OpenForm(aNode);
 
475
  }
 
476
  
 
477
  return theResult;
 
478
}
 
479
 
 
480
NS_IMETHODIMP
 
481
nsLoggingSink::CloseForm() {
 
482
  CloseNode("form");
 
483
 
 
484
  nsresult theResult=NS_OK;
 
485
 
 
486
  //then proxy the call to the real sink if you have one.
 
487
  if(mSink) {
 
488
    theResult=mSink->CloseForm();
 
489
  }
 
490
  
 
491
  return theResult;
 
492
}
 
493
 
 
494
NS_IMETHODIMP
 
495
nsLoggingSink::OpenMap(const nsIParserNode& aNode) {
 
496
  OpenNode("map", aNode);
 
497
 
 
498
  nsresult theResult=NS_OK;
 
499
 
 
500
  //then proxy the call to the real sink if you have one.
 
501
  if(mSink) {
 
502
    theResult=mSink->OpenMap(aNode);
 
503
  }
 
504
  
 
505
  return theResult;
 
506
}
 
507
 
 
508
NS_IMETHODIMP
 
509
nsLoggingSink::CloseMap() {
 
510
  CloseNode("map");
 
511
 
 
512
  nsresult theResult=NS_OK;
 
513
 
 
514
  //then proxy the call to the real sink if you have one.
 
515
  if(mSink) {
 
516
    theResult=mSink->CloseMap();
 
517
  }
 
518
  
 
519
  return theResult;
 
520
}
 
521
 
 
522
NS_IMETHODIMP
 
523
nsLoggingSink::OpenFrameset(const nsIParserNode& aNode) {
 
524
  OpenNode("frameset", aNode);
 
525
 
 
526
  nsresult theResult=NS_OK;
 
527
 
 
528
  //then proxy the call to the real sink if you have one.
 
529
  if(mSink) {
 
530
    theResult=mSink->OpenFrameset(aNode);
 
531
  }
 
532
  
 
533
  return theResult;
 
534
}
 
535
 
 
536
NS_IMETHODIMP
 
537
nsLoggingSink::CloseFrameset() {
 
538
  CloseNode("frameset");
 
539
 
 
540
  nsresult theResult=NS_OK;
 
541
 
 
542
  //then proxy the call to the real sink if you have one.
 
543
  if(mSink) {
 
544
    theResult=mSink->CloseFrameset();
 
545
  }
 
546
  
 
547
  return theResult;
 
548
}
 
549
 
 
550
 
 
551
nsresult
 
552
nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) {
 
553
        WriteTabs(mOutput,++mLevel);
 
554
 
 
555
  PR_fprintf(mOutput,"<open container=");
 
556
 
 
557
  nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
 
558
  if ((nodeType >= eHTMLTag_unknown) &&
 
559
      (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
 
560
    const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
 
561
    PR_fprintf(mOutput, "\"%s\"", NS_ConvertUCS2toUTF8(tag).get());
 
562
  }
 
563
  else {
 
564
    char* text;
 
565
    GetNewCString(aNode.GetText(), &text);
 
566
    if(text) {
 
567
      PR_fprintf(mOutput, "\"%s\"", text);
 
568
      nsMemory::Free(text);
 
569
    }
 
570
  }
 
571
 
 
572
  if (WillWriteAttributes(aNode)) {
 
573
    PR_fprintf(mOutput, ">\n");
 
574
    WriteAttributes(aNode);
 
575
    PR_fprintf(mOutput, "</open>\n");
 
576
  }
 
577
  else {
 
578
    PR_fprintf(mOutput, ">\n");
 
579
  }
 
580
 
 
581
  return NS_OK;
 
582
}
 
583
 
 
584
nsresult
 
585
nsLoggingSink::CloseNode(const char* aKind) {
 
586
        WriteTabs(mOutput,mLevel--);
 
587
  PR_fprintf(mOutput, "<close container=\"%s\">\n", aKind);
 
588
  return NS_OK;
 
589
}
 
590
 
 
591
 
 
592
nsresult
 
593
nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) {
 
594
 
 
595
  WriteTabs(mOutput,1+mLevel);
 
596
  nsAutoString tmp;
 
597
  PRInt32 ac = aNode.GetAttributeCount();
 
598
  for (PRInt32 i = 0; i < ac; ++i) {
 
599
    char* key=nsnull;
 
600
    char* value=nsnull;
 
601
    const nsAString& k = aNode.GetKeyAt(i);
 
602
    const nsAString& v = aNode.GetValueAt(i);
 
603
 
 
604
    GetNewCString(k, &key);
 
605
    if(key) {
 
606
      PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key);
 
607
      nsMemory::Free(key);
 
608
    }
 
609
 
 
610
    tmp.Truncate();
 
611
    tmp.Append(v);
 
612
    if(!tmp.IsEmpty()) {
 
613
      PRUnichar first = tmp.First();
 
614
      if ((first == '"') || (first == '\'')) {
 
615
        if (tmp.Last() == first) {
 
616
          tmp.Cut(0, 1);
 
617
          PRInt32 pos = tmp.Length() - 1;
 
618
          if (pos >= 0) {
 
619
            tmp.Cut(pos, 1);
 
620
          }
 
621
        } else {
 
622
          // Mismatched quotes - leave them in
 
623
        }
 
624
      }
 
625
      GetNewCString(tmp, &value);
 
626
 
 
627
      if(value) {
 
628
        PR_fprintf(mOutput, "%s\"/>\n", value);
 
629
        WriteTabs(mOutput,1+mLevel);
 
630
        nsMemory::Free(value);
 
631
      }
 
632
    }
 
633
  }
 
634
 
 
635
  if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
 
636
    nsCOMPtr<nsIDTD> dtd;
 
637
    mParser->GetDTD(getter_AddRefs(dtd));
 
638
    NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
 
639
    
 
640
    nsString theString;
 
641
    PRInt32 lineNo = 0;
 
642
 
 
643
    dtd->CollectSkippedContent(aNode.GetNodeType(), theString, lineNo);
 
644
    char* content = nsnull;
 
645
    GetNewCString(theString, &content);
 
646
    if(content) {
 
647
      PR_fprintf(mOutput, " <content value=\"");
 
648
      PR_fprintf(mOutput, "%s\"/>\n", content) ;
 
649
      nsMemory::Free(content);
 
650
    }
 
651
  }
 
652
  WriteTabs(mOutput,1+mLevel);
 
653
  return NS_OK;
 
654
}
 
655
 
 
656
PRBool
 
657
nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode)
 
658
{
 
659
  PRInt32 ac = aNode.GetAttributeCount();
 
660
  if (0 != ac) {
 
661
    return PR_TRUE;
 
662
  }
 
663
  if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
 
664
    nsCOMPtr<nsIDTD> dtd;
 
665
    mParser->GetDTD(getter_AddRefs(dtd));
 
666
    NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
 
667
    
 
668
    nsString content;
 
669
    PRInt32 lineNo = 0;
 
670
 
 
671
    dtd->CollectSkippedContent(aNode.GetNodeType(), content, lineNo);
 
672
    if (!content.IsEmpty()) {
 
673
      return PR_TRUE;
 
674
    }
 
675
  }
 
676
  return PR_FALSE;
 
677
}
 
678
 
 
679
nsresult
 
680
nsLoggingSink::LeafNode(const nsIParserNode& aNode)
 
681
{
 
682
        WriteTabs(mOutput,1+mLevel);
 
683
        nsHTMLTag                               nodeType  = nsHTMLTag(aNode.GetNodeType());
 
684
 
 
685
  if ((nodeType >= eHTMLTag_unknown) &&
 
686
      (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
 
687
    const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
 
688
 
 
689
                if(tag)
 
690
      PR_fprintf(mOutput, "<leaf tag=\"%s\"", NS_ConvertUCS2toUTF8(tag).get());
 
691
    else PR_fprintf(mOutput, "<leaf tag=\"???\"");
 
692
 
 
693
    if (WillWriteAttributes(aNode)) {
 
694
                        PR_fprintf(mOutput, ">\n");
 
695
      WriteAttributes(aNode);
 
696
                        PR_fprintf(mOutput, "</leaf>\n");
 
697
    }
 
698
    else {
 
699
                        PR_fprintf(mOutput, "/>\n");
 
700
    }
 
701
  }
 
702
  else {
 
703
    PRInt32 pos;
 
704
    nsAutoString tmp;
 
705
    char* str;
 
706
    switch (nodeType) {
 
707
                        case eHTMLTag_whitespace:
 
708
                        case eHTMLTag_text:
 
709
        GetNewCString(aNode.GetText(), &str);
 
710
        if(str) {
 
711
          PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str);
 
712
          nsMemory::Free(str);
 
713
        }
 
714
                                break;
 
715
 
 
716
                        case eHTMLTag_newline:
 
717
                                PR_fprintf(mOutput, "<newline/>\n");
 
718
                                break;
 
719
 
 
720
                        case eHTMLTag_entity:
 
721
                                tmp.Append(aNode.GetText());
 
722
                                tmp.Cut(0, 1);
 
723
                                pos = tmp.Length() - 1;
 
724
                                if (pos >= 0) {
 
725
                                        tmp.Cut(pos, 1);
 
726
                                }
 
727
                                PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get());
 
728
                                break;
 
729
 
 
730
                        default:
 
731
                                NS_NOTREACHED("unsupported leaf node type");
 
732
                }//switch
 
733
  }
 
734
  return NS_OK;
 
735
}
 
736
 
 
737
nsresult 
 
738
nsLoggingSink::QuoteText(const nsAString& aValue, nsString& aResult) {
 
739
  aResult.Truncate();
 
740
    /*
 
741
      if you're stepping through the string anyway, why not use iterators instead of forcing the string to copy?
 
742
     */
 
743
  const nsPromiseFlatString& flat = PromiseFlatString(aValue);
 
744
  const PRUnichar* cp = flat.get();
 
745
  const PRUnichar* end = cp + aValue.Length();
 
746
  while (cp < end) {
 
747
    PRUnichar ch = *cp++;
 
748
    if (ch == '"') {
 
749
      aResult.Append(NS_LITERAL_STRING("&quot;"));
 
750
    }
 
751
    else if (ch == '&') {
 
752
      aResult.Append(NS_LITERAL_STRING("&amp;"));
 
753
    }
 
754
    else if ((ch < 32) || (ch >= 127)) {
 
755
      aResult.Append(NS_LITERAL_STRING("&#"));
 
756
      aResult.AppendInt(PRInt32(ch), 10);
 
757
      aResult.Append(PRUnichar(';'));
 
758
    }
 
759
    else {
 
760
      aResult.Append(ch);
 
761
    }
 
762
  }
 
763
  return NS_OK;
 
764
}
 
765
 
 
766
/**
 
767
 * Use this method to convert nsString to char*. 
 
768
 * REMEMBER: Match this call with nsMemory::Free(aResult);
 
769
 * 
 
770
 * @update 04/04/99 harishd
 
771
 * @param aValue - The string value
 
772
 * @param aResult - String coverted to char*.
 
773
 */
 
774
nsresult
 
775
nsLoggingSink::GetNewCString(const nsAString& aValue, char** aResult)
 
776
{
 
777
  nsresult result=NS_OK;
 
778
  nsAutoString temp;
 
779
  result=QuoteText(aValue,temp);
 
780
  if(NS_SUCCEEDED(result)) {
 
781
    if(!temp.IsEmpty()) {
 
782
      *aResult = ToNewCString(temp);
 
783
    }
 
784
  }
 
785
  return result;
 
786
}
 
787
 
 
788
/**
 
789
 * This gets called when handling illegal contents, especially
 
790
 * in dealing with tables. This method creates a new context.
 
791
 * 
 
792
 * @update 04/04/99 harishd
 
793
 * @param aPosition - The position from where the new context begins.
 
794
 */
 
795
NS_IMETHODIMP
 
796
nsLoggingSink::BeginContext(PRInt32 aPosition) 
 
797
{
 
798
  return NS_OK;
 
799
}
 
800
 
 
801
/**
 
802
 * This method terminates any new context that got created by
 
803
 * BeginContext and switches back to the main context.  
 
804
 *
 
805
 * @update 04/04/99 harishd
 
806
 * @param aPosition - Validates the end of a context.
 
807
 */
 
808
NS_IMETHODIMP
 
809
nsLoggingSink::EndContext(PRInt32 aPosition)
 
810
{
 
811
  return NS_OK;
 
812
}