1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-22 00:17:58 +01:00

add forgotten files

This commit is contained in:
Martin Stubenschrott
2007-05-12 15:27:47 +00:00
parent 7ac9a05803
commit a8dbd904b5
2 changed files with 1047 additions and 0 deletions

View File

@@ -0,0 +1,575 @@
// XXX: remove!
function save_history()
{
set_pref("comp_history", comp_history.join("\n"));
}
function load_history()
{
var hist = get_pref("comp_history", "");
comp_history = hist.split("\n");
}
function multiliner(line, prev_match, heredoc)
{
var end = true;
var match = tokenize_ex(line, prev_match[4]);
if (prev_match[3] === undefined) prev_match[3] = '';
if (match[4] === null)
{
focusContent(false, true); // also sets tab_index to -1
execute_command.apply(this, match);
}
else
{
if (match[4] === false)
{
prev_match[3] = prev_match[3].replace(new RegExp('<<\s*' + prev_match[4]), heredoc.replace(/\n$/, ''));
focusContent(false, true); // also sets comp_tab_index to -1
execute_command.apply(this, prev_match);
prev_match = new Array(5);
prev_match[3] = '';
heredoc = '';
}
else
{
end = false;
if (!prev_match[3])
{
prev_match[0] = match[0];
prev_match[1] = match[1];
prev_match[2] = match[2];
prev_match[3] = match[3];
prev_match[4] = match[4];
}
else
{
heredoc += match[3] + '\n';
}
}
}
return [prev_match, heredoc, end];
}
/*
* This class is used for prompting of user input and echoing of messages
*
* it consists of a prompt and command field
* be sure to only create objects of this class when the chrome is ready
*/
function CommandLine ()
{
////////////////////////////////////////////////////////////////////////////////
////////////////////// PRIVATE SECTION /////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const UNINITIALIZED = -2; // notifies us, if we need to start history/tab-completion from the beginning
const HISTORY_SIZE = 500;
var completionlist = new CompletionList();
var completions = new Array();
var history = new Array();
var history_index = UNINITIALIZED;
var history_start = "";
// for the example command "open sometext| othertext" (| is the cursor pos)
var completion_start_index = 0; // will be 5 because we want to complete arguments for the :open command
var completion_prefix = "" // will be: "open sometext"
var completion_postfix = ""; // will be: " othertext"
var wild_index = 0; // keep track how often we press <Tab> in a row
var completion_index = UNINITIALIZED;
// The prompt for the current command, for example : or /. Can be blank
var prompt_widget = document.getElementById('new-vim-commandbar-prompt');
// The command bar which contains the current command
var command_widget = document.getElementById('new-vim-commandbar');
function setNormalStyle()
{
command_widget.inputField.setAttribute("style","font-family: monospace;");
}
function setErrorStyle()
{
command_widget.inputField.setAttribute("style", "font-family: monospace; color:white; background-color:red; font-weight: bold");
}
// Sets the prompt - for example, : or /
function setPrompt(prompt)
{
if (typeof(prompt) != "string")
prompt = "";
prompt_widget.value = prompt;
if (prompt)
{
// Initially (in the xul) the prompt is 'collapsed', this makes
// sure it's visible, then we toggle the display which works better
prompt_widget.style.visibility = 'visible';
prompt_widget.style.display = 'inline';
prompt_widget.size = prompt.length;
}
else
{
prompt_widget.style.display = 'none';
}
}
// Sets the command - e.g. 'tabopen', 'open http://example.com/'
function setCommand(cmd)
{
command_widget.value = cmd;
}
function addToHistory(str)
{
// first remove all old history elements which have this string
history = history.filter(function(elem) {
return elem != str;
});
// add string to the command line history
if (str.length >= 1 && history.push(str) > HISTORY_SIZE)
history.shift();
}
////////////////////////////////////////////////////////////////////////////////
////////////////////// PUBLIC SECTION //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
this.getCommand = function()
{
return command_widget.value;
};
/**
* All arguments can be ommited and will be defaulted to ""
*/
this.open = function(prompt, cmd, minor_mode)
{
if (!prompt)
prompt = "";
if (!cmd)
cmd = "";
if (minor_mode)
setCurrentMode(minor_mode);
setNormalStyle();
setPrompt(prompt);
setCommand(cmd);
history_index = UNINITIALIZED;
completion_index = UNINITIALIZED;
command_widget.focus();
};
this.echo = function(str)
{
setNormalStyle();
setPrompt("");
setCommand(str);
};
this.echoErr = function(str)
{
setErrorStyle();
setPrompt("");
setCommand(str);
};
this.clear = function()
{
setPrompt(" "); // looks faster than an empty string
setCommand("");
setNormalStyle();
};
this.onEvent = function(event)
{
//var end = false;
var command = this.getCommand();
if(event.type == "blur")
{
// when we do a command_widget.focus() we get a blur event immediately,
// so check if the target is the actualy input field
if (event.target == command_widget.inputField)
{
addToHistory(command);
completionlist.hide();
}
}
else if(event.type == "input")
{
vimperator.triggerCallback("change", command);
}
else if(event.type == "keypress")
{
var key = keyToString(event);
/* user pressed ENTER to carry out a command */
if (key == "<Return>" || key == "<C-j>" || key == "<C-m>")
{
// try {
// [prev_match, heredoc, end] = multiliner(command, prev_match, heredoc);
// } catch(e) {
// logObject(e);
// echoerr(e.name + ": " + e.message);
// prev_match = new Array(5);
// heredoc = '';
// return;
// }
// if (!end)
// command_line.value = "";
// the command is saved in the blur() handler
focusContent();
var res = vimperator.triggerCallback("submit", command);
return res;
}
/* user pressed ESCAPE to cancel this prompt */
else if (key == "<Esc>" || key == "<C-[>")
{
var res = vimperator.triggerCallback("cancel");
addToHistory(command);
this.clear();
focusContent(true, true);
return res;
}
/* user pressed UP or DOWN arrow to cycle history completion */
else if (key == "<Up>" || key == "<Down>")
{
//always reset the tab completion if we use up/down keys
completion_index = UNINITIALIZED;
/* save 'start' position for iterating through the history */
if (history_index == UNINITIALIZED)
{
history_index = history.length;
history_start = command;
}
while (history_index >= -1 && history_index <= history.length)
{
key == "<Up>" ? history_index-- : history_index++;
if (history_index == history.length) // user pressed DOWN when there is no newer history item
{
setCommand(history_start);
return;
}
// cannot go past history start/end
if (history_index <= -1)
{
history_index = 0;
beep();
break;
}
if (history_index >= history.length + 1)
{
history_index = history.length;
beep();
break;
}
if (history[history_index].indexOf(history_start) == 0)
{
setCommand(history[history_index]);
return;
}
}
beep();
}
/* user pressed TAB to get completions of a command */
else if (key == "<Tab>" || key == "<S-Tab>")
{
//always reset our completion history so up/down keys will start with new values
history_index = UNINITIALIZED;
// we need to build our completion list first
if (completion_index == UNINITIALIZED)
{
// FIXME: completions.clear();
completion_start_index = 0;
completion_index = -1;
wild_index = 0;
completion_prefix = command.substring(0, command_widget.selectionStart);
completion_postfix = command.substring(command_widget.selectionStart);
var res = vimperator.triggerCallback("complete", completion_prefix);
if (res)
[completion_start_index, completions] = res;
// Sort the completion list
if (get_pref('wildoptions').match(/\bsort\b/))
{
completions.sort(function(a, b) {
if (a[0] < b[0])
return -1;
else if (a[0] > b[0])
return 1;
else
return 0;
});
}
}
// we could also return when no completion is found
// but we fall through to the cleanup anyway
if (completions.length == 0)
{
beep();
// prevent tab from moving to the next field
event.preventDefault();
event.stopPropagation();
return;
}
var wim = get_pref('wildmode').split(/,/);
var has_list = false;
var longest = false;
var full = false;
var wildtype = wim[wild_index++] || wim[wim.length - 1];
if (wildtype == 'list' || wildtype == 'list:full' || wildtype == 'list:longest')
has_list = true;
else if (wildtype == 'longest' || wildtype == 'list:longest')
longest = true;
else if (wildtype == 'full' || wildtype == 'list:full')
full = true;
// show the list
if (has_list)
{
completionlist.show(completions);
}
if (full)
{
if (event.shiftKey)
{
completion_index--;
if(completion_index < -1)
completion_index = completions.length -1;
}
else
{
completion_index++;
if(completion_index >= completions.length)
completion_index = -1;
}
showStatusbarMessage("match " + (completion_index+1).toString() + " of " + completions.length.toString(), STATUSFIELD_PROGRESS);
// if the list is hidden, this function does nothing
completionlist.selectItem(completion_index);
}
// if (longest && completions.length == 1)
// {
// completion_index=0;
// }
if (completion_index == -1 && !longest) // wrapped around matches, reset command line
{
if (full && completions.length > 1)
{
setCommand(completion_prefix + completion_postfix);
//completion_list.selectedIndex = -1;
}
}
else
{
if (longest && completions.length > 1)
var compl = get_longest_substring();
if (full)
var compl = completions[completion_index][0];
if (completions.length == 1)
var compl = completions[COMMANDS][0];
//alert(compl)
if (compl)
{
setCommand(command.substring(0, completion_start_index) + compl + completion_postfix);
command_widget.selectionStart = command_widget.selectionEnd = completion_start_index + compl.length;
// XXX: needed?
// // Start a new completion in the next iteration. Useful for commands like :source
// if (completions.length == 1 && !full) // RFC: perhaps the command can indicate whether the completion should be restarted
// completion_index = UNINITIALIZED;
}
}
// prevent tab from moving to the next field
event.preventDefault();
event.stopPropagation();
}
else if (key == "<BS>")
{
// reset the tab completion
completion_index = history_index = UNINITIALIZED;
// and blur the command line if there is no text left
if(command.length == 0)
{
this.clear();
focusContent();
}
}
else // any other key
{
// reset the tab completion
completion_index = history_index = UNINITIALIZED;
}
}
}
logMessage("CommandLine initialized.");
}
function CompletionList()
{
const MAX_ITEMS = 10;
const CONTEXT_LINES = 3;
var completions = null; // a reference to the Array of completions
var completion_widget = document.getElementById("vim-completion");
var list_offset = 0; // how many items is the displayed list shifted from the internal tab index
var list_index = 0; // list_offset + list_index = completions[item]
// add a single completion item to the list
function addItem(completion_item, at_beginning)
{
var item = document.createElement("listitem");
var cell1 = document.createElement("listcell");
var cell2 = document.createElement("listcell");
cell1.setAttribute("label", completion_item[0]);
cell2.setAttribute("label", completion_item[1]);
cell2.setAttribute("style", "color:green; font-family: sans");
item.appendChild(cell1);
item.appendChild(cell2);
if (at_beginning == true)
{
var items = completion_widget.getElementsByTagName("listitem");
if (items.length > 0)
completion_widget.insertBefore(item, items[0]);
else
completion_widget.appendChild(item);
}
else
completion_widget.appendChild(item);
}
/**
* uses the entries in completions to fill the listbox
* @param startindex: start at this index and show MAX_ITEMS
* @returns the number of items
*/
function fill(startindex)
{
var complength = completions.length;
// remove all old items first
var items = completion_widget.getElementsByTagName("listitem");
while (items.length > 0) { completion_widget.removeChild(items[0]);}
// find start index
if (startindex + MAX_ITEMS > complength)
startindex = complength - MAX_ITEMS;
if (startindex < 0)
startindex = 0;
list_offset = startindex;
list_index = -1;
for(i = startindex; i < complength && i < startindex + MAX_ITEMS; i++)
{
addItem(completions[i], false);
}
return (i-startindex);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////// PUBLIC SECTION //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
this.len = function() {alert(completions.length);};
this.show = function(compl)
{
completions = compl;
fill(0);
var length = completions.length;
if (length > MAX_ITEMS)
length = MAX_ITEMS;
if (length > 1)
{
completion_widget.setAttribute("rows", length.toString());
completion_widget.hidden = false;
return true;
}
else
{
completion_widget.hidden = true;
return false;
}
}
this.hide = function()
{
completion_widget.hidden = true;
}
/**
* select index, refill list if necessary
*/
this.selectItem = function(index)
{
if(completion_widget.hidden)
return;
// find start index
var new_offset = 0;
if (index >= list_offset + MAX_ITEMS - CONTEXT_LINES)
new_offset = index - MAX_ITEMS + CONTEXT_LINES + 1;
else if (index <= list_offset + CONTEXT_LINES)
new_offset = index - CONTEXT_LINES;
else
new_offset = list_offset;
if (new_offset + MAX_ITEMS > completions.length)
new_offset = completions.length - MAX_ITEMS;
if (new_offset < 0)
new_offset = 0;
// for speed reason: just remove old item, and add the new one at the end of the list
var items = completion_widget.getElementsByTagName("listitem");
if (new_offset == list_offset + 1)
{
completion_widget.removeChild(items[0]);
addItem(completions[index + CONTEXT_LINES], false);
}
else if (new_offset == list_offset - 1)
{
completion_widget.removeChild(items[items.length-1]);
addItem(completions[index - CONTEXT_LINES], true);
}
else if (new_offset == list_offset)
{
// do nothing
}
else
fill(new_offset);
list_offset = new_offset;
completion_widget.selectedIndex = index - list_offset;
}
}
// function PreviewWindow()
// {
// var completion_widget = document.getElementById("vim-preview_window");
// }
// PreviewWindow.protoype = new CompletionList;
// var pw = new PreviewWindow();

View File

@@ -0,0 +1,472 @@
/***** BEGIN LICENSE BLOCK *****
Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.
The Initial Developer of the Original Code is Shawn Betts.
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
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
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.
***** 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();
}
// 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()
{
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
//Vimperator.prototype.search = new function()
function Search()
{
var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback
this.gWin = null;
this.gSelCtrl = null;
this.gFindState = [];
// Event handlers for search - closure is needed
vimperator.registerCallback("change", MODE_SEARCH, function(command){ self.searchKeyPressed(command); });
vimperator.registerCallback("submit", MODE_SEARCH, function(command){ self.searchSubmitted(command); });
vimperator.registerCallback("cancel", MODE_SEARCH, function(){ self.searchCancelled(); });
// Called when the search dialog is asked for. Sets up everything necessary
// for this round of searching
this.openSearchDialog = function() {
// Get a reference to the focused window if necessary
if (this.gWin == null) this.gWin = document.commandDispatcher.focusedWindow;
// 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('/', '', MODE_SEARCH);
}
// Called when the current search needs to be repeated in the forward
// direction
// @todo will need re-jigging when reverse search comes in
this.findNext = function() {
this.find(this.lastFindState()["search-str"], true, this.lastFindState()["range"]);
this.resumeFindState(this.lastFindState());
// if there is still a search result
if (this.lastFindState()["range"]) {
if (this.lastFindState()["wrapped"]) {
vimperator.echoerr("search hit BOTTOM, continuing at TOP");
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
// direction
this.findPrevious = function() {
this.find(this.lastFindState()["search-str"], false, this.lastFindState()["range"]);
this.resumeFindState(this.lastFindState());
// if there is still a search result
if (this.lastFindState()["range"]) {
if (this.lastFindState()["wrapped"]) {
vimperator.echoerr("search hit TOP, continuing at BOTTOM");
this.lastFindState()["wrapped"] = false;
}
else {
vimperator.echo('/' + this.lastFindState()["search-str"]);
}
}
}
// Called when the user types a key in the search dialog. Triggers a find attempt
this.searchKeyPressed = function(command) {
//this.find(command_line.value, true, this.lastFindState()["point"]);
if (command != "") {
this.find(vimperator.commandline.getCommand(), true, this.lastFindState()["point"]);
this.resumeFindState(this.lastFindState());
}
else {
clearSelection();
}
}
// Called when the enter key is pressed to trigger a search
this.searchSubmitted = function(command) {
removeMode(MODE_SEARCH);
if (this.lastFindState()["range"] == null) {
vimperator.echoerr("E492: Pattern not found: " + this.lastFindState()["search-str"]);
}
}
// Called when the search is cancelled - for example if someone presses
// escape while typing a search
this.searchCancelled = function() {
removeMode(MODE_SEARCH);
clearSelection();
focusContent(true, true);
}
//
// 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 = new Array();
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 = new Array();
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];
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;
}
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);
}
}
//logObject(vimperator);
logMessage("Search initialized.");
}
//searcher = new searcher();
//vimperator.registerCallback("submit", MODE_SEARCH, function(command) { /*vimperator.*/alert(command); } );
//vimperator.registerCallback("change", MODE_SEARCH, function(command) { /*vimperator.*/alert(command); } );
// @todo nicer way to register commands?
g_commands.push(
[
["nohilight", "noh"],
["noh[ilight]"],
"Clear the current selection",
"",
clearSelection,
null
]
);