[Pkg-mozext-commits] [nosquint] 04/47: Import of 1.0.0 release into git
David Prévot
taffit at moszumanska.debian.org
Tue Apr 28 01:41:16 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to annotated tag 2.1.6
in repository nosquint.
commit 620c2e88691cdc864e59f3448baca1eaebb4d585
Author: Jason Tackaberry <tack at urandom.ca>
Date: Fri Jan 13 19:41:13 2012 -0500
Import of 1.0.0 release into git
---
src/chrome.manifest | 3 +-
src/chrome.manifest.in | 3 +-
src/content/help.js | 9 +
src/content/help.xul | 22 +
src/content/init.js | 10 +-
src/content/nosquint.js | 756 +++++++++++----
src/content/overlay.xul | 29 +-
src/content/prefs.css | 11 -
src/content/prefs.js | 236 ++++-
src/content/prefs.xul | 190 ++--
src/content/two-level-tlds | 1696 ++++++++++++++++++++++++++++++++++
src/defaults/preferences/nosquint.js | 11 +-
src/install.rdf | 46 +-
src/locale/en-US/help.dtd | 2 +
src/locale/en-US/help.html | 276 ++++++
src/locale/en-US/overlay.dtd | 3 +-
src/locale/en-US/prefs.dtd | 42 +-
src/locale/en-US/prefs.properties | 3 +
src/skin/icon-enlarge-16.png | Bin 0 -> 961 bytes
src/skin/icon-enlarge-24.png | Bin 0 -> 1479 bytes
src/skin/icon-reduce-16.png | Bin 0 -> 673 bytes
src/skin/icon-reduce-24.png | Bin 0 -> 697 bytes
src/skin/toolbar.css | 15 +
23 files changed, 3014 insertions(+), 349 deletions(-)
diff --git a/src/chrome.manifest b/src/chrome.manifest
index c01d036..e87d7a0 100644
--- a/src/chrome.manifest
+++ b/src/chrome.manifest
@@ -3,4 +3,5 @@ overlay chrome://browser/content/browser.xul chrome://nosquint/content/overlay.x
locale nosquint en-US locale/en-US/
-skin nosquint classic/1.0 jar:chrome:/nosquint.jar!/skin/
+skin nosquint classic/1.0 skin/
+style chrome://global/content/customizeToolbar.xul chrome://nosquint/skin/toolbar.css
diff --git a/src/chrome.manifest.in b/src/chrome.manifest.in
index 4086a0d..c576e6c 100644
--- a/src/chrome.manifest.in
+++ b/src/chrome.manifest.in
@@ -3,4 +3,5 @@ overlay chrome://browser/content/browser.xul chrome://nosquint/content/overlay.x
locale nosquint en-US ${JAR}locale/en-US/
-skin nosquint classic/1.0 jar:chrome:/nosquint.jar!/skin/
+skin nosquint classic/1.0 ${JAR}skin/
+style chrome://global/content/customizeToolbar.xul chrome://nosquint/skin/toolbar.css
diff --git a/src/content/help.js b/src/content/help.js
new file mode 100644
index 0000000..f67cd4c
--- /dev/null
+++ b/src/content/help.js
@@ -0,0 +1,9 @@
+var NoSquintHelp = {
+
+ init: function(doc) {
+ var b = doc.getElementById("nosquint-help-browser");
+ //b.webBrowserFind.searchString = "NoSquint";
+ //b.webBrowserFind.findNext();
+ }
+};
+
diff --git a/src/content/help.xul b/src/content/help.xul
new file mode 100644
index 0000000..d0dcf28
--- /dev/null
+++ b/src/content/help.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://nosquint/locale/help.dtd">
+
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&ns.help.title;"
+ buttons="accept"
+ ondialogaccept="return"
+ id="nosquint-help-dialog"
+ persist="width height"
+ width="600"
+ height="700"
+ onload="NoSquintHelp.init(document)">
+
+ <script src="help.js" />
+
+ <dialogheader title="&ns.help.subtitle;" description="&ns.help.title;" />
+ <groupbox flex="1">
+ <browser type="content" src="chrome://nosquint/locale/help.html" id="nosquint-help-browser" flex="1" />
+ </groupbox>
+</dialog>
diff --git a/src/content/init.js b/src/content/init.js
index a3f8dde..0ee6c4a 100644
--- a/src/content/init.js
+++ b/src/content/init.js
@@ -3,17 +3,25 @@ window.addEventListener("unload", NoSquint.destroy, false);
ZoomManager.prototype.getInstance().reset = function() {
+ if (ZoomManager.prototype.getInstance().textZoom == NoSquint.defaultZoomLevel)
+ return;
+
ZoomManager.prototype.getInstance().textZoom = NoSquint.defaultZoomLevel;
NoSquint.saveCurrentZoom();
+ NoSquint.updateStatus();
}
ZoomManager.prototype.getInstance().enlarge = function() {
- // FIXME: do we want to update any other tabs of pages in this domain?
+ // FIXME: do we want to update any other tabs of pages in this site?
ZoomManager.prototype.getInstance().textZoom += NoSquint.zoomIncrement;
NoSquint.saveCurrentZoom();
+ NoSquint.updateStatus();
+ dump("Enlarge text\n");
}
ZoomManager.prototype.getInstance().reduce = function() {
ZoomManager.prototype.getInstance().textZoom -= NoSquint.zoomIncrement;
NoSquint.saveCurrentZoom();
+ NoSquint.updateStatus();
+ dump("Reduce text\n");
}
diff --git a/src/content/nosquint.js b/src/content/nosquint.js
index e02dce8..73ccb9c 100644
--- a/src/content/nosquint.js
+++ b/src/content/nosquint.js
@@ -1,65 +1,222 @@
-var SLDs = [
- "ac.uk", "co.uk", "gov.uk", "ltd.uk", "me.uk", "mod.uk", "net.uk",
- "nic.uk", "nhs.uk", "org.uk", "plc.uk", "police.uk", "sch.uk"
-];
+function readLines(aURL) {
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
+ .getService(Components.interfaces.nsIScriptableInputStream);
+
+ var channel = ioService.newChannel(aURL, null, null);
+ var input = channel.open();
+ scriptableStream.init(input);
+ var str = scriptableStream.read(input.available());
+ scriptableStream.close();
+ input.close();
+ return str.split("\n");
+}
var NoSquint = {
- prefs: null,
- mousePrefs: null,
- initialized: false,
- url: null,
- tabbrowser: null,
- listeners: [],
- rObserver: {
- observe: function(subject, topic, data) { NoSquint.prefsChanged(); }
- },
- eatNextPrefChange: false,
-
- // Prefs
- domains: {},
+ TLDs: null, // Hash of multi-level TLDs; shared between windows
+ prefs: null, // Prefs service rooted at extensions.nosquint.
+ mousePrefs: null, // Prefers service rooted at mousewheel.withcontrolkey.
+ initialized: false, // True when init() was called
+ prefsRecursion: 0, // Recursion level in observe()
+ saveTimer: null, // Timer for saveSiteList()
+ zoomAllTimer: null, // Timer for zoomAll()
+ pruneTimer: null, // Timer for pruneSites()
+ sitesDirty: false, // True when sites list needs saving
+ ignoreNextSitesChange: false,
+
+ /* Prefs */
+
+ // Sites hash is keyed on site name, with value being [level, timestamp, visits]
+ sites: {},
+ exceptions: [],
defaultZoomLevel: 120,
+ saveDelay: 5000,
zoomIncrement: 10,
- rememberDomains: true,
- wheelZoomEnabled: true,
- wheelActionSave: -1,
+ rememberSites: true,
+ wheelZoomEnabled: false,
+ hideStatus: false,
+ forgetMonths: 6,
+
init: function() {
if (NoSquint.initialized)
return;
+ var t0 = new Date().getTime();
+
+ /* The multi-level TLDs list is an object shared between all windows.
+ * First iterate over all existing windows to see if we can find it;
+ * this prevents us from parsing the ~2000 line file each time a window
+ * is opened. If not, read it from the two-level-tlds file.
+ */
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var windows = wm.getEnumerator("navigator:browser");
+ var win;
+ while (win = windows.getNext()) {
+ if (win._noSquintTLDs) {
+ // Found, grab a reference to the object.
+ NoSquint.TLDs = window._noSquintTLDs = win._noSquintTLDs;
+ break;
+ }
+ }
+ if (NoSquint.TLDs == null) {
+ // TLDs list not found in any existing window. Load the stored list,
+ // which is borrowed from http://www.surbl.org/two-level-tlds
+ lines = readLines('chrome://nosquint/content/two-level-tlds');
+ window._noSquintTLDs = NoSquint.TLDs = {};
+ for (var i in lines)
+ NoSquint.TLDs[lines[i]] = true;
+ }
+
+
NoSquint.initPrefs();
- NoSquint.tabbrowser = document.getElementById("content");
- NoSquint.tabbrowser.addEventListener("DOMNodeInserted", NoSquint.handleNewBrowser, false);
window.addEventListener("DOMMouseScroll", NoSquint.handleScrollWheel, false);
-
- var pbi = NoSquint.prefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
- pbi.addObserver("", NoSquint.rObserver, false);
+ gBrowser.tabContainer.addEventListener("TabOpen", NoSquint.handleNewTab, false);
+ gBrowser.tabContainer.addEventListener("TabClose", NoSquint.handleCloseTab, false);
NoSquint.initialized = true;
+ // Zoom any tabs anther extension may have opened and attach listeners to them.
+ NoSquint.zoomAll(true);
+
+ var t1 = new Date().getTime();
+ dump("NoSquint: initialization took " + (t1-t0) + " ms\n");
},
destroy: function() {
var pbi = NoSquint.prefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
- pbi.removeObserver("", NoSquint.rObserver);
- // Restore previous mousewheel.withcontrolkey.action value
- if (NoSquint.mousePrefs && NoSquint.wheelActionSave != -1) {
- NoSquint.mousePrefs.setIntPref("action", NoSquint.wheelActionSave);
- NoSquint.prefs.setIntPref("wheelActionSave", -1);
+ pbi.removeObserver("", this);
+ pbi = NoSquint.mousePrefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
+ pbi.removeObserver("", this);
+
+ if (NoSquint.sitesDirty)
+ NoSquint._saveSiteListTimer();
+
+ /* Even though we've removed the pref observers, they lamely still get
+ * invoked during setIntPref below; setting prefs to null here prevents
+ * full entry into observe(). We're done with it now anyway.
+ */
+ NoSquint.prefs = null;
+ // Restore mousewheel.withcontrolkey.action to default if wheel zoom enabled.
+ if (NoSquint.mousePrefs && NoSquint.wheelZoomEnabled && NoSquint.mousePrefs.getIntPref("action") == 0)
+ NoSquint.mousePrefs.setIntPref("action", 3);
+
+ gBrowser.tabContainer.removeEventListener("TabOpen", NoSquint.handleNewTab, false);
+ gBrowser.tabContainer.removeEventListener("TabClose", NoSquint.handleCloseTab, false);
+ gBrowser.tabContainer.removeEventListener("TabSelect", NoSquint.handleTabChanged, false);
+ },
+
+ getBaseDomainFromHost: function(host) {
+ if (host.match(/^[\d.]+$/) != null)
+ // IP address.
+ return host;
+
+ var parts = host.split('.');
+ var level2 = parts.slice(-2).join('.');
+ var level3 = parts.slice(-3).join('.');
+ if (NoSquint.TLDs[level3])
+ return parts.slice(-4).join('.');
+ else if (NoSquint.TLDs[level2])
+ return level3;
+ return level2;
+ },
+
+
+ processExceptions: function(exlist) {
+ // My eyes! The googles do nothing!
+ function regexpify(pattern, re_star, re_dblstar) {
+ var parts = pattern.split(/(\[\*+\]|\*+)/);
+ var pattern = [];
+ var sub = [];
+ var length = 0;
+ var wildcards = {
+ '*': '(' + re_star + ')',
+ '**': '(' + re_dblstar + ')',
+ '[*]': re_star,
+ '[**]': re_dblstar
+ };
+
+ for (var i = 0, n = 1; i < parts.length; i++) {
+ var part = parts[i];
+ if (part == '')
+ continue;
+ if (wildcards[part])
+ pattern.push(wildcards[part]);
+ else {
+ length += part.length;
+ pattern.push('(' + part + ')');
+ }
+
+ if (part[0] == '[')
+ sub.push(part.slice(1, -1));
+ else
+ sub.push('$' + n++);
+
+ }
+ return [ length, pattern.join(''), sub.join('') ];
+ }
+
+ var exceptions = [];
+ for (var i = 0; i < exlist.length; i++) {
+ var exc = exlist[i]
+ if (!exc)
+ continue;
+ // Escape metacharacters except *
+ exc = exc.replace(/([^\w*\[\]])/g, '\\$1');
+ // Split into host,path parts.
+ var [_, exc_host, exc_path] = exc.match(/([^\/]+)(\\\/.*|$)/);
+ var [ len_host, re_host, sub_host] = regexpify(exc_host, '[^.:/]+', '.*');
+ var [ len_path, re_path, sub_path] = regexpify(exc_path, '[^/]+', '.*');
+ exceptions.push([len_host, re_host, sub_host, len_path, re_path, sub_path]);
}
+ return exceptions;
+ },
+
+
+ getSiteFromURI: function(URI) {
+ //var t0 = new Date().getTime();
+
+ var uri_host = URI.asciiHost;
+ var uri_path = URI.path;
+ var base = NoSquint.getBaseDomainFromHost(uri_host);
+
+ var match = null;
+ var match_weight = 0;
+
+ for (var i in NoSquint.exceptions) {
+ var [len_host, re_host, sub_host, len_path, re_path, sub_path] = NoSquint.exceptions[i];
+ if (re_host != '([^.:/]+)')
+ var m1 = uri_host.match(new RegExp('(' + re_host + ')$'));
+ else
+ // Single star is base name
+ var m1 = [null, base];
+
+ var m2 = uri_path.match(new RegExp('^(' + re_path + ')'));
- // Clean up active progress listeners, unregistering DOMNodeRemoved event listeners
- for (var i = 0; i < NoSquint.listeners.length; i++) {
- var browser = NoSquint.listeners[i].browser;
- browser.parentNode.removeEventListener("DOMNodeRemoved", NoSquint.handleRemoveBrowser, false);
+ if (!m1 || !m2)
+ continue;
+
+ var cur_weight = len_host * 1000 + len_path;
+ if (cur_weight < match_weight)
+ continue;
+
+ site_host = m1[1].replace(new RegExp(re_host), sub_host);
+ site_path = m2[1].replace(new RegExp(re_path), sub_path);
+ match = site_host + site_path;
+ match_weight = cur_weight;
}
- NoSquint.listeners = [];
- // Unregister the event listeners setup during init.
- NoSquint.tabbrowser.removeEventListener("DOMNodeInserted", NoSquint.handleNewBrowser, false);
- //window.removeEventListener("DOMMouseScroll", NoSquint.handleScrollWheel, false);
+ //var t1 = new Date().getTime();
+ //dump("NoSquint: getSiteFromURI took " + (t1-t0) + " ms\n");
+
+ if (match)
+ return match;
+ return base;
},
+
handleScrollWheel: function(event) {
if (!event.ctrlKey || !NoSquint.wheelZoomEnabled)
return;
@@ -73,38 +230,26 @@ var NoSquint = {
event.preventDefault();
},
- getCurrentBrowser: function() {
- var nodes = NoSquint.tabbrowser.mPanelContainer.getElementsByTagName("browser");
- var cur = nodes[NoSquint.tabbrowser.mPanelContainer.selectedIndex];
- return cur;
+
+ handleTabChanged: function(event) {
+ if (gBrowser.selectedBrowser._noSquintified)
+ NoSquint.updateStatus();
},
- getDomainFromHost: function(host) {
- var domain = host.replace(/^.*?([^.]*\.[^.]*$)/, "$1");
- // Check second-level domains list, if domain is one of these, then
- // return third-level domain instead.
- for (var n in SLDs) {
- if (domain == SLDs[n])
- return host.replace(/^.*?([^.]*\.[^.]*\.[^.]*$)/, "$1");
- }
- return domain;
+ handleNewTab: function(event) {
+ NoSquint.attach(event.target.linkedBrowser);
},
- handleNewBrowser: function(event) {
- var nodes = NoSquint.tabbrowser.mPanelContainer.getElementsByTagName("browser");
- var last = nodes[nodes.length - 1];
- for (var i = 0; i < NoSquint.listeners.length; i++) {
- if (NoSquint.listeners[i].browser == last) {
- //alert("Not making lisener");
- return;
- }
- }
- last.parentNode.addEventListener("DOMNodeRemoved", NoSquint.handleRemoveBrowser, false);
+ handleCloseTab: function(event) {
+ var browser = event.target.linkedBrowser;
+ browser.removeProgressListener(browser._noSquintListener);
+ },
- var listener = new ProgressListener(last);
+ attach: function(browser) {
+ var listener = new ProgressListener(browser);
+ browser.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+ browser._noSquintListener = listener;
//alert("Create new listener");
- NoSquint.listeners[NoSquint.listeners.length] = listener;
- last.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
/* Sometimes the onLocationChange handler of the ProgressListener will
* get fired, and sometimes it won't. My best guess is this is a
@@ -113,182 +258,371 @@ var NoSquint = {
* browser explicitly for this initial page, rather than rely on the
* progress handler.
*/
- window.setTimeout(function() { NoSquint.zoom(last, null); }, 1);
+ setTimeout(function() { NoSquint.zoom(browser, null); }, 1);
},
- handleRemoveBrowser: function(event) {
- var nodes = event.target.getElementsByTagName("browser");
- if (nodes.length == 0) // should this ever happen?
+ updateStatus: function() {
+ if (NoSquint.hideStatus)
return;
- // Find the listener for this browser and remove it.
- // XXX: should we assume nodes.length == 1 here, or should we iterate
- // over each node?
- var browser = nodes[0];
- for (var i = 0; i < NoSquint.listeners.length; i++) {
- if (NoSquint.listeners[i].browser == browser) {
- NoSquint.listeners.splice(i, 1);
- return;
- }
- }
+ var browser = gBrowser.selectedBrowser;
+ var level = Math.round(browser.markupDocumentViewer.textZoom * 100);
+ var label = level + "%";
+ if (browser._noSquintSite)
+ label += " (" + browser._noSquintSite + ")";
+ document.getElementById('nosquint-status').label = label;
},
- zoom: function(node, domain) {
- if (!node)
- return;
- if (domain == null && node.currentURI)
- domain = NoSquint.getDomainFromHost(node.currentURI.asciiHost);
+ getLevelForSite: function(site) {
+ if (!site)
+ return null;
- if (!domain || !NoSquint.domains[domain] || !NoSquint.rememberDomains)
- level = NoSquint.defaultZoomLevel;
- else
- level = NoSquint.domains[domain];
-
- //alert("Set zoom for host: " + node + " -- " + domain + " -- " + level + " -- " + NoSquint.rememberDomains + " -- " + node.markupDocumentViewer.textZoom);
- node.markupDocumentViewer.textZoom = level / 100.0;
+ if (NoSquint.sites[site])
+ return NoSquint.sites[site][0];
+ return null;
},
- zoomAll: function() {
- var nodes;
- try {
- nodes = NoSquint.tabbrowser.mPanelContainer.getElementsByTagName("browser");
- } catch(ex) {
- return;
- }
- for (var i = 0; i < nodes.length; i++) {
- NoSquint.zoom(nodes[i]);
- }
- },
+ getLevelForBrowser: function(browser) {
+ if (!browser._noSquintSite)
+ browser._noSquintSite = NoSquint.getSiteFromURI(browser.currentURI);
- onMenuItemCommand: function() {
- var browser = NoSquint.getCurrentBrowser();
- var domain = NoSquint.getDomainFromHost(browser.currentURI.asciiHost);
- var level;
- if (domain && NoSquint.domains[domain])
- level = NoSquint.domains[domain];
- else
- level = "default";
- window.openDialog("chrome://nosquint/content/prefs.xul", "", "chrome", domain, level);
+ if (NoSquint.rememberSites) {
+ var site = browser._noSquintSite;
+ var level = NoSquint.getLevelForSite(site);
+ if (level != null)
+ return level;
+ }
+ return NoSquint.defaultZoomLevel;
},
- initPrefs: function() {
- if (NoSquint.prefs)
+ zoom: function(browser, level) {
+ if (!browser)
return;
+ if (level == null)
+ level = NoSquint.getLevelForBrowser(browser);
- var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(
- Components.interfaces.nsIPrefService);
- NoSquint.prefs = prefs.getBranch("extensions.nosquint.");
- NoSquint.mousePrefs = prefs.getBranch("mousewheel.withcontrolkey.");
+ browser.markupDocumentViewer.textZoom = level / 100.0;
+ browser._noSquintified = true;
+ if (browser == gBrowser.selectedBrowser)
+ NoSquint.updateStatus();
+ },
- try { NoSquint.prefs.getIntPref("zoomlevel"); }
- catch (err) { NoSquint.prefs.setIntPref("zoomlevel", NoSquint.defaultZoomLevel); }
- try { NoSquint.prefs.getIntPref("zoomIncrement"); }
- catch (err) { NoSquint.prefs.setIntPref("zoomIncrement", NoSquint.zoomIncrement); }
+ zoomAll: function(attach) {
+ dump("NoSquint: zooming all tabs; attach listeners = " + attach + "\n");
+ for (var i = 0; i < gBrowser.browsers.length; i++) {
+ var browser = gBrowser.browsers[i];
+ if (browser._noSquintSite)
+ delete browser._noSquintSite;
+ NoSquint.zoom(browser, null);
+ if (attach)
+ NoSquint.attach(browser);
+ }
+ },
- try { NoSquint.prefs.getCharPref("domains"); }
- catch (err) { NoSquint.prefs.setCharPref("domains", ""); }
+ queueZoomAll: function() {
+ dump("NoSquint: queuing zoom all\n");
+ if (NoSquint.zoomAllTimer != null)
+ clearTimeout(NoSquint.zoomAllTimer);
+ NoSquint.zoomAllTimer = setTimeout(function() { NoSquint.zoomAll(false); }, 1);
+ },
- try { NoSquint.prefs.getBoolPref("rememberDomains"); }
- catch (err) { NoSquint.prefs.setBoolPref("rememberDomains", NoSquint.rememberDomains); }
+ openPrefsDialog: function() {
+ var browser = gBrowser.selectedBrowser;
+ var site = NoSquint.getSiteFromURI(browser.currentURI);
+ var level = NoSquint.getLevelForSite(site) || "default";
+ var url = browser.currentURI.asciiHost + browser.currentURI.path;
+ window.openDialog("chrome://nosquint/content/prefs.xul", "NoSquint Settings", "chrome",
+ site, level, url, NoSquint);
+ },
- try { NoSquint.prefs.getBoolPref("wheelZoomEnabled"); }
- catch (err) { NoSquint.prefs.setBoolPref("wheelZoomEnabled", NoSquint.wheelZoomEnabled); }
- try { NoSquint.wheelActionSave = NoSquint.prefs.getBoolPref("wheelActionSave"); }
- catch (err) { NoSquint.prefs.setIntPref("wheelActionSave", NoSquint.wheelActionSave); }
+ locationChanged: function(browser, uri) {
+ var site = NoSquint.getSiteFromURI(uri);
+ if (site != browser._noSquintSite)
+ // Site changed; update timestamp on new site.
+ NoSquint.updateSiteList(site, null, true);
+ browser._noSquintSite = site;
+ setTimeout(function() { NoSquint.zoom(browser, NoSquint.getLevelForBrowser(browser)); }, 1);
+ },
- if (NoSquint.wheelActionSave == -1) {
- NoSquint.wheelActionSave = NoSquint.mousePrefs.getIntPref("action");
- NoSquint.prefs.setIntPref("wheelActionSave", NoSquint.wheelActionSave);
+ pruneSites: function() {
+ if (!NoSquint.rememberSites || NoSquint.forgetMonths == 0)
+ return;
+
+ var remove = [];
+ var now = new Date();
+ for (var site in NoSquint.sites) {
+ if (!NoSquint.sites[site])
+ continue
+ var [level, timestamp, counter] = NoSquint.sites[site];
+ var age = now - new Date(timestamp);
+ var prune = (age > NoSquint.forgetMonths*30*24*60*60*1000);
+ if (prune)
+ remove.push(site);
+ dump("NoSquint: prune check: " + site + ", age=" + Math.round(age/1000/60/60/24) +
+ " days, prune=" + prune + "\n");
+ }
+ if (remove.length) {
+ for (var i = 0; i < remove.length; i++)
+ delete NoSquint.sites[remove[i]];
+ NoSquint.saveSiteList();
}
- NoSquint.mousePrefs.setIntPref("action", 0);
- NoSquint.prefsChanged();
+ // Fire timer once a day.
+ if (NoSquint.pruneTimer == null)
+ NoSquint.pruneTimer = setTimeout(function() { NoSquint.pruneTimer = null; NoSquint.pruneSites(); },
+ 24*60*60*1000);
+
},
- initPrefsDialog: function(doc) {
- NoSquint.initPrefs();
- doc.getElementById("defaultZoomLevel").value = NoSquint.defaultZoomLevel;
- doc.getElementById("zoomIncrement").value = NoSquint.zoomIncrement;
- doc.getElementById("rememberDomains").selectedIndex = NoSquint.rememberDomains ? 1 : 0;
+ /* Saves the current tab's zoom level in the site list.
+ */
+ saveCurrentZoom: function() {
+ if (!NoSquint.rememberSites)
+ return;
+
+ var browser = gBrowser.selectedBrowser;
+ var current_level = Math.round(browser.markupDocumentViewer.textZoom * 100);
+ NoSquint.updateSiteList(browser, current_level);
},
- savePrefs: function(doc) {
- if (doc) {
- NoSquint.prefs.setIntPref("zoomlevel", doc.getElementById("defaultZoomLevel").value);
- NoSquint.prefs.setIntPref("zoomIncrement", doc.getElementById("zoomIncrement").value);
- var val = doc.getElementById("rememberDomains").selectedIndex == 0 ? false : true;
- NoSquint.prefs.setBoolPref("rememberDomains", val);
- if (window.arguments && window.arguments[0]) {
- var domain = window.arguments[0];
- var level = doc.getElementById("domainZoom").value;
- var domains = NoSquint.prefs.getCharPref("domains");
- var re = new RegExp(domain + "\\b=\\d+\\b", "ig");
- if (level == "default")
- domains = domains.replace(re, "");
- else if (domains.search(domain + "=") != -1)
- domains = domains.replace(re, domain + "=" + level);
+ updateSiteList: function(site_or_browser, level, update_timestamp) {
+ var site = site_or_browser;
+ if (typeof(site_or_browser) != "string")
+ site = site_or_browser._noSquintSite;
+ if (!site)
+ return false;
+ if (update_timestamp) {
+ if (!level && !NoSquint.sites[site])
+ // No need to update the timestamp for a site we're not remembering.
+ return false;
+ NoSquint.sites[site][1] = new Date().getTime();
+ NoSquint.sites[site][2] += 1;
+ NoSquint.saveSiteList();
+ }
+ if (level) {
+ level = parseInt(level) || NoSquint.defaultZoomLevel;
+ if (level == NoSquint.defaultZoomLevel) {
+ if (!NoSquint.sites[site])
+ // No settings for this site, nothing to do.
+ return;
+ // Setting site to default zoom level, remove it from list.
+ delete NoSquint.sites[site];
+ } else {
+ if (!NoSquint.sites[site])
+ NoSquint.sites[site] = [level, new Date().getTime(), 1];
else
- domains += " " + domain + "=" + level;
-
- domains = domains.replace(/ +/g, " ");
- NoSquint.prefs.setCharPref("domains", domains);
+ NoSquint.sites[site][0] = level;
+ // TODO: go through current tabs and resize tabs for this site
}
- return;
+ NoSquint.saveSiteList();
}
+ return true;
+ },
- var domains = [];
- for (var domain in NoSquint.domains) {
- if (NoSquint.domains[domain]) {
- domains[domains.length] = domain + "=" + NoSquint.domains[domain];
- }
- }
- var domainList = domains.join(" ");
- NoSquint.eatNextPrefChange = true;
- NoSquint.prefs.setCharPref("domains", domainList);
+ /* Stores the site list in the prefs service.
+ *
+ * NOTE: This must only be called when the list has actually changed, or
+ * else the next time a change is made in the Settings dialog, it will
+ * be ignored.
+ */
+ saveSiteList: function() {
+ if (NoSquint.saveTimer != null)
+ clearTimeout(NoSquint.saveTimer);
+
+ NoSquint.sitesDirty = true;
+ // The list is actually saved (by default) 5s later, so if the user
+ // changes the zoom several times in a short period of time, we aren't
+ // needlessly iterating over the sites array.
+ NoSquint.saveTimer = setTimeout(function() { NoSquint._saveSiteListTimer(); }, NoSquint.saveDelay);
},
- prefsChanged: function() {
- if (NoSquint.eatNextPrefChange) {
- NoSquint.eatNextPrefChange = false;
- return;
- }
- NoSquint.defaultZoomLevel = NoSquint.prefs.getIntPref("zoomlevel");
- NoSquint.zoomIncrement = NoSquint.prefs.getIntPref("zoomIncrement");
- NoSquint.wheelZoomEnabled = NoSquint.prefs.getBoolPref("wheelZoomEnabled");
- // TODO: if rememberDomains has been changed from false to true, iterate
- // over current browsers and remember current zoom levels for these windows.
- NoSquint.rememberDomains = NoSquint.prefs.getBoolPref("rememberDomains");
- var domainList = NoSquint.prefs.getCharPref("domains");
- var domains = domainList.replace(/(^\s+|\s+$)/g, "").split(" ");
- //var domains = domainList.split(" ");
- NoSquint.domains = {};
- for (var i = 0; i < domains.length; i++) {
- var domain = domains[i].split("=");
- if (domain.length != 2)
- continue; // malformed
- NoSquint.domains[domain[0]] = parseInt(domain[1]);
+ _saveSiteListTimer: function() {
+ /* XXX: this can take up to 20ms (!!!) even with a smallish sites list
+ * (about 50). If it scales linearly, this could be a problem. Need
+ * to do some more serious benchmarking here. Looks like setCharPref
+ * can trigger pref observer handlers synchronously, so time elapsed
+ * includes the time the handlers take too.
+ */
+ var t0 = new Date().getTime();
+ var sites = [];
+ for (var site in NoSquint.sites) {
+ if (!NoSquint.sites[site])
+ continue
+ var [level, timestamp, counter] = NoSquint.sites[site];
+ sites.push(site + "=" + level + "," + timestamp + "," + counter);
}
- NoSquint.zoomAll();
+ var siteList = sites.join(" ");
+ /* It's a precondition that the site list has changed, so when we set
+ * the pref it will fire a notification that we'll handle in
+ * prefsChanged() which is not necessary here. So set a flag that causes
+ * the next prefs notification for sites change to be ignored.
+ */
+ NoSquint.ignoreNextSitesChange = true;
+ NoSquint.prefs.setCharPref("sites", siteList);
+ dump("NoSquint: Sites save took: " + (new Date().getTime() - t0) + "ms\n");
+ clearTimeout(NoSquint.saveTimer);
+ NoSquint.saveTimer = null;
+ NoSquint.sitesDirty = false;
},
- locationChanged: function(browser, uri) {
- window.setTimeout(function() { NoSquint.zoom(browser, NoSquint.getDomainFromHost(uri.asciiHost)); }, 1);
+ initPrefs: function() {
+ if (NoSquint.prefs)
+ return;
+
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(
+ Components.interfaces.nsIPrefService);
+ NoSquint.prefs = prefs.getBranch("extensions.nosquint.");
+ NoSquint.mousePrefs = prefs.getBranch("mousewheel.withcontrolkey.");
+
+ // Backward compatibility: convert old prefs.
+ try {
+ // In 0.9.80, domains renamed to sites
+ var domains = NoSquint.prefs.getCharPref("domains");
+ NoSquint.prefs.setCharPref("sites", domains);
+ NoSquint.prefs.clearUserPref("domains");
+ } catch (err) {}
+
+ try {
+ // In 0.9.80, rememberDomains renamed to rememberSites
+ var rememberDomains = NoSquint.prefs.getBoolPref("rememberDomains");
+ NoSquint.prefs.setBoolPref("rememberSites", rememberDomains);
+ NoSquint.prefs.clearUserPref("rememberDomains");
+ } catch (err) {}
+
+ var prefs = [
+ "zoomIncrement", "wheelZoomEnabled", "zoomIncrement", "hideStatus", "zoomlevel",
+ "sitesSaveDelay", "rememberSites", "exceptions", "sites", "forgetMonths"
+ ];
+ for (var i in prefs)
+ NoSquint.observe(null, "nsPref:changed", prefs[i]);
+
+ var pbi = NoSquint.prefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
+ pbi.addObserver("", this, false);
+ pbi = NoSquint.mousePrefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
+ pbi.addObserver("", this, false);
},
- saveCurrentZoom: function() {
- if (!NoSquint.rememberDomains)
+ observe: function(subject, topic, data) {
+ if (topic != "nsPref:changed" || typeof(NoSquint) == 'undefined' || !NoSquint.prefs)
return;
- var browser = NoSquint.getCurrentBrowser();
- var domain = NoSquint.getDomainFromHost(browser.currentURI.asciiHost);
- var level = Math.round(browser.markupDocumentViewer.textZoom * 100);
- if (level != NoSquint.defaultZoomLevel)
- NoSquint.domains[domain] = level;
- else
- delete NoSquint.domains[domain];
-
- NoSquint.savePrefs(null);
+ NoSquint.prefsRecursion++;
+
+ switch (data) {
+ case "action":
+ if (NoSquint.prefsRecursion > 1)
+ break;
+ /* If mousewheel.withcontrolkey.action has changed (perhaps via another
+ * extension or edited manually by the user) try to do something
+ * sensible. If the action is set to 3 (default) then we enable the No
+ * Squint wheel zoom hooks and then set the action to 0 (otherwise we
+ * will never see events. If it is set to any other value, we disable
+ * the hook for wheel zoom.
+ */
+ var action = NoSquint.mousePrefs.getIntPref("action");
+ if (action == 3) {
+ NoSquint.prefs.setBoolPref("wheelZoomEnabled", true);
+ //alert("Setting wheelZoomEnabled=true, action=0 because action == 3");
+ NoSquint.mousePrefs.setIntPref("action", 0);
+ } else if (action != 0) {
+ //alert("Setting wheelZoomEnabled=false because action != 3 == " + action);
+ NoSquint.prefs.setBoolPref("wheelZoomEnabled", false);
+ }
+ break;
+
+ case "zoomlevel":
+ NoSquint.defaultZoomLevel = NoSquint.prefs.getIntPref("zoomlevel");
+ NoSquint.queueZoomAll();
+ break;
+
+ case "wheelZoomEnabled":
+ NoSquint.wheelZoomEnabled = NoSquint.prefs.getBoolPref("wheelZoomEnabled");
+ //alert("Pref wheelZoomEnabled changed to " + NoSquint.wheelZoomEnabled);
+ if (NoSquint.wheelZoomEnabled)
+ NoSquint.mousePrefs.setIntPref("action", 0);
+ break;
+
+ case "zoomIncrement":
+ NoSquint.zoomIncrement = NoSquint.prefs.getIntPref("zoomIncrement");
+ break;
+
+ case "forgetMonths":
+ NoSquint.forgetMonths = NoSquint.prefs.getIntPref("forgetMonths");
+ NoSquint.pruneSites();
+ break;
+
+ case "hideStatus":
+ NoSquint.hideStatus = NoSquint.prefs.getBoolPref("hideStatus");
+ document.getElementById("nosquint-status").hidden = NoSquint.hideStatus;
+ if (NoSquint.hideStatus)
+ gBrowser.tabContainer.removeEventListener("TabSelect", NoSquint.handleTabChanged, false);
+ else {
+ gBrowser.tabContainer.addEventListener("TabSelect", NoSquint.handleTabChanged, false);
+ NoSquint.handleTabChanged();
+ }
+ break;
+
+ case "rememberSites":
+ NoSquint.rememberSites = NoSquint.prefs.getBoolPref("rememberSites");
+ NoSquint.queueZoomAll();
+ break;
+
+ case "sitesSaveDelay":
+ NoSquint.saveDelay = NoSquint.prefs.getIntPref("sitesSaveDelay");
+ break;
+
+ case "exceptions":
+ // Parse exceptions list from prefs
+ var exlist = NoSquint.prefs.getCharPref("exceptions").replace(/(^\s+|\s+$)/g, "").split(" ");
+ //var list = NoSquint.parseExceptions(NoSquint.prefs.getCharPref("exceptions"));
+ NoSquint.exceptions = NoSquint.processExceptions(exlist);
+ NoSquint.queueZoomAll();
+ break;
+
+ case "sites":
+ /* Parse site list from prefs. The prefs string a list of site specs,
+ * delimited by a space, in the form sitename=level,timestamp,visits.
+ * Spaces are not allowed in any value. Level, timestamp, and visits
+ * are all integers. The parsing code tries to be robust and handle
+ * malformed entries gracefully (in case the user edits them manually
+ * and screws up).
+ */
+ if (NoSquint.ignoreNextSitesChange) {
+ NoSquint.ignoreNextSitesChange = false;
+ break;
+ }
+ var sitesStr = NoSquint.prefs.getCharPref("sites");
+
+ // Trim whitespace and split on space.
+ var sites = sitesStr.replace(/(^\s+|\s+$)/g, "").split(" ");
+ var now = new Date().getTime();
+ NoSquint.sites = {};
+ for (var i = 0; i < sites.length; i++) {
+ var parts = sites[i].split("=");
+ if (parts.length != 2)
+ continue; // malformed
+ var [site, info] = parts;
+ var parts = info.split(',');
+ NoSquint.sites[site] = [parseInt(parts[0]) || NoSquint.defaultZoomLevel, now, 1];
+ if (parts.length > 1)
+ NoSquint.sites[site][1] = parseInt(parts[1]) || now;
+ if (parts.length > 2)
+ NoSquint.sites[site][2] = parseInt(parts[2]) || 1;
+
+ }
+ if (NoSquint.sitesDirty) {
+ /* FIXME: looks like the sites list pref was updated (possibly by
+ * another browser window) before we got a chance to write out our
+ * changes. We have lost them now; we should try to merge only
+ * newer changes based on timestamp.
+ */
+ NoSquint.sitesDirty = false;
+ }
+ NoSquint.queueZoomAll();
+ break;
+ }
+ NoSquint.prefsRecursion--;
}
};
@@ -310,15 +644,29 @@ ProgressListener.prototype.QueryInterface = function(aIID) {
ProgressListener.prototype.onLocationChange = function(progress, request, uri) {
//alert("Location change: " + uri.spec + " -- old: " + this.lastURI);
- if (uri.spec == this.lastURI)
- return;
+ /* XXX: it makes sense that if the URI hasn't changed we don't need to
+ * change zoom, but there seems to be a bug in ff where if the page contains
+ * frames, reloads will not apply the browser's zoom level to the frame.
+ * So this we make sure we reset the textzoom level for all page loads.
+ */
this.lastURI = uri.spec;
NoSquint.locationChanged(this.browser, uri);
}
+ProgressListener.prototype.onStateChange = function(progress) {
+ if (!progress.isLoadingDocument) {
+ if (NoSquint.sitesDirty)
+ NoSquint.saveSiteList();
+ } else if (NoSquint.saveTimer) {
+ // Browser is not idle and we have a sites list save pending. Clear
+ // the timer, we will save it out after we're done loading all pages.
+ clearTimeout(NoSquint.saveTimer);
+ NoSquint.saveTimer = null;
+ }
+}
+
ProgressListener.prototype.onProgressChange =
ProgressListener.prototype.onStatusChange =
-ProgressListener.prototype.onStateChange =
ProgressListener.prototype.onSecurityChange =
ProgressListener.prototype.onLinkIconAvailable = function() {
return 0;
diff --git a/src/content/overlay.xul b/src/content/overlay.xul
index e2930aa..483403d 100644
--- a/src/content/overlay.xul
+++ b/src/content/overlay.xul
@@ -1,12 +1,37 @@
<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM "chrome://nosquint/locale/overlay.dtd">
+<?xml-stylesheet href="chrome://nosquint/skin/toolbar.css" type="text/css"?>
+
<overlay id="nosquint-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="nosquint.js" />
<script src="init.js" />
+ <toolbarpalette id="BrowserToolbarPalette">
+ <toolbaritem id="nosquint-toolbar">
+ <toolbarbutton id="nosquint-button-reduce" class="toolbarbutton-1"
+ label="Shrink Text" tooltiptext="Makes text smaller for this site"
+ oncommand="ZoomManager.prototype.getInstance().reduce();" />
+ <toolbarbutton id="nosquint-button-enlarge" class="toolbarbutton-1"
+ label="Enlarge Text" tooltiptext="Makes text larger for this site"
+ oncommand="ZoomManager.prototype.getInstance().enlarge();" />
+ </toolbaritem>
+ </toolbarpalette>
+
+ <keyset id="mainKeyset">
+ <key id="nosquint-menu-key" key="0" modifiers="alt" command="cmd_noSquintPrefs" />
+ </keyset>
+
+ <commandset id="mainCommandSet">
+ <command id="cmd_noSquintPrefs" oncommand="NoSquint.openPrefsDialog()" />
+ </commandset>
+
<menupopup id="menu_ToolsPopup">
- <menuitem id="nosquint-menuitem" label="&nosquint;" oncommand="NoSquint.onMenuItemCommand(event);"
- insertafter="devToolsSeparator" />
+ <menuitem id="nosquint-menuitem" label="&nosquint.label;" oncommand="NoSquint.openPrefsDialog()"
+ key="nosquint-menu-key" accesskey="&nosquint.accesskey;" insertafter="devToolsSeparator" />
</menupopup>
+ <statusbar id="status-bar">
+ <statusbarpanel class="statusbarpanel-iconic-text" id="nosquint-status" label="100%"
+ onclick="NoSquint.openPrefsDialog()" src="chrome://nosquint/skin/icon-enlarge-16.png" />
+ </statusbar>
</overlay>
diff --git a/src/content/prefs.css b/src/content/prefs.css
index 5d70b8f..bb10dbf 100644
--- a/src/content/prefs.css
+++ b/src/content/prefs.css
@@ -6,17 +6,6 @@ label.percent {
margin-left: -0.18em;
}
-.tip {
- margin-left: 4.7em;
- margin-bottom: 1.0em;
- margin-right: 0.5em;
- color: #666;
-}
-
.indent {
margin-left: 2.5em;
}
-
-#domainZoom-button {
- margin-bottom: 0.75em;
-}
diff --git a/src/content/prefs.js b/src/content/prefs.js
index 6b022f6..e381883 100644
--- a/src/content/prefs.js
+++ b/src/content/prefs.js
@@ -1,24 +1,216 @@
-function domains_rb_select(doc) {
- var label = doc.getElementById("domainZoom-label");
- if (!window.arguments || window.arguments[0] == "") {
- if (label.value.search("\\(") == -1)
- label.value = label.value.replace(":", " ([no domain in URL])");
- return;
- }
- var box = doc.getElementById("domainZoom-box");
- var disabled = doc.getElementById("rememberDomains").selectedIndex == 0;
- if (label.value.search("\\(") == -1) {
- label.value = label.value.replace(":", " (" + window.arguments[0] + "):");
- doc.getElementById("domainZoom").value = window.arguments[1];
- }
+var NoSquintPrefs = {
+ prefs: null,
+ site: null,
+ level: null,
+ NoSquint: null,
+
+ init: function(doc) {
+ NoSquintPrefs.doc = doc;
+
+ if (window.arguments) {
+ NoSquintPrefs.site = window.arguments[0];
+ NoSquintPrefs.level = window.arguments[1];
+ NoSquintPrefs.url = window.arguments[2];
+ NoSquintPrefs.NoSquint = window.arguments[3];
+ NoSquintPrefs.prefs = NoSquintPrefs.NoSquint.prefs;
+ } else {
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(
+ Components.interfaces.nsIPrefService);
+ NoSquintPrefs.prefs = prefs.getBranch("extensions.nosquint.")
+ }
+ doc.getElementById("defaultZoomLevel").value = NoSquintPrefs.prefs.getIntPref("zoomlevel");
+ doc.getElementById("zoomIncrement").value = NoSquintPrefs.prefs.getIntPref("zoomIncrement");
+ doc.getElementById("rememberSites").selectedIndex = NoSquintPrefs.prefs.getBoolPref("rememberSites") ? 1 : 0;
+ doc.getElementById("showStatus").checked = !NoSquintPrefs.prefs.getBoolPref("hideStatus");
+ doc.getElementById("wheelZoomEnabled").checked = NoSquintPrefs.prefs.getBoolPref("wheelZoomEnabled");
+
+ var forget_cb = doc.getElementById("siteForget");
+ var months = NoSquintPrefs.prefs.getIntPref("forgetMonths");
+ //if (months < 0 || months > 12 || months % 3 != 0)
+ // months = 6;
+ forget_cb.checked = (months != 0);
+ if (months)
+ doc.getElementById("siteForget-menu").value = months;
+ forget_cb.addEventListener("CheckboxStateChange", NoSquintPrefs.forgetMonthsChecked, false);
+ NoSquintPrefs.forgetMonthsChecked();
+
+ NoSquintPrefs.sitesRadioSelect();
+ NoSquintPrefs.parseExceptions();
+ NoSquintPrefs.excListSelect();
+ },
+
+ parseExceptions: function() {
+ var exstr = NoSquintPrefs.prefs.getCharPref("exceptions");
+ // Trim whitespace and split on space.
+ exlist = exstr.replace(/(^\s+|\s+$)/g, "").split(" ");
+ for (var i = 0; i < exlist.length; i++) {
+ if (exlist[i])
+ NoSquintPrefs.exceptionsListAdd(exlist[i], false);
+ }
+ NoSquintPrefs.doc.getElementById("exceptionsList")._changed = false;
+ },
+
+ exceptionsListAdd: function(pattern, check_dupe) {
+ // Strip URI scheme from pattern (if it exists)
+ pattern = pattern.replace(/^\w+:\/\//, '');
+
+ var listbox = NoSquintPrefs.doc.getElementById("exceptionsList");
+ if (check_dupe) {
+ for (var i = 0; i < listbox.childNodes.length; i++) {
+ var node = listbox.childNodes[i];
+ if (node.childNodes[0].getAttribute("label") == pattern) {
+ var bundle = NoSquintPrefs.doc.getElementById("nosquint-prefs-bundle");
+ alert(bundle.getString('patternExists'));
+ return;
+ }
+ }
+ }
+
+ var node = NoSquintPrefs.doc.createElement("listitem");
+ var li1 = NoSquintPrefs.doc.createElement("listcell");
+ li1.setAttribute("label", pattern);
+ node.appendChild(li1);
+ listbox.appendChild(node);
+ node.addEventListener("dblclick", NoSquintPrefs.buttonEditException, false);
+ listbox._changed = true;
+ },
+
+ textPatternKeyPress: function(event) {
+ if (event.keyCode == 13) {
+ NoSquintPrefs.buttonAddException();
+ return false;
+ }
+ },
+
+ textPatternChange: function() {
+ var pattern = NoSquintPrefs.doc.getElementById("pattern").value;
+ var exc_button = NoSquintPrefs.doc.getElementById("exceptionAdd-button");
+ exc_button.disabled = (pattern == '');
+ //var grp_button = NoSquintPrefs.doc.getElementById("groupAdd-button");
+ //exc_button.disabled = grp_button.disabled = (pattern == '');
+ },
+
+ excListKeyPress: function(event) {
+ if (event.keyCode == 13) {
+ NoSquintPrefs.buttonEditException();
+ return false;
+ }
+ },
+
+ excListSelect: function() {
+ var btn = NoSquintPrefs.doc.getElementById("exceptionRemove-button");
+ var listbox = NoSquintPrefs.doc.getElementById("exceptionsList");
+ btn.disabled = (listbox.selectedItems.length == 0);
+
+ var btn = NoSquintPrefs.doc.getElementById("exceptionEdit-button");
+ btn.disabled = listbox.selectedItems.length != 1;
+ },
- for (i = 0; i < box.childNodes.length; i++)
- box.childNodes[i].disabled = disabled;
- doc.getElementById("domainZoom-button").disabled = disabled;
- //doc.getElementById("domainZoom-grid").hidden = false;
-}
+ buttonCopyFromURL: function() {
+ var pattern = NoSquintPrefs.doc.getElementById("pattern");
+ pattern.value = NoSquintPrefs.url;
+ NoSquintPrefs.textPatternChange();
+ },
-function domains_use_default(doc) {
- window.arguments[1] = "default";
- doc.getElementById("domainZoom").value = "default";
-}
+ buttonAddException: function() {
+ var pattern = NoSquintPrefs.doc.getElementById("pattern");
+ NoSquintPrefs.exceptionsListAdd(pattern.value, true);
+ pattern.value = '';
+ NoSquintPrefs.textPatternChange();
+ },
+
+
+ buttonEditException: function() {
+ var listbox = NoSquintPrefs.doc.getElementById("exceptionsList");
+ var item = listbox.selectedItem;
+ var pattern = item.childNodes[0].getAttribute('label');
+ var bundle = NoSquintPrefs.doc.getElementById("nosquint-prefs-bundle");
+ var new_pattern = prompt(bundle.getString('editPrompt'), pattern, bundle.getString('editTitle'));
+ if (new_pattern != null && new_pattern != pattern) {
+ item.childNodes[0].setAttribute('label', new_pattern);
+ listbox._changed = true;
+ }
+ },
+
+ buttonRemoveException: function() {
+ var listbox = NoSquintPrefs.doc.getElementById("exceptionsList");
+ while (listbox.selectedItems.length)
+ listbox.removeChild(listbox.selectedItems[0]);
+ listbox._changed = true;
+ },
+
+ forgetMonthsChecked: function() {
+ var checked = NoSquintPrefs.doc.getElementById('siteForget').checked;
+ NoSquintPrefs.doc.getElementById('siteForget-menu').disabled = !checked;
+ },
+
+ sitesRadioSelect: function() {
+ var doc = NoSquintPrefs.doc;
+ var label = doc.getElementById("siteZoom-label");
+ if (NoSquintPrefs.site) {
+ if (label.value.search("\\(") == -1) {
+ label.value = label.value.replace(":", " (" + NoSquintPrefs.site + "):");
+ doc.getElementById("siteZoom").value = NoSquintPrefs.level;
+ }
+ }
+ else
+ doc.getElementById("siteZoom-box").style.display = "none";
+ if (!NoSquintPrefs.url)
+ doc.getElementById("copyURL-button").style.display = "none";
+
+ var disabled = doc.getElementById("rememberSites").selectedIndex == 0;
+ NoSquintPrefs.enableTree(doc.getElementById("siteZoom-box"), disabled);
+ NoSquintPrefs.enableTree(doc.getElementById("siteForget-box"), disabled);
+ },
+
+ enableTree: function(node, state) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (state && child.disabled == false || child.disabled == true)
+ child.disabled = state;
+ if (child.childNodes.length)
+ NoSquintPrefs.enableTree(child, state);
+ }
+ },
+
+ buttonSitesUseDefault: function() {
+ NoSquintPrefs.doc.getElementById("siteZoom").value = "default";
+ },
+
+ help: function() {
+ window.openDialog("chrome://nosquint/content/help.xul", "NoSquint Help", "chrome");
+ },
+
+ close: function() {
+ var doc = NoSquintPrefs.doc;
+ NoSquintPrefs.prefs.setBoolPref("hideStatus", !doc.getElementById("showStatus").checked);
+ NoSquintPrefs.prefs.setBoolPref("wheelZoomEnabled", doc.getElementById("wheelZoomEnabled").checked);
+ NoSquintPrefs.prefs.setIntPref("zoomlevel", doc.getElementById("defaultZoomLevel").value);
+ NoSquintPrefs.prefs.setIntPref("zoomIncrement", doc.getElementById("zoomIncrement").value);
+ var val = doc.getElementById("rememberSites").selectedIndex == 0 ? false : true;
+ NoSquintPrefs.prefs.setBoolPref("rememberSites", val);
+
+ var listbox = NoSquintPrefs.doc.getElementById("exceptionsList");
+ if (listbox._changed) {
+ var exceptions = [];
+ for (var i = 0; i < listbox.getRowCount(); i++) {
+ var item = listbox.getItemAtIndex(i);
+ var pattern = item.childNodes[0].getAttribute('label');
+ exceptions.push(pattern);
+ }
+ NoSquintPrefs.prefs.setCharPref("exceptions", exceptions.join(' '));
+ }
+ if (!NoSquintPrefs.doc.getElementById("siteForget").checked)
+ NoSquintPrefs.prefs.setIntPref("forgetMonths", 0);
+ else
+ NoSquintPrefs.prefs.setIntPref("forgetMonths", NoSquintPrefs.doc.getElementById("siteForget-menu").value);
+
+ if (!NoSquintPrefs.NoSquint)
+ return;
+
+ var level = doc.getElementById("siteZoom").value;
+ if (NoSquintPrefs.NoSquint.updateSiteList(NoSquintPrefs.site, level))
+ NoSquintPrefs.NoSquint.queueZoomAll();
+ //NoSquintPrefs.NoSquint.zoomAll(false);
+ }
+};
diff --git a/src/content/prefs.xul b/src/content/prefs.xul
index be25a58..7fcc362 100644
--- a/src/content/prefs.xul
+++ b/src/content/prefs.xul
@@ -6,76 +6,134 @@
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&ns.pref.title;"
- buttons="accept,cancel"
- ondialogaccept="NoSquint.savePrefs(document)"
+ buttons="help,accept,cancel"
+ ondialogaccept="NoSquintPrefs.close()"
+ ondialoghelp="NoSquintPrefs.help()"
+ id="nosquint-prefs-dialog"
persist="screenX screenY"
- onload="NoSquint.initPrefsDialog(document)">
+ onload="NoSquintPrefs.init(document)">
- <script src="nosquint.js" />
<script src="prefs.js" />
- <groupbox id="global">
- <caption label="&ns.pref.globalbox.label;" />
- <!-- XUL's grid container doesn't quite cut it. -->
- <html:table cellspacing="0" cellpadding="0" border="0">
- <html:tr>
- <html:td align="right" style="white-space: nowrap;">
- <label>&ns.pref.level.label;:</label>
- </html:td>
- <html:td width="100%">
- <hbox align="center">
- <textbox id="defaultZoomLevel" size="5"/>
- <label class="percent">%</label>
- </hbox>
- </html:td>
- </html:tr>
- <html:tr>
- <html:td colspan="2" width="100%">
- <html:div class="tip">&ns.pref.level.tip;</html:div>
- </html:td>
- </html:tr>
- <html:tr>
- <html:td align="right" style="white-space: nowrap;">
- <label>&ns.pref.increment.label;:</label>
- </html:td>
- <html:td width="100%">
- <hbox align="center">
- <textbox id="zoomIncrement" size="5"/>
- <label class="percent">%</label>
+ <stringbundleset id="stringbundleset">
+ <stringbundle id="nosquint-prefs-bundle" src="chrome://nosquint/locale/prefs.properties" />
+ </stringbundleset>
+
+ <tabbox flex="1">
+ <tabs>
+ <tab label="&ns.pref.tab.options.label;" />
+ <tab label="&ns.pref.tab.exceptions.label;" />
+ </tabs>
+
+ <tabpanels flex="1">
+ <!-- Options Tab -->
+ <tabpanel id="optionstab" flex="1">
+ <vbox flex="1">
+ <groupbox>
+ <caption label="&ns.pref.general.caption;" />
+ <grid>
+ <columns>
+ <column />
+ <column />
+ <column />
+ </columns>
+ <rows>
+ <row align="center">
+ <label>&ns.pref.general.level.label;:</label>
+ <textbox id="defaultZoomLevel" size="5"/>
+ <label class="percent">%</label>
+ </row>
+ <row align="center">
+ <hbox>
+ <spacer flex="1" />
+ <label>&ns.pref.general.increment.label;:</label>
+ </hbox>
+ <textbox id="zoomIncrement" size="5"/>
+ <label class="percent">%</label>
+ </row>
+ </rows>
+ </grid>
+ <vbox>
+ <checkbox id="wheelZoomEnabled" label="&ns.pref.general.mousewheel.label;" checked="false" />
+ <checkbox id="showStatus" label="&ns.pref.general.showstatus.label;" checked="false" />
+ </vbox>
+ </groupbox>
+
+ <groupbox id="site">
+ <caption label="&ns.pref.site.caption;" />
+ <radiogroup id="rememberSites" onselect="NoSquintPrefs.sitesRadioSelect()">
+ <radio label="&ns.pref.site.noRemember.label;" />
+ <radio label="&ns.pref.site.remember.label;" />
+ </radiogroup>
+ <hbox id="siteForget-box" align="center" class="indent">
+ <checkbox id="siteForget" label="&ns.pref.site.forget.label;" checked="false"
+ oncheck="document.getElementById('siteForget-menu').disabled = !this.checked" />
+ <menulist id="siteForget-menu">
+ <menupopup>
+ <menuitem value="12" label="&ns.pref.site.forget.year;"/>
+ <menuitem value="6" label="&ns.pref.site.forget.6months;" selected="true" />
+ <menuitem value="3" label="&ns.pref.site.forget.3months;" />
+ <menuitem value="1" label="&ns.pref.site.forget.month;"/>
+ </menupopup>
+ </menulist>
+ </hbox>
+ <grid id="siteZoom-box" class="indent">
+ <rows>
+ <row align="center">
+ <label disabled="true" id="siteZoom-label" value="&ns.pref.site.current.label;:" />
+ <textbox disabled="true" id="siteZoom" size="5"/>
+ <label disabled="true" class="percent">%</label>
+ </row>
+ <row align="top">
+ <label />
+ <button disabled="true" label="&ns.pref.site.resetButton.label;"
+ id="siteZoom-button" oncommand="NoSquintPrefs.buttonSitesUseDefault()" />
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+ </vbox>
+ </tabpanel>
+
+
+ <!-- exceptions Tab -->
+ <tabpanel id="exceptionstab" flex="1">
+ <vbox flex="1">
+ <html:p style="margin: 0 7px 0.5em 7px; padding: 0;">&ns.pref.exceptions.info;</html:p>
+
+ <label value="&ns.pref.exceptions.pattern.label;:" />
+ <textbox id="pattern" width="100%" oninput="NoSquintPrefs.textPatternChange()"
+ onkeypress="return NoSquintPrefs.textPatternKeyPress(event)" />
+ <hbox>
+ <button label="&ns.pref.exceptions.copyButton.label;" id="copyURL-button"
+ accesskey="&ns.pref.exceptions.copyButton.accesskey;"
+ oncommand="NoSquintPrefs.buttonCopyFromURL()" />
+ <spacer flex="1" />
+ <button label="&ns.pref.exceptions.addButton.label;" icon="add" id="exceptionAdd-button"
+ accesskey="&ns.pref.exceptions.addButton.accesskey;"
+ disabled="true" oncommand="NoSquintPrefs.buttonAddException()" />
</hbox>
- </html:td>
- </html:tr>
- <html:tr>
- <html:td colspan="2" width="100%">
- <html:div class="tip">&ns.pref.increment.tip;</html:div>
- </html:td>
- </html:tr>
- </html:table>
- </groupbox>
- <groupbox id="domain">
- <caption label="&ns.pref.domainbox.label;" />
- <radiogroup id="rememberDomains" onselect="domains_rb_select(document)">
- <radio label="&ns.pref.noRememberDomains;" />
- <radio label="&ns.pref.rememberDomains;" />
- </radiogroup>
- <grid id="domainZoom-grid" class="indent">
- <columns>
- <column />
- <column />
- <column />
- </columns>
- <rows>
- <row align="center" id="domainZoom-box">
- <label disabled="true" id="domainZoom-label" value="&ns.pref.domainZoom.label;:" />
- <textbox disabled="true" id="domainZoom" size="5"/>
- <label disabled="true" class="percent">%</label>
- </row>
- <row>
- <label />
- <button disabled="true" label="Use Default" id="domainZoom-button" onclick="domains_use_default(document)" />
- </row>
- </rows>
- </grid>
- </groupbox>
+ <separator />
+
+ <listbox id="exceptionsList" flex="1" seltype="multiple" rows="8"
+ onkeypress="return NoSquintPrefs.excListKeyPress(event)"
+ onselect="NoSquintPrefs.excListSelect()">
+ <listhead>
+ <listheader label="&ns.pref.exceptions.list.col1.label;" />
+ </listhead>
+ </listbox>
+ <hbox>
+ <button label="&ns.pref.exceptions.editButton.label;" id="exceptionEdit-button"
+ accesskey="&ns.pref.exceptions.editButton.accesskey;"
+ oncommand="NoSquintPrefs.buttonEditException()" />
+ <button label="&ns.pref.exceptions.removeButton.label;" icon="remove" id="exceptionRemove-button"
+ accesskey="&ns.pref.exceptions.removeButton.accesskey;"
+ oncommand="NoSquintPrefs.buttonRemoveException()" />
+ </hbox>
+ </vbox>
+ </tabpanel>
+
+ </tabpanels>
+ </tabbox>
</dialog>
diff --git a/src/content/two-level-tlds b/src/content/two-level-tlds
new file mode 100644
index 0000000..74ae495
--- /dev/null
+++ b/src/content/two-level-tlds
@@ -0,0 +1,1696 @@
+2000.hu
+ab.ca
+ab.se
+abo.pa
+ac.ae
+ac.at
+ac.be
+ac.cn
+ac.com
+ac.cr
+ac.cy
+ac.fj
+ac.fk
+ac.gg
+ac.gn
+ac.id
+ac.il
+ac.im
+ac.in
+ac.ir
+ac.je
+ac.jp
+ac.ke
+ac.kr
+ac.ma
+ac.mw
+ac.ng
+ac.nz
+ac.om
+ac.pa
+ac.pg
+ac.ru
+ac.rw
+ac.se
+ac.th
+ac.tj
+ac.tz
+ac.ug
+ac.uk
+ac.vn
+ac.yu
+ac.za
+ac.zm
+ac.zw
+act.au
+ad.jp
+adm.br
+adult.ht
+adv.br
+adygeya.ru
+aero.mv
+aero.tt
+aeroport.fr
+agr.br
+agrar.hu
+agro.pl
+ah.cn
+aichi.jp
+aid.pl
+ak.us
+akita.jp
+al.us
+aland.fi
+alderney.gg
+alt.na
+alt.za
+altai.ru
+am.br
+amur.ru
+amursk.ru
+aomori.jp
+ar.us
+arkhangelsk.ru
+army.mil
+arq.br
+art.br
+art.do
+art.dz
+art.ht
+art.pl
+arts.co
+arts.ro
+arts.ve
+asn.au
+asn.lv
+ass.dz
+assedic.fr
+assn.lk
+asso.dz
+asso.fr
+asso.gp
+asso.ht
+asso.mc
+asso.re
+astrakhan.ru
+at.tt
+atm.pl
+ato.br
+au.com
+au.tt
+auto.pl
+av.tr
+avocat.fr
+avoues.fr
+az.us
+baikal.ru
+barreau.fr
+bashkiria.ru
+bbs.tr
+bc.ca
+bd.se
+be.tt
+bel.tr
+belgie.be
+belgorod.ru
+bib.ve
+bio.br
+bir.ru
+biz.az
+biz.cy
+biz.et
+biz.fj
+biz.mv
+biz.nr
+biz.om
+biz.pk
+biz.pl
+biz.pr
+biz.tj
+biz.tr
+biz.tt
+biz.vn
+bj.cn
+bl.uk
+bmd.br
+bolt.hu
+bourse.za
+br.com
+brand.se
+british-library.uk
+bryansk.ru
+buryatia.ru
+c.se
+ca.tt
+ca.us
+casino.hu
+cbg.ru
+cci.fr
+ch.vu
+chambagri.fr
+chel.ru
+chelyabinsk.ru
+cherkassy.ua
+chernigov.ua
+chernovtsy.ua
+chiba.jp
+chirurgiens-dentistes.fr
+chita.ru
+chukotka.ru
+chuvashia.ru
+cim.br
+city.hu
+city.za
+ck.ua
+club.tw
+cmw.ru
+cn.com
+cn.ua
+cng.br
+cnt.br
+co.ae
+co.ag
+co.ao
+co.at
+co.bw
+co.ck
+co.cr
+co.dk
+co.fk
+co.gg
+co.hu
+co.id
+co.il
+co.im
+co.in
+co.ir
+co.je
+co.jp
+co.ke
+co.kr
+co.ls
+co.ma
+co.mu
+co.mw
+co.nz
+co.om
+co.rw
+co.st
+co.th
+co.tj
+co.tt
+co.tv
+co.tz
+co.ug
+co.uk
+co.us
+co.ve
+co.vi
+co.yu
+co.za
+co.zm
+co.zw
+com.ac
+com.ae
+com.af
+com.ag
+com.ai
+com.al
+com.an
+com.ar
+com.au
+com.aw
+com.az
+com.bb
+com.bd
+com.bh
+com.bm
+com.bn
+com.bo
+com.br
+com.bs
+com.bt
+com.bz
+com.cd
+com.ch
+com.cn
+com.co
+com.cu
+com.cy
+com.dm
+com.do
+com.dz
+com.ec
+com.ee
+com.eg
+com.er
+com.es
+com.et
+com.fj
+com.fk
+com.fr
+com.ge
+com.gh
+com.gi
+com.gn
+com.gp
+com.gr
+com.gt
+com.gu
+com.hk
+com.hn
+com.hr
+com.ht
+com.io
+com.jm
+com.jo
+com.kg
+com.kh
+com.kw
+com.ky
+com.kz
+com.la
+com.lb
+com.lc
+com.li
+com.lk
+com.lr
+com.lv
+com.ly
+com.mg
+com.mk
+com.mm
+com.mn
+com.mo
+com.mt
+com.mu
+com.mv
+com.mw
+com.mx
+com.my
+com.na
+com.nc
+com.ng
+com.ni
+com.np
+com.nr
+com.om
+com.pa
+com.pe
+com.pf
+com.pg
+com.ph
+com.pk
+com.pl
+com.pr
+com.ps
+com.pt
+com.py
+com.qa
+com.re
+com.ro
+com.ru
+com.rw
+com.sa
+com.sb
+com.sc
+com.sd
+com.sg
+com.sh
+com.st
+com.sv
+com.sy
+com.tj
+com.tn
+com.tr
+com.tt
+com.tw
+com.ua
+com.uy
+com.ve
+com.vi
+com.vn
+com.vu
+com.ws
+com.ye
+conf.au
+conf.lv
+consulado.st
+coop.br
+coop.ht
+coop.mv
+coop.mw
+coop.tt
+cpa.pro
+cq.cn
+cri.nz
+crimea.ua
+csiro.au
+ct.us
+cul.na
+cv.ua
+d.se
+dagestan.ru
+dc.us
+de.com
+de.net
+de.tt
+de.us
+de.vu
+dk.org
+dk.tt
+dn.ua
+dnepropetrovsk.ua
+dni.us
+dns.be
+donetsk.ua
+dp.ua
+dpn.br
+dr.tr
+dudinka.ru
+e-burg.ru
+e.se
+e164.arpa
+ebiz.tw
+ecn.br
+ed.ao
+ed.cr
+ed.jp
+edu.ac
+edu.af
+edu.ai
+edu.al
+edu.an
+edu.ar
+edu.au
+edu.az
+edu.bb
+edu.bd
+edu.bh
+edu.bm
+edu.bn
+edu.bo
+edu.br
+edu.bt
+edu.ck
+edu.cn
+edu.co
+edu.cu
+edu.dm
+edu.do
+edu.dz
+edu.ec
+edu.eg
+edu.er
+edu.es
+edu.et
+edu.ge
+edu.gh
+edu.gi
+edu.gp
+edu.gr
+edu.gt
+edu.gu
+edu.hk
+edu.hn
+edu.ht
+edu.in
+edu.jm
+edu.jo
+edu.kg
+edu.kh
+edu.kw
+edu.ky
+edu.kz
+edu.lb
+edu.lc
+edu.lk
+edu.lr
+edu.lv
+edu.ly
+edu.mg
+edu.mm
+edu.mn
+edu.mo
+edu.mt
+edu.mv
+edu.mw
+edu.mx
+edu.my
+edu.na
+edu.ng
+edu.ni
+edu.np
+edu.nr
+edu.om
+edu.pa
+edu.pe
+edu.pf
+edu.ph
+edu.pk
+edu.pl
+edu.pr
+edu.ps
+edu.pt
+edu.py
+edu.qa
+edu.ru
+edu.rw
+edu.sa
+edu.sb
+edu.sc
+edu.sd
+edu.sg
+edu.sh
+edu.sk
+edu.st
+edu.sv
+edu.tj
+edu.tr
+edu.tt
+edu.tw
+edu.ua
+edu.uk
+edu.uy
+edu.ve
+edu.vi
+edu.vn
+edu.vu
+edu.ws
+edu.ye
+edu.yu
+edu.za
+edunet.tn
+ehime.jp
+ekloges.cy
+embaixada.st
+eng.br
+ens.tn
+ernet.in
+erotica.hu
+erotika.hu
+es.tt
+esp.br
+etc.br
+eti.br
+eu.com
+eu.org
+eu.tt
+eun.eg
+experts-comptables.fr
+f.se
+fam.pk
+far.br
+fareast.ru
+fax.nr
+fed.us
+fgov.be
+fh.se
+fhs.no
+fhsk.se
+fhv.se
+fi.cr
+fie.ee
+film.hu
+fin.ec
+fin.tn
+firm.co
+firm.ht
+firm.in
+firm.ro
+firm.ve
+fj.cn
+fl.us
+fm.br
+fnd.br
+folkebibl.no
+forum.hu
+fot.br
+fr.tt
+fr.vu
+from.hr
+fst.br
+fukui.jp
+fukuoka.jp
+fukushima.jp
+fylkesbibl.no
+g.se
+g12.br
+ga.us
+game.tw
+games.hu
+gb.com
+gb.net
+gc.ca
+gd.cn
+geek.nz
+gen.in
+gen.nz
+gen.tr
+geometre-expert.fr
+ggf.br
+gifu.jp
+gmina.pl
+go.cr
+go.id
+go.jp
+go.ke
+go.kr
+go.th
+go.tj
+go.tz
+go.ug
+gob.bo
+gob.do
+gob.es
+gob.gt
+gob.hn
+gob.mx
+gob.ni
+gob.pa
+gob.pe
+gob.pk
+gob.sv
+gok.pk
+gon.pk
+gop.pk
+gos.pk
+gouv.fr
+gouv.ht
+gouv.rw
+gov.ac
+gov.ae
+gov.af
+gov.ai
+gov.al
+gov.ar
+gov.au
+gov.az
+gov.bb
+gov.bd
+gov.bf
+gov.bh
+gov.bm
+gov.bo
+gov.br
+gov.bt
+gov.by
+gov.ch
+gov.ck
+gov.cn
+gov.co
+gov.cu
+gov.cx
+gov.cy
+gov.dm
+gov.do
+gov.dz
+gov.ec
+gov.eg
+gov.er
+gov.et
+gov.fj
+gov.fk
+gov.ge
+gov.gg
+gov.gh
+gov.gi
+gov.gn
+gov.gr
+gov.gu
+gov.hk
+gov.ie
+gov.il
+gov.im
+gov.in
+gov.io
+gov.ir
+gov.it
+gov.je
+gov.jm
+gov.jo
+gov.jp
+gov.kg
+gov.kh
+gov.kw
+gov.ky
+gov.kz
+gov.lb
+gov.lc
+gov.li
+gov.lk
+gov.lr
+gov.lt
+gov.lu
+gov.lv
+gov.ly
+gov.ma
+gov.mg
+gov.mm
+gov.mn
+gov.mo
+gov.mt
+gov.mv
+gov.mw
+gov.my
+gov.ng
+gov.np
+gov.nr
+gov.om
+gov.ph
+gov.pk
+gov.pl
+gov.pr
+gov.ps
+gov.pt
+gov.py
+gov.qa
+gov.ru
+gov.rw
+gov.sa
+gov.sb
+gov.sc
+gov.sd
+gov.sg
+gov.sh
+gov.sk
+gov.st
+gov.sy
+gov.tj
+gov.tn
+gov.to
+gov.tp
+gov.tr
+gov.tt
+gov.tv
+gov.tw
+gov.ua
+gov.uk
+gov.ve
+gov.vi
+gov.vn
+gov.ws
+gov.ye
+gov.za
+gov.zm
+gov.zw
+govt.nz
+gr.jp
+greta.fr
+grozny.ru
+grp.lk
+gs.cn
+gsm.pl
+gub.uy
+guernsey.gg
+gunma.jp
+gv.ao
+gv.at
+gx.cn
+gz.cn
+h.se
+ha.cn
+hb.cn
+he.cn
+health.vn
+herad.no
+hi.cn
+hi.us
+hiroshima.jp
+hk.cn
+hl.cn
+hn.cn
+hokkaido.jp
+hotel.hu
+hotel.lk
+hu.com
+huissier-justice.fr
+hyogo.jp
+i.se
+ia.us
+ibaraki.jp
+icnet.uk
+id.au
+id.fj
+id.ir
+id.lv
+id.ly
+id.us
+idf.il
+idn.sg
+idrett.no
+idv.hk
+idv.tw
+if.ua
+il.us
+imb.br
+in-addr.arpa
+in.th
+in.ua
+in.us
+ind.br
+ind.er
+ind.gg
+ind.gt
+ind.in
+ind.je
+ind.tn
+inf.br
+inf.cu
+info.au
+info.az
+info.co
+info.cy
+info.ec
+info.et
+info.fj
+info.ht
+info.hu
+info.mv
+info.nr
+info.pl
+info.pr
+info.ro
+info.sd
+info.tn
+info.tr
+info.tt
+info.ve
+info.vn
+ing.pa
+ingatlan.hu
+inima.al
+int.ar
+int.az
+int.bo
+int.co
+int.lk
+int.mv
+int.mw
+int.pt
+int.ru
+int.rw
+int.tj
+int.tt
+int.ve
+int.vn
+intl.tn
+ip6.arpa
+iris.arpa
+irkutsk.ru
+isa.us
+ishikawa.jp
+isla.pr
+it.ao
+it.tt
+ivano-frankivsk.ua
+ivanovo.ru
+iwate.jp
+iwi.nz
+iz.hr
+izhevsk.ru
+jamal.ru
+jar.ru
+jersey.je
+jet.uk
+jl.cn
+jobs.tt
+jogasz.hu
+jor.br
+joshkar-ola.ru
+js.cn
+jx.cn
+k-uralsk.ru
+k.se
+k12.ec
+k12.il
+k12.tr
+kagawa.jp
+kagoshima.jp
+kalmykia.ru
+kaluga.ru
+kamchatka.ru
+kanagawa.jp
+kanazawa.jp
+karelia.ru
+kawasaki.jp
+kazan.ru
+kchr.ru
+kemerovo.ru
+kh.ua
+khabarovsk.ru
+khakassia.ru
+kharkov.ua
+kherson.ua
+khmelnitskiy.ua
+khv.ru
+kids.us
+kiev.ua
+kirov.ru
+kirovograd.ua
+kitakyushu.jp
+km.ua
+kms.ru
+kobe.jp
+kochi.jp
+koenig.ru
+komforb.se
+komi.ru
+kommunalforbund.se
+kommune.no
+komvux.se
+konyvelo.hu
+kostroma.ru
+kr.ua
+krasnoyarsk.ru
+ks.ua
+ks.us
+kuban.ru
+kumamoto.jp
+kurgan.ru
+kursk.ru
+kustanai.ru
+kuzbass.ru
+kv.ua
+ky.us
+kyonggi.kr
+kyoto.jp
+la.us
+lakas.hu
+lanarb.se
+lanbib.se
+law.pro
+law.za
+lel.br
+lg.jp
+lg.ua
+lipetsk.ru
+lkd.co.im
+ln.cn
+ltd.co.im
+ltd.cy
+ltd.gg
+ltd.gi
+ltd.je
+ltd.lk
+ltd.uk
+lugansk.ua
+lutsk.ua
+lviv.ua
+m.se
+ma.us
+magadan.ru
+magnitka.ru
+mail.pl
+maori.nz
+mari-el.ru
+mari.ru
+marine.ru
+mat.br
+matsuyama.jp
+mb.ca
+md.us
+me.uk
+me.us
+med.br
+med.ec
+med.ee
+med.ht
+med.ly
+med.om
+med.pa
+med.pro
+med.sa
+med.sd
+medecin.fr
+media.hu
+media.pl
+mi.th
+mi.us
+miasta.pl
+mie.jp
+mil.ac
+mil.ae
+mil.ar
+mil.az
+mil.bd
+mil.bo
+mil.br
+mil.by
+mil.co
+mil.do
+mil.ec
+mil.eg
+mil.er
+mil.fj
+mil.ge
+mil.gh
+mil.gt
+mil.gu
+mil.hn
+mil.id
+mil.in
+mil.io
+mil.jo
+mil.kg
+mil.kh
+mil.kw
+mil.kz
+mil.lb
+mil.lt
+mil.lu
+mil.lv
+mil.mg
+mil.mv
+mil.my
+mil.no
+mil.np
+mil.nz
+mil.om
+mil.pe
+mil.ph
+mil.pl
+mil.ru
+mil.rw
+mil.se
+mil.sh
+mil.sk
+mil.st
+mil.tj
+mil.tr
+mil.tw
+mil.uk
+mil.uy
+mil.ve
+mil.ye
+mil.za
+miyagi.jp
+miyazaki.jp
+mk.ua
+mn.us
+mo.cn
+mo.us
+mob.nr
+mobi.tt
+mobil.nr
+mobile.nr
+mod.gi
+mod.om
+mod.uk
+mordovia.ru
+mosreg.ru
+ms.us
+msk.ru
+mt.us
+muni.il
+murmansk.ru
+mus.br
+museum.mn
+museum.mv
+museum.mw
+museum.no
+museum.om
+museum.tt
+music.mobi
+mytis.ru
+n.se
+nagano.jp
+nagasaki.jp
+nagoya.jp
+nakhodka.ru
+nalchik.ru
+name.ae
+name.az
+name.cy
+name.et
+name.fj
+name.hr
+name.mv
+name.my
+name.pr
+name.tj
+name.tr
+name.tt
+name.vn
+nara.jp
+nat.tn
+national-library-scotland.uk
+naturbruksgymn.se
+navy.mil
+nb.ca
+nc.us
+nd.us
+ne.jp
+ne.ke
+ne.kr
+ne.tz
+ne.ug
+ne.us
+nel.uk
+net.ac
+net.ae
+net.af
+net.ag
+net.ai
+net.al
+net.an
+net.ar
+net.au
+net.az
+net.bb
+net.bd
+net.bh
+net.bm
+net.bn
+net.bo
+net.br
+net.bs
+net.bt
+net.bz
+net.cd
+net.ch
+net.ck
+net.cn
+net.co
+net.cu
+net.cy
+net.dm
+net.do
+net.dz
+net.ec
+net.eg
+net.er
+net.et
+net.fj
+net.fk
+net.ge
+net.gg
+net.gn
+net.gp
+net.gr
+net.gt
+net.gu
+net.hk
+net.hn
+net.ht
+net.id
+net.il
+net.im
+net.in
+net.io
+net.ir
+net.je
+net.jm
+net.jo
+net.jp
+net.kg
+net.kh
+net.kw
+net.ky
+net.kz
+net.la
+net.lb
+net.lc
+net.li
+net.lk
+net.lr
+net.lu
+net.lv
+net.ly
+net.ma
+net.mm
+net.mo
+net.mt
+net.mv
+net.mw
+net.mx
+net.my
+net.na
+net.nc
+net.ng
+net.ni
+net.np
+net.nr
+net.nz
+net.om
+net.pa
+net.pe
+net.pg
+net.ph
+net.pk
+net.pl
+net.pr
+net.ps
+net.pt
+net.py
+net.qa
+net.ru
+net.rw
+net.sa
+net.sb
+net.sc
+net.sd
+net.sg
+net.sh
+net.st
+net.sy
+net.th
+net.tj
+net.tn
+net.tr
+net.tt
+net.tw
+net.ua
+net.uk
+net.uy
+net.ve
+net.vi
+net.vn
+net.vu
+net.ws
+net.ye
+net.za
+news.hu
+nf.ca
+ngo.lk
+ngo.ph
+ngo.pl
+ngo.za
+nh.us
+nhs.uk
+nic.im
+nic.in
+nic.tt
+nic.uk
+nieruchomosci.pl
+niigata.jp
+nikolaev.ua
+nj.us
+nkz.ru
+nl.ca
+nls.uk
+nm.cn
+nm.us
+nnov.ru
+no.com
+nom.ad
+nom.ag
+nom.br
+nom.co
+nom.es
+nom.fk
+nom.fr
+nom.mg
+nom.ni
+nom.pa
+nom.pe
+nom.pl
+nom.re
+nom.ro
+nom.ve
+nom.za
+nome.pt
+norilsk.ru
+not.br
+notaires.fr
+nov.ru
+novosibirsk.ru
+ns.ca
+nsk.ru
+nsn.us
+nsw.au
+nt.au
+nt.ca
+nt.ro
+ntr.br
+nu.ca
+nv.us
+nx.cn
+ny.us
+o.se
+od.ua
+odessa.ua
+odo.br
+off.ai
+og.ao
+oh.us
+oita.jp
+ok.us
+okayama.jp
+okinawa.jp
+omsk.ru
+on.ca
+or.at
+or.cr
+or.id
+or.jp
+or.ke
+or.kr
+or.th
+or.tz
+or.ug
+or.us
+orenburg.ru
+org.ac
+org.ae
+org.ag
+org.ai
+org.al
+org.an
+org.ar
+org.au
+org.az
+org.bb
+org.bd
+org.bh
+org.bm
+org.bn
+org.bo
+org.br
+org.bs
+org.bt
+org.bw
+org.bz
+org.cd
+org.ch
+org.ck
+org.cn
+org.co
+org.cu
+org.cy
+org.dm
+org.do
+org.dz
+org.ec
+org.ee
+org.eg
+org.er
+org.es
+org.et
+org.fj
+org.fk
+org.ge
+org.gg
+org.gh
+org.gi
+org.gn
+org.gp
+org.gr
+org.gt
+org.gu
+org.hk
+org.hn
+org.ht
+org.hu
+org.il
+org.im
+org.in
+org.io
+org.ir
+org.je
+org.jm
+org.jo
+org.jp
+org.kg
+org.kh
+org.kw
+org.ky
+org.kz
+org.la
+org.lb
+org.lc
+org.li
+org.lk
+org.lr
+org.ls
+org.lu
+org.lv
+org.ly
+org.ma
+org.mg
+org.mk
+org.mm
+org.mn
+org.mo
+org.mt
+org.mv
+org.mw
+org.mx
+org.my
+org.na
+org.nc
+org.ng
+org.ni
+org.np
+org.nr
+org.nz
+org.om
+org.pa
+org.pe
+org.pf
+org.ph
+org.pk
+org.pl
+org.pr
+org.ps
+org.pt
+org.py
+org.qa
+org.ro
+org.ru
+org.sa
+org.sb
+org.sc
+org.sd
+org.se
+org.sg
+org.sh
+org.st
+org.sv
+org.sy
+org.tj
+org.tn
+org.tr
+org.tt
+org.tw
+org.ua
+org.uk
+org.uy
+org.ve
+org.vi
+org.vn
+org.vu
+org.ws
+org.ye
+org.yu
+org.za
+org.zm
+org.zw
+oryol.ru
+osaka.jp
+oskol.ru
+otc.au
+oz.au
+pa.us
+palana.ru
+parliament.cy
+parliament.uk
+parti.se
+pb.ao
+pc.pl
+pe.ca
+pe.kr
+penza.ru
+per.kh
+per.sg
+perm.ru
+perso.ht
+pharmacien.fr
+pl.ua
+plc.co.im
+plc.ly
+plc.uk
+plo.ps
+pol.dz
+pol.ht
+pol.tr
+police.uk
+poltava.ua
+port.fr
+powiat.pl
+pp.az
+pp.ru
+pp.se
+ppg.br
+prd.fr
+prd.mg
+press.cy
+press.ma
+press.se
+presse.fr
+pri.ee
+principe.st
+priv.at
+priv.hu
+priv.no
+priv.pl
+pro.ae
+pro.br
+pro.cy
+pro.ec
+pro.fj
+pro.ht
+pro.mv
+pro.om
+pro.pr
+pro.tt
+pro.vn
+psc.br
+psi.br
+pskov.ru
+ptz.ru
+pub.sa
+publ.pt
+pvt.ge
+pyatigorsk.ru
+qc.ca
+qc.com
+qh.cn
+qld.au
+qsl.br
+re.kr
+realestate.pl
+rec.br
+rec.co
+rec.ro
+rec.ve
+red.sv
+reklam.hu
+rel.ht
+rel.pl
+res.in
+ri.us
+rnd.ru
+rnrt.tn
+rns.tn
+rnu.tn
+rovno.ua
+ru.com
+rubtsovsk.ru
+rv.ua
+ryazan.ru
+s.se
+sa.au
+sa.com
+sa.cr
+saga.jp
+saitama.jp
+sakhalin.ru
+samara.ru
+saotome.st
+sapporo.jp
+saratov.ru
+sark.gg
+sc.cn
+sc.ke
+sc.ug
+sc.us
+sch.ae
+sch.gg
+sch.ir
+sch.je
+sch.lk
+sch.ly
+sch.ng
+sch.om
+sch.sa
+sch.sd
+sch.uk
+sch.zm
+school.fj
+school.nz
+school.za
+sci.eg
+sd.cn
+sd.us
+se.com
+se.tt
+sebastopol.ua
+sec.ps
+sendai.jp
+seoul.kr
+sex.hu
+sex.pl
+sh.cn
+shiga.jp
+shimane.jp
+shizuoka.jp
+shop.ht
+shop.hu
+shop.pl
+simbirsk.ru
+sk.ca
+sklep.pl
+sld.do
+sld.pa
+slg.br
+smolensk.ru
+sn.cn
+snz.ru
+soc.lk
+soros.al
+sos.pl
+spb.ru
+sport.hu
+srv.br
+sshn.se
+stat.no
+stavropol.ru
+store.co
+store.ro
+store.st
+store.ve
+stv.ru
+suli.hu
+sumy.ua
+surgut.ru
+sx.cn
+syzran.ru
+szex.hu
+szkola.pl
+t.se
+takamatsu.jp
+tambov.ru
+targi.pl
+tas.au
+tatarstan.ru
+te.ua
+tec.ve
+tel.no
+tel.nr
+tel.tr
+telecom.na
+telememo.au
+ternopil.ua
+test.ru
+tirana.al
+tj.cn
+tlf.nr
+tm.cy
+tm.fr
+tm.hu
+tm.mc
+tm.mg
+tm.mt
+tm.pl
+tm.ro
+tm.se
+tm.za
+tmp.br
+tn.us
+tochigi.jp
+tokushima.jp
+tokyo.jp
+tom.ru
+tomsk.ru
+tottori.jp
+tourism.pl
+tourism.tn
+toyama.jp
+tozsde.hu
+travel.pl
+travel.tt
+trd.br
+tsaritsyn.ru
+tsk.ru
+tula.ru
+tur.br
+turystyka.pl
+tuva.ru
+tv.bo
+tv.br
+tv.sd
+tver.ru
+tw.cn
+tx.us
+tyumen.ru
+u.se
+udm.ru
+udmurtia.ru
+uk.com
+uk.net
+uk.tt
+ulan-ude.ru
+unam.na
+uniti.al
+upt.al
+uri.arpa
+urn.arpa
+us.com
+us.tt
+ut.us
+utazas.hu
+utsunomiya.jp
+uu.mt
+uy.com
+uzhgorod.ua
+va.us
+vatican.va
+vdonsk.ru
+vet.br
+veterinaire.fr
+vgs.no
+vic.au
+video.hu
+vinnica.ua
+vladikavkaz.ru
+vladimir.ru
+vladivostok.ru
+vn.ua
+volgograd.ru
+vologda.ru
+voronezh.ru
+vrn.ru
+vt.us
+vyatka.ru
+w.se
+wa.au
+wa.us
+wakayama.jp
+weather.mobi
+web.co
+web.do
+web.lk
+web.pk
+web.tj
+web.tr
+web.ve
+web.za
+wi.us
+wv.us
+www.ro
+wy.us
+x.se
+xj.cn
+xz.cn
+y.se
+yakutia.ru
+yamagata.jp
+yamaguchi.jp
+yamal.ru
+yamanashi.jp
+yaroslavl.ru
+yekaterinburg.ru
+yk.ca
+yn.cn
+yokohama.jp
+yuzhno-sakhalinsk.ru
+z.se
+za.com
+zaporizhzhe.ua
+zgrad.ru
+zhitomir.ua
+zj.cn
+zlg.br
+zp.ua
+zt.ua
diff --git a/src/defaults/preferences/nosquint.js b/src/defaults/preferences/nosquint.js
index 9980b33..38a87af 100644
--- a/src/defaults/preferences/nosquint.js
+++ b/src/defaults/preferences/nosquint.js
@@ -1,6 +1,9 @@
pref("extensions.nosquint.zoomlevel", 120);
pref("extensions.nosquint.zoomIncrement", 10);
-pref("extensions.nosquint.rememberDomains", true);
-pref("extensions.nosquint.domains", "");
-pref("extensions.nosquint.wheelZoomEnabled", true);
-pref("extensions.nosquint.wheelActionSave", -1);
+pref("extensions.nosquint.rememberSites", true);
+pref("extensions.nosquint.sites", "");
+pref("extensions.nosquint.sitesSaveDelay", 5000);
+pref("extensions.nosquint.exceptions", "*/~* *.sourceforge.net *.google.[*]");
+pref("extensions.nosquint.wheelZoomEnabled", false);
+pref("extensions.nosquint.hideStatus", false);
+pref("extensions.nosquint.forgetMonths", 6);
diff --git a/src/install.rdf b/src/install.rdf
index 7f2c252..40bf81d 100644
--- a/src/install.rdf
+++ b/src/install.rdf
@@ -1,28 +1,20 @@
<?xml version="1.0"?>
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
- <Description about="urn:mozilla:install-manifest">
-
- <em:id>nosquint at urandom.ca</em:id>
- <em:name>No Squint</em:name>
- <em:version>0.9.1.1</em:version>
- <em:description>Zooms text by user-configurable percentage</em:description>
- <em:creator>Jason Tackaberry</em:creator>
-
- <em:homepageURL>http://urandom.ca/nosquint/</em:homepageURL>
- <em:optionsURL>chrome://nosquint/content/prefs.xul</em:optionsURL>
- <em:iconURL>chrome://nosquint/content/icon-32.png</em:iconURL>
-
- <!-- Firefox -->
- <em:targetApplication>
- <Description>
- <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
- <em:minVersion>1.5</em:minVersion>
- <em:maxVersion>2.0.0.*</em:maxVersion>
- </Description>
- </em:targetApplication>
-
- </Description>
-
-</RDF>
+<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
+ xmlns:NC="http://home.netscape.com/NC-rdf#"
+ xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <RDF:Description RDF:about="urn:mozilla:install-manifest"
+ em:id="nosquint at urandom.ca"
+ em:name="No Squint"
+ em:version="1.0.0"
+ em:description="Zooms text by user-configurable percentage"
+ em:creator="Jason Tackaberry"
+ em:homepageURL="http://urandom.ca/nosquint/"
+ em:optionsURL="chrome://nosquint/content/prefs.xul"
+ em:iconURL="chrome://nosquint/content/icon-32.png">
+ <em:targetApplication RDF:resource="rdf:#$AZWNY2"/>
+ </RDF:Description>
+ <RDF:Description RDF:about="rdf:#$AZWNY2"
+ em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
+ em:minVersion="2.0"
+ em:maxVersion="2.0.0.*" />
+</RDF:RDF>
diff --git a/src/locale/en-US/help.dtd b/src/locale/en-US/help.dtd
new file mode 100644
index 0000000..6e6f28a
--- /dev/null
+++ b/src/locale/en-US/help.dtd
@@ -0,0 +1,2 @@
+<!ENTITY ns.help.title "NoSquint Help">
+<!ENTITY ns.help.subtitle "Help">
diff --git a/src/locale/en-US/help.html b/src/locale/en-US/help.html
new file mode 100644
index 0000000..a486128
--- /dev/null
+++ b/src/locale/en-US/help.html
@@ -0,0 +1,276 @@
+<html>
+
+<style type="text/css">
+ body {
+ font-size: 110%;
+ padding: 0;
+ margin: 0;
+ text-align: justify;
+ }
+
+ ol {
+ text-align: left;
+ }
+
+ h2,h3 {
+ padding-left: 1em;
+ }
+
+ p,ol,li {
+ margin-left: 1em;
+ margin-right: 1.5em;
+ }
+
+ div.indent {
+ padding-left: 0.5em;
+ }
+
+ ul li b {
+ background-color: #eee;
+ padding: 0.2em;
+ }
+ ol li {
+ margin-bottom: 0.5em;
+ }
+
+ code {
+ font-size: 115%;
+ background-color: #fafafa;
+ }
+ h2 {
+ margin-top: 0.5em;
+ padding: 5px;
+ border-top: 1px solid #aaa;
+ border-bottom: 1px solid #aaa;
+ background-color: #f1f4fd;
+ font-family: sans-serif;
+ }
+ h3 {
+ font-family: sans-serif;
+ }
+
+</style>
+
+<body>
+<h2>Options Tab</h2>
+<h3>General Options</h3>
+<ul>
+ <li>
+ <b>Default text zoom level</b>
+ <p>This is the zoom level applied to all pages by default. A value
+ of 100% is the standard Firefox text size without NoSquint. With
+ NoSquint, you can override this value to be larger or smaller.</p>
+
+ <p>Modifying the text zoom when visiting a web page will override this
+ value for that site.</p>
+ </li>
+ <li>
+ <b>Zoom increment</b>
+ <p>You can change the text zoom for a page from the View menu, by
+ using one of the text zoom shortcuts (ctrl-plus/minus or
+ ctrl-mousewheel), or by using the optional toolbar buttons.
+ NoSquint will remember these changes. This setting specifies what
+ increment, in percent, to use when changing the zoom level.</p>
+ </li>
+ <li>
+ <b>Enable text zoom with ctrl-mousewheel</b>
+ <p>Selecting this option allows you to adjust the text zoom level
+ by pressing and holding the control key while moving the mousewheel
+ up or down.</p>
+ </li>
+ <li>
+ <b>Show current zoom level and site in status bar</b>
+ <p>Selecting this option shows the zoom level and site name in the
+ status bar for the current web page.</p>
+ </li>
+</ul>
+
+<h3>Site Options</h3>
+
+<p>To NoSquint, a site is a web location where all pages under that location
+have the same zoom level, and the site name is derived from the page's
+URL.</p>
+
+<p>In most cases, the site is the domain. For example, if the current page is
+<code>www2.ibm.com/index.php</code>, NoSquint will consider the site name to be
+<code>ibm.com</code>. NoSquint will also take into account common
+second-level domains. For example, if you're visiting
+<code>www.bbc.co.uk</code>, NoSquint will consider the site name to be
+<code>bbc.co.uk</code>.</p>
+
+<p>The default behaviour should work almost all the time. When it doesn't, you
+can control how NoSquint determines site names in the Exceptions Tab.</p>
+
+<ul>
+ <li>
+ <b>Use the default text zoom level for all sites</b>
+ <p>One of NoSquint's features is the ability to remember custom
+ text zoom levels for individual sites. If you're not interested
+ this and want to use the same level for all sites, or you just
+ don't want NoSquint to remember any manual changes, select this
+ option.</p>
+ </li>
+ <li>
+ <b>Remember text zoom level per site</b>
+ <p>With this option selected, NoSquint will remember any changes
+ you make to the text zoom level (via ctrl-plus/minus keys or
+ ctrl-mousewheel) for a given site. Next time you visit that site,
+ NoSquint will change the text zoom to the level previously used on
+ that site.</p>
+ </li>
+ <li>
+ <b>Forget zoom settings for sites not visited in the last ...</b>
+ <p>With the "remember text zoom level per site" option enabled,
+ NoSquint keeps track of all zoom level changes for sites, even
+ sites you only visit once. This option is house cleaning: if you
+ haven't visited a site (for which you've set a non-default zoom
+ level) for the specified number of months, NoSquint will forget the
+ setting.</p>
+ </li>
+ <li>
+ <b>Zoom level for the current site (example.com)</b>
+ <p>Sets the text zoom level to the specified value for the site in
+ the current browser tab or window.</p>
+ </li>
+</ul>
+
+<h2>Exceptions Tab</h2>
+
+<p>Because not all web sites are structured the same, sometimes the default
+logic NoSquint uses to determine the site name doesn't work the way you want it
+to. By way of exceptions, you can control how NoSquint determines what
+constitutes a separate site.</p>
+
+<h3>Use Cases</h3>
+<p>Exceptions are powerful and expressive, and unfortunately can be confusing.
+Before going into a detailed explanation, let's first examine some common
+use-cases. Hopefully one of these examples applies to your case.</p>
+
+<ol>
+ <li>
+ <b>Problem:</b> different subdomains on SourceForge, e.g.
+ <code>freevo.sourceforge.net</code> and
+ <code>audacity.sourceforge.net</code>, are wrongly treated as the same
+ site (<code>sourceforge.net</code>)<br />
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>*.sourceforge.net</code>
+ </li>
+
+ <li>
+ <b>Problem:</b> <code>example.com/users/mary</code> and
+ <code>example.com/users/john</code> are wrongly treated as the same
+ site (<code>example.com</code>)<br />
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>example.com/users/*</code>
+ </li>
+
+ <li>
+ <b>Problem:</b> I use Google Mail (<code>mail.google.com</code>) and
+ Google Reader (<code>google.com/reader</code>) and would like these
+ treated as sites separate from <code>google.com</code><br />
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>mail.google.com</code>; add another exception with the pattern
+ <code>google.com/reader</code>
+ </li>
+
+ <li>
+ <b>Problem:</b> my company's intranet is at
+ <code>intra.example.com</code>, but I'd like our wiki, located under
+ <code>intra.example.com/wiki</code> to be treated separately from the
+ rest of the intranet.<br />
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>intra.example.com/wiki</code>
+ </li>
+
+ <li>
+ <b>Problem:</b> Google Mail, Google Groups, and in fact all hosts on
+ Google should be treated as separate sites. But the country (the
+ top-level domain) shouldn't matter. So <code>mail.google.ca</code>
+ should be the same site as <code>mail.google.de</code>, but a different
+ site from <code>groups.google.de</code>, which itself would be the same
+ site as <code>groups.google.fi</code><br />
+
+ <b>Solution:</b> add an exception with the pattern <code>*.google.[*]</code>
+ </li>
+
+ <li>
+ <b>Problem:</b> my company has several web applications that are
+ distributed across multiple servers.
+ <code>example.com/server1/apps/app1</code> should be considered the
+ same site as <code>example.com/server2/apps/app1</code>, but there
+ could also be <code>example.com/server1/apps/app3</code> that should be
+ a separate site.<br />
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>example.com/[*]/apps/*</code>
+ </li>
+ <li>
+ <b>Problem:</b> same scenario the previous one, but sometimes the
+ server isn't in the URL, so <code>example.com/apps/app1</code> is
+ the same site as <code>example.com/server1/apps/app1</code>.<br/>
+
+ <b>Solution:</b> add an exception with the pattern
+ <code>example.com/[**]apps/*</code>
+ </li>
+</ol>
+</div>
+
+<h3>Gory Details</h3>
+<p>What follows is a technical explanation of exceptions. If you're not an
+advanced user, this section may create a fair amount of confusion; refer
+instead to the use-cases above to follow by example.</p>
+
+<p>Exception patterns may contain zero or more of the following possible wildcards:
+<ul>
+ <li>
+ <code>*</code> – When included in the host name, matches any character
+ except a dot ('.'). When included in the path, matches any character
+ except a slash ('/'). Does not match the empty string.
+ </li>
+ <li>
+ <code>**</code> – Matches any sequence of characters. Does match
+ the empty string.
+ </li>
+</ul>
+</p>
+
+<p>Site names are arbitrary strings that represent a given site and are
+computed by NoSquint based on the current page's URL and the user-defined list
+of exceptions. For instance, both <code>foo.example.com</code> and
+<code>myapp.*.example.com</code> could be site names, depending on the
+exceptions defined. NoSquint looks up zoom levels based on the site name. The
+site name, as determined by NoSquint, is by default displayed in the status bar
+beside the current zoom level.</p>
+
+<p>When a wildcard is enclosed in square brackets (i.e. <code>[*]</code> or
+<code>[**]</code>), the literal wildcard (<code>*</code> or <code>**</code>)
+will be used in the site name instead of the characters the wildcard matches.
+This is allows you to group together locations. For example, if the page's URL
+is <code>google.ca</code> and you've defined an exception
+<code>google.[*]</code>, the site name will be <code>google.*</code>. Since
+<code>google.fi</code> matches this pattern, the site name would also be
+<code>google.*</code>. Therefore, <code>google.ca</code> and
+<code>google.fi</code> would be considered the same site.</p>
+
+<p>Hostnames and paths are evaluated separately; an exception pattern is split
+into two sub-patterns, one for the host, and one for the path. These
+sub-patterns match substrings, but hosts are right-anchored, while paths are
+left-anchored. This means that any wildcards specified in the host name will
+not match any characters in the path, and vice versa. When the hostname part
+of a pattern is only <code>*</code>, it matches the domain of the page's URL.
+For example, for <code>www.google.com</code>, a single <code>*</code> matches
+<code>google.com</code>; for <code>www.bbc.co.uk</code> it matches
+<code>bbc.co.uk</code>.</p>
+
+<p>When multiple exceptions match a page's URL, NoSquint will use the exception
+that matches the most non-wildcard characters in the host name. If there are
+still multiple exceptions in that narrowed list, the exception that matches the
+most non-wildcard characters in the path is then chosen. If still there are
+multiple exceptions, the last one is chosen.</p>
+
+</body>
+</html>
diff --git a/src/locale/en-US/overlay.dtd b/src/locale/en-US/overlay.dtd
index dfffc68..b7f23f0 100644
--- a/src/locale/en-US/overlay.dtd
+++ b/src/locale/en-US/overlay.dtd
@@ -1 +1,2 @@
-<!ENTITY nosquint "NoSquint Settings">
+<!ENTITY nosquint.label "NoSquint Settings">
+<!ENTITY nosquint.accesskey "Q">
diff --git a/src/locale/en-US/prefs.dtd b/src/locale/en-US/prefs.dtd
index 7a1cfc7..a23d3c9 100644
--- a/src/locale/en-US/prefs.dtd
+++ b/src/locale/en-US/prefs.dtd
@@ -1,10 +1,34 @@
<!ENTITY ns.pref.title "NoSquint Settings">
-<!ENTITY ns.pref.level.label "Default text zoom level">
-<!ENTITY ns.pref.level.tip "The zoom level applied to all pages by default. Modifying the text zoom when visiting a web page will override this value for that domain.">
-<!ENTITY ns.pref.globalbox.label "Global Options">
-<!ENTITY ns.pref.increment.label "Zoom increment">
-<!ENTITY ns.pref.increment.tip "You can change the text zoom for a page from the View menu or using one of the text zoom shortcuts (ctrl-plus/minus, or ctrl-mousewheel). NoSquint will remember these changes. This setting specifies what increment to use when changing the zoom level.">
-<!ENTITY ns.pref.domainbox.label "Domain Options">
-<!ENTITY ns.pref.rememberDomains "Remember text zoom level per domain">
-<!ENTITY ns.pref.noRememberDomains "Use the default text zoom level (set above) for all domains">
-<!ENTITY ns.pref.domainZoom.label "Zoom level for this domain">
+<!ENTITY ns.pref.tab.options.label "Options">
+<!ENTITY ns.pref.tab.exceptions.label "Exceptions">
+
+<!ENTITY ns.pref.general.caption "General">
+<!ENTITY ns.pref.general.level.label "Default text zoom level">
+<!ENTITY ns.pref.general.increment.label "Zoom increment">
+<!ENTITY ns.pref.general.mousewheel.label "Enable text zoom with ctrl-mousewheel">
+<!ENTITY ns.pref.general.showstatus.label "Show current zoom level and site in status bar">
+
+<!ENTITY ns.pref.site.caption "Site">
+<!ENTITY ns.pref.site.noRemember.label "Use the default text zoom level (set above) for all sites">
+<!ENTITY ns.pref.site.remember.label "Remember text zoom level per site">
+<!ENTITY ns.pref.site.forget.label "Forget zoom settings for sites not visited in the last">
+<!ENTITY ns.pref.site.forget.year "Year">
+<!ENTITY ns.pref.site.forget.6months "Six Months">
+<!ENTITY ns.pref.site.forget.3months "Three Months">
+<!ENTITY ns.pref.site.forget.month "Month">
+<!ENTITY ns.pref.site.current.label "Zoom level for the current site">
+<!ENTITY ns.pref.site.resetButton.label "Use Default">
+
+<!ENTITY ns.pref.exceptions.info "Exceptions are an advanced feature that controls how NoSquint determines separate sites. Click the Help button below for full details.">
+
+<!ENTITY ns.pref.exceptions.pattern.label "Pattern for new exception">
+<!ENTITY ns.pref.exceptions.copyButton.label "Copy from URL">
+<!ENTITY ns.pref.exceptions.copyButton.accesskey "C">
+<!ENTITY ns.pref.exceptions.addButton.label "Add Exception">
+<!ENTITY ns.pref.exceptions.addButton.accesskey "A">
+<!ENTITY ns.pref.exceptions.list.col1.label "Exception Pattern">
+<!ENTITY ns.pref.exceptions.editButton.label "Edit Exception">
+<!ENTITY ns.pref.exceptions.editButton.accesskey "E">
+<!ENTITY ns.pref.exceptions.removeButton.label "Remove Exception">
+<!ENTITY ns.pref.exceptions.removeButton.accesskey "R">
+
diff --git a/src/locale/en-US/prefs.properties b/src/locale/en-US/prefs.properties
new file mode 100644
index 0000000..1608767
--- /dev/null
+++ b/src/locale/en-US/prefs.properties
@@ -0,0 +1,3 @@
+editPrompt=Specify pattern for exception
+editTitle=Edit Pattern
+patternExists=This pattern already exists in the Exceptions list.
diff --git a/src/skin/icon-enlarge-16.png b/src/skin/icon-enlarge-16.png
new file mode 100644
index 0000000..46a4b05
Binary files /dev/null and b/src/skin/icon-enlarge-16.png differ
diff --git a/src/skin/icon-enlarge-24.png b/src/skin/icon-enlarge-24.png
new file mode 100644
index 0000000..32b2846
Binary files /dev/null and b/src/skin/icon-enlarge-24.png differ
diff --git a/src/skin/icon-reduce-16.png b/src/skin/icon-reduce-16.png
new file mode 100644
index 0000000..e3841ee
Binary files /dev/null and b/src/skin/icon-reduce-16.png differ
diff --git a/src/skin/icon-reduce-24.png b/src/skin/icon-reduce-24.png
new file mode 100644
index 0000000..cff1f1a
Binary files /dev/null and b/src/skin/icon-reduce-24.png differ
diff --git a/src/skin/toolbar.css b/src/skin/toolbar.css
new file mode 100644
index 0000000..f9e05fc
--- /dev/null
+++ b/src/skin/toolbar.css
@@ -0,0 +1,15 @@
+#nosquint-button-reduce {
+ list-style-image: url("chrome://nosquint/skin/icon-reduce-24.png");
+}
+
+toolbar[iconsize="small"] #nosquint-button-reduce {
+ list-style-image: url("chrome://nosquint/skin/icon-reduce-16.png");
+}
+
+#nosquint-button-enlarge {
+ list-style-image: url("chrome://nosquint/skin/icon-enlarge-24.png");
+}
+
+toolbar[iconsize="small"] #nosquint-button-enlarge {
+ list-style-image: url("chrome://nosquint/skin/icon-enlarge-16.png");
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/nosquint.git
More information about the Pkg-mozext-commits
mailing list