html_documentimpl.cpp Source File (khtml Library)

| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# html_documentimpl.cpp

    00001
    00024 #include "html/html_documentimpl.h"
    00025 #include "html/html_imageimpl.h"
    00026 #include "html/html_headimpl.h"
    00027 #include "html/html_baseimpl.h"
    00028 #include "html/htmltokenizer.h"
    00029 #include "html/html_miscimpl.h"
    00030
    00031 #include "khtmlview.h"
    00032 #include "khtml_part.h"
    00033 #include "khtmlpart_p.h"
    00034 #include "khtml_settings.h"
    00035 #include "misc/htmlattrs.h"
    00036 #include "misc/htmlhashes.h"
    00037
    00038 #include "xml/xml_tokenizer.h"
    00039 #include "xml/dom2_eventsimpl.h"
    00040
    00041 #include "khtml_factory.h"
    00042 #include "rendering/render_object.h"
    00043
    00044 #include <dcopclient.h>
    00045 #include <kapplication.h>
    00046 #include <kdebug.h>
    00047 #include <kurl.h>
    00048 #include <kglobal.h>
    00049 #include <kcharsets.h>
    00050 #include <kglobalsettings.h>
    00051
    00052 #include "css/cssproperties.h"
    00053 #include "css/cssstyleselector.h"
    00054 #include "css/css_stylesheetimpl.h"
    00055 #include <stdlib.h>
    00056 #include <qptrstack.h>
    00057
    00058 template class QPtrStack<DOM::NodeImpl>;
    00059
    00060 using namespace DOM;
    00061 using namespace khtml;
    00062
    00063
    00064 HTMLDocumentImpl::HTMLDocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
    00065   : DocumentImpl(_implementation, v)
    00066 {
    00067 //    kdDebug( 6090 ) << "HTMLDocumentImpl constructor this = " << this << endl;
    00068     bodyElement = 0;
    00069     htmlElement = 0;
    00070
    00071 /* dynamic history stuff to be fixed later (pfeiffer)
    00072     connect( KHTMLFactory::vLinks(), SIGNAL( inserted( const QString& )),
    00073              SLOT( slotHistoryChanged() ));
    00074     connect( KHTMLFactory::vLinks(), SIGNAL( removed( const QString& )),
    00075              SLOT( slotHistoryChanged() ));
    00076 */
    00077     connect( KHTMLFactory::vLinks(), SIGNAL( cleared()),
    00078              SLOT( slotHistoryChanged() ));
    00079 }
    00080
    00081 HTMLDocumentImpl::~HTMLDocumentImpl()
    00082 {
    00083 }
    00084
    00085 DOMString HTMLDocumentImpl::referrer() const
    00086 {
    00087     if ( view() )
    00088         return view()->part()->pageReferrer();
    00089     return DOMString();
    00090 }
    00091
    00092 DOMString HTMLDocumentImpl::domain() const
    00093 {
    00094     if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and space)
    00095         m_domain = KURL(URL()).host(); // Initially set to the host
    00096     return m_domain;
    00097 }
    00098
    00099 void HTMLDocumentImpl::setDomain(const DOMString &newDomain)
    00100 {
    00101     if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and space)
    00102         m_domain = KURL(URL()).host().lower(); // Initially set to the host
    00103
    00104     if ( m_domain.isEmpty() /*&& view() && view()->part()->openedByJS()*/ )
    00105         m_domain = newDomain.lower();
    00106
    00107     // Both NS and IE specify that changing the domain is only allowed when
    00108     // the new domain is a suffix of the old domain.
    00109     int oldLength = m_domain.length();
    00110     int newLength = newDomain.length();
    00111     if ( newLength < oldLength ) // e.g. newDomain=kde.org (7) and m_domain=www.kde.org (11)
    00112     {
    00113         DOMString test = m_domain.copy();
    00114         DOMString reference = newDomain.lower();
    00115         if ( test[oldLength - newLength - 1] == '.' ) // Check that it's a subdomain, not e.g. "de.org"
    00116         {
    00117             test.remove( 0, oldLength - newLength ); // now test is "kde.org" from m_domain
    00118             if ( test == reference )                 // and we check that it's the same thing as newDomain
    00119                 m_domain = reference;
    00120         }
    00121     }
    00122 }
    00123
    00124 DOMString HTMLDocumentImpl::lastModified() const
    00125 {
    00126     if ( view() )
    00127         return view()->part()->lastModified();
    00128     return DOMString();
    00129 }
    00130
    00131 DOMString HTMLDocumentImpl::cookie() const
    00132 {
    00133     long windowId = 0;
    00134     KHTMLView *v = view ();
    00135
    00136     if ( v && v->topLevelWidget() )
    00137       windowId = v->topLevelWidget()->winId();
    00138
    00139     QCString replyType;
    00140     QByteArray params, reply;
    00141     QDataStream stream(params, IO_WriteOnly);
    00142     stream << URL() << windowId;
    00143     if (!kapp->dcopClient()->call("kcookiejar", "kcookiejar",
    00144                                   "findDOMCookies(QString,long int)", params,
    00145                                   replyType, reply))
    00146     {
    00147        kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
    00148        return DOMString();
    00149     }
    00150
    00151     QDataStream stream2(reply, IO_ReadOnly);
    00152     if(replyType != "QString") {
    00153          kdError(6010) << "DCOP function findDOMCookies(...) returns "
    00154                        << replyType << ", expected QString" << endl;
    00155          return DOMString();
    00156     }
    00157
    00158     QString result;
    00159     stream2 >> result;
    00160     return DOMString(result);
    00161 }
    00162
    00163 void HTMLDocumentImpl::setCookie( const DOMString & value )
    00164 {
    00165     long windowId = 0;
    00166     KHTMLView *v = view ();
    00167
    00168     if ( v && v->topLevelWidget() )
    00169       windowId = v->topLevelWidget()->winId();
    00170
    00171     QByteArray params;
    00172     QDataStream stream(params, IO_WriteOnly);
    00173     QString fake_header("Set-Cookie: ");
    00174     fake_header.append(value.string());
    00175     fake_header.append("\n");
    00176     stream << URL() << fake_header.utf8() << windowId;
    00177     if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
    00178                                   "addCookies(QString,QCString,long int)", params))
    00179     {
    00180          // Maybe it wasn't running (e.g. we're opening local html files)
    00181          KApplication::startServiceByDesktopName( "kcookiejar");
    00182          if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
    00183                                        "addCookies(QString,QCString,long int)", params))
    00184              kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
    00185     }
    00186 }
    00187
    00188
    00189
    00190 HTMLElementImpl *HTMLDocumentImpl::body()
    00191 {
    00192     NodeImpl *de = documentElement();
    00193     if (!de)
    00194         return 0;
    00195
    00196     // try to prefer a FRAMESET element over BODY
    00197     NodeImpl* body = 0;
    00198     for (NodeImpl* i = de->firstChild(); i; i = i->nextSibling()) {
    00199         if (i->id() == ID_FRAMESET)
    00200             return static_cast<HTMLElementImpl*>(i);
    00201
    00202         if (i->id() == ID_BODY)
    00203             body = i;
    00204     }
    00205     return static_cast<HTMLElementImpl *>(body);
    00206 }
    00207
    00208 void HTMLDocumentImpl::setBody(HTMLElementImpl *_body)
    00209 {
    00210     int exceptioncode = 0;
    00211     HTMLElementImpl *b = body();
    00212     if ( !_body && !b ) return;
    00213     if ( !_body )
    00214         documentElement()->removeChild( b, exceptioncode );
    00215     else if ( !b )
    00216         documentElement()->appendChild( _body, exceptioncode );
    00217     else
    00218         documentElement()->replaceChild( _body, b, exceptioncode );
    00219 }
    00220
    00221 Tokenizer *HTMLDocumentImpl::createTokenizer()
    00222 {
    00223     return new HTMLTokenizer(docPtr(),m_view);
    00224 }
    00225
    00226 // --------------------------------------------------------------------------
    00227 // not part of the DOM
    00228 // --------------------------------------------------------------------------
    00229
    00230 bool HTMLDocumentImpl::childAllowed( NodeImpl *newChild )
    00231 {
    00232     // ### support comments. etc as a child
    00233     return (newChild->id() == ID_HTML || newChild->id() == ID_COMMENT);
    00234 }
    00235
    00236 ElementImpl *HTMLDocumentImpl::createElement( const DOMString &name, int* pExceptioncode )
    00237 {
    00238     ElementImpl* e = createHTMLElement( name );
    00239     if ( e )
    00240         return e;
    00241     return DOM::DocumentImpl::createElement( name, pExceptioncode );
    00242 }
    00243
    00244 void HTMLDocumentImpl::slotHistoryChanged()
    00245 {
    00246     if ( true || !m_render ) // disabled for now
    00247         return;
    00248
    00249     recalcStyle( Force );
    00250     m_render->repaint();
    00251 }
    00252
    00253 HTMLMapElementImpl* HTMLDocumentImpl::getMap(const DOMString& _url)
    00254 {
    00255     QString url = _url.string();
    00256     QString s;
    00257     int pos = url.find('#');
    00258     //kdDebug(0) << "map pos of #:" << pos << endl;
    00259     s = QString(_url.unicode() + pos + 1, _url.length() - pos - 1);
    00260
    00261     QMapConstIterator<QString,HTMLMapElementImpl*> it = mapMap.find(s);
    00262
    00263     if (it != mapMap.end())
    00264         return *it;
    00265     else
    00266         return 0;
    00267 }
    00268
    00269 static bool isTransitional(const QString &spec, int start)
    00270 {
    00271     if((spec.find("TRANSITIONAL", start, false ) != -1 ) ||
    00272        (spec.find("LOOSE", start, false ) != -1 ) ||
    00273        (spec.find("FRAMESET", start, false ) != -1 ) ||
    00274        (spec.find("LATIN1", start, false ) != -1 ) ||
    00275        (spec.find("SYMBOLS", start, false ) != -1 ) ||
    00276        (spec.find("SPECIAL", start, false ) != -1 ) ) {
    00277         //kdDebug() << "isTransitional" << endl;
    00278         return true;
    00279     }
    00280     return false;
    00281 }
    00282
    00283 void HTMLDocumentImpl::close()
    00284 {
    00285     bool doload = !parsing() && m_tokenizer;
    00286
    00287     DocumentImpl::close();
    00288
    00289     HTMLElementImpl* b = body();
    00290     if (b && doload) {
    00291         // According to dom the load event must not bubble
    00292         // but other browsers execute in a frameset document
    00293         // the first(IE)/last(Moz/Konq) registered onload on a <frame> and the
    00294         // first(IE)/last(Moz/Konq) registered onload on a <frameset>.
    00295
    00296         // The body has the listener for <frame onload>
    00297         b->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
    00298
    00299         b = body(); // the onload code could have changed it (e.g. document.open/write/close)
    00300
    00301         // The document has the listener for <frameset onload>
    00302         if (b && b->id() == ID_FRAMESET)
    00303             getDocument()->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
    00304
    00305         // don't update rendering if we're going to redirect anyway
    00306         if ( view() && ( view()->part()->d->m_redirectURL.isNull() ||
    00307                          view()->part()->d->m_delayRedirect > 1 ) )
    00308         updateRendering();
    00309     }
    00310 }
    00311
    00312
    00313 void HTMLDocumentImpl::determineParseMode( const QString &str )
    00314 {
    00315     //kdDebug() << "DocumentImpl::determineParseMode str=" << str<< endl;
    00316     // determines the parse mode for HTML
    00317     // quite some hints here are inspired by the mozilla code.
    00318     int oldPMode = pMode;
    00319
    00320     // default parsing mode is Loose
    00321     pMode = Compat;
    00322     hMode = Html3;
    00323
    00324     ParseMode systemId = Unknown;
    00325     ParseMode publicId = Unknown;
    00326
    00327     int pos = 0;
    00328     int doctype = str.find("!doctype", 0, false);
    00329     if( doctype > 2 ) {
    00330         pos = doctype - 2;
    00331         // Store doctype name
    00332         int start = doctype + 9;
    00333         while ( start < (int)str.length() && str[start].isSpace() )
    00334             start++;
    00335         int espace = str.find(' ',start);
    00336         QString name = str.mid(start,espace-start);
    00337         //kdDebug() << "DocumentImpl::determineParseMode setName: " << name << endl;
    00338         m_doctype->setName( name );
    00339     }
    00340
    00341     // get the first tag (or the doctype tag)
    00342     int start = str.find('<', pos);
    00343     int stop = str.find('>', pos);
    00344     if( start > -1 && stop > start ) {
    00345         QString spec = str.mid( start + 1, stop - start - 1 );
    00346         //kdDebug() << "DocumentImpl::determineParseMode dtd=" << spec<< endl;
    00347         start = 0;
    00348         int quote = -1;
    00349         if( doctype != -1 ) {
    00350             while( (quote = spec.find( "\"", start )) != -1 ) {
    00351                 int quote2 = spec.find( "\"", quote+1 );
    00352                 if(quote2 < 0) quote2 = spec.length();
    00353                 QString val = spec.mid( quote+1, quote2 - quote-1 );
    00354                 //kdDebug() << "DocumentImpl::determineParseMode val = " << val << endl;
    00355                 // find system id
    00356                 pos = val.find("http://www.w3.org/tr/", 0, false);
    00357                 if ( pos != -1 ) {
    00358                     // loose or strict dtd?
    00359                     if ( val.find("strict.dtd", pos, false) != -1 )
    00360                         systemId = Strict;
    00361                     else if (isTransitional(val, pos))
    00362                         systemId = Transitional;
    00363                 }
    00364
    00365                 // find public id
    00366                 pos = val.find("//dtd", 0, false );
    00367                 if ( pos != -1 ) {
    00368                     if( val.find( "xhtml", pos+6, false ) != -1 ) {
    00369                         hMode = XHtml;
    00370                         publicId = isTransitional(val, pos) ? Transitional : Strict;
    00371                     } else if ( val.find( "15445:1999", pos+6 ) != -1 ) {
    00372                         hMode = Html4;
    00373                         publicId = Strict;
    00374                     } else {
    00375                         int tagPos = val.find( "html", pos+6, false );
    00376                         if( tagPos == -1 )
    00377                             tagPos = val.find( "hypertext markup", pos+6, false );
    00378                         if ( tagPos != -1 ) {
    00379                             tagPos = val.find(QRegExp("[0-9]"), tagPos );
    00380                             int version = val.mid( tagPos, 1 ).toInt();
    00381                             //kdDebug() << "DocumentImpl::determineParseMode tagPos = " << tagPos << " version=" << version << endl;
    00382                             if( version > 3 ) {
    00383                                 hMode = Html4;
    00384                                 publicId = isTransitional( val, tagPos ) ? Transitional : Strict;
    00385                             }
    00386                         }
    00387                     }
    00388                 }
    00389                 start = quote2 + 1;
    00390             }
    00391         }
    00392
    00393         if( systemId == publicId )
    00394             pMode = publicId;
    00395         else if ( systemId == Unknown )
    00396             pMode = hMode == Html4 ? Compat : publicId;
    00397         else if ( publicId == Transitional && systemId == Strict ) {
    00398             pMode = hMode == Html3 ? Compat : Strict;
    00399         } else
    00400             pMode = Compat;
    00401
    00402         if ( hMode == XHtml )
    00403             pMode = Strict;
    00404     }
    00405 //     kdDebug() << "DocumentImpl::determineParseMode: publicId =" << publicId << " systemId = " << systemId << endl;
    00406 //     kdDebug() << "DocumentImpl::determineParseMode: htmlMode = " << hMode<< endl;
    00407 //     if( pMode == Strict )
    00408 //         kdDebug(6020) << " using strict parseMode" << endl;
    00409 //     else if (pMode == Compat )
    00410 //         kdDebug(6020) << " using compatibility parseMode" << endl;
    00411 //     else
    00412 //         kdDebug(6020) << " using transitional parseMode" << endl;
    00413
    00414     if ( pMode != oldPMode && styleSelector() )
    00415         recalcStyleSelector();
    00416 }
    00417
    00418 #include "html_documentimpl.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:50 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001