/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include #include "CNavDelegate.h" #include "nsScanner.h" #include "nsParserTypes.h" #include "CNavDTD.h" // Note: We already handle the following special case conditions: // 1) If you see , simply treat it as a bad tag. // 2) If you see , treat it like a comment. // 3) If you see <> or <_ (< space) simply treat it as text. // 4) If you see <[!a..z] (< followed by non-alpha), treat it as text. static char gIdentChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; /** * Default constructor * * @updated gess 3/25/98 * @param * @return */ CNavDelegate::CNavDelegate() : ITokenizerDelegate(), mTokenDeque() { } /** * Default constructor * * @updated gess 3/25/98 * @param * @return */ CNavDelegate::CNavDelegate(CNavDelegate& aDelegate) : ITokenizerDelegate(), mTokenDeque() { } /** * * @update gess4/11/98 * @param * @return */ eParseMode CNavDelegate::GetParseMode(void) const { return eParseMode_unknown; } /** * Cause delegate to create and return a new DTD. * * @update gess4/22/98 * @return new DTD or null */ nsIDTD* CNavDelegate::GetDTD(void) const{ return new CNavDTD(); } /** * This method is called just after a "<" has been consumed * and we know we're at the start of some kind of tagged * element. We don't know yet if it's a tag or a comment. * * @update gess 5/12/98 * @param aChar is the last char read * @param aScanner is represents our input source * @param aToken is the out arg holding our new token * @return error code (may return kInterrupted). */ PRInt32 CNavDelegate::ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) { nsAutoString empty(""); PRInt32 result=aScanner.GetChar(aChar); if(kNoError==result) { switch(aChar) { case kForwardSlash: PRUnichar ch; result=aScanner.Peek(ch); if(kNoError==result) { if(nsString::IsAlpha(ch)) aToken=new CEndToken(empty); else aToken=new CCommentToken(empty); //Special case: is treated as a comment }//if break; case kExclamation: aToken=new CCommentToken(empty); break; default: if(nsString::IsAlpha(aChar)) return ConsumeStartTag(aChar,aScanner,aToken); else if(kEOF!=aChar) { nsAutoString temp("<"); return ConsumeText(temp,aScanner,aToken); } } //switch if((0!=aToken) && (kNoError==result)) { result= aToken->Consume(aChar,aScanner); //tell new token to finish consuming text... if(result) { delete aToken; aToken=0; } } //if } //if return result; } /** * This method is called just after we've consumed a start * tag, and we now have to consume its attributes. * * @update gess 3/25/98 * @param aChar: last char read * @param aScanner: see nsScanner.h * @return */ PRInt32 CNavDelegate::ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) { PRBool done=PR_FALSE; PRInt32 result=kNoError; nsAutoString as(""); PRInt16 theAttrCount=0; while((!done) && (result==kNoError)) { CToken* theToken= new CAttributeToken(as); if(theToken){ result=theToken->Consume(aChar,aScanner); //tell new token to finish consuming text... if(kNoError==result){ theAttrCount++; mTokenDeque.Push(theToken); }//if else delete theToken; //we can't keep it... }//if if(kNoError==result){ result=aScanner.Peek(aChar); if(aChar==kGreaterThan) { //you just ate the '>' aScanner.GetChar(aChar); //skip the '>' done=PR_TRUE; }//if }//if }//while aToken->SetAttributeCount(theAttrCount); return result; } /** * This is a special case method. It's job is to consume * all of the given tag up to an including the end tag. * * @param aChar: last char read * @param aScanner: see nsScanner.h * @param anErrorCode: arg that will hold error condition * @return new token or null */ PRInt32 CNavDelegate::ConsumeContentToEndTag(const nsString& aString,PRUnichar aChar,CScanner& aScanner,CToken*& aToken){ //In the case that we just read the given tag, we should go and //consume all the input until we find a matching end tag. nsAutoString endTag(""); aToken=new CSkippedContentToken(endTag); return aToken->Consume(aChar,aScanner); //tell new token to finish consuming text... } /** * This method is called just after a "<" has been consumed * and we know we're at the start of a tag. * * @update gess 3/25/98 * @param aChar: last char read * @param aScanner: see nsScanner.h * @param anErrorCode: arg that will hold error condition * @return new token or null */ PRInt32 CNavDelegate::ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) { PRInt32 theDequeSize=mTokenDeque.GetSize(); PRInt32 result=kNoError; aToken=new CStartToken(nsAutoString("")); if(aToken) { result= aToken->Consume(aChar,aScanner); //tell new token to finish consuming text... if(kNoError==result) { if(((CStartToken*)aToken)->IsAttributed()) { result=ConsumeAttributes(aChar,aScanner,aToken); } //now that that's over with, we have one more problem to solve. //In the case that we just read a