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

Initial import

This commit is contained in:
Martin Stubenschrott
2007-04-10 19:43:19 +00:00
parent 4eddbb5b36
commit d0fe3cc426
9 changed files with 4519 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
/*
* low-level BOOKMARK and HISTORY handling
*
* these commands try to be generic and don't use any GUI handling code
* for higher-level functions look into commands.js
*/
function getProperty( aInput, aArc, DS )
{
var node;
node = DS.GetTarget( aInput, aArc, true );
if( node instanceof Components.interfaces.nsIRDFResource ) {
return node.Value;
}
if( node instanceof Components.interfaces.nsIRDFLiteral ) {
return node.Value;
}
return "";
}
function addBookmark(title, uri)
{
folder = RDF.GetResource("NC:BookmarksRoot");
var rSource = BookmarksUtils.createBookmark(title, uri, null, title);
var selection = BookmarksUtils.getSelectionFromResource(rSource);
var target = BookmarksUtils.getTargetFromFolder(folder);
BookmarksUtils.insertAndCheckSelection("newbookmark", selection, target);
//also update bookmark cache
g_bookmarks.unshift([uri, title]);
}
/* no idea what it does, it Just Works (TM)
*
* returns number of deleted bookmarks
*/
function deleteBookmark(url)
{
var deleted = 0;
// gNC_NS for trunk, NC_NS for 1.X
try {var pNC_NS; pNC_NS = gNC_NS;} catch (err) { pNC_NS = NC_NS;}
if(! BMSVC || ! BMDS || ! RDF || ! pNC_NS ) return null;
if ( !url) return null; // just in case
var curfolder = RDF.GetResource("NC:BookmarksRoot");
var urlArc = RDF.GetResource(pNC_NS+"URL");
var urlLiteral = RDF.GetLiteral(url);
if (BMDS.hasArcIn(urlLiteral, urlArc)) {
var bmResources, bmResource, title, uri, type, ptype;
bmResources = BMSVC.GetSources(urlArc, urlLiteral, true);
while (bmResources.hasMoreElements()) {
bmResource = bmResources.getNext();
type = BookmarksUtils.resolveType(bmResource);
if (type != "ImmutableBookmark") {
ptype = BookmarksUtils.resolveType(BMSVC.getParent(bmResource));
// alert(type);
// if ( type == "Folder") // store the current folder
// curfolder = bmResource;
if ( (type == "Bookmark" || type == "IEFavorite") && ptype != "Livemark") {
title = BookmarksUtils.getProperty(bmResource, pNC_NS+"Name");
uri = BookmarksUtils.getProperty(bmResource, pNC_NS+"URL");
if (uri == url)
{
RDFC.Init(BMDS, BMSVC.getParent(bmResource));
RDFC.RemoveElement(bmResource, true);
deleted++;
}
}
}
}
}
// also update bookmark cache, if we removed at least one bookmark
if(deleted > 0)
bookmarks_loaded = false;
return deleted;
}
/* call the function like this:
var res = new Object();
parseBookmarkString("-t tag1,tag2 -T title http://www.orf.at", res);
res.tags is an array of tags
res.title is the title or "" if no one was given
res.url is the url as a string
returns false, if parsing failed
*/
function parseBookmarkString(str, res)
{
res.tags = [];
res.title = null;
res.url = null;
var re_title = /^\s*((-t|--title)\s+(\w+|\".*\"))(.*)/;
var re_tags = /^\s*((-T|--tags)\s+((\w+)(,\w+)*))(.*)/;
var re_url = /^\s*(\".+\"|\S+)(.*)/;
var match_tags = null;
var match_title = null;
var match_url = null;
while(!str.match(/^\s*$/))
{
/* first check for --tags */
match_tags = str.match(re_tags);
if(match_tags != null)
{
str = match_tags[match_tags.length-1]; // the last captured parenthesis is the rest of the string
tags = match_tags[3].split(",");
res.tags = res.tags.concat(tags);
}
else /* then for --titles */
{
match_title = str.match(re_title);
if(match_title != null)
{
// only one title allowed
if (res.title != null)
return false;
str = match_title[match_title.length-1]; // the last captured parenthesis is the rest of the string
title = match_title[3];
if(title.charAt(0) == '"')
title = title.substring(1,title.length-1);
res.title = title;
}
else /* at last check for an url */
{
match_url = str.match(re_url);
if (match_url != null)
{
// only one url allowed
if (res.url != null)
return false;
str = match_url[match_url.length-1]; // the last captured parenthesis is the rest of the string
url = match_url[1];
if(url.charAt(0) == '"')
url = url.substring(1,url.length-1);
res.url = url;
}
else return false; // no url, tag or title found but still text left, abort
}
}
}
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,486 @@
/*
* COMPLETION HANDLING
*
* also responsible for command history, url history and bookmark handling
*/
// array of all our bookmarks
var g_bookmarks = [];
var bookmarks_loaded = false;
// array of all our history items
var g_history = [];
var history_loaded = false;
// variables for the tab completion and command history:
// -1: filled, but no selection made
// >= 0: index of current item in the g_completions array
const COMPLETION_UNINITIALIZED = -2; // if we need to build the completion array first
const COMPLETION_MAXITEMS = 10;
const COMPLETION_CONTEXTLINES = 3;
const COMMAND_LINE_HISTORY_SIZE = 500;
// 2 dimensional: 1st element: what to complete
// 2nd element: help description
var g_completions = new Array();
var comp_tab_index = COMPLETION_UNINITIALIZED; // the index in the internal g_completions array
var comp_tab_list_offset = 0; // how many items is the displayed list shifted from the internal tab index
var comp_tab_startstring = "";
var comp_history = new Array();
var comp_history_index = -1;
/* uses the entries in g_completions to fill the listbox
* starts at index 'startindex', and shows COMPLETION_MAXITEMS
* returns the number of items */
function completion_fill_list(startindex)/*{{{*/
{
// remove all old items first
var items = completion_list.getElementsByTagName("listitem");
while (items.length > 0) { completion_list.removeChild(items[0]);}
// find start index
//var i = index - 3; // 3 lines of context
if (startindex + COMPLETION_MAXITEMS > g_completions.length)
startindex = g_completions.length - COMPLETION_MAXITEMS;
if (startindex < 0)
startindex = 0;
for(i=startindex; i<g_completions.length && i < startindex + COMPLETION_MAXITEMS; i++)
{
completion_add_to_list(g_completions[i], false);
}
//completion_list.hidden = true;
// completion_list.setAttribute("rows", (i-startindex).toString());
// showStatusbarMessage ( (i-startindex).toString(), 1);
// if ( i-startindex > 0) // XXX: respect completetopt setting
// completion_list.hidden = false;
// else
// completion_list.hidden = true;
// completion_list.setAttribute("rows", (i-startindex).toString());
return (i-startindex);
}/*}}}*/
function completion_show_list()/*{{{*/
{
var items = g_completions.length;
if (items > COMPLETION_MAXITEMS)
items = COMPLETION_MAXITEMS;
if (items > 1) // FIXME
{
//alert(completion_list.getRowCount().toString());
completion_list.setAttribute("rows", items.toString());
//completion_list.rowCountChanged(0, items);
completion_list.hidden = false;
//completion_list.selectedIndex = selected_index;
}
else
completion_list.hidden = true;
}/*}}}*/
/* add a single completion item to the list */
function completion_add_to_list(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]);
cell1.setAttribute("width", "200");
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_list.getElementsByTagName("listitem");
if (items.length > 0)
completion_list.insertBefore(item, items[0]);
else
completion_list.appendChild(item);
}
else
completion_list.appendChild(item);
}/*}}}*/
/* select the next index, refill list if necessary
*
* changes 'comp_tab_index' */
function completion_select_next_item()/*{{{*/
{
comp_tab_index++;
if (comp_tab_index >= g_completions.length) /* wrap around */
{
comp_tab_index = -1;
completion_list.selectedIndex = -1;
return;
}
if (comp_tab_index == 0) // at the top of the list
{
completion_fill_list(0);
comp_tab_list_offset = 0;
}
var listindex = comp_tab_index - comp_tab_list_offset;
// only move the list, if there are still items we can move
if (listindex >= COMPLETION_MAXITEMS - COMPLETION_CONTEXTLINES &&
comp_tab_list_offset < g_completions.length - COMPLETION_MAXITEMS)
{
// for speed reason: just remove old item, and add new at the end of the list
var items = completion_list.getElementsByTagName("listitem");
completion_list.removeChild(items[0]);
completion_add_to_list(g_completions[comp_tab_index + COMPLETION_CONTEXTLINES], false);
comp_tab_list_offset++;
}
listindex = comp_tab_index - comp_tab_list_offset;
completion_list.selectedIndex = listindex;
showStatusbarMessage(" match " + (comp_tab_index+1).toString() + " of " + g_completions.length.toString() + " ", STATUSFIELD_PROGRESS);
}/*}}}*/
/* select the previous index, refill list if necessary
*
* changes 'comp_tab_index' */
function completion_select_previous_item()/*{{{*/
{
comp_tab_index--;
if (comp_tab_index == -1)
{
completion_list.selectedIndex = -1;
return;
}
if (comp_tab_index < -1) // go to the end of the list
{
comp_tab_index = g_completions.length -1;
completion_fill_list(g_completions.length - COMPLETION_MAXITEMS);
comp_tab_list_offset = g_completions.length - COMPLETION_MAXITEMS;//COMPLETION_MAXITEMS - 1;
if (comp_tab_list_offset < 0)
comp_tab_list_offset = 0;
}
var listindex = comp_tab_index - comp_tab_list_offset;
// only move the list, if there are still items we can move
if (listindex < COMPLETION_CONTEXTLINES && comp_tab_list_offset > 0)
{
// for speed reason: just remove old item, and add new at the end of the list
var items = completion_list.getElementsByTagName("listitem");
completion_list.removeChild(items[items.length-1]);
completion_add_to_list(g_completions[comp_tab_index - COMPLETION_CONTEXTLINES], true);
comp_tab_list_offset--;
}
listindex = comp_tab_index - comp_tab_list_offset;
completion_list.selectedIndex = listindex;
showStatusbarMessage("item " + (comp_tab_index+1).toString() + " of " + g_completions.length.toString(), STATUSFIELD_PROGRESS);
}/*}}}*/
/*
* filter a list of urls
*
* may consist of searchengines, boorkmarks and history,
* depending on the 'complete' option
*/
function get_url_completions(filter)/*{{{*/
{
g_completions = [];
var cpt = get_pref("complete");
// join all completion arrays together
for (var i = 0; i < cpt.length; i++)
{
if (cpt[i] == 's')
g_completions = g_completions.concat(get_search_completions(filter));
else if (cpt[i] == 'b')
g_completions = g_completions.concat(get_bookmark_completions(filter));
else if (cpt[i] == 'h')
g_completions = g_completions.concat(get_history_completions(filter));
}
return g_completions;
}/*}}}*/
/* discard all entries in the 'urls' array, which don't match 'filter */
function filter_url_array(urls, filter, use_regex)/*{{{*/
{
var filtered = [];
// completions which don't match the url but just the description
// list them add the end of the array
var additional_completions = [];
var reg, reg2;
if (use_regex)
{
reg = new RegExp("^" + filter, "i");
reg2 = new RegExp(filter, "i");
}
outer:
for (var i = 0; i < urls.length; ++i)
{
if (filter != null && filter.length > 0)
{
// first check if the filter matches in the main part of the URL
var bm = urls[i][0].replace(/^.*:\/\/(www)?/, "");
bm = bm.replace(/\/.*$/, "");
var tokens = bm.split(".");
for (var k = 0; k < tokens.length-1; k++) // -1 because we don't search the domain (like .com)
{
if (use_regex)
{
if(tokens[k].search(reg) != -1)
{
filtered.push([urls[i][0], urls[i][1] ]);
continue outer;
}
}
else
{
if (tokens[k].indexOf(filter) == 0)
{
filtered.push([urls[i][0], urls[i][1] ]);
continue outer;
}
}
}
// otherwise check if the filter matches in the description of the bookmark
if (use_regex)
{
if(urls[i][0].search(reg2) == -1 && urls[i][1].search(reg2) == -1)
continue;
}
else
{
if (urls[i][0].indexOf(filter) == -1 && urls[i][1].indexOf(filter) == -1)
continue;
}
}
additional_completions.push([urls[i][0], urls[i][1] ]);
}
return filtered.concat(additional_completions);
}/*}}}*/
function get_search_completions(filter)/*{{{*/
{
var search_completions = [];
var reg = new RegExp("^" + filter, "i");
for (var i = 0; i < g_searchengines.length; i++)
{
if (g_searchengines[i][0].search(reg) != -1)
search_completions.push([g_searchengines[i][0] + " ", g_searchengines[i][1] ]);
}
return search_completions;
}/*}}}*/
function get_bookmark_completions(filter)/*{{{*/
{
if (!bookmarks_loaded)
{
// update our bookmark cache
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService( Components.interfaces.nsIRDFService );
var root = RDF.GetResource( "NC:BookmarksRoot" );
bookmarks = []; // here getAllChildren will store the bookmarks
g_bookmarks = []; // also clear our bookmark cache
BookmarksUtils.getAllChildren(root, bookmarks);
for(var i = 0; i < bookmarks.length; i++)
{
if (bookmarks[i][0] && bookmarks[i][1])
g_bookmarks.push([bookmarks[i][1].Value, bookmarks[i][0].Value ]);
}
bookmarks_loaded = true;
}
return filter_url_array(g_bookmarks, filter, true);
}/*}}}*/
function get_history_completions(filter)/*{{{*/
{
var history = document.getElementById("hiddenHistoryTree");
// build our history cache
if (history_loaded == false)
{
if (history.hidden)
{
history.hidden = false;
var globalHistory = Components.classes["@mozilla.org/browser/global-history;2"].getService(Components.interfaces.nsIRDFDataSource);
history.database.AddDataSource(globalHistory);
history_completions = [];
}
if (!history.ref)
history.ref = "NC:HistoryRoot";
const NC_NS = "http://home.netscape.com/NC-rdf#";
if (!gRDF)
gRDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
var nameResource = gRDF.GetResource(NC_NS + "Name");
var builder = history.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
var count = history.view.rowCount;
for (var i = count-1; i >= 0; i--)
{
var res = builder.getResourceAtIndex(i);
var url = res.Value;
// var col = history.columns["Name"];
//var title = history.view.getCellText(i, col);
var title;
var titleRes = history.database.GetTarget(res, nameResource, true);
if (!titleRes)
continue;
var titleLiteral = titleRes.QueryInterface(Components.interfaces.nsIRDFLiteral);
if(titleLiteral)
title = titleLiteral.Value;
else
title = "";
g_history.push([url, title]);
}
// if(url.toLowerCase().indexOf(filter.toLowerCase()) > -1)
history_loaded = true;
}
return filter_url_array(g_history, filter, true);
}/*}}}*/
function get_command_completions(filter)/*{{{*/
{
g_completions = [];
for(var i=0; i<g_commands.length; i++)
{
for(var j=0; j<g_commands[i][0].length; j++)
{
//var re = new RegExp("^" + filter);
if (g_commands[i][0][j].indexOf(filter) == 0)
{
g_completions.push([g_commands[i][0][j], g_commands[i][1]]);
break; // only add a command once
}
}
}
// commands should be sorted anyway, but it doesn't really hurt -> it DOES hurt :(
//g_completions.sort();
}/*}}}*/
function get_settings_completions(filter)/*{{{*/
{
settings_completions = [];
var no_mode = false;
if (filter.indexOf("no") == 0) // boolean option
{
no_mode = true;
filter = filter.substr(2);
}
// check if filter ends with =, then complete current value
else if(filter.length > 0 && filter.lastIndexOf("=") == filter.length -1)
{
filter = filter.substr(0, filter.length-1);
for(var i=0; i<g_settings.length; i++)
{
for(var j=0; j<g_settings[i][0].length; j++)
{
if (g_settings[i][0][j] == filter)
{
settings_completions.push([filter + "=" + g_settings[i][4].call(this), ""]);
return settings_completions;
}
}
}
return settings_completions;
}
for(var i=0; i<g_settings.length; i++)
{
if (filter == "" || g_settings[i][0][0].indexOf(filter) > -1)
{
// for 'no'-mode only return bool options
if (no_mode)
{
if (g_settings[i][5] == "bool")
settings_completions.push(["no" + g_settings[i][0][0], g_settings[i][1]]);
}
else
settings_completions.push([g_settings[i][0][0], g_settings[i][1]]);
}
}
return settings_completions;
}/*}}}*/
////////// COMMAND HISTORY HANDLING ////////////
function add_to_command_history(str)
{
/* add string to the command line history */
if (str.length >= 2 && comp_history.push(str) > COMMAND_LINE_HISTORY_SIZE)
comp_history.shift();
}
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");
}
///////// PREVIEW WINDOW //////////////////////
/* uses the entries in completions to fill the listbox */
function preview_window_fill(completions)
{
// remove all old items first
var items = preview_window.getElementsByTagName("listitem");
while (items.length > 0) { preview_window.removeChild(items[0]);}
for(i=0; i<completions.length; i++)
{
var item = document.createElement("listitem");
var cell1 = document.createElement("listcell");
var cell2 = document.createElement("listcell");
cell1.setAttribute("label", completions[i][0]);
cell2.setAttribute("label", completions[i][1]);
//cell2.setAttribute("style", "color:green; font-family: sans; text-align:right");
cell2.setAttribute("style", "color:green; font-family: sans;");
item.appendChild(cell1);
item.appendChild(cell2);
preview_window.appendChild(item);
}
}
function preview_window_select(event)
{
var listcell = document.getElementsByTagName("listcell");
// 2 columns for now, use the first column
var index = (preview_window.selectedIndex * 2) + 0;
var val = listcell[index].getAttribute("label");
if (val && event.button == 0 && event.type == "dblclick") // left double click
openURLs(val);
else if (val && event.button == 1) // middle click
openURLsInNewTab(val);
else
return false;
}
// vim: set fdm=marker :

