WebCore/loader/TextDocument.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006, 2007, 2008 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 "DecodedDataDocumentParser.h"
       
    29 #include "Element.h"
       
    30 #include "HTMLNames.h"
       
    31 #include "HTMLViewSourceDocument.h"
       
    32 #include "SegmentedString.h"
       
    33 #include "Text.h"
       
    34 
       
    35 using namespace std;
       
    36 
       
    37 namespace WebCore {
       
    38 
       
    39 using namespace HTMLNames;
       
    40 
       
    41 // FIXME: TextDocumentParser could just be an HTMLDocumentParser
       
    42 // which started the Tokenizer in the PlainText state.
       
    43 class TextDocumentParser : public DecodedDataDocumentParser {
       
    44 public:
       
    45     TextDocumentParser(Document*);
       
    46     virtual ~TextDocumentParser();
       
    47     TextDocumentParser(HTMLViewSourceDocument*);
       
    48 
       
    49 private:
       
    50     virtual void insert(const SegmentedString&);
       
    51     virtual void append(const SegmentedString&);
       
    52     virtual void finish();
       
    53     virtual bool finishWasCalled();
       
    54 
       
    55     inline void checkBuffer(int len = 10)
       
    56     {
       
    57         if ((m_dest - m_buffer) > m_size - len) {
       
    58             // Enlarge buffer
       
    59             int newSize = std::max(m_size * 2, m_size + len);
       
    60             int oldOffset = m_dest - m_buffer;
       
    61             m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar)));
       
    62             m_dest = m_buffer + oldOffset;
       
    63             m_size = newSize;
       
    64         }
       
    65     }
       
    66 
       
    67 private:
       
    68     Element* m_preElement;
       
    69 
       
    70     bool m_skipLF;
       
    71     
       
    72     int m_size;
       
    73     UChar* m_buffer;
       
    74     UChar* m_dest;
       
    75 };
       
    76 
       
    77 TextDocumentParser::TextDocumentParser(Document* document)
       
    78     : DecodedDataDocumentParser(document)
       
    79     , m_preElement(0)
       
    80     , m_skipLF(false)
       
    81 {    
       
    82     // Allocate buffer
       
    83     m_size = 254;
       
    84     m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size));
       
    85     m_dest = m_buffer;
       
    86 }    
       
    87 
       
    88 TextDocumentParser::TextDocumentParser(HTMLViewSourceDocument* document)
       
    89     : DecodedDataDocumentParser(document, true)
       
    90     , m_preElement(0)
       
    91     , m_skipLF(false)
       
    92 {    
       
    93     // Allocate buffer
       
    94     m_size = 254;
       
    95     m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size));
       
    96     m_dest = m_buffer;
       
    97 }
       
    98 
       
    99 TextDocumentParser::~TextDocumentParser()
       
   100 {
       
   101     // finish() should have been called to prevent any leaks
       
   102     ASSERT(!m_buffer);
       
   103 }
       
   104 
       
   105 void TextDocumentParser::insert(const SegmentedString&)
       
   106 {
       
   107     ASSERT_NOT_REACHED();
       
   108 }
       
   109 
       
   110 void TextDocumentParser::append(const SegmentedString& s)
       
   111 {
       
   112     ExceptionCode ec;
       
   113 
       
   114     m_dest = m_buffer;
       
   115     
       
   116     SegmentedString str = s;
       
   117     while (!str.isEmpty()) {
       
   118         UChar c = *str;
       
   119         
       
   120         if (c == '\r') {
       
   121             *m_dest++ = '\n';
       
   122             
       
   123             // possibly skip an LF in the case of an CRLF sequence
       
   124             m_skipLF = true;
       
   125         } else if (c == '\n') {
       
   126             if (!m_skipLF)
       
   127                 *m_dest++ = c;
       
   128             else
       
   129                 m_skipLF = false;
       
   130         } else {
       
   131             *m_dest++ = c;
       
   132             m_skipLF = false;
       
   133         }
       
   134         
       
   135         str.advance();
       
   136         
       
   137         // Maybe enlarge the buffer
       
   138         checkBuffer();
       
   139     }
       
   140 
       
   141     if (!m_preElement && !inViewSourceMode()) {
       
   142         RefPtr<Element> rootElement = document()->createElement(htmlTag, false);
       
   143         document()->appendChild(rootElement, ec);
       
   144 
       
   145         RefPtr<Element> body = document()->createElement(bodyTag, false);
       
   146         rootElement->appendChild(body, ec);
       
   147 
       
   148         RefPtr<Element> preElement = document()->createElement(preTag, false);
       
   149         preElement->setAttribute("style", "word-wrap: break-word; white-space: pre-wrap;", ec);
       
   150 
       
   151         body->appendChild(preElement, ec);
       
   152         
       
   153         m_preElement = preElement.get();
       
   154     } 
       
   155     
       
   156     String string = String(m_buffer, m_dest - m_buffer);
       
   157     if (inViewSourceMode()) {
       
   158         static_cast<HTMLViewSourceDocument*>(document())->addViewSourceText(string);
       
   159         return;
       
   160     }
       
   161 
       
   162     unsigned charsLeft = string.length();
       
   163     while (charsLeft) {
       
   164         // split large text to nodes of manageable size
       
   165         RefPtr<Text> text = Text::createWithLengthLimit(document(), string, charsLeft);
       
   166         m_preElement->appendChild(text, ec);
       
   167     }
       
   168 }
       
   169 
       
   170 void TextDocumentParser::finish()
       
   171 {
       
   172     if (!m_preElement)
       
   173         append(SegmentedString()); // Create document structure for an empty text document.
       
   174     m_preElement = 0;
       
   175     fastFree(m_buffer);
       
   176     m_buffer = 0;
       
   177     m_dest = 0;
       
   178 
       
   179     // FIXME: Should this call finishParsing even if m_parserStopped is true?
       
   180     // See equivalent implementation in RawDataDocumentParser.
       
   181     document()->finishedParsing();
       
   182 }
       
   183 
       
   184 bool TextDocumentParser::finishWasCalled()
       
   185 {
       
   186     // finish() always calls document()->finishedParsing() so we'll be deleted
       
   187     // after finish().
       
   188     return false;
       
   189 }
       
   190 
       
   191 TextDocument::TextDocument(Frame* frame, const KURL& url)
       
   192     : HTMLDocument(frame, url)
       
   193 {
       
   194 }
       
   195 
       
   196 DocumentParser* TextDocument::createParser()
       
   197 {
       
   198     return new TextDocumentParser(this);
       
   199 }
       
   200 
       
   201 DocumentParser* createTextDocumentParser(HTMLViewSourceDocument* document)
       
   202 {
       
   203     return new TextDocumentParser(document);
       
   204 }
       
   205 
       
   206 }