15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Copyright (C) 2000 Harri Porten (porten@kde.org)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reseved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  This library is free software; you can redistribute it and/or
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  modify it under the terms of the GNU Lesser General Public
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  License as published by the Free Software Foundation; either
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  version 2 of the License, or (at your option) any later version.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  This library is distributed in the hope that it will be useful,
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  but WITHOUT ANY WARRANTY; without even the implied warranty of
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Lesser General Public License for more details.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  You should have received a copy of the GNU Lesser General Public
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  License along with this library; if not, write to the Free Software
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *  USA
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/WindowFeatures.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
270019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch#include "wtf/Assertions.h"
280019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch#include "wtf/MathExtras.h"
290019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch#include "wtf/text/StringHash.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isWindowFeaturesSeparator(UChar c)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WindowFeatures::WindowFeatures(const String& features)
4010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    : x(0)
4110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , xSet(false)
4210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , y(0)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , ySet(false)
4410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , width(0)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , widthSet(false)
4610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , height(0)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , heightSet(false)
4810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , resizable(true)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , fullscreen(false)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , dialog(false)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /*
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     The IE rule is: all features except for channelmode and fullscreen default to YES, but
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     if the user specifies a feature string, all features default to NO. (There is no public
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     standard that applies to this method.)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     We always allow a window to be resized, which is consistent with Firefox.
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (features.isEmpty()) {
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        menuBarVisible = true;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        statusBarVisible = true;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        toolBarVisible = true;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        locationBarVisible = true;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scrollbarsVisible = true;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    menuBarVisible = false;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    statusBarVisible = false;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    toolBarVisible = false;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    locationBarVisible = false;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scrollbarsVisible = false;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    unsigned keyBegin, keyEnd;
785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    unsigned valueBegin, valueEnd;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String buffer = features.lower();
815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    unsigned length = buffer.length();
825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (unsigned i = 0; i < length; ) {
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // skip to first non-separator, but don't skip past the end of the string
8410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        while (i < length && isWindowFeaturesSeparator(buffer[i]))
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i++;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        keyBegin = i;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // skip to first separator
8910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        while (i < length && !isWindowFeaturesSeparator(buffer[i]))
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i++;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        keyEnd = i;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
9410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // skip to first '=', but don't skip past a ',' or the end of the string
9610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        while (i < length && buffer[i] != '=') {
9710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (buffer[i] == ',')
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i++;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
10310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // skip to first non-separator, but don't skip past a ',' or the end of the string
10510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        while (i < length && isWindowFeaturesSeparator(buffer[i])) {
10610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (buffer[i] == ',')
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i++;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        valueBegin = i;
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
11310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // skip to first separator
11510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        while (i < length && !isWindowFeaturesSeparator(buffer[i]))
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i++;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        valueEnd = i;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT_WITH_SECURITY_IMPLICATION(i <= length);
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setWindowFeature(keyString, valueString);
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int value;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Listing a key with no value is shorthand for key=yes
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (valueString.isEmpty() || valueString == "yes")
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        value = 1;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        value = valueString.toInt();
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is consistent with Firefox, but could also be handled at another level.
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (keyString == "left" || keyString == "screenx") {
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        xSet = true;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        x = value;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (keyString == "top" || keyString == "screeny") {
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ySet = true;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        y = value;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (keyString == "width" || keyString == "innerwidth") {
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        widthSet = true;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        width = value;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (keyString == "height" || keyString == "innerheight") {
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        heightSet = true;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        height = value;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (keyString == "menubar")
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        menuBarVisible = value;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (keyString == "toolbar")
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        toolBarVisible = value;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (keyString == "location")
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        locationBarVisible = value;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (keyString == "status")
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        statusBarVisible = value;
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (keyString == "fullscreen")
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fullscreen = value;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (keyString == "scrollbars")
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scrollbarsVisible = value;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value == 1)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        additionalFeatures.append(keyString);
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : widthSet(true)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , heightSet(true)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , menuBarVisible(false)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , toolBarVisible(false)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , locationBarVisible(false)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , fullscreen(false)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , dialog(true)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DialogFeaturesMap features;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parseDialogFeatures(dialogFeaturesString, features);
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const bool trusted = false;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The following features from Microsoft's documentation are not implemented:
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - default font settings
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - width, height, left, and top specified in units other than "px"
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - edge (sunken or raised, default is raised)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // - unadorned: trusted && boolFeature(features, "unadorned");
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - width, -1);
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    xSet = x > 0;
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - height, -1);
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ySet = y > 0;
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (boolFeature(features, "center", true)) {
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!xSet) {
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            xSet = true;
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!ySet) {
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ySet = true;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resizable = boolFeature(features, "resizable");
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scrollbarsVisible = boolFeature(features, "scroll", true);
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    statusBarVisible = boolFeature(features, "status", !trusted);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WindowFeatures::boolFeature(const DialogFeaturesMap& features, const char* key, bool defaultValue)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DialogFeaturesMap::const_iterator it = features.find(key);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (it == features.end())
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return defaultValue;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const String& value = it->value;
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return value.isNull() || value == "1" || value == "yes" || value == "on";
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float WindowFeatures::floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max, float defaultValue)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DialogFeaturesMap::const_iterator it = features.find(key);
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (it == features.end())
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return defaultValue;
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool ok;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double parsedNumber = it->value.toDouble(&ok);
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return defaultValue;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parsedNumber < min || max <= min)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return min;
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parsedNumber > max)
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return max;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return static_cast<int>(parsedNumber);
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WindowFeatures::parseDialogFeatures(const String& string, DialogFeaturesMap& map)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> vector;
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    string.split(';', vector);
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = vector.size();
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < size; ++i) {
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const String& featureString = vector[i];
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size_t separatorPosition = featureString.find('=');
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size_t colonPosition = featureString.find(':');
25206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (separatorPosition != kNotFound && colonPosition != kNotFound)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue; // ignore strings that have both = and :
25406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (separatorPosition == kNotFound)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            separatorPosition = colonPosition;
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Null string for value indicates key without value.
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String value;
26106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (separatorPosition != kNotFound) {
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value = value.left(value.find(' '));
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        map.set(key, value);
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
270c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
271