html_formimpl.cpp Source File (khtml Library)

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

# html_formimpl.cpp

    00001 /*
    00002  * This file is part of the DOM implementation for KDE.
    00003  *
    00004  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    00005  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    00006  *           (C) 2001 Dirk Mueller (mueller@kde.org)
    00007  *
    00008  * This library is free software; you can redistribute it and/or
    00009  * modify it under the terms of the GNU Library General Public
    00010  * License as published by the Free Software Foundation; either
    00011  * version 2 of the License, or (at your option) any later version.
    00012  *
    00013  * This library is distributed in the hope that it will be useful,
    00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016  * Library General Public License for more details.
    00017  *
    00018  * You should have received a copy of the GNU Library General Public License
    00019  * along with this library; see the file COPYING.LIB.  If not, write to
    00020  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021  * Boston, MA 02111-1307, USA.
    00022  *
    00023  */
    00024
    00025 #undef FORMS_DEBUG
    00026 //#define FORMS_DEBUG
    00027
    00028 #include "html/html_formimpl.h"
    00029
    00030 #include "khtmlview.h"
    00031 #include "khtml_part.h"
    00032 #include "html/html_documentimpl.h"
    00033 #include "khtml_settings.h"
    00034 #include "misc/htmlhashes.h"
    00035
    00036 #include "css/cssstyleselector.h"
    00037 #include "css/cssproperties.h"
    00038 #include "css/cssvalues.h"
    00039 #include "css/csshelper.h"
    00040 #include "xml/dom_textimpl.h"
    00041 #include "xml/dom_docimpl.h"
    00042 #include "xml/dom2_eventsimpl.h"
    00043 #include "khtml_ext.h"
    00044
    00045 #include "rendering/render_form.h"
    00046
    00047 #include <kcharsets.h>
    00048 #include <kglobal.h>
    00049 #include <kdebug.h>
    00050 #include <kmimetype.h>
    00051 #include <kmessagebox.h>
    00052 #include <kapplication.h>
    00053 #include <klocale.h>
    00054 #include <netaccess.h>
    00055 #include <kfileitem.h>
    00056 #include <qfile.h>
    00057 #include <qtextcodec.h>
    00058
    00059 // for keygen
    00060 #include <qstring.h>
    00061 #include <ksslkeygen.h>
    00062
    00063 #include <assert.h>
    00064
    00065 using namespace DOM;
    00066 using namespace khtml;
    00067
    00068 HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc, bool implicit)
    00069     : HTMLElementImpl(doc)
    00070 {
    00071     m_implicit = implicit;
    00072     m_post = false;
    00073     m_multipart = false;
    00074     m_autocomplete = true;
    00075     m_insubmit = false;
    00076     m_doingsubmit = false;
    00077     m_inreset = false;
    00078     m_enctype = "application/x-www-form-urlencoded";
    00079     m_boundary = "----------" + KApplication::randomString( 42 + 13 );
    00080     m_acceptcharset = "UNKNOWN";
    00081 }
    00082
    00083 HTMLFormElementImpl::~HTMLFormElementImpl()
    00084 {
    00085     QPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
    00086     for (; it.current(); ++it)
    00087         it.current()->m_form = 0;
    00088     QPtrListIterator<HTMLImageElementImpl> it2(imgElements);
    00089     for (; it2.current(); ++it2)
    00090         it2.current()->m_form = 0;
    00091 }
    00092
    00093 NodeImpl::Id HTMLFormElementImpl::id() const
    00094 {
    00095     return ID_FORM;
    00096 }
    00097
    00098 long HTMLFormElementImpl::length() const
    00099 {
    00100     int len = 0;
    00101     QPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
    00102     for (; it.current(); ++it)
    00103         if (it.current()->isEnumeratable())
    00104             ++len;
    00105
    00106     return len;
    00107 }
    00108
    00109 static QCString encodeCString(const QCString& e)
    00110 {
    00111     // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
    00112     // safe characters like NS handles them for compatibility
    00113     static const char *safe = "-._*";
    00114     QCString encoded(( e.length()+e.contains( '\n' ) )*3
    00115                      +e.contains('\r') * 3 + 1);
    00116     int enclen = 0;
    00117     bool crmissing = false;
    00118     unsigned char oldc;
    00119     unsigned char c ='\0';
    00120
    00121     //QCString orig(e.data(), e.size());
    00122
    00123     for(unsigned pos = 0; pos < e.length(); pos++) {
    00124         oldc = c;
    00125         c = e[pos];
    00126
    00127         if (crmissing && c != '\n') {
    00128             encoded[enclen++] = '%';
    00129             encoded[enclen++] = '0';
    00130             encoded[enclen++] = 'D';
    00131             crmissing = false;
    00132         }
    00133
    00134         if ( (( c >= 'A') && ( c <= 'Z')) ||
    00135              (( c >= 'a') && ( c <= 'z')) ||
    00136              (( c >= '0') && ( c <= '9')) ||
    00137              (strchr(safe, c))
    00138             )
    00139             encoded[enclen++] = c;
    00140         else if ( c == ' ' )
    00141             encoded[enclen++] = '+';
    00142         else if ( c == '\n' )
    00143         {
    00144             encoded[enclen++] = '%';
    00145             encoded[enclen++] = '0';
    00146             encoded[enclen++] = 'D';
    00147             encoded[enclen++] = '%';
    00148             encoded[enclen++] = '0';
    00149             encoded[enclen++] = 'A';
    00150             crmissing = false;
    00151         }
    00152         else if (c == '\r' && oldc != '\n') {
    00153             crmissing = true;
    00154         }
    00155         else if ( c != '\r' )
    00156         {
    00157             encoded[enclen++] = '%';
    00158             unsigned int h = c / 16;
    00159             h += (h > 9) ? ('A' - 10) : '0';
    00160             encoded[enclen++] = h;
    00161
    00162             unsigned int l = c % 16;
    00163             l += (l > 9) ? ('A' - 10) : '0';
    00164             encoded[enclen++] = l;
    00165         }
    00166     }
    00167     encoded[enclen++] = '\0';
    00168     encoded.truncate(enclen);
    00169
    00170     return encoded;
    00171 }
    00172
    00173 inline static QCString fixUpfromUnicode(const QTextCodec* codec, const QString& s)
    00174 {
    00175     QCString str = codec->fromUnicode(s);
    00176     str.truncate(str.length());
    00177     return str;
    00178 }
    00179
    00180 QByteArray HTMLFormElementImpl::formData(bool& ok)
    00181 {
    00182 #ifdef FORMS_DEBUG
    00183     kdDebug( 6030 ) << "form: formData()" << endl;
    00184 #endif
    00185
    00186     QByteArray form_data(0);
    00187     QCString enc_string = ""; // used for non-multipart data
    00188
    00189     // find out the QTextcodec to use
    00190     QString str = m_acceptcharset.string();
    00191     QChar space(' ');
    00192     for(unsigned int i=0; i < str.length(); i++) if(str[i].latin1() == ',') str[i] = space;
    00193     QStringList charsets = QStringList::split(' ', str);
    00194     QTextCodec* codec = 0;
    00195     KHTMLView *view = getDocument()->view();
    00196     for ( QStringList::Iterator it = charsets.begin(); it != charsets.end(); ++it )
    00197     {
    00198         QString enc = (*it);
    00199         if(enc.contains("UNKNOWN"))
    00200         {
    00201             // use standard document encoding
    00202             enc = "ISO 8859-1";
    00203             if(view && view->part())
    00204                 enc = view->part()->encoding();
    00205         }
    00206         if((codec = KGlobal::charsets()->codecForName(enc.latin1())))
    00207             break;
    00208     }
    00209
    00210     if(!codec)
    00211         codec = QTextCodec::codecForLocale();
    00212
    00213     // we need to map visual hebrew to logical hebrew, as the web
    00214     // server alsways expects responses in logical ordering
    00215     if ( codec->mibEnum() == 11 )
    00216         codec = QTextCodec::codecForMib( 85 );
    00217
    00218     m_encCharset = codec->name();
    00219     for(unsigned int i=0; i < m_encCharset.length(); i++)
    00220         m_encCharset[i] = m_encCharset[i].latin1() == ' ' ? QChar('-') : m_encCharset[i].lower();
    00221
    00222     QStringList fileUploads;
    00223
    00224     for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
    00225         HTMLGenericFormElementImpl* current = it.current();
    00226         khtml::encodingList lst;
    00227
    00228         if (!current->disabled() && current->encoding(codec, lst, m_multipart))
    00229         {
    00230             //kdDebug(6030) << "adding name " << current->name().string() << endl;
    00231             khtml::encodingList::Iterator it;
    00232             for( it = lst.begin(); it != lst.end(); ++it )
    00233             {
    00234                 if (!m_multipart)
    00235                 {
    00236                     // handle ISINDEX / <input name=isindex> special
    00237                     // but only if its the first entry
    00238                     if ( enc_string.isEmpty() && *it == "isindex" ) {
    00239                         ++it;
    00240                         enc_string += encodeCString( *it );
    00241                     }
    00242                     else {
    00243                         if(!enc_string.isEmpty())
    00244                             enc_string += '&';
    00245
    00246                         enc_string += encodeCString(*it);
    00247                         enc_string += "=";
    00248                         ++it;
    00249                         enc_string += encodeCString(*it);
    00250                     }
    00251                 }
    00252                 else
    00253                 {
    00254                     QCString hstr("--");
    00255                     hstr += m_boundary.latin1();
    00256                     hstr += "\r\n";
    00257                     hstr += "Content-Disposition: form-data; name=\"";
    00258                     hstr += (*it).data();
    00259                     hstr += "\"";
    00260
    00261                     // if the current type is FILE, then we also need to
    00262                     // include the filename
    00263                     if (current->nodeType() == Node::ELEMENT_NODE && current->id() == ID_INPUT &&
    00264                         static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE)
    00265                     {
    00266                         QString path = static_cast<HTMLInputElementImpl*>(current)->value().string();
    00267                         if (path.length()) fileUploads << path;
    00268                         QString onlyfilename = path.mid(path.findRev('/')+1);
    00269
    00270                         hstr += fixUpfromUnicode(codec, "; filename=\"" + onlyfilename + "\"");
    00271                         if(!static_cast<HTMLInputElementImpl*>(current)->value().isEmpty())
    00272                         {
    00273                             hstr += "\r\nContent-Type: ";
    00274                             KMimeType::Ptr ptr = KMimeType::findByURL(KURL(path));
    00275                             hstr += ptr->name().ascii();
    00276                         }
    00277                     }
    00278
    00279                     hstr += "\r\n\r\n";
    00280                     ++it;
    00281
    00282                     // append body
    00283                     unsigned int old_size = form_data.size();
    00284                     form_data.resize( old_size + hstr.length() + (*it).size() + 1);
    00285                     memcpy(form_data.data() + old_size, hstr.data(), hstr.length());
    00286                     memcpy(form_data.data() + old_size + hstr.length(), *it, (*it).size());
    00287                     form_data[form_data.size()-2] = '\r';
    00288                     form_data[form_data.size()-1] = '\n';
    00289                 }
    00290             }
    00291         }
    00292     }
    00293
    00294     if (fileUploads.count()) {
    00295         int result = KMessageBox::warningContinueCancelList( 0,
    00296                                                              i18n("You're about to transfer the following files from "
    00297                                                                   "your local computer to the Internet.\n"
    00298                                                                   "Do you really want to continue?"),
    00299                                                              fileUploads);
    00300
    00301
    00302         if (result == KMessageBox::Cancel) {
    00303             ok = false;
    00304             return QByteArray();
    00305         }
    00306     }
    00307
    00308     if (m_multipart)
    00309         enc_string = ("--" + m_boundary + "--\r\n").ascii();
    00310
    00311     int old_size = form_data.size();
    00312     form_data.resize( form_data.size() + enc_string.length() );
    00313     memcpy(form_data.data() + old_size, enc_string.data(), enc_string.length() );
    00314
    00315     ok = true;
    00316     return form_data;
    00317 }
    00318
    00319 void HTMLFormElementImpl::setEnctype( const DOMString& type )
    00320 {
    00321     if(type.string().find("multipart", 0, false) != -1 || type.string().find("form-data", 0, false) != -1)
    00322     {
    00323         m_enctype = "multipart/form-data";
    00324         m_multipart = true;
    00325         m_post = true;
    00326     } else if (type.string().find("text", 0, false) != -1 || type.string().find("plain", 0, false) != -1)
    00327     {
    00328         m_enctype = "text/plain";
    00329         m_multipart = false;
    00330     }
    00331     else
    00332     {
    00333         m_enctype = "application/x-www-form-urlencoded";
    00334         m_multipart = false;
    00335     }
    00336     m_encCharset = QString::null;
    00337 }
    00338
    00339 void HTMLFormElementImpl::submitFromKeyboard()
    00340 {
    00341     // Activate the first submit button
    00342     // if there is none, do a submit anyway if not more
    00343     // than one <input type=text> or <input type=password>
    00344     unsigned int inputtext = 0;
    00345     for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
    00346         if (it.current()->id() == ID_BUTTON) {
    00347             HTMLButtonElementImpl* current = static_cast<HTMLButtonElementImpl *>(it.current());
    00348             if (current->buttonType() == HTMLButtonElementImpl::SUBMIT && !current->disabled()) {
    00349                 current->activate();
    00350                 return;
    00351             }
    00352         } else if (it.current()->id() == ID_INPUT) {
    00353             HTMLInputElementImpl* current = static_cast<HTMLInputElementImpl *>(it.current());
    00354             switch(current->inputType())  {
    00355             case HTMLInputElementImpl::SUBMIT:
    00356             case HTMLInputElementImpl::IMAGE:
    00357                 current->activate();
    00358                 return;
    00359             case HTMLInputElementImpl::TEXT:
    00360             case HTMLInputElementImpl::PASSWORD:
    00361                 ++inputtext;
    00362             default:
    00363                 break;
    00364             }
    00365         }
    00366     }
    00367
    00368     if (inputtext <= 1)
    00369         prepareSubmit();
    00370 }
    00371
    00372 bool HTMLFormElementImpl::prepareSubmit()
    00373 {
    00374     KHTMLView *view = getDocument()->view();
    00375     if(m_insubmit || !view || !view->part() || view->part()->onlyLocalReferences())
    00376         return m_insubmit;
    00377
    00378     m_insubmit = true;
    00379     m_doingsubmit = false;
    00380
    00381     if ( dispatchHTMLEvent(EventImpl::SUBMIT_EVENT,true,true) && !m_doingsubmit )
    00382         m_doingsubmit = true;
    00383
    00384     m_insubmit = false;
    00385
    00386     if ( m_doingsubmit )
    00387         submit();
    00388
    00389     return m_doingsubmit;
    00390 }
    00391
    00392 void HTMLFormElementImpl::submit(  )
    00393 {
    00394     if ( m_insubmit ) {
    00395         m_doingsubmit = true;
    00396         return;
    00397     }
    00398
    00399     m_insubmit = true;
    00400
    00401 #ifdef FORMS_DEBUG
    00402     kdDebug( 6030 ) << "submitting!" << endl;
    00403 #endif
    00404
    00405     KHTMLView *view = getDocument()->view();
    00406     for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
    00407         HTMLGenericFormElementImpl* current = it.current();
    00408         if (current->id() == ID_INPUT &&
    00409             static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT &&
    00410             static_cast<HTMLInputElementImpl*>(current)->autoComplete() )
    00411         {
    00412             HTMLInputElementImpl *input = static_cast<HTMLInputElementImpl *>(current);
    00413             view->addFormCompletionItem(input->name().string(), input->value().string());
    00414         }
    00415     }
    00416
    00417     bool ok;
    00418     QByteArray form_data = formData(ok);
    00419     if (ok) {
    00420         DOMString url(khtml::parseURL(getAttribute(ATTR_ACTION)));
    00421         if(m_post) {
    00422             view->part()->submitForm( "post", url.string(), form_data,
    00423                                       m_target.string(),
    00424                                       enctype().string(),
    00425                                       m_boundary );
    00426         }
    00427         else {
    00428             view->part()->submitForm( "get", url.string(), form_data,
    00429                                       m_target.string() );
    00430         }
    00431     }
    00432
    00433     m_doingsubmit = m_insubmit = false;
    00434 }
    00435
    00436 void HTMLFormElementImpl::reset(  )
    00437 {
    00438     KHTMLView *view = getDocument()->view();
    00439     if(m_inreset || !view || !view->part()) return;
    00440
    00441     m_inreset = true;
    00442
    00443 #ifdef FORMS_DEBUG
    00444     kdDebug( 6030 ) << "reset pressed!" << endl;
    00445 #endif
    00446
    00447     // ### DOM2 labels this event as not cancelable, however
    00448     // common browsers( sick! ) allow it be cancelled.
    00449     if ( !dispatchHTMLEvent(EventImpl::RESET_EVENT,true, true) ) {
    00450         m_inreset = false;
    00451         return;
    00452     }
    00453
    00454     for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it)
    00455         it.current()->reset();
    00456
    00457     m_inreset = false;
    00458 }
    00459
    00460 void HTMLFormElementImpl::parseAttribute(AttributeImpl *attr)
    00461 {
    00462     switch(attr->id())
    00463     {
    00464     case ATTR_ACTION:
    00465         break;
    00466     case ATTR_TARGET:
    00467         m_target = attr->value();
    00468         break;
    00469     case ATTR_METHOD:
    00470         m_post = ( strcasecmp( attr->value(), "post" ) == 0 );
    00471         break;
    00472     case ATTR_ENCTYPE:
    00473         setEnctype( attr->value() );
    00474         break;
    00475     case ATTR_ACCEPT_CHARSET:
    00476         // space separated list of charsets the server
    00477         // accepts - see rfc2045
    00478         m_acceptcharset = attr->value();
    00479         break;
    00480     case ATTR_ACCEPT:
    00481         // ignore this one for the moment...
    00482         break;
    00483     case ATTR_AUTOCOMPLETE:
    00484         m_autocomplete = strcasecmp( attr->value(), "off" );
    00485         break;
    00486     case ATTR_ONSUBMIT:
    00487         setHTMLEventListener(EventImpl::SUBMIT_EVENT,
    00488             getDocument()->createHTMLEventListener(attr->value().string()));
    00489         break;
    00490     case ATTR_ONRESET:
    00491         setHTMLEventListener(EventImpl::RESET_EVENT,
    00492             getDocument()->createHTMLEventListener(attr->value().string()));
    00493         break;
    00494     case ATTR_ID:
    00495     case ATTR_NAME:
    00496         break;
    00497     default:
    00498         HTMLElementImpl::parseAttribute(attr);
    00499     }
    00500 }
    00501
    00502 void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller )
    00503 {
    00504     for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
    00505         HTMLGenericFormElementImpl *current = it.current();
    00506         if (current->id() == ID_INPUT &&
    00507             static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::RADIO &&
    00508             current != caller && current->form() == caller->form() && current->name() == caller->name()) {
    00509             static_cast<HTMLInputElementImpl*>(current)->setChecked(false);
    00510         }
    00511     }
    00512 }
    00513
    00514 void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl *e)
    00515 {
    00516     formElements.append(e);
    00517 }
    00518
    00519 void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl *e)
    00520 {
    00521     formElements.remove(e);
    00522 }
    00523
    00524 void HTMLFormElementImpl::registerImgElement(HTMLImageElementImpl *e)
    00525 {
    00526     imgElements.append(e);
    00527 }
    00528
    00529 void HTMLFormElementImpl::removeImgElement(HTMLImageElementImpl *e)
    00530 {
    00531     imgElements.remove(e);
    00532 }
    00533
    00534 // -------------------------------------------------------------------------
    00535
    00536 HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    00537     : HTMLElementImpl(doc)
    00538 {
    00539     m_disabled = m_readOnly = false;
    00540     m_name = 0;
    00541
    00542     if (f)
    00543         m_form = f;
    00544     else
    00545         m_form = getForm();
    00546     if (m_form)
    00547         m_form->registerFormElement(this);
    00548 }
    00549
    00550 void HTMLGenericFormElementImpl::insertedIntoDocument()
    00551 {
    00552     HTMLElementImpl::insertedIntoDocument();
    00553
    00554     HTMLFormElementImpl* newform = getForm();
    00555
    00556     if (!m_form && newform) {
    00557         m_form = newform;
    00558         m_form->registerFormElement(this);
    00559     }
    00560 }
    00561
    00562 void HTMLGenericFormElementImpl::removedFromDocument()
    00563 {
    00564     HTMLElementImpl::removedFromDocument();
    00565
    00566     if (m_form)
    00567         m_form->removeFormElement(this);
    00568
    00569     m_form = 0;
    00570 }
    00571
    00572 HTMLGenericFormElementImpl::~HTMLGenericFormElementImpl()
    00573 {
    00574     if (m_form)
    00575         m_form->removeFormElement(this);
    00576 }
    00577
    00578 void HTMLGenericFormElementImpl::parseAttribute(AttributeImpl *attr)
    00579 {
    00580     switch(attr->id())
    00581     {
    00582     case ATTR_NAME:
    00583         break;
    00584     case ATTR_DISABLED:
    00585         setDisabled( attr->val() != 0 );
    00586         break;
    00587     case ATTR_READONLY:
    00588     {
    00589         bool m_oldreadOnly = m_readOnly;
    00590         m_readOnly = attr->val() != 0;
    00591         if (m_oldreadOnly != m_readOnly) setChanged();
    00592         break;
    00593     }
    00594     default:
    00595         HTMLElementImpl::parseAttribute(attr);
    00596     }
    00597 }
    00598
    00599 void HTMLGenericFormElementImpl::attach()
    00600 {
    00601     assert(!attached());
    00602
    00603     if (m_render) {
    00604         assert(m_render->style());
    00605         parentNode()->renderer()->addChild(m_render, nextRenderer());
    00606         m_render->updateFromElement();
    00607     }
    00608
    00609     NodeBaseImpl::attach();
    00610 }
    00611
    00612 HTMLFormElementImpl *HTMLGenericFormElementImpl::getForm() const
    00613 {
    00614     NodeImpl *p = parentNode();
    00615     while(p)
    00616     {
    00617         if( p->id() == ID_FORM )
    00618             return static_cast<HTMLFormElementImpl *>(p);
    00619         p = p->parentNode();
    00620     }
    00621 #ifdef FORMS_DEBUG
    00622     kdDebug( 6030 ) << "couldn't find form!" << endl;
    00623     kdDebug( 6030 ) << kdBacktrace() << endl;
    00624 #endif
    00625     return 0;
    00626 }
    00627
    00628 DOMString HTMLGenericFormElementImpl::name() const
    00629 {
    00630     if (m_name) return m_name;
    00631
    00632 // ###
    00633 //     DOMString n = getDocument()->htmlMode() != DocumentImpl::XHtml ?
    00634 //                   getAttribute(ATTR_NAME) : getAttribute(ATTR_ID);
    00635     DOMString n = getAttribute(ATTR_NAME);
    00636     if (n.isNull())
    00637         return new DOMStringImpl("");
    00638
    00639     return n;
    00640 }
    00641
    00642 void HTMLGenericFormElementImpl::setName(const DOMString& name)
    00643 {
    00644     if (m_name) m_name->deref();
    00645     m_name = name.implementation();
    00646     if (m_name) m_name->ref();
    00647 }
    00648
    00649 void HTMLGenericFormElementImpl::onSelect()
    00650 {
    00651     // ### make this work with new form events architecture
    00652     dispatchHTMLEvent(EventImpl::SELECT_EVENT,true,false);
    00653 }
    00654
    00655 void HTMLGenericFormElementImpl::onChange()
    00656 {
    00657     // ### make this work with new form events architecture
    00658     dispatchHTMLEvent(EventImpl::CHANGE_EVENT,true,false);
    00659 }
    00660
    00661 void HTMLGenericFormElementImpl::setDisabled( bool _disabled )
    00662 {
    00663     if ( m_disabled != _disabled ) {
    00664         m_disabled = _disabled;
    00665         setChanged();
    00666     }
    00667 }
    00668
    00669 bool HTMLGenericFormElementImpl::isSelectable() const
    00670 {
    00671     return  m_render && m_render->isWidget() &&
    00672         static_cast<RenderWidget*>(m_render)->widget() &&
    00673         static_cast<RenderWidget*>(m_render)->widget()->focusPolicy() >= QWidget::TabFocus;
    00674 }
    00675
    00676 void HTMLGenericFormElementImpl::defaultEventHandler(EventImpl *evt)
    00677 {
    00678     if (evt->target()==this && !m_disabled)
    00679     {
    00680         // Report focus in/out changes to the browser extension (editable widgets only)
    00681         KHTMLView *view = getDocument()->view();
    00682         if (evt->id()==EventImpl::DOMFOCUSIN_EVENT && isEditable() && m_render && m_render->isWidget()) {
    00683             KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension());
    00684             QWidget *widget = static_cast<RenderWidget*>(m_render)->widget();
    00685             if (ext)
    00686                 ext->editableWidgetFocused(widget);
    00687         }
    00688         if (evt->id()==EventImpl::MOUSEDOWN_EVENT || evt->id()==EventImpl::KHTML_KEYDOWN_EVENT)
    00689         {
    00690             setActive();
    00691         }
    00692         else if (evt->id() == EventImpl::MOUSEUP_EVENT || evt->id()==EventImpl::KHTML_KEYUP_EVENT)
    00693         {
    00694             if (m_active)
    00695             {
    00696                 setActive(false);
    00697                 setFocus();
    00698             }
    00699             else {
    00700                 setActive(false);
    00701             }
    00702         }
    00703
    00704         if (evt->id()==EventImpl::KHTML_KEYDOWN_EVENT ||
    00705             evt->id()==EventImpl::KHTML_KEYUP_EVENT)
    00706         {
    00707             TextEventImpl * k = static_cast<TextEventImpl *>(evt);
    00708             if (k->keyVal() == QChar('\n').unicode() && m_render && m_render->isWidget() && k->qKeyEvent)
    00709                 QApplication::sendEvent(static_cast<RenderWidget *>(m_render)->widget(), k->qKeyEvent);
    00710         }
    00711
    00712         if (evt->id()==EventImpl::DOMFOCUSOUT_EVENT && isEditable() && m_render && m_render->isWidget()) {
    00713             KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension());
    00714             QWidget *widget = static_cast<RenderWidget*>(m_render)->widget();
    00715             if (ext)
    00716                 ext->editableWidgetBlurred(widget);
    00717
    00718             // ### Don't count popup as a valid reason for losing the focus (example: opening the options of a select
    00719             // combobox shouldn't emit onblur)
    00720         }
    00721     }
    00722     if (evt->target() == this && evt->isMouseEvent() && renderer())
    00723         evt->setDefaultHandled();
    00724
    00725     HTMLElementImpl::defaultEventHandler(evt);
    00726 }
    00727
    00728 bool HTMLGenericFormElementImpl::isEditable()
    00729 {
    00730     return false;
    00731 }
    00732
    00733 // -------------------------------------------------------------------------
    00734
    00735 HTMLButtonElementImpl::HTMLButtonElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    00736     : HTMLGenericFormElementImpl(doc, f)
    00737 {
    00738     m_clicked = false;
    00739     m_type = SUBMIT;
    00740     m_dirty = true;
    00741     m_activeSubmit = false;
    00742 }
    00743
    00744 HTMLButtonElementImpl::~HTMLButtonElementImpl()
    00745 {
    00746 }
    00747
    00748 NodeImpl::Id HTMLButtonElementImpl::id() const
    00749 {
    00750     return ID_BUTTON;
    00751 }
    00752
    00753 DOMString HTMLButtonElementImpl::type() const
    00754 {
    00755     return getAttribute(ATTR_TYPE);
    00756 }
    00757
    00758 void HTMLButtonElementImpl::parseAttribute(AttributeImpl *attr)
    00759 {
    00760     switch(attr->id())
    00761     {
    00762     case ATTR_TYPE:
    00763         if ( strcasecmp( attr->value(), "submit" ) == 0 )
    00764             m_type = SUBMIT;
    00765         else if ( strcasecmp( attr->value(), "reset" ) == 0 )
    00766             m_type = RESET;
    00767         else if ( strcasecmp( attr->value(), "button" ) == 0 )
    00768             m_type = BUTTON;
    00769         break;
    00770     case ATTR_VALUE:
    00771         m_value = attr->value();
    00772         m_currValue = m_value.string();
    00773         break;
    00774     case ATTR_ACCESSKEY:
    00775         break;
    00776     case ATTR_ONFOCUS:
    00777         setHTMLEventListener(EventImpl::FOCUS_EVENT,
    00778             getDocument()->createHTMLEventListener(attr->value().string()));
    00779         break;
    00780     case ATTR_ONBLUR:
    00781         setHTMLEventListener(EventImpl::BLUR_EVENT,
    00782             getDocument()->createHTMLEventListener(attr->value().string()));
    00783         break;
    00784     default:
    00785         HTMLGenericFormElementImpl::parseAttribute(attr);
    00786     }
    00787 }
    00788
    00789 void HTMLButtonElementImpl::attach()
    00790 {
    00791     assert(!attached());
    00792     assert(!m_render);
    00793     assert(parentNode());
    00794     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    00795     _style->ref();
    00796     if (parentNode()->renderer() && _style->display() != NONE) {
    00797         m_render = new RenderCustomButton(this);
    00798         m_render->setStyle(_style);
    00799     }
    00800     HTMLGenericFormElementImpl::attach();
    00801     _style->deref();
    00802 }
    00803
    00804 void HTMLButtonElementImpl::defaultEventHandler(EventImpl *evt)
    00805 {
    00806     if (m_type != BUTTON && (evt->id() == EventImpl::DOMACTIVATE_EVENT) && !m_disabled)
    00807         activate();
    00808     HTMLGenericFormElementImpl::defaultEventHandler(evt);
    00809 }
    00810
    00811 void HTMLButtonElementImpl::activate()
    00812 {
    00813     m_clicked = true;
    00814
    00815     if(m_form && m_type == SUBMIT) {
    00816         m_activeSubmit = true;
    00817         m_form->prepareSubmit();
    00818         m_activeSubmit = false; // in case we were canceled
    00819     }
    00820     if(m_form && m_type == RESET)
    00821         m_form->reset();
    00822 }
    00823
    00824 bool HTMLButtonElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoding, bool /*multipart*/)
    00825 {
    00826     if (m_type != SUBMIT || name().isEmpty() || !m_activeSubmit)
    00827         return false;
    00828
    00829     encoding += fixUpfromUnicode(codec, name().string());
    00830     QString enc_str = m_currValue.isNull() ? QString("") : m_currValue;
    00831     encoding += fixUpfromUnicode(codec, enc_str);
    00832
    00833     return true;
    00834 }
    00835
    00836
    00837 // -------------------------------------------------------------------------
    00838
    00839 HTMLFieldSetElementImpl::HTMLFieldSetElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    00840     : HTMLGenericFormElementImpl(doc, f), m_legend(0)
    00841 {
    00842 }
    00843
    00844 HTMLFieldSetElementImpl::~HTMLFieldSetElementImpl()
    00845 {
    00846 }
    00847
    00848 NodeImpl::Id HTMLFieldSetElementImpl::id() const
    00849 {
    00850     return ID_FIELDSET;
    00851 }
    00852
    00853 void HTMLFieldSetElementImpl::attach()
    00854 {
    00855     assert(!attached());
    00856     assert(!m_render);
    00857     assert(parentNode());
    00858     addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
    00859     addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
    00860     addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
    00861     addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
    00862     addCSSProperty(CSS_PROP_BORDER_WIDTH, "1px");
    00863     addCSSProperty(CSS_PROP_PADDING_LEFT, "4px");
    00864     addCSSProperty(CSS_PROP_PADDING_RIGHT, "4px");
    00865     addCSSProperty(CSS_PROP_PADDING_BOTTOM, "4px");
    00866
    00867
    00868     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    00869     _style->ref();
    00870     if (parentNode()->renderer() && _style->display() != NONE) {
    00871         m_render = new RenderFieldset(this);
    00872         m_render->setStyle(_style);
    00873     }
    00874     HTMLGenericFormElementImpl::attach();
    00875     _style->deref();
    00876 }
    00877
    00878 NodeImpl *HTMLFieldSetElementImpl::addChild(NodeImpl *child)
    00879 {
    00880     if(!m_legend && child->id() == ID_LEGEND) {
    00881         int exceptioncode = 0;
    00882         NodeImpl* r = insertBefore( child, firstChild(), exceptioncode );
    00883         m_legend = child;
    00884         return r;
    00885     }
    00886     return HTMLGenericFormElementImpl::addChild(child);
    00887 }
    00888
    00889 void HTMLFieldSetElementImpl::parseAttribute(AttributeImpl *attr)
    00890 {
    00891     HTMLElementImpl::parseAttribute(attr);
    00892 }
    00893
    00894 // -------------------------------------------------------------------------
    00895
    00896 HTMLInputElementImpl::HTMLInputElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    00897     : HTMLGenericFormElementImpl(doc, f)
    00898 {
    00899     m_type = TEXT;
    00900     m_maxLen = -1;
    00901     m_size = 20;
    00902     m_clicked = false;
    00903     m_checked = false;
    00904
    00905     m_activeSubmit = false;
    00906     m_autocomplete = true;
    00907     m_inited = false;
    00908
    00909     xPos = 0;
    00910     yPos = 0;
    00911
    00912     if ( m_form )
    00913         m_autocomplete = f->autoComplete();
    00914 }
    00915
    00916 HTMLInputElementImpl::~HTMLInputElementImpl()
    00917 {
    00918     if (getDocument()) getDocument()->deregisterMaintainsState(this);
    00919 }
    00920
    00921 NodeImpl::Id HTMLInputElementImpl::id() const
    00922 {
    00923     return ID_INPUT;
    00924 }
    00925
    00926 void HTMLInputElementImpl::setType(const DOMString& /*t*/)
    00927 {
    00928     // ###
    00929 }
    00930
    00931 DOMString HTMLInputElementImpl::type() const
    00932 {
    00933     // needs to be lowercase according to DOM spec
    00934     switch (m_type) {
    00935     case TEXT: return "text";
    00936     case PASSWORD: return "password";
    00937     case CHECKBOX: return "checkbox";
    00938     case RADIO: return "radio";
    00939     case SUBMIT: return "submit";
    00940     case RESET: return "reset";
    00941     case FILE: return "file";
    00942     case HIDDEN: return "hidden";
    00943     case IMAGE: return "image";
    00944     case BUTTON: return "button";
    00945     default: return "";
    00946     }
    00947 }
    00948
    00949 QString HTMLInputElementImpl::state( )
    00950 {
    00951     switch (m_type) {
    00952     case PASSWORD:
    00953         return QString::fromLatin1("."); // empty string, avoid restoring
    00954     case CHECKBOX:
    00955     case RADIO:
    00956         return QString::fromLatin1(m_checked ? "on" : "off");
    00957     default:
    00958         return value().string()+'.'; // Make sure the string is not empty!
    00959     }
    00960 }
    00961
    00962 void HTMLInputElementImpl::restoreState(const QString &state)
    00963 {
    00964     switch (m_type) {
    00965     case CHECKBOX:
    00966     case RADIO:
    00967         setChecked((state == QString::fromLatin1("on")));
    00968         break;
    00969     case FILE:
    00970         m_value = DOMString(state.left(state.length()-1));
    00971         setChanged();
    00972         break;
    00973     default:
    00974         setValue(DOMString(state.left(state.length()-1)));
    00975         break;
    00976     }
    00977 }
    00978
    00979 void HTMLInputElementImpl::select(  )
    00980 {
    00981     if(!m_render) return;
    00982
    00983     if (m_type == TEXT || m_type == PASSWORD)
    00984         static_cast<RenderLineEdit*>(m_render)->select();
    00985     else if (m_type == FILE)
    00986         static_cast<RenderFileButton*>(m_render)->select();
    00987 }
    00988
    00989 void HTMLInputElementImpl::click(  )
    00990 {
    00991     // ###
    00992 #ifdef FORMS_DEBUG
    00993     kdDebug( 6030 ) << " HTMLInputElementImpl::click(  )" << endl;
    00994 #endif
    00995 }
    00996
    00997 void HTMLInputElementImpl::parseAttribute(AttributeImpl *attr)
    00998 {
    00999     switch(attr->id())
    01000     {
    01001     case ATTR_AUTOCOMPLETE:
    01002         m_autocomplete = strcasecmp( attr->value(), "off" );
    01003         break;
    01004     case ATTR_TYPE:
    01005         // ignore to avoid that javascript can change a type field to file
    01006         break;
    01007     case ATTR_VALUE:
    01008     case ATTR_CHECKED:
    01009         // these are the defaults, don't change them
    01010         break;
    01011     case ATTR_MAXLENGTH:
    01012     {
    01013         m_maxLen = -1;
    01014         if (!attr->val()) break;
    01015         bool ok;
    01016         int ml = attr->val()->toInt(&ok);
    01017         if (ml > 0 && ml < 1024)
    01018             m_maxLen = ml;
    01019         else if (ok && ml <= 0)
    01020             m_maxLen = 0;
    01021         setChanged();
    01022     }
    01023     break;
    01024     case ATTR_SIZE:
    01025         m_size = attr->val() ? attr->val()->toInt() : 20;
    01026         break;
    01027     case ATTR_ALT:
    01028     case ATTR_SRC:
    01029         if (m_render && m_type == IMAGE) m_render->updateFromElement();
    01030         break;
    01031     case ATTR_USEMAP:
    01032     case ATTR_ACCESSKEY:
    01033         // ### ignore for the moment
    01034         break;
    01035     case ATTR_ALIGN:
    01036         addHTMLAlignment( attr->value() );
    01037         break;
    01038     case ATTR_WIDTH:
    01039         // ignore this attribute,  do _not_ add
    01040         // a CSS_PROP_WIDTH here!
    01041         // webdesigner are stupid - and IE/NS behave the same ( Dirk )
    01042         break;
    01043     case ATTR_HEIGHT:
    01044         addCSSLength(CSS_PROP_HEIGHT, attr->value() );
    01045         break;
    01046     case ATTR_ONFOCUS:
    01047         setHTMLEventListener(EventImpl::FOCUS_EVENT,
    01048             getDocument()->createHTMLEventListener(attr->value().string()));
    01049         break;
    01050     case ATTR_ONBLUR:
    01051         setHTMLEventListener(EventImpl::BLUR_EVENT,
    01052             getDocument()->createHTMLEventListener(attr->value().string()));
    01053         break;
    01054     case ATTR_ONSELECT:
    01055         setHTMLEventListener(EventImpl::SELECT_EVENT,
    01056             getDocument()->createHTMLEventListener(attr->value().string()));
    01057         break;
    01058     case ATTR_ONCHANGE:
    01059         setHTMLEventListener(EventImpl::CHANGE_EVENT,
    01060             getDocument()->createHTMLEventListener(attr->value().string()));
    01061         break;
    01062     default:
    01063         HTMLGenericFormElementImpl::parseAttribute(attr);
    01064     }
    01065 }
    01066
    01067 void HTMLInputElementImpl::attach()
    01068 {
    01069     assert(!attached());
    01070     assert(!m_render);
    01071     assert(parentNode());
    01072
    01073     if (!m_inited) {
    01074         DOMString type = getAttribute(ATTR_TYPE);
    01075         if ( strcasecmp( type, "password" ) == 0 )
    01076             m_type = PASSWORD;
    01077         else if ( strcasecmp( type, "checkbox" ) == 0 )
    01078             m_type = CHECKBOX;
    01079         else if ( strcasecmp( type, "radio" ) == 0 )
    01080             m_type = RADIO;
    01081         else if ( strcasecmp( type, "submit" ) == 0 )
    01082             m_type = SUBMIT;
    01083         else if ( strcasecmp( type, "reset" ) == 0 )
    01084             m_type = RESET;
    01085         else if ( strcasecmp( type, "file" ) == 0 )
    01086             m_type = FILE;
    01087         else if ( strcasecmp( type, "hidden" ) == 0 )
    01088             m_type = HIDDEN;
    01089         else if ( strcasecmp( type, "image" ) == 0 )
    01090             m_type = IMAGE;
    01091         else if ( strcasecmp( type, "button" ) == 0 )
    01092             m_type = BUTTON;
    01093         else if ( strcasecmp( type, "khtml_isindex" ) == 0 )
    01094             m_type = ISINDEX;
    01095         else
    01096             m_type = TEXT;
    01097
    01098         if (m_type != FILE) m_value = getAttribute(ATTR_VALUE);
    01099         if ((uint) m_type <= ISINDEX && !m_value.isEmpty()) {
    01100             QString value = m_value.string();
    01101             // remove newline stuff..
    01102             QString nvalue;
    01103             for (unsigned int i = 0; i < value.length(); ++i)
    01104                 if (value[i] >= ' ')
    01105                     nvalue += value[i];
    01106             m_value = nvalue;
    01107         }
    01108         m_checked = (getAttribute(ATTR_CHECKED) != 0);
    01109         m_inited = true;
    01110     }
    01111
    01112     // make sure we don't inherit a color to the form elements
    01113     // by adding a non-CSS color property. this his higher
    01114     // priority than inherited color, but lesser priority than
    01115     // any color specified by CSS for the elements.
    01116     switch( m_type ) {
    01117     case TEXT:
    01118     case PASSWORD:
    01119         addCSSProperty(CSS_PROP_FONT_FAMILY,  "monospace");
    01120         /* nobreak */
    01121     case ISINDEX:
    01122     case FILE:
    01123         addCSSProperty(CSS_PROP_COLOR, "text");
    01124         break;
    01125     case SUBMIT:
    01126     case RESET:
    01127     case BUTTON:
    01128     case CHECKBOX:
    01129     case RADIO:
    01130         addCSSProperty(CSS_PROP_COLOR, "buttontext" );
    01131     case HIDDEN:
    01132     case IMAGE:
    01133         if (!getAttribute(ATTR_WIDTH).isNull())
    01134             addCSSLength(CSS_PROP_WIDTH, getAttribute(ATTR_WIDTH));
    01135         break;
    01136     };
    01137
    01138     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    01139     _style->ref();
    01140     if (parentNode()->renderer() && _style->display() != NONE) {
    01141         switch(m_type)
    01142         {
    01143         case TEXT:
    01144         case PASSWORD:
    01145         case ISINDEX:      m_render = new RenderLineEdit(this);   break;
    01146         case CHECKBOX:  m_render = new RenderCheckBox(this); break;
    01147         case RADIO:        m_render = new RenderRadioButton(this); break;
    01148         case SUBMIT:      m_render = new RenderSubmitButton(this); break;
    01149         case IMAGE:       m_render =  new RenderImageButton(this); break;
    01150         case RESET:      m_render = new RenderResetButton(this);   break;
    01151         case FILE:         m_render =  new RenderFileButton(this);    break;
    01152         case BUTTON:  m_render = new RenderPushButton(this);
    01153         case HIDDEN:   break;
    01154         }
    01155     }
    01156
    01157     if (m_render)
    01158         m_render->setStyle(_style);
    01159
    01160     HTMLGenericFormElementImpl::attach();
    01161     _style->deref();
    01162 }
    01163
    01164 DOMString HTMLInputElementImpl::altText() const
    01165 {
    01166     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
    01167     // also heavily discussed by Hixie on bugzilla
    01168     // note this is intentionally different to HTMLImageElementImpl::altText()
    01169     DOMString alt = getAttribute( ATTR_ALT );
    01170     // fall back to title attribute
    01171     if ( alt.isNull() )
    01172         alt = getAttribute( ATTR_TITLE );
    01173     if ( alt.isNull() )
    01174         alt = getAttribute( ATTR_VALUE );
    01175     if ( alt.isEmpty() )
    01176         alt = i18n( "Submit" );
    01177
    01178     return alt;
    01179 }
    01180
    01181 bool HTMLInputElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoding, bool multipart)
    01182 {
    01183     QString nme = name().string();
    01184
    01185     // image generates its own name's
    01186     if (nme.isEmpty() && m_type != IMAGE) return false;
    01187
    01188     // IMAGE needs special handling later
    01189     if(m_type != IMAGE) encoding += fixUpfromUnicode(codec, nme);
    01190
    01191     switch (m_type) {
    01192         case CHECKBOX:
    01193
    01194             if( checked() ) {
    01195                 encoding += fixUpfromUnicode(codec, value().string());
    01196                 return true;
    01197             }
    01198             break;
    01199
    01200         case RADIO:
    01201
    01202             if( checked() ) {
    01203                 encoding += fixUpfromUnicode(codec, value().string());
    01204                 return true;
    01205             }
    01206             break;
    01207
    01208         case BUTTON:
    01209         case RESET:
    01210             // those buttons are never successful
    01211             return false;
    01212
    01213         case IMAGE:
    01214
    01215             if(m_clicked)
    01216             {
    01217                 m_clicked = false;
    01218                 QString astr(nme.isEmpty() ? QString::fromLatin1("x") : nme + ".x");
    01219
    01220                 encoding += fixUpfromUnicode(codec, astr);
    01221                 astr.setNum(KMAX( clickX(), 0 ));
    01222                 encoding += fixUpfromUnicode(codec, astr);
    01223                 astr = nme.isEmpty() ? QString::fromLatin1("y") : nme + ".y";
    01224                 encoding += fixUpfromUnicode(codec, astr);
    01225                 astr.setNum(KMAX( clickY(), 0 ) );
    01226                 encoding += fixUpfromUnicode(codec, astr);
    01227
    01228                 return true;
    01229             }
    01230             break;
    01231
    01232         case SUBMIT:
    01233
    01234             if (m_activeSubmit)
    01235             {
    01236                 QString enc_str = m_value.isNull() ?
    01237                     static_cast<RenderSubmitButton*>(m_render)->defaultLabel() : value().string();
    01238
    01239                 if(!enc_str.isEmpty())
    01240                 {
    01241                     encoding += fixUpfromUnicode(codec, enc_str);
    01242                     return true;
    01243                 }
    01244             }
    01245             break;
    01246
    01247         case FILE:
    01248         {
    01249             // don't submit if display: none or display: hidden
    01250             if(!renderer() || renderer()->style()->visibility() != khtml::VISIBLE)
    01251                 return false;
    01252
    01253             QString local;
    01254             QCString dummy("");
    01255
    01256             KURL fileurl(value().string());
    01257             KIO::UDSEntry filestat;
    01258
    01259             // can't submit file in www-url-form encoded
    01260             if (multipart && KIO::NetAccess::stat(fileurl, filestat)) {
    01261                 KFileItem fileitem(filestat, fileurl, true, false);
    01262
    01263                 if ( fileitem.isFile() && KIO::NetAccess::download(KURL(value().string()), local) ) {
    01264                     QFile file(local);
    01265                     if (file.open(IO_ReadOnly)) {
    01266                         QCString filearray(file.size()+1);
    01267                         int readbytes = file.readBlock( filearray.data(), file.size());
    01268                         if ( readbytes >= 0 )
    01269                             filearray[readbytes] = '\0';
    01270                         file.close();
    01271
    01272                         encoding += filearray;
    01273                         KIO::NetAccess::removeTempFile( local );
    01274
    01275                         return true;
    01276                     }
    01277                 }
    01278             }
    01279             // else fall through
    01280         }
    01281         case HIDDEN:
    01282         case TEXT:
    01283         case PASSWORD:
    01284             // always successful
    01285             encoding += fixUpfromUnicode(codec, value().string());
    01286             return true;
    01287         case ISINDEX:
    01288             encoding += fixUpfromUnicode(codec, m_value.string());
    01289             return true;
    01290     }
    01291     return false;
    01292 }
    01293
    01294 void HTMLInputElementImpl::reset()
    01295 {
    01296     setValue(getAttribute(ATTR_VALUE));
    01297     setChecked(getAttribute(ATTR_CHECKED) != 0);
    01298 }
    01299
    01300 void HTMLInputElementImpl::setChecked(bool _checked)
    01301 {
    01302     if (m_form && m_type == RADIO && _checked && !name().isEmpty())
    01303         m_form->radioClicked(this);
    01304
    01305     if (m_checked == _checked) return;
    01306     m_checked = _checked;
    01307     setChanged();
    01308 }
    01309
    01310
    01311 DOMString HTMLInputElementImpl::value() const
    01312 {
    01313     if(m_value.isNull())
    01314         return (m_type == CHECKBOX || m_type ==RADIO) ?
    01315             DOMString("on") : DOMString("");
    01316
    01317     return m_value;
    01318 }
    01319
    01320
    01321 void HTMLInputElementImpl::setValue(DOMString val)
    01322 {
    01323     if (m_type == FILE) return;
    01324
    01325     m_value = (val.isNull() ? DOMString("") : val);
    01326     setChanged();
    01327 }
    01328
    01329 void HTMLInputElementImpl::blur()
    01330 {
    01331     if(getDocument()->focusNode() == this)
    01332         getDocument()->setFocusNode(0);
    01333 }
    01334
    01335 void HTMLInputElementImpl::focus()
    01336 {
    01337     getDocument()->setFocusNode(this);
    01338 }
    01339
    01340 void HTMLInputElementImpl::defaultEventHandler(EventImpl *evt)
    01341 {
    01342     if ( !m_disabled )
    01343     {
    01344         if (evt->isMouseEvent() &&
    01345             evt->id() == EventImpl::CLICK_EVENT && m_type == IMAGE && m_render) {
    01346             // record the mouse position for when we get the DOMActivate event
    01347             MouseEventImpl *me = static_cast<MouseEventImpl*>(evt);
    01348             int offsetX, offsetY;
    01349             m_render->absolutePosition(offsetX,offsetY);
    01350             xPos = me->clientX()-offsetX;
    01351             yPos = me->clientY()-offsetY;
    01352         }
    01353
    01354         // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
    01355         // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
    01356         // on the element, or presses enter while it is the active element. Javascript code wishing to activate the element
    01357         // must dispatch a DOMActivate event - a click event will not do the job.
    01358         if ((evt->id() == EventImpl::DOMACTIVATE_EVENT) &&
    01359             (m_type == IMAGE || m_type == SUBMIT || m_type == RESET))
    01360             activate();
    01361     }
    01362     HTMLGenericFormElementImpl::defaultEventHandler(evt);
    01363 }
    01364
    01365 void HTMLInputElementImpl::activate()
    01366 {
    01367     if (!m_form || !m_render)
    01368         return;
    01369
    01370     m_clicked = true;
    01371     if (m_type == RESET) {
    01372         m_form->reset();
    01373     }
    01374     else {
    01375         m_activeSubmit = true;
    01376         if (!m_form->prepareSubmit()) {
    01377             xPos = 0;
    01378             yPos = 0;
    01379         }
    01380         m_activeSubmit = false;
    01381     }
    01382 }
    01383
    01384 bool HTMLInputElementImpl::isEditable()
    01385 {
    01386     return ((m_type == TEXT) || (m_type == PASSWORD) || (m_type == ISINDEX) || (m_type == FILE));
    01387 }
    01388
    01389 // -------------------------------------------------------------------------
    01390
    01391 HTMLLabelElementImpl::HTMLLabelElementImpl(DocumentPtr *doc)
    01392     : HTMLGenericFormElementImpl(doc)
    01393 {
    01394 }
    01395
    01396 HTMLLabelElementImpl::~HTMLLabelElementImpl()
    01397 {
    01398 }
    01399
    01400 NodeImpl::Id HTMLLabelElementImpl::id() const
    01401 {
    01402     return ID_LABEL;
    01403 }
    01404
    01405 void HTMLLabelElementImpl::parseAttribute(AttributeImpl *attr)
    01406 {
    01407     switch(attr->id())
    01408     {
    01409     case ATTR_ONFOCUS:
    01410         setHTMLEventListener(EventImpl::FOCUS_EVENT,
    01411             getDocument()->createHTMLEventListener(attr->value().string()));
    01412         break;
    01413     case ATTR_ONBLUR:
    01414         setHTMLEventListener(EventImpl::BLUR_EVENT,
    01415             getDocument()->createHTMLEventListener(attr->value().string()));
    01416         break;
    01417     default:
    01418         HTMLElementImpl::parseAttribute(attr);
    01419     }
    01420 }
    01421
    01422 void HTMLLabelElementImpl::attach()
    01423 {
    01424     // skip the generic handler
    01425     HTMLElementImpl::attach();
    01426 }
    01427
    01428 #if 0
    01429 ElementImpl *HTMLLabelElementImpl::formElement()
    01430 {
    01431     DOMString formElementId = getAttribute(ATTR_FOR);
    01432     if (formElementId.isEmpty())
    01433         return 0;
    01434     return getDocument()->getElementById(formElementId);
    01435 }
    01436 #endif
    01437
    01438 // -------------------------------------------------------------------------
    01439
    01440 HTMLLegendElementImpl::HTMLLegendElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    01441     : HTMLGenericFormElementImpl(doc, f)
    01442 {
    01443 }
    01444
    01445 HTMLLegendElementImpl::~HTMLLegendElementImpl()
    01446 {
    01447 }
    01448
    01449 NodeImpl::Id HTMLLegendElementImpl::id() const
    01450 {
    01451     return ID_LEGEND;
    01452 }
    01453
    01454 void HTMLLegendElementImpl::attach()
    01455 {
    01456     assert(!attached());
    01457     assert(!m_render);
    01458     assert(parentNode());
    01459     addCSSProperty(CSS_PROP_PADDING_LEFT, "1px");
    01460     addCSSProperty(CSS_PROP_PADDING_RIGHT, "1px");
    01461     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    01462     _style->ref();
    01463     if (parentNode()->renderer() && _style->display() != NONE) {
    01464         m_render = new RenderLegend(this);
    01465         m_render->setStyle(_style);
    01466     }
    01467     HTMLGenericFormElementImpl::attach();
    01468     _style->deref();
    01469 }
    01470
    01471 void HTMLLegendElementImpl::parseAttribute(AttributeImpl *attr)
    01472 {
    01473     switch(attr->id())
    01474     {
    01475     case ATTR_ACCESSKEY:
    01476         // ### ignore for the moment
    01477         break;
    01478     default:
    01479         HTMLElementImpl::parseAttribute(attr);
    01480     }
    01481 }
    01482
    01483 // -------------------------------------------------------------------------
    01484
    01485 HTMLSelectElementImpl::HTMLSelectElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    01486     : HTMLGenericFormElementImpl(doc, f)
    01487 {
    01488     m_multiple = false;
    01489     m_recalcListItems = false;
    01490     // 0 means invalid (i.e. not set)
    01491     m_size = 0;
    01492     m_minwidth = 0;
    01493 }
    01494
    01495 HTMLSelectElementImpl::~HTMLSelectElementImpl()
    01496 {
    01497     if (getDocument()) getDocument()->deregisterMaintainsState(this);
    01498 }
    01499
    01500 NodeImpl::Id HTMLSelectElementImpl::id() const
    01501 {
    01502     return ID_SELECT;
    01503 }
    01504
    01505 DOMString HTMLSelectElementImpl::type() const
    01506 {
    01507     return (m_multiple ? "select-multiple" : "select-one");
    01508 }
    01509
    01510 long HTMLSelectElementImpl::selectedIndex() const
    01511 {
    01512     // return the number of the first option selected
    01513     uint o = 0;
    01514     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01515     for (unsigned int i = 0; i < items.size(); i++) {
    01516         if (items[i]->id() == ID_OPTION) {
    01517             if (static_cast<HTMLOptionElementImpl*>(items[i])->selected())
    01518                 return o;
    01519             o++;
    01520         }
    01521     }
    01522     Q_ASSERT(m_multiple || items.isEmpty());
    01523     return -1;
    01524 }
    01525
    01526 void HTMLSelectElementImpl::setSelectedIndex( long  index )
    01527 {
    01528     // deselect all other options and select only the new one
    01529     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01530     int listIndex;
    01531     for (listIndex = 0; listIndex < int(items.size()); listIndex++) {
    01532         if (items[listIndex]->id() == ID_OPTION)
    01533             static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(false);
    01534     }
    01535     listIndex = optionToListIndex(index);
    01536     if (listIndex >= 0)
    01537         static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(true);
    01538
    01539     setChanged(true);
    01540 }
    01541
    01542 long HTMLSelectElementImpl::length() const
    01543 {
    01544     int len = 0;
    01545     uint i;
    01546     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01547     for (i = 0; i < items.size(); i++) {
    01548         if (items[i]->id() == ID_OPTION)
    01549             len++;
    01550     }
    01551     return len;
    01552 }
    01553
    01554 void HTMLSelectElementImpl::add( const HTMLElement &element, const HTMLElement &before, int& exceptioncode )
    01555 {
    01556     if(element.isNull() || element.handle()->id() != ID_OPTION)
    01557         return;
    01558
    01559     insertBefore(element.handle(), before.handle(), exceptioncode );
    01560     if (!exceptioncode)
    01561         setRecalcListItems();
    01562 }
    01563
    01564 void HTMLSelectElementImpl::remove( long index )
    01565 {
    01566     int exceptioncode = 0;
    01567     int listIndex = optionToListIndex(index);
    01568
    01569     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01570     if(listIndex < 0 || index >= int(items.size()))
    01571         return; // ### what should we do ? remove the last item?
    01572
    01573     removeChild(items[listIndex], exceptioncode);
    01574     if( !exceptioncode )
    01575         setRecalcListItems();
    01576 }
    01577
    01578 void HTMLSelectElementImpl::blur()
    01579 {
    01580     if(getDocument()->focusNode() == this)
    01581         getDocument()->setFocusNode(0);
    01582 }
    01583
    01584 void HTMLSelectElementImpl::focus()
    01585 {
    01586     getDocument()->setFocusNode(this);
    01587 }
    01588
    01589 DOMString HTMLSelectElementImpl::value( )
    01590 {
    01591     uint i;
    01592     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01593     for (i = 0; i < items.size(); i++) {
    01594         if ( items[i]->id() == ID_OPTION
    01595             && static_cast<HTMLOptionElementImpl*>(items[i])->selected())
    01596             return static_cast<HTMLOptionElementImpl*>(items[i])->value();
    01597     }
    01598     return DOMString("");
    01599 }
    01600
    01601 void HTMLSelectElementImpl::setValue(DOMStringImpl* /*value*/)
    01602 {
    01603     // ### find the option with value() matching the given parameter
    01604     // and make it the current selection.
    01605     kdWarning() << "Unimplemented HTMLSelectElementImpl::setValue called" << endl;
    01606 }
    01607
    01608 QString HTMLSelectElementImpl::state( )
    01609 {
    01610     QString state;
    01611     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01612
    01613     int l = items.count();
    01614
    01615     state.fill('.', l);
    01616     for(int i = 0; i < l; i++)
    01617         if(items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->selected())
    01618             state[i] = 'X';
    01619
    01620     return state;
    01621 }
    01622
    01623 void HTMLSelectElementImpl::restoreState(const QString &_state)
    01624 {
    01625     recalcListItems();
    01626
    01627     QString state = _state;
    01628     if(!state.isEmpty() && !state.contains('X') && !m_multiple && m_size <= 1) {
    01629         qWarning("should not happen in restoreState!");
    01630         state[0] = 'X';
    01631     }
    01632
    01633     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01634
    01635     int l = items.count();
    01636     for(int i = 0; i < l; i++) {
    01637         if(items[i]->id() == ID_OPTION) {
    01638             HTMLOptionElementImpl* oe = static_cast<HTMLOptionElementImpl*>(items[i]);
    01639             oe->setSelected(state[i] == 'X');
    01640         }
    01641     }
    01642     setChanged(true);
    01643 }
    01644
    01645 NodeImpl *HTMLSelectElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
    01646 {
    01647     NodeImpl *result = HTMLGenericFormElementImpl::insertBefore(newChild,refChild, exceptioncode );
    01648     if (!exceptioncode)
    01649         setRecalcListItems();
    01650     return result;
    01651 }
    01652
    01653 NodeImpl *HTMLSelectElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
    01654 {
    01655     NodeImpl *result = HTMLGenericFormElementImpl::replaceChild(newChild,oldChild, exceptioncode);
    01656     if( !exceptioncode )
    01657         setRecalcListItems();
    01658     return result;
    01659 }
    01660
    01661 NodeImpl *HTMLSelectElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
    01662 {
    01663     NodeImpl *result = HTMLGenericFormElementImpl::removeChild(oldChild, exceptioncode);
    01664     if( !exceptioncode )
    01665         setRecalcListItems();
    01666     return result;
    01667 }
    01668
    01669 NodeImpl *HTMLSelectElementImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
    01670 {
    01671     NodeImpl *result = HTMLGenericFormElementImpl::appendChild(newChild, exceptioncode);
    01672     if( !exceptioncode )
    01673         setRecalcListItems();
    01674     setChanged(true);
    01675     return result;
    01676 }
    01677
    01678 NodeImpl* HTMLSelectElementImpl::addChild(NodeImpl* newChild)
    01679 {
    01680     setRecalcListItems();
    01681     return HTMLGenericFormElementImpl::addChild(newChild);
    01682 }
    01683
    01684 void HTMLSelectElementImpl::parseAttribute(AttributeImpl *attr)
    01685 {
    01686     switch(attr->id())
    01687     {
    01688     case ATTR_SIZE:
    01689         m_size = QMAX( attr->val()->toInt(), 1 );
    01690         break;
    01691     case ATTR_WIDTH:
    01692         m_minwidth = QMAX( attr->val()->toInt(), 0 );
    01693         break;
    01694     case ATTR_MULTIPLE:
    01695         m_multiple = (attr->val() != 0);
    01696         break;
    01697     case ATTR_ACCESSKEY:
    01698         // ### ignore for the moment
    01699         break;
    01700     case ATTR_ONFOCUS:
    01701         setHTMLEventListener(EventImpl::FOCUS_EVENT,
    01702             getDocument()->createHTMLEventListener(attr->value().string()));
    01703         break;
    01704     case ATTR_ONBLUR:
    01705         setHTMLEventListener(EventImpl::BLUR_EVENT,
    01706             getDocument()->createHTMLEventListener(attr->value().string()));
    01707         break;
    01708     case ATTR_ONCHANGE:
    01709         setHTMLEventListener(EventImpl::CHANGE_EVENT,
    01710             getDocument()->createHTMLEventListener(attr->value().string()));
    01711         break;
    01712     default:
    01713         HTMLGenericFormElementImpl::parseAttribute(attr);
    01714     }
    01715 }
    01716
    01717 void HTMLSelectElementImpl::attach()
    01718 {
    01719     assert(!attached());
    01720     assert(parentNode());
    01721     assert(!renderer());
    01722
    01723     addCSSProperty(CSS_PROP_COLOR, "text");
    01724
    01725     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    01726     _style->ref();
    01727     if (parentNode()->renderer() && _style->display() != NONE) {
    01728         m_render = new RenderSelect(this);
    01729         m_render->setStyle(_style);
    01730     }
    01731
    01732     HTMLGenericFormElementImpl::attach();
    01733     _style->deref();
    01734 }
    01735
    01736 bool HTMLSelectElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoded_values, bool)
    01737 {
    01738     bool successful = false;
    01739     QCString enc_name = fixUpfromUnicode(codec, name().string());
    01740     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01741
    01742     uint i;
    01743     for (i = 0; i < items.size(); i++) {
    01744         if (items[i]->id() == ID_OPTION) {
    01745             HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[i]);
    01746             if (option->selected()) {
    01747                 encoded_values += enc_name;
    01748                 encoded_values += fixUpfromUnicode(codec, option->value().string());
    01749                 successful = true;
    01750             }
    01751         }
    01752     }
    01753
    01754     // ### this case should not happen. make sure that we select the first option
    01755     // in any case. otherwise we have no consistency with the DOM interface. FIXME!
    01756     // we return the first one if it was a combobox select
    01757     if (!successful && !m_multiple && m_size <= 1 && items.size() &&
    01758         (items[0]->id() == ID_OPTION) ) {
    01759         HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[0]);
    01760         encoded_values += enc_name;
    01761         if (option->value().isNull())
    01762             encoded_values += fixUpfromUnicode(codec, option->text().string().stripWhiteSpace());
    01763         else
    01764             encoded_values += fixUpfromUnicode(codec, option->value().string());
    01765         successful = true;
    01766     }
    01767
    01768     return successful;
    01769 }
    01770
    01771 int HTMLSelectElementImpl::optionToListIndex(int optionIndex) const
    01772 {
    01773     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01774     if (optionIndex < 0 || optionIndex >= int(items.size()))
    01775         return -1;
    01776
    01777     int listIndex = 0;
    01778     int optionIndex2 = 0;
    01779     for (;
    01780          optionIndex2 < int(items.size()) && optionIndex2 <= optionIndex;
    01781          listIndex++) { // not a typo!
    01782         if (items[listIndex]->id() == ID_OPTION)
    01783             optionIndex2++;
    01784     }
    01785     listIndex--;
    01786     return listIndex;
    01787 }
    01788
    01789 int HTMLSelectElementImpl::listToOptionIndex(int listIndex) const
    01790 {
    01791     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01792     if (listIndex < 0 || listIndex >= int(items.size()) ||
    01793         items[listIndex]->id() != ID_OPTION)
    01794         return -1;
    01795
    01796     int optionIndex = 0; // actual index of option not counting OPTGROUP entries that may be in list
    01797     int i;
    01798     for (i = 0; i < listIndex; i++)
    01799         if (items[i]->id() == ID_OPTION)
    01800             optionIndex++;
    01801     return optionIndex;
    01802 }
    01803
    01804 void HTMLSelectElementImpl::recalcListItems()
    01805 {
    01806     NodeImpl* current = firstChild();
    01807     m_listItems.resize(0);
    01808     HTMLOptionElementImpl* foundSelected = 0;
    01809     while(current) {
    01810         if (current->id() == ID_OPTGROUP && current->firstChild()) {
    01811             // ### what if optgroup contains just comments? don't want one of no options in it...
    01812             m_listItems.resize(m_listItems.size()+1);
    01813             m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current);
    01814             current = current->firstChild();
    01815         }
    01816         if (current->id() == ID_OPTION) {
    01817             m_listItems.resize(m_listItems.size()+1);
    01818             m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current);
    01819             if (!foundSelected && !m_multiple && m_size <= 1) {
    01820                 foundSelected = static_cast<HTMLOptionElementImpl*>(current);
    01821                 foundSelected->m_selected = true;
    01822             }
    01823             else if (foundSelected && !m_multiple && static_cast<HTMLOptionElementImpl*>(current)->selected()) {
    01824                 foundSelected->m_selected = false;
    01825                 foundSelected = static_cast<HTMLOptionElementImpl*>(current);
    01826             }
    01827         }
    01828         NodeImpl *parent = current->parentNode();
    01829         current = current->nextSibling();
    01830         if (!current) {
    01831             if (parent != this)
    01832                 current = parent->nextSibling();
    01833         }
    01834     }
    01835     m_recalcListItems = false;
    01836 }
    01837
    01838 void HTMLSelectElementImpl::childrenChanged()
    01839 {
    01840     setRecalcListItems();
    01841
    01842     HTMLGenericFormElementImpl::childrenChanged();
    01843 }
    01844
    01845 void HTMLSelectElementImpl::setRecalcListItems()
    01846 {
    01847     m_recalcListItems = true;
    01848     if (m_render)
    01849         static_cast<khtml::RenderSelect*>(m_render)->setOptionsChanged(true);
    01850     setChanged();
    01851 }
    01852
    01853 void HTMLSelectElementImpl::reset()
    01854 {
    01855     QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01856     uint i;
    01857     for (i = 0; i < items.size(); i++) {
    01858         if (items[i]->id() == ID_OPTION) {
    01859             HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[i]);
    01860             bool selected = (!option->getAttribute(ATTR_SELECTED).isNull());
    01861             option->setSelected(selected);
    01862         }
    01863     }
    01864     if ( m_render )
    01865         static_cast<RenderSelect*>(m_render)->setSelectionChanged(true);
    01866     setChanged( true );
    01867 }
    01868
    01869 void HTMLSelectElementImpl::notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected)
    01870 {
    01871     if (selected && !m_multiple) {
    01872         // deselect all other options
    01873         QMemArray<HTMLGenericFormElementImpl*> items = listItems();
    01874         uint i;
    01875         for (i = 0; i < items.size(); i++) {
    01876             if (items[i]->id() == ID_OPTION)
    01877                 static_cast<HTMLOptionElementImpl*>(items[i])->m_selected = (items[i] == selectedOption);
    01878         }
    01879     }
    01880     if (m_render)
    01881         static_cast<RenderSelect*>(m_render)->setSelectionChanged(true);
    01882
    01883     setChanged(true);
    01884 }
    01885
    01886 // -------------------------------------------------------------------------
    01887
    01888 HTMLKeygenElementImpl::HTMLKeygenElementImpl(DocumentPtr* doc, HTMLFormElementImpl* f)
    01889     : HTMLSelectElementImpl(doc, f)
    01890 {
    01891     QStringList keys = KSSLKeyGen::supportedKeySizes();
    01892     for (QStringList::Iterator i = keys.begin(); i != keys.end(); ++i) {
    01893         HTMLOptionElementImpl* o = new HTMLOptionElementImpl(doc, form());
    01894         addChild(o);
    01895         o->addChild(doc->document()->createTextNode(DOMString(*i).implementation()));
    01896     }
    01897 }
    01898
    01899 NodeImpl::Id HTMLKeygenElementImpl::id() const
    01900 {
    01901     return ID_KEYGEN;
    01902 }
    01903
    01904 void HTMLKeygenElementImpl::parseAttribute(AttributeImpl* attr)
    01905 {
    01906     switch(attr->id())
    01907     {
    01908     case ATTR_CHALLENGE:
    01909         break;
    01910     default:
    01911         // skip HTMLSelectElementImpl parsing!
    01912         HTMLGenericFormElementImpl::parseAttribute(attr);
    01913     }
    01914 }
    01915
    01916 bool HTMLKeygenElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoded_values, bool)
    01917 {
    01918     bool successful = false;
    01919     QCString enc_name = fixUpfromUnicode(codec, name().string());
    01920
    01921     encoded_values += enc_name;
    01922
    01923     // pop up the fancy certificate creation dialog here
    01924     KSSLKeyGen *kg = new KSSLKeyGen(static_cast<RenderWidget *>(m_render)->widget(), "Key Generator", true);
    01925
    01926     kg->setKeySize(0);
    01927     successful = (QDialog::Accepted == kg->exec());
    01928
    01929     delete kg;
    01930
    01931     encoded_values += "deadbeef";
    01932
    01933     return successful;
    01934 }
    01935
    01936 // -------------------------------------------------------------------------
    01937
    01938 NodeImpl::Id HTMLOptGroupElementImpl::id() const
    01939 {
    01940     return ID_OPTGROUP;
    01941 }
    01942
    01943 // -------------------------------------------------------------------------
    01944
    01945 HTMLOptionElementImpl::HTMLOptionElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    01946     : HTMLGenericFormElementImpl(doc, f)
    01947 {
    01948     m_selected = false;
    01949 }
    01950
    01951 NodeImpl::Id HTMLOptionElementImpl::id() const
    01952 {
    01953     return ID_OPTION;
    01954 }
    01955
    01956 DOMString HTMLOptionElementImpl::text() const
    01957 {
    01958     if (firstChild() && firstChild()->nodeType() == Node::TEXT_NODE) {
    01959         if (firstChild()->nextSibling()) {
    01960             DOMString ret = "";
    01961             NodeImpl *n = firstChild();
    01962             for (; n; n = n->nextSibling()) {
    01963                 if (n->nodeType() == Node::TEXT_NODE ||
    01964                     n->nodeType() == Node::CDATA_SECTION_NODE)
    01965                     ret += n->nodeValue();
    01966             }
    01967             return ret;
    01968         }
    01969         else
    01970             return firstChild()->nodeValue();
    01971     }
    01972     return "";
    01973 }
    01974
    01975 long HTMLOptionElementImpl::index() const
    01976 {
    01977     // Let's do this dynamically. Might be a bit slow, but we're sure
    01978     // we won't forget to update a member variable in some cases...
    01979     QMemArray<HTMLGenericFormElementImpl*> items = getSelect()->listItems();
    01980     int l = items.count();
    01981     int optionIndex = 0;
    01982     for(int i = 0; i < l; i++) {
    01983         if(items[i]->id() == ID_OPTION)
    01984         {
    01985             if (static_cast<HTMLOptionElementImpl*>(items[i]) == this)
    01986                 return optionIndex;
    01987             optionIndex++;
    01988         }
    01989     }
    01990     kdWarning() << "HTMLOptionElementImpl::index(): option not found!" << endl;
    01991     return 0;
    01992 }
    01993
    01994 void HTMLOptionElementImpl::setIndex( long  )
    01995 {
    01996     kdWarning() << "Unimplemented HTMLOptionElementImpl::setIndex(long) called" << endl;
    01997     // ###
    01998 }
    01999
    02000 void HTMLOptionElementImpl::parseAttribute(AttributeImpl *attr)
    02001 {
    02002     switch(attr->id())
    02003     {
    02004     case ATTR_SELECTED:
    02005         m_selected = (attr->val() != 0);
    02006         break;
    02007     case ATTR_VALUE:
    02008         m_value = attr->value();
    02009         break;
    02010     default:
    02011         HTMLGenericFormElementImpl::parseAttribute(attr);
    02012     }
    02013 }
    02014
    02015 DOMString HTMLOptionElementImpl::value() const
    02016 {
    02017     if ( !m_value.isNull() )
    02018         return m_value;
    02019     // Use the text if the value wasn't set.
    02020     return text().string().simplifyWhiteSpace();
    02021 }
    02022
    02023 void HTMLOptionElementImpl::setValue(DOMStringImpl* value)
    02024 {
    02025     setAttribute(ATTR_VALUE, value);
    02026 }
    02027
    02028 void HTMLOptionElementImpl::setSelected(bool _selected)
    02029 {
    02030     if(m_selected == _selected)
    02031         return;
    02032     m_selected = _selected;
    02033     HTMLSelectElementImpl *select = getSelect();
    02034     if (select)
    02035         select->notifyOptionSelected(this,_selected);
    02036 }
    02037
    02038 HTMLSelectElementImpl *HTMLOptionElementImpl::getSelect() const
    02039 {
    02040     NodeImpl *select = parentNode();
    02041     while (select && select->id() != ID_SELECT)
    02042         select = select->parentNode();
    02043     return static_cast<HTMLSelectElementImpl*>(select);
    02044 }
    02045
    02046 // -------------------------------------------------------------------------
    02047
    02048 HTMLTextAreaElementImpl::HTMLTextAreaElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    02049     : HTMLGenericFormElementImpl(doc, f)
    02050 {
    02051     // DTD requires rows & cols be specified, but we will provide reasonable defaults
    02052     m_rows = 2;
    02053     m_cols = 20;
    02054     m_wrap = ta_Virtual;
    02055     m_dirtyvalue = true;
    02056 }
    02057
    02058 HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl()
    02059 {
    02060     if (getDocument()) getDocument()->deregisterMaintainsState(this);
    02061 }
    02062
    02063 NodeImpl::Id HTMLTextAreaElementImpl::id() const
    02064 {
    02065     return ID_TEXTAREA;
    02066 }
    02067
    02068 DOMString HTMLTextAreaElementImpl::type() const
    02069 {
    02070     return "textarea";
    02071 }
    02072
    02073 QString HTMLTextAreaElementImpl::state( )
    02074 {
    02075     // Make sure the string is not empty!
    02076     return value().string()+'.';
    02077 }
    02078
    02079 void HTMLTextAreaElementImpl::restoreState(const QString &state)
    02080 {
    02081     setDefaultValue(state.left(state.length()-1));
    02082     // the close() in the rendertree will take care of transferring defaultvalue to 'value'
    02083 }
    02084
    02085 void HTMLTextAreaElementImpl::select(  )
    02086 {
    02087     if (m_render)
    02088         static_cast<RenderTextArea*>(m_render)->select();
    02089     onSelect();
    02090 }
    02091
    02092 void HTMLTextAreaElementImpl::parseAttribute(AttributeImpl *attr)
    02093 {
    02094     switch(attr->id())
    02095     {
    02096     case ATTR_ROWS:
    02097         m_rows = attr->val() ? attr->val()->toInt() : 3;
    02098         break;
    02099     case ATTR_COLS:
    02100         m_cols = attr->val() ? attr->val()->toInt() : 60;
    02101         break;
    02102     case ATTR_WRAP:
    02103         // virtual / physical is Netscape extension of HTML 3.0, now deprecated
    02104         // soft/ hard / off is recommendation for HTML 4 extension by IE and NS 4
    02105         if ( strcasecmp( attr->value(), "virtual" ) == 0  || strcasecmp( attr->value(), "soft") == 0)
    02106             m_wrap = ta_Virtual;
    02107         else if ( strcasecmp ( attr->value(), "physical" ) == 0 || strcasecmp( attr->value(), "hard") == 0)
    02108             m_wrap = ta_Physical;
    02109         else if(strcasecmp( attr->value(), "on" ) == 0)
    02110             m_wrap = ta_Physical;
    02111         else if(strcasecmp( attr->value(), "off") == 0)
    02112             m_wrap = ta_NoWrap;
    02113         break;
    02114     case ATTR_ACCESSKEY:
    02115         // ignore for the moment
    02116         break;
    02117     case ATTR_ONFOCUS:
    02118         setHTMLEventListener(EventImpl::FOCUS_EVENT,
    02119             getDocument()->createHTMLEventListener(attr->value().string()));
    02120         break;
    02121     case ATTR_ONBLUR:
    02122         setHTMLEventListener(EventImpl::BLUR_EVENT,
    02123             getDocument()->createHTMLEventListener(attr->value().string()));
    02124         break;
    02125     case ATTR_ONSELECT:
    02126         setHTMLEventListener(EventImpl::SELECT_EVENT,
    02127             getDocument()->createHTMLEventListener(attr->value().string()));
    02128         break;
    02129     case ATTR_ONCHANGE:
    02130         setHTMLEventListener(EventImpl::CHANGE_EVENT,
    02131             getDocument()->createHTMLEventListener(attr->value().string()));
    02132         break;
    02133     default:
    02134         HTMLGenericFormElementImpl::parseAttribute(attr);
    02135     }
    02136 }
    02137
    02138 void HTMLTextAreaElementImpl::attach()
    02139 {
    02140     assert(!attached());
    02141     assert(!m_render);
    02142     assert(parentNode());
    02143
    02144     addCSSProperty(CSS_PROP_COLOR, "text");
    02145     addCSSProperty( CSS_PROP_FONT_FAMILY, "monospace" );
    02146
    02147     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    02148     _style->ref();
    02149     if (parentNode()->renderer() && _style->display() != NONE) {
    02150         m_render = new RenderTextArea(this);
    02151         m_render->setStyle(_style);
    02152     }
    02153
    02154     HTMLGenericFormElementImpl::attach();
    02155     _style->deref();
    02156 }
    02157
    02158 bool HTMLTextAreaElementImpl::encoding(const QTextCodec* codec, encodingList& encoding, bool)
    02159 {
    02160     if (name().isEmpty() || !m_render) return false;
    02161
    02162     encoding += fixUpfromUnicode(codec, name().string());
    02163     encoding += fixUpfromUnicode(codec, value().string());
    02164
    02165     return true;
    02166 }
    02167
    02168 void HTMLTextAreaElementImpl::reset()
    02169 {
    02170     setValue(defaultValue());
    02171 }
    02172
    02173 DOMString HTMLTextAreaElementImpl::value()
    02174 {
    02175     if ( m_dirtyvalue) {
    02176         if ( m_render )  m_value = static_cast<RenderTextArea*>( m_render )->text();
    02177         m_dirtyvalue = false;
    02178     }
    02179
    02180     if ( m_value.isNull() ) return "";
    02181
    02182     return m_value;
    02183 }
    02184
    02185 void HTMLTextAreaElementImpl::setValue(DOMString _value)
    02186 {
    02187     // \r\n -> \n, \r -> \n
    02188     QString str = _value.string().replace( "\r\n", "\n" );
    02189     m_value = str.replace( "\r", "\n" );
    02190     m_dirtyvalue = false;
    02191     setChanged(true);
    02192 }
    02193
    02194
    02195 DOMString HTMLTextAreaElementImpl::defaultValue()
    02196 {
    02197     DOMString val = "";
    02198     // there may be comments - just grab the text nodes
    02199     NodeImpl *n;
    02200     for (n = firstChild(); n; n = n->nextSibling())
    02201         if (n->isTextNode())
    02202             val += static_cast<TextImpl*>(n)->data();
    02203     if (val[0] == '\r' && val[1] == '\n') {
    02204         val = val.copy();
    02205         val.remove(0,2);
    02206     }
    02207     else if (val[0] == '\r' || val[0] == '\n') {
    02208         val = val.copy();
    02209         val.remove(0,1);
    02210     }
    02211
    02212     return val;
    02213 }
    02214
    02215 void HTMLTextAreaElementImpl::setDefaultValue(DOMString _defaultValue)
    02216 {
    02217     // there may be comments - remove all the text nodes and replace them with one
    02218     QPtrList<NodeImpl> toRemove;
    02219     NodeImpl *n;
    02220     for (n = firstChild(); n; n = n->nextSibling())
    02221         if (n->isTextNode())
    02222             toRemove.append(n);
    02223     QPtrListIterator<NodeImpl> it(toRemove);
    02224     int exceptioncode = 0;
    02225     for (; it.current(); ++it) {
    02226         removeChild(it.current(), exceptioncode);
    02227     }
    02228     insertBefore(getDocument()->createTextNode(_defaultValue.implementation()),firstChild(), exceptioncode);
    02229     setValue(_defaultValue);
    02230 }
    02231
    02232 void HTMLTextAreaElementImpl::blur()
    02233 {
    02234     if(getDocument()->focusNode() == this)
    02235         getDocument()->setFocusNode(0);
    02236 }
    02237
    02238 void HTMLTextAreaElementImpl::focus()
    02239 {
    02240     getDocument()->setFocusNode(this);
    02241 }
    02242
    02243 bool HTMLTextAreaElementImpl::isEditable()
    02244 {
    02245     return true;
    02246 }
    02247
    02248 // -------------------------------------------------------------------------
    02249
    02250 HTMLIsIndexElementImpl::HTMLIsIndexElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    02251     : HTMLInputElementImpl(doc, f)
    02252 {
    02253     m_type = TEXT;
    02254     setName("isindex");
    02255 }
    02256
    02257 HTMLIsIndexElementImpl::~HTMLIsIndexElementImpl()
    02258 {
    02259 }
    02260
    02261 NodeImpl::Id HTMLIsIndexElementImpl::id() const
    02262 {
    02263     return ID_ISINDEX;
    02264 }
    02265
    02266 void HTMLIsIndexElementImpl::parseAttribute(AttributeImpl* attr)
    02267 {
    02268     // don't call HTMLInputElement::parseAttribute here, as it would
    02269     // accept attributes this element does not support
    02270     HTMLGenericFormElementImpl::parseAttribute(attr);
    02271 }
    02272
    02273 DOMString HTMLIsIndexElementImpl::prompt() const
    02274 {
    02275     // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created.
    02276     // So we have to look at the previous sibling to find the prompt text
    02277     DOM::NodeImpl* prev = previousSibling();
    02278     if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE)
    02279         return prev->nodeValue();
    02280     return "";
    02281 }
    02282
    02283 void HTMLIsIndexElementImpl::setPrompt(const DOMString& str)
    02284 {
    02285     // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created.
    02286     // So we have to look at the previous sibling to find the prompt text
    02287     int exceptioncode = 0;
    02288     DOM::NodeImpl* prev = previousSibling();
    02289     if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE)
    02290         static_cast<DOM::TextImpl *>(prev)->setData(str, exceptioncode);
    02291 }
    02292
    02293 // -------------------------------------------------------------------------
    02294

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:53 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001