summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/page/WindowFeatures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/page/WindowFeatures.cpp')
-rw-r--r--Source/WebCore/page/WindowFeatures.cpp266
1 files changed, 266 insertions, 0 deletions
diff --git a/Source/WebCore/page/WindowFeatures.cpp b/Source/WebCore/page/WindowFeatures.cpp
new file mode 100644
index 0000000..a229ae1
--- /dev/null
+++ b/Source/WebCore/page/WindowFeatures.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reseved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include "config.h"
+#include "WindowFeatures.h"
+
+#include "FloatRect.h"
+#include "PlatformString.h"
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when parsing window features.
+static bool isWindowFeaturesSeparator(UChar c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
+}
+
+WindowFeatures::WindowFeatures(const String& features)
+ : xSet(false)
+ , ySet(false)
+ , widthSet(false)
+ , heightSet(false)
+ , fullscreen(false)
+ , dialog(false)
+{
+ /*
+ The IE rule is: all features except for channelmode and fullscreen default to YES, but
+ if the user specifies a feature string, all features default to NO. (There is no public
+ standard that applies to this method.)
+
+ <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
+ We always allow a window to be resized, which is consistent with Firefox.
+ */
+
+ if (features.length() == 0) {
+ menuBarVisible = true;
+ statusBarVisible = true;
+ toolBarVisible = true;
+ locationBarVisible = true;
+ scrollbarsVisible = true;
+ resizable = true;
+ return;
+ }
+
+ menuBarVisible = false;
+ statusBarVisible = false;
+ toolBarVisible = false;
+ locationBarVisible = false;
+ scrollbarsVisible = false;
+ resizable = true;
+
+ // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
+ int keyBegin, keyEnd;
+ int valueBegin, valueEnd;
+
+ int i = 0;
+ int length = features.length();
+ String buffer = features.lower();
+ while (i < length) {
+ // skip to first non-separator, but don't skip past the end of the string
+ while (isWindowFeaturesSeparator(buffer[i])) {
+ if (i >= length)
+ break;
+ i++;
+ }
+ keyBegin = i;
+
+ // skip to first separator
+ while (!isWindowFeaturesSeparator(buffer[i]))
+ i++;
+ keyEnd = i;
+
+ // skip to first '=', but don't skip past a ',' or the end of the string
+ while (buffer[i] != '=') {
+ if (buffer[i] == ',' || i >= length)
+ break;
+ i++;
+ }
+
+ // skip to first non-separator, but don't skip past a ',' or the end of the string
+ while (isWindowFeaturesSeparator(buffer[i])) {
+ if (buffer[i] == ',' || i >= length)
+ break;
+ i++;
+ }
+ valueBegin = i;
+
+ // skip to first separator
+ while (!isWindowFeaturesSeparator(buffer[i]))
+ i++;
+ valueEnd = i;
+
+ ASSERT(i <= length);
+
+ String keyString(buffer.substring(keyBegin, keyEnd - keyBegin));
+ String valueString(buffer.substring(valueBegin, valueEnd - valueBegin));
+ setWindowFeature(keyString, valueString);
+ }
+}
+
+void WindowFeatures::setWindowFeature(const String& keyString, const String& valueString)
+{
+ int value;
+
+ // Listing a key with no value is shorthand for key=yes
+ if (valueString.isEmpty() || valueString == "yes")
+ value = 1;
+ else
+ value = valueString.toInt();
+
+ // We treat keyString of "resizable" here as an additional feature rather than setting resizeable to true.
+ // This is consistent with Firefox, but could also be handled at another level.
+
+ if (keyString == "left" || keyString == "screenx") {
+ xSet = true;
+ x = value;
+ } else if (keyString == "top" || keyString == "screeny") {
+ ySet = true;
+ y = value;
+ } else if (keyString == "width" || keyString == "innerwidth") {
+ widthSet = true;
+ width = value;
+ } else if (keyString == "height" || keyString == "innerheight") {
+ heightSet = true;
+ height = value;
+ } else if (keyString == "menubar")
+ menuBarVisible = value;
+ else if (keyString == "toolbar")
+ toolBarVisible = value;
+ else if (keyString == "location")
+ locationBarVisible = value;
+ else if (keyString == "status")
+ statusBarVisible = value;
+ else if (keyString == "fullscreen")
+ fullscreen = value;
+ else if (keyString == "scrollbars")
+ scrollbarsVisible = value;
+ else if (value == 1)
+ additionalFeatures.append(keyString);
+}
+
+WindowFeatures::WindowFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
+ : widthSet(true)
+ , heightSet(true)
+ , menuBarVisible(false)
+ , toolBarVisible(false)
+ , locationBarVisible(false)
+ , fullscreen(false)
+ , dialog(true)
+{
+ DialogFeaturesMap features;
+ parseDialogFeatures(dialogFeaturesString, features);
+
+ const bool trusted = false;
+
+ // The following features from Microsoft's documentation are not implemented:
+ // - default font settings
+ // - width, height, left, and top specified in units other than "px"
+ // - edge (sunken or raised, default is raised)
+ // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
+ // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
+ // - unadorned: trusted && boolFeature(features, "unadorned");
+
+ width = floatFeature(features, "dialogwidth", 100, screenAvailableRect.width(), 620); // default here came from frame size of dialog in MacIE
+ height = floatFeature(features, "dialogheight", 100, screenAvailableRect.height(), 450); // default here came from frame size of dialog in MacIE
+
+ x = floatFeature(features, "dialogleft", screenAvailableRect.x(), screenAvailableRect.right() - width, -1);
+ xSet = x > 0;
+ y = floatFeature(features, "dialogtop", screenAvailableRect.y(), screenAvailableRect.bottom() - height, -1);
+ ySet = y > 0;
+
+ if (boolFeature(features, "center", true)) {
+ if (!xSet) {
+ x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
+ xSet = true;
+ }
+ if (!ySet) {
+ y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
+ ySet = true;
+ }
+ }
+
+ resizable = boolFeature(features, "resizable");
+ scrollbarsVisible = boolFeature(features, "scroll", true);
+ statusBarVisible = boolFeature(features, "status", !trusted);
+}
+
+bool WindowFeatures::boolFeature(const DialogFeaturesMap& features, const char* key, bool defaultValue)
+{
+ DialogFeaturesMap::const_iterator it = features.find(key);
+ if (it == features.end())
+ return defaultValue;
+ const String& value = it->second;
+ return value.isNull() || value == "1" || value == "yes" || value == "on";
+}
+
+float WindowFeatures::floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max, float defaultValue)
+{
+ DialogFeaturesMap::const_iterator it = features.find(key);
+ if (it == features.end())
+ return defaultValue;
+ // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
+ // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
+ bool ok;
+ double parsedNumber = it->second.toDouble(&ok);
+ if ((parsedNumber == 0 && !ok) || isnan(parsedNumber))
+ return defaultValue;
+ if (parsedNumber < min || max <= min)
+ return min;
+ if (parsedNumber > max)
+ return max;
+ // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
+ return static_cast<int>(parsedNumber);
+}
+
+void WindowFeatures::parseDialogFeatures(const String& string, DialogFeaturesMap& map)
+{
+ Vector<String> vector;
+ string.split(';', vector);
+ size_t size = vector.size();
+ for (size_t i = 0; i < size; ++i) {
+ const String& featureString = vector[i];
+
+ size_t separatorPosition = featureString.find('=');
+ size_t colonPosition = featureString.find(':');
+ if (separatorPosition != notFound && colonPosition != notFound)
+ continue; // ignore strings that have both = and :
+ if (separatorPosition == notFound)
+ separatorPosition = colonPosition;
+
+ String key = featureString.left(separatorPosition).stripWhiteSpace().lower();
+
+ // Null string for value indicates key without value.
+ String value;
+ if (separatorPosition != notFound) {
+ value = featureString.substring(separatorPosition + 1).stripWhiteSpace().lower();
+ value = value.left(value.find(' '));
+ }
+
+ map.set(key, value);
+ }
+}
+
+} // namespace WebCore