LCOV - code coverage report
Current view: directory - parser/html - nsHtml5Highlighter.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 406 0 0.0 %
Date: 2012-06-02 Functions: 33 0 0.0 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is HTML5 View Source code.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Henri Sivonen <hsivonen@iki.fi>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "nsHtml5Highlighter.h"
      39                 : #include "nsDebug.h"
      40                 : #include "nsHtml5Tokenizer.h"
      41                 : #include "nsHtml5AttributeName.h"
      42                 : #include "nsString.h"
      43                 : #include "nsThreadUtils.h"
      44                 : #include "nsHtml5ViewSourceUtils.h"
      45                 : #include "mozilla/Preferences.h"
      46                 : 
      47                 : using namespace mozilla;
      48                 : 
      49                 : // The old code had a limit of 16 tokens. 1300 is a number picked my measuring
      50                 : // the size of 16 tokens on cnn.com.
      51                 : #define NS_HTML5_HIGHLIGHTER_PRE_BREAK_THRESHOLD 1300
      52                 : 
      53                 : PRUnichar nsHtml5Highlighter::sComment[] =
      54                 :   { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
      55                 : 
      56                 : PRUnichar nsHtml5Highlighter::sCdata[] =
      57                 :   { 'c', 'd', 'a', 't', 'a', 0 };
      58                 : 
      59                 : PRUnichar nsHtml5Highlighter::sEntity[] =
      60                 :   { 'e', 'n', 't', 'i', 't', 'y', 0 };
      61                 : 
      62                 : PRUnichar nsHtml5Highlighter::sEndTag[] =
      63                 :   { 'e', 'n', 'd', '-', 't', 'a', 'g', 0 };
      64                 : 
      65                 : PRUnichar nsHtml5Highlighter::sStartTag[] =
      66                 :   { 's', 't', 'a', 'r', 't', '-', 't', 'a', 'g', 0 };
      67                 : 
      68                 : PRUnichar nsHtml5Highlighter::sAttributeName[] =
      69                 :   { 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', '-', 'n', 'a', 'm', 'e', 0 };
      70                 : 
      71                 : PRUnichar nsHtml5Highlighter::sAttributeValue[] =
      72                 :   { 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', '-',
      73                 :     'v', 'a', 'l', 'u', 'e', 0 };
      74                 : 
      75                 : PRUnichar nsHtml5Highlighter::sDoctype[] =
      76                 :   { 'd', 'o', 'c', 't', 'y', 'p', 'e', 0 };
      77                 : 
      78                 : PRUnichar nsHtml5Highlighter::sPi[] =
      79                 :   { 'p', 'i', 0 };
      80                 : 
      81               0 : nsHtml5Highlighter::nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink)
      82                 :  : mState(NS_HTML5TOKENIZER_DATA)
      83                 :  , mCStart(PR_INT32_MAX)
      84                 :  , mPos(0)
      85                 :  , mLineNumber(1)
      86                 :  , mInlinesOpen(0)
      87                 :  , mInCharacters(false)
      88                 :  , mBuffer(nsnull)
      89                 :  , mSyntaxHighlight(Preferences::GetBool("view_source.syntax_highlight",
      90               0 :                                          true))
      91                 :  , mOpSink(aOpSink)
      92                 :  , mCurrentRun(nsnull)
      93                 :  , mAmpersand(nsnull)
      94                 :  , mSlash(nsnull)
      95               0 :  , mHandles(new nsIContent*[NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH])
      96               0 :  , mHandlesUsed(0)
      97                 : {
      98               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
      99               0 : }
     100                 : 
     101               0 : nsHtml5Highlighter::~nsHtml5Highlighter()
     102                 : {
     103               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     104               0 : }
     105                 : 
     106                 : void
     107               0 : nsHtml5Highlighter::Start(const nsAutoString& aTitle)
     108                 : {
     109                 :   // Doctype
     110               0 :   mOpQueue.AppendElement()->Init(nsGkAtoms::html, EmptyString(), EmptyString());
     111                 : 
     112               0 :   mOpQueue.AppendElement()->Init(STANDARDS_MODE);
     113                 : 
     114               0 :   nsIContent** root = CreateElement(nsHtml5Atoms::html, nsnull);
     115               0 :   mOpQueue.AppendElement()->Init(eTreeOpAppendToDocument, root);
     116               0 :   mStack.AppendElement(root);
     117                 : 
     118               0 :   Push(nsGkAtoms::head, nsnull);
     119                 : 
     120               0 :   Push(nsGkAtoms::title, nsnull);
     121                 :   // XUL will add the "Source of: " prefix.
     122               0 :   PRUint32 length = aTitle.Length();
     123               0 :   if (length > PR_INT32_MAX) {
     124               0 :     length = PR_INT32_MAX;
     125                 :   }
     126               0 :   AppendCharacters(aTitle.get(), 0, (PRInt32)length);
     127               0 :   Pop(); // title
     128                 : 
     129               0 :   Push(nsGkAtoms::link, nsHtml5ViewSourceUtils::NewLinkAttributes());
     130                 : 
     131               0 :   mOpQueue.AppendElement()->Init(eTreeOpUpdateStyleSheet, CurrentNode());
     132                 : 
     133               0 :   Pop(); // link
     134                 : 
     135               0 :   Pop(); // head
     136                 : 
     137               0 :   Push(nsGkAtoms::body, nsHtml5ViewSourceUtils::NewBodyAttributes());
     138                 : 
     139               0 :   nsHtml5HtmlAttributes* preAttrs = new nsHtml5HtmlAttributes(0);
     140               0 :   nsString* preId = new nsString(NS_LITERAL_STRING("line1"));
     141               0 :   preAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, preId);
     142               0 :   Push(nsGkAtoms::pre, preAttrs);
     143                 : 
     144               0 :   StartCharacters();
     145                 : 
     146               0 :   mOpQueue.AppendElement()->Init(eTreeOpStartLayout);
     147               0 : }
     148                 : 
     149                 : PRInt32
     150               0 : nsHtml5Highlighter::Transition(PRInt32 aState, bool aReconsume, PRInt32 aPos)
     151                 : {
     152               0 :   mPos = aPos;
     153               0 :   switch (mState) {
     154                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA:
     155                 :     case NS_HTML5TOKENIZER_RAWTEXT:
     156                 :     case NS_HTML5TOKENIZER_RCDATA:
     157                 :     case NS_HTML5TOKENIZER_DATA:
     158                 :       // We can transition on < and on &. Either way, we don't yet know the
     159                 :       // role of the token, so open a span without class.
     160               0 :       if (aState == NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE) {
     161               0 :         StartSpan();
     162                 :         // Start another span for highlighting the ampersand
     163               0 :         StartSpan();
     164               0 :         mAmpersand = CurrentNode();
     165                 :       } else {
     166               0 :         EndCharactersAndStartMarkupRun();
     167                 :       }
     168               0 :       break;
     169                 :     case NS_HTML5TOKENIZER_TAG_OPEN:
     170               0 :       switch (aState) {
     171                 :         case NS_HTML5TOKENIZER_TAG_NAME:
     172               0 :           StartSpan(sStartTag);
     173               0 :           break;
     174                 :         case NS_HTML5TOKENIZER_DATA:
     175               0 :           FinishTag(); // DATA
     176               0 :           break;
     177                 :         case NS_HTML5TOKENIZER_PROCESSING_INSTRUCTION:
     178               0 :           AddClass(sPi);
     179               0 :           break;
     180                 :       }
     181               0 :       break;
     182                 :     case NS_HTML5TOKENIZER_TAG_NAME:
     183               0 :       switch (aState) {
     184                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     185               0 :           EndSpanOrA(); // NS_HTML5TOKENIZER_TAG_NAME
     186               0 :           break;
     187                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     188               0 :           EndSpanOrA(); // NS_HTML5TOKENIZER_TAG_NAME
     189               0 :           StartSpan(); // for highlighting the slash
     190               0 :           mSlash = CurrentNode();
     191               0 :           break;
     192                 :         default:
     193               0 :           FinishTag();
     194               0 :           break;
     195                 :       }
     196               0 :       break;
     197                 :     case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     198               0 :       switch (aState) {
     199                 :         case NS_HTML5TOKENIZER_ATTRIBUTE_NAME:
     200               0 :           StartSpan(sAttributeName);
     201               0 :           break;
     202                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     203               0 :           StartSpan(); // for highlighting the slash
     204               0 :           mSlash = CurrentNode();
     205               0 :           break;
     206                 :         default:
     207               0 :           FinishTag();
     208               0 :           break;
     209                 :       }
     210               0 :       break;
     211                 :     case NS_HTML5TOKENIZER_ATTRIBUTE_NAME:
     212               0 :       switch (aState) {
     213                 :         case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_NAME:
     214                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_VALUE:
     215               0 :           EndSpanOrA(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME
     216               0 :           break;
     217                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     218               0 :           EndSpanOrA(); // NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME
     219               0 :           StartSpan(); // for highlighting the slash
     220               0 :           mSlash = CurrentNode();
     221               0 :           break;
     222                 :         default:
     223               0 :           FinishTag();
     224               0 :           break;
     225                 :       }
     226               0 :       break;
     227                 :     case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_VALUE:
     228               0 :       switch (aState) {
     229                 :         case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_DOUBLE_QUOTED:
     230                 :         case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_SINGLE_QUOTED:
     231               0 :           FlushCurrent();
     232               0 :           StartA();
     233               0 :           break;
     234                 :         case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED:
     235               0 :           StartA();
     236               0 :           break;
     237                 :         default:
     238               0 :           FinishTag();
     239               0 :           break;
     240                 :       }
     241               0 :       break;
     242                 :     case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_DOUBLE_QUOTED:
     243                 :     case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_SINGLE_QUOTED:
     244               0 :       switch (aState) {
     245                 :         case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_VALUE_QUOTED:
     246               0 :           EndSpanOrA();
     247               0 :           break;
     248                 :         case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE:
     249               0 :           StartSpan();
     250               0 :           StartSpan(); // for ampersand itself
     251               0 :           mAmpersand = CurrentNode();
     252               0 :           break;
     253                 :         default:
     254               0 :           NS_NOTREACHED("Impossible transition.");
     255               0 :           break;
     256                 :       }
     257               0 :       break;
     258                 :     case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_VALUE_QUOTED:
     259               0 :       switch (aState) {
     260                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     261               0 :           break;
     262                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     263               0 :           StartSpan(); // for highlighting the slash
     264               0 :           mSlash = CurrentNode();
     265               0 :           break;
     266                 :         default:
     267               0 :           FinishTag();
     268               0 :           break;
     269                 :       }
     270               0 :       break;
     271                 :     case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     272               0 :       EndSpanOrA(); // end the slash highlight
     273               0 :       switch (aState) {
     274                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     275               0 :           break;
     276                 :         default:
     277               0 :           FinishTag();
     278               0 :           break;
     279                 :       }
     280               0 :       break;
     281                 :     case NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED:
     282               0 :       switch (aState) {
     283                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     284               0 :           EndSpanOrA();
     285               0 :           break;
     286                 :         case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE:
     287               0 :           StartSpan();
     288               0 :           StartSpan(); // for ampersand itself
     289               0 :           mAmpersand = CurrentNode();
     290               0 :           break;
     291                 :         default:
     292               0 :           FinishTag();
     293               0 :           break;
     294                 :       }
     295               0 :       break;
     296                 :     case NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_NAME:
     297               0 :       switch (aState) {
     298                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     299               0 :           StartSpan(); // for highlighting the slash
     300               0 :           mSlash = CurrentNode();
     301               0 :           break;
     302                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_VALUE:
     303               0 :           break;
     304                 :         case NS_HTML5TOKENIZER_ATTRIBUTE_NAME:
     305               0 :           StartSpan(sAttributeName);
     306               0 :           break;
     307                 :         default:
     308               0 :           FinishTag();
     309               0 :           break;
     310                 :       }
     311               0 :       break;
     312                 :       // most comment states are omitted, because they don't matter to
     313                 :       // highlighting
     314                 :     case NS_HTML5TOKENIZER_COMMENT_START:
     315                 :     case NS_HTML5TOKENIZER_COMMENT_END:
     316                 :     case NS_HTML5TOKENIZER_COMMENT_END_BANG:
     317                 :     case NS_HTML5TOKENIZER_COMMENT_START_DASH:
     318                 :     case NS_HTML5TOKENIZER_BOGUS_COMMENT:
     319                 :     case NS_HTML5TOKENIZER_BOGUS_COMMENT_HYPHEN:
     320               0 :       if (aState == NS_HTML5TOKENIZER_DATA) {
     321               0 :         AddClass(sComment);
     322               0 :         FinishTag();
     323                 :       }
     324               0 :       break;
     325                 :       // most cdata states are omitted, because they don't matter to
     326                 :       // highlighting
     327                 :     case NS_HTML5TOKENIZER_CDATA_RSQB_RSQB:
     328               0 :       if (aState == NS_HTML5TOKENIZER_DATA) {
     329               0 :         AddClass(sCdata);
     330               0 :         FinishTag();
     331                 :       }
     332               0 :       break;
     333                 :     case NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE:
     334               0 :       EndSpanOrA(); // the span for the ampersand
     335               0 :       switch (aState) {
     336                 :         case NS_HTML5TOKENIZER_CONSUME_NCR:
     337                 :         case NS_HTML5TOKENIZER_CHARACTER_REFERENCE_HILO_LOOKUP:
     338               0 :           break;
     339                 :         default:
     340                 :           // not actually a character reference
     341               0 :           EndSpanOrA();
     342               0 :           break;
     343                 :       }
     344               0 :       break;
     345                 :     case NS_HTML5TOKENIZER_CHARACTER_REFERENCE_HILO_LOOKUP:
     346               0 :       if (aState == NS_HTML5TOKENIZER_CHARACTER_REFERENCE_TAIL) {
     347               0 :         break;
     348                 :       }
     349                 :       // not actually a character reference
     350               0 :       EndSpanOrA();
     351               0 :       break;
     352                 :     case NS_HTML5TOKENIZER_CHARACTER_REFERENCE_TAIL:
     353               0 :       if (!aReconsume) {
     354               0 :         FlushCurrent();
     355                 :       }
     356               0 :       EndSpanOrA();
     357               0 :       break;
     358                 :     case NS_HTML5TOKENIZER_DECIMAL_NRC_LOOP:
     359                 :     case NS_HTML5TOKENIZER_HEX_NCR_LOOP:
     360               0 :       switch (aState) {
     361                 :         case NS_HTML5TOKENIZER_HANDLE_NCR_VALUE:
     362               0 :           AddClass(sEntity);
     363               0 :           FlushCurrent();
     364               0 :           break;
     365                 :         case NS_HTML5TOKENIZER_HANDLE_NCR_VALUE_RECONSUME:
     366               0 :           AddClass(sEntity);
     367               0 :           break;
     368                 :       }
     369               0 :       EndSpanOrA();
     370               0 :       break;
     371                 :     case NS_HTML5TOKENIZER_CLOSE_TAG_OPEN:
     372               0 :       switch (aState) {
     373                 :         case NS_HTML5TOKENIZER_DATA:
     374               0 :           FinishTag();
     375               0 :           break;
     376                 :         case NS_HTML5TOKENIZER_TAG_NAME:
     377               0 :           StartSpan(sEndTag);
     378               0 :           break;
     379                 :       }
     380               0 :       break;
     381                 :     case NS_HTML5TOKENIZER_RAWTEXT_RCDATA_LESS_THAN_SIGN:
     382               0 :       if (aState == NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME) {
     383               0 :         FlushCurrent();
     384               0 :         StartSpan(); // don't know if it is "end-tag" yet :-(
     385               0 :         break;
     386                 :       }
     387               0 :       EndSpanOrA();
     388               0 :       StartCharacters();
     389               0 :       break;
     390                 :     case NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME:
     391               0 :       switch (aState) {
     392                 :         case NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME:
     393               0 :           AddClass(sEndTag);
     394               0 :           EndSpanOrA();
     395               0 :           break;
     396                 :         case NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG:
     397               0 :           AddClass(sEndTag);
     398               0 :           EndSpanOrA();
     399               0 :           StartSpan(); // for highlighting the slash
     400               0 :           mSlash = CurrentNode();
     401               0 :           break;
     402                 :         case NS_HTML5TOKENIZER_DATA: // yes, as a result of emitting the token
     403               0 :           AddClass(sEndTag);
     404               0 :           FinishTag();
     405               0 :           break;
     406                 :         default:
     407               0 :           FinishTag();
     408               0 :           break;
     409                 :       }
     410               0 :       break;
     411                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN:
     412                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
     413               0 :       if (aState == NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME) {
     414               0 :         FlushCurrent();
     415               0 :         StartSpan(); // don't know if it is "end-tag" yet :-(
     416               0 :         break;
     417                 :       }
     418               0 :       FinishTag();
     419               0 :       break;
     420                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_DASH_DASH:
     421                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED:
     422                 :     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_DASH:
     423               0 :       if (aState == NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN) {
     424               0 :         EndCharactersAndStartMarkupRun();
     425                 :       }
     426               0 :       break;
     427                 :       // Lots of double escape states omitted, because they don't highlight.
     428                 :       // Likewise, only doctype states that can emit the doctype are of
     429                 :       // interest. Otherwise, the transition out of bogus comment deals.
     430                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_NAME:
     431                 :     case NS_HTML5TOKENIZER_DOCTYPE_NAME:
     432                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_NAME:
     433                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD:
     434                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
     435                 :     case NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
     436                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
     437                 :     case NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
     438                 :     case NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
     439                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
     440                 :     case NS_HTML5TOKENIZER_BOGUS_DOCTYPE:
     441                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD:
     442                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
     443                 :     case NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
     444                 :     case NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
     445               0 :       if (aState == NS_HTML5TOKENIZER_DATA) {
     446               0 :         AddClass(sDoctype);
     447               0 :         FinishTag();
     448                 :       }
     449               0 :       break;
     450                 :     case NS_HTML5TOKENIZER_PROCESSING_INSTRUCTION_QUESTION_MARK:
     451               0 :       if (aState == NS_HTML5TOKENIZER_DATA) {
     452               0 :         FinishTag();
     453                 :       }
     454               0 :       break;
     455                 :     default:
     456               0 :       break;
     457                 :   }
     458               0 :   mState = aState;
     459               0 :   return aState;
     460                 : }
     461                 : 
     462                 : void
     463               0 : nsHtml5Highlighter::End()
     464                 : {
     465               0 :   switch (mState) {
     466                 :     case NS_HTML5TOKENIZER_COMMENT_END:
     467                 :     case NS_HTML5TOKENIZER_COMMENT_END_BANG:
     468                 :     case NS_HTML5TOKENIZER_COMMENT_START_DASH:
     469                 :     case NS_HTML5TOKENIZER_BOGUS_COMMENT:
     470                 :     case NS_HTML5TOKENIZER_BOGUS_COMMENT_HYPHEN:
     471               0 :       AddClass(sComment);
     472               0 :       break;
     473                 :     case NS_HTML5TOKENIZER_CDATA_RSQB_RSQB:
     474               0 :       AddClass(sCdata);
     475               0 :       break;
     476                 :     case NS_HTML5TOKENIZER_DECIMAL_NRC_LOOP:
     477                 :     case NS_HTML5TOKENIZER_HEX_NCR_LOOP:
     478                 :       // XXX need tokenizer help here
     479               0 :       break;
     480                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_NAME:
     481                 :     case NS_HTML5TOKENIZER_DOCTYPE_NAME:
     482                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_NAME:
     483                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_KEYWORD:
     484                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
     485                 :     case NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
     486                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
     487                 :     case NS_HTML5TOKENIZER_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
     488                 :     case NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
     489                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
     490                 :     case NS_HTML5TOKENIZER_BOGUS_DOCTYPE:
     491                 :     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_SYSTEM_KEYWORD:
     492                 :     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
     493                 :     case NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
     494                 :     case NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
     495               0 :       AddClass(sDoctype);
     496               0 :       break;
     497                 :     default:
     498               0 :       break;
     499                 :   }
     500               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     501               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     502               0 :   treeOp->Init(eTreeOpStreamEnded);
     503               0 :   FlushOps();
     504               0 : }
     505                 : 
     506                 : void
     507               0 : nsHtml5Highlighter::SetBuffer(nsHtml5UTF16Buffer* aBuffer)
     508                 : {
     509               0 :   NS_PRECONDITION(!mBuffer, "Old buffer still here!");
     510               0 :   mBuffer = aBuffer;
     511               0 :   mCStart = aBuffer->getStart();
     512               0 : }
     513                 : 
     514                 : void
     515               0 : nsHtml5Highlighter::DropBuffer(PRInt32 aPos)
     516                 : {
     517               0 :   NS_PRECONDITION(mBuffer, "No buffer to drop!");
     518               0 :   mPos = aPos;
     519               0 :   FlushChars();
     520               0 :   mBuffer = nsnull;
     521               0 : }
     522                 : 
     523                 : void
     524               0 : nsHtml5Highlighter::StartSpan()
     525                 : {
     526               0 :   FlushChars();
     527               0 :   Push(nsGkAtoms::span, nsnull);
     528               0 :   ++mInlinesOpen;
     529               0 : }
     530                 : 
     531                 : void
     532               0 : nsHtml5Highlighter::StartSpan(const PRUnichar* aClass)
     533                 : {
     534               0 :   StartSpan();
     535               0 :   AddClass(aClass);
     536               0 : }
     537                 : 
     538                 : void
     539               0 : nsHtml5Highlighter::EndSpanOrA()
     540                 : {
     541               0 :   FlushChars();
     542               0 :   Pop();
     543               0 :   --mInlinesOpen;
     544               0 : }
     545                 : 
     546                 : void
     547               0 : nsHtml5Highlighter::StartCharacters()
     548                 : {
     549               0 :   NS_PRECONDITION(!mInCharacters, "Already in characters!");
     550               0 :   FlushChars();
     551               0 :   Push(nsGkAtoms::span, nsnull);
     552               0 :   mCurrentRun = CurrentNode();
     553               0 :   mInCharacters = true;
     554               0 : }
     555                 : 
     556                 : void
     557               0 : nsHtml5Highlighter::EndCharactersAndStartMarkupRun()
     558                 : {
     559               0 :   NS_PRECONDITION(mInCharacters, "Not in characters!");
     560               0 :   FlushChars();
     561               0 :   Pop();
     562               0 :   mInCharacters = false;
     563                 :   // Now start markup run
     564               0 :   StartSpan();
     565               0 :   mCurrentRun = CurrentNode();
     566               0 : }
     567                 : 
     568                 : void
     569               0 : nsHtml5Highlighter::StartA()
     570                 : {
     571               0 :   FlushChars();
     572               0 :   Push(nsGkAtoms::a, nsnull);
     573               0 :   AddClass(sAttributeValue);
     574               0 :   ++mInlinesOpen;
     575               0 : }
     576                 : 
     577                 : void
     578               0 : nsHtml5Highlighter::FinishTag()
     579                 : {
     580               0 :   while (mInlinesOpen > 1) {
     581               0 :     EndSpanOrA();
     582                 :   }
     583               0 :   FlushCurrent(); // >
     584               0 :   EndSpanOrA(); // DATA
     585               0 :   NS_ASSERTION(!mInlinesOpen, "mInlinesOpen got out of sync!");
     586               0 :   StartCharacters();
     587               0 : }
     588                 : 
     589                 : void
     590               0 : nsHtml5Highlighter::FlushChars()
     591                 : {
     592               0 :   if (mCStart < mPos) {
     593               0 :     PRUnichar* buf = mBuffer->getBuffer();
     594               0 :     PRInt32 i = mCStart;
     595               0 :     while (i < mPos) {
     596               0 :       PRUnichar c = buf[i];
     597               0 :       switch (c) {
     598                 :         case '\r':
     599                 :           // The input this code sees has been normalized so that there are
     600                 :           // CR breaks and LF breaks but no CRLF breaks. Overwrite CR with LF
     601                 :           // to show consistent LF line breaks to layout. It is OK to mutate
     602                 :           // the input data, because there are no reparses in the View Source
     603                 :           // case, so we won't need the original data in the buffer anymore.
     604               0 :           buf[i] = '\n';
     605                 :           // fall through
     606                 :         case '\n': {
     607               0 :           ++i;
     608               0 :           if (mCStart < i) {
     609               0 :             PRInt32 len = i - mCStart;
     610               0 :             AppendCharacters(buf, mCStart, len);
     611               0 :             mCStart = i;
     612                 :           }
     613               0 :           ++mLineNumber;
     614               0 :           Push(nsGkAtoms::span, nsnull);
     615               0 :           nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     616               0 :           NS_ASSERTION(treeOp, "Tree op allocation failed.");
     617               0 :           treeOp->InitAddLineNumberId(CurrentNode(), mLineNumber);
     618               0 :           Pop();
     619               0 :           break;
     620                 :         }
     621                 :         default:
     622               0 :           ++i;
     623               0 :           break;
     624                 :       }
     625                 :     }
     626               0 :     if (mCStart < mPos) {
     627               0 :       PRInt32 len = mPos - mCStart;
     628               0 :       AppendCharacters(buf, mCStart, len);
     629               0 :       mCStart = mPos;
     630                 :     }
     631                 :   }
     632               0 : }
     633                 : 
     634                 : void
     635               0 : nsHtml5Highlighter::FlushCurrent()
     636                 : {
     637               0 :   mPos++;
     638               0 :   FlushChars();
     639               0 : }
     640                 : 
     641                 : bool
     642               0 : nsHtml5Highlighter::FlushOps()
     643                 : {
     644               0 :   bool hasOps = !mOpQueue.IsEmpty();
     645               0 :   if (hasOps) {
     646               0 :     mOpSink->MoveOpsFrom(mOpQueue);
     647                 :   }
     648               0 :   return hasOps;
     649                 : }
     650                 : 
     651                 : void
     652               0 : nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName,
     653                 :                                                nsString* aValue)
     654                 : {
     655               0 :   if (!(nsHtml5AttributeName::ATTR_HREF == aName ||
     656                 :         nsHtml5AttributeName::ATTR_SRC == aName ||
     657                 :         nsHtml5AttributeName::ATTR_ACTION == aName ||
     658                 :         nsHtml5AttributeName::ATTR_CITE == aName ||
     659                 :         nsHtml5AttributeName::ATTR_BACKGROUND == aName ||
     660                 :         nsHtml5AttributeName::ATTR_LONGDESC == aName ||
     661                 :         nsHtml5AttributeName::ATTR_XLINK_HREF == aName ||
     662               0 :         nsHtml5AttributeName::ATTR_DEFINITIONURL == aName)) {
     663               0 :     return;
     664                 :   }
     665               0 :   AddViewSourceHref(*aValue);
     666                 : }
     667                 : 
     668                 : void
     669               0 : nsHtml5Highlighter::CompletedNamedCharacterReference()
     670                 : {
     671               0 :   AddClass(sEntity);
     672               0 : }
     673                 : 
     674                 : nsIContent**
     675               0 : nsHtml5Highlighter::AllocateContentHandle()
     676                 : {
     677               0 :   if (mHandlesUsed == NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH) {
     678               0 :     mOldHandles.AppendElement(mHandles.forget());
     679               0 :     mHandles = new nsIContent*[NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH];
     680               0 :     mHandlesUsed = 0;
     681                 :   }
     682                 : #ifdef DEBUG
     683               0 :   mHandles[mHandlesUsed] = (nsIContent*)0xC0DEDBAD;
     684                 : #endif
     685               0 :   return &mHandles[mHandlesUsed++];
     686                 : }
     687                 : 
     688                 : nsIContent**
     689               0 : nsHtml5Highlighter::CreateElement(nsIAtom* aName,
     690                 :                                   nsHtml5HtmlAttributes* aAttributes)
     691                 : {
     692               0 :   NS_PRECONDITION(aName, "Got null name.");
     693               0 :   nsIContent** content = AllocateContentHandle();
     694                 :   mOpQueue.AppendElement()->Init(kNameSpaceID_XHTML,
     695                 :                                  aName,
     696                 :                                  aAttributes,
     697                 :                                  content,
     698               0 :                                  true);
     699               0 :   return content;
     700                 : }
     701                 : 
     702                 : nsIContent**
     703               0 : nsHtml5Highlighter::CurrentNode()
     704                 : {
     705               0 :   NS_PRECONDITION(mStack.Length() >= 1, "Must have something on stack.");
     706               0 :   return mStack[mStack.Length() - 1];
     707                 : }
     708                 : 
     709                 : void
     710               0 : nsHtml5Highlighter::Push(nsIAtom* aName,
     711                 :                          nsHtml5HtmlAttributes* aAttributes)
     712                 : {
     713               0 :   NS_PRECONDITION(mStack.Length() >= 1, "Pushing without root.");
     714               0 :   nsIContent** elt = CreateElement(aName, aAttributes); // Don't inline below!
     715               0 :   mOpQueue.AppendElement()->Init(eTreeOpAppend, elt, CurrentNode());
     716               0 :   mStack.AppendElement(elt);
     717               0 : }
     718                 : 
     719                 : void
     720               0 : nsHtml5Highlighter::Pop()
     721                 : {
     722               0 :   NS_PRECONDITION(mStack.Length() >= 2, "Popping when stack too short.");
     723               0 :   mStack.RemoveElementAt(mStack.Length() - 1);
     724               0 : }
     725                 : 
     726                 : void
     727               0 : nsHtml5Highlighter::AppendCharacters(const PRUnichar* aBuffer,
     728                 :                                      PRInt32 aStart,
     729                 :                                      PRInt32 aLength)
     730                 : {
     731               0 :   NS_PRECONDITION(aBuffer, "Null buffer");
     732                 : 
     733               0 :   PRUnichar* bufferCopy = new PRUnichar[aLength];
     734               0 :   memcpy(bufferCopy, aBuffer + aStart, aLength * sizeof(PRUnichar));
     735                 : 
     736                 :   mOpQueue.AppendElement()->Init(eTreeOpAppendText,
     737                 :                                  bufferCopy,
     738                 :                                  aLength,
     739               0 :                                  CurrentNode());
     740               0 : }
     741                 : 
     742                 : 
     743                 : void
     744               0 : nsHtml5Highlighter::AddClass(const PRUnichar* aClass)
     745                 : {
     746               0 :   if (!mSyntaxHighlight) {
     747               0 :     return;
     748                 :   }
     749               0 :   mOpQueue.AppendElement()->InitAddClass(CurrentNode(), aClass);
     750                 : }
     751                 : 
     752                 : void
     753               0 : nsHtml5Highlighter::AddViewSourceHref(const nsString& aValue)
     754                 : {
     755               0 :   PRUnichar* bufferCopy = new PRUnichar[aValue.Length() + 1];
     756               0 :   memcpy(bufferCopy, aValue.get(), aValue.Length() * sizeof(PRUnichar));
     757               0 :   bufferCopy[aValue.Length()] = 0;
     758                 : 
     759                 :   mOpQueue.AppendElement()->Init(eTreeOpAddViewSourceHref,
     760                 :                                  bufferCopy,
     761               0 :                                  aValue.Length(),
     762               0 :                                  CurrentNode());
     763               0 : }
     764                 : 
     765                 : void
     766               0 : nsHtml5Highlighter::AddErrorToCurrentNode(const char* aMsgId)
     767                 : {
     768               0 :   if (!mSyntaxHighlight) {
     769               0 :     return;
     770                 :   }
     771               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     772               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     773               0 :   treeOp->Init(CurrentNode(), aMsgId);
     774                 : }
     775                 : 
     776                 : void
     777               0 : nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId)
     778                 : {
     779               0 :   if (!mSyntaxHighlight) {
     780               0 :     return;
     781                 :   }
     782               0 :   NS_PRECONDITION(mCurrentRun, "Adding error to run without one!");
     783               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     784               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     785               0 :   treeOp->Init(mCurrentRun, aMsgId);
     786                 : }
     787                 : 
     788                 : void
     789               0 : nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId,
     790                 :                                          nsIAtom* aName)
     791                 : {
     792               0 :   if (!mSyntaxHighlight) {
     793               0 :     return;
     794                 :   }
     795               0 :   NS_PRECONDITION(mCurrentRun, "Adding error to run without one!");
     796               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     797               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     798               0 :   treeOp->Init(mCurrentRun, aMsgId, aName);
     799                 : }
     800                 : 
     801                 : void
     802               0 : nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId,
     803                 :                                          nsIAtom* aName,
     804                 :                                          nsIAtom* aOther)
     805                 : {
     806               0 :   if (!mSyntaxHighlight) {
     807               0 :     return;
     808                 :   }
     809               0 :   NS_PRECONDITION(mCurrentRun, "Adding error to run without one!");
     810               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     811               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     812               0 :   treeOp->Init(mCurrentRun, aMsgId, aName, aOther);
     813                 : }
     814                 : 
     815                 : void
     816               0 : nsHtml5Highlighter::AddErrorToCurrentAmpersand(const char* aMsgId)
     817                 : {
     818               0 :   if (!mSyntaxHighlight) {
     819               0 :     return;
     820                 :   }
     821               0 :   NS_PRECONDITION(mAmpersand, "Adding error to ampersand without one!");
     822               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     823               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     824               0 :   treeOp->Init(mAmpersand, aMsgId);
     825                 : }
     826                 : 
     827                 : void
     828               0 : nsHtml5Highlighter::AddErrorToCurrentSlash(const char* aMsgId)
     829                 : {
     830               0 :   if (!mSyntaxHighlight) {
     831               0 :     return;
     832                 :   }
     833               0 :   NS_PRECONDITION(mSlash, "Adding error to slash without one!");
     834               0 :   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     835               0 :   NS_ASSERTION(treeOp, "Tree op allocation failed.");
     836               0 :   treeOp->Init(mSlash, aMsgId);
     837                 : }

Generated by: LCOV version 1.7