📄 htmltokenizer.cpp
字号:
if (skipLF && (cc != '\n')) skipLF = false; if (skipLF) { skipLF = false; ++src; } else if ( Entity ) parseEntity( src, dest ); else if ( plaintext ) parseText( src ); else if (script) parseSpecial(src); else if (style) parseSpecial(src); else if (xmp) parseSpecial(src); else if (textarea) parseSpecial(src); else if (title) parseSpecial(src); else if (comment) parseComment(src); else if (server) parseServer(src); else if (processingInstruction) parseProcessingInstruction(src); else if (tag) parseTag(src); else if ( startTag ) { startTag = false; bool endTag = false; switch(cc) { case '/': endTag = true; break; case '!': { // <!-- comment --> searchCount = 1; // Look for '<!--' sequence to start comment break; } case '?': { // xml processing instruction processingInstruction = true; tquote = NoQuote; parseProcessingInstruction(src); continue; break; } case '%': if (!brokenServer) { // <% server stuff, handle as comment %> server = true; tquote = NoQuote; parseServer(src); continue; } // else fall through default: { if( ((cc >= 'a') && (cc <= 'z')) || ((cc >= 'A') && (cc <= 'Z'))) { // Start of a Start-Tag } else { // Invalid tag // Add as is if (pending) addPending(); *dest = '<'; dest++; continue; } } }; // end case // According to SGML any LF immediately after a starttag, or // immediately before an endtag should be ignored. // ### Gecko and MSIE though only ignores LF immediately after // starttags and only for PRE elements -- asj (28/06-2005) if ( pending ) if (!select) addPending(); else pending = NonePending; // Cancel unused discards discard = NoneDiscard; // if (!endTag) discard = LFDiscard; processToken(); cBufferPos = 0; tag = TagName; parseTag(src); } else if ( cc == '&' && !src.escaped()) { ++src; if ( pending ) addPending(); discard = NoneDiscard; parseEntity(src, dest, true); } else if ( cc == '<' && !src.escaped()) { tagStartLineno = lineno+src.lineCount(); ++src; discard = NoneDiscard; startTag = true; } else if (( cc == '\n' ) || ( cc == '\r' )) { if (discard == SpaceDiscard) discard = NoneDiscard; if (discard == LFDiscard) { // Ignore one LF discard = NoneDiscard; } else if (discard == AllDiscard) { // Ignore } else { if (select && !script) { pending = LFPending; } else { if (pending) addPending(); pending = LFPending; } } /* Check for MS-DOS CRLF sequence */ if (cc == '\r') { skipLF = true; } ++src; } else if (( cc == ' ' ) || ( cc == '\t' )) { if(discard == LFDiscard) discard = NoneDiscard; if(discard == SpaceDiscard) { // Ignore one space discard = NoneDiscard; } else if(discard == AllDiscard) { // Ignore } else { if (select && !script) { if (!pending) pending = SpacePending; } else { if (pending) addPending(); if (cc == ' ') pending = SpacePending; else pending = TabPending; } } ++src; } else { if (pending) addPending(); discard = NoneDiscard; if ( pre ) { prePos++; } *dest = *src; fixUpChar( *dest ); ++dest; ++src; } } if (noMoreData && cachedScript.isEmpty() && !m_executingScript) end(); // this actually causes us to be deleted}void HTMLTokenizer::timerEvent( QTimerEvent *e ){ if ( e->timerId() == m_autoCloseTimer && cachedScript.isEmpty() ) { finish(); }}void HTMLTokenizer::setAutoClose( bool b ) { killTimer( m_autoCloseTimer ); m_autoCloseTimer = 0; if ( b ) m_autoCloseTimer = startTimer(100);}void HTMLTokenizer::end(){ if ( buffer == 0 ) { emit finishedParsing(); return; } // parseTag is using the buffer for different matters if ( !tag ) processToken(); if(buffer) KHTML_DELETE_QCHAR_VEC(buffer); if(scriptCode) KHTML_DELETE_QCHAR_VEC(scriptCode); scriptCode = 0; scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0; buffer = 0; emit finishedParsing();}void HTMLTokenizer::finish(){ if ( m_autoCloseTimer ) { killTimer( m_autoCloseTimer ); m_autoCloseTimer = 0; } // do this as long as we don't find matching comment ends while((title || script || comment || server) && scriptCode && scriptCodeSize) { // we've found an unmatched comment start if (comment) brokenComments = true; else if (server) brokenServer = true; else if (script) brokenScript = true; checkScriptBuffer(); scriptCode[ scriptCodeSize ] = 0; scriptCode[ scriptCodeSize + 1 ] = 0; int pos; QString food; if (title || style || script) food.setUnicode(scriptCode, scriptCodeSize); else if (server) { food = "<"; food += QString(scriptCode, scriptCodeSize); } else { pos = QConstString(scriptCode, scriptCodeSize).string().find('>'); food.setUnicode(scriptCode+pos+1, scriptCodeSize-pos-1); // deep copy } KHTML_DELETE_QCHAR_VEC(scriptCode); scriptCode = 0; scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0; if (script) scriptHandler(); comment = title = server = script = false; if ( !food.isEmpty() ) write(food, true); } // this indicates we will not receive any more data... but if we are waiting on // an external script to load, we can't finish parsing until that is done noMoreData = true; if (cachedScript.isEmpty() && !m_executingScript && !onHold) end(); // this actually causes us to be deleted}void HTMLTokenizer::processToken(){ KJSProxy *jsProxy = view ? view->part()->jScript() : 0L; if (jsProxy) jsProxy->setEventHandlerLineno(tagStartLineno+1); if ( dest > buffer ) {#if 0 if(currToken.tid) { qDebug( "unexpected token id: %d, str: *%s*", currToken.tid,QConstString( buffer,dest-buffer ).string().latin1() ); assert(0); }#endif currToken.text = new DOMStringImpl( buffer, dest - buffer ); currToken.text->ref(); currToken.tid = ID_TEXT; } else if(!currToken.tid) { currToken.reset(); if (jsProxy) jsProxy->setEventHandlerLineno(lineno+src.lineCount()+1); return; } dest = buffer;#ifdef TOKEN_DEBUG QString name = QString( getTagName(currToken.tid) ); QString text; if(currToken.text) text = QConstString(currToken.text->s, currToken.text->l).string(); kdDebug( 6036 ) << "Token --> " << name << " id = " << currToken.tid << endl; if (currToken.flat) kdDebug( 6036 ) << "Token is FLAT!" << endl; if(!text.isNull()) kdDebug( 6036 ) << "text: \"" << text << "\"" << endl; unsigned long l = currToken.attrs ? currToken.attrs->length() : 0; if(l) { kdDebug( 6036 ) << "Attributes: " << l << endl; for (unsigned long i = 0; i < l; ++i) { NodeImpl::Id tid = currToken.attrs->idAt(i); DOMString value = currToken.attrs->valueAt(i); kdDebug( 6036 ) << " " << tid << " " << parser->doc()->getDocument()->getName(NodeImpl::AttributeId, tid).string() << "=\"" << value.string() << "\"" << endl; } } kdDebug( 6036 ) << endl;#endif // In some cases, parseToken() can cause javascript code to be executed // (for example, when setting an attribute that causes an event handler // to be created). So we need to protect against re-entrancy into the parser m_executingScript++; // pass the token over to the parser, the parser DOES NOT delete the token parser->parseToken(&currToken); m_executingScript--; if ( currToken.flat && currToken.tid != ID_TEXT && !parser->noSpaces() ) discard = NoneDiscard; currToken.reset(); if (jsProxy) jsProxy->setEventHandlerLineno(1);}HTMLTokenizer::~HTMLTokenizer(){ reset(); delete parser;}void HTMLTokenizer::enlargeBuffer(int len){ int newsize = kMax(size*2, size+len); int oldoffs = (dest - buffer); buffer = KHTML_REALLOC_QCHAR_VEC(buffer, newsize); dest = buffer + oldoffs; size = newsize;}void HTMLTokenizer::enlargeScriptBuffer(int len){ int newsize = kMax(scriptCodeMaxSize*2, scriptCodeMaxSize+len); scriptCode = KHTML_REALLOC_QCHAR_VEC(scriptCode, newsize); scriptCodeMaxSize = newsize;}void HTMLTokenizer::notifyFinished(CachedObject* /*finishedObj*/){ assert(!cachedScript.isEmpty()); bool done = false; while (!done && cachedScript.head()->isLoaded()) {#ifdef TOKEN_DEBUG kdDebug( 6036 ) << "Finished loading an external script" << endl;#endif CachedScript* cs = cachedScript.dequeue(); DOMString scriptSource = cs->script();#ifdef TOKEN_DEBUG kdDebug( 6036 ) << "External script is:" << endl << scriptSource.string() << endl;#endif setSrc(TokenizerString()); // make sure we forget about the script before we execute the new one // infinite recursion might happen otherwise QString cachedScriptUrl( cs->url().string() ); cs->deref(this); scriptExecution( scriptSource.string(), cachedScriptUrl ); done = cachedScript.isEmpty(); // 'script' is true when we are called synchronously from // parseScript(). In that case parseScript() will take care // of 'scriptOutput'. if ( !script ) { TokenizerString rest = pendingSrc; pendingSrc.clear(); write(rest, false); // we might be deleted at this point, do not // access any members. } }}bool HTMLTokenizer::isWaitingForScripts() const{ return cachedScript.count();}bool HTMLTokenizer::isExecutingScript() const{ return (m_executingScript > 0);}void HTMLTokenizer::setSrc(const TokenizerString& source){ lineno += src.lineCount(); src = source; src.resetLineCount();}void HTMLTokenizer::setOnHold(bool _onHold){ if (onHold == _onHold) return; onHold = _onHold;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -