[Pkg-mozext-commits] [nosquint] 06/47: Import of 1.91.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 e6b6600ed61c9726c730c5c87e85cc4b0afc752d
Author: Jason Tackaberry <tack at urandom.ca>
Date:   Fri Jan 13 19:41:13 2012 -0500

    Import of 1.91.0 release into git
---
 src/content/globalprefs.js              | 213 +++++++++++++
 src/content/globalprefs.xul             | 146 +++++++++
 src/content/init.js                     |  57 +++-
 src/content/nosquint.js                 | 515 +++++++++++++++++++++++++-------
 src/content/overlay.xul                 |  97 +++++-
 src/content/siteprefs.js                |  74 +++++
 src/content/siteprefs.xul               |  66 ++++
 src/content/testinit.js                 |  26 ++
 src/content/two-level-tlds              |  22 ++
 src/defaults/preferences/nosquint.js    |   1 +
 src/install.rdf                         |  46 +--
 src/locale/en-US/globalprefs.dtd        |  36 +++
 src/locale/en-US/globalprefs.properties |   3 +
 src/locale/en-US/help.html              |  78 +++--
 src/locale/en-US/overlay.dtd            |  10 +-
 src/locale/en-US/overlay.properties     |   5 +
 src/locale/en-US/siteprefs.dtd          |   5 +
 src/locale/en-US/siteprefs.properties   |   1 +
 src/skin/icon-enlarge-16.png            | Bin 961 -> 652 bytes
 src/skin/icon-enlarge-24.png            | Bin 1479 -> 1281 bytes
 src/skin/icon-reduce-16.png             | Bin 673 -> 654 bytes
 src/skin/icon-reduce-24.png             | Bin 697 -> 1233 bytes
 22 files changed, 1211 insertions(+), 190 deletions(-)

diff --git a/src/content/globalprefs.js b/src/content/globalprefs.js
new file mode 100644
index 0000000..80d7ae3
--- /dev/null
+++ b/src/content/globalprefs.js
@@ -0,0 +1,213 @@
+var NoSquintPrefs = {
+    prefs: null,
+    site: null,
+    level: null,
+    NoSquint: null,
+
+    init: function(doc, dialog) {
+        NoSquintPrefs.doc = doc;
+        NoSquintPrefs.dialog = dialog;
+        if (window.arguments) {
+            NoSquintPrefs.site = window.arguments[0];
+            NoSquintPrefs.level = window.arguments[1];
+            NoSquintPrefs.url = window.arguments[2];
+            NoSquintPrefs.NoSquint = window.arguments[3];
+            NoSquintPrefs.NoSquint.globalDialog = this;
+            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") ? 0 : 1;
+        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");
+        forget_cb.checked = (months != 0);
+        if (months)
+            doc.getElementById("siteForget-menu").value = months;
+        forget_cb.addEventListener("CheckboxStateChange", NoSquintPrefs.forgetMonthsChecked, false);
+        NoSquintPrefs.forgetMonthsChecked();
+
+        doc.getElementById('primaryZoomMethod-menu').value = NoSquintPrefs.prefs.getBoolPref("fullZoomPrimary") ? "full" : "text";
+
+        NoSquintPrefs.sitesRadioSelect();
+        NoSquintPrefs.parseExceptions();
+        NoSquintPrefs.excListSelect();
+    },
+
+    parseExceptions: function() {
+        var exstr = NoSquintPrefs.prefs.getCharPref("exceptions");
+        // Trim whitespace and split on space.
+        var 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 == '');
+    },
+
+    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;
+    },
+
+    buttonCopyFromURL: function() {
+        var pattern = NoSquintPrefs.doc.getElementById("pattern");
+        pattern.value = NoSquintPrefs.url;
+        NoSquintPrefs.textPatternChange();
+    },
+
+    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;
+        if (!doc)
+            return;
+        if (!NoSquintPrefs.url)
+            doc.getElementById("copyURL-button").style.display = "none";
+        var disabled = doc.getElementById("rememberSites").selectedIndex == 1;
+        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);
+        }
+    },
+
+    help: function() {
+        window.openDialog("chrome://nosquint/content/help.xul", "NoSquint Help", "chrome");
+    },
+
+    close: function() {
+        var doc = NoSquintPrefs.doc;
+
+        var full_zoom_primary = doc.getElementById("primaryZoomMethod-menu").value == "full";
+        var force_zoom = NoSquintPrefs.prefs.getBoolPref("fullZoomPrimary") != full_zoom_primary;
+        NoSquintPrefs.prefs.setBoolPref("fullZoomPrimary", full_zoom_primary);
+
+        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 == 1 ? 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;
+
+        NoSquintPrefs.NoSquint.globalDialog = null;
+        if (force_zoom)
+            NoSquintPrefs.NoSquint.queueZoomAll();
+    },
+
+    cancel: function() {
+        if (NoSquintPrefs.NoSquint)
+            NoSquintPrefs.NoSquint.globalDialog = null;
+    }
+
+};
diff --git a/src/content/globalprefs.xul b/src/content/globalprefs.xul
new file mode 100644
index 0000000..7cc8837
--- /dev/null
+++ b/src/content/globalprefs.xul
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css"  type="text/css"?>
+<?xml-stylesheet href="chrome://nosquint/content/prefs.css"  type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://nosquint/locale/globalprefs.dtd">
+
+<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="help,accept,cancel" 
+        ondialogaccept="NoSquintPrefs.close()"
+        ondialogcancel="NoSquintPrefs.cancel()"
+        ondialoghelp="NoSquintPrefs.help()"
+        id="nosquint-prefs-dialog"
+        persist="screenX screenY"
+        onload="NoSquintPrefs.init(document, this)">
+
+    <script src="globalprefs.js" />
+
+    <stringbundleset id="stringbundleset">
+        <stringbundle id="nosquint-prefs-bundle" src="chrome://nosquint/locale/globalprefs.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 />
+                            </columns>
+                            <rows>
+                                <row align="center">
+                                    <hbox>
+                                        <spacer flex="1" />
+                                        <label>&ns.pref.general.primaryMethod.label;:</label>
+                                    </hbox>
+                                    <menulist id="primaryZoomMethod-menu">
+                                        <menupopup>
+                                            <menuitem value="full" label="&ns.pref.general.primaryMethod.full;" 
+                                                      selected="true"/>
+                                            <menuitem value="text" label="&ns.pref.general.primaryMethod.text;"/>
+                                        </menupopup>
+                                    </menulist>
+                                </row>
+
+                                <row align="center">
+                                    <label>&ns.pref.general.level.label;:</label>
+                                    <hbox align="center">
+                                        <textbox id="defaultZoomLevel" size="2" type="number" min="40" 
+                                                 max="300" increment="5" />
+                                        <label class="percent">%</label>
+                                    </hbox>
+                                </row>
+
+                                <row align="center">
+                                    <hbox>
+                                        <spacer flex="1" />
+                                        <label>&ns.pref.general.increment.label;:</label>
+                                    </hbox>
+                                    <hbox align="center">
+                                        <textbox id="zoomIncrement" size="2" type="number" min="1" 
+                                                 max="100" increment="1" />
+                                        <label class="percent">%</label>
+                                    </hbox>
+                                </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.remember.label;" />
+                            <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>
+                            <radio label="&ns.pref.site.noRemember.label;" />
+                        </radiogroup>
+                    </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>
+
+                    <separator />
+
+                <listbox id="exceptionsList" flex="1" seltype="multiple" rows="5" 
+                         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/init.js b/src/content/init.js
index 0ee6c4a..b54a412 100644
--- a/src/content/init.js
+++ b/src/content/init.js
@@ -1,27 +1,64 @@
 window.addEventListener("load", NoSquint.init, false); 
 window.addEventListener("unload", NoSquint.destroy, false); 
 
+ZoomManager._nosquintPendingZoom = null;
+ZoomManager._nosquintOrigZoomGetter = ZoomManager.__lookupGetter__('zoom');
+ZoomManager._nosquintOrigZoomSetter = ZoomManager.__lookupSetter__('zoom');
 
