diff --git a/chrome/content/vimperator/commands.js b/chrome/content/vimperator/commands.js
index 96554440..63534461 100644
--- a/chrome/content/vimperator/commands.js
+++ b/chrome/content/vimperator/commands.js
@@ -1305,102 +1305,6 @@ function isDirectory(url)
return false;
}
-/////////////////////////////////////////////////////////////////////}}}
-// frame related functions /////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////{{{
-
-// TODO: allow callback for filtering out unwanted frames? User defined?
-Vimperator.prototype.shiftFrameFocus = function(count, forward)
-{
- try
- {
- var frames = [];
-
- // find all frames - depth-first search
- (function(frame)
- {
- if (frame.document.body.localName.toLowerCase() == "body")
- frames.push(frame);
- for (var i = 0; i < frame.frames.length; i++)
- arguments.callee(frame.frames[i])
- })(window.content);
-
- if (frames.length == 0) // currently top is always included
- return;
-
- // remove all unfocusable frames
- // TODO: find a better way to do this
- var start = document.commandDispatcher.focusedWindow;
- frames = frames.filter(function(frame) {
- frame.focus();
- if (document.commandDispatcher.focusedWindow == frame)
- return frame;
- });
- start.focus();
-
- // find the currently focused frame index
- // TODO: If the window is a frameset then the first _frame_ should be
- // focused. Since this is not the current FF behaviour,
- // we initalise current to -1 so the first call takes us to the
- // first frame.
- var current = -1;
- for (var i = 0; i < frames.length; i++)
- {
- if (frames[i] == document.commandDispatcher.focusedWindow)
- {
- var current = i;
- break;
- }
- }
-
- // calculate the next frame to focus
- var next = current;
- if (forward)
- {
- if (count > 1)
- next = current + count;
- else
- next++;
-
- if (next > frames.length - 1)
- next = frames.length - 1;
- }
- else
- {
- if (count > 1)
- next = current - count;
- else
- next--;
-
- if (next < 0)
- next = 0;
- }
-
- // focus next frame and scroll into view
- frames[next].focus();
- if (frames[next] != window.content)
- frames[next].frameElement.scrollIntoView(false);
-
- // add the frame indicator
- var doc = frames[next].document;
- var indicator = doc.createElement("div");
- indicator.id = "vimperator-frame-indicator";
- // NOTE: need to set a high z-index - it's a crapshoot!
- var style = "background-color: red; opacity: 0.5; z-index: 999;" +
- "position: fixed; top: 0; bottom: 0; left: 0; right: 0;";
- indicator.setAttribute("style", style);
- doc.body.appendChild(indicator);
-
- // remove the frame indicator
- setTimeout(function() { doc.body.removeChild(indicator); }, 500);
- }
- catch (e)
- {
- //vimperator.echoerr(e);
- // FIXME: fail silently here for now
- }
-}
-
/////////////////////////////////////////////////////////////////////}}}
// location handling ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////{{{
@@ -1416,7 +1320,6 @@ function getCurrentTitle()
return window.content.document.title;
}
-
/////////////////////////////////////////////////////////////////////}}}
// scrolling ///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////{{{
@@ -1506,7 +1409,7 @@ function zoom_in(factor)
}
}
-//Vimperator.prototype.zoom_to = function(value)
+//vimperator.zoom_to = function(value)
function zoom_to(value)
{
var zoomMgr = ZoomManager.prototype.getInstance();
@@ -1539,11 +1442,39 @@ function zoom_to(value)
vimperator.echo("Zoom value: " + value + "%");
}
-//}}}
-////////////////////////////////////////////////////////////////////////
-// misc helper functions ////////////////////////////////////////////{{{
-////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////}}}
+// DOM related helper functions ////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////{{{
+function isFormElemFocused()
+{
+ var elt = window.document.commandDispatcher.focusedElement;
+ if (elt == null)
+ return false;
+
+ try
+ { // sometimes the elt doesn't have .localName
+ var tagname = elt.localName.toLowerCase();
+ var type = elt.type.toLowerCase();
+
+ if ( (tagname == "input" && (type != "image")) ||
+ tagname == "textarea" ||
+ // tagName == "SELECT" ||
+ // tagName == "BUTTON" ||
+ tagname == "isindex") // isindex is a deprecated one-line input box
+ return true;
+ }
+ catch (e)
+ {
+ // FIXME: do nothing?
+ }
+
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////}}}
+// misc helper functions ///////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////{{{
function copyToClipboard(str)
{
@@ -1572,119 +1503,6 @@ function evaluateXPath(expression, doc, ordered)
);
return res;
}
-
-Vimperator.prototype.beep = function()
-{
- if (!vimperator.options["beep"])
- return;
-
- var gBeepService = Components.classes['@mozilla.org/sound;1']
- .getService(Components.interfaces.nsISound);
-
- if (gBeepService)
- gBeepService.beep();
- else
- vimperator.echoerr('no beep service found');
-}
-
-// quit vimperator, no matter how many tabs/windows are open
-Vimperator.prototype.quit = function(save_session)
-{
- if (save_session)
- Options.setFirefoxPref("browser.startup.page", 3); // start with saved session
- else
- Options.setFirefoxPref("browser.startup.page", 1); // start with default homepage session
-
- goQuitApplication();
-}
-
-Vimperator.prototype.restart = function()
-{
- // if (!arguments[1]) return;
- const nsIAppStartup = Components.interfaces.nsIAppStartup;
-
- // Notify all windows that an application quit has been requested.
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
- .createInstance(Components.interfaces.nsISupportsPRBool);
- os.notifyObservers(cancelQuit, "quit-application-requested", null);
-
- // Something aborted the quit process.
- if (cancelQuit.data)
- return;
-
- // Notify all windows that an application quit has been granted.
- os.notifyObservers(null, "quit-application-granted", null);
-
- // Enumerate all windows and call shutdown handlers
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- var windows = wm.getEnumerator(null);
- while (windows.hasMoreElements())
- {
- var win = windows.getNext();
- if (("tryToClose" in win) && !win.tryToClose())
- return;
- }
- Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup)
- .quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
-}
-
-Vimperator.prototype.source = function(filename, silent)
-{
- if (!filename)
- return;
-
- function getEnv(variable)
- {
- var environment = Components.classes["@mozilla.org/process/environment;1"]
- .getService(Components.interfaces.nsIEnvironment);
- return environment.get(variable);
- }
-
- // convert "~" to HOME on Windows
- if (navigator.platform == "Win32")
- {
- // TODO: proper pathname separator translation like Vim
- filename = filename.replace('/', '\\', 'g');
- var matches = filename.match(/^~(.*)/)
- if (matches)
- {
- var home_dir = getEnv("HOME");
- if (!home_dir)
- home_dir = getEnv("USERPROFILE");
- if (!home_dir)
- {
- // TODO: are these guaranteed to be set?
- home_dir = getEnv("HOMEDRIVE") + getEnv("HOMEPATH");
- }
- filename = home_dir + "\\" + matches[1];
- }
- }
-
- try
- {
- var fd = fopen(filename, "<");
- if (!fd)
- return;
-
- var s = fd.read();
- fd.close();
-
- var prev_match = new Array(5);
- var heredoc = '';
- var end = false;
- s.split('\n').forEach(function(line) {
- [prev_match, heredoc, end] = multiliner(line, prev_match, heredoc);
- });
- }
- catch (e)
- {
- if (!silent)
- vimperator.echoerr(e);
- }
-}
//}}}
// vim: set fdm=marker sw=4 ts=4 et:
diff --git a/chrome/content/vimperator/find.js b/chrome/content/vimperator/find.js
index 66a8db72..19916551 100644
--- a/chrome/content/vimperator/find.js
+++ b/chrome/content/vimperator/find.js
@@ -240,7 +240,7 @@ function abs_point (node) {
// Vimperator searcher
// make sure you only create this object when the "vimperator" object is ready
-//Vimperator.prototype.search = new function()
+//vimperator.search = new function()
function Search() //{{{
{
var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback
diff --git a/chrome/content/vimperator/help.js b/chrome/content/vimperator/help.js
index 9fd80474..df3cb78e 100644
--- a/chrome/content/vimperator/help.js
+++ b/chrome/content/vimperator/help.js
@@ -26,7 +26,7 @@ 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 *****/
-Vimperator.prototype.help = function(section, easter) //{{{
+vimperator.help = function(section, easter) //{{{
{
if (easter)
{
diff --git a/chrome/content/vimperator/mappings.js b/chrome/content/vimperator/mappings.js
index 139d688f..4bb9da5e 100644
--- a/chrome/content/vimperator/mappings.js
+++ b/chrome/content/vimperator/mappings.js
@@ -848,7 +848,7 @@ function Mappings() //{{{
{
short_help: "Escape next key",
help: "If you need to pass a certain key to a javascript form field or another extension prefix the key with <C-v>.
" +
- "Also works to unshadow Firefox shortcuts like <C-o> which are otherwise hidden in Vimperator.
" +
+ "Also works to unshadow Firefox shortcuts like <C-o> which are otherwise hidden in vimperator.
" +
"When in 'ignorekeys' mode (activated by <I>), <C-v> will pass the next key to Vimperator instead of the web page."
}
));
diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js
index d1711a5c..f21ee0a6 100644
--- a/chrome/content/vimperator/vimperator.js
+++ b/chrome/content/vimperator/vimperator.js
@@ -26,128 +26,13 @@ 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 *****/
-// The only global object, a handler to the main Vimperator object
-var vimperator = null;
-
-var popup_allowed_events; // need to change and reset this firefox pref XXX: move to options class
-
-// called when the chrome is fully loaded and before the main window is shown
-window.addEventListener("load", init, false);
-
-////////////////////////////////////////////////////////////////////////
-// init/uninit /////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////{{{
-
-function init() //{{{
-{
- window.dump("Vimperator init\n");
- // init the main object
- vimperator = new Vimperator();
- vimperator.log("Initializing vimperator object...", 1);
-
- // these inner classes are created here, because outside the init()
- // function, the chrome:// is not ready
- vimperator.log("Loading module options...", 3);
- Vimperator.prototype.options = new Options();
- vimperator.log("Loading module events...", 3);
- Vimperator.prototype.events = new Events();
- vimperator.log("Loading module commands...", 3);
- Vimperator.prototype.commands = new Commands();
- vimperator.log("Loading module bookmarks...", 3);
- Vimperator.prototype.bookmarks = new Bookmarks();
- vimperator.log("Loading module history...", 3);
- Vimperator.prototype.history = new History();
- vimperator.log("Loading module commandline...", 3);
- Vimperator.prototype.commandline = new CommandLine();
- vimperator.log("Loading module search...", 3);
- Vimperator.prototype.search = new Search();
- vimperator.log("Loading module preview window...", 3);
- Vimperator.prototype.previewwindow = new InformationList("vimperator-previewwindow", { incremental_fill: false, max_items: 10 });
- vimperator.log("Loading module buffer window...", 3);
- Vimperator.prototype.bufferwindow = new InformationList("vimperator-bufferwindow", { incremental_fill: false, max_items: 10 });
- vimperator.log("Loading module mappings...", 3);
- Vimperator.prototype.mappings = new Mappings();
- vimperator.log("Loading module statusline...", 3);
- Vimperator.prototype.statusline = new StatusLine();
- vimperator.log("Loading module tabs...", 3);
- Vimperator.prototype.tabs = new Tabs();
- vimperator.log("Loading module marks...", 3);
- Vimperator.prototype.marks = new Marks();
- vimperator.log("Loading module quickmarks...", 3);
- Vimperator.prototype.quickmarks = new QuickMarks();
- vimperator.log("Loading module hints...", 3);
- Vimperator.prototype.hints = new Hints();
- vimperator.log("All modules loaded", 3);
-
- // DJK FIXME
- Vimperator.prototype.echo = vimperator.commandline.echo;
- Vimperator.prototype.echoerr = vimperator.commandline.echoErr;
-
- // XXX: move elsewhere
- vimperator.registerCallback("submit", vimperator.modes.EX, function(command) { /*vimperator.*/execute(command); } );
- vimperator.registerCallback("complete", vimperator.modes.EX, function(str) { return exTabCompletion(str); } );
-
- // this function adds all our required listeners to react on events
- // also stuff like window.onScroll is handled there.
- //addEventListeners();
- //vimperator.events();
-
- // work around firefox popup blocker
- popup_allowed_events = Options.getFirefoxPref('dom.popup_allowed_events', 'change click dblclick mouseup reset submit');
- if (!popup_allowed_events.match("keypress"))
- Options.setFirefoxPref('dom.popup_allowed_events', popup_allowed_events + " keypress");
-
- // we have our own typeahead find implementation
- Options.setFirefoxPref('accessibility.typeaheadfind.autostart', false);
- Options.setFirefoxPref('accessibility.typeaheadfind', false); // actually the above setting should do it, but has no effect in firefox
-
- // first time intro message
- if (Options.getPref("firsttime", true))
- {
- setTimeout(function() {
- vimperator.help(null, null, null, { inTab: true });
- Options.setPref("firsttime", false);
- }, 1000);
- }
-
- gURLBar.blur();
- vimperator.focusContent();
-
- // firefox preferences which we need to be changed to work well with vimperator
- Options.setFirefoxPref("browser.startup.page", 3); // start with saved session
-
- // Finally, read a ~/.vimperatorrc
- // Make sourcing asynchronous, otherwise commands that open new tabs won't work
- setTimeout(function() {
- vimperator.source("~/.vimperatorrc", true);
- vimperator.log("~/.vimperatorrc sourced", 1);
- }, 50);
-
- window.addEventListener("unload", unload, false);
- vimperator.log("Vimperator fully initialized", 1);
-} //}}}
-
-function unload() //{{{
-{
- /*** save our preferences ***/
- vimperator.commandline.destroy();
- vimperator.events.destroy();
- vimperator.quickmarks.destroy();
-
- // reset some modified firefox prefs
- if (Options.getFirefoxPref('dom.popup_allowed_events', 'change click dblclick mouseup reset submit')
- == popup_allowed_events + " keypress")
- Options.setFirefoxPref('dom.popup_allowed_events', popup_allowed_events);
-} //}}}
-//}}}
-
-function Vimperator() //{{{
+const vimperator = (function() //{{{
{
////////////////////////////////////////////////////////////////////////////////
////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
- this.modes = { // actually not private, but Firefox complains if this doesn't come first
+ var modes = {
// main modes
NONE: 0,
NORMAL: 1 << 0,
@@ -166,25 +51,33 @@ function Vimperator() //{{{
EXTENDED_HINT: 1 << 17,
ALWAYS_HINT: 1 << 18
}
- var mode_messages = {};
- mode_messages[this.modes.NORMAL] = "";
- mode_messages[this.modes.INSERT] = "INSERT";
- mode_messages[this.modes.VISUAL] = "VISUAL";
- mode_messages[this.modes.HINTS] = "HINTS";
- mode_messages[this.modes.ESCAPE_ONE_KEY] = "escape one key";
- mode_messages[this.modes.ESCAPE_ALL_KEYS] = "escape all keys";
- mode_messages[this.modes.ESCAPE_ONE_KEY | this.modes.ESCAPE_ALL_KEYS] = "pass one key";
- mode_messages[this.modes.QUICK_HINT] = "quick";
- mode_messages[this.modes.EXTENDED_HINT] = "extended";
- mode_messages[this.modes.ALWAYS_HINT] = "always";
- var callbacks = new Array();
- var mode = this.modes.NORMAL;
- var extended_mode = this.modes.NONE;
+ var mode_messages = {};
+ mode_messages[modes.NORMAL] = "";
+ mode_messages[modes.INSERT] = "INSERT";
+ mode_messages[modes.VISUAL] = "VISUAL";
+ mode_messages[modes.HINTS] = "HINTS";
+ mode_messages[modes.ESCAPE_ONE_KEY] = "escape one key";
+ mode_messages[modes.ESCAPE_ALL_KEYS] = "escape all keys";
+ mode_messages[modes.ESCAPE_ONE_KEY | modes.ESCAPE_ALL_KEYS] = "pass one key";
+ mode_messages[modes.QUICK_HINT] = "quick";
+ mode_messages[modes.EXTENDED_HINT] = "extended";
+ mode_messages[modes.ALWAYS_HINT] = "always";
+
+ var mode = modes.NORMAL;
+ var extended_mode = modes.NONE;
+
+ var callbacks = [];
+
+ var popup_allowed_events; // need to change and reset this firefox pref XXX: move to options class
// our services
+ var sound_service = Components.classes['@mozilla.org/sound;1']
+ .getService(Components.interfaces.nsISound);
var console_service = Components.classes['@mozilla.org/consoleservice;1']
.getService(Components.interfaces.nsIConsoleService);
+ var environment_service = Components.classes["@mozilla.org/process/environment;1"]
+ .getService(Components.interfaces.nsIEnvironment);
function showMode()
{
@@ -214,169 +107,428 @@ function Vimperator() //{{{
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
- this.version = "###VERSION### CVS (created: ###DATE###)";
+ return {
- this.input = {
- buffer: "", // partial command storage
- pendingMap: null, // pending map storage
- count: -1 // parsed count from the input buffer
- };
+ modes: modes,
- /////////////// callbacks ////////////////////////////
- // XXX: shouldn't that callback be moved to commandline? --mst
- /**
- * @param type Can be:
- * "submit": when the user pressed enter in the command line
- * "change"
- * "cancel"
- * "complete"
- */
- this.registerCallback = function(type, mode, func)
- {
- // TODO: check if callback is already registered
- callbacks.push([type, mode, func]);
- }
+ version: "###VERSION### CVS (created: ###DATE###)",
- this.triggerCallback = function(type, data)
- {
- for (var i in callbacks)
- {
- var [thistype, thismode, thisfunc] = callbacks[i];
- if (vimperator.hasMode(thismode) && type == thistype)
- return thisfunc.call(this, data);
- }
- return false;
- }
+ input: {
+ buffer: "", // partial command storage
+ pendingMap: null, // pending map storage
+ count: -1 // parsed count from the input buffer
+ },
- // just forward these echo commands
- // DJK FIXME: this.echo = this.commandline.echo;
- // DJK FIXME: this.echoerr = this.commandline.echoErr;
-
-
- this.getMode = function()
- {
- return [mode, extended_mode];
- }
-
- // set current mode
- // use "null" if you only want to set one of those modes
- this.setMode = function(main, extended, silent)
- {
- // if a main mode is set, the extended is always cleared
- if (main)
+ /**
+ * @param type Can be:
+ * "submit": when the user pressed enter in the command line
+ * "change"
+ * "cancel"
+ * "complete"
+ */
+ registerCallback: function(type, mode, func)
{
- mode = main;
- extended_mode = this.modes.NONE;
- }
- if (typeof extended === "number")
- extended_mode = extended;
+ // TODO: check if callback is already registered
+ callbacks.push([type, mode, func]);
+ },
- if (!silent)
- showMode();
- }
-
- // returns true if "whichmode" is found in either the main or
- // extended mode
- this.hasMode = function(whichmode)
- {
- return ((mode & whichmode) || (extended_mode & whichmode) > 0) ? true : false;
- }
-
- this.addMode = function(main, extended)
- {
- if (main)
- mode |= main;
- if (extended)
- extended_mode |= extended;
-
- showMode();
- }
-
- // always show the new mode in the statusline
- this.removeMode = function(main, extended)
- {
- if (main)
- mode = (mode | main) ^ main;
- if (extended)
- extended_mode = (extended_mode | extended) ^ extended;
-
- showMode();
- }
-
- // After pressing Escape, put focus on a non-input field of the browser document
- this.focusContent = function()
- {
- 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();
- }
-
- /**
- * logs any object to the javascript error console
- * also prints all properties of thie object
- */
- this.log = function(msg, level)
- {
- // if (Options.getPref("verbose") >= level) // FIXME: hangs vimperator, probably timing issue --mst
- console_service.logStringMessage('vimperator: ' + msg);
- }
-
- /**
- * logs any object to the javascript error console
- * also prints all properties of the object
- */
- this.logObject = function(object, level)
- {
- if (typeof object != 'object')
+ triggerCallback: function(type, data)
+ {
+ for (var i in callbacks)
+ {
+ var [thistype, thismode, thisfunc] = callbacks[i];
+ if (vimperator.hasMode(thismode) && type == thistype)
+ return thisfunc.call(this, data);
+ }
return false;
+ },
- var string = object + '::\n';
- for (var i in object)
+ getMode: function()
{
- var value;
- try {
- var value = object[i];
- } catch (e) { value = '' }
+ return [mode, extended_mode];
+ },
- string += i + ': ' + value + '\n';
+ // set current mode
+ // use "null" if you only want to set one of those modes
+ setMode: function(main, extended, silent)
+ {
+ // if a main mode is set, the extended is always cleared
+ if (main)
+ {
+ mode = main;
+ extended_mode = this.modes.NONE;
+ }
+ if (typeof extended === "number")
+ extended_mode = extended;
+
+ if (!silent)
+ showMode();
+ },
+
+ // returns true if "whichmode" is found in either the main or
+ // extended mode
+ hasMode: function(whichmode)
+ {
+ return ((mode & whichmode) || (extended_mode & whichmode) > 0) ? true : false;
+ },
+
+ addMode: function(main, extended)
+ {
+ if (main)
+ mode |= main;
+ if (extended)
+ extended_mode |= extended;
+
+ showMode();
+ },
+
+ // always show the new mode in the statusline
+ removeMode: function(main, extended)
+ {
+ if (main)
+ mode = (mode | main) ^ main;
+ if (extended)
+ extended_mode = (extended_mode | extended) ^ extended;
+
+ showMode();
+ },
+
+ beep: function()
+ {
+ if (vimperator.options["beep"])
+ sound_service.beep();
+ },
+
+ // After pressing Escape, put focus on a non-input field of the browser document
+ focusContent: function()
+ {
+ 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();
+ },
+
+ /**
+ * logs a message to the javascript error console
+ */
+ log: function(msg, level)
+ {
+ // if (Options.getPref("verbose") >= level) // FIXME: hangs vimperator, probably timing issue --mst
+ console_service.logStringMessage('vimperator: ' + msg);
+ },
+
+ /**
+ * logs an object to the javascript error console also prints all
+ * properties of the object
+ */
+ logObject: function(object, level)
+ {
+ if (typeof object != 'object')
+ return false;
+
+ var string = object + '::\n';
+ for (var i in object)
+ {
+ var value;
+ try {
+ var value = object[i];
+ } catch (e) { value = '' }
+
+ string += i + ': ' + value + '\n';
+ }
+ this.log(string, level);
+ },
+
+ // quit vimperator, no matter how many tabs/windows are open
+ quit: function(save_session)
+ {
+ if (save_session)
+ Options.setFirefoxPref("browser.startup.page", 3); // start with saved session
+ else
+ Options.setFirefoxPref("browser.startup.page", 1); // start with default homepage session
+
+ goQuitApplication();
+ },
+
+ restart: function()
+ {
+ // if (!arguments[1]) return;
+ const nsIAppStartup = Components.interfaces.nsIAppStartup;
+
+ // Notify all windows that an application quit has been requested.
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
+ .createInstance(Components.interfaces.nsISupportsPRBool);
+ os.notifyObservers(cancelQuit, "quit-application-requested", null);
+
+ // Something aborted the quit process.
+ if (cancelQuit.data)
+ return;
+
+ // Notify all windows that an application quit has been granted.
+ os.notifyObservers(null, "quit-application-granted", null);
+
+ // Enumerate all windows and call shutdown handlers
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var windows = wm.getEnumerator(null);
+ while (windows.hasMoreElements())
+ {
+ var win = windows.getNext();
+ if (("tryToClose" in win) && !win.tryToClose())
+ return;
+ }
+ Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup)
+ .quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
+ },
+
+ // TODO: allow callback for filtering out unwanted frames? User defined?
+ shiftFrameFocus: function(count, forward)
+ {
+ try
+ {
+ var frames = [];
+
+ // find all frames - depth-first search
+ (function(frame)
+ {
+ if (frame.document.body.localName.toLowerCase() == "body")
+ frames.push(frame);
+ for (var i = 0; i < frame.frames.length; i++)
+ arguments.callee(frame.frames[i])
+ })(window.content);
+
+ if (frames.length == 0) // currently top is always included
+ return;
+
+ // remove all unfocusable frames
+ // TODO: find a better way to do this
+ var start = document.commandDispatcher.focusedWindow;
+ frames = frames.filter(function(frame) {
+ frame.focus();
+ if (document.commandDispatcher.focusedWindow == frame)
+ return frame;
+ });
+ start.focus();
+
+ // find the currently focused frame index
+ // TODO: If the window is a frameset then the first _frame_ should be
+ // focused. Since this is not the current FF behaviour,
+ // we initalise current to -1 so the first call takes us to the
+ // first frame.
+ var current = -1;
+ for (var i = 0; i < frames.length; i++)
+ {
+ if (frames[i] == document.commandDispatcher.focusedWindow)
+ {
+ var current = i;
+ break;
+ }
+ }
+
+ // calculate the next frame to focus
+ var next = current;
+ if (forward)
+ {
+ if (count > 1)
+ next = current + count;
+ else
+ next++;
+
+ if (next > frames.length - 1)
+ next = frames.length - 1;
+ }
+ else
+ {
+ if (count > 1)
+ next = current - count;
+ else
+ next--;
+
+ if (next < 0)
+ next = 0;
+ }
+
+ // focus next frame and scroll into view
+ frames[next].focus();
+ if (frames[next] != window.content)
+ frames[next].frameElement.scrollIntoView(false);
+
+ // add the frame indicator
+ var doc = frames[next].document;
+ var indicator = doc.createElement("div");
+ indicator.id = "vimperator-frame-indicator";
+ // NOTE: need to set a high z-index - it's a crapshoot!
+ var style = "background-color: red; opacity: 0.5; z-index: 999;" +
+ "position: fixed; top: 0; bottom: 0; left: 0; right: 0;";
+ indicator.setAttribute("style", style);
+ doc.body.appendChild(indicator);
+
+ // remove the frame indicator
+ setTimeout(function() { doc.body.removeChild(indicator); }, 500);
+ }
+ catch (e)
+ {
+ //vimperator.echoerr(e);
+ // FIXME: fail silently here for now
+ }
+ },
+
+ source: function(filename, silent)
+ {
+ if (!filename)
+ return;
+
+ // convert "~" to HOME on Windows
+ if (navigator.platform == "Win32")
+ {
+ // TODO: proper pathname separator translation like Vim
+ filename = filename.replace('/', '\\', 'g');
+ var matches = filename.match(/^~(.*)/)
+ if (matches)
+ {
+ var home_dir = environment_service.get("HOME");
+ if (!home_dir)
+ home_dir = environment_service.get("USERPROFILE");
+ if (!home_dir)
+ {
+ // TODO: are these guaranteed to be set?
+ home_dir = environment_service.get("HOMEDRIVE") + environment_service.get("HOMEPATH");
+ }
+ filename = home_dir + "\\" + matches[1];
+ }
+ }
+
+ try
+ {
+ var fd = fopen(filename, "<");
+ if (!fd)
+ return;
+
+ var s = fd.read();
+ fd.close();
+
+ var prev_match = new Array(5);
+ var heredoc = '';
+ var end = false;
+ s.split('\n').forEach(function(line) {
+ [prev_match, heredoc, end] = multiliner(line, prev_match, heredoc);
+ });
+ }
+ catch (e)
+ {
+ if (!silent)
+ vimperator.echoerr(e);
+ }
+ },
+
+ startup: function()
+ {
+ window.dump("Vimperator startup\n");
+ vimperator.log("Initializing vimperator object...", 1);
+
+ // these objects are created here only after the chrome is ready
+ vimperator.log("Loading module options...", 3);
+ vimperator.options = new Options();
+ vimperator.log("Loading module events...", 3);
+ vimperator.events = new Events();
+ vimperator.log("Loading module commands...", 3);
+ vimperator.commands = new Commands();
+ vimperator.log("Loading module bookmarks...", 3);
+ vimperator.bookmarks = new Bookmarks();
+ vimperator.log("Loading module history...", 3);
+ vimperator.history = new History();
+ vimperator.log("Loading module commandline...", 3);
+ vimperator.commandline = new CommandLine();
+ vimperator.log("Loading module search...", 3);
+ vimperator.search = new Search();
+ vimperator.log("Loading module preview window...", 3);
+ vimperator.previewwindow = new InformationList("vimperator-previewwindow", { incremental_fill: false, max_items: 10 });
+ vimperator.log("Loading module buffer window...", 3);
+ vimperator.bufferwindow = new InformationList("vimperator-bufferwindow", { incremental_fill: false, max_items: 10 });
+ vimperator.log("Loading module mappings...", 3);
+ vimperator.mappings = new Mappings();
+ vimperator.log("Loading module statusline...", 3);
+ vimperator.statusline = new StatusLine();
+ vimperator.log("Loading module tabs...", 3);
+ vimperator.tabs = new Tabs();
+ vimperator.log("Loading module marks...", 3);
+ vimperator.marks = new Marks();
+ vimperator.log("Loading module quickmarks...", 3);
+ vimperator.quickmarks = new QuickMarks();
+ vimperator.log("Loading module hints...", 3);
+ vimperator.hints = new Hints();
+ vimperator.log("All modules loaded", 3);
+
+ vimperator.echo = vimperator.commandline.echo;
+ vimperator.echoerr = vimperator.commandline.echoErr;
+
+ // XXX: move elsewhere
+ vimperator.registerCallback("submit", vimperator.modes.EX, function(command) { /*vimperator.*/execute(command); } );
+ vimperator.registerCallback("complete", vimperator.modes.EX, function(str) { return exTabCompletion(str); } );
+
+ // this function adds all our required listeners to react on events
+ // also stuff like window.onScroll is handled there.
+ //addEventListeners();
+ //vimperator.events();
+
+ // work around firefox popup blocker
+ popup_allowed_events = Options.getFirefoxPref('dom.popup_allowed_events', 'change click dblclick mouseup reset submit');
+ if (!popup_allowed_events.match("keypress"))
+ Options.setFirefoxPref('dom.popup_allowed_events', popup_allowed_events + " keypress");
+
+ // we have our own typeahead find implementation
+ Options.setFirefoxPref('accessibility.typeaheadfind.autostart', false);
+ Options.setFirefoxPref('accessibility.typeaheadfind', false); // actually the above setting should do it, but has no effect in firefox
+
+ // first time intro message
+ if (Options.getPref("firsttime", true))
+ {
+ setTimeout(function() {
+ vimperator.help(null, null, null, { inTab: true });
+ Options.setPref("firsttime", false);
+ }, 1000);
+ }
+
+ //gURLBar.blur(); // TODO: needed anymore?
+ vimperator.focusContent();
+
+ // firefox preferences which we need to be changed to work well with vimperator
+ Options.setFirefoxPref("browser.startup.page", 3); // start with saved session
+
+ // Finally, read a ~/.vimperatorrc
+ // Make sourcing asynchronous, otherwise commands that open new tabs won't work
+ setTimeout(function() {
+ vimperator.source("~/.vimperatorrc", true);
+ vimperator.log("~/.vimperatorrc sourced", 1);
+ }, 50);
+
+ vimperator.log("Vimperator fully initialized", 1);
+ },
+
+ shutdown: function()
+ {
+ window.dump("Vimperator shutdown\n");
+
+ /*** save our preferences ***/
+ vimperator.commandline.destroy();
+ vimperator.events.destroy();
+ vimperator.quickmarks.destroy();
+
+ // reset some modified firefox prefs
+ if (Options.getFirefoxPref('dom.popup_allowed_events', 'change click dblclick mouseup reset submit')
+ == popup_allowed_events + " keypress")
+ Options.setFirefoxPref('dom.popup_allowed_events', popup_allowed_events);
}
- this.log(string, level);
- }
- //}}}
-} //}}}
+ } //}}}
+})(); //}}}
-////////////////////////////////////////////////////////////////////////
-// DOM related helper functions ////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////{{{
-function isFormElemFocused()
-{
- var elt = window.document.commandDispatcher.focusedElement;
- if (elt == null)
- return false;
-
- try
- { // sometimes the elt doesn't have .localName
- var tagname = elt.localName.toLowerCase();
- var type = elt.type.toLowerCase();
-
- if ( (tagname == "input" && (type != "image")) ||
- tagname == "textarea" ||
- // tagName == "SELECT" ||
- // tagName == "BUTTON" ||
- tagname == "isindex") // isindex is a deprecated one-line input box
- return true;
- }
- catch (e)
- {
- // FIXME: do nothing?
- }
-
- return false;
-}
-//}}}
+// called when the chrome is fully loaded and before the main window is shown
+window.addEventListener("load", vimperator.startup, false);
+window.addEventListener("unload", vimperator.shutdown, false);
// vim: set fdm=marker sw=4 ts=4 et: