mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-22 09:07:58 +01:00
first commit of native / and ? search, especially ? is buggy right now
This commit is contained in:
1
NEWS
1
NEWS
@@ -1,6 +1,7 @@
|
|||||||
<pre>
|
<pre>
|
||||||
2007-xx-xx:
|
2007-xx-xx:
|
||||||
* version 0.6
|
* version 0.6
|
||||||
|
* native / and ? search and n and N working again
|
||||||
* the URL in the status line can be selected with the mouse again
|
* the URL in the status line can be selected with the mouse again
|
||||||
* commandline history now works properly on Windows
|
* commandline history now works properly on Windows
|
||||||
* filename completion now works on Windows
|
* filename completion now works on Windows
|
||||||
|
|||||||
@@ -682,6 +682,16 @@ function Commands() //{{{
|
|||||||
help: "If <code class=\"argument\">[arg]</code> is specified then limit the list to those marks mentioned."
|
help: "If <code class=\"argument\">[arg]</code> is specified then limit the list to those marks mentioned."
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
addDefaultCommand(new Command(["noh[lsearch]"],
|
||||||
|
function(args)
|
||||||
|
{
|
||||||
|
vimperator.search.clear();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
short_help: "Clear the current selection",
|
||||||
|
help: "TODO"
|
||||||
|
}
|
||||||
|
));
|
||||||
addDefaultCommand(new Command(["norm[al]"],
|
addDefaultCommand(new Command(["norm[al]"],
|
||||||
function(args)
|
function(args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ table.vimperator {
|
|||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: dotted;
|
border-style: dotted;
|
||||||
border-color: gray;
|
border-color: gray;
|
||||||
margin-bottom: 2em; /* FIXME: just a quick hack until we have proper pages */
|
/*margin-bottom: 2em; /* FIXME: just a quick hack until we have proper pages */
|
||||||
}
|
}
|
||||||
table.vimperator td {
|
table.vimperator td {
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|||||||
for the specific language governing rights and limitations under the
|
for the specific language governing rights and limitations under the
|
||||||
License.
|
License.
|
||||||
|
|
||||||
The Initial Developer of the Original Code is Shawn Betts.
|
(c) 2006-2007: Martin Stubenschrott <stubenschrott@gmx.net>
|
||||||
Portions created by the Initial Developer are Copyright (C) 2004,2005
|
|
||||||
by the Initial Developer. All Rights Reserved.
|
|
||||||
|
|
||||||
Alternatively, the contents of this file may be used under the terms of
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
@@ -28,443 +26,122 @@ the provisions above, a recipient may use your version of this file under
|
|||||||
the terms of any one of the MPL, the GPL or the LGPL.
|
the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
}}} ***** END LICENSE BLOCK *****/
|
}}} ***** END LICENSE BLOCK *****/
|
||||||
|
|
||||||
// Finder for vimperator
|
|
||||||
// Author: Nigel McNie <http://nigel.mcnie.name/>
|
|
||||||
// Original Author: Shawn Betts
|
|
||||||
//
|
|
||||||
// The algorithm was taken from conkeror <http://conkeror.mozdev.net/>, but
|
|
||||||
// extensively refactored and changed to behave like vim (naturally!)
|
|
||||||
|
|
||||||
// The window to search in (which frame)
|
|
||||||
//var gWin = null;
|
|
||||||
//var gSelCtrl = null;
|
|
||||||
|
|
||||||
//function highlight(range, node) {
|
|
||||||
// var startContainer = range.startContainer;
|
|
||||||
// var startOffset = range.startOffset;
|
|
||||||
// var endOffset = range.endOffset;
|
|
||||||
// var docfrag = range.extractContents();
|
|
||||||
// var before = startContainer.splitText(startOffset);
|
|
||||||
// var parent = before.parentNode;
|
|
||||||
// node.appendChild(docfrag);
|
|
||||||
// parent.insertBefore(node, before);
|
|
||||||
// return node;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Clears the current selection
|
|
||||||
// @todo this should be in vimperator.js, and not depend on searcher.gSelCtrl
|
|
||||||
function clearSelection() {
|
|
||||||
//var selctrl = gSelCtrl;
|
|
||||||
var selctrl = vimperator.search.gSelCtrl;
|
|
||||||
var sel = selctrl.getSelection(Components.interfaces.nsISelectionController.SELECTION_NORMAL);
|
|
||||||
sel.removeAllRanges();
|
|
||||||
gFindBar.highlightDoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets what is currently selected
|
|
||||||
// @todo as for clearSelection
|
|
||||||
function setSelection(range) {
|
|
||||||
try {
|
|
||||||
var selctrlcomp = Components.interfaces.nsISelectionController;
|
|
||||||
//var selctrl = gSelCtrl;
|
|
||||||
var selctrl = vimperator.search.gSelCtrl;
|
|
||||||
var sel = selctrl.getSelection(selctrlcomp.SELECTION_NORMAL);
|
|
||||||
sel.removeAllRanges();
|
|
||||||
sel.addRange(range.cloneRange());
|
|
||||||
|
|
||||||
selctrl.scrollSelectionIntoView(selctrlcomp.SELECTION_NORMAL,
|
|
||||||
selctrlcomp.SELECTION_FOCUS_REGION,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
alert("setSelection: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Highlight find matches and move selection to the first occurrence
|
|
||||||
// starting from pt.
|
|
||||||
// @todo move into searcher and clean up
|
|
||||||
function highlightFind(str, color, wrapped, dir, pt)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
var gWin = vimperator.search.gWin;//document.commandDispatcher.focusedWindow;
|
|
||||||
if (!gWin) {
|
|
||||||
alert('gWin does not exist here...');
|
|
||||||
alert(vimperator.search.gWin);
|
|
||||||
}
|
|
||||||
var doc = gWin.document;
|
|
||||||
var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance()
|
|
||||||
.QueryInterface(Components.interfaces.nsIFind);
|
|
||||||
var searchRange;
|
|
||||||
var startPt;
|
|
||||||
var endPt;
|
|
||||||
var body = doc.body;
|
|
||||||
|
|
||||||
finder.findBackwards = !dir;
|
|
||||||
|
|
||||||
searchRange = doc.createRange();
|
|
||||||
startPt = doc.createRange();
|
|
||||||
endPt = doc.createRange();
|
|
||||||
|
|
||||||
var count = body.childNodes.length;
|
|
||||||
|
|
||||||
// Search range in the doc
|
|
||||||
searchRange.setStart(body,0);
|
|
||||||
searchRange.setEnd(body, count);
|
|
||||||
|
|
||||||
if (!dir) {
|
|
||||||
if (pt == null) {
|
|
||||||
startPt.setStart(body, count);
|
|
||||||
startPt.setEnd(body, count);
|
|
||||||
} else {
|
|
||||||
startPt.setStart(pt.startContainer, pt.startOffset);
|
|
||||||
startPt.setEnd(pt.startContainer, pt.startOffset);
|
|
||||||
}
|
|
||||||
endPt.setStart(body, 0);
|
|
||||||
endPt.setEnd(body, 0);
|
|
||||||
} else {
|
|
||||||
if (pt == null) {
|
|
||||||
startPt.setStart(body, 0);
|
|
||||||
startPt.setEnd(body, 0);
|
|
||||||
} else {
|
|
||||||
startPt.setStart(pt.endContainer, pt.endOffset);
|
|
||||||
startPt.setEnd(pt.endContainer, pt.endOffset);
|
|
||||||
}
|
|
||||||
endPt.setStart(body, count);
|
|
||||||
endPt.setEnd(body, count);
|
|
||||||
}
|
|
||||||
// search the doc
|
|
||||||
var retRange = null;
|
|
||||||
var selectionRange = null;
|
|
||||||
|
|
||||||
if (!wrapped) {
|
|
||||||
do {
|
|
||||||
retRange = finder.Find(str, searchRange, startPt, endPt);
|
|
||||||
var keepSearching = false;
|
|
||||||
if (retRange) {
|
|
||||||
var sc = retRange.startContainer;
|
|
||||||
var ec = retRange.endContainer;
|
|
||||||
var scp = sc.parentNode;
|
|
||||||
var ecp = ec.parentNode;
|
|
||||||
var sy1 = abs_point(scp).y;
|
|
||||||
var ey2 = abs_point(ecp).y + ecp.offsetHeight;
|
|
||||||
|
|
||||||
startPt = retRange.startContainer.ownerDocument.createRange();
|
|
||||||
if (!dir) {
|
|
||||||
startPt.setStart(retRange.startContainer, retRange.startOffset);
|
|
||||||
startPt.setEnd(retRange.startContainer, retRange.startOffset);
|
|
||||||
} else {
|
|
||||||
startPt.setStart(retRange.endContainer, retRange.endOffset);
|
|
||||||
startPt.setEnd(retRange.endContainer, retRange.endOffset);
|
|
||||||
}
|
|
||||||
// We want to find a match that is completely
|
|
||||||
// visible, otherwise the view will scroll just a
|
|
||||||
// bit to fit the selection in completely.
|
|
||||||
// alert ("sy1: " + sy1 + " scry: " + gWin.scrollY);
|
|
||||||
// alert ("ey2: " + ey2 + " bot: " + (gWin.scrollY + gWin.innerHeight));
|
|
||||||
keepSearching = (dir && sy1 < gWin.scrollY)
|
|
||||||
|| (!dir && ey2 >= gWin.scrollY + gWin.innerHeight);
|
|
||||||
}
|
|
||||||
} while (retRange && keepSearching);
|
|
||||||
} else {
|
|
||||||
retRange = finder.Find(str, searchRange, startPt, endPt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retRange) {
|
|
||||||
setSelection(retRange);
|
|
||||||
selectionRange = retRange.cloneRange();
|
|
||||||
// highlightAllBut(str, retRange, color);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return selectionRange;
|
|
||||||
} catch(e) { alert('highlightFind:'+e); }
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearHighlight()
|
|
||||||
{
|
|
||||||
gFindBar.highlightDoc();
|
|
||||||
var win = window.content;
|
|
||||||
var doc = win.document;
|
|
||||||
if (!document)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var elem = null;
|
|
||||||
while ((elem = doc.getElementById("__vimperator-findbar-search-id"))) {
|
|
||||||
var child = null;
|
|
||||||
var docfrag = doc.createDocumentFragment();
|
|
||||||
var next = elem.nextSibling;
|
|
||||||
var parent = elem.parentNode;
|
|
||||||
while ((child = elem.firstChild)) {
|
|
||||||
docfrag.appendChild(child);
|
|
||||||
}
|
|
||||||
parent.removeChild(elem);
|
|
||||||
parent.insertBefore(docfrag, next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finds the absolute X and Y co-ordinates of a given node from the top left of
|
|
||||||
* the document
|
|
||||||
*
|
|
||||||
* Taken from conkeror utils.js
|
|
||||||
*/
|
|
||||||
function abs_point (node) {
|
|
||||||
var orig = node;
|
|
||||||
var pt = {};
|
|
||||||
try {
|
|
||||||
pt.x = node.offsetLeft;
|
|
||||||
pt.y = node.offsetTop;
|
|
||||||
|
|
||||||
// Find imagemap's coordinates
|
|
||||||
if (node.tagName == "AREA") {
|
|
||||||
var coords = node.getAttribute("coords").split(",");
|
|
||||||
pt.x += Number(coords[0]);
|
|
||||||
pt.y += Number(coords[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node.offsetParent;
|
|
||||||
|
|
||||||
while (node.tagName != "BODY") {
|
|
||||||
pt.x += node.offsetLeft;
|
|
||||||
pt.y += node.offsetTop;
|
|
||||||
node = node.offsetParent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vimperator searcher
|
|
||||||
// make sure you only create this object when the "vimperator" object is ready
|
// make sure you only create this object when the "vimperator" object is ready
|
||||||
//vimperator.search = new function()
|
// vimperator.search = new function()
|
||||||
function Search() //{{{
|
function Search() //{{{
|
||||||
{
|
{
|
||||||
var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback
|
var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback
|
||||||
this.gWin = null;
|
var lastsearch = ""; // keep track of the last searched string
|
||||||
this.gSelCtrl = null;
|
var found = false; // true if the last search was successful
|
||||||
this.gFindState = [];
|
|
||||||
|
|
||||||
// Event handlers for search - closure is needed
|
// Event handlers for search - closure is needed
|
||||||
vimperator.registerCallback("change", vimperator.modes.SEARCH_FORWARD, function(command){ self.searchKeyPressed(command); });
|
vimperator.registerCallback("change", vimperator.modes.SEARCH_FORWARD, function(command){ self.searchKeyPressed(command); });
|
||||||
vimperator.registerCallback("submit", vimperator.modes.SEARCH_FORWARD, function(command){ self.searchSubmitted(command); });
|
vimperator.registerCallback("submit", vimperator.modes.SEARCH_FORWARD, function(command){ self.searchSubmitted(command); });
|
||||||
vimperator.registerCallback("cancel", vimperator.modes.SEARCH_FORWARD, function(){ self.searchCancelled(); });
|
vimperator.registerCallback("cancel", vimperator.modes.SEARCH_FORWARD, function(){ self.searchCanceled(); });
|
||||||
|
// TODO: allow advanced modes in register/triggerCallback
|
||||||
|
vimperator.registerCallback("change", vimperator.modes.SEARCH_BACKWARD, function(command){ self.searchKeyPressed(command); });
|
||||||
|
vimperator.registerCallback("submit", vimperator.modes.SEARCH_BACKWARD, function(command){ self.searchSubmitted(command); });
|
||||||
|
vimperator.registerCallback("cancel", vimperator.modes.SEARCH_BACKWARD, function(){ self.searchCanceled(); });
|
||||||
|
|
||||||
|
// Called when the search dialog is asked for
|
||||||
// Called when the search dialog is asked for. Sets up everything necessary
|
// If you omit "mode", it will default to forward searching
|
||||||
// for this round of searching
|
this.openSearchDialog = function(mode)
|
||||||
this.openSearchDialog = function()
|
|
||||||
{
|
{
|
||||||
// Get a reference to the focused window if necessary
|
if (mode == vimperator.modes.SEARCH_BACKWARD)
|
||||||
if (this.gWin == null) this.gWin = document.commandDispatcher.focusedWindow;
|
vimperator.commandline.open('?', '', vimperator.modes.SEARCH_BACKWARD);
|
||||||
|
else
|
||||||
// Change the currently selected text to not be the attention colour
|
|
||||||
// @todo: check what this REALLY does
|
|
||||||
try {
|
|
||||||
this.gSelCtrl = this.getFocusedSelCtrl();
|
|
||||||
this.gSelCtrl.setDisplaySelection(Components.interfaces.nsISelectionController.SELECTION_ATTENTION);
|
|
||||||
this.gSelCtrl.repaintSelection(Components.interfaces.nsISelectionController.SELECTION_NORMAL);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
alert('Could not change the colour of the current selection:' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the state list for this attempt at searching
|
|
||||||
var state = this.createInitialFindState();
|
|
||||||
this.gFindState = [];
|
|
||||||
this.gFindState.push(state);
|
|
||||||
this.resumeFindState(state);
|
|
||||||
|
|
||||||
vimperator.commandline.open('/', '', vimperator.modes.SEARCH_FORWARD);
|
vimperator.commandline.open('/', '', vimperator.modes.SEARCH_FORWARD);
|
||||||
|
|
||||||
|
// TODO: focus the top of the currently visible screen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the current search needs to be repeated in the forward
|
// Finds text in a page
|
||||||
// direction
|
// TODO: backwards seems impossible i fear :(
|
||||||
// @todo will need re-jigging when reverse search comes in
|
this.find = function(str, backwards)
|
||||||
this.findNext = function() {
|
{
|
||||||
this.find(this.lastFindState()["search-str"], true, this.lastFindState()["range"]);
|
const FIND_NORMAL = 0;
|
||||||
this.resumeFindState(this.lastFindState());
|
const FIND_TYPEAHEAD = 1;
|
||||||
// if there is still a search result
|
const FIND_LINKS = 2;
|
||||||
if (this.lastFindState()["range"]) {
|
|
||||||
if (this.lastFindState()["wrapped"]) {
|
var res = getBrowser().fastFind.find(str, FIND_TYPEAHEAD);
|
||||||
vimperator.echoerr("search hit BOTTOM, continuing at TOP");
|
res == Components.interfaces.nsITypeAheadFind.FIND_FOUND ? found = true : found = false;
|
||||||
this.lastFindState()["wrapped"] = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO: this could probably be done in a nicer way - perhaps
|
|
||||||
// echoErr could not clobber all of this information somehow?
|
|
||||||
vimperator.echo('/' + this.lastFindState()["search-str"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the current search needs to be repeated in the backward
|
// Called when the current search needs to be repeated
|
||||||
// direction
|
this.findAgain = function(reverse)
|
||||||
this.findPrevious = function() {
|
{
|
||||||
this.find(this.lastFindState()["search-str"], false, this.lastFindState()["range"]);
|
// this hack is needed to make n/N work with the correct string, if
|
||||||
this.resumeFindState(this.lastFindState());
|
// we typed /foo<esc> after the original search
|
||||||
// if there is still a search result
|
if (getBrowser().fastFind.searchString != lastsearch)
|
||||||
if (this.lastFindState()["range"]) {
|
this.find(lastsearch, false);
|
||||||
if (this.lastFindState()["wrapped"]) {
|
|
||||||
|
var backward = vimperator.hasMode(vimperator.modes.SEARCH_BACKWARD);
|
||||||
|
var up = reverse ? !backward : backward;
|
||||||
|
var result = getBrowser().fastFind.findAgain(up, null);
|
||||||
|
|
||||||
|
if (result == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND)
|
||||||
|
vimperator.echoerr("E486: Pattern not found: " + lastsearch);
|
||||||
|
else if (result == Components.interfaces.nsITypeAheadFind.FIND_WRAPPED)
|
||||||
|
{
|
||||||
|
// hack needed, because wrapping causes a "scroll" event which clears
|
||||||
|
// our command line
|
||||||
|
setTimeout( function() {
|
||||||
|
if (up)
|
||||||
vimperator.echoerr("search hit TOP, continuing at BOTTOM");
|
vimperator.echoerr("search hit TOP, continuing at BOTTOM");
|
||||||
this.lastFindState()["wrapped"] = false;
|
else
|
||||||
}
|
vimperator.echoerr("search hit BOTTOM, continuing at TOP");
|
||||||
else {
|
}, 10);
|
||||||
vimperator.echo('/' + this.lastFindState()["search-str"]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the user types a key in the search dialog. Triggers a find attempt
|
// Called when the user types a key in the search dialog. Triggers a find attempt
|
||||||
this.searchKeyPressed = function(command) {
|
this.searchKeyPressed = function(command)
|
||||||
if (command != "") {
|
{
|
||||||
var str = vimperator.commandline.getCommand();
|
// TODO: check for 'incsearch'
|
||||||
this.find(str, true, this.lastFindState()["point"]);
|
var backward = vimperator.hasMode(vimperator.modes.SEARCH_BACKWARD);
|
||||||
this.resumeFindState(this.lastFindState());
|
this.find(command, backward);
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearSelection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the enter key is pressed to trigger a search
|
// Called when the enter key is pressed to trigger a search
|
||||||
this.searchSubmitted = function(command) {
|
this.searchSubmitted = function(command)
|
||||||
|
{
|
||||||
|
gFindBar._highlightDoc("yellow", "black", command);
|
||||||
|
|
||||||
|
// need to find again to draw the highlight of the current search
|
||||||
|
// result over the "highlight all" search results
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
// XXX: still not really working everywhere, inspite of this
|
||||||
|
setTimeout(function() {
|
||||||
|
var backward = vimperator.hasMode(vimperator.modes.SEARCH_BACKWARD);
|
||||||
|
this.find(command, backward);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
//removeMode(MODE_SEARCH);
|
//removeMode(MODE_SEARCH);
|
||||||
vimperator.setMode(vimperator.modes.NORMAL);
|
vimperator.setMode(vimperator.modes.NORMAL);
|
||||||
if (this.lastFindState()["range"] == null) {
|
vimperator.focusContent();
|
||||||
vimperator.echoerr("E492: Pattern not found: " + this.lastFindState()["search-str"]);
|
|
||||||
}
|
lastsearch = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the search is cancelled - for example if someone presses
|
// Called when the search is cancelled - for example if someone presses
|
||||||
// escape while typing a search
|
// escape while typing a search
|
||||||
this.searchCancelled = function() {
|
this.searchCanceled = function()
|
||||||
|
{
|
||||||
//removeMode(MODE_SEARCH);
|
//removeMode(MODE_SEARCH);
|
||||||
vimperator.setMode(vimperator.modes.NORMAL);
|
vimperator.setMode(vimperator.modes.NORMAL);
|
||||||
clearSelection();
|
//gFindBar._highlightDoc();
|
||||||
|
this.clear();
|
||||||
vimperator.focusContent();
|
vimperator.focusContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.clear = function()
|
||||||
//
|
|
||||||
// Helper methods
|
|
||||||
//
|
|
||||||
|
|
||||||
// Turn on the selection in all frames
|
|
||||||
// @todo to tell the truth, I have no idea what this does
|
|
||||||
this.getFocusedSelCtrl = function() {
|
|
||||||
var ds = getBrowser().docShell;
|
|
||||||
var dsEnum = ds.getDocShellEnumerator(Components.interfaces.nsIDocShellTreeItem.typeContent,
|
|
||||||
Components.interfaces.nsIDocShell.ENUMERATE_FORWARDS);
|
|
||||||
while (dsEnum.hasMoreElements()) {
|
|
||||||
ds = dsEnum.getNext().QueryInterface(Components.interfaces.nsIDocShell);
|
|
||||||
if (ds.hasFocus) {
|
|
||||||
var display = ds.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Components.interfaces.nsISelectionDisplay);
|
|
||||||
if (!display) return null;
|
|
||||||
return display.QueryInterface(Components.interfaces.nsISelectionController);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// One last try
|
|
||||||
return getBrowser().docShell
|
|
||||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Components.interfaces.nsISelectionDisplay)
|
|
||||||
.QueryInterface(Components.interfaces.nsISelectionController);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a default find state
|
|
||||||
this.createInitialFindState = function() {
|
|
||||||
var state = [];
|
|
||||||
state["screenx"] = this.gWin.scrollX;
|
|
||||||
state["screeny"] = this.gWin.scrollY;
|
|
||||||
state["search-str"] = "";
|
|
||||||
state["wrapped"] = false;
|
|
||||||
state["point"] = null;
|
|
||||||
state["range"] = document.createRange();
|
|
||||||
state["selection"] = null;
|
|
||||||
state["direction"] = true;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a find state, moves the browser to the way it should be in the
|
|
||||||
// state - highlighting the correct thing and the screen scrolled to the
|
|
||||||
// correct location
|
|
||||||
this.resumeFindState = function(state) {
|
|
||||||
if (state["selection"]) {
|
|
||||||
setSelection(state["selection"]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearSelection();
|
|
||||||
}
|
|
||||||
this.gWin.scrollTo(state["screenx"], state["screeny"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves the current find state that we're in
|
|
||||||
// @todo rename to currentFindState?
|
|
||||||
this.lastFindState = function() {
|
|
||||||
return this.gFindState[this.gFindState.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a find state to the stack of such states. This is done every time a find is successful
|
|
||||||
this.addFindState = function(screenX, screenY, searchStr, wrapped, point, range, selection, direction) {
|
|
||||||
var state = [];
|
|
||||||
state["screenx"] = screenX;
|
|
||||||
state["screeny"] = screenY;
|
|
||||||
state["search-str"] = searchStr;
|
|
||||||
state["wrapped"] = wrapped;
|
|
||||||
state["point"] = point;
|
|
||||||
state["range"] = range;
|
|
||||||
state["selection"] = selection;
|
|
||||||
state["direction"] = direction;
|
|
||||||
this.gFindState.push(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finds text in a page
|
|
||||||
this.find = function(str, dir, pt)
|
|
||||||
{
|
{
|
||||||
var norecurse = arguments[3];
|
gFindBar._highlightDoc();
|
||||||
|
}
|
||||||
|
|
||||||
var matchRange;
|
|
||||||
clearHighlight();
|
|
||||||
|
|
||||||
// Should we wrap this time?
|
|
||||||
var wrapped = this.lastFindState()["wrapped"];
|
|
||||||
var point = pt;
|
|
||||||
if (this.lastFindState()["wrapped"] == false
|
|
||||||
&& this.lastFindState()["range"] == null
|
|
||||||
&& this.lastFindState()["search-str"] == str
|
|
||||||
&& this.lastFindState()["direction"] == dir) {
|
|
||||||
wrapped = true;
|
|
||||||
point = null;
|
|
||||||
}
|
|
||||||
gFindBar.highlightDoc('yellow', 'black', str);
|
|
||||||
matchRange = highlightFind(str, "lightblue", wrapped, dir, point);
|
|
||||||
if (matchRange == null) {
|
|
||||||
// No more matches in this direction. So add the state and then find
|
|
||||||
// again to wrap around. But only find again once to prevent infinite
|
|
||||||
// recursion if an error occurs
|
|
||||||
this.addFindState(this.gWin.scrollX, this.gWin.scrollY, str, wrapped, point,
|
|
||||||
matchRange, this.lastFindState()["selection"], dir);
|
|
||||||
if (!norecurse)
|
|
||||||
this.find(str, dir, pt, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.addFindState(this.gWin.scrollX, this.gWin.scrollY, str, wrapped,
|
|
||||||
point, matchRange, matchRange, dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//// @TODO should be moved into commands.js
|
|
||||||
//vimperator.commands.add(new Command(["noh[lsearch]"],
|
|
||||||
// clearSelection,
|
|
||||||
// {
|
|
||||||
// short_help: "Clear the current selection"
|
|
||||||
// }
|
|
||||||
//));
|
|
||||||
|
|
||||||
// vim: set fdm=marker sw=4 ts=4 et:
|
// vim: set fdm=marker sw=4 ts=4 et:
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ function Hints() //{{{
|
|||||||
var rect = elem.getClientRects()[0];
|
var rect = elem.getClientRects()[0];
|
||||||
if (rect)
|
if (rect)
|
||||||
{
|
{
|
||||||
|
if (!rect.left || !rect.top)
|
||||||
|
vimperator.log("HUI: no rect.left or top");
|
||||||
elem.absoLeft = rect.left;
|
elem.absoLeft = rect.left;
|
||||||
elem.absoTop = rect.top;
|
elem.absoTop = rect.top;
|
||||||
}
|
}
|
||||||
@@ -171,9 +173,9 @@ function Hints() //{{{
|
|||||||
|
|
||||||
// for extended hint mode, show all - even currently hidden - hints
|
// for extended hint mode, show all - even currently hidden - hints
|
||||||
//if (vimperator.hasMode(vimperator.modes.QUICK_HINT) && (elem.absoTop < area[1] || elem.absoTop > area[3] ||
|
//if (vimperator.hasMode(vimperator.modes.QUICK_HINT) && (elem.absoTop < area[1] || elem.absoTop > area[3] ||
|
||||||
if ((elem.absoTop < area[1] || elem.absoTop > area[3] ||
|
// if ((elem.absoTop < area[1] || elem.absoTop > area[3] ||
|
||||||
elem.absoLeft > area[2] || elem.absoLeft < area[0]))
|
// elem.absoLeft > area[2] || elem.absoLeft < area[0]))
|
||||||
continue;
|
// continue;
|
||||||
|
|
||||||
// if (elem.offsetWidth == 0 && elem.offsetHeight == 0)
|
// if (elem.offsetWidth == 0 && elem.offsetHeight == 0)
|
||||||
// continue;
|
// continue;
|
||||||
@@ -688,9 +690,9 @@ function Hints() //{{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.document.addEventListener("DOMContentLoaded", initDoc, null);
|
window.document.addEventListener("DOMContentLoaded", initDoc, null);
|
||||||
//window.document.addEventListener("DOMContentLoaded", function() { vimperator.log("contentloaded"); }, null);
|
window.document.addEventListener("DOMContentLoaded", function() { vimperator.log("contentloaded"); }, null);
|
||||||
//window.addEventListener("load", function() { vimperator.log("load"); }, null);
|
window.addEventListener("load", function() { vimperator.log("load"); }, null);
|
||||||
//window.document.addEventListener("pageshow", function() { vimperator.log("pageshow"); }, null);
|
window.document.addEventListener("pageshow", function() { vimperator.log("pageshow"); }, null);
|
||||||
// FIXME: add resize support
|
// FIXME: add resize support
|
||||||
//window.addEventListener("resize", onResize, null);
|
//window.addEventListener("resize", onResize, null);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|||||||
@@ -938,27 +938,32 @@ function Mappings() //{{{
|
|||||||
));
|
));
|
||||||
|
|
||||||
// search management
|
// search management
|
||||||
addDefaultMap(new Map(vimperator.modes.NORMAL, ["g/"],
|
addDefaultMap(new Map(vimperator.modes.NORMAL, ["/"],
|
||||||
function() { vimperator.search.openSearchDialog(); },
|
function() { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_FORWARD); },
|
||||||
{
|
{
|
||||||
short_help: "Search forward for a pattern",
|
short_help: "Search forward for a pattern",
|
||||||
help: "Buggy on many sites, use / if you want a reliable search!"
|
help: "TODO"
|
||||||
|
}
|
||||||
|
));
|
||||||
|
addDefaultMap(new Map(vimperator.modes.NORMAL, ["?"],
|
||||||
|
function() { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_BACKWARD); },
|
||||||
|
{
|
||||||
|
short_help: "Search backwards for a pattern",
|
||||||
|
help: "TODO"
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
addDefaultMap(new Map(vimperator.modes.NORMAL, ["n"],
|
addDefaultMap(new Map(vimperator.modes.NORMAL, ["n"],
|
||||||
function() { vimperator.search.findNext(); },
|
function() { vimperator.search.findAgain(false); },
|
||||||
{
|
{
|
||||||
short_help: "Find next",
|
short_help: "Find next",
|
||||||
help: "Repeat the last \"g/\" 1 time (until count is supported). <br/>" +
|
help: "Repeat the last search 1 time (until count is supported)."
|
||||||
"NOTE: As \"g/\" is a little broken right now, use <F3> to go to the next search item of the \"/\" search for now."
|
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
addDefaultMap(new Map(vimperator.modes.NORMAL, ["N"],
|
addDefaultMap(new Map(vimperator.modes.NORMAL, ["N"],
|
||||||
function() { vimperator.search.findPrevious(); },
|
function() { vimperator.search.findAgain(true); },
|
||||||
{
|
{
|
||||||
short_help: "Find previous",
|
short_help: "Find previous",
|
||||||
help: "Repeat the last \"g/\" 1 time (until count is supported) in the opposite direction.<br/>" +
|
help: "Repeat the last search 1 time (until count is supported) in the opposite direction."
|
||||||
"NOTE: As \"g/\" is a little broken right now, use <S-F3> to go to the previous search item of the \"/\" search for now."
|
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ function Options() //{{{
|
|||||||
addOption(new Option(["hintstyle", "hs"], "string",
|
addOption(new Option(["hintstyle", "hs"], "string",
|
||||||
{
|
{
|
||||||
short_help: "CSS specification of unfocused hints appearance",
|
short_help: "CSS specification of unfocused hints appearance",
|
||||||
default_value: "z-index:5000; font-family:monospace; font-size:12px; color:black; background-color:yellow; " +
|
default_value: "z-index:5000; font-family:monospace; font-size:12px; color:white; background-color:red; " +
|
||||||
"border-color:ButtonShadow; border-width:0px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;"
|
"border-color:ButtonShadow; border-width:0px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;"
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|||||||
Reference in New Issue
Block a user