-ZoomManager.prototype.getInstance().reset = function() {
-    if (ZoomManager.prototype.getInstance().textZoom == NoSquint.defaultZoomLevel)
+ZoomManager.__defineSetter__('zoom', function(value) {
+    /* XXX: Horrid hack, makes baby Jesus cry.
+     *
+     * Problem: on location change and tab change, some internal FF mechanism
+     * sets zoom to some stored value (on a per site basis).  NoSquint
+     * must fully override this mechanism, as we implement our own approach.
+     *
+     * Solution: rather than update zoom on the current browser immediately,
+     * we queue it with a timer, and give the location/tab change handlers
+     * in nosquint.js a chance to abort the queued zoom via
+     * NoSquint.abortPendingZoomManager()
+     */
+    ZoomManager._nosquintPendingZoom = value;
+    if (NoSquint.zoomManagerTimeout == false) {
+        dump("[nosquint] EATING ZOOM REQUEST: "+ value + "\n");
+        NoSquint.zoomManagerTimeout = null;
         return;
+    }
+    NoSquint.zoomManagerTimeout = setTimeout(function() { 
+        dump("[nosquint] setting zoom through ZoomManager: " + value + "\n");
+        ZoomManager._nosquintOrigZoomSetter(value);
+        NoSquint.zoomManagerTimeout = null;
+        ZoomManager._nosquintPendingZoom = null;
+    }, 0);
+});
 
-    ZoomManager.prototype.getInstance().textZoom = NoSquint.defaultZoomLevel;
+
+ZoomManager.__defineGetter__('zoom', function() {
+    if (ZoomManager._nosquintPendingZoom != null)
+        return ZoomManager._nosquintPendingZoom;
+    return ZoomManager._nosquintOrigZoomGetter();
+});
+
+ZoomManager.enlarge = function() {
+    // FIXME: do we want to update any other tabs of pages in this site?
+    getBrowser().mCurrentBrowser.markupDocumentViewer.fullZoom += (NoSquint.zoomIncrement / 100.0);
     NoSquint.saveCurrentZoom();
     NoSquint.updateStatus();
 }
 
-ZoomManager.prototype.getInstance().enlarge = function() {
-    // FIXME: do we want to update any other tabs of pages in this site?
-    ZoomManager.prototype.getInstance().textZoom += NoSquint.zoomIncrement;
+ZoomManager.reduce = function() {
+    getBrowser().mCurrentBrowser.markupDocumentViewer.fullZoom -= (NoSquint.zoomIncrement / 100.0);
     NoSquint.saveCurrentZoom();
     NoSquint.updateStatus();
-    dump("Enlarge text\n");
 }
 
-ZoomManager.prototype.getInstance().reduce = function() {
-    ZoomManager.prototype.getInstance().textZoom -= NoSquint.zoomIncrement;
+ZoomManager.reset = function() {
+    var viewer = getBrowser().mCurrentBrowser.markupDocumentViewer;
+    var page_zoom_default = NoSquint.getZoomDefaults()[1];
+    if (Math.round(viewer.fullZoom * 100.0) == page_zoom_default)
+        // Page zoom is already at default.
+        return false;
+    viewer.fullZoom = page_zoom_default / 100.0;
     NoSquint.saveCurrentZoom();
     NoSquint.updateStatus();
-    dump("Reduce text\n");
+    return true;
 }
diff --git a/src/content/nosquint.js b/src/content/nosquint.js
index 73ccb9c..670cc3a 100644
--- a/src/content/nosquint.js
+++ b/src/content/nosquint.js
@@ -1,3 +1,5 @@
+// chrome://browser/content/browser.xul
+// open dialogs will raise if already open
 function readLines(aURL) {
   var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                   .getService(Components.interfaces.nsIIOService);
@@ -13,18 +15,25 @@ function readLines(aURL) {
   return str.split("\n");
 } 
 
+function debug(msg) {
+    dump("[nosquint] " + msg + "\n");
+}
+
 var NoSquint = {
 
-    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
+    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,
+    zoomManagerTimeout: null,
+    globalDialog: null,
+    siteDialog: null,
 
     /* Prefs */
 
@@ -38,11 +47,15 @@ var NoSquint = {
     wheelZoomEnabled: false,
     hideStatus: false,
     forgetMonths: 6,
+    fullZoomPrimary: false,
 
 
     init: function() {
+        debug("start init");
+        NoSquint.updateZoomMenu();
         if (NoSquint.initialized)
             return;
+        NoSquint.initialized = true;
 
         var t0 = new Date().getTime();
 
@@ -71,29 +84,27 @@ var NoSquint = {
                 NoSquint.TLDs[lines[i]] = true;
         }
 
-
         NoSquint.initPrefs();
 
         window.addEventListener("DOMMouseScroll", NoSquint.handleScrollWheel, false); 
         gBrowser.tabContainer.addEventListener("TabOpen", NoSquint.handleNewTab, false);
         gBrowser.tabContainer.addEventListener("TabClose", NoSquint.handleCloseTab, false);
+        gBrowser.tabContainer.addEventListener("TabSelect", NoSquint.handleTabChanged, 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");
+        debug("initialization took " + (t1-t0) + " ms");
     },
 
     destroy: function() {
-        var pbi = NoSquint.prefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
-        pbi.removeObserver("", this);
-        pbi = NoSquint.mousePrefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
-        pbi.removeObserver("", this);
+        NoSquint.prefs.removeObserver("", NoSquint);
+        NoSquint.mousePrefs.removeObserver("", NoSquint);
 
-        if (NoSquint.sitesDirty)
+        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
@@ -102,13 +113,248 @@ var NoSquint = {
         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);
+            NoSquint.mousePrefs.setIntPref("action", 5);
 
         gBrowser.tabContainer.removeEventListener("TabOpen", NoSquint.handleNewTab, false);
         gBrowser.tabContainer.removeEventListener("TabClose", NoSquint.handleCloseTab, false);
         gBrowser.tabContainer.removeEventListener("TabSelect", NoSquint.handleTabChanged, false);
     },
 
+    updateZoomMenu: function() {
+        var bundle = document.getElementById("nosquint-overlay-bundle");
+        var popup = document.getElementById('viewFullZoomMenu').childNodes[0];
+        var full_zoom_primary = NoSquint.fullZoomPrimary;
+        var toggle_zoom = null;
+
+        if (!NoSquint.initialized) {
+            for (var i = 0; i < popup.childNodes.length; i++) {
+                var child = popup.childNodes[i];
+                if (child.id == 'toggle_zoom')
+                    toggle_zoom = child;
+                if (child.nodeName != 'menuitem' || (child.command != 'cmd_fullZoomEnlarge' && 
+                    child.command != 'cmd_fullZoomReduce'))
+                    continue;
+
+                var icon = document.defaultView.getComputedStyle(child, null).getPropertyValue('list-style-image');
+                var enlarge = child.command == 'cmd_fullZoomEnlarge';
+                var item = document.createElement('menuitem');
+                var suffix = "noSquint" + (enlarge ? "Enlarge" : "Reduce") + "Secondary";
+                item.setAttribute("command",  "cmd_" + suffix);
+                item.setAttribute("key",  "key_" + suffix);
+                item.style.listStyleImage = icon;
+                popup.insertBefore(item, popup.childNodes[i + 2]);
+                if (0 && icon) {
+                    // Override toolbar icon to use platform-native enlarge icon
+                    var button = document.getElementById("nosquint-button-" + (enlarge ? "enlarge" : "reduce"));
+                    if (button)
+                        button.style.listStyleImage = icon.replace(/menu/, 'toolbar');
+                    if (enlarge) {
+                        document.getElementById('nosquint-status').src =  icon.replace(/url\((.*)\)/, "$1");
+                    }
+                }
+            }
+            var item = document.createElement('menuitem');
+            item.setAttribute('command', 'cmd_noSquintPrefs');
+            item.setAttribute('label', bundle.getString('zoomMenuSettings'));
+            if (toggle_zoom)
+                popup.replaceChild(item, toggle_zoom);
+            else {
+                popup.appendChild(document.createElement('menuseparator'));
+                popup.appendChild(item);
+            }
+        }
+
+        for (var i = 0; i < popup.childNodes.length; i++) {
+            var child = popup.childNodes[i];
+            if (child.nodeName != 'menuitem')
+                continue;
+            var command = child.getAttribute('command');
+            if (command == "cmd_fullZoomEnlarge")
+                child.setAttribute('label', bundle.getString('zoomMenuIn' + (full_zoom_primary ? "Full" : "Text")));
+            else if (command == "cmd_noSquintEnlargeSecondary")
+                child.setAttribute('label', bundle.getString('zoomMenuIn' + (full_zoom_primary ? "Text" : "Full")));
+            if (command == "cmd_fullZoomReduce")
+                child.setAttribute('label', bundle.getString('zoomMenuOut' + (full_zoom_primary ? "Full" : "Text")));
+            else if (command == "cmd_noSquintReduceSecondary")
+                child.setAttribute('label', bundle.getString('zoomMenuOut' + (full_zoom_primary ? "Text" : "Full")));
+        }
+    },
+
+    cmdEnlargePrimary: function() {
+        NoSquint.fullZoomPrimary ? NoSquint.enlargeFullZoom() : NoSquint.enlargeTextZoom();
+    },
+    cmdReducePrimary: function() {
+        NoSquint.fullZoomPrimary ? NoSquint.reduceFullZoom() : NoSquint.reduceTextZoom();
+    },
+    cmdEnlargeSecondary: function() {
+        NoSquint.fullZoomPrimary ? NoSquint.enlargeTextZoom() : NoSquint.enlargeFullZoom();
+    },
+    cmdReduceSecondary: function() {
+        NoSquint.fullZoomPrimary ? NoSquint.reduceTextZoom() : NoSquint.reduceFullZoom();
+    },
+    cmdReset: function() {
+        var text_zoom_default = NoSquint.getZoomDefaults()[0];
+        var viewer = getBrowser().mCurrentBrowser.markupDocumentViewer;
+        if (Math.round(viewer.textZoom * 100.0) != text_zoom_default)
+            viewer.textZoom = text_zoom_default / 100.0;
+        if (!ZoomManager.reset()) {
+            NoSquint.saveCurrentZoom();
+            NoSquint.updateStatus();
+        }
+    },
+    buttonEnlarge: function(event) {
+        event.shiftKey ? NoSquint.cmdEnlargeSecondary() : NoSquint.cmdEnlargePrimary();
+    },
+    buttonReduce: function(event) {
+        event.shiftKey ? NoSquint.cmdReduceSecondary() : NoSquint.cmdReducePrimary();
+    },
+    enlargeTextZoom: function() {
+        getBrowser().mCurrentBrowser.markupDocumentViewer.textZoom += (NoSquint.zoomIncrement / 100.0);
+        NoSquint.saveCurrentZoom();
+        NoSquint.updateStatus();
+    },
+    reduceTextZoom: function() {
+        getBrowser().mCurrentBrowser.markupDocumentViewer.textZoom -= (NoSquint.zoomIncrement / 100.0);
+        NoSquint.saveCurrentZoom();
+        NoSquint.updateStatus();
+    },
+    enlargeFullZoom: function() {
+        ZoomManager.enlarge();
+    },
+    reduceFullZoom: function() {
+        ZoomManager.reduce();
+    },
+
+    popupItemSelect: function(event) {
+        var item = event.target;
+        var label = item.label;
+        if (label.search(/%$/) != -1) {
+            var level = parseInt(label.replace(/%/, ''));
+            var browser = gBrowser.selectedBrowser;
+            if (item.getAttribute('name') == 'text')
+                NoSquint.zoom(browser, level, false);
+            else
+                NoSquint.zoom(browser, false, level);
+            NoSquint.saveCurrentZoom();
+        }
+    },
+
+    statusPanelClick: function(event) {
+        if (event.button == 0)
+            return NoSquint.openSitePrefsDialog();
+
+        var popup = document.getElementById("nosquint-status-popup");
+        var browser = gBrowser.selectedBrowser;
+
+        // Hide all but the last menuitem if there is no site
+        for (var i = 0; i < popup.childNodes.length - 1; i++)
+            popup.childNodes[i].style.display = browser._noSquintSite ? '' : 'none';
+
+        var popup_text = document.getElementById("nosquint-status-popup-text");
+        var popup_full = document.getElementById("nosquint-status-popup-full");
+
+        var current_text = Math.round(browser.markupDocumentViewer.textZoom * 100);
+        var current_full = Math.round(browser.markupDocumentViewer.fullZoom * 100);
+
+        popup.childNodes[0].label = browser._noSquintSite;
+
+        for (var i = 0; i < popup_text.childNodes.length; i++) {
+            var child = popup_text.childNodes[i];
+            child.setAttribute('checked', child.label.replace(/%/, '') == current_text);
+        }
+        for (var i = 0; i < popup_full.childNodes.length; i++) {
+            var child = popup_full.childNodes[i];
+            child.setAttribute('checked', child.label.replace(/%/, '') == current_full);
+        }
+
+        popup.openPopupAtScreen(event.screenX, event.screenY, true);
+    },
+
+    openSitePrefsDialog: function() {
+        var browser = gBrowser.selectedBrowser;
+        var site = NoSquint.getSiteFromURI(browser.currentURI);
+        if (!site)
+            return;
+        if (NoSquint.siteDialog) {
+            NoSquint.siteDialog.setValues(browser, site);
+            return NoSquint.siteDialog.dialog.focus();
+        }
+        if (NoSquint.sitesDirty)
+            NoSquint._saveSiteListTimer();
+        window.openDialog("chrome://nosquint/content/siteprefs.xul", "NoSquint Site Settings", "chrome", 
+                          NoSquint, browser, site);
+    },
+
+
+    openGlobalPrefsDialog: function() {
+        if (NoSquint.globalDialog)
+            return NoSquint.globalDialog.dialog.focus();
+
+        if (NoSquint.sitesDirty)
+            NoSquint._saveSiteListTimer();
+        var browser = gBrowser.selectedBrowser;
+        var site = NoSquint.getSiteFromURI(browser.currentURI);
+        var level = NoSquint.getLevelForSite(site)[0] || "default";
+        var url = browser.currentURI.asciiHost + browser.currentURI.path;
+        window.openDialog("chrome://nosquint/content/globalprefs.xul", "NoSquint Settings", "chrome", 
+                          site, level, url, NoSquint);
+    },
+
+
+    handleScrollWheel: function(event) {
+        if (!event.ctrlKey || !NoSquint.wheelZoomEnabled)
+            return;
+        var browser = gBrowser.selectedBrowser;
+        var text = full = false;
+        var increment = NoSquint.zoomIncrement * (event.detail < 0 ? -1 : 1);
+        if (NoSquint.fullZoomPrimary && !event.shiftKey || !NoSquint.fullZoomPrimary && event.shiftKey)
+            full = (browser.markupDocumentViewer.fullZoom * 100) + increment;
+        else
+            text = (browser.markupDocumentViewer.textZoom * 100) + increment;
+        var current = Math.round(browser.markupDocumentViewer.textZoom * 100);
+        NoSquint.zoom(browser, text, full);
+        NoSquint.saveCurrentZoom();
+
+        event.stopPropagation();
+        event.preventDefault();
+    },
+
+
+    handleTabChanged: function(event) {
+        if (gBrowser.selectedBrowser._noSquintified) {
+            // ZoomManager.fullZoom was set somewhere internally in FF.  Abort
+            // the pending zoom.
+            NoSquint.abortPendingZoomManager();
+            NoSquint.updateStatus();
+        }
+    },
+
+    handleNewTab: function(event) {
+        NoSquint.attach(event.target.linkedBrowser);
+    },
+
+    handleCloseTab: function(event) {
+        var browser = event.target.linkedBrowser;
+        browser.removeProgressListener(browser._noSquintListener);
+    },
+
+    /* In init.js, we hook the setter for ZoomManager.zoom to have it
+     * queue the requested zoom rather than apply it immediately.  This
+     * gives handleTabChanged() above and our custom ProgressListener an
+     * opportunity to abort the pending zoom, in order to fully bypass
+     * FF's new internal per-site zoom mechanism.
+     */
+    abortPendingZoomManager: function() {
+        debug("aborting pending ZoomManager zoom");
+        if (NoSquint.zoomManagerTimeout != null) {
+            clearTimeout(NoSquint.zoomManagerTimeout);
+            NoSquint.zoomManagerTimeout = null;
+            ZoomManager._nosquintPendingZoom = null;
+        } else
+            NoSquint.zoomManagerTimeout = false;
+    },
+
+
     getBaseDomainFromHost: function(host) {
         if (host.match(/^[\d.]+$/) != null)
             // IP address.
@@ -177,7 +423,9 @@ var NoSquint = {
 
 
     getSiteFromURI: function(URI) {
-        //var t0 = new Date().getTime();
+        var t0 = new Date().getTime();
+        if (!URI)
+            return null;
 
         var uri_host = URI.asciiHost;
         var uri_path = URI.path;
@@ -203,13 +451,13 @@ var NoSquint = {
             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);
+            var site_host = m1[1].replace(new RegExp(re_host), sub_host);
+            var site_path = m2[1].replace(new RegExp(re_path), sub_path);
             match = site_host + site_path;
             match_weight = cur_weight;
         }
-        //var t1 = new Date().getTime();
-        //dump("NoSquint: getSiteFromURI took " + (t1-t0) + " ms\n");
+        var t1 = new Date().getTime();
+        debug("getSiteFromURI took " + (t1-t0) + " ms");
 
         if (match)
             return match;
@@ -217,38 +465,11 @@ var NoSquint = {
     },
 
 
-    handleScrollWheel: function(event) {
-        if (!event.ctrlKey || !NoSquint.wheelZoomEnabled)
-            return;
-        //alert(event.detail + ' -- target -- ' + event.target.nodeName);
-        if (event.detail < 0)
-            ZoomManager.prototype.getInstance().reduce();
-        else if (event.detail > 0)
-            ZoomManager.prototype.getInstance().enlarge();
-
-        event.stopPropagation();
-        event.preventDefault();
-    },
-
-
-    handleTabChanged: function(event) {
-        if (gBrowser.selectedBrowser._noSquintified)
-            NoSquint.updateStatus();
-    },
-
-    handleNewTab: function(event) {
-        NoSquint.attach(event.target.linkedBrowser);
-    },
-
-    handleCloseTab: function(event) {
-        var browser = event.target.linkedBrowser;
-        browser.removeProgressListener(browser._noSquintListener);
-    },
-
     attach: function(browser) {
         var listener = new ProgressListener(browser);
         browser.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
         browser._noSquintListener = listener;
+        NoSquint.zoom(browser, null, null);
         //alert("Create new listener");
 
         /* Sometimes the onLocationChange handler of the ProgressListener will
@@ -258,90 +479,121 @@ var NoSquint = {
          * browser explicitly for this initial page, rather than rely on the
          * progress handler.
          */
-        setTimeout(function() { NoSquint.zoom(browser, null); }, 1);
+        // XXX: is this still needed (for iframes)?
+        //setTimeout(function() { NoSquint.zoom(browser, null); }, 1);
     },
     
     updateStatus: function() {
         if (NoSquint.hideStatus)
             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;
+        var text = Math.round(browser.markupDocumentViewer.textZoom * 100);
+        var full = Math.round(browser.markupDocumentViewer.fullZoom * 100);
+        var [ text_default, full_default ] = NoSquint.getZoomDefaults();
+
+        //text += (text == text_default) ? "% (default)" : "%";
+        //full += (full == full_default) ? "% (default)" : "%";
+
+        var e = document.getElementById('nosquint-status')
+        if (NoSquint.fullZoomPrimary)
+            e.label = full + "%" + (text == text_default ? "" : (" / " + text + "%"));
+        else
+            e.label = text + "%" + (full == full_default ? "" : (" / " + full + "%"));
+
+        var site = browser._noSquintSite ? browser._noSquintSite : "(none)";
+        document.getElementById("nosquint-status-tooltip-site").value = site;
+        document.getElementById("nosquint-status-tooltip-full").value = full + "%";
+        document.getElementById("nosquint-status-tooltip-text").value = text + "%";
     },
 
+    // Returns array [text_size, full_size]
     getLevelForSite: function(site) {
         if (!site)
-            return null;
+            return [null, null];
 
         if (NoSquint.sites[site])
-            return NoSquint.sites[site][0];
-        return null;
+            return [NoSquint.sites[site][0], NoSquint.sites[site][3]];
+        return [null, null];
+    },
+
+    getZoomDefaults: function() {
+        return [ NoSquint.fullZoomPrimary ? 100 : NoSquint.defaultZoomLevel,
+                 NoSquint.fullZoomPrimary ? NoSquint.defaultZoomLevel : 100 ];
     },
 
     getLevelForBrowser: function(browser) {
         if (!browser._noSquintSite)
             browser._noSquintSite = NoSquint.getSiteFromURI(browser.currentURI);
 
+        var [ text_default, full_default ] = NoSquint.getZoomDefaults();
+
         if (NoSquint.rememberSites) {
             var site = browser._noSquintSite;
-            var level = NoSquint.getLevelForSite(site);
-            if (level != null)
-                return level;
+            var [ text, full ] = NoSquint.getLevelForSite(site);
+            return [ text || text_default, full || full_default ];
         }
-        return NoSquint.defaultZoomLevel;
+        return [ text_default, full_default ];
     },
 
-    zoom: function(browser, level) {
-        if (!browser)
+
+    /* Zooms text and/or full zoom to the specified level.  If text or full is
+     * null, the default for browser is used.  If it is false, it is
+     * untouched.  Status bar is updated, but new level is NOT saved.
+     */
+    zoom: function(browser, text, full) {
+        if (!browser || (text == false && full == false))
             return;
-        if (level == null)
-            level = NoSquint.getLevelForBrowser(browser);
 
-        browser.markupDocumentViewer.textZoom = level / 100.0;
+        if (text == null || full == null) {
+            var [ site_text, site_full ] = NoSquint.getLevelForBrowser(browser);
+            if (text == null)
+                text = text || site_text;
+            if (full == null)
+                full = full || site_full;
+        }
+
+        debug("set zoom: text=" + text + ", full=" + full);
+        if (text != false)
+            browser.markupDocumentViewer.textZoom = text / 100.0;
+        if (full != false)
+            browser.markupDocumentViewer.fullZoom = full / 100.0;
+
         browser._noSquintified = true;
         if (browser == gBrowser.selectedBrowser)
             NoSquint.updateStatus();
     },
 
     zoomAll: function(attach) {
-        dump("NoSquint: zooming all tabs; attach listeners = " + attach + "\n");
+        debug("zooming all tabs; attach listeners = " + attach);
         for (var i = 0; i < gBrowser.browsers.length; i++) {
             var browser = gBrowser.browsers[i];
             if (browser._noSquintSite)
                 delete browser._noSquintSite;
-            NoSquint.zoom(browser, null);
+            NoSquint.zoom(browser, null, null);
             if (attach)
                 NoSquint.attach(browser);
         }
+        NoSquint.updateStatus();
     },
 
     queueZoomAll: function() {
-        dump("NoSquint: queuing zoom all\n");
         if (NoSquint.zoomAllTimer != null)
             clearTimeout(NoSquint.zoomAllTimer);
         NoSquint.zoomAllTimer = setTimeout(function() { NoSquint.zoomAll(false); }, 1);
     },
 
-    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);
-    },
-
-
     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);
+        var [ text, full ] = NoSquint.getLevelForBrowser(browser);
+        NoSquint.zoom(browser, text, full);
+        if (NoSquint.siteDialog && NoSquint.siteDialog.browser == browser)
+            NoSquint.siteDialog.setValues(browser, site);
+        // XXX: is this still needed (for iframes) in ff3?
+        //setTimeout(function() { NoSquint.zoom(browser, NoSquint.getLevelForBrowser(browser)); }, 1);
     },
 
 
@@ -354,13 +606,13 @@ var NoSquint = {
         for (var site in NoSquint.sites) {
             if (!NoSquint.sites[site])
                 continue
-            var [level, timestamp, counter] = NoSquint.sites[site];
+            var [text, timestamp, counter, full] = 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");
+            debug("prune check: " + site + ", age=" + Math.round(age/1000/60/60/24) + 
+                 " days, prune=" + prune);
         }
         if (remove.length) {
             for (var i = 0; i < remove.length; i++)
@@ -382,27 +634,32 @@ var NoSquint = {
             return;
 
         var browser = gBrowser.selectedBrowser;
-        var current_level = Math.round(browser.markupDocumentViewer.textZoom * 100);
-        NoSquint.updateSiteList(browser, current_level);
+        var text = Math.round(browser.markupDocumentViewer.textZoom * 100);
+        var full = Math.round(browser.markupDocumentViewer.fullZoom * 100);
+        NoSquint.updateSiteList(browser, [text, full]);
     },
 
-    updateSiteList: function(site_or_browser, level, update_timestamp) {
+    updateSiteList: function(site_or_browser, levels, 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])
+            if (!levels && !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 (levels) {
+            var [ text_default, full_default ] = NoSquint.getZoomDefaults();
+            var [ text, full ] = levels;
+            [ text, full ] = [ text == text_default ? 0 : text, full == full_default ? 0 : full ];
+
+            if (!text && !full) {
                 if (!NoSquint.sites[site])
                     // No settings for this site, nothing to do.
                     return;
@@ -410,9 +667,11 @@ var NoSquint = {
                 delete NoSquint.sites[site];
             } else {
                 if (!NoSquint.sites[site])
-                    NoSquint.sites[site] = [level, new Date().getTime(), 1];
-                else
-                    NoSquint.sites[site][0] = level;
+                    NoSquint.sites[site] = [text, new Date().getTime(), 1, full];
+                else {
+                    NoSquint.sites[site][0] = text;
+                    NoSquint.sites[site][3] = full;
+                }
                 // TODO: go through current tabs and resize tabs for this site
             }
             NoSquint.saveSiteList();
@@ -449,8 +708,8 @@ var NoSquint = {
         for (var site in NoSquint.sites) {
             if (!NoSquint.sites[site])
                 continue
-            var [level, timestamp, counter] = NoSquint.sites[site];
-            sites.push(site + "=" + level + "," + timestamp + "," + counter);
+            var [text, timestamp, counter, full] = NoSquint.sites[site];
+            sites.push(site + "=" + text + "," + timestamp + "," + counter + "," + full);
         }
         var siteList = sites.join(" ");
         /* It's a precondition that the site list has changed, so when we set
@@ -460,7 +719,7 @@ var NoSquint = {
          */
         NoSquint.ignoreNextSitesChange = true;
         NoSquint.prefs.setCharPref("sites", siteList);
-        dump("NoSquint: Sites save took: " + (new Date().getTime() - t0) + "ms\n");
+        debug("sites save took: " + (new Date().getTime() - t0) + "ms");
         clearTimeout(NoSquint.saveTimer);
         NoSquint.saveTimer = null;
         NoSquint.sitesDirty = false;
@@ -491,16 +750,18 @@ var NoSquint = {
         } catch (err) {} 
 
         var prefs = [
-            "zoomIncrement", "wheelZoomEnabled", "zoomIncrement", "hideStatus", "zoomlevel",
-            "sitesSaveDelay", "rememberSites", "exceptions", "sites", "forgetMonths"
+            "zoomIncrement", "wheelZoomEnabled", "zoomIncrement", "hideStatus", "zoomlevel", "action",
+            "sitesSaveDelay", "rememberSites", "exceptions", "sites", "forgetMonths", "fullZoomPrimary"
         ];
         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);
+    
+        
+        NoSquint.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
+        NoSquint.prefs.addObserver("", NoSquint, false);
+        NoSquint.mousePrefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
+        NoSquint.mousePrefs.addObserver("", NoSquint, false);
     },
 
     observe: function(subject, topic, data) {
@@ -521,7 +782,7 @@ var NoSquint = {
                  * the hook for wheel zoom.
                  */
                 var action = NoSquint.mousePrefs.getIntPref("action");
-                if (action == 3) {
+                if (action == 3 || action == 5) {
                     NoSquint.prefs.setBoolPref("wheelZoomEnabled", true);
                     //alert("Setting wheelZoomEnabled=true, action=0 because action == 3");
                     NoSquint.mousePrefs.setIntPref("action", 0);
@@ -552,15 +813,26 @@ var NoSquint = {
                 NoSquint.pruneSites();
                 break;
 
+            case "fullZoomPrimary":
+                NoSquint.fullZoomPrimary = NoSquint.prefs.getBoolPref("fullZoomPrimary");
+                NoSquint.updateZoomMenu();
+                NoSquint.queueZoomAll();
+                break;
+
             case "hideStatus":
                 NoSquint.hideStatus = NoSquint.prefs.getBoolPref("hideStatus");
                 document.getElementById("nosquint-status").hidden = NoSquint.hideStatus;
+                if (!NoSquint.hideStatus)
+                    NoSquint.handleTabChanged();
+
+                /*
                 if (NoSquint.hideStatus)
                     gBrowser.tabContainer.removeEventListener("TabSelect", NoSquint.handleTabChanged, false);
                 else {
                     gBrowser.tabContainer.addEventListener("TabSelect", NoSquint.handleTabChanged, false);
                     NoSquint.handleTabChanged();
                 }
+                */
                 break;
 
             case "rememberSites":
@@ -588,6 +860,7 @@ var NoSquint = {
                  * malformed entries gracefully (in case the user edits them manually
                  * and screws up).
                  */
+                // TODO: look at nsIContentPrefService
                 if (NoSquint.ignoreNextSitesChange) {
                     NoSquint.ignoreNextSitesChange = false;
                     break;
@@ -604,11 +877,13 @@ var NoSquint = {
                         continue; // malformed
                     var [site, info] = parts;
                     var parts = info.split(',');
-                    NoSquint.sites[site] = [parseInt(parts[0]) || NoSquint.defaultZoomLevel, now, 1];
+                    NoSquint.sites[site] = [parseInt(parts[0]) || 0, now, 1, 0];
                     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 (parts.length > 3)
+                        NoSquint.sites[site][3] = parseInt(parts[3]) || 0;
 
                 }
                 if (NoSquint.sitesDirty) {
@@ -631,7 +906,7 @@ var NoSquint = {
 // Listener used to receive notifications when a new URI is about to be loaded.
 function ProgressListener(browser) {
     this.browser = browser;
-    this.lastURI = null;
+    this.update = false;
 }
 
 ProgressListener.prototype.QueryInterface = function(aIID) {
@@ -643,17 +918,25 @@ ProgressListener.prototype.QueryInterface = function(aIID) {
 }
 
 ProgressListener.prototype.onLocationChange = function(progress, request, uri) {
-    //alert("Location change: " + uri.spec + " -- old: " + this.lastURI);
-    /* 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 is called when it's confirmed a URL is loading (including reload).
+     * We set a flag here to update the zoom levels on the next state change
+     * rather than doing it immediately, because sometime between now and then
+     * firefox's internal full zoom gets reset, and we want to update full
+     * zoom after that happens (to override it, in effect).
      */
-    this.lastURI = uri.spec;
-    NoSquint.locationChanged(this.browser, uri);
+    debug("Location change: " + uri.spec);
+    this.update = true;
+    NoSquint.abortPendingZoomManager();
+    NoSquint.locationChanged(this.browser, this.browser.currentURI);
 }
 
-ProgressListener.prototype.onStateChange = function(progress) {
+ProgressListener.prototype.onStateChange = function(progress, request, state, status) {
+    /*
+    if (this.update) {
+        this.update = false;
+        NoSquint.locationChanged(this.browser, this.browser.currentURI);
+    }
+    */
     if (!progress.isLoadingDocument) {
         if (NoSquint.sitesDirty)
             NoSquint.saveSiteList();
diff --git a/src/content/overlay.xul b/src/content/overlay.xul
index de84ab1..fb0b1e7 100644
--- a/src/content/overlay.xul
+++ b/src/content/overlay.xul
@@ -6,28 +6,103 @@
     <script src="nosquint.js" />
     <script src="init.js" />
 
+    <stringbundleset id="stringbundleset">
+        <stringbundle id="nosquint-overlay-bundle" src="chrome://nosquint/locale/overlay.properties" />
+    </stringbundleset>
+
     <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();" />
+                           label="Zoom Out" tooltiptext="Zoom out"
+                           oncommand="NoSquint.buttonReduce(event);" />
             <toolbarbutton id="nosquint-button-enlarge" class="toolbarbutton-1"
-                           label="Enlarge Text" tooltiptext="Makes text larger for this site"
-                            oncommand="ZoomManager.prototype.getInstance().enlarge();" />
+                           label="Zoom In" tooltiptext="Zoom in"
+                           oncommand="NoSquint.buttonEnlarge(event);" />
         </toolbaritem>
     </toolbarpalette>
 
+    <keyset id="mainKeyset">
+        <key id="key_noSquintEnlargeSecondary" key="+" modifiers="control shift" 
+             command="cmd_noSquintEnlargeSecondary" />
+        <key id="key_noSquintReduceSecondary" key="_" modifiers="control shift" 
+             command="cmd_noSquintReduceSecondary" keytext="-" />
+    </keyset>
+
     <commandset id="mainCommandSet">
-        <command id="cmd_noSquintPrefs" oncommand="NoSquint.openPrefsDialog()" />
+        <command id="cmd_noSquintPrefs" oncommand="NoSquint.openGlobalPrefsDialog()" />
+        <command id="cmd_fullZoomEnlarge" oncommand="NoSquint.cmdEnlargePrimary()" />
+        <command id="cmd_fullZoomReduce" oncommand="NoSquint.cmdReducePrimary()" />
+        <command id="cmd_fullZoomReset" oncommand="NoSquint.cmdReset()" />
+        <command id="cmd_noSquintEnlargeSecondary" oncommand="NoSquint.cmdEnlargeSecondary()" />
+        <command id="cmd_noSquintReduceSecondary" oncommand="NoSquint.cmdReduceSecondary()" />
     </commandset>
 
-    <menupopup id="menu_ToolsPopup">
-        <menuitem id="nosquint-menuitem" label="&nosquint.label;" oncommand="NoSquint.openPrefsDialog()"
-                  insertafter="devToolsSeparator" />
-    </menupopup>
-
     <statusbar id="status-bar">
+        <tooltip id="nosquint-status-tooltip" orient="vertical" style="background-color: #33DD00;">
+            <grid>
+                <columns>
+                    <column />
+                    <column />
+                </columns>
+                <rows>
+                    <row>
+                        <hbox>
+                            <spacer flex="1" />
+                            <label value="&ns.tooltip.site.label;:" style="font-weight: bold" />
+                        </hbox>
+                        <label value="" id="nosquint-status-tooltip-site" />
+                    </row>
+                    <row>
+                        <hbox>
+                            <spacer flex="1" />
+                            <label value="&ns.tooltip.fullZoom.label;:" style="font-weight: bold" />
+                        </hbox>
+                        <label value="" id="nosquint-status-tooltip-full" />
+                    </row>
+                    <row>
+                        <hbox>
+                            <spacer flex="1" />
+                            <label value="&ns.tooltip.textZoom.label;:" style="font-weight: bold" />
+                        </hbox>
+                        <label value="" id="nosquint-status-tooltip-text" />
+                    </row>
+                </rows>
+            </grid>
+        </tooltip>
+
+        <menupopup id="nosquint-status-popup" oncommand="NoSquint.popupItemSelect(event)">
+            <menuitem id="nosquint-popup-site" label="Site" disabled="true" style="font-style: italic" />
+            <menu label="&ns.menu.fullZoom.label;">
+                <menupopup id="nosquint-status-popup-full">
+                    <menuitem type="radio" name="full" label="90%" />
+                    <menuitem type="radio" name="full" label="100%" />
+                    <menuitem type="radio" name="full" label="110%" />
+                    <menuitem type="radio" name="full" label="120%" />
+                    <menuitem type="radio" name="full" label="130%" />
+                    <menuitem type="radio" name="full" label="140%" />
+                    <menuitem type="radio" name="full" label="150%" />
+                </menupopup>
+            </menu>
+            <menu label="&ns.menu.textZoom.label;">
+                <menupopup id="nosquint-status-popup-text">
+                    <menuitem type="radio" name="text" label="90%" />
+                    <menuitem type="radio" name="text" label="100%" />
+                    <menuitem type="radio" name="text" label="110%" />
+                    <menuitem type="radio" name="text" label="120%" />
+                    <menuitem type="radio" name="text" label="130%" />
+                    <menuitem type="radio" name="text" label="140%" />
+                    <menuitem type="radio" name="text" label="150%" />
+                </menupopup>
+            </menu>
+            <menuitem label="&ns.menu.reset.label;" onclick="NoSquint.cmdReset()" />
+            <menuitem label="&ns.menu.siteSettings.label;" onclick="NoSquint.openSitePrefsDialog()" />
+            <menuseparator />
+            <menuitem label="&ns.menu.globalSettings.label;" onclick="NoSquint.openGlobalPrefsDialog()" />
+        </menupopup>
+
         <statusbarpanel class="statusbarpanel-iconic-text" id="nosquint-status" label="100%" 
-                        onclick="NoSquint.openPrefsDialog()" src="chrome://nosquint/skin/icon-enlarge-16.png" />
+                        onclick="NoSquint.statusPanelClick(event)" 
+                        src="chrome://nosquint/skin/icon-enlarge-16.png" 
+                        tooltip="nosquint-status-tooltip" />
     </statusbar>
 </overlay> 
diff --git a/src/content/siteprefs.js b/src/content/siteprefs.js
new file mode 100644
index 0000000..72928c9
--- /dev/null
+++ b/src/content/siteprefs.js
@@ -0,0 +1,74 @@
+var NoSquintSitePrefs = {
+    prefs: null,
+    browser: null,
+    NoSquint: null,
+    bundle: null,
+
+    init: function(doc, dialog) {
+        NoSquintSitePrefs.doc = doc;
+        NoSquintSitePrefs.dialog = dialog;
+        NoSquintSitePrefs.NoSquint = window.arguments[0];
+        NoSquintSitePrefs.prefs = NoSquintSitePrefs.NoSquint.prefs;
+        NoSquintSitePrefs.bundle = doc.getElementById('nosquint-prefs-bundle');
+        NoSquintSitePrefs.NoSquint.siteDialog = this;
+
+        doc.getElementById('full-zoom-level').onchange = function() { NoSquintSitePrefs.valueChange('full', this); }
+        doc.getElementById('text-zoom-level').onchange = function() { NoSquintSitePrefs.valueChange('text', this); }
+        NoSquintSitePrefs.setValues(window.arguments[1], window.arguments[2]);
+    },
+
+    setValues: function(browser, site) {
+        var doc = NoSquintSitePrefs.doc;
+        var [text, full] = NoSquintSitePrefs.NoSquint.getLevelForBrowser(browser);
+
+        NoSquintSitePrefs.browser = browser;
+        NoSquintSitePrefs.site = site;
+
+        doc.getElementById('text-zoom-slider').value = text;
+        doc.getElementById('full-zoom-slider').value = full;
+
+        var caption = doc.getElementById('site').childNodes[0];
+        caption.label = NoSquintSitePrefs.bundle.getString('settingsFor') + " " + site;
+
+    },
+
+    sliderChange: function(which, slider) {
+        var doc = NoSquintSitePrefs.doc;
+        slider.value = parseInt(slider.value / 5) * 5;
+        if (doc)
+            doc.getElementById(which + '-zoom-level').value = slider.value;
+        return 5;
+    },
+
+    valueChange: function(which, textbox) {
+        var doc = NoSquintSitePrefs.doc;
+        doc.getElementById(which + '-zoom-slider').value = textbox.value;
+    },
+
+    buttonUseDefault: function(which) {
+        var doc = NoSquintSitePrefs.doc;
+        var [text, full] = NoSquintSitePrefs.NoSquint.getZoomDefaults();
+        var input = doc.getElementById(which + '-zoom-level');
+        input.value = which == 'text' ? text : full;
+        input.onchange();
+    },
+
+
+    close: function() {
+        var doc = NoSquintSitePrefs.doc;
+        var browser = NoSquintSitePrefs.browser;
+        var [text_current, full_current] = NoSquintSitePrefs.NoSquint.getLevelForBrowser(browser);
+        var text = doc.getElementById('text-zoom-level').value;
+        var full = doc.getElementById('full-zoom-level').value;
+        if (text != text_current || full != full_current) {
+            NoSquintSitePrefs.NoSquint.zoom(browser, text, full);
+            NoSquintSitePrefs.NoSquint.saveCurrentZoom();
+        }
+        NoSquintSitePrefs.NoSquint.siteDialog = null;
+        NoSquintSitePrefs.NoSquint = null;
+    },
+
+    cancel: function() {
+        NoSquintSitePrefs.NoSquint.siteDialog = null;
+    }
+};
diff --git a/src/content/siteprefs.xul b/src/content/siteprefs.xul
new file mode 100644
index 0000000..3edbfef
--- /dev/null
+++ b/src/content/siteprefs.xul
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css"  type="text/css"?>
+<?xml-stylesheet href="chrome://nosquint/content/prefs.css"  type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://nosquint/locale/siteprefs.dtd">
+
+<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="NoSquintSitePrefs.close()"
+        ondialogcancel="NoSquintSitePrefs.cancel()"
+        id="nosquint-siteprefs-dialog"
+        persist="screenX screenY"
+        onload="NoSquintSitePrefs.init(document, this)">
+
+    <script src="siteprefs.js" />
+
+    <stringbundleset id="stringbundleset">
+        <stringbundle id="nosquint-prefs-bundle" src="chrome://nosquint/locale/siteprefs.properties" />
+    </stringbundleset>
+
+    <groupbox id="site">
+        <caption />
+        <grid id="siteZoom-box" flex="1">
+            <columns>
+                <column />
+                <column />
+                <column />
+                <column flex="1" />
+                <column />
+            </columns>
+            <rows>
+                <row align="center">
+                    <hbox>
+                        <spacer flex="1" />
+                        <label value="&ns.pref.fullZoom.label;:" />
+                    </hbox>
+                    <scale id="full-zoom-slider" min="40" increment="1" max="300" style="width:200px"
+                           onchange="NoSquintSitePrefs.sliderChange('full', this)"/>
+                    <hbox align="center">
+                        <textbox id="full-zoom-level" size="2" type="number" min="40" max="300" increment="5" />
+                        <label class="percent">%</label>
+                    </hbox>
+                    <spacer flex="1" />
+                    <button  label="&ns.pref.button.useDefault.label;"
+                             id="siteZoom-button" oncommand="NoSquintSitePrefs.buttonUseDefault('full')" />
+                </row>
+                <row align="center">
+                    <hbox>
+                        <spacer flex="1" />
+                        <label value="&ns.pref.textZoom.label;:" />
+                    </hbox>
+                    <scale id="text-zoom-slider" min="40" increment="1" max="300" 
+                           onchange="NoSquintSitePrefs.sliderChange('text', this)"/>
+                    <hbox align="center">
+                        <textbox id="text-zoom-level" size="2" type="number" min="40" max="300" increment="5"  />
+                        <label class="percent">%</label>
+                    </hbox>
+                    <spacer flex="1" />
+                    <button  label="&ns.pref.button.useDefault.label;"
+                             id="siteZoom-button" oncommand="NoSquintSitePrefs.buttonUseDefault('text')" />
+                </row>
+            </rows>
+        </grid>
+    </groupbox>
+</dialog>
diff --git a/src/content/testinit.js b/src/content/testinit.js
new file mode 100644
index 0000000..2e53a8c
--- /dev/null
+++ b/src/content/testinit.js
@@ -0,0 +1,26 @@
+var TestExtension = {
+    prefs: null,
+
+    init: function() {
+        var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(
+                          Components.interfaces.nsIPrefService);
+        TestExtension.prefs = prefs.getBranch("extensions.testextension.");
+        TestExtension.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
+        TestExtension.prefs.addObserver("", this, false);
+    },
+
+    destroy: function() {
+        try {
+            TestExtension.prefs.removeObserver("", this);
+        } catch (err) {
+            dump(err + "\n");
+        }
+    },
+
+    observe: function(subject, topic, data) {
+    },
+};
+
+
+window.addEventListener("load", TestExtension.init, false); 
+window.addEventListener("unload", TestExtension.destroy, false); 
diff --git a/src/content/two-level-tlds b/src/content/two-level-tlds
index 74ae495..52428b6 100644
--- a/src/content/two-level-tlds
+++ b/src/content/two-level-tlds
@@ -4,6 +4,7 @@ ab.se
 abo.pa
 ac.ae
 ac.at
+ac.bd
 ac.be
 ac.cn
 ac.com
@@ -140,6 +141,7 @@ brand.se
 british-library.uk
 bryansk.ru
 buryatia.ru
+busan.kr
 c.se
 ca.tt
 ca.us
@@ -157,6 +159,8 @@ chiba.jp
 chirurgiens-dentistes.fr
 chita.ru
 chukotka.ru
+chungbuk.kr
+chungnam.kr
 chuvashia.ru
 cim.br
 city.hu
@@ -350,6 +354,8 @@ ct.us
 cul.na
 cv.ua
 d.se
+daegu.kr
+daejeon.kr
 dagestan.ru
 dc.us
 de.com
@@ -489,6 +495,7 @@ ens.tn
 ernet.in
 erotica.hu
 erotika.hu
+es.kr
 es.tt
 esp.br
 etc.br
@@ -539,6 +546,7 @@ g12.br
 ga.us
 game.tw
 games.hu
+gangwon.kr
 gb.com
 gb.net
 gc.ca
@@ -706,7 +714,11 @@ guernsey.gg
 gunma.jp
 gv.ao
 gv.at
+gwangju.kr
 gx.cn
+gyeongbuk.kr
+gyeonggi.kr
+gyeongnam.kr
 gz.cn
 h.se
 ha.cn
@@ -723,6 +735,7 @@ hn.cn
 hokkaido.jp
 hotel.hu
 hotel.lk
+hs.kr
 hu.com
 huissier-justice.fr
 hyogo.jp
@@ -748,6 +761,7 @@ in-addr.arpa
 in.th
 in.ua
 in.us
+incheon.kr
 ind.br
 ind.er
 ind.gg
@@ -811,6 +825,9 @@ iz.hr
 izhevsk.ru
 jamal.ru
 jar.ru
+jeju.kr
+jeonbuk.kr
+jeonnam.kr
 jersey.je
 jet.uk
 jl.cn
@@ -837,6 +854,7 @@ kawasaki.jp
 kazan.ru
 kchr.ru
 kemerovo.ru
+kg.kr
 kh.ua
 khabarovsk.ru
 khakassia.ru
@@ -954,6 +972,7 @@ mil.io
 mil.jo
 mil.kg
 mil.kh
+mil.kr
 mil.kw
 mil.kz
 mil.lb
@@ -999,6 +1018,7 @@ mod.om
 mod.uk
 mordovia.ru
 mosreg.ru
+ms.kr
 ms.us
 msk.ru
 mt.us
@@ -1493,6 +1513,7 @@ saratov.ru
 sark.gg
 sc.cn
 sc.ke
+sc.kr
 sc.ug
 sc.us
 sch.ae
@@ -1621,6 +1642,7 @@ uk.com
 uk.net
 uk.tt
 ulan-ude.ru
+ulsan.kr
 unam.na
 uniti.al
 upt.al
diff --git a/src/defaults/preferences/nosquint.js b/src/defaults/preferences/nosquint.js
index 38a87af..ad31683 100644
--- a/src/defaults/preferences/nosquint.js
+++ b/src/defaults/preferences/nosquint.js
@@ -7,3 +7,4 @@ pref("extensions.nosquint.exceptions", "*/~* *.sourceforge.net *.google.[*]");
 pref("extensions.nosquint.wheelZoomEnabled", false);
 pref("extensions.nosquint.hideStatus", false);
 pref("extensions.nosquint.forgetMonths", 6);
+pref("extensions.nosquint.fullZoomPrimary", true);
diff --git a/src/install.rdf b/src/install.rdf
index adbdd32..1572ed6 100644
--- a/src/install.rdf
+++ b/src/install.rdf
@@ -1,20 +1,28 @@
 <?xml version="1.0"?>
-<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.1"
-                   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>
+<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>1.91.0</em:version>
+        <em:description>Manage site-specific full page and text zoom levels</em:description>
+        <em:creator>Jason Tackaberry</em:creator>
+        <!-- optional items -->
+        <em:homepageURL>http://urandom.ca/nosquint/</em:homepageURL>
+        <em:optionsURL>chrome://nosquint/content/globalprefs.xul</em:optionsURL>
+        <em:iconURL>chrome://nosquint/content/icon-32.png</em:iconURL>
+        <em:type>2</em:type> <!-- type=extension --> 
+
+        <!-- Firefox -->
+        <em:targetApplication>
+            <Description>
+                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+                <em:minVersion>3.0b4pre</em:minVersion>
+                <em:maxVersion>3.0b4</em:maxVersion>
+            </Description>
+        </em:targetApplication>
+    </Description>
+
+</RDF>
diff --git a/src/locale/en-US/globalprefs.dtd b/src/locale/en-US/globalprefs.dtd
new file mode 100644
index 0000000..522b741
--- /dev/null
+++ b/src/locale/en-US/globalprefs.dtd
@@ -0,0 +1,36 @@
+<!ENTITY ns.pref.title "NoSquint Global Settings">
+<!ENTITY ns.pref.tab.options.label "Options">
+<!ENTITY ns.pref.tab.exceptions.label "Exceptions">
+
+<!ENTITY ns.pref.general.caption "General">
+
+<!ENTITY ns.pref.general.primaryMethod.label "Primary zoom method">
+<!ENTITY ns.pref.general.primaryMethod.full "Full Page Zoom (images and text)">
+<!ENTITY ns.pref.general.primaryMethod.text "Text Zoom (text only)">
+
+<!ENTITY ns.pref.general.level.label "Default primary zoom level">
+<!ENTITY ns.pref.general.increment.label "Zoom increment">
+<!ENTITY ns.pref.general.mousewheel.label "Enable zoom with ctrl-mousewheel">
+<!ENTITY ns.pref.general.showstatus.label "Show current zoom levels in status bar">
+
+<!ENTITY ns.pref.site.caption "Site">
+<!ENTITY ns.pref.site.noRemember.label "Use the default zoom level (set above) for all sites">
+<!ENTITY ns.pref.site.remember.label "Remember 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.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/globalprefs.properties b/src/locale/en-US/globalprefs.properties
new file mode 100644
index 0000000..1608767
--- /dev/null
+++ b/src/locale/en-US/globalprefs.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/locale/en-US/help.html b/src/locale/en-US/help.html
index a486128..e9a70d1 100644
--- a/src/locale/en-US/help.html
+++ b/src/locale/en-US/help.html
@@ -56,32 +56,49 @@
 <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
+        <b>Primary zoom method</b>
+            <p>The primary zoom method specifies the behaviour of the standard
+            zoom adjustment shortcuts (ctrl-plus, ctrl-minus, ctrl-mousewheel).
+            With <code>Full Page Zoom</code>, both images and text will be zoomed;
+            with <code>Text Zoom</code>, only text is zoomed.  Whichever zoom method
+            is <i>not</i> set to be primary is referred to as the secondary method.</p>
+
+            <p>The shift key can be added to any of the shortcuts to control the
+            secondary zoom method.  For example, if the primary zoom method is
+            set to Full Page Zoom, and ctrl-shift-plus is pressed, only text size will
+            be increased.</p>
+            
+
+        <b>Default primary zoom level</b>
+            <p>This is the zoom level of the primary zoom method as applied to
+            all pages by default.  A value of 100% is the standard Firefox zoom
+            level without NoSquint.  With NoSquint, you can override this value
+            to be larger or smaller.</p>
+
+            <p>Modifying the 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
+            <p>You can change the zoom level for a page from the View menu, by
+            using one of the zoom shortcuts (ctrl-plus/minus or
             ctrl-mousewheel), or by using the optional toolbar buttons.
-            NoSquint will remember these changes.  This setting specifies what
+            NoSquint can 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>
+        <b>Enable zoom with ctrl-mousewheel</b>
+            <p>Selecting this option allows you to adjust the zoom level by
+            pressing and holding the control key while moving the mousewheel up
+            or down.  If ctrl-shift-mousewheel is used, this controls the
+            secondary zoom method.</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>
+        <b>Show current zoom levels in status bar</b>
+            <p>Selecting this option shows the zoom levels (both full page and
+            text zoom) in the status bar for the current web page.  When
+            hovering over the status panel, a tooltip will appear providing
+            more information.</p>
     </li>
 </ul>
 
@@ -103,24 +120,16 @@ 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>
+        <b>Remember 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>
+            you make to the zoom levels for a given site.  Both full page zoom
+            and text zoom levels are remembered independently.  Next time you
+            visit that site, NoSquint will change the zoom to the levels
+            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,
+            <p>With the "remember zoom levels 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
@@ -128,9 +137,12 @@ can control how NoSquint determines site names in the Exceptions Tab.</p>
             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>
+        <b>Use the default zoom level for all sites</b>
+            <p>One of NoSquint's features is the ability to remember custom
+            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>
 </ul>
 
diff --git a/src/locale/en-US/overlay.dtd b/src/locale/en-US/overlay.dtd
index d3ed0e6..cdd380c 100644
--- a/src/locale/en-US/overlay.dtd
+++ b/src/locale/en-US/overlay.dtd
@@ -1 +1,9 @@
-<!ENTITY nosquint.label "NoSquint Settings">
+<!ENTITY ns.tooltip.site.label "Site Name">
+<!ENTITY ns.tooltip.fullZoom.label "Full Zoom">
+<!ENTITY ns.tooltip.textZoom.label "Text Zoom">
+
+<!ENTITY ns.menu.fullZoom.label "Full Zoom">
+<!ENTITY ns.menu.textZoom.label "Text Zoom">
+<!ENTITY ns.menu.reset.label "Reset Levels">
+<!ENTITY ns.menu.siteSettings.label "Site Settings">
+<!ENTITY ns.menu.globalSettings.label "Global Settings">
diff --git a/src/locale/en-US/overlay.properties b/src/locale/en-US/overlay.properties
new file mode 100644
index 0000000..3dfe0ec
--- /dev/null
+++ b/src/locale/en-US/overlay.properties
@@ -0,0 +1,5 @@
+zoomMenuInText=Text Zoom In
+zoomMenuOutText=Text Zoom Out
+zoomMenuInFull=Full Zoom In
+zoomMenuOutFull=Full Zoom Out
+zoomMenuSettings=Zoom Settings (NoSquint)
diff --git a/src/locale/en-US/siteprefs.dtd b/src/locale/en-US/siteprefs.dtd
new file mode 100644
index 0000000..16c879f
--- /dev/null
+++ b/src/locale/en-US/siteprefs.dtd
@@ -0,0 +1,5 @@
+<!ENTITY ns.pref.title "NoSquint Site Settings">
+
+<!ENTITY ns.pref.fullZoom.label "Full zoom level">
+<!ENTITY ns.pref.textZoom.label "Text zoom level">
+<!ENTITY ns.pref.button.useDefault.label "Use Default">
diff --git a/src/locale/en-US/siteprefs.properties b/src/locale/en-US/siteprefs.properties
new file mode 100644
index 0000000..08ef25b
--- /dev/null
+++ b/src/locale/en-US/siteprefs.properties
@@ -0,0 +1 @@
+settingsFor=Settings for
diff --git a/src/skin/icon-enlarge-16.png b/src/skin/icon-enlarge-16.png
index 46a4b05..e1bf549 100644
Binary files a/src/skin/icon-enlarge-16.png 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
index 32b2846..54937bd 100644
Binary files a/src/skin/icon-enlarge-24.png 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
index e3841ee..385fec0 100644
Binary files a/src/skin/icon-reduce-16.png 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
index cff1f1a..7543ac4 100644
Binary files a/src/skin/icon-reduce-24.png and b/src/skin/icon-reduce-24.png differ

-- 
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