--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/s60/misc/WebUtil.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,776 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Frame in webkit side
+*
+*/
+
+#include "config.h"
+
+#include "BrCtl.h"
+#include "Frame.h"
+#include "Cache.h"
+#include "DocLoader.h"
+#include "IntPoint.h"
+#include "String.h"
+#include "HTMLNames.h"
+#include "EventNames.h"
+#include "HTMLInputElement.h"
+#include "Document.h"
+#include "WebFrame.h"
+#include "WebFrameView.h"
+#include "WebCursor.h"
+#include "WebView.h"
+#include "FrameView.h"
+#include "RenderImage.h"
+#include "IntRect.h"
+#include "FloatRect.h"
+#include "Image.h"
+#include "HTMLImageElement.h"
+#include "StaticObjectsContainer.h"
+#include "SelectionController.h"
+#include "WebUtil.h"
+#include "errordefs.h"
+#include "RenderListBox.h"
+#include "RenderTextControl.h"
+#include "RenderView.h"
+#include "PlatformScrollbar.h"
+#include "HTMLSelectElement.h"
+#include "webkitlogger.h"
+#include <StringLoader.h>
+#include <sslerr.h>
+#include <httperr.h>
+#include <inet6err.h>
+#include <in_sock.h>
+
+using namespace WebCore;
+using namespace EventNames;
+using namespace HTMLNames;
+
+static const char* KTel = "tel:";
+static const char* KMailto = "mailto:";
+static const char* KWtai = "wtai:";
+static const char* KWtaiMC = "wtai://wp/mc;";
+static const char* KWtaiAP = "wtai://wp/ap;";
+static const char* KWtaiSD = "wtai://wp/sd;";
+
+_LIT(KPathBegin,"<!--framePathBegin ");
+_LIT(KPathEnd," framePathEnd --!>");
+_LIT(KMimeWBMP, "image/vnd.wap.wbmp");
+_LIT(KMimeOTA, "image/vnd.nokia.ota-bitmap");
+
+TBrCtlDefs::TBrCtlElementType nodeTypeB(Node* node, Frame* frame)
+{
+ if( !node || !node->isElementNode() )
+ return TBrCtlDefs::EElementNone;
+
+ TBrCtlDefs::TBrCtlElementType elType(TBrCtlDefs::EElementNone);
+ HTMLElement *e = static_cast<HTMLElement *>(node);
+
+ // get the right element type
+ if ( e->hasLocalName(linkTag) ) {
+ elType = TBrCtlDefs::EElementAnchor;
+ }
+ else if ( e->hasLocalName(aTag) ) {
+ elType = TBrCtlDefs::EElementAnchor;
+
+ String href = e->getAttribute( hrefAttr );
+ if (!href.isNull()) {
+
+ if( href.startsWith( KTel ) ) {
+ elType = TBrCtlDefs::EElementTelAnchor;
+ }
+ else if( href.startsWith( KWtai ) ) {
+
+ if( href.startsWith( KWtaiMC ) || href.startsWith(KWtaiAP) || href.startsWith(KWtaiSD) ) {
+ elType = TBrCtlDefs::EElementTelAnchor;
+ }
+
+ }
+ else if( href.startsWith( KMailto ) ) {
+ elType = TBrCtlDefs::EElementMailtoAnchor;
+ }
+
+
+ }
+ else if (!e->getAttribute( ctiAttr ).isNull()) {
+ elType = TBrCtlDefs::EElementTelAnchor;
+ }
+ else if( e->hasLocalName(areaTag) ) {
+
+ elType = TBrCtlDefs::EElementInputBox;
+ }
+ }
+ else if (e->isControl()) {
+ HTMLGenericFormElement* ie = static_cast<HTMLGenericFormElement*>( e );
+ // default for form element
+ elType = TBrCtlDefs::EElementInputBox;
+ if (ie->type() == "radio")
+ elType = ((HTMLInputElement*)ie)->checked() ? TBrCtlDefs::EElementRadioButtonSelected : TBrCtlDefs::EElementRadioButtonUnSelected;
+ else if (ie->type() == "checkbox")
+ elType = ((HTMLInputElement*)ie)->checked() ? TBrCtlDefs::EElementCheckBoxChecked : TBrCtlDefs::EElementCheckBoxUnChecked;
+ else if (ie->type() == "button" || ie->type() == "reset" || ie->type() == "submit")
+ elType = TBrCtlDefs::EElementButton;
+ else if (ie->type() == "file") {
+ if (((HTMLInputElement*)ie)->value() == String())
+ elType = TBrCtlDefs::EElementFileSelectionBoxNoContent;
+ else
+ elType = TBrCtlDefs::EElementFileSelectionBoxWithContent;
+ }
+ else if (ie->type() == "select-multiple")
+ elType = TBrCtlDefs::EElementSelectMultiBox;
+ else if ( ie->type() == "select-one") {
+ if(!e->getAttribute(sizeAttr).isNull() && !(e->getAttribute(sizeAttr) == "1")) {
+ elType = TBrCtlDefs::EElementSelectMultiBox;
+ }
+ else {
+ elType = TBrCtlDefs::EElementSelectBox;
+ }
+ }
+ else if (ie->type() == "textarea")
+ elType = TBrCtlDefs::EElementTextAreaBox;
+ }
+ else if( e->hasLocalName(objectTag) || e->hasLocalName(embedTag) ) {
+ if( e->renderer() && e->renderer()->isWidget() )
+ if(node->active())
+ elType = TBrCtlDefs::EElementActivatedObjectBox;
+ else
+ elType = TBrCtlDefs::EElementObjectBox;
+ else
+ elType = TBrCtlDefs::EElementNone;
+ }
+
+ // change to activated input box
+ WebView* v = control(frame)->webView();
+ if ((elType == TBrCtlDefs::EElementInputBox || elType == TBrCtlDefs::EElementTextAreaBox) && v && v->isEditable())
+ elType = TBrCtlDefs::EElementActivatedInputBox;
+
+ return elType;
+}
+
+
+WebFrame* frameAndPointUnderCursor(IntPoint& p_, WebView& v_)
+{
+ WebFrameView* mfv = v_.mainFrame()->frameView();
+ p_ = StaticObjectsContainer::instance()->webCursor()->position();
+ WebFrame* frame = v_.mainFrame()->frameAtPoint(p_);
+ if (!frame)
+ frame = v_.mainFrame();
+ IntPoint rc = frame->frameView()->rectInGlobalCoords().iTl;
+ p_ = frame->frameView()->viewCoordsInFrameCoords(p_);
+ return frame;
+}
+
+String getNodeUrlAtPointInFrame(WebFrame& f_, IntPoint& p_)
+{
+ Document* doc = core(&f_)->document();
+ if (doc) {
+ Node* node = doc->elementFromPoint(p_.x(), p_.y());
+
+ if (node) {
+ if (node->hasTagName(areaTag)) {
+ HTMLElement* e = static_cast<HTMLElement*>(node);
+ if(!e->getAttribute(hrefAttr).isNull()) {
+ return e->getAttribute(hrefAttr);
+ }
+ }
+ // get the navigable node at this point
+ Node* n = node;
+ for (; n; n = n->parentNode())
+ if (n->isFocusable() && n->isElementNode())
+ break;
+
+ if (n && n->isFocusable() && n->isElementNode()) {
+ HTMLElement* e = static_cast<HTMLElement*>(n);
+ if (!e->getAttribute(hrefAttr).isNull()) {
+ return e->getAttribute(hrefAttr);
+ }
+ }
+ }
+ }
+ return String();
+}
+
+
+int imageCountInFrame(WebFrame& wf_, bool visibleOnly_)
+{
+ int count = 0;
+ Frame* f = core(&wf_);
+
+ if (!f || !f->document() || !f->document()->renderer())
+ return count;
+
+ Document* doc = f->document();
+ RefPtr<WebCore::HTMLCollection> collection = doc->images();
+
+ FrameView* v = doc->view();
+ IntRect r1 = wf_.frameView()->topView()->mainFrame()->frameView()->rect();
+
+ for (Node *n = collection->firstItem(); n; n = collection->nextItem()) {
+
+ RenderImage* render = static_cast<RenderImage*>(n->renderer());
+ if (render) {
+
+ Image* img = render->image();
+ if (!img->isNull() && img->data()) {
+ //if visible only is true, check for intersection
+ bool processing = true;
+ if (visibleOnly_) {
+ IntRect imageRect;
+ IntPoint tl = wf_.frameView()->frameCoordsInViewCoords(n->getRect().topLeft());
+ IntPoint br = wf_.frameView()->frameCoordsInViewCoords(n->getRect().bottomRight());
+ imageRect.setLocation(tl);
+ imageRect.setSize(br-tl);
+
+ processing = r1.intersects(imageRect);
+ }
+ if (processing) {
+ String alttext = static_cast<HTMLImageElement*>(render->element())->altText();
+ // Check if alttext is "Nokia" or "No_save".
+ // Then do not count
+ if (!(equalIgnoringCase(alttext, "nokia") || equalIgnoringCase(alttext, "no_save")))
+ ++count;
+ }
+ }
+ }
+
+ }
+ return count;
+}
+
+CArrayFixFlat<TBrCtlImageCarrier>* imagesInFrame(WebFrame& wf_, bool visibleOnly_)
+{
+ CArrayFixFlat<TBrCtlImageCarrier>* imglist = new CArrayFixFlat<TBrCtlImageCarrier>(10);
+ Frame* f = core(&wf_);
+
+ if (!f || !f->document() || !f->document()->renderer())
+ return imglist;
+
+ CleanupStack::PushL(imglist);
+
+ Document* doc = f->document();
+ FrameView* v = doc->view();
+ IntRect r1 = wf_.frameView()->topView()->mainFrame()->frameView()->rect();
+
+
+ RefPtr<WebCore::HTMLCollection> collection = doc->images();
+ for (Node* n = collection->firstItem(); n; n = collection->nextItem()) {
+
+ RenderImage* render = static_cast<RenderImage*>(n->renderer());
+ if (render) {
+ Image* img = render->image();
+ if (!img->isNull() && img->data()) {
+ //if visible only is true, check for intersection
+ TBool processing = ETrue;
+ if (visibleOnly_) {
+ IntRect imageRect;
+ IntPoint tl = wf_.frameView()->frameCoordsInViewCoords(n->getRect().topLeft());
+ IntPoint br = wf_.frameView()->frameCoordsInViewCoords(n->getRect().bottomRight());
+ imageRect.setLocation(tl);
+ imageRect.setSize(br-tl);
+
+ processing = r1.intersects(imageRect);
+ }
+ if (processing) {
+ String alttext = static_cast<HTMLImageElement*>(render->element())->altText();
+ TBrCtlImageType type = EImageTypeAny;
+ if (img->getMimeType().find("image/vnd.wap.wbmp") == 0)
+ type = EImageTypeWbmp;
+ else if (img->getMimeType().find("image/vnd.nokia.ota-bitmap") == 0)
+ type = EImageTypeOta;
+ //
+ TBrCtlImageCarrier tImg(TPtrC8((const TUint8*)img->data()->data(),img->data()->size()),
+ static_cast<HTMLImageElement*>(render->element())->getAttribute(srcAttr),
+ alttext, type, img->getMimeType());
+
+ // Check if alttext is "Nokia" or "No_save".
+ // Then do not add the image to the list
+ if (!(equalIgnoringCase(alttext, "nokia") || equalIgnoringCase(alttext, "no_save"))) {
+ // Check if this image has been retrieved before.
+ // Image pointer should be the same for similar images
+ TBool imgexists = false;
+ for (int i=0; i<imglist->Count();i++) {
+ TBrCtlImageCarrier wcImage = imglist->At(i);
+ if (tImg.RawData() == wcImage.RawData()) {
+ imgexists = true;
+ break;
+ }
+
+ }
+ if (!imgexists)
+ imglist->AppendL(tImg);
+ }
+ }
+ }
+ }
+ }
+ CleanupStack::Pop(imglist);
+ return imglist;
+}
+
+CArrayFixFlat<TBrCtlSubscribeTo>* findSubscribeToInFrame(WebFrame& wf_)
+{
+ CArrayFixFlat<TBrCtlSubscribeTo>* linkList = new CArrayFixFlat<TBrCtlSubscribeTo>(10);
+ Frame* f = core(&wf_);
+
+ if (!f || !f->document())
+ return linkList;
+
+ CleanupStack::PushL(linkList);
+ for (Node *n = f->document(); n; n = n->traverseNextNode()) {
+ if (n->isElementNode() && n->hasTagName(linkTag)) {
+
+ HTMLElement* e = static_cast<HTMLElement*>(n);
+ String type = e->getAttribute(typeAttr);
+
+ if (type == "application/rss+xml" || type == "application/atom+xml" ||
+ type == "text/xml" || type == "application/xml") {
+ String href = e->getAttribute(hrefAttr);
+ String title = e->getAttribute(titleAttr);
+
+ TBrCtlSubscribeTo item(title.des(), href.des(), 0);
+ linkList->AppendL(item);
+ }
+ }
+ }
+ CleanupStack::Pop(linkList);
+ return linkList;
+}
+
+int focusedImage(WebView* webView, TBrCtlImageCarrier*& imageCarrier)
+{
+ int ret = KErrNone;
+ TBrCtlImageCarrier* t = NULL;
+ RenderImage *r = renderImageUnderCursor(webView);
+ if (r) {
+ Image* img = r->image();
+ CachedImage* ci = r->cachedImage();
+ if( ci && !img->isNull()) {
+ SharedBuffer* imgData = img->data();
+ if (imgData) {
+ TPtrC8 rawData((const unsigned char*)(imgData->data()), (imgData->size()));
+ // Check if there is data in the image buffer.
+ // Broken links do not have data in them
+ if (rawData.Length() > 0) {
+ // Get the alt text
+ String alttext = static_cast<HTMLImageElement*>(r->element())->altText();
+ // Check if alttext is "Nokia" or "No_save".
+ // Then do not add the image to the list
+ if (!(equalIgnoringCase(alttext, "nokia") || equalIgnoringCase(alttext, "no_save"))) {
+ TBrCtlImageType brCtlTtype = EImageTypeAny;
+ if( img->getMimeType().des().Find(KMimeWBMP) != KErrNotFound ) {
+ brCtlTtype = EImageTypeWbmp;
+ }
+ else if ( img->getMimeType().des().Find(KMimeOTA) != KErrNotFound ) {
+ brCtlTtype = EImageTypeOta;
+ }
+ t = new TBrCtlImageCarrier(TPtrC8((const TUint8*)img->data()->data(),img->data()->size()),
+ static_cast<HTMLImageElement*>(r->element())->getAttribute(srcAttr),
+ alttext, brCtlTtype, img->getMimeType());
+ if (!t) {
+ ret = KErrNoMemory;
+ }
+ else {
+ ret = KErrNone;
+ }
+ }
+ else {
+ ret = KErrAccessDenied;
+ }
+ } // if (rawData.Length() > 0)
+ else {
+ ret = KErrNotFound;
+ }
+ }
+ else {
+ ret = KErrNotFound;
+ }
+ } // if (ci)
+ else {
+ ret = KErrNotFound;
+ }
+ } // if (r)
+ else {
+ ret = KErrNoMemory;
+ }
+ imageCarrier = t;
+ return ret;
+}
+
+void loadFocusedImage(WebView* webView)
+{
+ RenderImage *r = renderImageUnderCursor(webView);
+ if (r) {
+ CachedImage* ci = r->cachedImage();
+ if (ci && ci->status() == CachedResource::Unknown) {
+ IntPoint p;
+ WebFrame* frame = frameAndPointUnderCursor(p, *webView);
+ cache()->loader()->load(core(frame)->document()->docLoader(), ci, true);
+ }
+ }
+}
+
+RenderImage* renderImageUnderCursor(WebView* webView)
+{
+ IntPoint p;
+ WebFrame* frame = frameAndPointUnderCursor(p, *webView);
+ Frame* f = core(frame);
+ RenderImage* render = NULL;
+ if (!f || !f->document() || !f->document()->renderer())
+ return NULL;
+ Document* doc = f->document();
+ FrameView* v = doc->view();
+ RefPtr<WebCore::HTMLCollection> collection = doc->images();
+ for (Node* n = collection->firstItem(); n; n = collection->nextItem()) {
+ render = static_cast<RenderImage*>(n->renderer());
+ if (render) {
+ Image* img = render->image();
+ if (!img->isNull()) {
+ //if visible only is true, check for intersection
+ if (n->getRect().contains(p)) {
+ return render;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+HBufC* generateFrameName()
+{
+ HBufC* name = NULL;
+ name = HBufC::New(60);
+ if (name) {
+ TPtr path = name->Des();
+ path.Copy(KPathBegin);
+ TBuf<20>timeBuf;
+ TTime ttime;
+ ttime.HomeTime();
+ timeBuf.Num(ttime.Int64());
+ path.Append(timeBuf);
+ path.Append(KPathEnd);
+ }
+ return name;
+}
+
+
+void addOneMenuItemAfter(CEikMenuPane& menuPane, unsigned int after, int command, int resourceId, unsigned int commandBase)
+{
+ CEikMenuPaneItem::SData item;
+ HBufC* buf = StringLoader::LoadLC(resourceId);
+ item.iText.Copy(*buf);
+ CleanupStack::PopAndDestroy(); // buf
+ buf = NULL;
+ item.iCommandId = command + commandBase;
+ item.iFlags = 0;
+ item.iCascadeId = 0;
+ menuPane.AddMenuItemL(item, after);
+}
+
+void insertOneMenuItem(CEikMenuPane& menuPane, int command, int resourceId, unsigned int commandBase)
+{
+ CEikMenuPaneItem::SData item;
+ HBufC* buf = StringLoader::LoadLC(resourceId);
+ item.iText.Copy(*buf);
+ CleanupStack::PopAndDestroy(); // buf
+ buf = NULL;
+ item.iCommandId = command + commandBase;
+ item.iFlags = 0;
+ item.iCascadeId = 0;
+ menuPane.InsertMenuItemL(item, 0);
+}
+
+int textMultiplier(int fontLevel, int originalSize)
+{
+ int sizeMultiplier = originalSize;
+ switch(fontLevel)
+ {
+ case TBrCtlDefs::EFontSizeLevelAllSmall:
+ // show text 40% smaller than the declared size
+ sizeMultiplier *= 0.6;
+ break;
+ case TBrCtlDefs::EFontSizeLevelSmaller:
+ // show text 20% smaller than the declared size
+ sizeMultiplier *= 0.8;
+ break;
+ default:
+ case TBrCtlDefs::EFontSizeLevelNormal:
+ break;
+ case TBrCtlDefs::EFontSizeLevelLarger:
+ // show text 25% larger than the declared size
+ sizeMultiplier *= 1.25;
+ break;
+ case TBrCtlDefs::EFontSizeLevelAllLarge:
+ // show text 50% larger than the declared size
+ sizeMultiplier *= 1.50;
+ break;
+ }
+ return sizeMultiplier;
+}
+
+static void handleSpecialSchemeL(String url, CBrCtl* brctl)
+{
+ // only the url is supported currently
+ RArray<TUint> typeArray;
+ CDesCArrayFlat* strArray = new CDesCArrayFlat( 1 );
+ if (strArray) {
+ // add url id
+ typeArray.Append( EParamRequestUrl );
+ // add url string
+ TRAPD(err, strArray->AppendL( url.des() ));
+ if (err == KErrNone) {
+ TRAP_IGNORE(brctl->brCtlSpecialLoadObserver()->HandleRequestL( &typeArray, strArray ));
+ }
+ delete strArray;
+ }
+}
+
+void addFocusedUrlToContacts(WebView* webView)
+{
+ if (webView->brCtl()->brCtlSpecialLoadObserver()) {
+ IntPoint point;
+ WebFrame* frame = frameAndPointUnderCursor(point, *webView);
+ if (frame) {
+ Document* doc = core(frame)->document();
+ if (doc) {
+ Node* node = doc->elementFromPoint(point.x(), point.y());
+ if (node) {
+ // get the navigable node at this point
+ Node* n = node;
+ for (; n; n = n->parentNode())
+ if (n->isFocusable() && n->isElementNode())
+ break;
+
+ if (n && n->isFocusable() && n->isElementNode()) {
+ HTMLElement* e = static_cast<HTMLElement*>(n);
+ String tel;
+ String email;
+ String telbook;
+ // href
+ String attr = e->getAttribute(hrefAttr);
+ if (!attr.isNull() && !attr.isEmpty()) {
+ if ( attr.startsWith( KTel ) )
+ tel = attr.substring(4);
+ else if( attr.startsWith(KWtaiMC) )
+ tel = attr.substring(13);
+ else if( attr.startsWith(KWtaiAP) )
+ tel = attr.substring(13);
+ else if( attr.startsWith(KWtaiSD) )
+ tel = attr.substring(13);
+ else if ( attr.startsWith( KMailto ) ) {
+ email = attr.substring(7);
+ // Find just the email address
+ int i = email.find('?');
+ if (i > 0 ) {
+ email = email.left(i).stripWhiteSpace();
+ }
+ }
+ }
+ // cti
+ attr = e->getAttribute(ctiAttr);
+ if (!attr.isNull() && !attr.isEmpty() )
+ tel = attr;
+ // email
+ attr = e->getAttribute(emailAttr);
+ if (!attr.isNull() && !attr.isEmpty() )
+ email = attr;
+ // telbook
+ attr = e->getAttribute(telbookAttr);
+ if (!attr.isNull() && !attr.isEmpty() )
+ telbook = attr;
+ // Save to phone book
+ String url;
+ String makeCallUrlPrefix("wtai://wp/ap;");
+ char numberNameSeparator = ';';
+ int len = makeCallUrlPrefix.length() + 3; // NULL terminator and ';' separators
+ len += tel.length() + telbook.length() + email.length();
+ //url.reserve(len);
+ url = makeCallUrlPrefix;
+ url.append(tel);
+ url.append(numberNameSeparator);
+ url.append(telbook);
+ url.append(numberNameSeparator);
+ url.append(email);
+ handleSpecialSchemeL(url, webView->brCtl());
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Map the Symbian errors to rainbow errors.
+// -----------------------------------------------------------------------------
+//
+int mapHttpErrors(int err )
+{
+ if (err == KErrSSLAlertUserCanceled){
+ return KBrowserCancelled;
+ }
+ // All SSL errors are mapped into this one, which gets displayed to the user
+ if (err <= SSL_ERROR_BASE && err > SSL_ERROR_BASE - 200 ||
+ err == KErrHttpCannotEstablishTunnel) {
+ return KErrSSLAlertHandshakeFailure;
+ }
+
+ // Deal with DNS lookup errors
+ if ((err <= KErrInet6NoDestination) && (err > (KErrInet6NoDestination - 200))) {
+ return KBrowserHTTP502;
+ }
+
+ // Deal with HTTP errors
+ if (err <= KHttpErrorBase && err > KHttpErrorBase - 200) {
+ // Encode errors
+ if (err <= KErrHttpEncodeDefault && err >= KErrHttpEncodeCookie2) {
+ return KBrowserFailure;
+ }
+ // Auth errors
+ if (err == KErrHttpDecodeWWWAuthenticate ||
+ err == KErrHttpDecodeUnknownAuthScheme ||
+ err == KErrHttpDecodeBasicAuth ||
+ err == KErrHttpDecodeDigestAuth) {
+ return KBrowserMissingAuthHeader;
+ }
+
+ // Decode errors
+ if (err <= KErrHttpDecodeMalformedDate && err >= KErrHttpDecodeCookie) {
+ return KBrowserBadContent;
+ }
+ switch (err)
+ {
+ case KErrHttpRedirectExceededLimit:
+ {
+ return KBrowserTooManyRedirects;
+ }
+ case KErrHttpRedirectNoLocationField:
+ case KErrHttpRedirectUseProxy:
+ {
+ return KBrowserBadRedirect;
+ }
+ case KErrHttpInvalidUri:
+ {
+ return KBrowserMalformedUrl;
+ }
+ default:
+ {
+ return KBrowserFailure;
+ }
+ }
+ }
+ if (err <= KBrowserHTTP100 && err > KBrowserFailure)
+ return err;
+ switch (err)
+ {
+ case KErrHostUnreach:
+ {
+ return KBrowserTcpHostUnreachable;
+ }
+ case KErrAbort: //User has interrupted the loading process. We treat it as cancellation so that no error message shown.
+ case KErrCancel:
+ {
+ return KBrowserCancelled;
+ }
+ case KErrBadName:
+ case KErrPathNotFound:
+ {
+ return KBrowserFileNotFound;
+ }
+ case KErrCommsLineFail:
+ case KErrNotReady:
+ {
+ return KBrowserConnFailed;
+ }
+ case KErrDiskFull:
+ {
+ return KBrowserFileDiskFullError;
+ }
+ case KErrTimedOut:
+ {
+ return KBrowserWaitTimeout;
+ }
+ case KErrCouldNotConnect:
+ {
+ return KBrowserMalformedUrl;
+ }
+ case KErrDisconnected:
+ {
+ return KBrowserHTTP504;
+ }
+ case KErrNoMemory:
+ {
+ return KBrowserOutOfMemory;
+ }
+ default:
+ {
+ return KBrowserFailure;
+ }
+ } // end of switch
+}
+
+
+bool handleSelectElementScrolling(WebView* webView, int tb)
+{
+ bool ret = false;
+ if (webView->focusedElementType() == TBrCtlDefs::EElementSelectMultiBox && tb != 0) {
+ IntPoint point;
+ WebFrame* frame = frameAndPointUnderCursor(point, *webView);
+ Element* e = core(frame)->document()->elementFromPoint(point.x(), point.y());
+ if (e && e->isControl()) {
+ HTMLGenericFormElement* ie = static_cast<HTMLGenericFormElement*>( e );
+ if (ie->type() == "select-multiple") {
+ RenderListBox* render = static_cast<RenderListBox*>(e->renderer());
+ if (render->isScrollable()) {
+ HTMLSelectElement* selectElement = static_cast<HTMLSelectElement*>( e );
+ IntRect r = e->getRect();
+ int curIndex = render->listIndexAtOffset(point.x() - r.x(), point.y() - r.y());
+ int topIndex = render->indexOffset();
+ int bottomIndex = topIndex + selectElement->size() - 1;
+ TPoint curPointInSelectBox(point.x() - r.x(), point.y() - r.y());
+ IntRect itemRect = render->itemRect(0, 0, curIndex);
+ int centerOfRect = itemRect.y() + (itemRect.height() * 1) / 4;
+ if (tb == -1) {
+ if (curIndex == topIndex) {
+ if (render->scroll(ScrollUp, ScrollByLine)) {
+ ret = true;
+ }
+ }
+ else {
+ int step = ((itemRect.height() + (curPointInSelectBox.iY - centerOfRect)) * webView->scalingFactor()) / 100;
+ if (step <= 0) step = (itemRect.height() * webView->scalingFactor()) / 100;
+ TPoint tp(StaticObjectsContainer::instance()->webCursor()->position().iX, StaticObjectsContainer::instance()->webCursor()->position().iY - step);
+ StaticObjectsContainer::instance()->webCursor()->updatePositionAndElemType(tp);
+ ret = true;
+ }
+ }
+ else {
+ if (curIndex == bottomIndex) {
+ if (render->scroll(ScrollDown, ScrollByLine)) {
+ ret = true;
+ }
+ }
+ else {
+ int step = ((itemRect.height() + (centerOfRect - curPointInSelectBox.iY)) * webView->scalingFactor()) / 100;
+ if (step <= 0) step = (itemRect.height() * webView->scalingFactor()) / 100;
+ TPoint tp(StaticObjectsContainer::instance()->webCursor()->position().iX, StaticObjectsContainer::instance()->webCursor()->position().iY + step);
+ StaticObjectsContainer::instance()->webCursor()->updatePositionAndElemType(tp);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return ret;
+}
+