#undef FORMS_DEBUG
#include "html/html_formimpl.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include "html/html_documentimpl.h"
#include "html_imageimpl.h"
#include "khtml_settings.h"
#include "misc/htmlhashes.h"
#include "misc/formdata.h"
#include "css/cssstyleselector.h"
#include "css/cssproperties.h"
#include "css/csshelper.h"
#include "xml/dom_textimpl.h"
#include "xml/dom2_eventsimpl.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 <klocale.h>
#include <netaccess.h>
#include <kfileitem.h>
#include <qfile.h>
#include <qtextcodec.h>
#include <qstring.h>
#include <ksslkeygen.h>
#include <assert.h>
using namespace khtml;
namespace DOM {
struct FormDataListItem {
FormDataListItem(const QCString &data) : m_data(data) { }
FormDataListItem(const QString &path) : m_path(path) { }
QString m_path;
QCString m_data;
};
class FormDataList {
public:
FormDataList(QTextCodec *);
void appendData(const DOMString &key, const DOMString &value)
{ appendString(key.string()); appendString(value.string()); }
void appendData(const DOMString &key, const QString &value)
{ appendString(key.string()); appendString(value); }
void appendData(const DOMString &key, const QCString &value)
{ appendString(key.string()); appendString(value); }
void appendData(const DOMString &key, int value)
{ appendString(key.string()); appendString(QString::number(value)); }
void appendFile(const DOMString &key, const DOMString &filename);
QValueListConstIterator<FormDataListItem> begin() const
{ return m_list.begin(); }
QValueListConstIterator<FormDataListItem> end() const
{ return m_list.end(); }
private:
void appendString(const QCString &s);
void appendString(const QString &s);
QTextCodec *m_codec;
QValueList<FormDataListItem> m_list;
};
HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc)
: HTMLElementImpl(doc)
{
collectionInfo = 0;
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 = "----------0xKhTmLbOuNdArY";
m_acceptcharset = "UNKNOWN";
m_malformed = false;
}
HTMLFormElementImpl::~HTMLFormElementImpl()
{
delete collectionInfo;
for (unsigned i = 0; i < formElements.count(); ++i)
formElements[i]->m_form = 0;
for (unsigned i = 0; i < dormantFormElements.count(); ++i)
dormantFormElements[i]->m_form = 0;
for (unsigned i = 0; i < imgElements.count(); ++i)
imgElements[i]->m_form = 0;
}
NodeImpl::Id HTMLFormElementImpl::id() const
{
return ID_FORM;
}
#if APPLE_CHANGES
bool HTMLFormElementImpl::formWouldHaveSecureSubmission(const DOMString &url)
{
if (url.isNull()) {
return false;
}
return getDocument()->completeURL(url.string()).startsWith("https:", false);
}
#endif
void HTMLFormElementImpl::attach()
{
HTMLElementImpl::attach();
if (getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->addNamedImageOrForm(oldNameAttr);
document->addNamedImageOrForm(oldIdAttr);
}
#if APPLE_CHANGES
if (formWouldHaveSecureSubmission(m_url))
getDocument()->secureFormAdded();
#endif
}
void HTMLFormElementImpl::detach()
{
if (getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->removeNamedImageOrForm(oldNameAttr);
document->removeNamedImageOrForm(oldIdAttr);
}
HTMLElementImpl::detach();
}
long HTMLFormElementImpl::length() const
{
int len = 0;
for (unsigned i = 0; i < formElements.count(); ++i)
if (formElements[i]->isEnumeratable())
++len;
return len;
}
#if APPLE_CHANGES
void HTMLFormElementImpl::submitClick()
{
bool submitFound = false;
for (unsigned i = 0; i < formElements.count(); ++i) {
if (formElements[i]->id() == ID_INPUT) {
HTMLInputElementImpl *element = static_cast<HTMLInputElementImpl *>(formElements[i]);
if (element->isSuccessfulSubmitButton() && element->renderer()) {
submitFound = true;
element->click(false);
break;
}
}
}
if (!submitFound) prepareSubmit();
}
#endif // APPLE_CHANGES
static QCString encodeCString(const QCString& e)
{
static const char *safe = "-._*";
int elen = e.length();
QCString encoded(( elen+e.contains( '\n' ) )*3+1);
int enclen = 0;
for(int pos = 0; pos < elen; pos++) {
unsigned char c = e[pos];
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' || ( c == '\r' && e[pos+1] != '\n' ) )
{
encoded[enclen++] = '%';
encoded[enclen++] = '0';
encoded[enclen++] = 'D';
encoded[enclen++] = '%';
encoded[enclen++] = '0';
encoded[enclen++] = 'A';
}
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;
}
static QCString fixLineBreaks(const QCString &s)
{
unsigned newLen = 0;
const char *p = s.data();
while (char c = *p++) {
if (c == '\r') {
if (*p != '\n') {
newLen += 2;
}
} else if (c == '\n') {
newLen += 2;
} else {
newLen += 1;
}
}
if (newLen == s.length()) {
return s;
}
p = s.data();
QCString result(newLen + 1);
char *q = result.data();
while (char c = *p++) {
if (c == '\r') {
if (*p != '\n') {
*q++ = '\r';
*q++ = '\n';
}
} else if (c == '\n') {
*q++ = '\r';
*q++ = '\n';
} else {
*q++ = c;
}
}
return result;
}
#if !APPLE_CHANGES
void HTMLFormElementImpl::i18nData()
{
QString foo1 = i18n( "You're about to send data to the Internet "
"via an unencrypted connection. It might be possible "
"for others to see this information.\n"
"Do you want to continue?");
QString foo2 = i18n("KDE Web browser");
QString foo3 = i18n("When you send a password unencrypted to the Internet, "
"it might be possible for others to capture it as plain text.\n"
"Do you want to continue?");
QString foo5 = i18n("Your data submission is redirected to "
"an insecure site. The data is sent unencrypted.\n"
"Do you want to continue?");
QString foo6 = i18n("The page contents expired. You can repost the form"
"data by using <a href=\"javascript:go(0);\">Reload</a>");
}
#endif
bool HTMLFormElementImpl::formData(FormData &form_data) const
{
#ifdef FORMS_DEBUG
kdDebug( 6030 ) << "form: formData()" << endl;
#endif
QCString enc_string = "";
QString str = m_acceptcharset.string();
str.replace(',', ' ');
QStringList charsets = QStringList::split(' ', str);
QTextCodec* codec = 0;
KHTMLPart *part = getDocument()->part();
for ( QStringList::Iterator it = charsets.begin(); it != charsets.end(); ++it )
{
QString enc = (*it);
if(enc.contains("UNKNOWN"))
{
enc = "ISO-8859-1";
if (part)
enc = part->encoding();
}
if((codec = KGlobal::charsets()->codecForName(enc.latin1())))
break;
}
if(!codec)
codec = QTextCodec::codecForLocale();
#if !APPLE_CHANGES
QStringList fileUploads;
#endif
for (unsigned i = 0; i < formElements.count(); ++i) {
HTMLGenericFormElementImpl* current = formElements[i];
FormDataList lst(codec);
if (!current->disabled() && current->appendFormData(lst, m_multipart))
{
for(QValueListConstIterator<FormDataListItem> it = lst.begin(); it != lst.end(); ++it )
{
if (!m_multipart)
{
if ( enc_string.isEmpty() && (*it).m_data == "isindex" ) {
++it;
enc_string += encodeCString( (*it).m_data );
}
else {
if(!enc_string.isEmpty())
enc_string += '&';
enc_string += encodeCString((*it).m_data);
enc_string += "=";
++it;
enc_string += encodeCString((*it).m_data);
}
}
else
{
QCString hstr("--");
hstr += m_boundary.string().latin1();
hstr += "\r\n";
hstr += "Content-Disposition: form-data; name=\"";
hstr += (*it).m_data.data();
hstr += "\"";
if (current->nodeType() == Node::ELEMENT_NODE && current->id() == ID_INPUT &&
static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE)
{
QString path = static_cast<HTMLInputElementImpl*>(current)->value().string();
#if !APPLE_CHANGES
if (path.length()) fileUploads << path;
#endif
hstr += "; filename=\"";
hstr += codec->fromUnicode(path.mid(path.findRev('/') + 1));
hstr += "\"";
if(!static_cast<HTMLInputElementImpl*>(current)->value().isEmpty())
{
#if APPLE_CHANGES
QString mimeType = part ? KWQ(part)->mimeTypeForFileName(path) : QString();
#else
KMimeType::Ptr ptr = KMimeType::findByURL(KURL(path));
QString mimeType = ptr->name();
#endif
if (!mimeType.isEmpty()) {
hstr += "\r\nContent-Type: ";
hstr += mimeType.ascii();
}
}
}
hstr += "\r\n\r\n";
++it;
form_data.appendData(hstr.data(), hstr.length());
#if APPLE_CHANGES
const FormDataListItem &item = *it;
size_t dataSize = item.m_data.size();
if (dataSize != 0)
form_data.appendData(item.m_data, dataSize - 1);
else if (!item.m_path.isEmpty())
form_data.appendFile(item.m_path);
#else
form_data.appendData((*it).m_data, (*it).m_data.size() - 1);
#endif
form_data.appendData("\r\n", 2);
}
}
}
}
#if !APPLE_CHANGES
if (fileUploads.count()) {
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);
if (result == KMessageBox::Cancel) {
return false;
}
}
#endif
if (m_multipart)
enc_string = ("--" + m_boundary.string() + "--\r\n").ascii();
form_data.appendData(enc_string.data(), enc_string.length());
return true;
}
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;
}
}
void HTMLFormElementImpl::setBoundary( const DOMString& bound )
{
m_boundary = bound;
}
bool HTMLFormElementImpl::prepareSubmit()
{
KHTMLPart *part = getDocument()->part();
if(m_insubmit || !part || part->onlyLocalReferences())
return m_insubmit;
m_insubmit = true;
m_doingsubmit = false;
if ( dispatchHTMLEvent(EventImpl::SUBMIT_EVENT,false,true) && !m_doingsubmit )
m_doingsubmit = true;
m_insubmit = false;
if ( m_doingsubmit )
submit(true);
return m_doingsubmit;
}
void HTMLFormElementImpl::submit( bool activateSubmitButton )
{
KHTMLView *view = getDocument()->view();
KHTMLPart *part = getDocument()->part();
if (!view || !part) {
return;
}
if ( m_insubmit ) {
m_doingsubmit = true;
return;
}
m_insubmit = true;
#ifdef FORMS_DEBUG
kdDebug( 6030 ) << "submitting!" << endl;
#endif
HTMLGenericFormElementImpl* firstSuccessfulSubmitButton = 0;
bool needButtonActivation = activateSubmitButton;
#if APPLE_CHANGES
KWQ(part)->clearRecordedFormValues();
#endif
for (unsigned i = 0; i < formElements.count(); ++i) {
HTMLGenericFormElementImpl* current = formElements[i];
#if APPLE_CHANGES
if (current->id() == ID_INPUT) {
HTMLInputElementImpl *input = static_cast<HTMLInputElementImpl*>(current);
if (input->inputType() == HTMLInputElementImpl::TEXT
|| input->inputType() == HTMLInputElementImpl::PASSWORD
|| input->inputType() == HTMLInputElementImpl::SEARCH)
{
KWQ(part)->recordFormValue(input->name().string(), input->value().string(), this);
if (input->renderer() && input->inputType() == HTMLInputElementImpl::SEARCH)
static_cast<RenderLineEdit*>(input->renderer())->addSearchResult();
}
}
#else
if (current->id() == ID_INPUT &&
static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT &&
static_cast<HTMLInputElementImpl*>(current)->autoComplete() )
{
HTMLInputElementImpl *input = static_cast<HTMLInputElementImpl *>(current);
view->addFormCompletionItem(input->name().string(), input->value().string());
}
#endif
if (needButtonActivation) {
if (current->isActivatedSubmit()) {
needButtonActivation = false;
} else if (firstSuccessfulSubmitButton == 0 && current->isSuccessfulSubmitButton()) {
firstSuccessfulSubmitButton = current;
}
}
}
if (needButtonActivation && firstSuccessfulSubmitButton) {
firstSuccessfulSubmitButton->setActivatedSubmit(true);
}
FormData form_data;
if (formData(form_data)) {
if(m_post) {
part->submitForm( "post", m_url.string(), form_data,
m_target.string(),
enctype().string(),
boundary().string() );
}
else {
part->submitForm( "get", m_url.string(), form_data,
m_target.string() );
}
}
if (needButtonActivation && firstSuccessfulSubmitButton) {
firstSuccessfulSubmitButton->setActivatedSubmit(false);
}
m_doingsubmit = m_insubmit = false;
}
void HTMLFormElementImpl::reset( )
{
KHTMLPart *part = getDocument()->part();
if(m_inreset || !part) return;
m_inreset = true;
#ifdef FORMS_DEBUG
kdDebug( 6030 ) << "reset pressed!" << endl;
#endif
if ( !dispatchHTMLEvent(EventImpl::RESET_EVENT,true, true) ) {
m_inreset = false;
return;
}
for (unsigned i = 0; i < formElements.count(); ++i)
formElements[i]->reset();
m_inreset = false;
}
void HTMLFormElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_ACTION:
#if APPLE_CHANGES
{
bool oldURLWasSecure = formWouldHaveSecureSubmission(m_url);
#endif
m_url = khtml::parseURL(attr->value());
#if APPLE_CHANGES
bool newURLIsSecure = formWouldHaveSecureSubmission(m_url);
if (m_attached && (oldURLWasSecure != newURLIsSecure))
if (newURLIsSecure)
getDocument()->secureFormAdded();
else
getDocument()->secureFormRemoved();
}
#endif
break;
case ATTR_TARGET:
m_target = attr->value();
break;
case ATTR_METHOD:
if ( strcasecmp( attr->value(), "post" ) == 0 )
m_post = true;
else if ( strcasecmp( attr->value(), "get" ) == 0 )
m_post = false;
break;
case ATTR_ENCTYPE:
setEnctype( attr->value() );
break;
case ATTR_ACCEPT_CHARSET:
m_acceptcharset = attr->value();
break;
case ATTR_ACCEPT:
break;
case ATTR_AUTOCOMPLETE:
m_autocomplete = strcasecmp( attr->value(), "off" );
break;
case ATTR_ONSUBMIT:
setHTMLEventListener(EventImpl::SUBMIT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONRESET:
setHTMLEventListener(EventImpl::RESET_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_NAME:
{
QString newNameAttr = attr->value().string();
if (attached() && getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->removeNamedImageOrForm(oldNameAttr);
document->addNamedImageOrForm(newNameAttr);
}
oldNameAttr = newNameAttr;
}
break;
case ATTR_ID:
{
QString newIdAttr = attr->value().string();
if (attached() && getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->removeNamedImageOrForm(oldIdAttr);
document->addNamedImageOrForm(newIdAttr);
}
oldIdAttr = newIdAttr;
}
default:
HTMLElementImpl::parseHTMLAttribute(attr);
}
}
void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller )
{
for (unsigned i = 0; i < formElements.count(); ++i) {
HTMLGenericFormElementImpl *current = formElements[i];
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);
}
}
}
template<class T> static void appendToVector(QPtrVector<T> &vec, T *item)
{
unsigned size = vec.size();
unsigned count = vec.count();
if (size == count)
vec.resize(size == 0 ? 8 : (int)(size * 1.5));
vec.insert(count, item);
}
template<class T> static void removeFromVector(QPtrVector<T> &vec, T *item)
{
int pos = vec.findRef(item);
int count = vec.count();
if (pos < 0)
return;
for (int i = pos; i < count - 1; i++) {
vec.insert(i, vec[i+1]);
}
vec.remove(count - 1);
}
void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl *e)
{
appendToVector(formElements, e);
removeFromVector(dormantFormElements, e);
}
void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl *e)
{
removeFromVector(formElements, e);
removeFromVector(dormantFormElements, e);
}
void HTMLFormElementImpl::makeFormElementDormant(HTMLGenericFormElementImpl *e)
{
appendToVector(dormantFormElements, e);
removeFromVector(formElements, e);
}
bool HTMLFormElementImpl::isURLAttribute(AttributeImpl *attr) const
{
return attr->id() == ATTR_ACTION;
}
void HTMLFormElementImpl::registerImgElement(HTMLImageElementImpl *e)
{
appendToVector(imgElements, e);
}
void HTMLFormElementImpl::removeImgElement(HTMLImageElementImpl *e)
{
removeFromVector(imgElements, e);
}
HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLElementImpl(doc)
{
m_disabled = m_readOnly = false;
m_name = 0;
m_dormant = false;
if (f)
m_form = f;
else
m_form = getForm();
if (m_form)
m_form->registerFormElement(this);
}
HTMLGenericFormElementImpl::~HTMLGenericFormElementImpl()
{
if (m_form)
m_form->removeFormElement(this);
if (m_name) m_name->deref();
}
void HTMLGenericFormElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_NAME:
break;
case ATTR_DISABLED:
setDisabled( !attr->isNull() );
break;
case ATTR_READONLY:
{
bool m_oldreadOnly = m_readOnly;
m_readOnly = !attr->isNull();
if (m_oldreadOnly != m_readOnly) setChanged();
break;
}
default:
HTMLElementImpl::parseHTMLAttribute(attr);
}
}
void HTMLGenericFormElementImpl::attach()
{
assert(!attached());
if (!m_form) {
m_form = getForm();
if (m_form)
m_form->registerFormElement(this);
}
HTMLElementImpl::attach();
if (m_render) {
m_render->updateFromElement();
if (getDocument()->focusNode() == this && m_render->isWidget() &&
static_cast<RenderWidget*>(renderer())->widget())
static_cast<RenderWidget*>(renderer())->widget()->setFocus();
}
}
void HTMLGenericFormElementImpl::insertedIntoDocument()
{
if (m_form && m_dormant)
m_form->registerFormElement(this);
m_dormant = false;
HTMLElementImpl::insertedIntoDocument();
}
void HTMLGenericFormElementImpl::removedFromDocument()
{
if (m_form)
m_form->makeFormElementDormant(this);
m_dormant = true;
HTMLElementImpl::removedFromDocument();
}
HTMLFormElementImpl *HTMLGenericFormElementImpl::getForm() const
{
NodeImpl *p = parentNode();
while(p)
{
if( p->id() == ID_FORM )
return static_cast<HTMLFormElementImpl *>(p);
p = p->parentNode();
}
#ifdef FORMS_DEBUG
kdDebug( 6030 ) << "couldn't find form!" << endl;
#endif
return 0;
}
DOMString HTMLGenericFormElementImpl::name() const
{
if (m_name) return m_name;
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();
if (m_name) m_name->ref();
}
void HTMLGenericFormElementImpl::onSelect()
{
dispatchHTMLEvent(EventImpl::SELECT_EVENT,true,false);
}
void HTMLGenericFormElementImpl::onChange()
{
dispatchHTMLEvent(EventImpl::CHANGE_EVENT,true,false);
}
bool HTMLGenericFormElementImpl::disabled() const
{
return m_disabled;
}
void HTMLGenericFormElementImpl::setDisabled( bool _disabled )
{
if ( m_disabled != _disabled ) {
m_disabled = _disabled;
setChanged();
}
}
void HTMLGenericFormElementImpl::recalcStyle( StyleChange ch )
{
HTMLElementImpl::recalcStyle( ch );
if (m_render )
m_render->updateFromElement();
}
bool HTMLGenericFormElementImpl::isFocusable() const
{
if (!m_render || (m_render->style() && m_render->style()->visibility() != VISIBLE) || m_render->width() == 0 || m_render->height() == 0)
return false;
return true;
}
bool HTMLGenericFormElementImpl::isKeyboardFocusable() const
{
if (isFocusable()) {
if (m_render->isWidget()) {
return static_cast<RenderWidget*>(m_render)->widget() &&
(static_cast<RenderWidget*>(m_render)->widget()->focusPolicy() & QWidget::TabFocus);
}
if (getDocument()->part())
return getDocument()->part()->tabsToAllControls();
}
return false;
}
bool HTMLGenericFormElementImpl::isMouseFocusable() const
{
if (isFocusable()) {
if (m_render->isWidget()) {
return static_cast<RenderWidget*>(m_render)->widget() &&
(static_cast<RenderWidget*>(m_render)->widget()->focusPolicy() & QWidget::ClickFocus);
}
#if APPLE_CHANGES
return false;
#else
return true;
#endif
}
return false;
}
void HTMLGenericFormElementImpl::defaultEventHandler(EventImpl *evt)
{
if (evt->target()==this)
{
KHTMLPart *part = getDocument()->part();
if (evt->id()==EventImpl::DOMFOCUSIN_EVENT && isEditable() && part && m_render && m_render->isWidget()) {
KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(part->browserExtension());
QWidget *widget = static_cast<RenderWidget*>(m_render)->widget();
if (ext)
ext->editableWidgetFocused(widget);
}
#if APPLE_CHANGES
#else
if (evt->id()==EventImpl::KEYDOWN_EVENT ||
evt->id()==EventImpl::KEYUP_EVENT)
{
KeyboardEventImpl * k = static_cast<KeyboardEventImpl *>(evt);
if (k->keyVal() == QChar('\n').unicode() && m_render && m_render->isWidget() && k->qKeyEvent)
QApplication::sendEvent(static_cast<RenderWidget *>(m_render)->widget(), k->qKeyEvent);
}
#endif
if (evt->id()==EventImpl::DOMFOCUSOUT_EVENT && isEditable() && part && m_render && m_render->isWidget()) {
KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(part->browserExtension());
QWidget *widget = static_cast<RenderWidget*>(m_render)->widget();
if (ext)
ext->editableWidgetBlurred(widget);
}
}
HTMLElementImpl::defaultEventHandler(evt);
}
bool HTMLGenericFormElementImpl::isEditable()
{
return false;
}
const char stateSeparator = '&';
const char stateEscape = '<';
static const char stateSeparatorMarker[] = "<A";
static const char stateEscapeMarker[] = "<<";
static QString encodedElementName(QString str)
{
int sepLoc = str.find(stateSeparator);
int escLoc = str.find(stateSeparator);
if (sepLoc >= 0 || escLoc >= 0) {
QString newStr = str;
while (escLoc >= 0) {
newStr.replace(escLoc, 1, stateEscapeMarker);
escLoc = str.find(stateSeparator, escLoc+1);
}
while (sepLoc >= 0) {
newStr.replace(sepLoc, 1, stateSeparatorMarker);
sepLoc = str.find(stateSeparator, sepLoc+1);
}
return newStr;
} else {
return str;
}
}
QString HTMLGenericFormElementImpl::state( )
{
return encodedElementName(name().string()) + stateSeparator + type().string() + stateSeparator;
}
QString HTMLGenericFormElementImpl::findMatchingState(QStringList &states)
{
QString encName = encodedElementName(name().string());
QString typeStr = type().string();
for (QStringList::Iterator it = states.begin(); it != states.end(); ++it) {
QString state = *it;
int sep1 = state.find(stateSeparator);
int sep2 = state.find(stateSeparator, sep1+1);
assert(sep1 >= 0);
assert(sep2 >= 0);
QString nameAndType = state.left(sep2);
if (encName.length() + typeStr.length() + 1 == (uint)sep2
&& nameAndType.startsWith(encName)
&& nameAndType.endsWith(typeStr))
{
states.remove(it);
return state.mid(sep2+1);
}
}
return QString::null;
}
HTMLButtonElementImpl::HTMLButtonElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f)
{
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::parseHTMLAttribute(HTMLAttributeImpl *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;
break;
case ATTR_ACCESSKEY:
break;
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::FOCUS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBLUR:
setHTMLEventListener(EventImpl::BLUR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
void HTMLButtonElementImpl::defaultEventHandler(EventImpl *evt)
{
if (m_type != BUTTON && (evt->id() == EventImpl::DOMACTIVATE_EVENT)) {
if(m_form && m_type == SUBMIT) {
m_activeSubmit = true;
m_form->prepareSubmit();
m_activeSubmit = false; }
if(m_form && m_type == RESET) m_form->reset();
}
HTMLGenericFormElementImpl::defaultEventHandler(evt);
}
bool HTMLButtonElementImpl::isSuccessfulSubmitButton() const
{
return m_type == SUBMIT && !m_disabled;
}
bool HTMLButtonElementImpl::isActivatedSubmit() const
{
return m_activeSubmit;
}
void HTMLButtonElementImpl::setActivatedSubmit(bool flag)
{
m_activeSubmit = flag;
}
bool HTMLButtonElementImpl::appendFormData(FormDataList& encoding, bool )
{
if (m_type != SUBMIT || name().isEmpty() || !m_activeSubmit)
return false;
encoding.appendData(name(), m_currValue);
return true;
}
void HTMLButtonElementImpl::click(bool sendMouseEvents)
{
#if APPLE_CHANGES
QWidget *widget;
if (renderer() && (widget = static_cast<RenderWidget *>(renderer())->widget())) {
static_cast<QButton *>(widget)->click(sendMouseEvents);
}
else
#endif
HTMLGenericFormElementImpl::click(sendMouseEvents);
}
void HTMLButtonElementImpl::accessKeyAction(bool sendToAnyElement)
{
click(sendToAnyElement);
}
HTMLFieldSetElementImpl::HTMLFieldSetElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f)
{
}
HTMLFieldSetElementImpl::~HTMLFieldSetElementImpl()
{
}
bool HTMLFieldSetElementImpl::isFocusable() const
{
return false;
}
NodeImpl::Id HTMLFieldSetElementImpl::id() const
{
return ID_FIELDSET;
}
DOMString HTMLFieldSetElementImpl::type() const
{
return "fieldset";
}
RenderObject* HTMLFieldSetElementImpl::createRenderer(RenderArena* arena, RenderStyle* style)
{
return new (arena) RenderFieldset(this);
}
HTMLInputElementImpl::HTMLInputElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f), m_imageLoader(0), m_valueMatchesRenderer(false)
{
m_type = TEXT;
m_maxLen = -1;
m_size = 20;
m_checked = false;
m_defaultChecked = false;
m_useDefaultChecked = true;
m_haveType = false;
m_activeSubmit = false;
m_autocomplete = true;
m_inited = false;
xPos = 0;
yPos = 0;
#if APPLE_CHANGES
m_maxResults = -1;
#endif
if ( m_form )
m_autocomplete = f->autoComplete();
}
HTMLInputElementImpl::~HTMLInputElementImpl()
{
if (getDocument()) getDocument()->deregisterMaintainsState(this);
delete m_imageLoader;
}
NodeImpl::Id HTMLInputElementImpl::id() const
{
return ID_INPUT;
}
void HTMLInputElementImpl::setType(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;
#if APPLE_CHANGES
else if ( strcasecmp( t, "search" ) == 0 )
newType = SEARCH;
else if ( strcasecmp( t, "range" ) == 0 )
newType = RANGE;
#endif
else
newType = TEXT;
if (m_type != newType) {
if (newType == FILE && m_haveType) {
setAttribute(ATTR_TYPE, type());
} else {
bool wasAttached = m_attached;
if (wasAttached)
detach();
bool didStoreValue = storesValueSeparateFromAttribute();
m_type = newType;
bool willStoreValue = storesValueSeparateFromAttribute();
if (didStoreValue && !willStoreValue && !m_value.isNull()) {
setAttribute(ATTR_VALUE, m_value);
m_value = DOMString();
}
if (!didStoreValue && willStoreValue) {
m_value = getAttribute(ATTR_VALUE);
}
if (wasAttached)
attach();
}
}
m_haveType = true;
}
DOMString HTMLInputElementImpl::type() const
{
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";
#if APPLE_CHANGES
case SEARCH: return "search";
case RANGE: return "range";
#endif
case ISINDEX: return "";
}
return "";
}
QString HTMLInputElementImpl::state( )
{
assert(m_type != PASSWORD);
QString state = HTMLGenericFormElementImpl::state();
switch (m_type) {
case CHECKBOX:
case RADIO:
return state + (checked() ? "on" : "off");
default:
return state + value().string()+'.'; }
}
void HTMLInputElementImpl::restoreState(QStringList &states)
{
assert(m_type != PASSWORD);
QString state = HTMLGenericFormElementImpl::findMatchingState(states);
if (state.isNull()) return;
switch (m_type) {
case CHECKBOX:
case RADIO:
setChecked((state == "on"));
break;
default:
setValue(DOMString(state.left(state.length()-1)));
break;
}
}
void HTMLInputElementImpl::select( )
{
if(!m_render) return;
switch (m_type) {
case FILE:
static_cast<RenderFileButton*>(m_render)->select();
break;
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
#endif
case TEXT:
static_cast<RenderLineEdit*>(m_render)->select();
break;
case BUTTON:
case CHECKBOX:
case HIDDEN:
case IMAGE:
case ISINDEX:
case RADIO:
#if APPLE_CHANGES
case RANGE:
#endif
case RESET:
case SUBMIT:
break;
}
}
void HTMLInputElementImpl::click(bool sendMouseEvents)
{
switch (inputType()) {
case HIDDEN:
break;
case CHECKBOX:
case RADIO:
case SUBMIT:
case RESET:
case BUTTON:
#if APPLE_CHANGES
{
QWidget *widget;
if (renderer() && (widget = static_cast<RenderWidget *>(renderer())->widget())) {
static_cast<QButton *>(widget)->click(sendMouseEvents);
break;
}
}
#endif
HTMLGenericFormElementImpl::click(sendMouseEvents);
break;
case FILE:
#if APPLE_CHANGES
if (renderer()) {
static_cast<RenderFileButton *>(renderer())->click(sendMouseEvents);
break;
}
#endif
HTMLGenericFormElementImpl::click(sendMouseEvents);
break;
case IMAGE:
case ISINDEX:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
case RANGE:
#endif
case TEXT:
HTMLGenericFormElementImpl::click(sendMouseEvents);
break;
}
}
void HTMLInputElementImpl::accessKeyAction(bool sendToAnyElement)
{
switch (inputType()) {
case HIDDEN:
break;
case TEXT:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
#endif
case ISINDEX:
focus();
break;
case CHECKBOX:
case RADIO:
case SUBMIT:
case RESET:
case IMAGE:
case BUTTON:
case FILE:
#if APPLE_CHANGES
case RANGE:
#endif
focus();
click(sendToAnyElement);
break;
}
}
bool HTMLInputElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
{
switch (attr) {
case ATTR_WIDTH:
case ATTR_HEIGHT:
case ATTR_VSPACE:
case ATTR_HSPACE:
result = eUniversal;
return false;
case ATTR_ALIGN:
result = eReplaced; return false;
default:
break;
}
return HTMLElementImpl::mapToEntry(attr, result);
}
void HTMLInputElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_AUTOCOMPLETE:
m_autocomplete = strcasecmp( attr->value(), "off" );
break;
case ATTR_TYPE:
setType(attr->value());
if (m_type != IMAGE && m_imageLoader) {
delete m_imageLoader;
m_imageLoader = 0;
}
break;
case ATTR_VALUE:
if (m_value.isNull())
setChanged();
m_valueMatchesRenderer = false;
break;
case ATTR_CHECKED:
m_defaultChecked = !attr->isNull();
if (m_useDefaultChecked) {
setChecked(m_defaultChecked);
m_useDefaultChecked = true;
}
break;
case ATTR_MAXLENGTH:
m_maxLen = !attr->isNull() ? attr->value().toInt() : -1;
setChanged();
break;
case ATTR_SIZE:
m_size = !attr->isNull() ? attr->value().toInt() : 20;
break;
case ATTR_ALT:
if (m_render && m_type == IMAGE)
static_cast<RenderImage*>(m_render)->updateAltText();
break;
case ATTR_SRC:
if (m_render && m_type == IMAGE) {
if (!m_imageLoader)
m_imageLoader = new HTMLImageLoader(this);
m_imageLoader->updateFromElement();
}
break;
case ATTR_USEMAP:
case ATTR_ACCESSKEY:
break;
case ATTR_VSPACE:
addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
break;
case ATTR_HSPACE:
addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
break;
case ATTR_ALIGN:
addHTMLAlignment(attr);
break;
case ATTR_WIDTH:
addCSSLength(attr, CSS_PROP_WIDTH, attr->value() );
break;
case ATTR_HEIGHT:
addCSSLength(attr, CSS_PROP_HEIGHT, attr->value() );
break;
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::FOCUS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBLUR:
setHTMLEventListener(EventImpl::BLUR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONSELECT:
setHTMLEventListener(EventImpl::SELECT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCHANGE:
setHTMLEventListener(EventImpl::CHANGE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONINPUT:
setHTMLEventListener(EventImpl::INPUT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
#if APPLE_CHANGES
case ATTR_ONSEARCH:
setHTMLEventListener(EventImpl::SEARCH_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_RESULTS:
m_maxResults = !attr->isNull() ? attr->value().toInt() : -1;
case ATTR_AUTOSAVE:
case ATTR_INCREMENTAL:
case ATTR_PLACEHOLDER:
case ATTR_MIN:
case ATTR_MAX:
case ATTR_PRECISION:
setChanged();
break;
#endif
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
bool HTMLInputElementImpl::rendererIsNeeded(RenderStyle *style)
{
switch(m_type)
{
case TEXT:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
case RANGE:
#endif
case ISINDEX:
case CHECKBOX:
case RADIO:
case SUBMIT:
case IMAGE:
case RESET:
case FILE:
case BUTTON: return HTMLGenericFormElementImpl::rendererIsNeeded(style);
case HIDDEN: return false;
}
assert(false);
return false;
}
RenderObject *HTMLInputElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
switch(m_type)
{
case TEXT:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
#endif
case ISINDEX: return new (arena) RenderLineEdit(this);
case CHECKBOX: return new (arena) RenderCheckBox(this);
case RADIO: return new (arena) RenderRadioButton(this);
case SUBMIT: return new (arena) RenderSubmitButton(this);
case IMAGE: return new (arena) RenderImageButton(this);
case RESET: return new (arena) RenderResetButton(this);
case FILE: return new (arena) RenderFileButton(this);
case BUTTON: return new (arena) RenderPushButton(this);
#if APPLE_CHANGES
case RANGE: return new (arena) RenderSlider(this);
#endif
case HIDDEN: break;
}
assert(false);
return 0;
}
void HTMLInputElementImpl::attach()
{
if (!m_inited) {
if (!m_haveType)
setType(getAttribute(ATTR_TYPE));
DOMString val = getAttribute(ATTR_VALUE);
if ((uint) m_type <= ISINDEX && !val.isEmpty()) {
QString nvalue;
for (unsigned int i = 0; i < val.length(); ++i)
if (val[i] >= ' ')
nvalue += val[i];
if (val.length() != nvalue.length())
setAttribute(ATTR_VALUE, nvalue);
}
m_defaultChecked = (!getAttribute(ATTR_CHECKED).isNull());
m_inited = true;
}
if (hasMappedAttributes() && m_type != HIDDEN && m_type != IMAGE && !getAttribute(ATTR_WIDTH).isEmpty()) {
int excCode;
removeAttribute(ATTR_WIDTH, excCode);
}
HTMLGenericFormElementImpl::attach();
if (m_type == IMAGE) {
if (!m_imageLoader)
m_imageLoader = new HTMLImageLoader(this);
m_imageLoader->updateFromElement();
if (renderer()) {
RenderImage* imageObj = static_cast<RenderImage*>(renderer());
imageObj->setImage(m_imageLoader->image());
}
}
#if APPLE_CHANGES
if (m_type == PASSWORD)
getDocument()->passwordFieldAdded();
#endif
}
void HTMLInputElementImpl::detach()
{
HTMLGenericFormElementImpl::detach();
m_valueMatchesRenderer = false;
}
DOMString HTMLInputElementImpl::altText() const
{
DOMString alt = getAttribute( ATTR_ALT );
if ( alt.isNull() )
alt = getAttribute( ATTR_TITLE );
if ( alt.isNull() )
alt = getAttribute( ATTR_VALUE );
if ( alt.isEmpty() )
#if APPLE_CHANGES
alt = inputElementAltText();
#else
alt = i18n( "Submit" );
#endif
return alt;
}
bool HTMLInputElementImpl::isSuccessfulSubmitButton() const
{
return !m_disabled && (m_type == IMAGE || m_type == SUBMIT);
}
bool HTMLInputElementImpl::isActivatedSubmit() const
{
return m_activeSubmit;
}
void HTMLInputElementImpl::setActivatedSubmit(bool flag)
{
m_activeSubmit = flag;
}
bool HTMLInputElementImpl::appendFormData(FormDataList &encoding, bool multipart)
{
if (name().isEmpty() && m_type != IMAGE) return false;
switch (m_type) {
case HIDDEN:
case TEXT:
#if APPLE_CHANGES
case SEARCH:
case RANGE:
#endif
case PASSWORD:
encoding.appendData(name(), value());
return true;
case CHECKBOX:
case RADIO:
if (checked()) {
encoding.appendData(name(), value());
return true;
}
break;
case BUTTON:
case RESET:
return false;
case IMAGE:
if (m_activeSubmit)
{
encoding.appendData(name().isEmpty() ? QString::fromLatin1("x") : (name().string() + ".x"), clickX());
encoding.appendData(name().isEmpty() ? QString::fromLatin1("y") : (name().string() + ".y"), clickY());
if (!name().isEmpty() && !value().isEmpty())
encoding.appendData(name(), value());
return true;
}
break;
case SUBMIT:
if (m_activeSubmit)
{
QString enc_str = valueWithDefault().string();
if (!enc_str.isEmpty()) {
encoding.appendData(name(), enc_str);
return true;
}
}
break;
case FILE:
{
if(!multipart || !renderer() || renderer()->style()->visibility() != khtml::VISIBLE)
return false;
if (value().isEmpty()) {
encoding.appendData(name(), QString(""));
return true;
}
#if APPLE_CHANGES
encoding.appendFile(name(), value());
return true;
#else
KURL fileurl("file:///");
fileurl.setPath(value().string());
KIO::UDSEntry filestat;
if (!KIO::NetAccess::stat(fileurl, filestat)) {
KMessageBox::sorry(0L, i18n("Error fetching file for submission:\n%1").arg(KIO::NetAccess::lastErrorString()));
return false;
}
KFileItem fileitem(filestat, fileurl, true, false);
if (fileitem.isDir()) {
return false;
}
QString local;
if ( KIO::NetAccess::download(fileurl, local) )
{
QFile file(local);
if (file.open(IO_ReadOnly))
{
QCString filearray(file.size()+1);
int readbytes = file.readBlock( filearray.data(), file.size());
if ( readbytes >= 0 )
filearray[readbytes] = '\0';
file.close();
encoding.appendData(name(), filearray);
KIO::NetAccess::removeTempFile( local );
return true;
}
return false;
}
else {
KMessageBox::sorry(0L, i18n("Error fetching file for submission:\n%1").arg(KIO::NetAccess::lastErrorString()));
return false;
}
break;
#endif
}
case ISINDEX:
encoding.appendData(name(), value());
return true;
}
return false;
}
void HTMLInputElementImpl::reset()
{
if (storesValueSeparateFromAttribute())
setValue(DOMString());
setChecked(m_defaultChecked);
m_useDefaultChecked = true;
}
void HTMLInputElementImpl::setChecked(bool _checked)
{
if (checked() == _checked) return;
if (m_form && m_type == RADIO && _checked && !name().isEmpty())
m_form->radioClicked(this);
m_useDefaultChecked = false;
m_checked = _checked;
setChanged();
}
DOMString HTMLInputElementImpl::value() const
{
DOMString value = m_value;
if (value.isNull() && m_type != FILE)
value = getAttribute(ATTR_VALUE);
if (value.isNull() && (m_type == CHECKBOX || m_type == RADIO))
return DOMString(checked() ? "on" : "");
return value;
}
DOMString HTMLInputElementImpl::valueWithDefault() const
{
DOMString v = value();
if (v.isEmpty()) {
switch (m_type) {
case RESET:
#if APPLE_CHANGES
v = resetButtonDefaultLabel();
#else
v = i18n("Reset");
#endif
break;
case SUBMIT:
#if 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:
#if APPLE_CHANGES
case RANGE:
case SEARCH:
#endif
case TEXT:
break;
}
}
return v;
}
void HTMLInputElementImpl::setValue(const DOMString &value)
{
if (m_type == FILE) return;
if (storesValueSeparateFromAttribute()) {
m_value = value;
setChanged();
} else {
setAttribute(ATTR_VALUE, value);
}
m_valueMatchesRenderer = false;
}
void HTMLInputElementImpl::setValueFromRenderer(const DOMString &value)
{
m_value = value;
m_valueMatchesRenderer = true;
dispatchHTMLEvent(EventImpl::INPUT_EVENT, true, false);
}
bool HTMLInputElementImpl::storesValueSeparateFromAttribute() const
{
switch (m_type) {
case BUTTON:
case CHECKBOX:
case FILE:
case HIDDEN:
case IMAGE:
case RADIO:
#if APPLE_CHANGES
case RANGE:
#endif
case RESET:
case SUBMIT:
return false;
case ISINDEX:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
#endif
case TEXT:
return true;
}
return false;
}
void HTMLInputElementImpl::blur()
{
if(getDocument()->focusNode() == this)
getDocument()->setFocusNode(0);
}
void HTMLInputElementImpl::focus()
{
getDocument()->setFocusNode(this);
}
void HTMLInputElementImpl::defaultEventHandler(EventImpl *evt)
{
if (evt->isMouseEvent() &&
( evt->id() == EventImpl::KHTML_CLICK_EVENT || evt->id() == EventImpl::KHTML_DBLCLICK_EVENT ) &&
m_type == IMAGE
&& m_render) {
MouseEventImpl *me = static_cast<MouseEventImpl*>(evt);
int offsetX, offsetY;
m_render->absolutePosition(offsetX,offsetY);
xPos = me->clientX()-offsetX;
yPos = me->clientY()-offsetY;
me->setDefaultHandled();
}
if ((evt->id() == EventImpl::DOMACTIVATE_EVENT) &&
(m_type == IMAGE || m_type == SUBMIT || m_type == RESET)){
if (!m_form)
return;
if (m_type == RESET) {
m_form->reset();
}
else {
m_activeSubmit = true;
if (!m_form->prepareSubmit()) {
xPos = 0;
yPos = 0;
}
m_activeSubmit = false;
}
}
#if APPLE_CHANGES
if (evt->id() == EventImpl::KEYPRESS_EVENT && evt->isKeyboardEvent()) {
DOMString key = static_cast<KeyboardEventImpl *>(evt)->keyIdentifier();
switch (m_type) {
case BUTTON:
case CHECKBOX:
case FILE:
case IMAGE:
case RADIO:
case RESET:
case SUBMIT:
if (key == "U+000020" || key == "Enter") {
click(false);
evt->setDefaultHandled();
}
break;
case HIDDEN:
case ISINDEX:
case PASSWORD:
case RANGE:
case SEARCH:
case TEXT:
if (key == "Enter" && m_form) {
m_form->submitClick();
evt->setDefaultHandled();
}
break;
}
}
#endif
HTMLGenericFormElementImpl::defaultEventHandler(evt);
}
bool HTMLInputElementImpl::isEditable()
{
return ((m_type == TEXT) || (m_type == PASSWORD) ||
(m_type == SEARCH) || (m_type == ISINDEX) || (m_type == FILE));
}
bool HTMLInputElementImpl::isURLAttribute(AttributeImpl *attr) const
{
return (attr->id() == ATTR_SRC);
}
HTMLLabelElementImpl::HTMLLabelElementImpl(DocumentPtr *doc)
: HTMLElementImpl(doc)
{
}
HTMLLabelElementImpl::~HTMLLabelElementImpl()
{
}
bool HTMLLabelElementImpl::isFocusable() const
{
return false;
}
NodeImpl::Id HTMLLabelElementImpl::id() const
{
return ID_LABEL;
}
void HTMLLabelElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::FOCUS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBLUR:
setHTMLEventListener(EventImpl::BLUR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
default:
HTMLElementImpl::parseHTMLAttribute(attr);
}
}
ElementImpl *HTMLLabelElementImpl::formElement()
{
DOMString formElementId = getAttribute(ATTR_FOR);
if (formElementId.isNull()) {
NodeImpl *node = this;
while ((node = node->traverseNextNode(this))) {
if (node->isHTMLElement()) {
HTMLElementImpl *element = static_cast<HTMLElementImpl *>(node);
if (element->isGenericFormElement()) {
return element;
}
}
}
return 0;
}
if (formElementId.isEmpty())
return 0;
return getDocument()->getElementById(formElementId);
}
void HTMLLabelElementImpl::accessKeyAction(bool sendToAnyElement)
{
ElementImpl *element = formElement();
if (element)
element->accessKeyAction(sendToAnyElement);
}
HTMLLegendElementImpl::HTMLLegendElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f)
{
}
HTMLLegendElementImpl::~HTMLLegendElementImpl()
{
}
bool HTMLLegendElementImpl::isFocusable() const
{
return false;
}
NodeImpl::Id HTMLLegendElementImpl::id() const
{
return ID_LEGEND;
}
RenderObject* HTMLLegendElementImpl::createRenderer(RenderArena* arena, RenderStyle* style)
{
return new (arena) RenderLegend(this);
}
DOMString HTMLLegendElementImpl::type() const
{
return "legend";
}
HTMLSelectElementImpl::HTMLSelectElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f), m_options(0)
{
m_multiple = false;
m_recalcListItems = false;
m_size = 0;
m_minwidth = 0;
}
HTMLSelectElementImpl::~HTMLSelectElementImpl()
{
if (getDocument()) getDocument()->deregisterMaintainsState(this);
if (m_options) {
m_options->detach();
m_options->deref();
}
}
NodeImpl::Id HTMLSelectElementImpl::id() const
{
return ID_SELECT;
}
void HTMLSelectElementImpl::recalcStyle( StyleChange ch )
{
if (hasChangedChild() && m_render) {
static_cast<khtml::RenderSelect*>(m_render)->setOptionsChanged(true);
}
HTMLGenericFormElementImpl::recalcStyle( ch );
}
DOMString HTMLSelectElementImpl::type() const
{
return (m_multiple ? "select-multiple" : "select-one");
}
long HTMLSelectElementImpl::selectedIndex() const
{
uint o = 0;
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
for (unsigned int i = 0; i < items.size(); i++) {
if (items[i]->id() == ID_OPTION) {
if (static_cast<HTMLOptionElementImpl*>(items[i])->selected())
return o;
o++;
}
}
Q_ASSERT(m_multiple);
return -1;
}
void HTMLSelectElementImpl::setSelectedIndex( long index )
{
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
int listIndex;
for (listIndex = 0; listIndex < int(items.size()); 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
{
int len = 0;
uint i;
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
for (i = 0; i < items.size(); i++) {
if (items[i]->id() == ID_OPTION)
len++;
}
return len;
}
void HTMLSelectElementImpl::add( HTMLElementImpl *element, HTMLElementImpl *before )
{
if (!element || element->id() != ID_OPTION)
return;
int exceptioncode = 0;
insertBefore(element, before, exceptioncode);
if (!exceptioncode)
setRecalcListItems();
}
void HTMLSelectElementImpl::remove( long index )
{
int exceptioncode = 0;
int listIndex = optionToListIndex(index);
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
if(listIndex < 0 || index >= int(items.size()))
return;
removeChild(items[listIndex], exceptioncode);
if( !exceptioncode )
setRecalcListItems();
}
void HTMLSelectElementImpl::blur()
{
if(getDocument()->focusNode() == this)
getDocument()->setFocusNode(0);
}
void HTMLSelectElementImpl::focus()
{
getDocument()->setFocusNode(this);
}
DOMString HTMLSelectElementImpl::value( )
{
uint i;
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
for (i = 0; i < items.size(); 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)
{
QMemArray<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;
}
}
QString HTMLSelectElementImpl::state( )
{
#if !APPLE_CHANGES
QString state;
#endif
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
int l = items.count();
#if APPLE_CHANGES
QChar stateChars[l];
for(int i = 0; i < l; i++)
if(items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->selected())
stateChars[i] = 'X';
else
stateChars[i] = '.';
QString state(stateChars, l);
#else
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';
#endif
return HTMLGenericFormElementImpl::state() + state;
}
void HTMLSelectElementImpl::restoreState(QStringList &_states)
{
QString _state = HTMLGenericFormElementImpl::findMatchingState(_states);
if (_state.isNull()) return;
recalcListItems();
QString state = _state;
if(!state.isEmpty() && !state.contains('X') && !m_multiple) {
qWarning("should not happen in restoreState!");
#if APPLE_CHANGES
#else
state[0] = 'X';
#endif
}
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
int l = items.count();
for(int i = 0; i < l; i++) {
if(items[i]->id() == ID_OPTION) {
HTMLOptionElementImpl* oe = static_cast<HTMLOptionElementImpl*>(items[i]);
oe->setSelected(state[i] == 'X');
}
}
setChanged(true);
}
NodeImpl *HTMLSelectElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::insertBefore(newChild,refChild, exceptioncode );
if (!exceptioncode)
setRecalcListItems();
return result;
}
NodeImpl *HTMLSelectElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::replaceChild(newChild,oldChild, exceptioncode);
if( !exceptioncode )
setRecalcListItems();
return result;
}
NodeImpl *HTMLSelectElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::removeChild(oldChild, exceptioncode);
if( !exceptioncode )
setRecalcListItems();
return result;
}
NodeImpl *HTMLSelectElementImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::appendChild(newChild, exceptioncode);
if( !exceptioncode )
setRecalcListItems();
setChanged(true);
return result;
}
NodeImpl* HTMLSelectElementImpl::addChild(NodeImpl* newChild)
{
setRecalcListItems();
return HTMLGenericFormElementImpl::addChild(newChild);
}
void HTMLSelectElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_SIZE:
m_size = QMAX( attr->value().toInt(), 1 );
break;
case ATTR_WIDTH:
m_minwidth = QMAX( attr->value().toInt(), 0 );
break;
case ATTR_MULTIPLE:
m_multiple = (!attr->isNull());
break;
case ATTR_ACCESSKEY:
break;
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::FOCUS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBLUR:
setHTMLEventListener(EventImpl::BLUR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCHANGE:
setHTMLEventListener(EventImpl::CHANGE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
RenderObject *HTMLSelectElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
return new (arena) RenderSelect(this);
}
bool HTMLSelectElementImpl::appendFormData(FormDataList& encoded_values, bool)
{
bool successful = false;
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
uint i;
for (i = 0; i < items.size(); i++) {
if (items[i]->id() == ID_OPTION) {
HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[i]);
if (option->selected()) {
encoded_values.appendData(name(), option->value());
successful = true;
}
}
}
if (!successful && !m_multiple && m_size <= 1 && items.size() &&
(items[0]->id() == ID_OPTION) ) {
HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[0]);
if (option->value().isNull())
encoded_values.appendData(name(), option->text().string().stripWhiteSpace());
else
encoded_values.appendData(name(), option->value());
successful = true;
}
return successful;
}
int HTMLSelectElementImpl::optionToListIndex(int optionIndex) const
{
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
if (optionIndex < 0 || optionIndex >= int(items.size()))
return -1;
int listIndex = 0;
int optionIndex2 = 0;
for (;
optionIndex2 < int(items.size()) && optionIndex2 <= optionIndex;
listIndex++) { if (items[listIndex]->id() == ID_OPTION)
optionIndex2++;
}
listIndex--;
return listIndex;
}
int HTMLSelectElementImpl::listToOptionIndex(int listIndex) const
{
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
if (listIndex < 0 || listIndex >= int(items.size()) ||
items[listIndex]->id() != ID_OPTION)
return -1;
int optionIndex = 0; int i;
for (i = 0; i < listIndex; i++)
if (items[i]->id() == ID_OPTION)
optionIndex++;
return optionIndex;
}
HTMLOptionsCollectionImpl *HTMLSelectElementImpl::options()
{
if (!m_options) {
m_options = new HTMLOptionsCollectionImpl(this);
m_options->ref();
}
return m_options;
}
void HTMLSelectElementImpl::recalcListItems()
{
NodeImpl* current = firstChild();
m_listItems.resize(0);
HTMLOptionElementImpl* foundSelected = 0;
while(current) {
if (current->id() == ID_OPTGROUP && current->firstChild()) {
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_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 *parent = current->parentNode();
current = current->nextSibling();
if (!current) {
if (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()
{
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
uint i;
for (i = 0; i < items.size(); i++) {
if (items[i]->id() == ID_OPTION) {
HTMLOptionElementImpl *option = static_cast<HTMLOptionElementImpl*>(items[i]);
bool selected = (!option->getAttribute(ATTR_SELECTED).isNull());
option->setSelected(selected);
}
}
if ( m_render )
static_cast<RenderSelect*>(m_render)->setSelectionChanged(true);
setChanged( true );
}
void HTMLSelectElementImpl::notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected)
{
if (selected && !m_multiple) {
QMemArray<HTMLGenericFormElementImpl*> items = listItems();
uint i;
for (i = 0; i < items.size(); 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);
}
#if APPLE_CHANGES
void HTMLSelectElementImpl::defaultEventHandler(EventImpl *evt)
{
if (evt->id() == EventImpl::KEYPRESS_EVENT) {
if (!m_form || !m_render || !evt->isKeyboardEvent())
return;
DOMString key = static_cast<KeyboardEventImpl *>(evt)->keyIdentifier();
if (key == "Enter") {
m_form->submitClick();
evt->setDefaultHandled();
}
}
HTMLGenericFormElementImpl::defaultEventHandler(evt);
}
#endif // APPLE_CHANGES
void HTMLSelectElementImpl::accessKeyAction(bool sendToAnyElement)
{
focus();
}
HTMLKeygenElementImpl::HTMLKeygenElementImpl(DocumentPtr* doc, HTMLFormElementImpl* f)
: HTMLSelectElementImpl(doc, f)
{
QStringList keys = KSSLKeyGen::supportedKeySizes();
for (QStringList::Iterator i = keys.begin(); i != keys.end(); ++i) {
HTMLOptionElementImpl* o = new HTMLOptionElementImpl(doc, form());
addChild(o);
o->addChild(new TextImpl(doc, DOMString(*i)));
}
}
NodeImpl::Id HTMLKeygenElementImpl::id() const
{
return ID_KEYGEN;
}
DOMString HTMLKeygenElementImpl::type() const
{
return "keygen";
}
void HTMLKeygenElementImpl::parseHTMLAttribute(HTMLAttributeImpl* attr)
{
switch(attr->id())
{
case ATTR_CHALLENGE:
m_challenge = attr->value();
break;
case ATTR_KEYTYPE:
m_keyType = attr->value();
break;
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
bool HTMLKeygenElementImpl::appendFormData(FormDataList& encoded_values, bool)
{
#if APPLE_CHANGES
if (!m_keyType.isNull() && strcasecmp(m_keyType, "rsa")) {
return false;
}
QString value = KSSLKeyGen::signedPublicKeyAndChallengeString(selectedIndex(), m_challenge.string(), getDocument()->part()->baseURL());
if (value.isNull()) {
return false;
}
encoded_values.appendData(name(), value.utf8());
return true;
#else
bool successful = false;
KSSLKeyGen *kg = new KSSLKeyGen(static_cast<RenderWidget *>(m_render)->widget(), "Key Generator", true);
kg->setKeySize(0);
successful = (QDialog::Accepted == kg->exec());
delete kg;
encoded_values.appendData(name(), "deadbeef");
return successful;
#endif
}
HTMLOptGroupElementImpl::HTMLOptGroupElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f)
{
}
HTMLOptGroupElementImpl::~HTMLOptGroupElementImpl()
{
}
bool HTMLOptGroupElementImpl::isFocusable() const
{
return false;
}
NodeImpl::Id HTMLOptGroupElementImpl::id() const
{
return ID_OPTGROUP;
}
DOMString HTMLOptGroupElementImpl::type() const
{
return "optgroup";
}
NodeImpl *HTMLOptGroupElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::insertBefore(newChild,refChild, exceptioncode);
if ( !exceptioncode )
recalcSelectOptions();
return result;
}
NodeImpl *HTMLOptGroupElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::replaceChild(newChild,oldChild, exceptioncode);
if(!exceptioncode)
recalcSelectOptions();
return result;
}
NodeImpl *HTMLOptGroupElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::removeChild(oldChild, exceptioncode);
if( !exceptioncode )
recalcSelectOptions();
return result;
}
NodeImpl *HTMLOptGroupElementImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
{
NodeImpl *result = HTMLGenericFormElementImpl::appendChild(newChild, exceptioncode);
if( !exceptioncode )
recalcSelectOptions();
return result;
}
NodeImpl* HTMLOptGroupElementImpl::addChild(NodeImpl* newChild)
{
recalcSelectOptions();
return HTMLGenericFormElementImpl::addChild(newChild);
}
void HTMLOptGroupElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
recalcSelectOptions();
}
void HTMLOptGroupElementImpl::recalcSelectOptions()
{
NodeImpl *select = parentNode();
while (select && select->id() != ID_SELECT)
select = select->parentNode();
if (select)
static_cast<HTMLSelectElementImpl*>(select)->setRecalcListItems();
}
HTMLOptionElementImpl::HTMLOptionElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f)
{
m_selected = false;
}
bool HTMLOptionElementImpl::isFocusable() const
{
return false;
}
NodeImpl::Id HTMLOptionElementImpl::id() const
{
return ID_OPTION;
}
DOMString HTMLOptionElementImpl::type() const
{
return "option";
}
DOMString HTMLOptionElementImpl::text() const
{
DOMString text;
if (getDocument() && !getDocument()->inCompatMode()) {
DOMString text = getAttribute(ATTR_LABEL);
if (!text.isEmpty())
return text;
}
const NodeImpl *n = this;
while ((n = n->traverseNextNode(this))) {
if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE)
text += n->nodeValue();
}
return text;
}
long HTMLOptionElementImpl::index() const
{
QMemArray<HTMLGenericFormElementImpl*> items = getSelect()->listItems();
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::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_SELECTED:
m_selected = (!attr->isNull());
break;
case ATTR_VALUE:
m_value = attr->value();
break;
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
DOMString HTMLOptionElementImpl::value() const
{
if ( !m_value.isNull() )
return m_value;
return text().string().stripWhiteSpace();
}
void HTMLOptionElementImpl::setValue(DOMStringImpl* value)
{
setAttribute(ATTR_VALUE, value);
}
void HTMLOptionElementImpl::setSelected(bool _selected)
{
if(m_selected == _selected)
return;
m_selected = _selected;
HTMLSelectElementImpl *select = getSelect();
if (select)
select->notifyOptionSelected(this,_selected);
}
void HTMLOptionElementImpl::childrenChanged()
{
HTMLSelectElementImpl *select = getSelect();
if (select)
select->childrenChanged();
}
HTMLSelectElementImpl *HTMLOptionElementImpl::getSelect() const
{
NodeImpl *select = parentNode();
while (select && select->id() != ID_SELECT)
select = select->parentNode();
return static_cast<HTMLSelectElementImpl*>(select);
}
HTMLTextAreaElementImpl::HTMLTextAreaElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLGenericFormElementImpl(doc, f), m_valueIsValid(false), m_valueMatchesRenderer(false)
{
m_rows = 2;
m_cols = 20;
m_wrap = ta_Virtual;
}
HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl()
{
if (getDocument()) getDocument()->deregisterMaintainsState(this);
}
NodeImpl::Id HTMLTextAreaElementImpl::id() const
{
return ID_TEXTAREA;
}
DOMString HTMLTextAreaElementImpl::type() const
{
return "textarea";
}
QString HTMLTextAreaElementImpl::state( )
{
return HTMLGenericFormElementImpl::state() + value().string()+'.';
}
void HTMLTextAreaElementImpl::restoreState(QStringList &states)
{
QString state = HTMLGenericFormElementImpl::findMatchingState(states);
if (state.isNull()) return;
setDefaultValue(state.left(state.length()-1));
}
void HTMLTextAreaElementImpl::select( )
{
if (m_render)
static_cast<RenderTextArea*>(m_render)->select();
onSelect();
}
void HTMLTextAreaElementImpl::childrenChanged()
{
setValue(defaultValue());
}
void HTMLTextAreaElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch(attr->id())
{
case ATTR_ROWS:
m_rows = !attr->isNull() ? attr->value().toInt() : 3;
if (renderer())
renderer()->setNeedsLayoutAndMinMaxRecalc();
break;
case ATTR_COLS:
m_cols = !attr->isNull() ? attr->value().toInt() : 60;
if (renderer())
renderer()->setNeedsLayoutAndMinMaxRecalc();
break;
case ATTR_WRAP:
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;
if (renderer())
renderer()->setNeedsLayoutAndMinMaxRecalc();
break;
case ATTR_ACCESSKEY:
break;
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::FOCUS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBLUR:
setHTMLEventListener(EventImpl::BLUR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONSELECT:
setHTMLEventListener(EventImpl::SELECT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCHANGE:
setHTMLEventListener(EventImpl::CHANGE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
RenderObject *HTMLTextAreaElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
return new (arena) RenderTextArea(this);
}
bool HTMLTextAreaElementImpl::appendFormData(FormDataList& encoding, bool)
{
if (name().isEmpty()) return false;
encoding.appendData(name(), value());
return true;
}
void HTMLTextAreaElementImpl::reset()
{
setValue(defaultValue());
}
void HTMLTextAreaElementImpl::updateValue()
{
if ( !m_valueIsValid ) {
if ( m_render ) {
m_value = static_cast<RenderTextArea*>( m_render )->text();
m_valueMatchesRenderer = true;
} else {
m_value = defaultValue().string();
m_valueMatchesRenderer = false;
}
m_valueIsValid = true;
}
}
DOMString HTMLTextAreaElementImpl::value()
{
updateValue();
return m_value.isNull() ? DOMString("") : m_value;
}
void HTMLTextAreaElementImpl::setValue(const DOMString &value)
{
m_value = value.string();
m_valueIsValid = true;
m_valueMatchesRenderer = false;
setChanged(true);
}
DOMString HTMLTextAreaElementImpl::defaultValue()
{
DOMString val = "";
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(const DOMString &defaultValue)
{
QPtrList<NodeImpl> toRemove;
NodeImpl *n;
for (n = firstChild(); n; n = n->nextSibling())
if (n->isTextNode())
toRemove.append(n);
QPtrListIterator<NodeImpl> it(toRemove);
int exceptioncode = 0;
for (; it.current(); ++it) {
removeChild(it.current(), exceptioncode);
}
insertBefore(getDocument()->createTextNode(defaultValue),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;
}
void HTMLTextAreaElementImpl::accessKeyAction(bool sendToAnyElement)
{
focus();
}
void HTMLTextAreaElementImpl::detach()
{
HTMLGenericFormElementImpl::detach();
m_valueMatchesRenderer = false;
}
HTMLIsIndexElementImpl::HTMLIsIndexElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLInputElementImpl(doc, f)
{
m_type = TEXT;
setName("isindex");
}
NodeImpl::Id HTMLIsIndexElementImpl::id() const
{
return ID_ISINDEX;
}
void HTMLIsIndexElementImpl::parseHTMLAttribute(HTMLAttributeImpl* attr)
{
switch(attr->id())
{
case ATTR_PROMPT:
setValue(attr->value());
default:
HTMLGenericFormElementImpl::parseHTMLAttribute(attr);
}
}
unsigned long HTMLOptionsCollectionImpl::length() const
{
return 0;
}
void HTMLOptionsCollectionImpl::setLength(unsigned long length)
{
}
NodeImpl *HTMLOptionsCollectionImpl::item(unsigned long index) const
{
return 0;
}
NodeImpl *HTMLOptionsCollectionImpl::namedItem(const DOMString &name) const
{
return 0;
}
FormDataList::FormDataList(QTextCodec *c)
: m_codec(c)
{
}
void FormDataList::appendString(const QCString &s)
{
m_list.append(s);
}
void FormDataList::appendString(const QString &s)
{
QCString cstr = fixLineBreaks(m_codec->fromUnicode(s));
cstr.truncate(cstr.length());
m_list.append(cstr);
}
void FormDataList::appendFile(const DOMString &key, const DOMString &filename)
{
appendString(key.string());
m_list.append(filename.string());
}
}