View File

@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<RDF:Seq RDF:about="urn:mozilla:package:root">
<RDF:li RDF:resource="urn:mozilla:package:vimperator"/>
</RDF:Seq>
<!--<RDF:Seq RDF:about="urn:mozilla:overlays">-->
<!--<RDF:li RDF:resource="chrome://browser/content/browser.xul"/>-->
<!--</RDF:Seq>-->
<RDF:Seq RDF:about="chrome://browser/content/browser.xul">
<RDF:li>chrome://vimperator/content/vimperator.xul</RDF:li>
</RDF:Seq>
<RDF:Description RDF:about="urn:mozilla:package:vimperator"
chrome:displayName="Vimperator"
chrome:author="Martin Stubenschrott"
chrome:name="vimperator"
chrome:extension="true"
chrome:description="Make Firefox like Vim">
</RDF:Description>
</RDF:RDF>

View File

@@ -0,0 +1,640 @@
/**
*
* Mozilla Public License Notice
*
* 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 Original Code and Idea is the Hit-a-Hint Mozilla extension.
* The Initial Developer of the Original Code and the Idea is Pekka
* P. Sillanpaa. Portions created by Initial Developer are Copyright
* (C) 2004. All Rights Reserved.
*
* Contributor(s): Pekka Sillanpaa, Paul Stone
* adapted for vimperator use by: Martin Stubenschrott
*
*/
const HINT_MODE_QUICK = 0;
const HINT_MODE_ALWAYS = 1;
const HINT_MODE_EXTENDED = 2;
function hit_a_hint()
{
const HINT_PREFIX = 'hah_hint_'; // prefix for the hint id
// public accessors
this.hintsVisible = function() { return isHahModeEnabled; };
this.hintedElements = function() { return hintedElems; };
this.currentState = function() { return state;};
this.setCurrentState = function(s) { state = s;};
this.currentMode = function() { return hintmode;};
var isHahModeEnabled = false; // is typing mode on
var hintmode = HINT_MODE_QUICK;
var hintedElems = [];
var linkNumString = ""; // the typed link number is in this string
var linkCount = 0;
var state = 0; // 0: empty or processing, 1: a full hint was parsed
var wins; // frame array
// each hint element is a clone of this element
var hintElemSpan;
////////////////////////////////////////////////////////////////////////////////
// configuration and initialization related functions
////////////////////////////////////////////////////////////////////////////////
// function load()
// {
// isHahModeEnabled = false;
// hintedElem = null;
// }
////////////////////////////////////////////////////////////////////////////////
// hint activating and loading related functions
////////////////////////////////////////////////////////////////////////////////
function startCoordLoader(doc)
{
win = doc.defaultView;
if (!win)
return;
if (win.winId != null)
{
window.clearTimeout(win.coordLoaderId);
}
else
{
if (!wins)
wins = new Array();
win.winId = wins.length;
wins.push(win);
}
// logMessage("winId:"+win.winId);
win.res = doc.evaluate(get_pref("hinttags"), doc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
win.coordLoaderId = window.setTimeout("hah.loadCoord(" + win.winId + ", 0);", 1);
}
this.loadCoord = function(winId, i)
{
win = wins[winId];
var elem = win.res.snapshotItem(i);
if (elem)
genElemCoords(elem);
i++;
if (i < win.res.snapshotLength && !isHahModeEnabled)
window.setTimeout("hah.loadCoord(" + winId + ", "+ i +");", 1);
else
win.coordLoaderId = null;
};
function genElemCoords(elem)
{
if (typeof(elem.validCoord) != "undefined")
{
if (elem.validCoord == elem.ownerDocument.validCoords)
return;
}
if (elem.offsetParent)
{
genElemCoords(elem.offsetParent);
elem.absoLeft = elem.offsetParent.absoLeft + elem.offsetLeft;
elem.absoTop = elem.offsetParent.absoTop + elem.offsetTop;
}
else
{
elem.absoLeft = elem.offsetLeft - 5;
elem.absoTop = elem.offsetTop;
}
elem.validCoord = elem.ownerDocument.validCoords;
}
function createHints(win)
{
if (!win)
{
win = window._content;
linkCount = 0;
}
var area = new Array(4);
area[0] = win.pageXOffset - 5;
area[1] = win.pageYOffset - 5;
area[2] = area[0] + win.innerWidth;
area[3] = area[1] + win.innerHeight;
var doc = win.document;
var res = doc.evaluate(get_pref("hinttags"), doc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var elem, i;
hintElemSpan = doc.createElement('SPAN');
hintElemSpan.style.cssText = get_pref("hintstyle");
hintElemSpan.setAttribute('name', 'hah_hint');
var hintContainer = doc.getElementById('hah_hints');
if (hintContainer == null)
{
genHintContainer(doc);
hintContainer = doc.getElementById('hah_hints');
}
hintContainer.valid_hint_count = 0; // none of these hints should be visible initially
var hints = hintContainer.childNodes;
var maxhints = get_pref("maxhints");
for (i = 0; i < res.snapshotLength; i++)
{
// this saves from script timeouts on pages with some thousand links
if (linkCount >= maxhints)
break;
elem = res.snapshotItem(i);
genElemCoords(elem);
// for extended hint mode, show all - even currently hidden - hints
if (hintmode == HINT_MODE_QUICK && (elem.absoTop < area[1] || elem.absoTop > area[3] ||
elem.absoLeft > area[2] || elem.absoLeft < area[0]))
continue;
// XXX: what does that do
// if (elem.offsetWidth == 0 && elem.offsetHeight == 0)
// continue;
var cs = doc.defaultView.getComputedStyle(elem, null);
if (cs.getPropertyValue("visibility") == "hidden")
continue;
if (linkCount < hints.length)
hintElem = hints[linkCount];
else // need to attach this new hintElem to the hint container
{
hintElem = hintElemSpan.cloneNode(false);
hintContainer.appendChild(hintElem);
}
hintElem.style.display = 'none';
hintElem.style.top = elem.absoTop + "px";
hintElem.style.left = elem.absoLeft + "px";
hintElem.refElem = elem;
hintContainer.valid_hint_count++; // one more visible hint in this frame
linkCount++; // and one more total hint
}
doc.coordsInvalidated = false;
// recursively create hints
for (i = 0; i < win.frames.length; i++)
createHints(win.frames[i]);
}
function showHints(win, off)
{
offset = off; // must be global without 'var' for recursion
if (!win)
win = window._content;
if (linkCount == 0 && hintmode != HINT_MODE_ALWAYS)
{
beep();
linkNumString = '';
hintedElems = [];
isHahModeEnabled = false;
return;
}
var doc = win.document;
var hintElem = null;
var hintContainer = doc.getElementById('hah_hints');
var hints = hintContainer.childNodes;
var i, j;
for (i = 0; i < hintContainer.valid_hint_count; i++)
{
hintText = formatHint(offset+i);
hintElem = hints[i];
hintElem.style.display = 'inline';
//hintElem.style.position = 'absolute';
hintElem.innerHTML = hintText;
hintElem.id = HINT_PREFIX + hintText;
}
offset += hintContainer.valid_hint_count;
// recursively show hints
for (j = 0; j < win.frames.length; j++)
showHints(win.frames[j], offset);
}
/* removes all visible hints from doc
* or from current document, if doc == null
*/
function removeHints(win)
{
if (!win)
win = window._content;
var doc = win.document;
var res = doc.evaluate("//HINTS/SPAN", doc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE , null);
var elem, i;
for (i = 0; i < res.snapshotLength; i++)
{
elem = res.snapshotItem(i);
setHintStyle(elem, get_pref("hintstyle"));
elem.style.display = 'none';
}
for (i = 0; i < win.frames.length; i++)
removeHints(win.frames[i]);
}
function onResize(event)
{
doc = event.originalTarget;
invalidateCoords(doc);
startCoordLoader(doc);
}
function invalidateCoords(doc)
{
if (!doc.coordsInvalidated)
{
// every element has .validCoord
// if it is the same as doc:s .validCoords,
// the coordinates have not been regenerated, otherwise they
// have. This way we can also use recursive generation
// so that the coordinates are generated for every
// element just once
doc.validCoords = !doc.validCoords;
// this is because window can be resized many times
// and the coords should be invalidated just once.
doc.coordsInvalidated = true;
// logMessage(doc.validCoords);
}
}
function getHintById(id, win)
{
if (!win)
win = window._content;
var doc = win.document;
var elem, i;
//var hintId = parseInt(id, nums.length);
//elem = doc.getElementById(prefix + hintId);
elem = doc.getElementById(HINT_PREFIX + id);
if (elem)
{
return elem;
}
else
{
for (i = 0; i < win.frames.length; i++)
{
elem = getHintById(id, win.frames[i]);
if (elem)
return elem;
}
}
return null;
}
function formatHint(hintNum)
{
var hintCharacters = get_pref("hintchars");
var str = hintNum.toString(hintCharacters.length); // turn hintNum into a base(length) number
// map the number onto the chars in the numbers string
var result = '';
// make all links the same length
var hintLength = 1;
var tmp = linkCount;
while((tmp /= hintCharacters.length) > 1.0)
hintLength++;
while(str.length < hintLength)
{
result += hintCharacters.charAt(0).toUpperCase();
hintLength--;
}
for (var i = 0; i < str.length; i++)
result += (hintCharacters.charAt(parseInt(str[i], hintCharacters.length))).toUpperCase();
return result;
}
function setHintStyle(hintElem, styleString)
{
if (hintElem && hintElem.style)
{
xTemp = hintElem.style.left;
yTemp = hintElem.style.top;
hintElem.style.cssText = styleString;
hintElem.style.left = xTemp;
hintElem.style.top = yTemp;
}
}
function changeHintFocus(linkNumString, oldLinkNumString)
{
var styleString = get_pref("hintstyle");
var styleStringFocus = get_pref("focusedhintstyle");
var hintElem;
if (oldLinkNumString.length > 0)
{
hintElem = getHintById(oldLinkNumString);
setHintStyle(hintElem, styleString);
}
if (linkNumString.length > 0)
{
hintElem = getHintById(linkNumString);
setHintStyle(hintElem, styleStringFocus);
if(hintElem)
setMouseOverElement(hintElem.refElem);
}
}
////////////////////////////////////////////////////////////////////////////////
// basic functionality
////////////////////////////////////////////////////////////////////////////////
/**
* Enables the HaH-mode by showing the hints and prepare to input the
* hint numbers
*
* @author Pekka Sillanpaa
* @param event that caused the mode to change
* @return -1 if already enabled
*/
//function enableHahMode(event, mode)
this.enableHahMode = function(mode)
{
// if (isHahModeEnabled)
// return false;
hintmode = mode;
state = 0;
linkCount = 0;
linkNumString = '';
isHahModeEnabled = true;
createHints();
showHints(null, 0);
return true;
};
/**
* Disables the HaH-mode by hiding the hints and disabling the input mode
*
* @author Pekka Sillanpaa
* @param event that caused the mode to change
* @param action = true if something is to be clicked
* false if cancel
* @return -1 if already disabled
*/
//function disableHahMode(event)
this.disableHahMode = function(win)
{
isHahModeEnabled = false;
hintmode = HINT_MODE_QUICK;
linkNumString = '';
hintedElems = [];
removeHints(win);
return 0;
};
this.resetHintedElements = function()
{
linkNumString = '';
state = 0;
while(hintedElems.length > 0)
{
var elem = hintedElems.pop();
if (!elem)
return 0;
// reset style attribute
setHintStyle(elem, get_pref("hintstyle"));
}
};
// this function 'click' an element, which also works
// for javascript links
this.openHints = function(new_tab, new_window)
{
var x = 0, y = 0;
while(hintedElems.length > 0)
{
var elem = hintedElems.pop();
if (!elem)
return 0;
setHintStyle(elem, get_pref("hintstyle"));
elem = elem.refElem;
var elemTagName = elem.tagName;
elem.focus();
if (elemTagName == 'FRAME' || elemTagName == 'IFRAME')
return 0;
// for imagemap
if (elemTagName == 'AREA')
{
var coords = elem.getAttribute("coords").split(",");
x = Number(coords[0]);
y = Number(coords[1]);
}
doc = window._content.document;
view = window.document.defaultView;
var evt = doc.createEvent('MouseEvents');
evt.initMouseEvent('mousedown', true, true, view, 1, x+1, y+1, 0, 0, /*ctrl*/ new_tab, /*event.altKey*/0, /*event.shiftKey*/ new_window, /*event.metaKey*/0, 0, null);
elem.dispatchEvent(evt);
var evt = doc.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, view, 1, x+1, y+1, 0, 0, /*ctrl*/ new_tab, /*event.altKey*/0, /*event.shiftKey*/ new_window, /*event.metaKey*/0, 0, null);
elem.dispatchEvent(evt);
// for 'pure' open calls without a new tab or window it doesn't
// make sense to open more hints in the current tab, open new tabs
// for it
if (!new_tab && !new_window)
new_tab = true;
}
return 0;
};
this.yankHints = function()
{
var loc = "";
var elems = hah.hintedElements();
var tmp = "";
for(i=0; i<elems.length; i++)
{
tmp = elems[i].refElem.href;
if (typeof(tmp) != 'undefined' && tmp.length > 0)
loc += tmp + "\n";
}
copyToClipboard(loc);
echo("Yanked " + loc);
};
function setMouseOverElement(elem)
{
var doc = window.document;
if (elem.tagName == 'FRAME' || elem.tagName == 'IFRAME')
{
elem.contentWindow.focus();
return;
}
else
{
//elem.focus();
}
var evt = doc.createEvent('MouseEvents');
var x = 0;
var y = 0;
// for imagemap
if (elem.tagName == 'AREA')
{
var coords = elem.getAttribute("coords").split(",");
x = Number(coords[0]);
y = Number(coords[1]);
}
evt.initMouseEvent('mouseover', true, true, doc.defaultView, 1, x, y, 0, 0, 0, 0, 0, 0, 0, null);
elem.dispatchEvent(evt);
}
////////////////////////////////////////////////////////////////////////////////
// event handlers
////////////////////////////////////////////////////////////////////////////////
// returns nr. of fully parsed links when a new hint has been found,
// otherwise 0 if current state is part of a hint, or -1 if an error occured
// (like we have typed keys which never can become a hint
this.processEvent = function(event)
{
if (!isHahModeEnabled)
return -1;
// reset state to show that we are in processing mode
state = 0;
var num = String.fromCharCode(event.charCode).toUpperCase();
var hintCharacters = get_pref("hintchars");
if (num != null && hintCharacters.toUpperCase().indexOf(num) > -1)
{
var oldLinkNumString = linkNumString;
linkNumString += '' + num;
// update reference to currently selected node;
var elem = getHintById(linkNumString);
changeHintFocus(linkNumString, oldLinkNumString);
// if we found the hint, fine just return it
if (elem)
{
hintedElems.push(elem);
linkNumString = '';
state = 1;
return hintedElems.length;
}
//calculate how many characters a hint must have
var hintLength = 1;
var tmp = linkCount;
while((tmp /= hintCharacters.length) > 1.0)
hintLength++;
if (linkNumString.length >= hintLength)
return -1;
else
return 0;
}
// an unparseable or wrong key
return -1;
}
function genHintContainer(doc)
{
if (doc.getElementsByTagName('HINTS').length > 0)
return;
hints = doc.createElement('HINTS');
hints.id = "hah_hints";
hints.valid_hint_count = 0; // initially 0 elements are usable as hints
doc.body.appendChild(hints);
}
function initDoc(event)
{
doc = event.originalTarget;
genHintContainer(doc);
isHahModeEnabled = false;
hintedElems = [];
if (!doc.validCoords)
doc.validCoords = true;
else
doc.validCoords = false;
// XXX: prepend a ! ?
if (doc.coordsInvalidated)
doc.coordsInvalidated = true;
else
doc.coordsInvalidated = false;
startCoordLoader(doc);
if (hintmode == HINT_MODE_ALWAYS)
{
state = 0;
linkCount = 0;
linkNumString = '';
isHahModeEnabled = true;
createHints();
showHints(null, 0);
}
//window.setTimeout("this.enableHahMode(HINT_MODE_ALWAYS);", 0);
}
window.document.addEventListener("pageshow", initDoc, null);
window.addEventListener("resize", onResize, null);
logMessage("HAH initialized.");
}
var hah = new hit_a_hint();

View File

@@ -0,0 +1,358 @@
// settings.js
//
// handles all persistent storage of information
// to and from the firefox registry
// the global handle to the root of the firefox settings
var g_firefox_prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var g_vimperator_prefs = null;
// non persistent options
var opt_usermode = false;
var opt_fullscreen = false;
/* all user-setable vimperator settings
* format:
* [
* 0: [all names of this setting],
* 1: description,
* 2: help text,
* 3: set_function,
* 4: get_function,
* 5: type,
* 6: default,
* 7: checkfunc,
* 8: completefunc
* ]
*/
var g_settings = [/*{{{*/
[
["activate"],
"Define when tabs are automatically activated",
"Not implemented yet",
function(value) { set_pref("activate", value); },
function() { return get_pref("activate"); },
"stringlist",
"quickmark,tabopen,paste",
null,
null
],
[
["beep"],
"Emit a pc speaker beep on certain errors",
null,
function(value) { set_pref("beep", value); },
function() { return get_pref("beep"); },
"boolean",
true,
null,
null
],
[
["complete", "cpt"],
"Order and items which are completed at the :[tab]open prompt",
"Available items:<br>"+
"<ul><li><b>s</b>: Search machines</li><li>"+
" <b>b</b>: Bookmarks</li><li>"+
" <b>h</b>: History</li></ul>"+
"The order is important, so <code class=command>:set complete=bs</code> would list bookmarks first, and then any available quick searches.",
function(value) { set_pref("complete", value); },
function() { return get_pref("complete"); },
"charlist",
"sbh",
null,
null
],
[
["completeopt", "cot"],
"Define how command line completion works",
"Not implemented yet.",
function(value) { set_pref("completeopt", value); },
function() { return get_pref("completeopt"); },
"stringlist",
"menu",
null,
null
],
[
["extendedhinttags", "eht"],
"XPath string of hintable elements activated by ';'",
null,
function(value) { set_pref("extendedhinttags", value); },
function() { return get_pref("extendedhinttags"); },
"string",
"//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | //input[@type!='hidden'] | //a | //area | //iframe | //textarea | //button | //select",
null,
null
],
[
["focusedhintstyle", "fhs"],
"CSS specification of focused hints appearance",
null,
function(value) { set_pref("focusedhintstyle", value); },
function() { return get_pref("focusedhintstyle"); },
"string",
"z-index:500;font:normal normal normal x-small monospace;color:ButtonText;background-color:ButtonShadow;border-color:ButtonShadow;border-width:1px;border-style:solid;padding:0px 1px 0px 1px;position:absolute;",
null,
null
],
[
["fullscreen", "fs"],
"Shows the current window fullscreen",
null,
function(value) { opt_fullscreen = value; BrowserFullScreen(); },
function() { return opt_fullscreen; },
"boolean",
false,
null,
null
],
[
["guioptions", "go"],
"Shows or hides the menu, toolbar and scrollbars",
"Supported characters:<br><ul><li><b>m</b>: menubar</li><li><b>T</b>: toolbar</ul>",
function(value) { set_pref("guioptions", value); set_guioptions(value); },
function() { return get_pref("guioptions"); },
"charlist",
"",
null,
null
],
[
["hintchars", "hc"],
"String of single characters which can be used to follow hints",
null,
function(value) { set_pref("hintchars", value); },
function() { return get_pref("hintchars"); },
"charlist",
"hjklasdfgyuiopqwertnmzxcvb",
null,
null
],
[
["hintstyle", "hs"],
"CSS specification of unfocused hints appearance",
null,
function(value) { set_pref("hintstyle", value); },
function() { return get_pref("hintstyle"); },
"string",
"z-index:500;font:normal normal normal x-small monospace;color:black;background-color:yellow;border-color:ButtonShadow;border-width:0px;border-style:solid;padding:0px 0px 0px 0px;position:absolute;",
null,
null
],
[
["hinttags"],
"XPath string of hintable elements activated by 'f'",
null,
function(value) { set_pref("hinttags", value); },
function() { return get_pref("hinttags"); },
"string",
"//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | //input[@type!='hidden'] | //a | //area | //iframe | //textarea | //button | //select",
null,
null
],
[
["maxhints", "mh"],
"Maximum of simultanously shown hints",
"If you want to speed up display of hints, choose a smaller value",
function(value) { set_pref("maxhints", value); },
function() { return get_pref("maxhints"); },
"number",
250,
function (value) { if (value>=1 && value <=1000) return true; else return false; },
null
],
[
["preload"],
"Speed up first time history/bookmark completion",
"History access can be quite slow for a large history. Vimperator maintains a cache to speed it up significantly on subsequent access.<br>"+
"In order to also speed up first time access, it is cached at startup, if this option is set (recommended).",
function(value) { set_pref("preload", value); },
function() { return get_pref("preload"); },
"boolean",
true,
null,
null
],
[
["showtabline", "stal"],
"Control when to show the tab bar of opened web pages",
"Available items:<br>"+
"<ul><li><b>0</b>: Never show tab bar</li><li>"+
" <b>1</b>: Show tab bar only if more than one tab is open</li><li>"+
" <b>2</b>: Always show tab bar</li></ul>"+
"Not implemented yet.",
function(value) { set_pref("showtabline", value); set_showtabline(value); },
function() { return get_pref("showtabline"); },
"number",
2,
function (value) { if (value>=0 && value <=2) return true; else return false; },
null
],
[
["usermode", "um"],
"Show current website with a minimal stylesheet to make it easily accessible",
"Note that this is a local setting for now, later it may be split into a global and <code style=command>:setlocal</code> part",
function(value) { opt_usermode = value; setStyleDisabled(value); },
function() { return opt_usermode; },
"boolean",
false,
null,
null
]
]/*}}}*/
// return null, if the cmd cannot be found in our g_settings array, or
// otherwise a refernce to our command
function get_setting(cmd)
{
for (var i=0; i < g_settings.length; i++)
{
for (var j=0; j < g_settings[i][0].length; j++)
{
if (g_settings[i][0][j] == cmd)
{
return g_settings[i];
}
}
}
return null;
}
/////////////////////////////////////////////////
// preference getter functions ///////////// {{{1
/////////////////////////////////////////////////
function get_pref(name, forced_default)
{
var pref = null;
var default_value = "";
// sometimes this var is not yet inititialized, make sure, it is
if (!g_vimperator_prefs)
g_vimperator_prefs = g_firefox_prefs.getBranch("extensions.vimperator.");
if (forced_default) // this argument sets defaults for non-user settable options (like comp_history)
default_value = forced_default;
else
{
for (var i=0; i<g_settings.length; i++)
{
if (g_settings[i][0][0] == name) // only first name is searched
{
default_value = g_settings[i][6];
break;
}
}
}
try
{
if (typeof(default_value) == "string")
pref = g_vimperator_prefs.getCharPref(name);
else if (typeof(default_value) == "number")
pref = g_vimperator_prefs.getIntPref(name);
else if (typeof(default_value) == "boolean")
pref = g_vimperator_prefs.getBoolPref(name);
else
pref = default_value;
} catch (e)
{
//alert("error: " + e);
pref = default_value;
}
return pref;
}
function get_firefox_pref(name, default_value)
{
var pref;
try
{
if (typeof(default_value) == "string")
pref = g_firefox_prefs.getCharPref(name);
else if (typeof(default_value) == "number")
pref = g_firefox_prefs.getIntPref(name);
else if (typeof(default_value) == "boolean")
pref = g_firefox_prefs.getBoolPref(name);
else
pref = default_value;
} catch (e)
{
pref = default_value;
}
return pref;
}
/////////////////////////////////////////////////
// preference setter functions ///////////// {{{1
/////////////////////////////////////////////////
function set_pref(name, value)
{
// sometimes this var is not yet inititialized, make sure, it is
if (!g_vimperator_prefs)
g_vimperator_prefs = g_firefox_prefs.getBranch("extensions.vimperator.");
if (typeof(value) == "string")
g_vimperator_prefs.setCharPref(name, value);
else if (typeof(value) == "number")
g_vimperator_prefs.setIntPref(name, value);
else if (typeof(value) == "boolean")
g_vimperator_prefs.setBoolPref(name, value);
else
echoerr("Unkown typeof pref: " + value);
}
function set_firefox_pref(name, value)
{
// NOTE: firefox prefs are always inititialized, no need to re-init
if (typeof(value) == "string")
g_firefox_prefs.setCharPref(name, value);
else if (typeof(value) == "number")
g_firefox_prefs.setIntPref(name, value);
else if (typeof(value) == "boolean")
g_firefox_prefs.setBoolPref(name, value);
else
echoerr("Unkown typeof pref: " + value);
}
/////////////////////////////////////////////////
// helper functions //////////////////////// {{{1
/////////////////////////////////////////////////
function set_guioptions(value)
{
// hide menubar
document.getElementById("toolbar-menubar").collapsed = value.indexOf("m") > -1 ? false : true;
document.getElementById("toolbar-menubar").hidden = value.indexOf("m") > -1 ? false : true;
// and main toolbar
document.getElementById("nav-bar").collapsed = value.indexOf("T") > -1 ? false : true;
document.getElementById("nav-bar").hidden = value.indexOf("T") > -1 ? false : true;
// and bookmarks toolbar
document.getElementById("PersonalToolbar").collapsed = value.indexOf("b") > -1 ? false : true;
document.getElementById("PersonalToolbar").hidden = value.indexOf("b") > -1 ? false : true;
// and original status bar (default), but show it, e.g. when needed for extensions
document.getElementById("status-bar").collapsed = value.indexOf("S") > -1 ? false : true;
document.getElementById("status-bar").hidden = value.indexOf("S") > -1 ? false : true;
}
function set_showtabline(value)
{
// hide tabbar
if(value == 0)
{
gBrowser.mStrip.collapsed = true;
gBrowser.mStrip.hidden = true;
}
else if(value == 1)
echo("show tabline only with > 1 page open not impl. yet");
else
{
gBrowser.mStrip.collapsed = false;
gBrowser.mStrip.hidden = false;
}
}
// vim: set fdm=marker :

View File

@@ -0,0 +1,110 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 2 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.6 //
addBookmark bookmarks.js /^function addBookmark(title, uri)$/;" f
add_to_command_history completion.js /^function add_to_command_history(str)$/;" f
beep commands.js /^function beep()$/;" f
bmadd commands.js /^function bmadd(str)$/;" f
bmdel commands.js /^function bmdel(str)$/;" f
bmshow commands.js /^function bmshow(filter, fullmode)$/;" f
changeHintFocus hints.js /^ function changeHintFocus(linkNumString, oldLinkNumString)$/;" f
completion_add_to_list completion.js /^function completion_add_to_list(completion_item, at_beginning)\/*{{{*\/$/;" f
completion_fill_list completion.js /^function completion_fill_list(startindex)\/*{{{*\/$/;" f
completion_select_next_item completion.js /^function completion_select_next_item()\/*{{{*\/$/;" f
completion_select_previous_item completion.js /^function completion_select_previous_item()\/*{{{*\/$/;" f
completion_show_list completion.js /^function completion_show_list()\/*{{{*\/$/;" f
copyToClipboard commands.js /^function copyToClipboard(str)$/;" f
createCursorPositionString vimperator.js /^function createCursorPositionString()$/;" f
createHints hints.js /^ function createHints(win)$/;" f
createProgressBar vimperator.js /^function createProgressBar(aProgress)$/;" f
deleteBookmark bookmarks.js /^function deleteBookmark(url)$/;" f
del_url_mark commands.js /^function del_url_mark(mark)$/;" f
echo commands.js /^function echo(msg)$/;" f
echoerr commands.js /^function echoerr(msg)$/;" f
execute_command commands.js /^function execute_command(count, cmd, special, args) \/\/ {{{$/;" f
filter_url_array completion.js /^function filter_url_array(urls, filter, use_regex)\/*{{{*\/$/;" f
focusContent vimperator.js /^function focusContent(clear_command_line, clear_statusline)$/;" f
focusNextFrame commands.js /^function focusNextFrame()$/;" f
formatHint hints.js /^ function formatHint(hintNum)$/;" f
genElemCoords hints.js /^ function genElemCoords(elem)$/;" f
genHintContainer hints.js /^ function genHintContainer(doc)$/;" f
getCurrentLinkLocation commands.js /^function getCurrentLinkLocation()$/;" f
getCurrentLocation commands.js /^function getCurrentLocation()$/;" f
getHintById hints.js /^ function getHintById(id, win)$/;" f
getLinkNodes vimperator.js /^function getLinkNodes(doc)$/;" f
getPageLinkNodes vimperator.js /^function getPageLinkNodes()$/;" f
getProperty bookmarks.js /^function getProperty( aInput, aArc, DS )$/;" f
get_bookmark_completions completion.js /^function get_bookmark_completions(filter)\/*{{{*\/$/;" f
get_command commands.js /^function get_command(cmd) \/\/ {{{$/;" f
get_command_completions completion.js /^function get_command_completions(filter)\/*{{{*\/$/;" f
get_firefox_pref settings.js /^function get_firefox_pref(name, default_value)$/;" f
get_history_completions completion.js /^function get_history_completions(filter)\/*{{{*\/$/;" f
get_pref settings.js /^function get_pref(name, forced_default)$/;" f
get_search_completions completion.js /^function get_search_completions(filter)\/*{{{*\/$/;" f
get_setting settings.js /^function get_setting(cmd)$/;" f
get_settings_completions completion.js /^function get_settings_completions(filter)\/*{{{*\/$/;" f
get_url_completions completion.js /^function get_url_completions(filter)\/*{{{*\/$/;" f
get_url_mark commands.js /^function get_url_mark(mark)$/;" f
goUp commands.js /^function goUp() \/\/ FIXME$/;" f
help commands.js /^function help(section)$/;" f
hit_a_hint hints.js /^function hit_a_hint()$/;" f
hsshow commands.js /^function hsshow(filter, fullmode)$/;" f
init vimperator.js /^function init()$/;" f
initDoc hints.js /^ function initDoc(event)$/;" f
invalidateCoords hints.js /^ function invalidateCoords(doc)$/;" f
isFormElemFocused vimperator.js /^function isFormElemFocused()$/;" f
keyToString vimperator.js /^function keyToString(event)$/;" f
load_history completion.js /^function load_history()$/;" f
logMessage vimperator.js /^function logMessage(msg)$/;" f
makeHelpString commands.js /^ function makeHelpString(commands, color, beg, end, func)$/;" f
makeSettingsHelpString commands.js /^ function makeSettingsHelpString(command)$/;" f
nsBrowserStatusHandler vimperator.js /^function nsBrowserStatusHandler() \/*{{{*\/$/;" f
onBlur vimperator.js /^function onBlur() \/\/ FIXME: needed?$/;" f
onCommandBarInput vimperator.js /^function onCommandBarInput(event)$/;" f
onCommandBarKeypress vimperator.js /^function onCommandBarKeypress(evt)\/*{{{*\/$/;" f
onEscape vimperator.js /^function onEscape()$/;" f
onResize hints.js /^ function onResize(event)$/;" f
onVimperatorKeypress vimperator.js /^function onVimperatorKeypress(event)\/*{{{*\/$/;" f
openURLs commands.js /^function openURLs(str)$/;" f
openURLsInNewTab commands.js /^function openURLsInNewTab(str, activate)$/;" f
openVimperatorBar vimperator.js /^function openVimperatorBar(str)$/;" f
outputAddonsList commands.js /^function outputAddonsList(aTarget)$/;" f
parseBookmarkString bookmarks.js /^function parseBookmarkString(str, res)$/;" f
preview_window_fill completion.js /^function preview_window_fill(completions)$/;" f
preview_window_select completion.js /^function preview_window_select(event)$/;" f
quit commands.js /^function quit(save_session)$/;" f
reload commands.js /^function reload(all_tabs)$/;" f
removeHints hints.js /^ function removeHints(win)$/;" f
save_history completion.js /^function save_history()$/;" f
scrollBufferAbsolute commands.js /^function scrollBufferAbsolute(horizontal, vertical)$/;" f
scrollBufferRelative commands.js /^function scrollBufferRelative(right, down)$/;" f
selectInput commands.js /^function selectInput()$/;" f
set commands.js /^function set(args, special)$/;" f
setHintStyle hints.js /^ function setHintStyle(hintElem, styleString)$/;" f
setMouseOverElement hints.js /^ function setMouseOverElement(elem)$/;" f
setStatusbarColor vimperator.js /^function setStatusbarColor(color)$/;" f
set_firefox_pref settings.js /^function set_firefox_pref(name, value)$/;" f
set_guioptions settings.js /^function set_guioptions(value)$/;" f
set_location_mark commands.js /^function set_location_mark(mark)$/;" f
set_pref settings.js /^function set_pref(name, value)$/;" f
set_showtabline settings.js /^function set_showtabline(value)$/;" f
set_url_mark commands.js /^function set_url_mark(mark, url)$/;" f
showHints hints.js /^ function showHints(win, off)$/;" f
showStatusbarMessage vimperator.js /^function showStatusbarMessage(msg, field)$/;" f
show_location_marks commands.js /^function show_location_marks(mark)$/;" f
show_url_marks commands.js /^function show_url_marks(mark)$/;" f
source commands.js /^function source(filename)$/;" f
startCoordLoader hints.js /^ function startCoordLoader(doc)$/;" f
stepInHistory commands.js /^function stepInHistory(steps)$/;" f
stringToURLs commands.js /^function stringToURLs(str)$/;" f
tab_go commands.js /^function tab_go(index)$/;" f
tab_remove commands.js /^function tab_remove(count, focus_left_tab, quit_on_last_tab)$/;" f
toggle_images commands.js /^function toggle_images() {$/;" f
unload vimperator.js /^function unload()$/;" f
updateStatusbar vimperator.js /^function updateStatusbar()$/;" f
yankCurrentLocation commands.js /^function yankCurrentLocation()$/;" f
zoom_in commands.js /^function zoom_in(factor)$/;" f
zoom_to commands.js /^function zoom_to(value)$/;" f

View File

@@ -0,0 +1,970 @@
/***** 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.
(c) 2006-2007: Martin Stubenschrott <stubenschrott@gmx.net>
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 *****/
var Modes = { // XXX: not yet used
MODE_NORMAL: 1,
MODE_INSERT: 2,
MODE_HAH_MAGIC: 3 // when we are holding space for hah input
};
var current_mode = Modes.MODE_NORMAL;
var popup_allowed_events; // need to change and reset this firefox pref
var g_inputbuffer = ""; // here we store partial commands (e.g. 'g' if you want to type 'gg')
var g_count = -1; // the parsed integer of g_inputbuffer, or -1 if no count was given
// handles to our gui elements
var preview_window = null;
var status_line = null;
var completion_list = null;
var command_line = null;
// our status bar fields
const STATUSFIELD_URL = 1;
const STATUSFIELD_INPUTBUFFER = 2;
const STATUSFIELD_PROGRESS = 3;
const STATUSFIELD_BUFFERS = 4;
const STATUSFIELD_CURSOR_POSITION = 5;
/* this function reacts to status bar and url changes which are sent from
the mozilla core */
function nsBrowserStatusHandler() /*{{{*/
{
this.init();
}
nsBrowserStatusHandler.prototype =
{
QueryInterface : function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
init : function()
{
},
setOverLink : function(link, b)
{
echo(link);
},
setJSStatus : function(status)
{
// echo("setJSStatus");
// this.updateStatusField(status);
},
setJSDefaultStatus : function(status)
{
// echo("setJSDefaultStatus");
// this.updateStatusField(status);
},
setDefaultStatus : function(status)
{
// echo("setDefaultStatus");
// this.updateStatusField(status);
},
onStateChange:function(aProgress,aRequest,aFlag,aStatus)
{
//alert("state change");
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel;
if (aFlag & nsIWebProgressListener.STATE_START && aRequest && aRequest.URI)
{
var toLoadUrl = aRequest.URI.spec;
}
else if (aFlag & nsIWebProgressListener.STATE_STOP)
{
updateStatusbar();
}
return 0;
},
onLocationChange:function (aWebProgress, aRequest, aLocation)
{
UpdateBackForwardButtons();
var url = aLocation.spec;
gURLBar.value = url; // also update the original firefox location bar
// onLocationChange is also called when switching/deleting tabs
if (hah.currentMode() != HINT_MODE_ALWAYS)
hah.disableHahMode();
// updating history cache is not done here but in
// the 'pageshow' event handler, because at this point I don't
// have access to the url title
},
onProgressChange:function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
{
showStatusbarMessage(createProgressBar(aCurTotalProgress/aMaxTotalProgress), STATUSFIELD_PROGRESS);
return 0;
},
onStatusChange:function (aWebProgress, aRequest, aStatus, aMessage)
{
showStatusbarMessage(aMessage, STATUSFIELD_URL);
return 0;
},
onSecurityChange:function (aWebProgress, aRequest, aState)
{
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
if(aState & nsIWebProgressListener.STATE_IS_INSECURE)
setStatusbarColor("transparent");
else if(aState & nsIWebProgressListener.STATE_IS_BROKEN)
setStatusbarColor("orange");
else if(aState & nsIWebProgressListener.STATE_IS_SECURE)
setStatusbarColor("yellow");
return 0;
}
//onLinkIconAvailable:function(a){}
};/*}}}*/
window.addEventListener("load", init, false);
////////////////////////////////////////////////////////////////////////
// init/uninit //////////////////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
function init()
{
preview_window = document.getElementById("vim-preview_window");
status_line = document.getElementById("vim-statusbar");
completion_list = document.getElementById("vim-completion");
command_line = document.getElementById("vim-commandbar");
if (!completion_list || !command_line)
alert("GUI not correctly created! Strange things will happen (until I find out, how to exit this script by code)");
// Setup our status handler - from browser.js
window.XULBrowserWindow = new nsBrowserStatusHandler();
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIXULWindow)
.XULBrowserWindow = window.XULBrowserWindow;
window.addEventListener("unload", unload, false);
window.addEventListener("keypress", onVimperatorKeypress, true);
// window.addEventListener("keyup", onVimperatorKeyup, true);
// window.addEventListener("keydown", onVimperatorKeydown, true);
// this handler is for middle click only in the content
//window.addEventListener("mousedown", onVimperatorKeypress, true);
//content.mPanelContainer.addEventListener("mousedown", onVimperatorKeypress, true);
//document.getElementById("content").onclick = function(event) { alert("foo"); };
// these 4 events require >=firefox-2.0 beta1
window.addEventListener("TabMove", updateStatusbar, false);
window.addEventListener("TabOpen", updateStatusbar, false);
window.addEventListener("TabClose", updateStatusbar, false);
//window.addEventListener("TabSelect", updateStatusbar, false);
window.addEventListener("TabSelect", function(event)
{
//alert("select");
if (hah.currentMode == HINT_MODE_ALWAYS)
{
hah.disableHahMode();
hah.enableHahMode(HINT_MODE_ALWAYS);
}
updateStatusbar();
}, false);
/*** load our preferences ***/
load_history();
set_showtabline(get_pref("showtabline"));
set_guioptions(get_pref("guioptions"));
// work around firefox popup blocker
popup_allowed_events = get_firefox_pref('dom.popup_allowed_events', 'change click dblclick mouseup reset submit');
if (!popup_allowed_events.match("keypress"))
set_firefox_pref('dom.popup_allowed_events', popup_allowed_events + " keypress");
// we have our own typeahead find implementation
set_firefox_pref('accessibility.typeaheadfind.autostart', false);
set_firefox_pref('accessibility.typeaheadfind', false); // actually the above setting should do it, but has no effect in firefox
// first time intro message
if (get_pref("firsttime", true))
{
setTimeout(function() {
var tab = openURLsInNewTab("about:blank", true);
BrowserStop();
help();
set_pref("firsttime", false);
},1000);
}
// update our history cache when a new page is shown
// XXX: there should be a cleaner way with onload() handler, but it just
// does not work out well for me :(
window.document.addEventListener("pageshow", function(event)
{
if (!event.persisted) // only if not bypassing cache
{
var url = getCurrentLocation();
var title = document.title;
for(var i=0; i<g_history.length; i++)
{
if(g_history[i][0] == url)
return;
}
g_history.unshift([url, title]);
}
}
, null);
// called when the window is scrolled.
window.onscroll = function (event)
{
showStatusbarMessage(createCursorPositionString(), STATUSFIELD_CURSOR_POSITION);
};
gURLBar.blur();
focusContent(true, true);
// everything important is done, register a preload handler to speed up first time history cache
if(get_pref("preload"))
setTimeout(function() { get_url_completions(""); } , 100);
logMessage("Initialized");
}
function unload()
{
/*** save our preferences ***/
save_history();
// reset firefox pref
if (get_firefox_pref('dom.popup_allowed_events',
'change click dblclick mouseup reset submit') == popup_allowed_events + " keypress")
set_firefox_pref('dom.popup_allowed_events', popup_allowed_events);
// XXX: not needed anymore?: window.getBrowser().removeProgressListener(urlChangeListener);
}
////////////////////////////////////////////////////////////////////////
// keyboard input handling //////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
function onVimperatorKeypress(event)/*{{{*/
{
// XXX: for now only, later: input mappings if form element focused
if (isFormElemFocused())
return false;
// // FIXME: handle middle click in content area {{{
// // alert(event.target.id);
// if (/*event.type == 'mousedown' && */event.button == 1 && event.target.id == 'content')
// {
// //echo("foo " + event.target.id);
// //if (document.commandDispatcher.focusedElement == command_line.inputField)
// {
// //alert(command_line.value.substring(0, command_line.selectionStart));
// command_line.value = command_line.value.substring(0, command_line.selectionStart) +
// readFromClipboard() +
// command_line.value.substring(command_line.selectionEnd, command_line.value.length);
// alert(command_line.value);
// }
// //else
// // {
// // openURLs(readFromClipboard());
// // }
// return true;
// } }}}
// change the event to a usable string representation
var key = keyToString(event);
if (key == null)
return false;
// if Hit-a-hint mode is on, special handling of keys is required
// g_hint_mappings is used
if (hah.hintsVisible())
{
// never propagate this key to firefox, when hints are visible
event.preventDefault();
event.preventBubble();
event.stopPropagation();
for (i = 0; i < g_hint_mappings.length; i++)
{
if(g_hint_mappings[i][0] == key)
{
if(g_hint_mappings[i][3] == true || hah.currentState() == 1)
{
//g_hint_mappings[i][1].call(this, event);
eval(g_hint_mappings[i][1]);
if (g_hint_mappings[i][2] == true) // stop processing this event
{
hah.disableHahMode();
g_inputbuffer = "";
updateStatusbar();
return false;
}
else
{
// make sure that YOU update the statusbar message yourself
// first in g_hint_mappings when in this mode!
updateStatusbar();
return false;
}
}
}
}
// no mapping found, beep()
if (hah.currentState() == 1)
{
beep();
hah.disableHahMode();
g_inputbuffer = "";
updateStatusbar();
return true;
}
// if we came here, let hit-a-hint process the key as it is part
// of a partial link
var res = hah.processEvent(event);
if (res < 0) // error occured processing this key
{
beep();
if(hah.currentMode() == HINT_MODE_QUICK)
hah.disableHahMode();
else // ALWAYS mode
hah.resetHintedElements();
g_inputbuffer = "";
}
else if (res == 0 || hah.currentMode() == HINT_MODE_EXTENDED) // key processed, part of a larger hint
g_inputbuffer += key;
else // this key completed a quick hint
{
// if the hint is all in UPPERCASE, open it in new tab
g_inputbuffer += key;
if (g_inputbuffer.toUpperCase() == g_inputbuffer)
hah.openHints(true, false);
else // open in current window
hah.openHints(false, false);
if(hah.currentMode() == HINT_MODE_QUICK)
hah.disableHahMode();
else // ALWAYS mode
hah.resetHintedElements();
g_inputbuffer = "";
}
updateStatusbar();
return true;
}
// set this variable to true, if we have the start of a mapping
var couldBecomeCompleteMapping = false;
var count_str = g_inputbuffer.match(/^[0-9]*/)[0];
// counts must be at the start of a complete mapping (10j -> go 10 lines down)
if (event.charCode >= 48 && event.charCode <= 57 && !(event.ctrlKey || event.altKey))
{
if (g_inputbuffer.search(/[^0-9]/) != -1)
{
g_inputbuffer = "";
beep();
updateStatusbar();
return true;
}
else
{
// handle '0' specially to allow binding of 0
if (g_inputbuffer != "" || key != "0")
{
g_inputbuffer += key;
updateStatusbar();
return true;
}
// else let the flow continue, and check if 0 is a mapping
}
}
for (var i in g_mappings)
{
// each internal mapping can have multiple keys
for (var j in g_mappings[i][0])
{
var mapping = g_mappings[i][0][j];
// alert("key: " + key +" - mapping: "+ mapping + " - g_input: " + g_inputbuffer);
if(count_str + mapping == g_inputbuffer + key)
{
g_count = parseInt(count_str, 10);
if (isNaN(g_count))
g_count = -1;
// allow null (= no operation) mappings
if(g_mappings[i][3] != null)
g_mappings[i][3].call(this, g_count);
// command executed, reset input buffer
g_inputbuffer = "";
updateStatusbar();
event.preventDefault();
event.preventBubble();
event.stopPropagation();
return false;
}
else if ((count_str+mapping).indexOf(g_inputbuffer + key) == 0)
{
couldBecomeCompleteMapping = true;
}
}
}
if (couldBecomeCompleteMapping)
{
g_inputbuffer += key;
event.preventDefault();
event.preventBubble();
event.stopPropagation();
}
else
{
g_inputbuffer = "";
beep();
}
updateStatusbar();
return false;
}/*}}}*/
function onCommandBarKeypress(evt)/*{{{*/
{
try
{
/* parse our command string into tokens */
var command = command_line.value;
var matches1 = command.match(/^:(\d+)/);
var matches2 = command.match(/^:(\d+)?([a-zA-Z!]+)/);
var matches3 = command.match(/^:(\d+)?([a-zA-Z!]+)\s*(.*?)\s*$/);
var count = 0;
var cmd = "";
var args= "";
var special = false;
if (matches1 != null && matches1.length == 2)
count = parseInt(matches1[1], 10);
if (matches2 != null && matches2.length >= 3)
cmd = matches2[2];
if (matches3 != null && matches3.length >= 4)
args = matches3[3];
/* if the user executes a command with ! at the end */
if (cmd.length - 1 == cmd.lastIndexOf("!"))
{
special = true;
cmd = cmd.replace(/!$/, "");
}
else
special = false;
/* user pressed ENTER to carry out a command */
if (evt.keyCode == KeyEvent.DOM_VK_RETURN)
{
// unfocus command line first
focusContent(false, true); // also sets comp_tab_index to -1
add_to_command_history(command);
execute_command(count, cmd, special, args);
}
else if (evt.keyCode == KeyEvent.DOM_VK_ESCAPE)
{
add_to_command_history(command);
focusContent(true, true);
}
/* user pressed UP or DOWN arrow to cycle completion */
else if (evt.keyCode == KeyEvent.DOM_VK_UP || evt.keyCode == KeyEvent.DOM_VK_DOWN)
{
/* save 'start' position for iterating through the history */
if (comp_history_index == -1)
{
comp_history_index = comp_history.length;
comp_history_start = command_line.value;
}
while (comp_history_index >= -1 && comp_history_index <= comp_history.length)
{
evt.keyCode == KeyEvent.DOM_VK_UP ? comp_history_index-- : comp_history_index++;
if (comp_history_index == comp_history.length) // user pressed DOWN when there is no newer history item
{
command_line.value = comp_history_start;
return;
}
/* if we are at either end of the list, reset the counter, break the loop and beep */
if((evt.keyCode == KeyEvent.DOM_VK_UP && comp_history_index <= -1) ||
(evt.keyCode == KeyEvent.DOM_VK_DOWN && comp_history_index >= comp_history.length))
{
evt.keyCode == KeyEvent.DOM_VK_UP ? comp_history_index++ : comp_history_index--;
break;
}
if (comp_history[comp_history_index].indexOf(comp_history_start) == 0)
{
command_line.value = comp_history[comp_history_index];
return;
}
}
beep();
}
/* user pressed TAB to get completions of a command */
else if (evt.keyCode == KeyEvent.DOM_VK_TAB)
{
//always reset our completion history so up/down keys will start with new values
comp_history_index = -1;
// we need to build our completion list first
if (comp_tab_index == COMPLETION_UNINITIALIZED)
{
g_completions = [];
comp_tab_index = -1;
comp_tab_list_offset = 0;
comp_tab_startstring = command;
/* if there is no space between the command name and the cursor
* then get completions of the command name
*/
if(command_line.value.substring(0, command_line.selectionStart).search(/[ \t]/) == -1)
{
get_command_completions(cmd);
}
else // dynamically get completions as specified in the g_commands array
{
var command = get_command(cmd);
if (command && command[4])
{
g_completions = command[4].call(this, args);
}
}
}
/* now we have the g_completions, so lets show them */
if (comp_tab_index >= -1)
{
// we could also return when no completion is found
// but we fall through to the cleanup anyway
if (g_completions.length == 0)
beep();
// show the list
completion_show_list();
if (evt.shiftKey)
completion_select_previous_item();
else
completion_select_next_item();
//command_line.focus(); // workaraound only need for RICHlistbox
if (comp_tab_index == -1) // wrapped around matches, reset command line
{
command_line.value = comp_tab_startstring;
completion_list.selectedIndex = -1;
}
else
{
var compl = g_completions[comp_tab_index][0];
if (compl)
{
/* if there is no space between the command name and the cursor
* the completions are for the command name
*/
if(command_line.value.substring(0, command_line.selectionStart).search(/[ \t]/) == -1)
{
command_line.value = ":" + (count ? count.toString() : "") + compl;
}
else // completions are for an argument
{
command_line.value = ":" + (count ? count.toString() : "") +
cmd + (special ? "!" : "") + " " + compl;
}
}
}
}
// prevent tab from moving to the next field
evt.preventDefault();
evt.preventBubble();
evt.stopPropagation();
}
else if (evt.keyCode == KeyEvent.DOM_VK_BACK_SPACE)
{
if (command_line.value == ":")
{
evt.preventDefault();
focusContent(true, true);
}
comp_tab_index = COMPLETION_UNINITIALIZED;
comp_history_index = -1;
}
else
{
// some key hit, check if the cursor is before the :
if (command_line.selectionStart == 0)
command_line.selectionStart = 1;
// and reset the tab completion
comp_tab_index = COMPLETION_UNINITIALIZED;
comp_history_index = -1;
}
} catch(e) { alert(e); }
}/*}}}*/
function onCommandBarInput(event)
{
if (command_line.value == "")
command_line.value = ":";
}
////////////////////////////////////////////////////////////////////////
// focus and mode handling //////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
/* After pressing Escape, put focus on a non-input field of the browser document */
function focusContent(clear_command_line, clear_statusline)
{
try
{
g_count = -1; // clear count
if(clear_command_line)
{
command_line.value = "";
command_line.inputField.setAttribute("style","font-family: monospace;");
}
if(clear_statusline)
{
completion_list.hidden = true;
comp_tab_index = COMPLETION_UNINITIALIZED;
comp_history_index = -1;
updateStatusbar();
}
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
if (window == ww.activeWindow && document.commandDispatcher.focusedElement)
{
document.commandDispatcher.focusedElement.blur();
}
content.focus();
} catch(e)
{
echoerr(e);
}
}
function openVimperatorBar(str)
{
// make sure the input field is not red anymore if we had an echoerr() first
command_line.inputField.setAttribute("style","font-family: monospace;");
if(str == null)
str = "";
if (g_count > 1)
command_line.value = ":" + g_count.toString() + str;
else
command_line.value = ":" + str;
try {
command_line.focus();
} catch(e) {
echo(e);
}
}
function onEscape()
{
BrowserStop();
focusContent(true, true);
hah.disableHahMode();
}
function onBlur() // FIXME: needed?
{
//alert('blur');
//focusContent(false, false);
}
////////////////////////////////////////////////////////////////////////
// statusbar/progressbar ////////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
/* the statusbar is currently divided into 5 fields, you can set
* each one independently */
function showStatusbarMessage(msg, field)
{
var bar = document.getElementById("vim-sb-field-" + field);
if (bar)
bar.value = msg;
}
function setStatusbarColor(color)
{
var bar = document.getElementById("vim-statusbar");
bar.setAttribute("style", "background-color: " + color);
}
function updateStatusbar()
{
var buffers = "[" + (gBrowser.tabContainer.selectedIndex + 1).toString() + "/" +
gBrowser.tabContainer.childNodes.length.toString() + "]";
showStatusbarMessage(getCurrentLocation(), STATUSFIELD_URL);
showStatusbarMessage(" " + g_inputbuffer + " ", STATUSFIELD_INPUTBUFFER);
showStatusbarMessage("", STATUSFIELD_PROGRESS);
showStatusbarMessage(buffers, STATUSFIELD_BUFFERS);
// required to postpone it a little, otherwise we could get the wrong cursor
// position when switching tabs
setTimeout(function() {
showStatusbarMessage(createCursorPositionString(), STATUSFIELD_CURSOR_POSITION);
} , 10);
}
/* aProgress is a float between 0 and 1 */
function createProgressBar(aProgress)
{
/* the progress field */
var progress;
if (aProgress <= 0)
progress = "[ Loading... ]";
else if (aProgress >= 1)
progress = "[====================]";
else
{
progress = /*(aProgress*100).round().toString() + "% */"[";
done = Math.floor(aProgress * 20);
for (i=0; i < done; i++)
progress = progress + "=";
progress = progress + ">";
for (i=19; i > done; i--)
progress = progress + " ";
progress = progress + "]";
}
return progress;
}
function createCursorPositionString()
{
var win = document.commandDispatcher.focusedWindow;
//var x = win.scrollMaxX == 0 ? 100 : Math.round(win.scrollX / win.scrollMaxX * 100);
var y = win.scrollMaxY == 0 ? -1 : Math.round(win.scrollY / win.scrollMaxY * 100);
var percent;
if (y < 0) percent = "All";
else if (y == 0) percent = "Top";
else if (y < 10) percent = " " + y.toString() + "%";
else if (y >= 100) percent = "Bot";
else percent = y.toString() + "%";
return(" " + percent);
}
////////////////////////////////////////////////////////////////////////
// text input functions /////////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
function isFormElemFocused()
{
var elt = document.commandDispatcher.focusedElement;
if (elt == null) return false;
var tagName = elt.localName.toUpperCase();
if (tagName == "INPUT" ||
tagName == "TEXTAREA" ||
tagName == "SELECT" ||
tagName == "BUTTON" ||
tagName == "ISINDEX")
return true;
return false;
}
////////////////////////////////////////////////////////////////////////
// logging //////////////////////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
var gConsoleService = Components.classes['@mozilla.org/consoleservice;1']
.getService(Components.interfaces.nsIConsoleService);
function logMessage(msg)
{
gConsoleService.logStringMessage('vimperator: ' + msg);
}
////////////////////////////////////////////////////////////////////////
// misc helper funcstions ///////////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
// this function gets an event as the input and converts it to
// a keycode which can be used in mappings
// e.g. pressing ctrl+n would result in the string "<c-n>"
function keyToString(event)
{
var key = String.fromCharCode(event.charCode);
var modifier = "";
if (event.charCode > 0)
{
if (event.ctrlKey)
modifier += "C-";
if (event.altKey)
modifier += "A-";
if (event.metaKey)
modifier += "M-";
if (modifier.length > 0)
return "<" + modifier + key + ">";
else
return key;
}
else if (event.keyCode == KeyEvent.DOM_VK_ESCAPE)
return "<Esc>";
else if (event.keyCode == KeyEvent.DOM_VK_RETURN)
return "<Return>";
else if (event.keyCode == KeyEvent.DOM_VK_TAB)
return "<Tab>";
else if (event.keyCode == KeyEvent.DOM_VK_DELETE)
return "<Del>";
else if (event.keyCode == KeyEvent.DOM_VK_BACK_SPACE)
return "<BS>";
else if (event.keyCode == KeyEvent.DOM_VK_HOME)
return "<Home>";
else if (event.keyCode == KeyEvent.DOM_VK_END)
return "<End>";
else if (event.keyCode == KeyEvent.DOM_VK_LEFT)
return "<Left>";
else if (event.keyCode == KeyEvent.DOM_VK_RIGHT)
return "<Right>";
else if (event.keyCode == KeyEvent.DOM_VK_UP)
return "<Up>";
else if (event.keyCode == KeyEvent.DOM_VK_DOWN)
return "<Down>";
else if (event.keyCode == KeyEvent.DOM_VK_PAGE_UP)
return "<PageUp>";
else if (event.keyCode == KeyEvent.DOM_VK_PAGE_DOWN)
return "<PageDown>";
else if (event.keyCode == KeyEvent.DOM_VK_F1)
return "<F1>";
else if (event.keyCode == KeyEvent.DOM_VK_F2)
return "<F2>";
else if (event.keyCode == KeyEvent.DOM_VK_F3)
return "<F3>";
else if (event.keyCode == KeyEvent.DOM_VK_F4)
return "<F4>";
else if (event.keyCode == KeyEvent.DOM_VK_F5)
return "<F5>";
else if (event.keyCode == KeyEvent.DOM_VK_F6)
return "<F6>";
else if (event.keyCode == KeyEvent.DOM_VK_F7)
return "<F7>";
else if (event.keyCode == KeyEvent.DOM_VK_F8)
return "<F8>";
else if (event.keyCode == KeyEvent.DOM_VK_F9)
return "<F9>";
else if (event.keyCode == KeyEvent.DOM_VK_F10)
return "<F10>";
else if (event.keyCode == KeyEvent.DOM_VK_F11)
return "<F11>";
else if (event.keyCode == KeyEvent.DOM_VK_F12)
return "<F12>";
// if nothing matches
return null;
}
////////////////////////////////////////////////////////////////////////
// DOM related helper functsion /////////////////////////////////// {{{1
////////////////////////////////////////////////////////////////////////
// Handle frames if they're present
function getPageLinkNodes()
{
var frames = window._content.frames;
// The main content may have link nodes as well as it's frames.
var nodes = getLinkNodes(_content.content.document);
var tmp;
for (var i=0; i<frames.length; i++) {
tmp = getLinkNodes(frames[i].document);
// is javascript this crappy?
for (var j=0; j<tmp.length; j++)
nodes.push(tmp[j]);
}
return nodes;
}
// For a single document, grab all the nodes
function getLinkNodes(doc)
{
var a_nodes = doc.getElementsByTagName('a');
var i_nodes = doc.getElementsByTagName('input');
var s_nodes = doc.getElementsByTagName('select');
var t_nodes = doc.getElementsByTagName('textarea');
var links = [];
for (var i=0; i<t_nodes.length; i++) {
links.push(t_nodes[i]);
}
for (var i=0; i<s_nodes.length; i++) {
links.push(s_nodes[i]);
}
for (var i=0; i<i_nodes.length; i++) {
if (i_nodes[i].type == "hidden") continue;
links.push(i_nodes[i]);
}
for (var i=0; i<a_nodes.length; i++) {
if (!a_nodes[i].hasAttribute('href')) continue;
links.push(a_nodes[i]);
}
return links;
}
// vim: set fdm=marker :

View File

@@ -0,0 +1,96 @@
<?xml version="1.0"?>
<!-- ***** 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
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 ***** -->
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<overlay id="vimperator"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:nc="http://home.netscape.com/NC-rdf#"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<!-- you may not believe it, but order is really important here -->
<script type="application/x-javascript" src="vimperator.js"/>
<script type="application/x-javascript" src="commands.js"/>
<script type="application/x-javascript" src="settings.js"/>
<script type="application/x-javascript" src="completion.js"/>
<script type="application/x-javascript" src="bookmarks.js"/>
<script type="application/x-javascript" src="hints.js"/>
<window id="main-window">
<toolbar id="vimperator-toolbar" hidden="false" align="center" fullscreentoolbar="true"
onblur="onBlur();">
<vbox id="vim-container" flex="1" hidden="false">
<listbox id="vim-preview_window" class="plain" rows="10" flex="1" hidden="true"
ondblclick="preview_window_select(event);" onclick="preview_window_select(event);" onkeydown="preview_window_select(event);"
style="font-family: monospace; -moz-user-focus:ignore; overflow:-moz-scrollbars-none;">
<listcols>
<listcol flex="1" width="50%"/>
<listcol flex="1" width="50%"/>
</listcols>
</listbox>
<hbox id="vim-statusbar" flex="1" height="10" hidden="false" style="-moz-user-focus:ignore;">
<textbox class="plain" id="vim-sb-field-1" flex="1" crop="right" value="about:blank"
readonly="true" style="font-family: monospace; background-color: transparent; -moz-user-focus:ignore;"/>
<label class="plain" id="vim-sb-field-2" flex="0" crop="right" value="[===> ]"
style="font-family: monospace"/>
<label class="plain" id="vim-sb-field-3" flex="0" crop="right" value=""
style="font-family: monospace"/>
<label class="plain" id="vim-sb-field-4" flex="0" crop="right" value="[0/0]"
style="font-family: monospace"/>
<label class="plain" id="vim-sb-field-5" flex="0" crop="right" value=" Top"
style="font-family: monospace"/>
</hbox>
<listbox id="vim-completion" class="plain" rows="1" flex="1" hidden="true"
style="font-family: monospace; -moz-user-focus:ignore; -moz-user-select:ignore; overflow:-moz-scrollbars-none;">
<listcols>
<listcol flex="1" width="50%"/>
<listcol flex="1" width="50%"/>
</listcols>
</listbox>
<textbox class="plain" id="vim-commandbar" flex="1" hidden="false" type="timed" timeout="100"
onkeypress="onCommandBarKeypress(event);" oninput="onCommandBarInput(event);"
style="font-family: monospace"/>
</vbox>
</toolbar>
<keyset id="mainKeyset">
<key id="key_open_vimbar" key=":" oncommand="openVimperatorBar();" modifiers=""/>
<key id="key_stop" keycode="VK_ESCAPE" oncommand="onEscape();"/>
<!-- other keys are handled inside vimperator.js event loop -->
</keyset>
</window>
</overlay>