diff --git a/common/content/bindings.xml b/common/content/bindings.xml
index 746ca242..901e467e 100644
--- a/common/content/bindings.xml
+++ b/common/content/bindings.xml
@@ -19,11 +19,55 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/content/buffer.js b/common/content/buffer.js
index 5c2f0c97..0e3f54f2 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -148,39 +148,12 @@ var Buffer = Module("buffer", {
buffer.viewSource([elem.getAttribute("href"), Number(elem.getAttribute("line"))])
};
- this.replaceProgressListener(this.progressListener);
+ this.cleanupProgressListener = util.overlayObject(window.XULBrowserWindow,
+ this.progressListener);
},
cleanup: function () {
- for (let prop in properties(this.progressListener))
- if (!this.progressListener.__lookupGetter__(prop) &&
- !callable(this.progressListener[prop]))
- this.origProgressListener[prop] = this.progressListener[prop]
-
- this.replaceProgressListener(this.origProgressListener);
- },
-
- replaceProgressListener: function (newListener) {
- // I hate this whole hack. --Kris
- let obj = window.XULBrowserWindow, getter;
- for (let prop in properties(obj))
- if ((getter = obj.__lookupGetter__(prop)) && !obj.__lookupSetter__(prop)) {
- newListener.__defineGetter__(prop, getter);
- delete obj[prop];
- }
-
- this.origProgressListener = window.XULBrowserWindow;
- try {
- config.browser.removeProgressListener(window.XULBrowserWindow);
- }
- catch (e) {} // Why? --djk
-
- config.browser.addProgressListener(newListener, Ci.nsIWebProgress.NOTIFY_ALL);
- window.XULBrowserWindow = newListener;
- window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
- .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIXULWindow)
- .XULBrowserWindow = newListener;
+ this.cleanupProgressListener();
},
destroy: function () {
@@ -237,11 +210,6 @@ var Buffer = Module("buffer", {
dactyl.initHelp();
config.styleHelp();
}
-
- // mark the buffer as loaded, we can't use buffer.loaded
- // since that always refers to the current buffer, while doc can be
- // any buffer, even in a background tab
- doc.pageIsFullyLoaded = 1;
}
if (doc instanceof HTMLDocument) {
@@ -266,10 +234,8 @@ var Buffer = Module("buffer", {
/**
* @property {Object} The document loading progress listener.
*/
- progressListener: update(Object.create(window.XULBrowserWindow), {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIWebProgressListener]),
-
- loadCount: 0,
+ progressListener: {
+ dactylLoadCount: 0,
// XXX: function may later be needed to detect a canceled synchronous openURL()
onStateChange: function onStateChange(webProgress, request, flags, status) {
@@ -280,12 +246,11 @@ var Buffer = Module("buffer", {
// This fires when the load event is initiated
// only thrown for the current tab, not when another tab changes
if (flags & Ci.nsIWebProgressListener.STATE_START) {
- webProgress.DOMWindow.document.pageIsFullyLoaded = 0;
statusline.updateProgress(0);
buffer._triggerLoadAutocmd("PageLoadPre", webProgress.DOMWindow.document);
- if (document.commandDispatcher.focusedWindow == webProgress.DOMWindow && this.loadCount++)
+ if (document.commandDispatcher.focusedWindow == webProgress.DOMWindow && this.dactylLoadCount++)
util.timeout(function () { modes.reset(false); },
dactyl.mode == modes.HINTS ? 500 : 0);
}
@@ -294,8 +259,6 @@ var Buffer = Module("buffer", {
config.browser.mCurrentBrowser.collapsed = false;
if (!dactyl.focusedElement)
dactyl.focusContent();
-
- webProgress.DOMWindow.document.pageIsFullyLoaded = (status == 0 ? 1 : 2);
statusline.updateUrl();
}
}
@@ -366,7 +329,7 @@ var Buffer = Module("buffer", {
break;
}
},
- }),
+ },
/**
* @property {Array} The alternative style sheets for the current
@@ -387,19 +350,12 @@ var Buffer = Module("buffer", {
pageInfo: null,
/**
- * @property {number} A value indicating whether the buffer is loaded.
- * Values may be:
- * 0 - Loading.
- * 1 - Fully loaded.
- * 2 - Load failed.
+ * @property {number} True when the buffer is fully loaded.
*/
- get loaded()
- Math.min.apply(Math,
- buffer.allFrames().map(function (frame)
- frame.document.pageIsFullyLoaded || 0)),
- set loaded(val)
- buffer.allFrames().forEach(function (frame)
- frame.document.pageIsFullyLoaded = val),
+ get loaded() Math.min.apply(null,
+ buffer.allFrames()
+ .map(function (frame) ["loading", "interactive", "complete"]
+ .indexOf(frame.document.readyState))),
/**
* @property {Object} The local state store for the currently selected
@@ -1217,6 +1173,13 @@ var Buffer = Module("buffer", {
return elem || doc.body || doc.documentElement;
},
+ scrollTo: function scrollTo(elem, left, top) {
+ if (left != null)
+ elem.scrollLeft = left;
+ if (top != null)
+ elem.scrollTop = top;
+ },
+
scrollVertical: function scrollVertical(elem, increment, number) {
elem = elem || Buffer.findScrollable(number, false);
let fontSize = parseInt(util.computedStyle(elem).fontSize);
@@ -1227,10 +1190,8 @@ var Buffer = Module("buffer", {
else
throw Error();
- if (number < 0 ? elem.scrollTop > 0 : elem.scrollTop < elem.scrollHeight - elem.clientHeight)
- elem.scrollTop += number * increment;
- else
- dactyl.beep();
+ dactyl.assert(number < 0 ? elem.scrollTop > 0 : elem.scrollTop < elem.scrollHeight - elem.clientHeight);
+ Buffer.scrollTo(elem, null, elem.scrollTop + number * increment);
},
scrollHorizontal: function scrollHorizontal(elem, increment, number) {
@@ -1243,21 +1204,19 @@ var Buffer = Module("buffer", {
else
throw Error();
- if (number < 0 ? elem.scrollLeft > 0 : elem.scrollLeft < elem.scrollWidth - elem.clientWidth)
- elem.scrollLeft += number * increment;
- else
- dactyl.beep();
+ dactyl.assert(number < 0 ? elem.scrollLeft > 0 : elem.scrollLeft < elem.scrollWidth - elem.clientWidth);
+ Buffer.scrollTo(elem, elem.scrollLeft + number * increment, null);
},
scrollToPercent: function scrollElemToPercent(elem, horizontal, vertical) {
elem = elem || Buffer.findScrollable(0, vertical == null);
marks.add("'", true);
- if (horizontal != null)
- elem.scrollLeft = (elem.scrollWidth - elem.clientWidth) * (horizontal / 100);
-
- if (vertical != null)
- elem.scrollTop = (elem.scrollHeight - elem.clientHeight) * (vertical / 100);
+ Buffer.scrollTo(elem,
+ horizontal == null ? null
+ : (elem.scrollWidth - elem.clientWidth) * (horizontal / 100),
+ vertical == null ? null
+ : (elem.scrollHeight - elem.clientHeight) * (vertical / 100));
},
openUploadPrompt: function openUploadPrompt(elem) {
diff --git a/common/content/configbase.js b/common/content/configbase.js
index 6fb48960..d9378581 100644
--- a/common/content/configbase.js
+++ b/common/content/configbase.js
@@ -20,6 +20,16 @@ var ConfigBase = Class(ModuleBase, {
highlight.styleableChrome = this.styleableChrome;
highlight.loadCSS(this.CSS);
highlight.loadCSS(this.helpCSS);
+ if (!util.haveGecko("2b"))
+ highlight.loadCSS();
let img = Image();
img.src = this.logo || "chrome://" + this.name + "/content/logo.png";
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index 6ea9a0a8..36ce66f7 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -1335,9 +1335,12 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
styles.system.add("taboptions", "chrome://*",
classes.length ? classes.join(",") + "{ display: none; }" : "");
- },
- validator: function (opts) dactyl.has("Gecko2") ||
- Option.validIf(!/[nN]/.test(opts), "Tab numbering not available in this " + config.host + " version")
+
+ if (!dactyl.has("Gecko2")) {
+ tabs.tabBinding.enabled = Array.some(opts, function (k) k in this.opts, this);
+ tabs.updateTabCount();
+ }
+ }
}
].filter(function (group) !group.feature || dactyl.has(group.feature));
diff --git a/common/content/events.js b/common/content/events.js
index deab0e50..b3aaf6c0 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -206,7 +206,6 @@ var Events = Module("events", {
}
catch (e) {}
- buffer.loaded = 1; // even if not a full page load, assume it did load correctly before starting the macro
modes.replaying = true;
res = events.feedkeys(this._macros.get(this._lastMacro).keys, { noremap: true });
modes.replaying = false;
@@ -657,15 +656,14 @@ var Events = Module("events", {
commandline.clear();
// TODO: allow macros to be continued when page does not fully load with an option
- let ret = (buffer.loaded == 1);
- if (!ret)
+ if (!buffer.loaded)
dactyl.echoerr("Page did not load completely in " + maxWaitTime + " seconds. Macro stopped.");
// sometimes the input widget had focus when replaying a macro
// maybe this call should be moved somewhere else?
// dactyl.focusContent(true);
- return ret;
+ return buffer.loaded;
},
onDOMMenuBarActive: function () {
@@ -1106,8 +1104,7 @@ var Events = Module("events", {
else if (this.pendingArgMap) {
let map = this.pendingArgMap;
if (!Events.isEscape(key))
- if (!modes.replaying || this.waitForPageLoad())
- execute(map, null, this.count, key);
+ execute(map, null, this.count, key);
return true;
}
else if (map && !event.skipmap && candidates.length == 0) {
@@ -1136,8 +1133,7 @@ var Events = Module("events", {
if (modes.replaying && !this.waitForPageLoad())
return true;
- let ret = execute(map, null, this.count);
- return !(map.route && ret);
+ return !execute(map, null, this.count) || !map.route
}
}
else if (mappings.getCandidates(this.main, candidateCommand).length > 0 && !event.skipmap) {
diff --git a/common/content/options.js b/common/content/options.js
index 08d7599f..0b462af7 100644
--- a/common/content/options.js
+++ b/common/content/options.js
@@ -669,7 +669,7 @@ var Options = Module("options", {
}
let closure = function () options._optionMap[name];
- memoize(this._options, this._options.length, closure);
+
memoize(this._optionMap, name, function () Option(names, description, type, defaultValue, extraInfo));
for (let alias in values(names.slice(1)))
memoize(this._optionMap, alias, closure);
@@ -678,6 +678,8 @@ var Options = Module("options", {
closure().initValue();
else
memoize(this.needInit, this.needInit.length, closure);
+ this._floptions = (this._floptions || []).concat(name);
+ memoize(this._options, this._options.length, closure);
// quickly access options with options["wildmode"]:
this.__defineGetter__(name, function () this._optionMap[name].value);
@@ -821,9 +823,9 @@ var Options = Module("options", {
*/
remove: function (name) {
let opt = this.get(name);
+ this._options = this._options.filter(function (o) o != opt);
for (let name in values(opt.names))
delete this._optionMap[name];
- this._options = this._options.filter(function (o) o != opt);
},
/** @property {Object} The options store. */
diff --git a/common/content/tabs.js b/common/content/tabs.js
index f7a6ad5f..fbefa2af 100644
--- a/common/content/tabs.js
+++ b/common/content/tabs.js
@@ -34,6 +34,11 @@ var Tabs = Module("tabs", {
dactyl.commands["tabs.select"] = function (event) {
tabs.select(event.originalTarget.getAttribute("identifier"));
};
+
+ this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", String.replace(<>>, /tab-./g, function (m) util.OS.isMacOSX ? "tab-mac" : m),
+ false, true);
},
cleanup: function cleanup() {
@@ -45,9 +50,9 @@ var Tabs = Module("tabs", {
}
},
- _updateTabCount: function () {
- if (dactyl.has("Gecko2"))
- for (let [i, tab] in Iterator(this.visibleTabs)) {
+ updateTabCount: function () {
+ for (let [i, tab] in Iterator(this.visibleTabs)) {
+ if (dactyl.has("Gecko2")) {
function node(clas) document.getAnonymousElementByAttribute(tab, "class", clas);
if (!node("dactyl-tab-number")) {
let nodes = {};
@@ -60,8 +65,10 @@ var Tabs = Module("tabs", {
tab.__defineGetter__("dactylOrdinal", function () Number(nodes.icon.value));
tab.__defineSetter__("dactylOrdinal", function (i) nodes.icon.value = nodes.label.textContent = i);
}
- tab.dactylOrdinal = i + 1;
}
+ tab.setAttribute("dactylOrdinal", i + 1);
+ tab.dactylOrdinal = i + 1;
+ }
statusline.updateTabCount(true);
},
@@ -497,7 +504,7 @@ var Tabs = Module("tabs", {
}
}, {
load: function () {
- tabs._updateTabCount();
+ tabs.updateTabCount();
},
commands: function () {
commands.add(["bd[elete]", "bw[ipeout]", "bun[load]", "tabc[lose]"],
@@ -864,7 +871,7 @@ var Tabs = Module("tabs", {
events: function () {
let tabContainer = config.tabbrowser.mTabContainer;
["TabMove", "TabOpen", "TabClose"].forEach(function (event) {
- events.addSessionListener(tabContainer, event, this.closure._updateTabCount, false);
+ events.addSessionListener(tabContainer, event, this.closure.updateTabCount, false);
}, this);
events.addSessionListener(tabContainer, "TabSelect", this.closure._onTabSelect, false);
},
diff --git a/common/modules/base.jsm b/common/modules/base.jsm
index 1a23ff67..0d37df49 100644
--- a/common/modules/base.jsm
+++ b/common/modules/base.jsm
@@ -10,7 +10,6 @@ if (!JSMLoader)
globals: {},
stale: {},
load: function load(url, target) {
- dump("dactyl: load: " + url + "\n");
if (this.stale[url]) {
delete this.stale[url];
let global = this.globals[url];
@@ -26,7 +25,6 @@ if (!JSMLoader)
Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader)
.loadSubScript(url, global);
- dump("dactyl: load reloaded: " + url + "\n");
}
Components.utils.import(url, target);
},
@@ -296,7 +294,10 @@ function deprecated(reason, fn) {
(obj ? obj + "." : "") + (fn.name || name) + " is deprecated: " + reason);
return func.apply(this, arguments);
}
- deprecatedMethod.seen = { "chrome://dactyl/content/javascript.js": true };
+ deprecatedMethod.seen = {
+ "chrome://dactyl/content/javascript.js": true,
+ "resource://dactyl/util.jsm": true
+ };
return callable(fn) ? deprecatedMethod : Class.Property({
get: function () deprecatedMethod,
@@ -692,10 +693,11 @@ function update(target) {
desc = desc.value.init(k) || desc.value;
if (typeof desc.value == "function" && Object.getPrototypeOf(target)) {
let func = desc.value;
- desc.value.superapply = function (self, args)
+ desc.value.__defineGetter__("super", function () Object.getPrototypeOf(target)[k]);
+ desc.value.superapply = function superapply(self, args)
let (meth = Object.getPrototypeOf(target)[k])
meth && meth.apply(self, args);
- desc.value.supercall = function (self)
+ desc.value.supercall = function supercall(self)
func.superapply(self, Array.slice(arguments, 1));
}
Object.defineProperty(target, k, desc);
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index 7c4e2ca9..8c79e8cd 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -1020,6 +1020,27 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
}), true);
},
+ overlayObject: function (object, overrides) {
+ let original = Object.create(object);
+ overrides = update(Object.create(original), overrides);
+
+ for each (let k in Object.getOwnPropertyNames(overrides)) {
+ let orig, desc = Object.getOwnPropertyDescriptor(overrides, k);
+ if (desc.value instanceof Class.Property)
+ desc = desc.value.init(k) || desc.value;
+
+ for (let obj = object; obj && !orig; obj = Object.getPrototypeOf(obj))
+ if (orig = Object.getOwnPropertyDescriptor(obj, k))
+ Object.defineProperty(original, k, orig);
+
+ Object.defineProperty(object, k, desc);
+ }
+ return function unwrap() {
+ for each (let k in Object.getOwnPropertyNames(original))
+ Object.defineProperty(object, k, Object.getOwnPropertyDescriptor(original, k));
+ }
+ },
+
overlayWindow: function (url, fn) {
if (url instanceof Ci.nsIDOMWindow)
util._loadOverlay(url, fn);
diff --git a/common/skin/dactyl.css b/common/skin/dactyl.css
index f145dacd..73945471 100644
--- a/common/skin/dactyl.css
+++ b/common/skin/dactyl.css
@@ -77,9 +77,9 @@
@-moz-document
url-prefix(chrome://) {
-.tab-icon-image, .tab-throbber { -moz-box-ordinal-group: 10; }
-[dactyl|highlight~=tab-number] { -moz-box-ordinal-group: 20; }
-.tab-text, .tab-label, .tab-close-button { -moz-box-ordinal-group: 50; }
+#TabsToolbar .tab-icon-image, .tab-throbber { -moz-box-ordinal-group: 10; }
+[dactyl|highlight~=tab-number] { -moz-box-ordinal-group: 20; }
+.tab-text, .tab-label, .tab-close-button { -moz-box-ordinal-group: 50; }
[dactyl|highlight~=Bell] {
-moz-appearance: none !important;
@@ -117,7 +117,7 @@ label[collapsed=true] {
/* fixes the min-height: 22px from firefox */
statusbarpanel {
-moz-appearance: none !important;
- border: 0;
+ border: 0 !important;
min-height: 18px !important;
background: transparent;
}
diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS
index be34680f..6d42bd9b 100644
--- a/pentadactyl/NEWS
+++ b/pentadactyl/NEWS
@@ -26,6 +26,8 @@
backspace.
- Supports reverse incremental search.
- Input boxes are not focused when matches are highlighted.
+ * It's now possible to map keys in many more modes, including
+ Hint, Multi-line Output, and Menu.
* Ex command parsing improvements, including:
- Multiple Ex commands may now be separated by |
- Commands can continue over multiple lines in RC files by
@@ -49,6 +51,9 @@
* The concept of completion contexts is now exposed to the user
(see :h :contexts), allowing for powerful and fine-grained
completion system customization.
+ * The external editor can now be configured to open to a given
+ line number and column, used for opening source links and
+ editing input fields with . See 'editor'.
* Command changes:
- :viusage, :optionusage and :exusage were replaced with :listkeys,
:listoptions and :listcommands, providing more powerful and
@@ -63,8 +68,11 @@
- Added :feedkeys command.
- Added -sort option to :history.
- Added several new options, including -javascript, to :abbrev and :map.
- - Added :mksyntax command.
+ - Added :mksyntax command to auto-generate Vim syntax files.
- :open now only opens files beginning with /, ./, ../, or ~/
+ - :saveas now provides completions for default file names, and
+ automatically chooses a filename when the save target is a
+ directory.
- Added :write !cmd and :write >>file.
- Added :yank command.
* Improvements to :style and :highlight:
@@ -74,8 +82,9 @@
- Active filters are not highlighted in :style listings.
- :style-related commands now divide their completions between
those active and inactive for the current site.
- - CSS property name completion is not available.
+ - CSS property name completion is now available.
* IMPORTANT option changes:
+ - Boolean options no longer accept an argument.
- 'cdpath' and 'runtimepath' no longer treat ",,"
specially. Use "." instead.
- 'incsearch', 'hlsearch', 'ignorecase', and 'smartcase' have