]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/modules/finder.jsm
Import 1.0b7.1 supporting Firefox up to 8.*
[dactyl.git] / common / modules / finder.jsm
index 5edd5904f4b0d657ec3cd754461338cca5ff703d..e2d24bb020495fa74ee45d713d963ac31957f679 100644 (file)
@@ -7,11 +7,14 @@
 Components.utils.import("resource://dactyl/bootstrap.jsm");
 defineModule("finder", {
     exports: ["RangeFind", "RangeFinder", "rangefinder"],
+    require: ["prefs"],
     use: ["messages", "services", "util"]
 }, this);
 
 function equals(a, b) XPCNativeWrapper(a) == XPCNativeWrapper(b);
 
+try {
+
 /** @instance rangefinder */
 var RangeFinder = Module("rangefinder", {
     Local: function (dactyl, modules, window) ({
@@ -31,6 +34,12 @@ var RangeFinder = Module("rangefinder", {
         set rangeFind(val) modules.buffer.localStore.rangeFind = val
     }),
 
+    init: function init() {
+        prefs.safeSet("accessibility.typeaheadfind.autostart", false);
+        // The above should be sufficient, but: http://dactyl.sf.net/bmo/348187
+        prefs.safeSet("accessibility.typeaheadfind", false);
+    },
+
     get commandline() this.modules.commandline,
     get modes() this.modules.modes,
     get options() this.modules.options,
@@ -41,10 +50,13 @@ var RangeFinder = Module("rangefinder", {
 
         if (this.rangeFind && equals(this.rangeFind.window.get(), this.window))
             this.rangeFind.reset();
-        this.find("", mode === this.modes.FIND_BACKWARD);
+        this.find("", mode == this.modes.FIND_BACKWARD);
     },
 
     bootstrap: function (str, backward) {
+        if (arguments.length < 2 && this.rangeFind)
+            backward = this.rangeFind.reverse;
+
         let highlighted = this.rangeFind && this.rangeFind.highlighted;
         let selections = this.rangeFind && this.rangeFind.selections;
         let linksOnly = false;
@@ -132,6 +144,10 @@ var RangeFinder = Module("rangefinder", {
         }
     },
 
+    onHistory: function () {
+        this.rangeFind.found = false;
+    },
+
     onSubmit: function (command) {
         if (!this.options["incfind"] || !this.rangeFind || !this.rangeFind.found) {
             this.clear();
@@ -168,7 +184,7 @@ var RangeFinder = Module("rangefinder", {
 
         modes.addMode("FIND", {
             description: "Find mode, active when typing search input",
-            bases: [modes.COMMAND_LINE],
+            bases: [modes.COMMAND_LINE]
         });
         modes.addMode("FIND_FORWARD", {
             description: "Forward Find mode, active when typing search input",
@@ -200,40 +216,41 @@ var RangeFinder = Module("rangefinder", {
 
             get onCancel() modules.rangefinder.closure.onCancel,
             get onChange() modules.rangefinder.closure.onChange,
+            get onHistory() modules.rangefinder.closure.onHistory,
             get onSubmit() modules.rangefinder.closure.onSubmit
         });
     },
     mappings: function (dactyl, modules, window) {
-        const { buffer, config, mappings, modes, rangefinder } = modules;
+        const { Buffer, buffer, config, mappings, modes, rangefinder } = modules;
         var myModes = config.browserModes.concat([modes.CARET]);
 
         mappings.add(myModes,
-            ["/"], "Find a pattern starting at the current caret position",
+            ["/", "<find-forward>"], "Find a pattern starting at the current caret position",
             function () { rangefinder.openPrompt(modes.FIND_FORWARD); });
 
         mappings.add(myModes,
-            ["?"], "Find a pattern backward of the current caret position",
+            ["?", "<find-backward>"], "Find a pattern backward of the current caret position",
             function () { rangefinder.openPrompt(modes.FIND_BACKWARD); });
 
         mappings.add(myModes,
-            ["n"], "Find next",
+            ["n", "<find-next>"], "Find next",
             function () { rangefinder.findAgain(false); });
 
         mappings.add(myModes,
-            ["N"], "Find previous",
+            ["N", "<find-previous>"], "Find previous",
             function () { rangefinder.findAgain(true); });
 
-        mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["*"],
+        mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["*", "<find-word-forward>"],
             "Find word under cursor",
             function () {
-                rangefinder.find(buffer.getCurrentWord(), false);
+                rangefinder.find(Buffer.currentWord(buffer.focusedFrame, true), false);
                 rangefinder.findAgain();
             });
 
-        mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["#"],
+        mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["#", "<find-word-backward>"],
             "Find word under cursor backwards",
             function () {
-                rangefinder.find(buffer.getCurrentWord(), true);
+                rangefinder.find(Buffer.currentWord(buffer.focusedFrame, true), true);
                 rangefinder.findAgain();
             });
 
@@ -242,10 +259,6 @@ var RangeFinder = Module("rangefinder", {
         const { options, rangefinder } = modules;
         const { prefs } = require("prefs");
 
-        // prefs.safeSet("accessibility.typeaheadfind.autostart", false);
-        // The above should be sufficient, but: https://bugzilla.mozilla.org/show_bug.cgi?id=348187
-        prefs.safeSet("accessibility.typeaheadfind", false);
-
         options.add(["hlfind", "hlf"],
             "Highlight all /find pattern matches on the current page after submission",
             "boolean", false, {
@@ -267,7 +280,7 @@ var RangeFinder = Module("rangefinder", {
             });
 
         options.add(["incfind", "if"],
-            "Find a pattern incrementally as it is typed rather than awaiting <Return>",
+            "Find a pattern incrementally as it is typed rather than awaiting c_<Return>",
             "boolean", true);
     }
 });
@@ -369,7 +382,7 @@ var RangeFind = Class("RangeFind", {
         let doc = range.startContainer.ownerDocument;
         let win = doc.defaultView;
         let ranges = this.ranges.filter(function (r)
-            r.window === win && RangeFind.contains(r.range, range));
+            r.window === win && RangeFind.sameDocument(r.range, range) && RangeFind.contains(r.range, range));
 
         if (this.backward)
             return ranges[ranges.length - 1];
@@ -390,7 +403,7 @@ var RangeFind = Class("RangeFind", {
             var node = util.evaluateXPath(RangeFind.selectNodePath,
                                           this.lastRange.commonAncestorContainer).snapshotItem(0);
         if (node) {
-            node.focus()
+            node.focus();
             // Re-highlight collapsed selection
             this.selectedRange = this.lastRange;
         }
@@ -480,7 +493,9 @@ var RangeFind = Class("RangeFind", {
                     frames.push(r);
             }
 
-            let range = start.startContainer.ownerDocument.createRange();
+            let doc = start.startContainer.ownerDocument;
+
+            let range = doc.createRange();
             range.setStart(start.startContainer, start.startOffset);
             range.setEnd(end.startContainer, end.startOffset);
 
@@ -492,7 +507,7 @@ var RangeFind = Class("RangeFind", {
         }
         function rec(win) {
             let doc = win.document;
-            let pageRange = RangeFind.nodeRange(doc.body || doc.documentElement.lastChild);
+            let pageRange = RangeFind[doc.body ? "nodeRange" : "nodeContents"](doc.body || doc.documentElement);
             backup = backup || pageRange;
             let pageStart = RangeFind.endpoint(pageRange, true);
             let pageEnd = RangeFind.endpoint(pageRange, false);
@@ -507,6 +522,14 @@ var RangeFind = Class("RangeFind", {
                 }
             }
             pushRange(pageStart, pageEnd);
+
+            let anonNodes = doc.getAnonymousNodes(doc.documentElement);
+            if (anonNodes) {
+                for (let [, elem] in iter(anonNodes)) {
+                    let range = RangeFind.nodeContents(elem);
+                    pushRange(RangeFind.endpoint(range, true), RangeFind.endpoint(range, false));
+                }
+            }
         }
         rec(win);
         if (frames.length == 0)
@@ -724,6 +747,14 @@ var RangeFind = Class("RangeFind", {
             return false;
         }
     },
+    nodeContents: function (node) {
+        let range = node.ownerDocument.createRange();
+        try {
+            range.selectNodeContents(node);
+        }
+        catch (e) {}
+        return range;
+    },
     nodeRange: function (node) {
         let range = node.ownerDocument.createRange();
         try {
@@ -732,10 +763,23 @@ var RangeFind = Class("RangeFind", {
         catch (e) {}
         return range;
     },
-    sameDocument: function (r1, r2) r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument,
+    sameDocument: function (r1, r2) {
+        if (!(r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument))
+            return false;
+        try {
+            r1.compareBoundaryPoints(r1.START_TO_START, r2);
+        }
+        catch (e if e.result == 0x80530004 /* NS_ERROR_DOM_WRONG_DOCUMENT_ERR */) {
+            return false;
+        }
+        return true;
+    },
     selectNodePath: ["a", "xhtml:a", "*[@onclick]"].map(function (p) "ancestor-or-self::" + p).join(" | ")
 });
 
+} catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
+
 endModule();
 
+
 // vim: set fdm=marker sw=4 ts=4 et ft=javascript: