Reviewed by Mitz.
[WebKit-https.git] / WebCore / loader / TextDocument.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
23  */
24
25 #include "config.h"
26 #include "TextDocument.h"
27
28 #include "Element.h"
29 #include "HTMLNames.h"
30 #include "HTMLViewSourceDocument.h"
31 #include "SegmentedString.h"
32 #include "Text.h"
33 #include "XMLTokenizer.h"
34
35 using namespace std;
36
37 namespace WebCore {
38
39 using namespace HTMLNames;
40
41 TextTokenizer::TextTokenizer(Document* doc)
42     : m_doc(doc)
43     , m_preElement(0)
44     , m_skipLF(false)
45 {    
46     // Allocate buffer
47     m_size = 254;
48     m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size));
49     m_dest = m_buffer;
50 }    
51
52 TextTokenizer::TextTokenizer(HTMLViewSourceDocument* doc)
53     : Tokenizer(true)
54     , m_doc(doc)
55     , m_preElement(0)
56     , m_skipLF(false)
57 {    
58     // Allocate buffer
59     m_size = 254;
60     m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size));
61     m_dest = m_buffer;
62 }    
63
64 bool TextTokenizer::write(const SegmentedString& s, bool appendData)
65 {
66     ExceptionCode ec;
67
68     m_dest = m_buffer;
69     
70     SegmentedString str = s;
71     while (!str.isEmpty()) {
72         UChar c = *str;
73         
74         if (c == '\r') {
75             *m_dest++ = '\n';
76             
77             // possibly skip an LF in the case of an CRLF sequence
78             m_skipLF = true;
79         } else if (c == '\n') {
80             if (!m_skipLF)
81                 *m_dest++ = c;
82             else
83                 m_skipLF = false;
84         } else {
85             *m_dest++ = c;
86             m_skipLF = false;
87         }
88         
89         str.advance();
90         
91         // Maybe enlarge the buffer
92         checkBuffer();
93     }
94
95     if (!m_preElement && !inViewSourceMode()) {
96         RefPtr<Element> rootElement = m_doc->createElementNS(xhtmlNamespaceURI, "html", ec);
97         m_doc->appendChild(rootElement, ec);
98
99         RefPtr<Element> body = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec);
100         rootElement->appendChild(body, ec);
101
102         RefPtr<Element> preElement = m_doc->createElementNS(xhtmlNamespaceURI, "pre", ec);
103         preElement->setAttribute("style", "word-wrap: break-word; white-space: pre-wrap;", ec);
104
105         body->appendChild(preElement, ec);
106         
107         m_preElement = preElement.get();
108     } 
109     
110     String string = String(m_buffer, m_dest - m_buffer);
111     if (inViewSourceMode()) {
112         static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceText(string);
113         return false;
114     }
115
116     unsigned charsLeft = string.length();
117     while (charsLeft) {
118         // split large text to nodes of manageable size
119         RefPtr<Text> text = Text::createWithLengthLimit(m_doc, string, charsLeft);
120         m_preElement->appendChild(text, ec);
121     }
122
123     return false;
124 }
125
126 void TextTokenizer::finish()
127 {
128     m_preElement = 0;
129     fastFree(m_buffer);
130         
131     m_doc->finishedParsing();
132 }
133
134 bool TextTokenizer::isWaitingForScripts() const
135 {
136     // A text document is never waiting for scripts
137     return false;
138 }
139
140 TextDocument::TextDocument(DOMImplementation* implementation, Frame* frame)
141     : HTMLDocument(implementation, frame)
142 {
143 }
144
145 Tokenizer* TextDocument::createTokenizer()
146 {
147     return new TextTokenizer(this);
148 }
149
150 }