📄 htmltokenizer.cpp
字号:
{
int p;
switch (pending)
{
case SpacePending:
// Insert a breaking space
*dest++ = QChar(' ');
prePos++;
break;
case LFPending:
*dest = '\n';
dest++;
prePos = 0;
break;
case TabPending:
p = TAB_SIZE - ( prePos % TAB_SIZE );
#ifdef TOKEN_DEBUG
qDebug("tab pending, prePos: %d, toadd: %d", prePos, p);
#endif
for ( int x = 0; x < p; x++ )
*dest++ = QChar(' ');
prePos += p;
break;
case NonePending:
assert(0);
break;
}
}
pending = NonePending;
}
void HTMLTokenizer::write(const TokenizerString &str, bool appendData)
{
#ifdef TOKEN_DEBUG
kdDebug( 6036 ) << this << " Tokenizer::write(\"" << str << "\"," << appendData << ")" << endl;
#endif
// don't do parsing if there is not enough memory
OOM_PRE_CHECK( ( src.length() + str.length() ) * 16, 0, "HTMLTokenizer::write" )
if (!buffer)
return;
if (loadStopped)
return;
if ( ( m_executingScript && appendData ) || (!cachedScript.isEmpty()
#if NOKIA_CHANGES
&& !parser->doc()->fastDisplayMode()
#endif
) ) {
// don't parse; we will do this later
if (currentPrependingSrc) {
currentPrependingSrc->append(str);
} else {
pendingSrc.append(str);
}
return;
}
if ( onHold ) {
src.append(str);
return;
}
if (!src.isEmpty())
src.append(str);
else
setSrc(str);
// Once a timer is set, it has control of when the tokenizer continues.
if (timerId)
return;
bool wasInWrite = inWrite;
inWrite = true;
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("Beginning write at time %d\n", parser->doc()->elapsedTime());
#endif
// if (Entity)
// parseEntity(src, dest);
int processedCount = 0;
QTime startTime;
startTime.start();
KWQUIEventTime eventTime;
while (!src.isEmpty() && (!parser->doc()->part() || !parser->doc()->part()->isScheduledLocationChangePending())) {
if (!continueProcessing(processedCount, startTime, eventTime))
break;
// do we need to enlarge the buffer?
RETURN_IF_OOM( checkBuffer() );
ushort cc = src->unicode();
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;
switch(cc) {
case '/':
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
if ( pending ) {
// pre context always gets its spaces/linefeeds
if ( pre || script || (!parser->selectMode() &&
(!parser->noSpaces() || dest > buffer ))) {
addPending();
discard = AllDiscard; // So we discard the first LF after the open tag.
}
// just forget it
else
pending = NonePending;
}
if (cc == '/' && discard == AllDiscard)
discard = NoneDiscard; // A close tag. No need to discard LF.
processToken();
cBufferPos = 0;
tag = TagName;
parseTag(src);
}
else if ( cc == '&' && !src.escaped())
{
++src;
if ( pending )
addPending();
parseEntity(src, dest, true);
}
else if ( cc == '<' && !src.escaped())
{
tagStartLineno = lineno+src.lineCount();
++src;
startTag = true;
}
else if (( cc == '\n' ) || ( cc == '\r' ))
{
if (select && !script)
{
if (discard == LFDiscard)
{
// Ignore this LF
discard = NoneDiscard; // We have discarded 1 LF
}
else if(discard == AllDiscard)
{
}
else
{
// Process this LF
if (pending == NonePending)
pending = LFPending;
}
}
else {
if (discard == LFDiscard || discard == AllDiscard)
{
// Ignore this LF
discard = NoneDiscard; // We have discarded 1 LF
}
else
{
// Process this LF
if (pending)
addPending();
pending = LFPending;
}
}
/* Check for MS-DOS CRLF sequence */
if (cc == '\r')
{
skipLF = true;
}
++src;
}
else if (( cc == ' ' ) || ( cc == '\t' ))
{
if (select && !script) {
if(discard == SpaceDiscard)
discard = NoneDiscard;
else if(discard == AllDiscard)
{ }
else
pending = SpacePending;
}
else {
if (discard == AllDiscard)
discard = NoneDiscard;
if (pending)
addPending();
if (cc == ' ')
pending = SpacePending;
else
pending = TabPending;
}
++src;
}
else
{
if (pending)
addPending();
discard = NoneDiscard;
if ( pre )
{
prePos++;
}
#if QT_VERSION < 300
unsigned char row = src->row();
if ( row > 0x05 && row < 0x10 || row > 0xfd )
currToken.complexText = true;
#endif
*dest = *src;
fixUpChar( *dest );
++dest;
++src;
}
}
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("Ending write at time %d\n", parser->doc()->elapsedTime());
#endif
inWrite = wasInWrite;
if (noMoreData && !inWrite && !loadingExtScript && !m_executingScript && !timerId)
end(); // this actually causes us to be deleted
OOM_POST_CHECK_FAILED(
end();
)
}
void HTMLTokenizer::stopped()
{
if (timerId) {
killTimer(timerId);
timerId = 0;
}
}
bool HTMLTokenizer::processingData() const
{
return timerId != 0;
}
bool HTMLTokenizer::continueProcessing(int& processedCount, const QTime& startTime, const KWQUIEventTime& eventTime)
{
// We don't want to be checking elapsed time with every character, so we only check after we've
// processed a certain number of characters.
bool allowedYield = allowYield;
allowYield = false;
if (!loadingExtScript && !forceSynchronous && !m_executingScript && (processedCount > TOKENIZER_CHUNK_SIZE || allowedYield)) {
processedCount = 0;
if (startTime.elapsed() > TOKENIZER_TIME_DELAY) {
/* FIXME: We'd like to yield aggressively to give stylesheets the opportunity to
load, but this hurts overall performance on slower machines. For now turn this
off.
|| (!parser->doc()->haveStylesheetsLoaded() &&
(parser->doc()->documentElement()->id() != ID_HTML || parser->doc()->body()))) {*/
// Schedule the timer to keep processing as soon as possible.
if (!timerId)
timerId = startTimer(0);
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (eventTime.uiEventPending())
printf("Deferring processing of data because of UI event.\n");
else if (startTime.elapsed() > TOKENIZER_TIME_DELAY)
printf("Deferring processing of data because 200ms elapsed away from event loop.\n");
#endif
return false;
}
}
processedCount++;
return true;
}
void HTMLTokenizer::timerEvent(QTimerEvent* e)
{
if (e->timerId() == timerId) {
// Kill the timer.
killTimer(timerId);
timerId = 0;
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("Beginning timer write at time %d\n", parser->doc()->elapsedTime());
#endif
if (parser->doc()->view() && parser->doc()->view()-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -