diff options
Diffstat (limited to 'khtml/html/html_formimpl.cpp')
-rw-r--r-- | khtml/html/html_formimpl.cpp | 2980 |
1 files changed, 0 insertions, 2980 deletions
diff --git a/khtml/html/html_formimpl.cpp b/khtml/html/html_formimpl.cpp deleted file mode 100644 index c7c232dc9..000000000 --- a/khtml/html/html_formimpl.cpp +++ /dev/null @@ -1,2980 +0,0 @@ -/* - * This file is part of the DOM implementation for KDE. - * - * Copyright (C) 1999 Lars Knoll ([email protected]) - * (C) 1999 Antti Koivisto ([email protected]) - * (C) 2001 Dirk Mueller ([email protected]) - * (C) 2004, 2005, 2006 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#undef FORMS_DEBUG -//#define FORMS_DEBUG - -#include "html/html_formimpl.h" - -#include "khtmlview.h" -#include "khtml_part.h" -#include "html/html_documentimpl.h" -#include "khtml_settings.h" -#include "misc/htmlhashes.h" - -#include "css/cssstyleselector.h" -#include "css/cssproperties.h" -#include "css/cssvalues.h" -#include "css/csshelper.h" -#include "xml/dom_textimpl.h" -#include "xml/dom_docimpl.h" -#include "xml/dom2_eventsimpl.h" -#include "xml/dom_restyler.h" -#include "khtml_ext.h" - -#include "rendering/render_form.h" - -#include <kcharsets.h> -#include <kglobal.h> -#include <kdebug.h> -#include <kmimetype.h> -#include <kmessagebox.h> -#include <kapplication.h> -#include <klocale.h> -#ifndef KHTML_NO_WALLET -#include <kwallet.h> -#endif -#include <netaccess.h> -#include <kfileitem.h> -#include <tqfile.h> -#include <tqdir.h> -#include <tqtextcodec.h> - -// for keygen -#include <tqstring.h> -#include <ksslkeygen.h> - -#include <assert.h> - - -using namespace DOM; -using namespace khtml; - -HTMLFormElementImpl::HTMLFormElementImpl(DocumentImpl *doc, bool implicit) - : HTMLElementImpl(doc) -{ - m_implicit = implicit; - m_post = false; - m_multipart = false; - m_autocomplete = true; - m_insubmit = false; - m_doingsubmit = false; - m_inreset = false; - m_enctype = "application/x-www-form-urlencoded"; - m_boundary = "----------" + TDEApplication::randomString( 42 + 13 ); - m_acceptcharset = "UNKNOWN"; - m_malformed = false; -} - -HTMLFormElementImpl::~HTMLFormElementImpl() -{ - if (getDocument() && getDocument()->view() && getDocument()->view()->part()) { - getDocument()->view()->part()->dequeueWallet(this); - } - TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); - for (; it.current(); ++it) - it.current()->m_form = 0; - TQPtrListIterator<HTMLImageElementImpl> it2(imgElements); - for (; it2.current(); ++it2) - it2.current()->m_form = 0; -} - -NodeImpl::Id HTMLFormElementImpl::id() const -{ - return ID_FORM; -} - -long HTMLFormElementImpl::length() const -{ - int len = 0; - TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); - for (; it.current(); ++it) - if (it.current()->isEnumeratable()) - ++len; - - return len; -} - -static TQCString encodeCString(const TQCString& e) -{ - // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 - // safe characters like NS handles them for compatibility - static const char *safe = "-._*"; - TQCString encoded(( e.length()+e.contains( '\n' ) )*3 - +e.contains('\r') * 3 + 1); - int enclen = 0; - bool crmissing = false; - unsigned char oldc; - unsigned char c ='\0'; - - //TQCString orig(e.data(), e.size()); - - unsigned len = e.length(); - for(unsigned pos = 0; pos < len; pos++) { - oldc = c; - c = e[pos]; - - if (crmissing && c != '\n') { - encoded[enclen++] = '%'; - encoded[enclen++] = '0'; - encoded[enclen++] = 'D'; - crmissing = false; - } - - if ( (( c >= 'A') && ( c <= 'Z')) || - (( c >= 'a') && ( c <= 'z')) || - (( c >= '0') && ( c <= '9')) || - (strchr(safe, c)) - ) - encoded[enclen++] = c; - else if ( c == ' ' ) - encoded[enclen++] = '+'; - else if ( c == '\n' ) - { - encoded[enclen++] = '%'; - encoded[enclen++] = '0'; - encoded[enclen++] = 'D'; - encoded[enclen++] = '%'; - encoded[enclen++] = '0'; - encoded[enclen++] = 'A'; - crmissing = false; - } - else if (c == '\r' && oldc != '\n') { - crmissing = true; - } - else if ( c != '\r' ) - { - encoded[enclen++] = '%'; - unsigned int h = c / 16; - h += (h > 9) ? ('A' - 10) : '0'; - encoded[enclen++] = h; - - unsigned int l = c % 16; - l += (l > 9) ? ('A' - 10) : '0'; - encoded[enclen++] = l; - } - } - encoded[enclen++] = '\0'; - encoded.truncate(enclen); - - return encoded; -} - -// ### This function only encodes to numeric ampersand escapes, -// ### we could use standard ampersand values as well. -inline static TQString escapeUnencodeable(const TQTextCodec* codec, const TQString& s) { - TQString enc_string; - const int len = s.length(); - for(int i=0; i <len; ++i) { - const TQChar c = s[i]; - if (codec->canEncode(c)) - enc_string.append(c); - else { - TQString ampersandEscape; - ampersandEscape.sprintf("&#%u;", c.unicode()); - enc_string.append(ampersandEscape); - } - } - return enc_string; -} - -inline static TQCString fixUpfromUnicode(const TQTextCodec* codec, const TQString& s) -{ - TQCString str = codec->fromUnicode(escapeUnencodeable(codec,s)); - str.truncate(str.length()); - return str; -} - -TQByteArray HTMLFormElementImpl::formData(bool& ok) -{ -#ifdef FORMS_DEBUG - kdDebug( 6030 ) << "form: formData()" << endl; -#endif - - TQByteArray form_data(0); - TQCString enc_string = ""; // used for non-multipart data - - // find out the QTextcodec to use - const TQString str = m_acceptcharset.string(); - const TQChar space(' '); - const unsigned int strLength = str.length(); - for(unsigned int i=0; i < strLength; ++i) if(str[i].latin1() == ',') str[i] = space; - const TQStringList charsets = TQStringList::split(' ', str); - TQTextCodec* codec = 0; - KHTMLView *view = getDocument()->view(); - { - TQStringList::ConstIterator it = charsets.begin(); - const TQStringList::ConstIterator itEnd = charsets.end(); - - for ( ; it != itEnd; ++it ) - { - TQString enc = (*it); - if(enc.contains("UNKNOWN")) - { - // use standard document encoding - enc = "ISO 8859-1"; - if(view && view->part()) - enc = view->part()->encoding(); - } - if((codec = TDEGlobal::charsets()->codecForName(enc.latin1()))) - break; - } - } - if(!codec) - codec = TQTextCodec::codecForLocale(); - - // we need to map visual hebrew to logical hebrew, as the web - // server alsways expects responses in logical ordering - if ( codec->mibEnum() == 11 ) - codec = TQTextCodec::codecForMib( 85 ); - - m_encCharset = codec->name(); - const unsigned int m_encCharsetLength = m_encCharset.length(); - for(unsigned int i=0; i < m_encCharsetLength; ++i) - m_encCharset[i] = m_encCharset[i].latin1() == ' ' ? TQChar('-') : m_encCharset[i].lower(); - - TQStringList fileUploads, fileNotUploads; - - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { - HTMLGenericFormElementImpl* const current = it.current(); - khtml::encodingList lst; - - if (!current->disabled() && current->encoding(codec, lst, m_multipart)) - { - //kdDebug(6030) << "adding name '" << current->name().string() << "'" << endl; - khtml::encodingList::ConstIterator it = lst.begin(); - const khtml::encodingList::ConstIterator itEnd = lst.end(); - for( it = lst.begin(); it != itEnd; ++it ) - { - if (!m_multipart) - { - // handle ISINDEX / <input name=isindex> special - // but only if its the first entry - if ( enc_string.isEmpty() && *it == "isindex" ) { - ++it; - enc_string += encodeCString( *it ); - } - else { - if(!enc_string.isEmpty()) - enc_string += '&'; - - enc_string += encodeCString(*it); - enc_string += "="; - ++it; - enc_string += encodeCString(*it); - } - } - else - { - TQCString hstr("--"); - hstr += m_boundary.latin1(); - hstr += "\r\n"; - hstr += "Content-Disposition: form-data; name=\""; - hstr += (*it).data(); - hstr += "\""; - - // if the current type is FILE, then we also need to - // include the filename - if (current->id() == ID_INPUT && - static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE && - current->renderer()) - { - KURL path; - TQString val = static_cast<HTMLInputElementImpl*>(current)->value().string().stripWhiteSpace(); - if (!val.isEmpty() && - TQDir::isRelativePath(val) && - TQFile::exists(TDEGlobalSettings::documentPath() + val)) { - path.setPath(TDEGlobalSettings::documentPath() + val); - } else { - path = KURL::fromPathOrURL(val); - } - - hstr += fixUpfromUnicode(codec, "; filename=\"" + path.fileName() + "\""); - if (path.isValid()) { - fileUploads << path.prettyURL(0, KURL::StripFileProtocol); - const KMimeType::Ptr ptr = KMimeType::findByURL(path); - if (!ptr->name().isEmpty()) { - hstr += "\r\nContent-Type: "; - hstr += ptr->name().ascii(); - } - } else if (!val.isEmpty()) { - fileNotUploads << path.prettyURL(0, KURL::StripFileProtocol); - } - } - - hstr += "\r\n\r\n"; - ++it; - - // append body - const unsigned int old_size = form_data.size(); - form_data.resize( old_size + hstr.length() + (*it).size() + 1); - memcpy(form_data.data() + old_size, hstr.data(), hstr.length()); - memcpy(form_data.data() + old_size + hstr.length(), *it, (*it).size()); - form_data[form_data.size()-2] = '\r'; - form_data[form_data.size()-1] = '\n'; - - // reset unsubmittedFormChange flag - if (current->id() == ID_INPUT && - static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT) - static_cast<HTMLInputElementImpl*>(current)->setUnsubmittedFormChange(false); - - if (current->id() == ID_TEXTAREA) - static_cast<HTMLTextAreaElementImpl*>(current)->setUnsubmittedFormChange(false); - - } - } - } - } - - if (fileNotUploads.count()) { - const int result = KMessageBox::warningContinueCancelList( 0, - i18n("The following files will not be uploaded" - " because they could not be found.\n" - "Do you want to continue?"), - fileNotUploads, - i18n("Submit Confirmation"),KGuiItem(i18n("&Submit Anyway"))); - - - if (result == KMessageBox::Cancel) { - ok = false; - return TQByteArray(); - } - } - - if (fileUploads.count()) { - const int result = KMessageBox::warningContinueCancelList( 0, - i18n("You're about to transfer the following files from " - "your local computer to the Internet.\n" - "Do you really want to continue?"), - fileUploads, - i18n("Send Confirmation"),KGuiItem(i18n("&Send Files"))); - - - if (result == KMessageBox::Cancel) { - ok = false; - return TQByteArray(); - } - } - - if (m_multipart) - enc_string = ("--" + m_boundary + "--\r\n").ascii(); - - const int old_size = form_data.size(); - form_data.resize( form_data.size() + enc_string.length() ); - memcpy(form_data.data() + old_size, enc_string.data(), enc_string.length() ); - - ok = true; - return form_data; -} - -void HTMLFormElementImpl::setEnctype( const DOMString& type ) -{ - if(type.string().find("multipart", 0, false) != -1 || type.string().find("form-data", 0, false) != -1) - { - m_enctype = "multipart/form-data"; - m_multipart = true; - m_post = true; - } else if (type.string().find("text", 0, false) != -1 || type.string().find("plain", 0, false) != -1) - { - m_enctype = "text/plain"; - m_multipart = false; - } - else - { - m_enctype = "application/x-www-form-urlencoded"; - m_multipart = false; - } - m_encCharset = TQString::null; -} - -static TQString calculateAutoFillKey(const HTMLFormElementImpl& e) -{ - KURL k(e.getDocument()->URL()); - k.setRef(TQString::null); - k.setQuery(TQString::null); - // ensure that we have the user / password inside the url - // otherwise we might have a potential security problem - // by saving passwords under wrong lookup key. - const TQString name = e.getAttribute(ATTR_NAME).string().stripWhiteSpace(); - const TQRegExp re("[;,!]"); - const TQStringList url = TQStringList::split(re, k.url()); - return url[0] + '#' + name; -} - -void HTMLFormElementImpl::doAutoFill() -{ -#ifndef KHTML_NO_WALLET - const TQString key = calculateAutoFillKey(*this); - - if (KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), - KWallet::Wallet::FormDataFolder(), - key)) - return; - - // assert(view()) - getDocument()->view()->part()->openWallet(this); -#endif // KHTML_NO_WALLET -} - - -void HTMLFormElementImpl::walletOpened(KWallet::Wallet *w) { -#ifndef KHTML_NO_WALLET - assert(w); - const TQString key = calculateAutoFillKey(*this); - if (!w->hasFolder(KWallet::Wallet::FormDataFolder())) { - return; // failed - } - w->setFolder(KWallet::Wallet::FormDataFolder()); - TQMap<TQString, TQString> map; - if (w->readMap(key, map)) - return; // failed, abort - - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { - if (it.current()->id() == ID_INPUT) { - HTMLInputElementImpl* const current = static_cast<HTMLInputElementImpl*>(it.current()); - if ((current->inputType() == HTMLInputElementImpl::PASSWORD || - current->inputType() == HTMLInputElementImpl::TEXT) && - !current->readOnly() && - map.contains(current->name().string())) { - getDocument()->setFocusNode(current); - current->setValue(map[current->name().string()]); - } - } - } -#endif // KHTML_NO_WALLET -} - -void HTMLFormElementImpl::submitFromKeyboard() -{ - // Activate the first nondisabled submit button - // if there is none, do a submit anyway if not more - // than one <input type=text> or <input type=password> - unsigned int inputtext = 0; - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { - if (it.current()->id() == ID_BUTTON) { - HTMLButtonElementImpl* const current = static_cast<HTMLButtonElementImpl *>(it.current()); - if (current->buttonType() == HTMLButtonElementImpl::SUBMIT && !current->disabled()) { - current->click(); - return; - } - } else if (it.current()->id() == ID_INPUT) { - HTMLInputElementImpl* const current = static_cast<HTMLInputElementImpl *>(it.current()); - switch(current->inputType()) { - case HTMLInputElementImpl::SUBMIT: - case HTMLInputElementImpl::IMAGE: - if(!current->disabled()) { - current->click(); - return; - } - break; - case HTMLInputElementImpl::TEXT: - case HTMLInputElementImpl::PASSWORD: - ++inputtext; - default: - break; - } - } - } - - if (inputtext <= 1) - prepareSubmit(); -} - - -void HTMLFormElementImpl::gatherWalletData() -{ -#ifndef KHTML_NO_WALLET - KHTMLView* const view = getDocument()->view(); - // check if we have any password input's - m_walletMap.clear(); - m_havePassword = false; - m_haveTextarea = false; - const KURL formUrl(getDocument()->URL()); - if (view && !view->nonPasswordStorableSite(formUrl.host())) { - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { - if (it.current()->id() == ID_INPUT) { - HTMLInputElementImpl* const c = static_cast<HTMLInputElementImpl*> (it.current()); - if ((c->inputType() == HTMLInputElementImpl::TEXT || - c->inputType() == HTMLInputElementImpl::PASSWORD) && - !c->readOnly()) { - m_walletMap.insert(c->name().string(), c->value().string()); - if (c->inputType() == HTMLInputElementImpl::PASSWORD && - !c->value().isEmpty()) - m_havePassword = true; - } - } - else if (it.current()->id() == ID_TEXTAREA) - m_haveTextarea = true; - } - } -#endif // KHTML_NO_WALLET -} - - -bool HTMLFormElementImpl::prepareSubmit() -{ - KHTMLView* const view = getDocument()->view(); - if(m_insubmit || !view || !view->part() || view->part()->onlyLocalReferences()) - return m_insubmit; - - gatherWalletData(); - - m_insubmit = true; - m_doingsubmit = false; - - if ( dispatchHTMLEvent(EventImpl::SUBMIT_EVENT,true,true) && !m_doingsubmit ) - m_doingsubmit = true; - - m_insubmit = false; - - if ( m_doingsubmit ) - submit(); - - return m_doingsubmit; -} - -void HTMLFormElementImpl::submit( ) -{ - if ( m_insubmit ) { - m_doingsubmit = true; - return; - } - - m_insubmit = true; - -#ifdef FORMS_DEBUG - kdDebug( 6030 ) << "submitting!" << endl; -#endif - - bool ok; - KHTMLView* const view = getDocument()->view(); - const TQByteArray form_data = formData(ok); - const KURL formUrl(getDocument()->URL()); - - if (ok && view) { - if (m_walletMap.isEmpty()) { - gatherWalletData(); - } -#ifndef KHTML_NO_WALLET - if (m_havePassword && !m_haveTextarea && KWallet::Wallet::isEnabled()) { - const TQString key = calculateAutoFillKey(*this); - const bool doesnotexist = KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::FormDataFolder(), key); - KWallet::Wallet* const w = view->part()->wallet(); - bool login_changed = false; - - if (!doesnotexist && w) { - // check if the login information changed from what - // we had so far. - if (w->hasFolder(KWallet::Wallet::FormDataFolder())) { - w->setFolder(KWallet::Wallet::FormDataFolder()); - TQMap<TQString, TQString> map; - if (!w->readMap(key, map)) { - TQMapConstIterator<TQString, TQString> it = map.begin(); - const TQMapConstIterator<TQString, TQString> itEnd = map.end(); - for ( ; it != itEnd; ++it ) - if ( map[it.key()] != m_walletMap[it.key()] ) { - login_changed = true; - break; - } - } else { - login_changed = true; - } - } - } - - if ( doesnotexist || !w || login_changed ) { - // TODO use KMessageBox::questionYesNoCancel() again, if you can pass a KGuiItem for Cancel - KDialogBase* const dialog = new KDialogBase(i18n("Save Login Information"), - KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel, - KDialogBase::Yes, KDialogBase::Cancel, - 0, "questionYesNoCancel", true, true, - i18n("Store"), KGuiItem(i18n("Ne&ver for This Site")), i18n("Do Not Store")); - - bool checkboxResult = false; - const int savePassword = KMessageBox::createKMessageBox(dialog, TQMessageBox::Information, - i18n("Store passwords on this page?"), - TQStringList(), TQString::null, &checkboxResult, KMessageBox::Notify); - - if ( savePassword == KDialogBase::Yes ) { - // ensure that we have the user / password inside the url - // otherwise we might have a potential security problem - // by saving passwords under wrong lookup key. - - if (view->part()) { - view->part()->saveToWallet(key, m_walletMap); - } - } else if ( savePassword == KDialogBase::No ) { - view->addNonPasswordStorableSite(formUrl.host()); - } - } - } -#endif // KHTML_NO_WALLET - - const DOMString url(khtml::parseURL(getAttribute(ATTR_ACTION))); - if(m_post) { - view->part()->submitForm( "post", url.string(), form_data, - m_target.string(), - enctype().string(), - m_boundary ); - } - else { - view->part()->submitForm( "get", url.string(), form_data, - m_target.string() ); - } - } - - m_walletMap.clear(); // done with it - m_havePassword = m_haveTextarea= false; - m_doingsubmit = m_insubmit = false; -} - -void HTMLFormElementImpl::reset( ) -{ - KHTMLView* const view = getDocument()->view(); - if(m_inreset || !view || !view->part()) return; - - m_inreset = true; - -#ifdef FORMS_DEBUG - kdDebug( 6030 ) << "reset pressed!" << endl; -#endif - - // ### DOM2 labels this event as not cancelable, however - // common browsers( sick! ) allow it be cancelled. - if ( !dispatchHTMLEvent(EventImpl::RESET_EVENT,true, true) ) { - m_inreset = false; - return; - } - - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) - it.current()->reset(); - - m_inreset = false; -} - -void HTMLFormElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_ACTION: - break; - case ATTR_TARGET: - m_target = attr->value(); - break; - case ATTR_METHOD: - m_post = ( strcasecmp( attr->value(), "post" ) == 0 ); - break; - case ATTR_ENCTYPE: - setEnctype( attr->value() ); - break; - case ATTR_ACCEPT_CHARSET: - // space separated list of charsets the server - // accepts - see rfc2045 - m_acceptcharset = attr->value(); - break; - case ATTR_ACCEPT: - // ignore this one for the moment... - break; - case ATTR_AUTOCOMPLETE: - m_autocomplete = strcasecmp( attr->value(), "off" ); - break; - case ATTR_ONSUBMIT: - setHTMLEventListener(EventImpl::SUBMIT_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onsubmit", this)); - break; - case ATTR_ONRESET: - setHTMLEventListener(EventImpl::RESET_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onreset", this)); - break; - case ATTR_NAME: - if (inDocument() && m_name != attr->value()) { - getDocument()->underDocNamedCache().remove(m_name.string(), this); - getDocument()->underDocNamedCache().add (attr->value().string(), this); - } - m_name = attr->value(); - //Fallthrough intentional - default: - HTMLElementImpl::parseAttribute(attr); - } -} - -void HTMLFormElementImpl::removedFromDocument() -{ - getDocument()->underDocNamedCache().remove(m_name.string(), this); - HTMLElementImpl::removedFromDocument(); -} - -void HTMLFormElementImpl::insertedIntoDocument() -{ - getDocument()->underDocNamedCache().add(m_name.string(), this); - HTMLElementImpl::insertedIntoDocument(); -} - -void HTMLFormElementImpl::removeId(const TQString& id) -{ - getDocument()->underDocNamedCache().remove(id, this); - HTMLElementImpl::removeId(id); -} - -void HTMLFormElementImpl::addId (const TQString& id) -{ - getDocument()->underDocNamedCache().add(id, this); - HTMLElementImpl::addId(id); -} - - -void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller ) -{ - for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) { - HTMLGenericFormElementImpl* const current = it.current(); - if (current->id() == ID_INPUT && - static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::RADIO && - current != caller && current->form() == caller->form() && current->name() == caller->name()) - static_cast<HTMLInputElementImpl*>(current)->setChecked(false); - } -} - -void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl *e) -{ - formElements.append(e); -} - -void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl *e) -{ - formElements.remove(e); -} - -void HTMLFormElementImpl::registerImgElement(HTMLImageElementImpl *e) -{ - imgElements.append(e); -} - -void HTMLFormElementImpl::removeImgElement(HTMLImageElementImpl *e) -{ - imgElements.remove(e); -} - -// ------------------------------------------------------------------------- - -HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLElementImpl(doc) -{ - m_disabled = m_readOnly = false; - m_name = 0; - - if (f) - m_form = f; - else - m_form = getForm(); - if (m_form) - m_form->registerFormElement(this); -} - -void HTMLGenericFormElementImpl::insertedIntoDocument() -{ - HTMLElementImpl::insertedIntoDocument(); - - if (!m_form) { - HTMLFormElementImpl* const newform = getForm(); - if (newform) { - m_form = newform; - m_form->registerFormElement(this); - } - } -} - -void HTMLGenericFormElementImpl::removedFromDocument() -{ - HTMLElementImpl::removedFromDocument(); - - if (m_form) - m_form->removeFormElement(this); - - m_form = 0; -} - -HTMLGenericFormElementImpl::~HTMLGenericFormElementImpl() -{ - if (m_form) - m_form->removeFormElement(this); - if (m_name) m_name->deref(); -} - -void HTMLGenericFormElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_DISABLED: - setDisabled( attr->val() != 0 ); - break; - case ATTR_READONLY: - { - const bool m_oldreadOnly = m_readOnly; - m_readOnly = attr->val() != 0; - if (m_oldreadOnly != m_readOnly) setChanged(); - break; - } - default: - HTMLElementImpl::parseAttribute(attr); - } -} - -void HTMLGenericFormElementImpl::attach() -{ - assert(!attached()); - - if (m_render) { - assert(m_render->style()); - parentNode()->renderer()->addChild(m_render, nextRenderer()); - } - - // FIXME: This handles the case of a new form element being created by - // JavaScript and inserted inside a form. What it does not handle is - // a form element being moved from inside a form to outside, or from one - // inside one form to another. The reason this other case is hard to fix - // is that during parsing, we may have been passed a form that we are not - // inside, DOM-tree-wise. If so, it's hard for us to know when we should - // be removed from that form's element list. - if (!m_form) { - m_form = getForm(); - if (m_form) - m_form->registerFormElement(this); - } - - NodeBaseImpl::attach(); - - // The call to updateFromElement() needs to go after the call through - // to the base class's attach() because that can sometimes do a close - // on the renderer. - if (m_render) - m_render->updateFromElement(); - -} - -HTMLFormElementImpl *HTMLGenericFormElementImpl::getForm() const -{ - NodeImpl *p = parentNode(); - while(p) - { - if( p->id() == ID_FORM ) - return static_cast<HTMLFormElementImpl *>(p); - if( p->parentNode() && p->parentNode()->id() == ID_TABLE && p->previousSibling() ) - { - p = p->previousSibling(); - continue; - } - p = p->parentNode(); - } -#ifdef FORMS_DEBUG - kdDebug( 6030 ) << "couldn't find form!" << endl; - kdDebug( 6030 ) << kdBacktrace() << endl; -#endif - return 0; -} - -DOMString HTMLGenericFormElementImpl::name() const -{ - if (m_name) return m_name; - -// ### -// DOMString n = getDocument()->htmlMode() != DocumentImpl::XHtml ? -// getAttribute(ATTR_NAME) : getAttribute(ATTR_ID); - const DOMString n = getAttribute(ATTR_NAME); - if (n.isNull()) - return new DOMStringImpl(""); - - return n; -} - -void HTMLGenericFormElementImpl::setName(const DOMString& name) -{ - if (m_name) m_name->deref(); - m_name = name.implementation(); - setAttribute( ATTR_NAME, name ); - if (m_name) m_name->ref(); -} - -void HTMLGenericFormElementImpl::onSelect() -{ - // ### make this work with new form events architecture - dispatchHTMLEvent(EventImpl::SELECT_EVENT,true,false); -} - -void HTMLGenericFormElementImpl::onChange() -{ - // ### make this work with new form events architecture - dispatchHTMLEvent(EventImpl::CHANGE_EVENT,true,false); -} - -void HTMLGenericFormElementImpl::setDisabled( bool _disabled ) -{ - if ( m_disabled != _disabled ) { - m_disabled = _disabled; - // Trigger dynamic restyles - getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency); - // We need to update rendering under all circumstances - if (!changed() && m_render) { - m_render->updateFromElement(); - } - } -} - -bool HTMLGenericFormElementImpl::isFocusable() const -{ - if (disabled()) - return false; - - //Non-widget INPUT TYPE="image" and <BUTTON> support focus, too. - if (id() == ID_INPUT && static_cast<const HTMLInputElementImpl *>(this)->inputType() == HTMLInputElementImpl::IMAGE) - return true; - - if (id() == ID_BUTTON) - return true; - - if (!m_render || !m_render->isWidget()) - return false; - - TQWidget* widget = static_cast<RenderWidget*>(m_render)->widget(); - return widget && widget->focusPolicy() >= TQ_TabFocus; -} - -class FocusHandleWidget : public TQWidget -{ -public: - void focusNextPrev(bool n) { - if (!focusNextPrevChild(n) && inherits(TQTEXTEDIT_OBJECT_NAME_STRING)) - TQWidget::focusNextPrevChild(n); - } -}; - -void HTMLGenericFormElementImpl::defaultEventHandler(EventImpl *evt) -{ - if (evt->target() == this && renderer() && renderer()->isWidget()) { - switch(evt->id()) { - case EventImpl::MOUSEDOWN_EVENT: - case EventImpl::MOUSEUP_EVENT: - case EventImpl::MOUSEMOVE_EVENT: - case EventImpl::MOUSEOUT_EVENT: - case EventImpl::MOUSEOVER_EVENT: - case EventImpl::KEYDOWN_EVENT: - case EventImpl::KEYUP_EVENT: - case EventImpl::KEYPRESS_EVENT: - if (static_cast<RenderWidget*>(renderer())->handleEvent(*evt)) - evt->setDefaultHandled(); - default: - break; - } - } - - if (evt->target()==this && !m_disabled) - { - // Report focus in/out changes to the browser extension (editable widgets only) - KHTMLView* const view = getDocument()->view(); - if (view && evt->id() == EventImpl::DOMFOCUSIN_EVENT && isEditable() && m_render && m_render->isWidget()) { - KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension()); - TQWidget* const widget = static_cast<RenderWidget*>(m_render)->widget(); - if (ext) - ext->editableWidgetFocused(widget); - } - if (evt->id()==EventImpl::MOUSEDOWN_EVENT || evt->id()==EventImpl::KEYDOWN_EVENT) - { - setActive(); - } - else if (evt->id() == EventImpl::MOUSEUP_EVENT || evt->id()==EventImpl::KEYUP_EVENT) - { - if (m_active) - { - setActive(false); - setFocus(); - } - else { - setActive(false); - } - } - - if (!evt->defaultHandled() && m_render && m_render->isWidget()) { - // handle tabbing out, either from a single or repeated key event. - if ( evt->id() == EventImpl::KEYPRESS_EVENT && evt->isKeyRelatedEvent() ) { - TQKeyEvent* const k = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent(); - if ( k && (k->key() == Qt::Key_Tab || k->key() == TQt::Key_BackTab) ) { - TQWidget* const widget = static_cast<RenderWidget*>(m_render)->widget(); -#ifdef USE_QT4 - if (widget) - static_cast<FocusHandleWidget *>(widget) - ->focusNextPrev(k->key() == Qt::Key_Tab); -#else // USE_QT4 - TQFocusEvent::setReason( k->key() == Qt::Key_Tab ? TQFocusEvent::Tab : TQFocusEvent::Backtab ); - if (widget) - static_cast<FocusHandleWidget *>(widget) - ->focusNextPrev(k->key() == Qt::Key_Tab); - TQFocusEvent::resetReason(); -#endif // USE_QT4 - evt->setDefaultHandled(); - } - } - } - - - if (view && evt->id() == EventImpl::DOMFOCUSOUT_EVENT && isEditable() && m_render && m_render->isWidget()) { - KHTMLPartBrowserExtension* const ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension()); - TQWidget* const widget = static_cast<RenderWidget*>(m_render)->widget(); - if (ext) - ext->editableWidgetBlurred(widget); - - // ### Don't count popup as a valid reason for losing the focus (example: opening the options of a select - // combobox shouldn't emit onblur) - } - } - if (evt->target() == this && evt->isMouseEvent() && renderer()) - evt->setDefaultHandled(); - - HTMLElementImpl::defaultEventHandler(evt); -} - -bool HTMLGenericFormElementImpl::isEditable() -{ - return false; -} - -// ------------------------------------------------------------------------- - -HTMLButtonElementImpl::HTMLButtonElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ - m_clicked = false; - m_type = SUBMIT; - m_dirty = true; - m_activeSubmit = false; -} - -HTMLButtonElementImpl::~HTMLButtonElementImpl() -{ -} - -NodeImpl::Id HTMLButtonElementImpl::id() const -{ - return ID_BUTTON; -} - -DOMString HTMLButtonElementImpl::type() const -{ - return getAttribute(ATTR_TYPE); -} - -void HTMLButtonElementImpl::blur() -{ - if(getDocument()->focusNode() == this) - getDocument()->setFocusNode(0); -} - -void HTMLButtonElementImpl::focus() -{ - getDocument()->setFocusNode(this); -} - -void HTMLButtonElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_TYPE: - if ( strcasecmp( attr->value(), "submit" ) == 0 ) - m_type = SUBMIT; - else if ( strcasecmp( attr->value(), "reset" ) == 0 ) - m_type = RESET; - else if ( strcasecmp( attr->value(), "button" ) == 0 ) - m_type = BUTTON; - break; - case ATTR_VALUE: - m_value = attr->value(); - m_currValue = m_value.string(); - break; - case ATTR_ACCESSKEY: - break; - case ATTR_ALIGN: - break; - default: - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -void HTMLButtonElementImpl::defaultEventHandler(EventImpl *evt) -{ - if (m_type != BUTTON && !m_disabled) { - bool act = (evt->id() == EventImpl::DOMACTIVATE_EVENT); - if (!act && evt->id()==EventImpl::KEYUP_EVENT && evt->isKeyRelatedEvent()) { - TQKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent(); - if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space)) - act = true; - } - if (act) - activate(); - } - HTMLGenericFormElementImpl::defaultEventHandler(evt); -} - -void HTMLButtonElementImpl::activate() -{ - m_clicked = true; - - if(m_form && m_type == SUBMIT) { - m_activeSubmit = true; - m_form->prepareSubmit(); - m_activeSubmit = false; // in case we were canceled - } - if(m_form && m_type == RESET) - m_form->reset(); -} - -void HTMLButtonElementImpl::click() -{ - TQMouseEvent me(TQEvent::MouseButtonRelease, TQPoint(0,0),Qt::LeftButton, 0); - dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1); -} - -bool HTMLButtonElementImpl::encoding(const TQTextCodec* codec, khtml::encodingList& encoding, bool /*multipart*/) -{ - if (m_type != SUBMIT || name().isEmpty() || !m_activeSubmit) - return false; - - encoding += fixUpfromUnicode(codec, name().string()); - const TQString enc_str = m_currValue.isNull() ? TQString("") : m_currValue; - encoding += fixUpfromUnicode(codec, enc_str); - - return true; -} - -void HTMLButtonElementImpl::attach() -{ - // skip the generic handler - HTMLElementImpl::attach(); -} - -// ------------------------------------------------------------------------- - -HTMLFieldSetElementImpl::HTMLFieldSetElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ -} - -HTMLFieldSetElementImpl::~HTMLFieldSetElementImpl() -{ -} - -NodeImpl::Id HTMLFieldSetElementImpl::id() const -{ - return ID_FIELDSET; -} - -void HTMLFieldSetElementImpl::attach() -{ - assert(!attached()); - assert(!m_render); - assert(parentNode()); - - RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this); - _style->ref(); - if (parentNode()->renderer() && _style->display() != NONE) { - m_render = new (getDocument()->renderArena()) RenderFieldset(this); - m_render->setStyle(_style); - } - HTMLGenericFormElementImpl::attach(); - _style->deref(); -} - -void HTMLFieldSetElementImpl::parseAttribute(AttributeImpl *attr) -{ - HTMLElementImpl::parseAttribute(attr); -} - -// ------------------------------------------------------------------------- - -HTMLInputElementImpl::HTMLInputElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ - m_type = TEXT; - m_maxLen = -1; - m_size = 20; - m_clicked = false; - m_checked = false; - m_defaultChecked = false; - m_useDefaultChecked = true; - m_indeterminate = false; - - m_haveType = false; - m_activeSubmit = false; - m_autocomplete = true; - m_inited = false; - m_unsubmittedFormChange = false; - - xPos = 0; - yPos = 0; - - if ( m_form ) - m_autocomplete = f->autoComplete(); -} - -HTMLInputElementImpl::~HTMLInputElementImpl() -{ - if (getDocument()) getDocument()->deregisterMaintainsState(this); -} - -NodeImpl::Id HTMLInputElementImpl::id() const -{ - return ID_INPUT; -} - -// Called from JS. Can't merge with parseType since we -// also need to actually set ATTR_TYPE, which can't be done there. -void HTMLInputElementImpl::setType(const DOMString& t) -{ - setAttribute(ATTR_TYPE, t); -} - -void HTMLInputElementImpl::parseType(const DOMString& t) -{ - typeEnum newType; - - if ( strcasecmp( t, "password" ) == 0 ) - newType = PASSWORD; - else if ( strcasecmp( t, "checkbox" ) == 0 ) - newType = CHECKBOX; - else if ( strcasecmp( t, "radio" ) == 0 ) - newType = RADIO; - else if ( strcasecmp( t, "submit" ) == 0 ) - newType = SUBMIT; - else if ( strcasecmp( t, "reset" ) == 0 ) - newType = RESET; - else if ( strcasecmp( t, "file" ) == 0 ) - newType = FILE; - else if ( strcasecmp( t, "hidden" ) == 0 ) - newType = HIDDEN; - else if ( strcasecmp( t, "image" ) == 0 ) - newType = IMAGE; - else if ( strcasecmp( t, "button" ) == 0 ) - newType = BUTTON; - else if ( strcasecmp( t, "khtml_isindex" ) == 0 ) - newType = ISINDEX; - else - newType = TEXT; - - // ### IMPORTANT: Don't allow the type to be changed to FILE after the first - // type change, otherwise a JavaScript programmer would be able to set a text - // field's value to something like /etc/passwd and then change it to a file field. - if (m_type != newType) { - if (newType == FILE && m_haveType) { - // Set the attribute back to the old value. - // Note that this calls parseAttribute again. - setAttribute(ATTR_TYPE, type()); - } else { - m_type = newType; - - // force reattach if need be. - if (attached()) { - detach(); - attach(); - } - } - } - m_haveType = true; -} - -DOMString HTMLInputElementImpl::type() const -{ - // needs to be lowercase according to DOM spec - switch (m_type) { - case TEXT: return "text"; - case PASSWORD: return "password"; - case CHECKBOX: return "checkbox"; - case RADIO: return "radio"; - case SUBMIT: return "submit"; - case RESET: return "reset"; - case FILE: return "file"; - case HIDDEN: return "hidden"; - case IMAGE: return "image"; - case BUTTON: return "button"; - default: return ""; - } -} - -TQString HTMLInputElementImpl::state( ) -{ - switch (m_type) { - case PASSWORD: - return TQString::fromLatin1("."); // empty string, avoid restoring - case CHECKBOX: - case RADIO: - return TQString::fromLatin1(checked() ? "on" : "off"); - case TEXT: - if (autoComplete() && value() != getAttribute(ATTR_VALUE) && getDocument()->view()) - getDocument()->view()->addFormCompletionItem(name().string(), value().string()); - /* nobreak */ - default: - return value().string() + (m_unsubmittedFormChange ? 'M' : '.'); - } -} - -void HTMLInputElementImpl::restoreState(const TQString &state) -{ - switch (m_type) { - case CHECKBOX: - case RADIO: - setChecked((state == TQString::fromLatin1("on"))); - break; - case FILE: - m_value = DOMString(state.left(state.length()-1)); - setChanged(); - break; - default: - setValue(DOMString(state.left(state.length()-1))); - m_unsubmittedFormChange = state.endsWith("M"); - break; - } -} - -void HTMLInputElementImpl::select( ) -{ - if(!m_render) return; - - if (m_type == TEXT || m_type == PASSWORD) - static_cast<RenderLineEdit*>(m_render)->select(); - else if (m_type == FILE) - static_cast<RenderFileButton*>(m_render)->select(); -} - -void HTMLInputElementImpl::click() -{ - TQMouseEvent me(TQEvent::MouseButtonRelease, TQPoint(0,0),Qt::LeftButton, 0); - dispatchMouseEvent(&me,0, 1); - dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1); -} - -void HTMLInputElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_AUTOCOMPLETE: - m_autocomplete = strcasecmp( attr->value(), "off" ); - break; - case ATTR_TYPE: - parseType(attr->value()); - break; - case ATTR_VALUE: - if (m_value.isNull()) {// We only need to setChanged if the form is looking - setChanged(); // at the default value right now. - if (m_type == TEXT && m_render) - m_render->updateFromElement(); - } - break; - case ATTR_CHECKED: - m_defaultChecked = attr->val(); - if (m_useDefaultChecked) // We only need to setChanged if the form is looking - setChanged(); // at the default checked state right now. - break; - case ATTR_MAXLENGTH: - { - m_maxLen = -1; - if (!attr->val()) break; - bool ok; - const int ml = attr->val()->toInt(&ok); - if (ml > 0 && ml < 32767) - m_maxLen = ml; - else if (ok && ml <= 0) - m_maxLen = 0; - setChanged(); - } - break; - case ATTR_SIZE: - m_size = attr->val() ? attr->val()->toInt() : 20; - break; - case ATTR_ALT: - case ATTR_SRC: - if (m_type == IMAGE) - setChanged(); - break; - case ATTR_USEMAP: - // ### ignore for the moment - break; - case ATTR_ALIGN: - if ( m_inited && m_type == IMAGE ) - addHTMLAlignment( attr->value() ); - break; - case ATTR_ACCESSKEY: - break; - case ATTR_WIDTH: - if ( m_type == IMAGE ) - addCSSLength(CSS_PROP_WIDTH, attr->value() ); - break; - case ATTR_HEIGHT: - if ( m_type == IMAGE ) - addCSSLength(CSS_PROP_HEIGHT, attr->value() ); - break; - case ATTR_ONSELECT: - setHTMLEventListener(EventImpl::SELECT_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onselect", this)); - break; - case ATTR_ONCHANGE: - setHTMLEventListener(EventImpl::CHANGE_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this)); - break; - default: - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -void HTMLInputElementImpl::attach() -{ - assert(!attached()); - assert(!m_render); - assert(parentNode()); - - if (!m_inited) { - // FIXME: This needs to be dynamic, doesn't it, since someone could set this - // after attachment? - if ((uint) m_type <= ISINDEX && !m_value.isEmpty()) { - const TQString value = m_value.string(); - // remove newline stuff.. - TQString nvalue; - unsigned int valueLength = value.length(); - for (unsigned int i = 0; i < valueLength; ++i) - if (value[i] >= TQChar(' ')) - nvalue += value[i]; - m_value = nvalue; - } - m_defaultChecked = (getAttribute(ATTR_CHECKED) != 0); - if ( m_type == IMAGE ) - addHTMLAlignment( getAttribute( ATTR_ALIGN ) ); - m_inited = true; - } - - switch( m_type ) { - case PASSWORD: - if (getDocument()->isHTMLDocument()) - static_cast<HTMLDocumentImpl*>(getDocument())->setAutoFill(); - break; - case HIDDEN: - case IMAGE: - if (!getAttribute(ATTR_WIDTH).isNull()) - addCSSLength(CSS_PROP_WIDTH, getAttribute(ATTR_WIDTH)); - if (!getAttribute(ATTR_HEIGHT).isNull()) - addCSSLength(CSS_PROP_HEIGHT, getAttribute(ATTR_HEIGHT)); - default: - break; - }; - - RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this); - _style->ref(); - if (parentNode()->renderer() && _style->display() != NONE) { - switch(m_type) - { - case TEXT: - case PASSWORD: - case ISINDEX: m_render = new (getDocument()->renderArena()) RenderLineEdit(this); break; - case CHECKBOX: m_render = new (getDocument()->renderArena()) RenderCheckBox(this); break; - case RADIO: m_render = new (getDocument()->renderArena()) RenderRadioButton(this); break; - case SUBMIT: m_render = new (getDocument()->renderArena()) RenderSubmitButton(this); break; - case IMAGE: m_render = new (getDocument()->renderArena()) RenderImageButton(this); break; - case RESET: m_render = new (getDocument()->renderArena()) RenderResetButton(this); break; - case FILE: m_render = new (getDocument()->renderArena()) RenderFileButton(this); break; - case BUTTON: m_render = new (getDocument()->renderArena()) RenderPushButton(this); - case HIDDEN: break; - } - } - - // Let check and radio boxes start indeterminate - setIndeterminate(true); - - if (m_render) - m_render->setStyle(_style); - - HTMLGenericFormElementImpl::attach(); - _style->deref(); -} - -DOMString HTMLInputElementImpl::altText() const -{ - // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen - // also heavily discussed by Hixie on bugzilla - // note this is intentionally different to HTMLImageElementImpl::altText() - DOMString alt = getAttribute( ATTR_ALT ); - // fall back to title attribute - if ( alt.isNull() ) - alt = getAttribute( ATTR_TITLE ); - if ( alt.isNull() ) - alt = getAttribute( ATTR_VALUE ); - if ( alt.isEmpty() ) - alt = i18n( "Submit" ); - - return alt; -} - -bool HTMLInputElementImpl::encoding(const TQTextCodec* codec, khtml::encodingList& encoding, bool multipart) -{ - const TQString nme = name().string(); - - // image generates its own name's - if (nme.isEmpty() && m_type != IMAGE) return false; - - // IMAGE needs special handling later - if(m_type != IMAGE) encoding += fixUpfromUnicode(codec, nme); - - switch (m_type) { - case CHECKBOX: - - if( checked() ) { - encoding += fixUpfromUnicode(codec, value().string()); - return true; - } - break; - - case RADIO: - - if( checked() ) { - encoding += fixUpfromUnicode(codec, value().string()); - return true; - } - break; - - case BUTTON: - case RESET: - // those buttons are never successful - return false; - - case IMAGE: - - if(m_clicked) - { - m_clicked = false; - TQString astr(nme.isEmpty() ? TQString::fromLatin1("x") : nme + ".x"); - - encoding += fixUpfromUnicode(codec, astr); - astr.setNum(KMAX( clickX(), 0 )); - encoding += fixUpfromUnicode(codec, astr); - astr = nme.isEmpty() ? TQString::fromLatin1("y") : nme + ".y"; - encoding += fixUpfromUnicode(codec, astr); - astr.setNum(KMAX( clickY(), 0 ) ); - encoding += fixUpfromUnicode(codec, astr); - astr = value().string(); - if(astr.length() > 0) { - encoding += fixUpfromUnicode(codec, nme); - encoding += fixUpfromUnicode(codec, astr); - } - - return true; - } - break; - - case SUBMIT: - - if (m_activeSubmit) - { - TQString enc_str = valueWithDefault().string(); - if(!enc_str.isEmpty()) - { - encoding += fixUpfromUnicode(codec, enc_str); - return true; - } - } - break; - - case FILE: // hmm, we have the type FILE also. bad choice here... - { - // don't submit if display: none or display: hidden - if(!renderer() || renderer()->style()->visibility() != khtml::VISIBLE) - return false; - - TQString local; - KURL fileurl; - TQString val = value().string(); - if (!val.isEmpty() && - TQDir::isRelativePath(val) && - TQFile::exists(TDEGlobalSettings::documentPath() + val)) { - fileurl.setPath(TDEGlobalSettings::documentPath() + val); - } else { - fileurl = KURL::fromPathOrURL(val); - } - - TDEIO::UDSEntry filestat; - - // can't submit file in www-url-form encoded - TQWidget* const toplevel = static_cast<RenderSubmitButton*>(m_render)->widget()->topLevelWidget(); - if (multipart) { - TQCString filearray( "" ); - if ( TDEIO::NetAccess::stat(fileurl, filestat, toplevel)) { - const KFileItem fileitem(filestat, fileurl, true, false); - if ( fileitem.isFile() && - TDEIO::NetAccess::download(fileurl, local, toplevel) ) { - TQFile file(local); - filearray.resize(file.size()+1); - if ( file.open( IO_ReadOnly ) ) { - const int readbytes = file.readBlock( filearray.data(), file.size()); - if ( readbytes >= 0 ) - filearray[readbytes] = '\0'; - file.close(); - } - TDEIO::NetAccess::removeTempFile( local ); - } - } - encoding += filearray; - return true; - } - // else fall through - } - case HIDDEN: - case TEXT: - case PASSWORD: - // always successful - encoding += fixUpfromUnicode(codec, value().string()); - return true; - case ISINDEX: - encoding += fixUpfromUnicode(codec, value().string()); - return true; - } - return false; -} - -void HTMLInputElementImpl::reset() -{ - if (m_type == FILE) { - // set directly to bypass security check. emptying the value - // should mean no risk. - if (!m_value.isEmpty()) { - m_value = DOMString(); - setChanged(); - } - } else { - setValue(getAttribute(ATTR_VALUE)); - } - m_useDefaultChecked = true; - m_checked = m_defaultChecked; - setIndeterminate(true); -} - -void HTMLInputElementImpl::setChecked(bool _checked) -{ - if (m_form && m_type == RADIO && _checked && !name().isEmpty()) - m_form->radioClicked(this); - - if (checked() == _checked) return; - m_useDefaultChecked = false; - m_checked = _checked; - -// setIndeterminate(false); - - // Trigger dynamic restyles - getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency); - // We need to update rendering under all circumstances - if (!changed() && m_render) { - m_render->updateFromElement(); - } -} - -void HTMLInputElementImpl::setIndeterminate(bool _indeterminate) -{ - // Only checkboxes and radio-boxes honor indeterminate. - if (inputType() != CHECKBOX || inputType() != RADIO || indeterminate() == _indeterminate) - return; - - m_indeterminate = _indeterminate; - - // Trigger dynamic restyles -// getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency); - // We need to update rendering under all circumstances - if (!changed() && m_render) { - m_render->updateFromElement(); - } -} - -DOMString HTMLInputElementImpl::value() const -{ - if (m_type == CHECKBOX || m_type == RADIO) { - const DOMString val = getAttribute(ATTR_VALUE); - // If no attribute exists, then we'll just return "on" as - // other browsers strangely seem to do without respecting the - // checked() state of the control. - if (val.isNull()) - return DOMString("on"); - return val; - } - - DOMString val = m_value; - // It's important *not* to fall back to the value attribute for file inputs, - // because that would allow a malicious web page to upload files by setting the - // value attribute in markup. - if (val.isNull() && m_type != FILE) - val = getAttribute(ATTR_VALUE); - - return val.isNull() ? DOMString("") : val; -} - - -void HTMLInputElementImpl::setValue(DOMString val) -{ - if (m_type == FILE) return; - - m_value = (val.isNull() ? DOMString("") : val); - // ### set attribute for other types, too. no need for m_value - // ### in those cases. - if (m_type == RADIO || m_type == CHECKBOX) - setAttribute(ATTR_VALUE, m_value); - if (m_type == TEXT && m_render) - m_render->updateFromElement(); - setChanged(); -} - -void HTMLInputElementImpl::blur() -{ - if(getDocument()->focusNode() == this) - getDocument()->setFocusNode(0); -} - -void HTMLInputElementImpl::focus() -{ - getDocument()->setFocusNode(this); -} - -void HTMLInputElementImpl::defaultEventHandler(EventImpl *evt) -{ - if ( !m_disabled ) - { - - if (evt->isMouseEvent()) { - MouseEventImpl* const me = static_cast<MouseEventImpl*>(evt); - if ((m_type == RADIO || m_type == CHECKBOX) - && me->id() == EventImpl::MOUSEUP_EVENT && me->detail() > 0) { - // click will follow - setChecked(m_type == RADIO ? true : !checked()); - } - if (evt->id() == EventImpl::CLICK_EVENT && m_type == IMAGE && m_render) { - // record the mouse position for when we get the DOMActivate event - int offsetX, offsetY; - m_render->absolutePosition(offsetX,offsetY); - xPos = me->clientX()-offsetX; - yPos = me->clientY()-offsetY; - KHTMLView* v = getDocument()->view(); - if ( v ) { - xPos += v->contentsX(); - yPos += v->contentsY(); - } - } - } - - if (m_type == RADIO || m_type == CHECKBOX || m_type == SUBMIT || m_type == RESET || m_type == BUTTON ) { - bool check = false; - if (active() && ( evt->id() == EventImpl::KEYUP_EVENT || - evt->id() == EventImpl::KEYPRESS_EVENT ) ) { - TextEventImpl* const te = static_cast<TextEventImpl *>(evt); - if (te->keyVal() == ' ') - check = true; - else if (te->keyVal() == '\r' && (m_type == BUTTON || m_type == RESET || m_type == SUBMIT)) - check = true; - } - if (check) { - if (evt->id() == EventImpl::KEYUP_EVENT) - click(); - // Tell the parent that we handle this key (keyup and keydown), even though only keyup activates (#70478) - evt->setDefaultHandled(); - } - } - - - // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means - // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks - // on the element, or presses enter while it is the active element. Javascript code wishing to activate the element - // must dispatch a DOMActivate event - a click event will not do the job. - if (m_type == IMAGE || m_type == SUBMIT || m_type == RESET) { - bool act = (evt->id() == EventImpl::DOMACTIVATE_EVENT); - if (!act && evt->id() == EventImpl::KEYUP_EVENT && evt->isKeyRelatedEvent()) { - TQKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent(); - if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space)) - act = true; - } - if (act) - activate(); - } - } - HTMLGenericFormElementImpl::defaultEventHandler(evt); -} - -void HTMLInputElementImpl::activate() -{ - if (!m_form) - return; - - m_clicked = true; - if (m_type == RESET) { - m_form->reset(); - } - else { - m_activeSubmit = true; - if (!m_form->prepareSubmit()) { - xPos = 0; - yPos = 0; - } - m_activeSubmit = false; - } -} - -bool HTMLInputElementImpl::isEditable() -{ - return ((m_type == TEXT) || (m_type == PASSWORD) || (m_type == ISINDEX) || (m_type == FILE)); -} - -long HTMLInputElementImpl::selectionStart() -{ - if (m_type != TEXT || !m_render) return -1; - return static_cast<RenderLineEdit*>(m_render)->selectionStart(); -} - -long HTMLInputElementImpl::selectionEnd() -{ - if (m_type != TEXT || !m_render) return -1; - return static_cast<RenderLineEdit*>(m_render)->selectionEnd(); -} - -void HTMLInputElementImpl::setSelectionStart(long pos) -{ - if (m_type != TEXT || !m_render) return; - static_cast<RenderLineEdit*>(m_render)->setSelectionStart(pos); -} - -void HTMLInputElementImpl::setSelectionEnd (long pos) -{ - if (m_type != TEXT || !m_render) return; - static_cast<RenderLineEdit*>(m_render)->setSelectionEnd(pos); -} - -void HTMLInputElementImpl::setSelectionRange(long start, long end) -{ - if (m_type != TEXT || !m_render) return; - static_cast<RenderLineEdit*>(m_render)->setSelectionRange(start, end); -} - -// ------------------------------------------------------------------------- - -HTMLLabelElementImpl::HTMLLabelElementImpl(DocumentImpl *doc) - : HTMLGenericFormElementImpl(doc) -{ -} - -HTMLLabelElementImpl::~HTMLLabelElementImpl() -{ -} - -NodeImpl::Id HTMLLabelElementImpl::id() const -{ - return ID_LABEL; -} - -void HTMLLabelElementImpl::attach() -{ - // skip the generic handler - HTMLElementImpl::attach(); -} - -NodeImpl* HTMLLabelElementImpl::getFormElement() -{ - const DOMString formElementId = getAttribute(ATTR_FOR); - NodeImpl *newNode=0L; - if (!formElementId.isEmpty()) - newNode=getDocument()->getElementById(formElementId); - if (!newNode){ - const uint children=childNodeCount(); - if (children>1) - for (unsigned int i=0;i<children;++i){ - const uint nodeId=childNode(i)->id(); - if (nodeId==ID_INPUT || nodeId==ID_SELECT || nodeId==ID_TEXTAREA){ - newNode=childNode(i); - break; - } - } - } -return newNode; -} - -void HTMLLabelElementImpl::defaultEventHandler(EventImpl *evt) -{ - if ( !m_disabled ) { - bool act = false; - if ( evt->id() == EventImpl::CLICK_EVENT ) { - act = true; - } - else if ( evt->isKeyRelatedEvent() && ( evt->id() == EventImpl::KEYUP_EVENT || - evt->id() == EventImpl::KEYPRESS_EVENT ) ) { - TQKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent(); - if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space)) - act = true; - } - - if (act) { - NodeImpl* const formNode=getFormElement(); - if (formNode && evt->target() != formNode) { - getDocument()->setFocusNode(formNode); - if (formNode->id()==ID_INPUT) - static_cast<DOM::HTMLInputElementImpl*>(formNode)->click(); - evt->setDefaultHandled(); - } - } - } - HTMLGenericFormElementImpl::defaultEventHandler(evt); -} - -// ------------------------------------------------------------------------- - -HTMLLegendElementImpl::HTMLLegendElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ -} - -HTMLLegendElementImpl::~HTMLLegendElementImpl() -{ -} - -NodeImpl::Id HTMLLegendElementImpl::id() const -{ - return ID_LEGEND; -} - -void HTMLLegendElementImpl::attach() -{ - assert(!attached()); - assert(!m_render); - assert(parentNode()); - RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this); - _style->ref(); - if (parentNode()->renderer() && _style->display() != NONE) { - m_render = new (getDocument()->renderArena()) RenderLegend(this); - m_render->setStyle(_style); - } - HTMLGenericFormElementImpl::attach(); - _style->deref(); -} - -void HTMLLegendElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_ACCESSKEY: - break; - default: - HTMLElementImpl::parseAttribute(attr); - } -} - -// ------------------------------------------------------------------------- - -HTMLSelectElementImpl::HTMLSelectElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ - m_multiple = false; - m_recalcListItems = false; - // 0 means invalid (i.e. not set) - m_size = 0; - m_minwidth = 0; - m_length = 0; -} - -HTMLSelectElementImpl::~HTMLSelectElementImpl() -{ - if (getDocument()) getDocument()->deregisterMaintainsState(this); -} - -NodeImpl::Id HTMLSelectElementImpl::id() const -{ - return ID_SELECT; -} - -DOMString HTMLSelectElementImpl::type() const -{ - return (m_multiple ? "select-multiple" : "select-one"); -} - -long HTMLSelectElementImpl::selectedIndex() const -{ - // return the number of the first option selected - uint o = 0; - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - const unsigned int itemsSize = items.size(); - for (unsigned int i = 0; i < itemsSize; ++i) { - if (items[i]->id() == ID_OPTION) { - if (static_cast<HTMLOptionElementImpl*>(items[i])->selected()) - return o; - o++; - } - } - Q_ASSERT(m_multiple || items.isEmpty()); - return -1; -} - -void HTMLSelectElementImpl::setSelectedIndex( long index ) -{ - // deselect all other options and select only the new one - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - int listIndex; - const int itemsSize = int(items.size()); - for (listIndex = 0; listIndex < itemsSize; ++listIndex) { - if (items[listIndex]->id() == ID_OPTION) - static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(false); - } - listIndex = optionToListIndex(index); - if (listIndex >= 0) - static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(true); - - setChanged(true); -} - -long HTMLSelectElementImpl::length() const -{ - if (m_recalcListItems) - recalcListItems(); - return m_length; -} - -void HTMLSelectElementImpl::add( const HTMLElement &element, const HTMLElement &before, int& exceptioncode ) -{ - if(element.isNull() || element.handle()->id() != ID_OPTION) - return; - - HTMLOptionElementImpl* option = static_cast<HTMLOptionElementImpl*>(element.handle());; - //Fast path for appending an item. Can't be done if it is selected and - //we're single-select, since we may need to drop an implicitly-selected item - bool fastAppendLast = false; - if (before.handle() == 0 && (m_multiple || !option->selected()) && !m_recalcListItems) - fastAppendLast = true; - - insertBefore(option, before.handle(), exceptioncode ); - - if (fastAppendLast) { - m_listItems.resize(m_listItems.size() + 1); - m_listItems[m_listItems.size() - 1] = option; - ++m_length; - m_recalcListItems = false; - } else if (!exceptioncode) - setRecalcListItems(); -} - -void HTMLSelectElementImpl::remove( long index ) -{ - int exceptioncode = 0; - const int listIndex = optionToListIndex(index); - - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - if(listIndex < 0 || index >= int(items.size())) - return; // ### what should we do ? remove the last item? - - //Fast path for last element, for e.g. clearing the box - //Note that if this is a single-select, we may have to recompute - //anyway if the item was selected, since we may want to set - //a different one - bool fastRemoveLast = false; - if ((listIndex == (signed)items.size() - 1) && !m_recalcListItems && - (m_multiple || !static_cast<HTMLOptionElementImpl*>(items[listIndex])->selected())) - fastRemoveLast = true; - - removeChild(items[listIndex], exceptioncode); - - if (fastRemoveLast) { - m_listItems.resize(m_listItems.size() - 1); - --m_length; - m_recalcListItems = false; - } else if( !exceptioncode) - setRecalcListItems(); -} - -void HTMLSelectElementImpl::blur() -{ - if(getDocument()->focusNode() == this) - getDocument()->setFocusNode(0); -} - -void HTMLSelectElementImpl::focus() -{ - getDocument()->setFocusNode(this); -} - -DOMString HTMLInputElementImpl::valueWithDefault() const -{ - DOMString v = value(); - if (v.isEmpty()) { - switch (m_type) { - case RESET: -#ifdef APPLE_CHANGES - v = resetButtonDefaultLabel(); -#else - v = i18n("Reset"); -#endif - break; - - case SUBMIT: -#ifdef APPLE_CHANGES - v = submitButtonDefaultLabel(); -#else - v = i18n("Submit"); -#endif - break; - - case BUTTON: - case CHECKBOX: - case FILE: - case HIDDEN: - case IMAGE: - case ISINDEX: - case PASSWORD: - case RADIO: - #ifdef APPLE_CHANGES - case RANGE: - case SEARCH: - #endif - case TEXT: - break; - } - } - return v; -} - -DOMString HTMLSelectElementImpl::value( ) const -{ - uint i; - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - const uint itemsSize = items.size(); - for (i = 0; i < itemsSize; ++i) { - if ( items[i]->id() == ID_OPTION - && static_cast<HTMLOptionElementImpl*>(items[i])->selected()) - return static_cast<HTMLOptionElementImpl*>(items[i])->value(); - } - return DOMString(""); -} - -void HTMLSelectElementImpl::setValue(DOMStringImpl* value) -{ - // find the option with value() matching the given parameter - // and make it the current selection. - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - for (unsigned i = 0; i < items.size(); i++) - if (items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->value() == value) { - static_cast<HTMLOptionElementImpl*>(items[i])->setSelected(true); - return; - } -} - -TQString HTMLSelectElementImpl::state( ) -{ - TQString state; - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - - const int l = items.count(); - - state.fill('.', l); - for(int i = 0; i < l; ++i) - if(items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->selected()) - state[i] = 'X'; - - return state; -} - -void HTMLSelectElementImpl::restoreState(const TQString &_state) -{ - recalcListItems(); - - TQString state = _state; - if(!state.isEmpty() && !state.contains('X') && !m_multiple && m_size <= 1) { - tqWarning("should not happen in restoreState!"); - state[0] = 'X'; - } - - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - - const int l = items.count(); - for(int i = 0; i < l; ++i) { - if(items[i]->id() == ID_OPTION) { - HTMLOptionElementImpl* const oe = static_cast<HTMLOptionElementImpl*>(items[i]); - oe->setSelected(state[i] == 'X'); - } - } - setChanged(true); -} - -NodeImpl *HTMLSelectElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode ) -{ - NodeImpl* const result = HTMLGenericFormElementImpl::insertBefore(newChild,refChild, exceptioncode ); - if (!exceptioncode) - setRecalcListItems(); - return result; -} - -void HTMLSelectElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode ) -{ - HTMLGenericFormElementImpl::replaceChild(newChild,oldChild, exceptioncode); - if( !exceptioncode ) - setRecalcListItems(); -} - -void HTMLSelectElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode ) -{ - HTMLGenericFormElementImpl::removeChild(oldChild, exceptioncode); - if( !exceptioncode ) - setRecalcListItems(); -} - -NodeImpl *HTMLSelectElementImpl::appendChild ( NodeImpl *newChild, int &exceptioncode ) -{ - NodeImpl* const result = HTMLGenericFormElementImpl::appendChild(newChild, exceptioncode); - if( !exceptioncode ) - setRecalcListItems(); - setChanged(true); - return result; -} - -NodeImpl* HTMLSelectElementImpl::addChild(NodeImpl* newChild) -{ - setRecalcListItems(); - return HTMLGenericFormElementImpl::addChild(newChild); -} - -void HTMLSelectElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_SIZE: - m_size = kMax( attr->val()->toInt(), 1 ); - setChanged(); - break; - case ATTR_WIDTH: - m_minwidth = kMax( attr->val()->toInt(), 0 ); - break; - case ATTR_MULTIPLE: - m_multiple = (attr->val() != 0); - break; - case ATTR_ACCESSKEY: - break; - case ATTR_ALIGN: - addHTMLAlignment( attr->value() ); - break; - case ATTR_ONCHANGE: - setHTMLEventListener(EventImpl::CHANGE_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this)); - break; - default: - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -void HTMLSelectElementImpl::attach() -{ - assert(!attached()); - assert(parentNode()); - assert(!renderer()); - - RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this); - _style->ref(); - if (parentNode()->renderer() && _style->display() != NONE) { - m_render = new (getDocument()->renderArena()) RenderSelect(this); - m_render->setStyle(_style); - } - - HTMLGenericFormElementImpl::attach(); - _style->deref(); -} - -bool HTMLSelectElementImpl::encoding(const TQTextCodec* codec, khtml::encodingList& encoded_values, bool) -{ - bool successful = false; - const TQCString enc_name = fixUpfromUnicode(codec, name().string()); - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - - uint i; - const uint itemsSize = items.size(); - for (i = 0; i < itemsSize; ++i) { - if (items[i]->id() == ID_OPTION) { - HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[i]); - if (option->selected()) { - encoded_values += enc_name; - encoded_values += fixUpfromUnicode(codec, option->value().string()); - successful = true; - } - } - } - - // ### this case should not happen. make sure that we select the first option - // in any case. otherwise we have no consistency with the DOM interface. FIXME! - // we return the first one if it was a combobox select - if (!successful && !m_multiple && m_size <= 1 && itemsSize && - (items[0]->id() == ID_OPTION) ) { - HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[0]); - encoded_values += enc_name; - if (option->value().isNull()) - encoded_values += fixUpfromUnicode(codec, option->text().string().stripWhiteSpace()); - else - encoded_values += fixUpfromUnicode(codec, option->value().string()); - successful = true; - } - - return successful; -} - -int HTMLSelectElementImpl::optionToListIndex(int optionIndex) const -{ - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - const int itemsSize = int(items.size()); - if (optionIndex < 0 || optionIndex >= itemsSize) - return -1; - - //See if we're asked for the very last item, and check whether it's an <option> - //to fastpath clear - if ((unsigned int)optionIndex == (m_length - 1) && items[itemsSize - 1]->id() == ID_OPTION) - return itemsSize - 1; - - int listIndex = 0; - int optionIndex2 = 0; - for (; - optionIndex2 < itemsSize && optionIndex2 <= optionIndex; - ++listIndex) { // not a typo! - if (items[listIndex]->id() == ID_OPTION) - ++optionIndex2; - } - --listIndex; - return listIndex; -} - -int HTMLSelectElementImpl::listToOptionIndex(int listIndex) const -{ - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - if (listIndex < 0 || listIndex >= int(items.size()) || - items[listIndex]->id() != ID_OPTION) - return -1; - - int optionIndex = 0; // actual index of option not counting OPTGROUP entries that may be in list - int i; - for (i = 0; i < listIndex; i++) - if (items[i]->id() == ID_OPTION) - optionIndex++; - return optionIndex; -} - -void HTMLSelectElementImpl::recalcListItems() const -{ - NodeImpl* current = firstChild(); - m_listItems.resize(0); - HTMLOptionElementImpl* foundSelected = 0; - m_length = 0; - while(current) { - if (current->id() == ID_OPTGROUP && current->firstChild()) { - // ### what if optgroup contains just comments? don't want one of no options in it... - m_listItems.resize(m_listItems.size()+1); - m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current); - current = current->firstChild(); - } - if (current->id() == ID_OPTION) { - ++m_length; - m_listItems.resize(m_listItems.size()+1); - m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current); - if (!foundSelected && !m_multiple && m_size <= 1) { - foundSelected = static_cast<HTMLOptionElementImpl*>(current); - foundSelected->m_selected = true; - } - else if (foundSelected && !m_multiple && static_cast<HTMLOptionElementImpl*>(current)->selected()) { - foundSelected->m_selected = false; - foundSelected = static_cast<HTMLOptionElementImpl*>(current); - } - } - NodeImpl* const parent = current->parentNode(); - current = current->nextSibling(); - if (!current) { - if (static_cast<const NodeImpl *>(parent) != this) - current = parent->nextSibling(); - } - } - m_recalcListItems = false; -} - -void HTMLSelectElementImpl::childrenChanged() -{ - setRecalcListItems(); - - HTMLGenericFormElementImpl::childrenChanged(); -} - -void HTMLSelectElementImpl::setRecalcListItems() -{ - m_recalcListItems = true; - if (m_render) - static_cast<khtml::RenderSelect*>(m_render)->setOptionsChanged(true); - setChanged(); -} - -void HTMLSelectElementImpl::reset() -{ - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - uint i; - const uint itemsSize = items.size(); - bool anySelected = false; - for (i = 0; i < itemsSize; ++i) { - if (items[i]->id() == ID_OPTION) { - HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[i]); - const bool selected = (!option->getAttribute(ATTR_SELECTED).isNull()); - option->setSelected(selected); - if (selected) - anySelected = true; - } - } - // If this is a single-row SELECT and there is no default selection, jump to first option. - if ( !anySelected && m_size <= 1 ) { - for (i = 0; i < itemsSize; ++i) { - if (items[i]->id() == ID_OPTION) { - static_cast<HTMLOptionElementImpl*>(items[i])->setSelected(true); - break; - } - } - } - if ( m_render ) - static_cast<RenderSelect*>(m_render)->setSelectionChanged(true); - setChanged( true ); -} - -void HTMLSelectElementImpl::notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected) -{ - if (selected && !m_multiple) { - // deselect all other options - TQMemArray<HTMLGenericFormElementImpl*> items = listItems(); - uint i; - const uint itemsSize = items.size(); - for (i = 0; i < itemsSize; ++i) { - if (items[i]->id() == ID_OPTION) - static_cast<HTMLOptionElementImpl*>(items[i])->m_selected = (items[i] == selectedOption); - } - } - if (m_render) - static_cast<RenderSelect*>(m_render)->setSelectionChanged(true); - - setChanged(true); -} - -// ------------------------------------------------------------------------- - -HTMLKeygenElementImpl::HTMLKeygenElementImpl(DocumentImpl* doc, HTMLFormElementImpl* f) - : HTMLSelectElementImpl(doc, f) -{ - const TQStringList keys = KSSLKeyGen::supportedKeySizes(); - TQStringList::ConstIterator i = keys.begin(); - const TQStringList::ConstIterator iEnd = keys.end(); - for ( ; i != iEnd; ++i) { - HTMLOptionElementImpl* const o = new HTMLOptionElementImpl(doc, form()); - addChild(o); - o->addChild(doc->createTextNode(DOMString(*i).implementation())); - } -} - -NodeImpl::Id HTMLKeygenElementImpl::id() const -{ - return ID_KEYGEN; -} - -void HTMLKeygenElementImpl::parseAttribute(AttributeImpl* attr) -{ - switch(attr->id()) - { - case ATTR_CHALLENGE: - break; - default: - // skip HTMLSelectElementImpl parsing! - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -bool HTMLKeygenElementImpl::encoding(const TQTextCodec* codec, khtml::encodingList& encoded_values, bool) -{ - bool successful = false; - const TQCString enc_name = fixUpfromUnicode(codec, name().string()); - - encoded_values += enc_name; - - // pop up the fancy certificate creation dialog here - KSSLKeyGen* const kg = new KSSLKeyGen(getDocument()->view(), "Key Generator", true); - - kg->setKeySize(0); - successful = (TQDialog::Accepted == kg->exec()); - - delete kg; - - encoded_values += "deadbeef"; - - return successful; -} - -// ------------------------------------------------------------------------- - -NodeImpl::Id HTMLOptGroupElementImpl::id() const -{ - return ID_OPTGROUP; -} - -// ------------------------------------------------------------------------- - -HTMLOptionElementImpl::HTMLOptionElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ - m_selected = false; -} - -NodeImpl::Id HTMLOptionElementImpl::id() const -{ - return ID_OPTION; -} - -DOMString HTMLOptionElementImpl::text() const -{ - if (firstChild() && firstChild()->nodeType() == Node::TEXT_NODE) { - if (firstChild()->nextSibling()) { - DOMString ret = ""; - NodeImpl *n = firstChild(); - for (; n; n = n->nextSibling()) { - if (n->nodeType() == Node::TEXT_NODE || - n->nodeType() == Node::CDATA_SECTION_NODE) - ret += n->nodeValue(); - } - return ret; - } - else - return firstChild()->nodeValue(); - } - return ""; -} - -long HTMLOptionElementImpl::index() const -{ - // Let's do this dynamically. Might be a bit slow, but we're sure - // we won't forget to update a member variable in some cases... - TQMemArray<HTMLGenericFormElementImpl*> items = getSelect()->listItems(); - const int l = items.count(); - int optionIndex = 0; - for(int i = 0; i < l; ++i) { - if(items[i]->id() == ID_OPTION) - { - if (static_cast<HTMLOptionElementImpl*>(items[i]) == this) - return optionIndex; - ++optionIndex; - } - } - kdWarning() << "HTMLOptionElementImpl::index(): option not found!" << endl; - return 0; -} - -void HTMLOptionElementImpl::setIndex( long ) -{ - kdWarning() << "Unimplemented HTMLOptionElementImpl::setIndex(long) called" << endl; - // ### -} - -void HTMLOptionElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_SELECTED: - m_selected = (attr->val() != 0); - break; - case ATTR_VALUE: - m_value = attr->value(); - break; - default: - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -DOMString HTMLOptionElementImpl::value() const -{ - if ( !m_value.isNull() ) - return m_value; - // Use the text if the value wasn't set. - return text().string().simplifyWhiteSpace(); -} - -void HTMLOptionElementImpl::setValue(DOMStringImpl* value) -{ - setAttribute(ATTR_VALUE, value); -} - -void HTMLOptionElementImpl::setSelected(bool _selected) -{ - if(m_selected == _selected) - return; - m_selected = _selected; - HTMLSelectElementImpl* const select = getSelect(); - if (select) - select->notifyOptionSelected(this,_selected); -} - -HTMLSelectElementImpl *HTMLOptionElementImpl::getSelect() const -{ - NodeImpl *select = parentNode(); - while (select && select->id() != ID_SELECT) - select = select->parentNode(); - return static_cast<HTMLSelectElementImpl*>(select); -} - -// ------------------------------------------------------------------------- - -HTMLTextAreaElementImpl::HTMLTextAreaElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLGenericFormElementImpl(doc, f) -{ - // DTD requires rows & cols be specified, but we will provide reasonable defaults - m_rows = 2; - m_cols = 20; - m_wrap = ta_Virtual; - m_changed = false; - m_dirtyvalue = true; - m_initialized = false; - m_unsubmittedFormChange = false; -} - -HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl() -{ - if (getDocument()) getDocument()->deregisterMaintainsState(this); -} - -NodeImpl::Id HTMLTextAreaElementImpl::id() const -{ - return ID_TEXTAREA; -} - -DOMString HTMLTextAreaElementImpl::type() const -{ - return "textarea"; -} - -TQString HTMLTextAreaElementImpl::state( ) -{ - return value().string() + (m_unsubmittedFormChange ? 'M' : '.'); -} - -void HTMLTextAreaElementImpl::restoreState(const TQString &state) -{ - setDefaultValue(state.left(state.length()-1)); - m_unsubmittedFormChange = state.endsWith("M"); - // the close() in the rendertree will take care of transferring defaultvalue to 'value' -} - -void HTMLTextAreaElementImpl::select( ) -{ - if (m_render) - static_cast<RenderTextArea*>(m_render)->select(); - onSelect(); -} - -void HTMLTextAreaElementImpl::parseAttribute(AttributeImpl *attr) -{ - switch(attr->id()) - { - case ATTR_ROWS: - m_rows = 0; - if (attr->val()) - m_rows = DOMString(attr->val()).string().toInt(); - if (!m_rows) m_rows = 2; - if (renderer()) - renderer()->setNeedsLayoutAndMinMaxRecalc(); - break; - case ATTR_COLS: - m_cols = 0; - if (attr->val()) - m_cols = DOMString(attr->val()).string().toInt(); - if (!m_cols) m_cols = 20; - if (renderer()) - renderer()->setNeedsLayoutAndMinMaxRecalc(); - break; - case ATTR_WRAP: - // virtual / physical is Netscape extension of HTML 3.0, now deprecated - // soft/ hard / off is recommendation for HTML 4 extension by IE and NS 4 - if ( strcasecmp( attr->value(), "virtual" ) == 0 || strcasecmp( attr->value(), "soft") == 0) - m_wrap = ta_Virtual; - else if ( strcasecmp ( attr->value(), "physical" ) == 0 || strcasecmp( attr->value(), "hard") == 0) - m_wrap = ta_Physical; - else if(strcasecmp( attr->value(), "on" ) == 0) - m_wrap = ta_Physical; - else if(strcasecmp( attr->value(), "off") == 0) - m_wrap = ta_NoWrap; - break; - case ATTR_ACCESSKEY: - break; - case ATTR_ALIGN: - break; - case ATTR_ONSELECT: - setHTMLEventListener(EventImpl::SELECT_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onselect", this)); - break; - case ATTR_ONCHANGE: - setHTMLEventListener(EventImpl::CHANGE_EVENT, - getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this)); - break; - default: - HTMLGenericFormElementImpl::parseAttribute(attr); - } -} - -void HTMLTextAreaElementImpl::attach() -{ - assert(!attached()); - assert(!m_render); - assert(parentNode()); - - RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this); - _style->ref(); - if (parentNode()->renderer() && _style->display() != NONE) { - m_render = new (getDocument()->renderArena()) RenderTextArea(this); - m_render->setStyle(_style); - } - - HTMLGenericFormElementImpl::attach(); - _style->deref(); -} - - -static TQString expandLF(const TQString& s) -{ - // LF -> CRLF - unsigned crs = s.contains( '\n' ); - if (crs == 0) - return s; - unsigned len = s.length(); - - TQString r; - r.reserve(len + crs + 1); - unsigned pos2 = 0; - for(unsigned pos = 0; pos < len; pos++) - { - TQChar c = s.at(pos); - switch(c.unicode()) - { - case '\n': - r[pos2++] = '\r'; - r[pos2++] = '\n'; - break; - - case '\r': - break; - - default: - r[pos2++]= c; - break; - } - } - r.squeeze(); - return r; -} - - -bool HTMLTextAreaElementImpl::encoding(const TQTextCodec* codec, encodingList& encoding, bool) -{ - if (name().isEmpty()) return false; - - encoding += fixUpfromUnicode(codec, name().string()); - encoding += fixUpfromUnicode(codec, expandLF(value().string())); - - return true; -} - -void HTMLTextAreaElementImpl::reset() -{ - setValue(defaultValue()); -} - - -DOMString HTMLTextAreaElementImpl::value() -{ - if ( m_dirtyvalue) { - if ( m_render && m_initialized ) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - m_value = renderArea->text(); - m_dirtyvalue = false; - } else { - m_value = defaultValue().string(); - m_initialized = true; - m_dirtyvalue = false; - } - } - - if ( m_value.isNull() ) return ""; - - return m_value; -} - -void HTMLTextAreaElementImpl::setValue(DOMString _value) -{ - // \r\n -> \n, \r -> \n - TQString str = _value.string().replace( "\r\n", "\n" ); - m_value = str.replace( '\r', '\n' ); - m_dirtyvalue = false; - m_initialized = true; - setChanged(true); -} - -DOMString HTMLTextAreaElementImpl::defaultValue() -{ - DOMString val = ""; - // there may be comments - just grab the text nodes - NodeImpl *n; - for (n = firstChild(); n; n = n->nextSibling()) - if (n->isTextNode()) - val += static_cast<TextImpl*>(n)->data(); - - if (val[0] == '\r' && val[1] == '\n') { - val = val.copy(); - val.remove(0,2); - } - else if (val[0] == '\r' || val[0] == '\n') { - val = val.copy(); - val.remove(0,1); - } - - return val; -} - -void HTMLTextAreaElementImpl::setDefaultValue(DOMString _defaultValue) -{ - // there may be comments - remove all the text nodes and replace them with one - TQPtrList<NodeImpl> toRemove; - NodeImpl *n; - for (n = firstChild(); n; n = n->nextSibling()) - if (n->isTextNode()) - toRemove.append(n); - TQPtrListIterator<NodeImpl> it(toRemove); - int exceptioncode = 0; - for (; it.current(); ++it) { - removeChild(it.current(), exceptioncode); - } - insertBefore(getDocument()->createTextNode(_defaultValue.implementation()),firstChild(), exceptioncode); - setValue(_defaultValue); -} - -void HTMLTextAreaElementImpl::blur() -{ - if(getDocument()->focusNode() == this) - getDocument()->setFocusNode(0); -} - -void HTMLTextAreaElementImpl::focus() -{ - getDocument()->setFocusNode(this); -} - -bool HTMLTextAreaElementImpl::isEditable() -{ - return true; -} - -//Mozilla extensions. -long HTMLTextAreaElementImpl::selectionStart() -{ - if (m_render) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - return renderArea->selectionStart(); - } - - return 0; -} - -long HTMLTextAreaElementImpl::selectionEnd() -{ - if (m_render) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - return renderArea->selectionEnd(); - } - - return 0; -} - -void HTMLTextAreaElementImpl::setSelectionStart(long pos) -{ - if (m_render) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - renderArea->setSelectionStart( pos ); - } -} - -void HTMLTextAreaElementImpl::setSelectionEnd(long pos) -{ - if (m_render) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - renderArea->setSelectionEnd( pos ); - } -} - -void HTMLTextAreaElementImpl::setSelectionRange(long start, long end) -{ - if (m_render) { - RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render ); - renderArea->setSelectionRange( start, end ); - } -} - -long HTMLTextAreaElementImpl::textLength() -{ - return value().length(); -} - -// ------------------------------------------------------------------------- - -HTMLIsIndexElementImpl::HTMLIsIndexElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f) - : HTMLInputElementImpl(doc, f) -{ - m_type = TEXT; - setName("isindex"); -} - -HTMLIsIndexElementImpl::~HTMLIsIndexElementImpl() -{ -} - -NodeImpl::Id HTMLIsIndexElementImpl::id() const -{ - return ID_ISINDEX; -} - -void HTMLIsIndexElementImpl::parseAttribute(AttributeImpl* attr) -{ - // don't call HTMLInputElement::parseAttribute here, as it would - // accept attributes this element does not support - HTMLGenericFormElementImpl::parseAttribute(attr); -} - -DOMString HTMLIsIndexElementImpl::prompt() const -{ - // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created. - // So we have to look at the previous sibling to find the prompt text - DOM::NodeImpl* const prev = previousSibling(); - if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE) - return prev->nodeValue(); - return ""; -} - -void HTMLIsIndexElementImpl::setPrompt(const DOMString& str) -{ - // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created. - // So we have to look at the previous sibling to find the prompt text - int exceptioncode = 0; - DOM::NodeImpl* const prev = previousSibling(); - if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE) - static_cast<DOM::TextImpl *>(prev)->setData(str, exceptioncode); -} - -// ------------------------------------------------------------------------- - |