You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pm...@apache.org on 2012/02/15 18:42:37 UTC

[29/51] [partial] Apache-ization, port to node.js

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js
new file mode 100644
index 0000000..4bd5c65
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/SummaryBar.js
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008, 2009 Anthony Ricaud <ri...@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SummaryBar = function(categories)
+{
+    this.categories = categories;
+
+    this.element = document.createElement("div");
+    this.element.className = "summary-bar";
+
+    this.graphElement = document.createElement("canvas");
+    this.graphElement.setAttribute("width", "450");
+    this.graphElement.setAttribute("height", "38");
+    this.graphElement.className = "summary-graph";
+    this.element.appendChild(this.graphElement);
+
+    this.legendElement = document.createElement("div");
+    this.legendElement.className = "summary-graph-legend";
+    this.element.appendChild(this.legendElement);
+}
+
+WebInspector.SummaryBar.prototype = {
+
+    get calculator() {
+        return this._calculator;
+    },
+
+    set calculator(x) {
+        this._calculator = x;
+    },
+
+    reset: function()
+    {
+        this.legendElement.removeChildren();
+        this._drawSummaryGraph();
+    },
+
+    update: function(data)
+    {
+        var graphInfo = this.calculator.computeSummaryValues(data);
+
+        var fillSegments = [];
+
+        this.legendElement.removeChildren();
+
+        for (var category in this.categories) {
+            var size = graphInfo.categoryValues[category];
+            if (!size)
+                continue;
+
+            var colorString = this.categories[category].color;
+
+            var fillSegment = {color: colorString, value: size};
+            fillSegments.push(fillSegment);
+
+            var legendLabel = this._makeLegendElement(this.categories[category].title, this.calculator.formatValue(size), colorString);
+            this.legendElement.appendChild(legendLabel);
+        }
+
+        if (graphInfo.total) {
+            var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
+            totalLegendLabel.addStyleClass("total");
+            this.legendElement.appendChild(totalLegendLabel);
+        }
+
+        this._drawSummaryGraph(fillSegments);
+    },
+
+    _drawSwatch: function(canvas, color)
+    {
+        var ctx = canvas.getContext("2d");
+
+        function drawSwatchSquare() {
+            ctx.fillStyle = color;
+            ctx.fillRect(0, 0, 13, 13);
+
+            var gradient = ctx.createLinearGradient(0, 0, 13, 13);
+            gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
+            gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+            ctx.fillStyle = gradient;
+            ctx.fillRect(0, 0, 13, 13);
+
+            gradient = ctx.createLinearGradient(13, 13, 0, 0);
+            gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
+            gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
+
+            ctx.fillStyle = gradient;
+            ctx.fillRect(0, 0, 13, 13);
+
+            ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
+            ctx.strokeRect(0.5, 0.5, 12, 12);
+        }
+
+        ctx.clearRect(0, 0, 13, 24);
+
+        drawSwatchSquare();
+
+        ctx.save();
+
+        ctx.translate(0, 25);
+        ctx.scale(1, -1);
+
+        drawSwatchSquare();
+
+        ctx.restore();
+
+        this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
+    },
+
+    _drawSummaryGraph: function(segments)
+    {
+        if (!segments || !segments.length) {
+            segments = [{color: "white", value: 1}];
+            this._showingEmptySummaryGraph = true;
+        } else
+            delete this._showingEmptySummaryGraph;
+
+        // Calculate the total of all segments.
+        var total = 0;
+        for (var i = 0; i < segments.length; ++i)
+            total += segments[i].value;
+
+        // Calculate the percentage of each segment, rounded to the nearest percent.
+        var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
+
+        // Calculate the total percentage.
+        var percentTotal = 0;
+        for (var i = 0; i < percents.length; ++i)
+            percentTotal += percents[i];
+
+        // Make sure our percentage total is not greater-than 100, it can be greater
+        // if we rounded up for a few segments.
+        while (percentTotal > 100) {
+            for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
+                if (percents[i] > 1) {
+                    --percents[i];
+                    --percentTotal;
+                }
+            }
+        }
+
+        // Make sure our percentage total is not less-than 100, it can be less
+        // if we rounded down for a few segments.
+        while (percentTotal < 100) {
+            for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
+                ++percents[i];
+                ++percentTotal;
+            }
+        }
+
+        var ctx = this.graphElement.getContext("2d");
+
+        var x = 0;
+        var y = 0;
+        var w = 450;
+        var h = 19;
+        var r = (h / 2);
+
+        function drawPillShadow()
+        {
+            // This draws a line with a shadow that is offset away from the line. The line is stroked
+            // twice with different X shadow offsets to give more feathered edges. Later we erase the
+            // line with destination-out 100% transparent black, leaving only the shadow. This only
+            // works if nothing has been drawn into the canvas yet.
+
+            ctx.beginPath();
+            ctx.moveTo(x + 4, y + h - 3 - 0.5);
+            ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
+            ctx.closePath();
+
+            ctx.save();
+
+            ctx.shadowBlur = 2;
+            ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
+            ctx.shadowOffsetX = 3;
+            ctx.shadowOffsetY = 5;
+
+            ctx.strokeStyle = "white";
+            ctx.lineWidth = 1;
+
+            ctx.stroke();
+
+            ctx.shadowOffsetX = -3;
+
+            ctx.stroke();
+
+            ctx.restore();
+
+            ctx.save();
+
+            ctx.globalCompositeOperation = "destination-out";
+            ctx.strokeStyle = "rgba(0, 0, 0, 1)";
+            ctx.lineWidth = 1;
+
+            ctx.stroke();
+
+            ctx.restore();
+        }
+
+        function drawPill()
+        {
+            // Make a rounded rect path.
+            ctx.beginPath();
+            ctx.moveTo(x, y + r);
+            ctx.lineTo(x, y + h - r);
+            ctx.arc(x + r, y + h - r, r, Math.PI, Math.PI / 2, true);
+            ctx.lineTo(x + w - r, y + h);
+            ctx.arc(x + w - r, y + h - r, r, Math.PI / 2, 0, true);
+            ctx.lineTo(x + w, y + r);
+            ctx.arc(x + w - r, y + r, r, 0, 3 * Math.PI / 2, true);
+            ctx.lineTo(x + r, y);
+            ctx.arc(x + r, y + r, r, Math.PI / 2, Math.PI, true);
+            ctx.closePath();
+
+            // Clip to the rounded rect path.
+            ctx.save();
+            ctx.clip();
+
+            // Fill the segments with the associated color.
+            var previousSegmentsWidth = 0;
+            for (var i = 0; i < segments.length; ++i) {
+                var segmentWidth = Math.round(w * percents[i] / 100);
+                ctx.fillStyle = segments[i].color;
+                ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
+                previousSegmentsWidth += segmentWidth;
+            }
+
+            // Draw the segment divider lines.
+            ctx.lineWidth = 1;
+            for (var i = 1; i < 20; ++i) {
+                ctx.beginPath();
+                ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
+                ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
+                ctx.closePath();
+
+                ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
+                ctx.stroke();
+
+                ctx.beginPath();
+                ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
+                ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
+                ctx.closePath();
+
+                ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
+                ctx.stroke();
+            }
+
+            // Draw the pill shading.
+            var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
+            lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
+            lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
+            lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+            var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
+            darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
+            darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
+            darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
+
+            ctx.fillStyle = darkGradient;
+            ctx.fillRect(x, y, w, h);
+
+            ctx.fillStyle = lightGradient;
+            ctx.fillRect(x, y, w, h);
+
+            ctx.restore();
+        }
+
+        ctx.clearRect(x, y, w, (h * 2));
+
+        drawPillShadow();
+        drawPill();
+
+        ctx.save();
+
+        ctx.translate(0, (h * 2) + 1);
+        ctx.scale(1, -1);
+
+        drawPill();
+
+        ctx.restore();
+
+        this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
+    },
+
+    _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
+    {
+        ctx.save();
+
+        var gradient = ctx.createLinearGradient(x, y, x, y + h);
+        gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
+        gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
+        gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
+
+        ctx.globalCompositeOperation = "destination-out";
+
+        ctx.fillStyle = gradient;
+        ctx.fillRect(x, y, w, h);
+
+        ctx.restore();
+    },
+
+    _makeLegendElement: function(label, value, color)
+    {
+        var legendElement = document.createElement("label");
+        legendElement.className = "summary-graph-legend-item";
+
+        if (color) {
+            var swatch = document.createElement("canvas");
+            swatch.className = "summary-graph-legend-swatch";
+            swatch.setAttribute("width", "13");
+            swatch.setAttribute("height", "24");
+
+            legendElement.appendChild(swatch);
+
+            this._drawSwatch(swatch, color);
+        }
+
+        var labelElement = document.createElement("div");
+        labelElement.className = "summary-graph-legend-label";
+        legendElement.appendChild(labelElement);
+
+        var headerElement = document.createElement("div");
+        headerElement.className = "summary-graph-legend-header";
+        headerElement.textContent = label;
+        labelElement.appendChild(headerElement);
+
+        var valueElement = document.createElement("div");
+        valueElement.className = "summary-graph-legend-value";
+        valueElement.textContent = value;
+        labelElement.appendChild(valueElement);
+
+        return legendElement;
+    }
+}
+
+WebInspector.SummaryBar.prototype.__proto__ = WebInspector.Object.prototype;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js
new file mode 100644
index 0000000..84ab702
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TabbedPane.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TabbedPane = function(element)
+{
+    this.element = element || document.createElement("div");
+    this.element.addStyleClass("tabbed-pane");
+    this._tabsElement = this.element.createChild("div", "tabbed-pane-header");
+    this._contentElement = this.element.createChild("div", "tabbed-pane-content");
+    this._tabs = {};
+}
+
+WebInspector.TabbedPane.prototype = {
+    appendTab: function(id, tabTitle, view)
+    {
+        var tabElement = document.createElement("li");
+        tabElement.textContent = tabTitle;
+        tabElement.addEventListener("click", this.selectTab.bind(this, id, true), false);
+
+        this._tabsElement.appendChild(tabElement);
+        this._contentElement.appendChild(view.element);
+
+        this._tabs[id] = { tabElement: tabElement, view: view }
+    },
+
+    selectTab: function(id, userGesture)
+    {
+        if (!(id in this._tabs))
+            return false;
+
+        if (this._currentTab) {
+            this._hideTab(this._currentTab)
+            delete this._currentTab;
+        }
+
+        var tab = this._tabs[id];
+        this._showTab(tab);
+        this._currentTab = tab;
+        if (userGesture) {
+            var event = {tabId: id};
+            this.dispatchEventToListeners("tab-selected", event);
+        }
+        return true;
+    },
+
+    _showTab: function(tab)
+    {
+        tab.tabElement.addStyleClass("selected");
+        tab.view.show(this._contentElement);
+    },
+
+    _hideTab: function(tab)
+    {
+        tab.tabElement.removeStyleClass("selected");
+        tab.view.visible = false;
+    }
+}
+
+WebInspector.TabbedPane.prototype.__proto__ = WebInspector.Object.prototype;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js
new file mode 100644
index 0000000..3bfe28c
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TestController.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TestController = function(callId)
+{
+    this._callId = callId;
+    this._waitUntilDone = false;
+    this.results = [];
+}
+
+WebInspector.TestController.prototype = {
+    waitUntilDone: function()
+    {
+        this._waitUntilDone = true;
+    },
+
+    notifyDone: function(result)
+    {
+        if (typeof result === "undefined" && this.results.length)
+            result = this.results;
+        var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result);
+        InspectorBackend.didEvaluateForTestInFrontend(this._callId, message);
+    },
+
+    runAfterPendingDispatches: function(callback)
+    {
+        if (WebInspector.pendingDispatches === 0) {
+            callback();
+            return;
+        }
+        setTimeout(this.runAfterPendingDispatches.bind(this), 0, callback);
+    }
+}
+
+WebInspector.evaluateForTestInFrontend = function(callId, script)
+{
+    var controller = new WebInspector.TestController(callId);
+    function invokeMethod()
+    {
+        try {
+            var result;
+            if (window[script] && typeof window[script] === "function")
+                result = window[script].call(WebInspector, controller);
+            else
+                result = window.eval(script);
+
+            if (!controller._waitUntilDone)
+                controller.notifyDone(result);
+        } catch (e) {
+            controller.notifyDone(e.toString());
+        }
+    }
+    controller.runAfterPendingDispatches(invokeMethod);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js
new file mode 100644
index 0000000..4ac831e
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorHighlighter.js
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
+{
+    this._textModel = textModel;
+    this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html");
+    this._damageCallback = damageCallback;
+    this.reset();
+}
+
+WebInspector.TextEditorHighlighter.prototype = {
+    set mimeType(mimeType)
+    {
+        var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
+        if (tokenizer) {
+            this._tokenizer = tokenizer;
+            this._tokenizerCondition = this._tokenizer.initialCondition;
+        }
+    },
+
+    reset: function()
+    {
+        this._lastHighlightedLine = 0;
+        this._lastHighlightedColumn = 0;
+        this._tokenizerCondition = this._tokenizer.initialCondition;
+    },
+
+    highlight: function(endLine)
+    {
+        // First check if we have work to do.
+        if (endLine <= this._lastHighlightedLine)
+            return;
+
+        this._requestedEndLine = endLine;
+
+        if (this._highlightTimer) {
+            // There is a timer scheduled, it will catch the new job based on the new endLine set.
+            return;
+        }
+
+        // Do small highlight synchronously. This will provide instant highlight on PageUp / PageDown, gentle scrolling.
+        this._highlightInChunks(endLine);
+
+        // Schedule tail highlight if necessary.
+        if (this._lastHighlightedLine < endLine)
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
+    },
+
+    _highlightInChunks: function(endLine)
+    {
+        delete this._highlightTimer;
+
+        // First we always check if we have work to do. Could be that user scrolled back and we can quit.
+        if (this._requestedEndLine <= this._lastHighlightedLine)
+            return;
+
+        if (this._requestedEndLine !== endLine) {
+            // User keeps updating the job in between of our timer ticks. Just reschedule self, don't eat CPU (they must be scrolling).
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 100);
+            return;
+        }
+
+        this._highlightLines(this._requestedEndLine);
+
+        // Schedule tail highlight if necessary.
+        if (this._lastHighlightedLine < this._requestedEndLine)
+            this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._requestedEndLine), 10);
+    },
+
+    _highlightLines: function(endLine)
+    {
+        // Tokenizer is stateless and reused accross viewers, restore its condition before highlight and save it after.
+        this._tokenizer.condition = this._tokenizerCondition;
+        var tokensCount = 0;
+        for (var lineNumber = this._lastHighlightedLine; lineNumber < endLine; ++lineNumber) {
+            var line = this._textModel.line(lineNumber);
+            this._tokenizer.line = line;
+            var attributes = this._textModel.getAttribute(lineNumber, "highlight") || {};
+
+            // Highlight line.
+            do {
+                var newColumn = this._tokenizer.nextToken(this._lastHighlightedColumn);
+                var tokenType = this._tokenizer.tokenType;
+                if (tokenType)
+                    attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType, subTokenizer: this._tokenizer.subTokenizer };
+                this._lastHighlightedColumn = newColumn;
+                if (++tokensCount > 1000)
+                    break;
+            } while (this._lastHighlightedColumn < line.length)
+
+            this._textModel.setAttribute(lineNumber, "highlight", attributes);
+            if (this._lastHighlightedColumn < line.length) {
+                // Too much work for single chunk - exit.
+                break;
+            } else
+                this._lastHighlightedColumn = 0;
+        }
+
+        this._damageCallback(this._lastHighlightedLine, lineNumber);
+        this._tokenizerCondition = this._tokenizer.condition;
+        this._lastHighlightedLine = lineNumber;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js
new file mode 100644
index 0000000..f23ce76
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextEditorModel.js
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn)
+{
+    this.startLine = startLine;
+    this.startColumn = startColumn;
+    this.endLine = endLine;
+    this.endColumn = endColumn;
+}
+
+WebInspector.TextRange.prototype = {
+    isEmpty: function()
+    {
+        return this.startLine === this.endLine && this.startColumn === this.endColumn;
+    },
+
+    get linesCount()
+    {
+        return this.endLine - this.startLine;
+    },
+
+    clone: function()
+    {
+        return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); 
+    }
+}
+
+WebInspector.TextEditorModel = function()
+{
+    this._lines = [""];
+    this._attributes = [];
+    this._undoStack = [];
+    this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/;
+}
+
+WebInspector.TextEditorModel.prototype = {
+    set changeListener(changeListener)
+    {
+        this._changeListener = changeListener;
+    },
+
+    get linesCount()
+    {
+        return this._lines.length;
+    },
+
+    line: function(lineNumber)
+    {
+        if (lineNumber >= this._lines.length)
+            throw "Out of bounds:" + lineNumber;
+        return this._lines[lineNumber];
+    },
+
+    lineLength: function(lineNumber)
+    {
+        return this._lines[lineNumber].length;
+    },
+
+    setText: function(range, text)
+    {
+        if (!range)
+            range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);
+        var command = this._pushUndoableCommand(range, text);
+        var newRange = this._innerSetText(range, text);
+        command.range = newRange.clone();
+
+        if (this._changeListener)
+            this._changeListener(range, newRange, command.text, text);
+        return newRange;
+    },
+
+    set replaceTabsWithSpaces(replaceTabsWithSpaces)
+    {
+        this._replaceTabsWithSpaces = replaceTabsWithSpaces;
+    },
+
+    _innerSetText: function(range, text)
+    {
+        this._eraseRange(range);
+        if (text === "")
+            return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn);
+
+        var newLines = text.split("\n");
+        this._replaceTabsIfNeeded(newLines);
+
+        var prefix = this._lines[range.startLine].substring(0, range.startColumn);
+        var prefixArguments = this._arguments
+        var suffix = this._lines[range.startLine].substring(range.startColumn);
+
+        var postCaret = prefix.length;
+        // Insert text.
+        if (newLines.length === 1) {
+            this._setLine(range.startLine, prefix + newLines[0] + suffix);
+            postCaret += newLines[0].length;
+        } else {
+            this._setLine(range.startLine, prefix + newLines[0]);
+            for (var i = 1; i < newLines.length; ++i)
+                this._insertLine(range.startLine + i, newLines[i]);
+            this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix);
+            postCaret = newLines[newLines.length - 1].length;
+        }
+        return new WebInspector.TextRange(range.startLine, range.startColumn,
+                                          range.startLine + newLines.length - 1, postCaret);
+    },
+
+    _replaceTabsIfNeeded: function(lines)
+    {
+        if (!this._replaceTabsWithSpaces)
+            return;
+        var spaces = [ "    ", "   ", "  ", " "];
+        for (var i = 0; i < lines.length; ++i) {
+            var line = lines[i];
+            var index = line.indexOf("\t");
+            while (index !== -1) {
+                line = line.substring(0, index) + spaces[index % 4] + line.substring(index + 1);
+                index = line.indexOf("\t", index + 1);
+            }
+            lines[i] = line;
+        }
+    },
+
+    _eraseRange: function(range)
+    {
+        if (range.isEmpty())
+            return;
+
+        var prefix = this._lines[range.startLine].substring(0, range.startColumn);
+        var suffix = this._lines[range.endLine].substring(range.endColumn);
+
+        if (range.endLine > range.startLine)
+            this._removeLines(range.startLine + 1, range.endLine - range.startLine);
+        this._setLine(range.startLine, prefix + suffix);
+    },
+
+    _setLine: function(lineNumber, text)
+    {
+        this._lines[lineNumber] = text;
+    },
+
+    _removeLines: function(fromLine, count)
+    {
+        this._lines.splice(fromLine, count);
+        this._attributes.splice(fromLine, count);
+    },
+
+    _insertLine: function(lineNumber, text)
+    {
+        this._lines.splice(lineNumber, 0, text);
+        this._attributes.splice(lineNumber, 0, {});
+    },
+
+    wordRange: function(lineNumber, column)
+    {
+        return new WebInspector.TextRange(lineNumber, this.wordStart(lineNumber, column, true), lineNumber, this.wordEnd(lineNumber, column, true));
+    },
+
+    wordStart: function(lineNumber, column, gapless)
+    {
+        var line = this._lines[lineNumber];
+        var prefix = line.substring(0, column).split("").reverse().join("");
+        var prefixMatch = this._noPunctuationRegex.exec(prefix);
+        return prefixMatch && (!gapless || prefixMatch.index === 0) ? column - prefixMatch.index - prefixMatch[0].length : column;
+    },
+
+    wordEnd: function(lineNumber, column, gapless)
+    {
+        var line = this._lines[lineNumber];
+        var suffix = line.substring(column);
+        var suffixMatch = this._noPunctuationRegex.exec(suffix);
+        return suffixMatch && (!gapless || suffixMatch.index === 0) ? column + suffixMatch.index + suffixMatch[0].length : column;
+    },
+
+    copyRange: function(range)
+    {
+        if (!range)
+            range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);
+
+        var clip = [];
+        if (range.startLine === range.endLine) {
+            clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn));
+            return clip.join("\n");
+        }
+        clip.push(this._lines[range.startLine].substring(range.startColumn));
+        for (var i = range.startLine + 1; i < range.endLine; ++i)
+            clip.push(this._lines[i]);
+        clip.push(this._lines[range.endLine].substring(0, range.endColumn));
+        return clip.join("\n");
+    },
+
+    setAttribute: function(line, name, value)
+    {
+        var attrs = this._attributes[line];
+        if (!attrs) {
+            attrs = {};
+            this._attributes[line] = attrs;
+        }
+        attrs[name] = value;
+    },
+
+    getAttribute: function(line, name)
+    {
+        var attrs = this._attributes[line];
+        return attrs ? attrs[name] : null;
+    },
+
+    removeAttribute: function(line, name)
+    {
+        var attrs = this._attributes[line];
+        if (attrs)
+            delete attrs[name];
+    },
+
+    _pushUndoableCommand: function(range, text)
+    {
+        var command = {
+            text: this.copyRange(range),
+            startLine: range.startLine,
+            startColumn: range.startColumn,
+            endLine: range.startLine,
+            endColumn: range.startColumn
+        };
+        if (this._inUndo)
+            this._redoStack.push(command);
+        else {
+            if (!this._inRedo)
+                this._redoStack = [];
+            this._undoStack.push(command);
+        }
+        return command;
+    },
+
+    undo: function()
+    {
+        this._markRedoableState();
+
+        this._inUndo = true;
+        var range = this._doUndo(this._undoStack);
+        delete this._inUndo;
+
+        return range;
+    },
+
+    redo: function()
+    {
+        this.markUndoableState();
+
+        this._inRedo = true;
+        var range = this._doUndo(this._redoStack);
+        delete this._inRedo;
+
+        return range;
+    },
+
+    _doUndo: function(stack)
+    {
+        var range = null;
+        for (var i = stack.length - 1; i >= 0; --i) {
+            var command = stack[i];
+            stack.length = i;
+
+            range = this.setText(command.range, command.text);
+            if (i > 0 && stack[i - 1].explicit)
+                return range;
+        }
+        return range;
+    },
+
+    markUndoableState: function()
+    {
+        if (this._undoStack.length)
+            this._undoStack[this._undoStack.length - 1].explicit = true;
+    },
+
+    _markRedoableState: function()
+    {
+        if (this._redoStack.length)
+            this._redoStack[this._redoStack.length - 1].explicit = true;
+    },
+
+    resetUndoStack: function()
+    {
+        this._undoStack = [];
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre/blob/c4fbd3d0/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js
----------------------------------------------------------------------
diff --git a/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js
new file mode 100644
index 0000000..36a38cc
--- /dev/null
+++ b/weinre.build/vendor/webkit/WebCore/inspector/front-end/TextPrompt.js
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2008 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextPrompt = function(element, completions, stopCharacters, omitHistory)
+{
+    this.element = element;
+    this.element.addStyleClass("text-prompt");
+    this.completions = completions;
+    this.completionStopCharacters = stopCharacters;
+    if (!omitHistory) {
+        this.history = [];
+        this.historyOffset = 0;
+    }
+    this._boundOnKeyDown = this._onKeyDown.bind(this);
+    this.element.addEventListener("keydown", this._boundOnKeyDown, true);
+}
+
+WebInspector.TextPrompt.prototype = {
+    get text()
+    {
+        return this.element.textContent;
+    },
+
+    set text(x)
+    {
+        if (!x) {
+            // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
+            this.element.removeChildren();
+            this.element.appendChild(document.createElement("br"));
+        } else
+            this.element.textContent = x;
+
+        this.moveCaretToEndOfPrompt();
+    },
+
+    removeFromElement: function()
+    {
+        this.clearAutoComplete(true);
+        this.element.removeEventListener("keydown", this._boundOnKeyDown, true);
+    },
+
+    _onKeyDown: function(event)
+    {
+        function defaultAction()
+        {
+            this.clearAutoComplete();
+            this.autoCompleteSoon();
+        }
+
+        if (event.handled)
+            return;
+
+        var handled = false;
+
+        switch (event.keyIdentifier) {
+            case "Up":
+                this.upKeyPressed(event);
+                break;
+            case "Down":
+                this.downKeyPressed(event);
+                break;
+            case "U+0009": // Tab
+                this.tabKeyPressed(event);
+                break;
+            case "Right":
+            case "End":
+                if (!this.acceptAutoComplete())
+                    this.autoCompleteSoon();
+                break;
+            case "Alt":
+            case "Meta":
+            case "Shift":
+            case "Control":
+                break;
+            case "U+0050": // Ctrl+P = Previous
+                if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
+                    handled = true;
+                    this._moveBackInHistory();
+                    break;
+                }
+                defaultAction.call(this);
+                break;
+            case "U+004E": // Ctrl+N = Next
+                if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
+                    handled = true;
+                    this._moveForwardInHistory();
+                    break;
+                }
+                defaultAction.call(this);
+                break;
+            default:
+                defaultAction.call(this);
+                break;
+        }
+
+        handled |= event.handled;
+        if (handled) {
+            event.handled = true;
+            event.preventDefault();
+            event.stopPropagation();
+        }
+    },
+
+    acceptAutoComplete: function()
+    {
+        if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
+            return false;
+
+        var text = this.autoCompleteElement.textContent;
+        var textNode = document.createTextNode(text);
+        this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
+        delete this.autoCompleteElement;
+
+        var finalSelectionRange = document.createRange();
+        finalSelectionRange.setStart(textNode, text.length);
+        finalSelectionRange.setEnd(textNode, text.length);
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+
+        return true;
+    },
+
+    clearAutoComplete: function(includeTimeout)
+    {
+        if (includeTimeout && "_completeTimeout" in this) {
+            clearTimeout(this._completeTimeout);
+            delete this._completeTimeout;
+        }
+
+        if (!this.autoCompleteElement)
+            return;
+
+        if (this.autoCompleteElement.parentNode)
+            this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
+        delete this.autoCompleteElement;
+
+        if (!this._userEnteredRange || !this._userEnteredText)
+            return;
+
+        this._userEnteredRange.deleteContents();
+        this.element.pruneEmptyTextNodes();
+
+        var userTextNode = document.createTextNode(this._userEnteredText);
+        this._userEnteredRange.insertNode(userTextNode);
+
+        var selectionRange = document.createRange();
+        selectionRange.setStart(userTextNode, this._userEnteredText.length);
+        selectionRange.setEnd(userTextNode, this._userEnteredText.length);
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+
+        delete this._userEnteredRange;
+        delete this._userEnteredText;
+    },
+
+    autoCompleteSoon: function()
+    {
+        if (!("_completeTimeout" in this))
+            this._completeTimeout = setTimeout(this.complete.bind(this, true), 250);
+    },
+
+    complete: function(auto, reverse)
+    {
+        this.clearAutoComplete(true);
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        var isEmptyInput = selectionRange.commonAncestorContainer === this.element; // this.element has no child Text nodes.
+
+        // Do not attempt to auto-complete an empty input in the auto mode (only on demand).
+        if (auto && isEmptyInput)
+            return;
+        if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this.element))
+            return;
+        if (auto && !this.isCaretAtEndOfPrompt())
+            return;
+        var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
+        this.completions(wordPrefixRange, auto, this._completionsReady.bind(this, selection, auto, wordPrefixRange, reverse));
+    },
+
+    _completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions)
+    {
+        if (!completions || !completions.length)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+
+        var fullWordRange = document.createRange();
+        fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset);
+        fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+
+        if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString())
+            return;
+
+        var wordPrefixLength = originalWordPrefixRange.toString().length;
+
+        if (auto)
+            var completionText = completions[0];
+        else {
+            if (completions.length === 1) {
+                var completionText = completions[0];
+                wordPrefixLength = completionText.length;
+            } else {
+                var commonPrefix = completions[0];
+                for (var i = 0; i < completions.length; ++i) {
+                    var completion = completions[i];
+                    var lastIndex = Math.min(commonPrefix.length, completion.length);
+                    for (var j = wordPrefixLength; j < lastIndex; ++j) {
+                        if (commonPrefix[j] !== completion[j]) {
+                            commonPrefix = commonPrefix.substr(0, j);
+                            break;
+                        }
+                    }
+                }
+                wordPrefixLength = commonPrefix.length;
+
+                if (selection.isCollapsed)
+                    var completionText = completions[0];
+                else {
+                    var currentText = fullWordRange.toString();
+
+                    var foundIndex = null;
+                    for (var i = 0; i < completions.length; ++i) {
+                        if (completions[i] === currentText)
+                            foundIndex = i;
+                    }
+
+                    var nextIndex = foundIndex + (reverse ? -1 : 1);
+                    if (foundIndex === null || nextIndex >= completions.length)
+                        var completionText = completions[0];
+                    else if (nextIndex < 0)
+                        var completionText = completions[completions.length - 1];
+                    else
+                        var completionText = completions[nextIndex];
+                }
+            }
+        }
+
+        this._userEnteredRange = fullWordRange;
+        this._userEnteredText = fullWordRange.toString();
+
+        fullWordRange.deleteContents();
+        this.element.pruneEmptyTextNodes();
+
+        var finalSelectionRange = document.createRange();
+
+        if (auto) {
+            var prefixText = completionText.substring(0, wordPrefixLength);
+            var suffixText = completionText.substring(wordPrefixLength);
+
+            var prefixTextNode = document.createTextNode(prefixText);
+            fullWordRange.insertNode(prefixTextNode);
+
+            this.autoCompleteElement = document.createElement("span");
+            this.autoCompleteElement.className = "auto-complete-text";
+            this.autoCompleteElement.textContent = suffixText;
+
+            prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+
+            finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+            finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+        } else {
+            var completionTextNode = document.createTextNode(completionText);
+            fullWordRange.insertNode(completionTextNode);
+
+            if (completions.length > 1)
+                finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
+            else
+                finalSelectionRange.setStart(completionTextNode, completionText.length);
+
+            finalSelectionRange.setEnd(completionTextNode, completionText.length);
+        }
+
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+    },
+
+    isCaretInsidePrompt: function()
+    {
+        return this.element.isInsertionCaretInside();
+    },
+
+    isCaretAtEndOfPrompt: function()
+    {
+        var selection = window.getSelection();
+        if (!selection.rangeCount || !selection.isCollapsed)
+            return false;
+
+        var selectionRange = selection.getRangeAt(0);
+        var node = selectionRange.startContainer;
+        if (node !== this.element && !node.isDescendant(this.element))
+            return false;
+
+        if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+            return false;
+
+        var foundNextText = false;
+        while (node) {
+            if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
+                if (foundNextText)
+                    return false;
+                foundNextText = true;
+            }
+
+            node = node.traverseNextNode(this.element);
+        }
+
+        return true;
+    },
+
+    isCaretOnFirstLine: function()
+    {
+        var selection = window.getSelection();
+        var focusNode = selection.focusNode;
+        if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
+            return true;
+
+        if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1)
+            return false;
+        focusNode = focusNode.previousSibling;
+
+        while (focusNode) {
+            if (focusNode.nodeType !== Node.TEXT_NODE)
+                return true;
+            if (focusNode.textContent.indexOf("\n") !== -1)
+                return false;
+            focusNode = focusNode.previousSibling;
+        }
+
+        return true;
+    },
+
+    isCaretOnLastLine: function()
+    {
+        var selection = window.getSelection();
+        var focusNode = selection.focusNode;
+        if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
+            return true;
+
+        if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1)
+            return false;
+        focusNode = focusNode.nextSibling;
+
+        while (focusNode) {
+            if (focusNode.nodeType !== Node.TEXT_NODE)
+                return true;
+            if (focusNode.textContent.indexOf("\n") !== -1)
+                return false;
+            focusNode = focusNode.nextSibling;
+        }
+
+        return true;
+    },
+
+    moveCaretToEndOfPrompt: function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+
+        var offset = this.element.childNodes.length;
+        selectionRange.setStart(this.element, offset);
+        selectionRange.setEnd(this.element, offset);
+
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+    },
+
+    tabKeyPressed: function(event)
+    {
+        event.handled = true;
+        this.complete(false, event.shiftKey);
+    },
+
+    upKeyPressed: function(event)
+    {
+        if (!this.isCaretOnFirstLine())
+            return;
+
+        event.handled = true;
+        this._moveBackInHistory();
+    },
+
+    downKeyPressed: function(event)
+    {
+        if (!this.isCaretOnLastLine())
+            return;
+
+        event.handled = true;
+        this._moveForwardInHistory();
+    },
+
+    _moveBackInHistory: function()
+    {
+        if (!this.history || this.historyOffset == this.history.length)
+            return;
+
+        this.clearAutoComplete(true);
+
+        if (this.historyOffset === 0)
+            this.tempSavedCommand = this.text;
+
+        ++this.historyOffset;
+        this.text = this.history[this.history.length - this.historyOffset];
+
+        this.element.scrollIntoView(true);
+        var firstNewlineIndex = this.text.indexOf("\n");
+        if (firstNewlineIndex === -1)
+            this.moveCaretToEndOfPrompt();
+        else {
+            var selection = window.getSelection();
+            var selectionRange = document.createRange();
+
+            selectionRange.setStart(this.element.firstChild, firstNewlineIndex);
+            selectionRange.setEnd(this.element.firstChild, firstNewlineIndex);
+
+            selection.removeAllRanges();
+            selection.addRange(selectionRange);
+        }
+    },
+
+    _moveForwardInHistory: function()
+    {
+        if (!this.history || this.historyOffset === 0)
+            return;
+
+        this.clearAutoComplete(true);
+
+        --this.historyOffset;
+
+        if (this.historyOffset === 0) {
+            this.text = this.tempSavedCommand;
+            delete this.tempSavedCommand;
+            return;
+        }
+
+        this.text = this.history[this.history.length - this.historyOffset];
+        this.element.scrollIntoView();
+    }
+}