changeset 0:0ebd7c7a83cb

Initial import
author Peter Geer <pageer@skepticats.com>
date Sat, 18 Aug 2012 13:10:14 -0400
parents
children 601d7c30681d
files .hgignore .komodotools/Build.komodotool .komodotools/Build_and_Install.komodotool .komodotools/Docs_-_Extensions.komodotool .komodotools/Reconfigure.komodotool TabSwitcher.komodoproject chrome.manifest chrome.p.manifest content/arrays.js content/bookmarks/bookmarks-pane.xul content/bookmarks/bookmarksOverlay.js content/bookmarks/bookmarksOverlay.xul content/bookmarks/bookmarksTreeview.js content/common.js content/commonPrefs.js content/editPosition/editPosition.js content/htmlutils.js content/pref/pref-editposition.js content/pref/pref-editposition.xul content/pref/pref-main.xul content/pref/pref-ordertabs.js content/pref/pref-ordertabs.xul content/pref/pref-switchview.js content/pref/pref-switchview.xul content/pref/prefOverlay.xul content/prefs.js content/tabSwitcher/tabSwitcher.js content/tabSwitcher/tabSwitcher.xul content/tabSwitcher/tabSwitcherTreeview.js content/tabswitchMenuKO5.xul content/tabswitchMenuKO6.xul content/tabswitchOverlay.js content/tabswitchOverlay.xul content/tabswitcher_overlay.xul install.rdf locale/en-US/bookmarks.dtd locale/en-US/pref.dtd locale/en-US/tabswitcher.dtd locale/en-US/tabswitcher.properties skin/appicon.png skin/bookmarks.css skin/goto-last-edit.png skin/goto-next-edit.png skin/refresh.png skin/remove-all.png skin/remove-selected.png skin/tabSwitcher.css tabswitcher-0.9.2-ko.xpi
diffstat 48 files changed, 3700 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,1 @@
+build/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.komodotools/Build.komodotool	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,36 @@
+{
+  "keyboard_shortcut": "", 
+  "name": "Build", 
+  "language": "JavaScript", 
+  "trigger_enabled": false, 
+  "value": [
+    "/**", 
+    " * Script to build an xpi, running koext build in the current project root.", 
+    " */", 
+    "", 
+    "var project = ko.macros.current.project;", 
+    "var projectDir = ko.interpolate.interpolateString('%p');", 
+    "var callback = function() {", 
+    "  ko.statusBar.AddMessage('Build complete', 'projects', 5000, true);", 
+    "  ko.projects.manager.saveProject(project);", 
+    "};", 
+    "var osPath = Components.classes[\"@activestate.com/koOsPath;1\"].", 
+    "                getService(Components.interfaces.koIOsPath);", 
+    "var preprocessedChromePath = osPath.join(projectDir, \"chrome.p.manifest\");", 
+    "if (osPath.exists(preprocessedChromePath)) {", 
+    "  ko.koextgen.extensionLib.command('build -i chrome.manifest -i chrome.p.manifest ' +", 
+    "                                   '-d \"' + projectDir + '\"',", 
+    "                                   callback);", 
+    "} else {", 
+    "  ko.koextgen.extensionLib.command('build -i chrome.manifest ' +", 
+    "                                   '-d \"' + projectDir + '\"',", 
+    "                                   callback);", 
+    "}"
+  ], 
+  "trigger": "", 
+  "rank": 100, 
+  "version": "1.0.7", 
+  "async": 1, 
+  "type": "macro", 
+  "icon": "chrome://fugue/skin/icons/building--plus.png"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.komodotools/Build_and_Install.komodotool	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,54 @@
+{
+  "keyboard_shortcut": "", 
+  "name": "Build and Install", 
+  "language": "JavaScript", 
+  "trigger_enabled": false, 
+  "value": [
+    "/**", 
+    " * Script to build an xpi, running koext build in the current project root and", 
+    " * then install it into the currently running Komodo.", 
+    " */", 
+    "", 
+    "var project = ko.macros.current.project;", 
+    "var projectDir = ko.interpolate.interpolateString('%p');", 
+    "var callback = function() {", 
+    "  ko.statusBar.AddMessage('Build complete', 'projects', 5000, true);", 
+    "  ko.projects.manager.saveProject(project);", 
+    "  var os = Components.classes[\"@activestate.com/koOs;1\"].", 
+    "                  getService(Components.interfaces.koIOs);", 
+    "  var entries = os.listdir(projectDir, {});", 
+    "  var xpi_entries = entries.filter(function(name) { return /.xpi$/.test(name); } );", 
+    "  if (xpi_entries.length == 0) {", 
+    "    ko.dialogs.alert(\"No xpi file found in project dir: \" + projectDir);", 
+    "  } else if (xpi_entries.length == 1) {", 
+    "    ko.open.URI(os.path.join(projectDir, xpi_entries[0]));", 
+    "  } else {", 
+    "    var result = ko.dialogs.selectFromList(\"Extension Installation\",", 
+    "                              \"Pick the xpi to install: \",", 
+    "                              xpi_entries,", 
+    "                              \"one\");", 
+    "    if (result) {", 
+    "      ko.open.URI(os.path.join(projectDir, result));", 
+    "    }", 
+    "  }", 
+    "};", 
+    "var osPath = Components.classes[\"@activestate.com/koOsPath;1\"].", 
+    "                getService(Components.interfaces.koIOsPath);", 
+    "var preprocessedChromePath = osPath.join(projectDir, \"chrome.p.manifest\");", 
+    "if (osPath.exists(preprocessedChromePath)) {", 
+    "  ko.koextgen.extensionLib.command('build -i chrome.manifest -i chrome.p.manifest ' +", 
+    "                                   '-d \"' + projectDir + '\"',", 
+    "                                   callback);", 
+    "} else {", 
+    "  ko.koextgen.extensionLib.command('build -i chrome.manifest ' +", 
+    "                                   '-d \"' + projectDir + '\"',", 
+    "                                   callback);", 
+    "}"
+  ], 
+  "trigger": "", 
+  "rank": 100, 
+  "version": "1.0.7", 
+  "async": 1, 
+  "type": "macro", 
+  "icon": "chrome://fugue/skin/icons/building--arrow.png"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.komodotools/Docs_-_Extensions.komodotool	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,15 @@
+{
+  "keyboard_shortcut": "", 
+  "name": "Docs - Extensions", 
+  "language": "JavaScript", 
+  "trigger_enabled": false, 
+  "value": [
+    "ko.help.open('komodo_extensions');"
+  ], 
+  "trigger": "", 
+  "rank": 100, 
+  "version": "1.0.7", 
+  "async": 1, 
+  "type": "macro", 
+  "icon": "chrome://fugue/skin/icons/information-white.png"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.komodotools/Reconfigure.komodotool	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,64 @@
+{
+  "keyboard_shortcut": "", 
+  "name": "Reconfigure", 
+  "language": "JavaScript", 
+  "trigger_enabled": false, 
+  "value": [
+    "/* Copyright (c) 2011 YourNameHere", 
+    "   See the file LICENSE.txt for licensing information. */", 
+    "", 
+    "var reconfigure = function() {", 
+    "try {", 
+    "    var macro = ko.macros.current;", 
+    "    var project = macro.project;", 
+    "    if (!project) {", 
+    "        ko.dialogs.alert(\"Unexpected error: no project associated with macro \"", 
+    "                         + macro.name);", 
+    "    }", 
+    "    var prefset = project.prefset;", 
+    "    if (!prefset.hasPrefHere(\"koextgen.target\")) {", 
+    "        ko.dialogs.alert(\"Project \"", 
+    "                         + project.name", 
+    "                         + \" doesn't seem to be an extension project.\");", 
+    "        return;", 
+    "    }", 
+    "    var targetName = prefset.getStringPref(\"koextgen.target\");", 
+    "    var projectFileEx = project.getFile();", 
+    "    // Get the project's location, then from one point higher populate it.", 
+    "    var projectDirPath = projectFileEx.dirName;", 
+    "", 
+    "    var koExt = ko.koextgen.extensionLib;", 
+    "    ", 
+    "    var rdfFile = koExt.os.path.join(projectDirPath, \"install.rdf\");", 
+    "    var rdfVars = koExt.getRDFVars(koExt.readFile(rdfFile));", 
+    "    var callbackFn = function(data) {", 
+    "        if (data.valid) {", 
+    "            koExt.updateProject(projectDirPath, targetName, data.vars);", 
+    "        }", 
+    "    }", 
+    "    var data = {", 
+    "        'callback': callbackFn,", 
+    "        'valid': false,", 
+    "        'configured': true,", 
+    "        'vars': rdfVars,", 
+    "    };", 
+    "    data.vars['ext_name'] = koExt.getNiceName(data.vars.name);", 
+    "    var setup_xul_uri = \"chrome://koextgen/content/resources/setup.xul\";", 
+    "    window.openDialog(", 
+    "        setup_xul_uri,", 
+    "        \"_blank\",", 
+    "        \"centerscreen,chrome,resizable,scrollbars,dialog=no,close,modal=no\",", 
+    "        data);", 
+    "} catch(ex) {", 
+    "    ko.dialogs.alert(\"Error in reconfigure: \" + ex)", 
+    "}", 
+    "};", 
+    "reconfigure();"
+  ], 
+  "trigger": "", 
+  "rank": 100, 
+  "version": "1.0.7", 
+  "async": 1, 
+  "type": "macro", 
+  "icon": "chrome://fugue/skin/icons/wrench.png"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TabSwitcher.komodoproject	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Komodo Project File - DO NOT EDIT -->
+<project id="de77f5bf-9ca6-4def-963f-db52b88af8b3" kpf_version="5" name="TabSwitcher.komodoproject">
+<preference-set idref="de77f5bf-9ca6-4def-963f-db52b88af8b3">
+  <boolean id="configured">1</boolean>
+  <string id="koextgen.target">komodo</string>
+</preference-set>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chrome.manifest	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+content tabswitcher jar:tabswitcher.jar!/content/
+skin tabswitcher classic/1.0 jar:tabswitcher.jar!/skin/
+locale tabswitcher en-US jar:tabswitcher.jar!/locale/en-US/
+
+
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchOverlay.xul
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/bookmarks/bookmarksOverlay.xul
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchMenuKO5.xul appversion<6b1
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchMenuKO6.xul appversion>6b1
+overlay	chrome://komodo/content/pref/pref.xul	chrome://tabswitcher/content/pref/prefOverlay.xul
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chrome.p.manifest	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,16 @@
+# #if MODE == "dev"
+content tabswitcher content/
+skin tabswitcher classic/1.0 skin/
+locale tabswitcher en-US locale/en-US/
+
+# #else
+content tabswitcher jar:tabswitcher.jar!/content/
+skin tabswitcher classic/1.0 jar:tabswitcher.jar!/skin/
+locale tabswitcher en-US jar:tabswitcher.jar!/locale/en-US/
+# #endif
+
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchOverlay.xul
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/bookmarks/bookmarksOverlay.xul
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchMenuKO5.xul appversion<6b1
+overlay	chrome://komodo/content/komodo.xul	chrome://tabswitcher/content/tabswitchMenuKO6.xul appversion>6b1
+overlay	chrome://komodo/content/pref/pref.xul	chrome://tabswitcher/content/pref/prefOverlay.xul
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/arrays.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,78 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+function FixedSizeStack(maxItems) {
+    this.items = new Array();
+    this.maxItems = maxItems ? maxItems : 100;
+}
+
+FixedSizeStack.prototype = {
+    push : function(item) {
+        if (this.items.length >= this.maxItems) {
+            this.items.splice(0, 1);
+        }
+        this.items.push(item);
+    },
+    
+    pop : function() {
+        return this.items.pop();
+    },
+    
+    peek : function() {
+        return this.items[this.items.length - 1];
+    },
+    
+    get length() {
+        return this.items.length;
+    },
+
+    clear : function() {
+        this.items.splice(0, this.items.length);
+    },
+
+    resize : function(newSize) {
+        this.maxItems = newSize;
+    },
+
+    toString : function() {
+        var arr = new Array();
+        for (var i = 0; i < this.items.length; i++) {
+            arr.push(i + ":" + this.items[i].view.title);
+        }
+        return arr.join("\n");
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/bookmarks/bookmarks-pane.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/bookmarks.dtd">
+<?xml-stylesheet href="chrome://tabswitcher/skin/bookmarks.css" type="text/css"?>
+
+<?xml-stylesheet href="chrome://komodo/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/global/global.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/bindings/scrolltabs.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/bindings/sidebar.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/bindings/views.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/bindings/widgets.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/toolbar.css" type="text/css"?>
+<?xml-stylesheet href="chrome://komodo/skin/platform.css" type="text/css"?>
+<?xml-stylesheet href="chrome://tabswitcher/skin" type="text/css"?>
+
+<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <!-- Komodo specific code -->
+    <script type="application/x-javascript"
+            src="chrome://komodo/content/library/logging.js" />
+    <script type="application/x-javascript"
+            src="chrome://komodo/content/library/uilayout.js" />
+  
+    <script type="application/x-javascript"
+            src="chrome://tabswitcher/content/common.js" />
+    <script type="application/x-javascript"
+            src="chrome://tabswitcher/content/bookmarks/bookmarksTreeview.js" />
+    <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/bookmarks/bookmarksOverlay.js" />
+
+    <vbox flex="1">
+        <hbox align="center">
+            <label id="viewswitcher-bookmark-status"
+                   flex="1"
+                   bookmarklabel="&viewswitcher.bookmark.found;"/>
+            <separator flex="1"/>
+            <button id="viewswitcher_bookmarks-refresh"
+                    class="button-viewswitcher-refresh button-toolbar-a"
+                    tooltiptext="&viewswitcher.bookmark.refresh.tooltip;"
+                    oncommand="gViewSwitcherBookmarks.onRefresh();"/>
+            <button id="viewswitcher_bookmarks-remove-selected"
+                    class="button-viewswitcher-remove-selected button-toolbar-a"
+                    tooltiptext="&viewswitcher.bookmark.remove.selected.label;"
+                    oncommand="gViewSwitcherBookmarks.onRemoveSelected();"/>
+            <button id="viewswitcher_bookmarks-remove-all"
+                    class="button-viewswitcher-remove-all button-toolbar-a"
+                    tooltiptext="&viewswitcher.bookmark.remove.all.label;"
+                    oncommand="gViewSwitcherBookmarks.onRemoveAll();"/>
+        </hbox>
+        <tree id="viewswitcher_bookmarks-tree"
+              flex="1"
+              seltype="multiple">
+            <treecols>
+                <treecol primary="true"
+                         crop="center"
+                         flex="8"
+                         persist="width"
+                         id="viewswitcher_bookmarks-filename"
+                         label="&viewswitcher.bookmark.file.label;" />
+                <splitter class="tree-splitter" />
+                <treecol id="viewswitcher_bookmarks-linenum"
+                         label="&viewswitcher.bookmark.line.number.label;"
+                         persist="width"/>
+                <splitter class="tree-splitter" />
+                <treecol id="viewswitcher_bookmarks-content"
+                         flex="12"
+                         label="&viewswitcher.bookmark.line.content.label;"
+                         persist="width" />
+            </treecols>
+            <treechildren id="viewswitcher_bookmarks-treechildren"
+                          flex="1"
+                          ondblclick="gViewSwitcherBookmarks.onDblClick();"/>
+        </tree>
+    </vbox>
+</page>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/bookmarks/bookmarksOverlay.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,138 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+var gViewSwitcherBookmarks = {
+    onLoad : function() {
+        try {
+            this.treeView = new BookmarksTreeView(
+                    document.getElementById("viewswitcher_bookmarks-tree"));
+            var obs = DafizillaCommon.getObserverService();
+            obs.addObserver(this, "view_opened", false);
+            obs.addObserver(this, "view_closed", false);
+
+            this.addListeners();
+        } catch (err) {
+            alert("gViewSwitcherBookmarks onLoad " + err);
+        }
+    },
+
+    onUnLoad : function() {
+        var obs = DafizillaCommon.getObserverService();
+        obs.addObserver(this, "view_opened", false);
+        obs.removeObserver(this, "view_closed");
+        this.removeListeners();
+    },
+
+    observe : function(subject, topic, data) {
+        try {
+        switch (topic) {
+            case "view_opened":
+                this.onRefresh();
+                break;
+            case "view_closed":
+                this.onRefresh();
+                break;
+        }
+        } catch (err) {
+            alert(topic + "--" + data + "\n" + err);
+        }
+    },
+
+    onRefresh : function() {
+        this.treeView.fillBookmarksArray();
+        this.treeView.refresh();
+        var status = document.getElementById("viewswitcher-bookmark-status");
+
+        var label = "";
+        if (this.treeView.viewWithBookmarkCount) {
+            label = status.getAttribute("bookmarklabel")
+                            .replace("%1", this.treeView.items.length)
+                            .replace("%2", this.treeView.viewWithBookmarkCount)
+                            .replace("%3", this.treeView.viewCount);
+        }
+        status.setAttribute("value", label);
+    },
+
+    onRemoveSelected : function() {
+        this.treeView.removeSelectedBookmarks();
+        this.onRefresh();
+    },
+
+    onRemoveAll : function() {
+        this.treeView.removeAllBookmarks();
+        this.onRefresh();
+    },
+
+    onDblClick : function() {
+        this.treeView.moveToSelectedBookmark();
+    },
+
+    addListeners : function() {
+        var self = this;
+
+        this.handle_view_opened_setup = function(event) {
+            self.onViewOpened(event);
+        };
+
+        this.handle_view_closed_setup = function(event) {
+            self.onViewClosed(event);
+        };
+
+        window.addEventListener('view_opened',
+                                this.handle_view_opened_setup, false);
+        window.addEventListener('view_closed',
+                                this.handle_view_closed_setup, false);
+    },
+
+    removeListeners : function() {
+        window.removeEventListener('view_opened',
+                                this.handle_view_opened_setup, false);
+        window.removeEventListener('view_closed',
+                                this.handle_view_closed_setup, false);
+    },
+
+    onViewOpened : function(event) {
+        this.onRefresh();
+    },
+
+    onViewClosed : function(event) {
+        this.onRefresh();
+    }
+}
+
+window.addEventListener("load", function(event) {gViewSwitcherBookmarks.onLoad(event)}, false);
+window.addEventListener("unload", function(event) {gViewSwitcherBookmarks.onUnLoad(event)}, false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/bookmarks/bookmarksOverlay.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/bookmarks.dtd">
+<?xml-stylesheet href="chrome://tabswitcher/skin/bookmarks.css" type="text/css"?>
+
+<overlay id="viewSwitcherBookmarkOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <menupopup id="menu_view_tabs_popup">
+        <menuitem id="show_viewswitcher_bookmarks_tab2"
+            observes="show_viewswitcher_bookmarks_tab"
+            class="menuitem-iconic-wide"
+            oncommand="ko.uilayout.ensureTabShown('viewswitcher_bookmarks_tab', true)"
+            label="&viewswitcher.bookmark.tab.title;"
+            type="checkbox"
+            />
+    </menupopup>
+
+    <menupopup id="tabPicker_popup">
+        <menuitem id="show_viewswitcher_bookmarks_tab"
+            oncommand="ko.uilayout.ensureTabShown('viewswitcher_bookmarks_tab', true)"
+            label="&viewswitcher.bookmark.tab.title;"
+            />
+    </menupopup>
+    <!-- TODO: test -->
+    <ko-pane id="workspace_bottom_area">
+        <browser type="ko-widget"
+                 id="viewswitcher_bookmarks_tab"
+                 label="&viewswitcher.bookmark.tab.title;"
+                 src="chrome://tabswitcher/content/bookmarks/bookmarks-pane.xul"
+                 tab_onfocus="ko.extensions.tabswitcher.focus();" />
+    </ko-pane>
+
+</overlay>
+   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/bookmarks/bookmarksTreeview.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,255 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+function BookmarksTreeView(treeElement) {
+    this.treeElement = treeElement;
+    this.items = [];
+    this.viewWithBookmarkCount = 0;
+    this.viewCount = 0;
+
+    this.treebox = null;
+
+    this.treeElement.view = this;
+}
+
+BookmarksTreeView.prototype = {
+    fillBookmarksArray : function() {
+        var views = ko.views.manager.topView.getDocumentViews(true);
+        var marker_mask = 1 << ko.markers.MARKNUM_BOOKMARK;
+
+        var newItems = [];
+        this.viewWithBookmarkCount = 0;
+
+        for (var i = 0; i < views.length; i++) {
+            var view = views[i];
+
+            if (view.getAttribute("type") != "editor") {
+                continue;
+            }
+            var line = 0;
+            var foundBookmarks = false;
+            do {
+                line = view.scintilla.scimoz.markerNext(line, marker_mask);
+                if (line >= 0) {
+                    foundBookmarks = true;
+                    newItems.push({ view : view, line: line});
+                    ++line;
+                }
+            } while (line >= 0);
+            
+            if (foundBookmarks) {
+                ++this.viewWithBookmarkCount;
+            }
+        }
+        this.viewCount = views.length;
+        this.treebox.rowCountChanged(0, newItems.length - this.items.length);
+        this.items = newItems;
+    },
+
+    removeSelectedBookmarks : function(index) {
+        var selArr = this.selectedIndexes;
+        
+        for (var i = 0; i < selArr.length; i++) {
+            var bookmark = this.items[selArr[i]];
+            var scimoz = bookmark.view.scintilla.scimoz;
+
+            scimoz.markerDelete(bookmark.line, ko.markers.MARKNUM_BOOKMARK);
+        }
+        this.fillBookmarksArray();
+    },
+
+    removeAllBookmarks : function(index) {
+        for (var i = 0; i < this.items.length; i++) {
+            var scimoz = this.items[i].view.scintilla.scimoz;
+    
+            scimoz.markerDeleteAll(ko.markers.MARKNUM_BOOKMARK);
+        }
+        this.fillBookmarksArray();
+    },
+
+    get selectedItems() {
+        var ar = [];
+        var selIndexes = this.selectedIndexes;
+
+        for (var i = 0; i < selIndexes.length; i++) {
+            ar.push(this.items[selIndexes[i]]);
+        }
+
+        return ar;
+    },
+
+    get selectedIndexes() {
+        var selection = this.selection;
+        var items = [];
+
+        for (var i = 0; i < selection.getRangeCount(); i++) {
+            var minIdx = {};
+            var maxIdx = {};
+            selection.getRangeAt(i, minIdx, maxIdx);
+            for (var selIdx = minIdx.value; selIdx <= maxIdx.value; selIdx++) {
+                items.push(selIdx);
+            }
+        }
+
+        return items;
+    },
+
+    deleteItems : function(items) {
+        if (items && items.length > 0) {
+            for (var i = items.length - 1; i >= 0; i--) {
+                this.items.splice(items[i], 1);
+            }
+            this.treebox.rowCountChanged(items[0], -items.length);
+        }
+    },
+
+    deleteSelectedItem : function() {
+        try {
+            var selIdx = this.selection.currentIndex;
+
+            if (selIdx < 0) {
+                return;
+            }
+            var newItems = new Array();
+
+            for (var i = 0; i < this.items.length; i++) {
+                if (i != selIdx) {
+                    newItems.push(this.items[i]);
+                }
+            }
+
+            this.items = newItems;
+            // -1 means remove (< 0)
+            this.treebox.rowCountChanged(selIdx, -1);
+
+            if (newItems.length > 0) {
+                this.selection.select(this.rowCount == selIdx ? selIdx - 1 : selIdx);
+            }
+        } catch (err) {
+            alert(err);
+        }
+    },
+
+    invalidate : function() {
+        this.treebox.invalidate();
+    },
+
+    get currentSelectedItem() {
+        if (this.selection.currentIndex < 0) {
+            return null;
+        }
+        return this.items[this.selection.currentIndex];
+    },
+    
+    refresh : function() {
+        this.selection.clearSelection();
+        this.treebox.invalidate();
+    },
+
+    moveToSelectedBookmark : function() {
+        var view = this.currentSelectedItem.view;
+        var scimoz = view.scintilla.scimoz;
+
+        scimoz.gotoLine(this.currentSelectedItem.line);
+        view.makeCurrent();
+    },
+
+    selectAndEnsureVisible : function(index) {
+        this.selection.select(index);
+        this.treebox.ensureRowIsVisible(index);
+    },
+
+    getCellText : function(row, column) {
+        switch (column.id || column) {
+            case "viewswitcher_bookmarks-filename":
+                if (ko.views.manager.currentView.document.file) {
+                    return this.items[row].view.document.file.path;
+                } else {
+                    return this.items[row].view.document.displayPath;
+                }
+            case "viewswitcher_bookmarks-linenum":
+                return this.items[row].line + 1;
+            case "viewswitcher_bookmarks-content":
+                var scimoz = this.items[row].view.scintilla.scimoz;
+                var lineStart = scimoz.positionFromLine(this.items[row].line);
+                var lineEnd = scimoz.getLineEndPosition(this.items[row].line);
+                return scimoz.getTextRange(lineStart, lineEnd);
+        }
+
+        return "";
+    },
+
+    get rowCount() {
+        return this.items.length;
+    },
+
+    cycleCell: function(row, column) {},
+
+    getImageSrc: function (row, column) {
+        return null;
+    },
+
+    setTree: function(treebox) {
+        this.treebox = treebox;
+    },
+
+    isContainerOpen: function(index) {},
+    isContainerEmpty: function(index) {},
+    canDrop: function(index, orientation, dataTransfer) {},
+    drop: function(row, orientation, dataTransfer) {},
+    getParentIndex: function(rowIndex) {},
+    hasNextSibling: function(rowIndex, afterIndex) {},
+    getProgressMode: function(row, col) {},
+    getCellValue: function(row, col) {},
+    toggleOpenState: function(index) {},
+    selectionChanged: function() {},
+    isEditable: function(row, col) {},
+    isSelectable: function(row, col) {},
+    setCellValue: function(row, col, value) {},
+    setCellText: function(row, col, value) {},
+    performAction: function(action) {},
+    performActionOnRow: function(action, row) {},
+    performActionOnCell: function(action, row, col) {},
+    getCellProperties: function(row, column, props) {},
+    cycleHeader: function(col, elem) {},
+    isContainer: function(row){ return false; },
+    isSeparator: function(row){ return false; },
+    isSorted: function(row){ return false; },
+    getLevel: function(row){ return 0; },
+    getRowProperties: function(row,props){},
+    getColumnProperties: function(colid,col,props){}
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/common.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,82 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+function DafizillaCommon() {
+}
+
+DafizillaCommon.getObserverService = function () {
+    const CONTRACTID_OBSERVER = "@mozilla.org/observer-service;1";
+    const nsObserverService = Components.interfaces.nsIObserverService;
+
+    return Components.classes[CONTRACTID_OBSERVER].getService(nsObserverService);
+}
+
+DafizillaCommon.log = function(msg) {
+    ko.logging.getLogger("extensions.tabswitcher").warn(msg);
+}
+
+DafizillaCommon.exception = function(error) {
+    ko.logging.getLogger("extensions.tabswitcher").exception(error);
+}
+
+DafizillaCommon.removeMenuItems = function(menu) {
+    var children = menu.childNodes;
+
+    for (var i = children.length - 1; i >= 0; i--) {
+        menu.removeChild(children[i]);
+    }
+}
+
+DafizillaCommon.sortTabs = function(view, sorter) {
+    if (typeof(view) == "undefined" || view == null) {
+        return;
+    }
+    var tabbox = view.parentNode;
+
+    while (tabbox && tabbox.nodeName != "tabbox" && tabbox.nodeName != "xul:tabbox") {
+        tabbox = tabbox.parentNode;
+    }
+    var childNodes = tabbox._tabs.childNodes;
+
+    for (var i = 0; i < childNodes.length; i++) {
+        for (var j = childNodes.length - 1; j > i; j--) {
+            if (sorter(childNodes[j], childNodes[j - 1]) < 0) {
+                tabbox._tabs.insertBefore(childNodes[j], childNodes[j - 1])
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/commonPrefs.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,112 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+function DafizillaPrefs(prefix) {
+    if (prefix) {
+        this.prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+            .getService(Components.interfaces.nsIPrefService)
+            .getBranch(prefix);
+        this.prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
+    }
+}
+    
+DafizillaPrefs.prototype = {
+    getString : function(prefName, defValue) {
+        var prefValue;
+        try {
+            prefValue = this.prefBranch.getCharPref(prefName);
+        } catch (ex) {
+            prefValue = null;
+        }
+        return prefValue == null ? defValue : prefValue;
+    },
+    
+    setString : function(prefName, prefValue) {
+        this.prefBranch.setCharPref(prefName, prefValue);
+    },
+
+    getBool : function(prefName, defValue) {
+        var prefValue = false;
+        try {
+            prefValue = this.prefBranch.getBoolPref(prefName);
+        } catch (ex) {
+            if (defValue != undefined) {
+                prefValue = defValue;
+            }
+        }
+
+        return prefValue;
+    },
+
+    setBool : function(prefName, prefValue) {
+        this.prefBranch.setBoolPref(prefName, prefValue);
+    },
+    
+    load : function() {
+    },
+
+    save : function() {
+    }
+}
+
+DafizillaPrefs.safeInt = function(value, defValue, checkCallback) {
+    var tmpValue;
+
+    if (typeof(value) == "number") {
+        tmpValue = value;
+    } else {
+        tmpValue = parseInt(value);
+        if (isNaN(tmpValue)) {
+            return defValue;
+        }
+    }
+
+    if (typeof(checkCallback) == "function") {
+        if (!checkCallback(tmpValue)) {
+            return defValue;
+        }
+    }
+    return tmpValue;
+}
+
+/////////////
+/// List of checkers routines
+/////////////
+
+DafizillaPrefs.checkers = {};
+DafizillaPrefs.checkers.checkGreaterOrEqualThan = function(value, greaterThanValue) {
+    return value >= greaterThanValue;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/editPosition/editPosition.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,629 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+function EditPosFixedSizeStack(maxItems) {
+    this.items = new Array();
+    this.maxItems = maxItems ? maxItems : 100;
+}
+
+//special stack, clearing markers on item deletion
+EditPosFixedSizeStack.prototype = {
+    push : function(item) {
+        if (this.items.length >= this.maxItems) {
+            scimoz = this.items[0].view.scimoz;
+            scimoz.markerDeleteHandle(this.items[0].marker);
+            this.items.splice(0, 1);
+        }
+        this.items.push(item);
+    },
+
+    pop : function() {
+        return this.items.pop();
+    },
+
+    peek : function() {
+        return this.items[this.items.length - 1];
+    },
+
+    get length() {
+        return this.items.length;
+    },
+
+    clear : function() {
+        for (var i = 0; i < this.items.length; i++) {
+            //remove markers first
+            scimoz = this.items[i].view.scimoz;
+            scimoz.markerDeleteHandle(this.items[i].marker);
+        }
+        this.items.splice(0, this.items.length);
+    },
+
+    resize : function(newSize) {
+        this.maxItems = newSize;
+        //TODO: discard items when newSize < maxItems
+    },
+
+    toString : function() {
+        var arr = new Array();
+        for (var i = 0; i < this.items.length; i++) {
+            arr.push(i + ":"
+                     + this.items[i].view.title
+                     +" l:"+(this.items[i].line+1)
+                     +" c:"+(this.items[i].col+1)+"\n");
+        }
+        return arr.join("\n");
+    }
+}
+
+const MARKNUM_EDITPOSLOC = 14;
+
+var gEditPosition = {
+    lastEditStack : new EditPosFixedSizeStack(10),
+    nextEditStack : new EditPosFixedSizeStack(10),
+    mode : null,
+    editClearNextStack: null,
+    fgColor : null,
+    bgColor : null,
+
+    onLoad : function() {
+        try {
+            var obs = DafizillaCommon.getObserverService();
+            obs.addObserver(this, "view_opened", false);
+            obs.addObserver(this, "view_closed", false);
+            obs.addObserver(this, "tabswitcher_pref_changed", false);
+
+            this.prefs = new TabSwitcherPrefs();
+            this.init();
+
+            if (this.prefs.editCompatibility) {
+                obs.addObserver(this, "current_view_check_status", false);
+            };
+
+            this.addListeners();
+
+            xtk.include("color");
+
+            this.fgColor = xtk.color.RGB(0x00, 0x00, 0x00); // black
+            this.bgColor = xtk.color.RGB(0x00, 0xFF, 0xFF); // cyan
+
+            //DafizillaCommon.log("onLoad done");
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    init : function() {
+        try {
+            this.prefs.load();
+
+            //cache some prefs
+            var mode = this.prefs.editGranularity;
+
+            if (mode == "s") {
+                this.mode = mode;
+            } else {
+                this.mode = parseInt(mode) - 1;
+            }
+
+            this.editClearNextStack = this.prefs.editClearNextStack;
+
+            this.lastEditStack.resize(this.prefs.maxSizeEditPositionStack);
+            this.nextEditStack.resize(this.prefs.maxSizeEditPositionStack);
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    onUnLoad : function() {
+        try {
+            var obs = DafizillaCommon.getObserverService();
+            if (this.prefs.editCompatibility) {
+                obs.removeObserver(this, "current_view_check_status");
+            };
+            obs.removeObserver(this, "view_opened");
+            obs.removeObserver(this, "view_closed");
+            obs.removeObserver(this, "tabswitcher_pref_changed");
+            this.removeListeners();
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    observe : function(subject, topic, data) {
+        try {
+            switch (topic) {
+                case "current_view_check_status":
+                    //StatusBar_AddMessage("current_view_check_status", "debugger",5000,true);
+                    this.pushEdit();
+                    break;
+                case "view_closed":
+                    this.viewClosed(subject);
+                    break;
+                case "view_opened":
+                    this.viewOpened(subject);
+                    break;
+                case "tabswitcher_pref_changed":
+                    this.init();
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    removeView : function(view, arr) {
+        try {
+            for (var i = arr.length - 1; i >= 0; i--) {
+                if (arr[i].view == view) {
+                    try {
+                        //remove markers first
+                        scimoz = arr[i].view.scimoz;
+                        scimoz.markerDeleteHandle(arr[i].marker);
+                    } catch (e) {}
+
+                    arr.splice(i, 1);
+                }
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    pushEdit : function(view, position) {
+        //keep this function bloody FAST
+        try {
+            if (view) {
+                var currentView = view;
+            } else {
+                var currentView = ko.views.manager.currentView;
+            };
+            //DafizillaCommon.log("pushEdit");
+
+            if (!currentView.document) {
+                return;
+            }
+
+            if (!currentView.document.isDirty) {
+                return;
+            }
+
+            if (this.lastEditStack.length) {
+                var last = this.lastEditStack.peek();
+            } else {
+                var last = null;
+            }
+
+            var scimoz = currentView.scimoz;
+            if (position) {
+                var currentPos = position;
+            } else {
+                var currentPos = scimoz.currentPos;
+            }
+
+            if (last && last.view == currentView) {
+                // seems to happen that pushEdit is called multiple times
+                // with the same position
+                if (last.position != currentPos) {
+                    var currentLine = scimoz.lineFromPosition(currentPos);
+                    if (this.mode == "s") {
+                        //track ONLY the last line in a file
+                        this.movePosition(last, scimoz, currentPos, currentLine);
+                    } else {
+                        var cnt = this.mode;
+                        var diff = last.line - currentLine;
+                        var absdiff = diff < 0 ? -diff : diff;
+                        if (absdiff <= cnt) {
+                            //var msg = "modifypos: "+cnt+" "+absdiff+" "+last.position+" "+currentPos;
+                            //StatusBar_AddMessage(msg, "debugger",5000,true);
+
+                            this.movePosition(last, scimoz, currentPos, currentLine);
+                        } else {
+                            //var msg = "addpos: "+cnt+" "+absdiff+" "+currentPos;
+                            //StatusBar_AddMessage(msg, "debugger",5000,true);
+
+                            this.addPositionToStack(this.lastEditStack,
+                                                    currentView, currentPos);
+                        }
+                    }
+                }
+            } else {
+                this.addPositionToStack(this.lastEditStack,
+                                        currentView, currentPos);
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    movePosition : function(item, scimoz, position, currentLine) {
+        //keep this function bloody FAST
+        try {
+            item.position = position;
+            item.col = scimoz.getColumn(position);
+
+            if (item.line != currentLine) {
+                item.line = currentLine;
+
+                //move marker too
+                scimoz.markerDeleteHandle(item.marker);
+                item.marker = scimoz.markerAdd(currentLine,
+                                              MARKNUM_EDITPOSLOC);
+            }
+
+            if (this.editClearNextStack) {
+                if (this.nextEditStack.length > 0) {
+                    this.nextEditStack.clear();
+                    this.updateCommands();
+                }
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    addPositionToStack : function(toStack, view, position) {
+        //keep this function bloody FAST
+        try {
+            var cleared = false;
+            if (this.editClearNextStack) {
+                if (this.nextEditStack.length > 0) {
+                    this.nextEditStack.clear();
+                    cleared = true;
+                }
+            }
+
+            var scimoz = view.scimoz;
+            var line = scimoz.lineFromPosition(position);
+            var marker = scimoz.markerAdd(line, MARKNUM_EDITPOSLOC);
+
+            //var msg = "new marker: "+line;
+            //StatusBar_AddMessage(msg, "debugger",5000,true);
+
+            toStack.push({
+                view : view,
+                position : position,
+                line: line,
+                col: scimoz.getColumn(position),
+                marker: marker});
+
+            if (toStack.length == 1 || cleared) {
+                // status will change only when the length was 0 and got 1
+                this.updateCommands();
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    updateCommands : function() {
+        this.enable("cmd_tabswitcher_goto_last_edit_position",
+                    this.lastEditStack.length > 0);
+        this.enable("cmd_tabswitcher_goto_next_edit_position",
+                    this.nextEditStack.length > 0);
+    },
+
+    enable : function(elementId, isEnabled) {
+        try {
+            var el = document.getElementById(elementId);
+
+            if (el) {
+                if (isEnabled) {
+                    el.removeAttribute("disabled");
+                } else {
+                    el.setAttribute("disabled", true);
+                }
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    goToLastEdit : function(index) {
+        this._popEditPosition(this.lastEditStack, index, this.nextEditStack,
+                              this.prefs.editRememberCurrentPos);
+    },
+
+    goToNextEdit : function(index) {
+        this._popEditPosition(this.nextEditStack, index, this.lastEditStack,
+                              false);
+    },
+
+    _showStacks : function(msg) {
+        try {
+            var last = this.lastEditStack.toString();
+            var next = this.nextEditStack.toString();
+
+            alert(msg+'\nlast:'+last+'\nnext:'+next);
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    _popEditPosition : function(fromStack, fromIndex, toStack, saveCurrent) {
+        try {
+
+            if (fromStack.length == 0) {
+                return false;
+            }
+
+            if (fromIndex == 0 && this.isEditOnCurrentView(fromStack.peek())) {
+                fromIndex = 1;
+            }
+
+            // elements are retrieved starting from end of array
+            // if fromIndex < 0 editPos is undefined
+            fromIndex = fromStack.items.length - 1 - fromIndex;
+
+            var editPos = fromStack.items[fromIndex];
+
+            if (!editPos) {
+                return false;
+            }
+
+            if (saveCurrent && toStack.length == 0){
+                //this._showStacks('before');
+                if (!this.isEditOnCurrentView(fromStack.peek())) {
+                    var currentView = ko.views.manager.currentView;
+                    this.addPositionToStack(toStack,
+                                            currentView, currentView.scimoz.currentPos);
+                    //this._showStacks('after');
+                }
+            }
+
+            var elementToMoveCount = fromStack.items.length;
+            for (var i = elementToMoveCount - 1; i >= fromIndex ; i--) {
+                toStack.push(fromStack.items[i]);
+            }
+
+            //no need to delete the marker here, because the whole
+            //item moves to the other stack
+            fromStack.items.splice(fromIndex, elementToMoveCount - fromIndex);
+            editPos.view.makeCurrent();
+            var scimoz = editPos.view.scimoz;
+
+            var line = scimoz.markerLineFromHandle(editPos.marker);
+            if (line == -1) {
+                //marker gone or whatever
+                scimoz.setSel(-1, editPos.position);
+            } else {
+                scimoz.gotoPos(scimoz.positionAtColumn(line, editPos.col));
+            }
+
+            this.updateCommands();
+
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+
+        return true;
+    },
+
+    removeAll : function() {
+        this.lastEditStack.clear();
+        this.nextEditStack.clear();
+        this.updateCommands();
+    },
+
+    initLastEditPopupMenu : function(menu) {
+        this.initPopupMenu(menu,
+                           this.lastEditStack,
+                           "gEditPosition.goToLastEdit(%1)");
+    },
+
+    initNextEditPopupMenu : function(menu) {
+        this.initPopupMenu(menu,
+                           this.nextEditStack,
+                           "gEditPosition.goToNextEdit(%1)");
+    },
+
+    initPopupMenu : function(menuPrefix, stack, command) {
+        try {
+            var menu = document.getElementById(menuPrefix + "-menubox");
+            DafizillaCommon.removeMenuItems(menu);
+
+            var items = stack.items;
+            var count = items.length - 1;
+            var index = 0;
+
+            // don't show current view
+            if (this.isEditOnCurrentView(items[count])) {
+                index = 1;
+            }
+            var itemsToAdd = this.prefs.maxVisibleMenuItems;
+            for (; index <= count && itemsToAdd > 0; index++, --itemsToAdd) {
+                var item = items[count - index];
+                var view = item.view;
+                var mi = document.createElement("menuitem");
+                // show line and column, but scimoz is 0 based
+                var text = view.title+" l:"+(item.line+1)+" c:"+(item.col+1);
+                mi.setAttribute("label", text);
+                mi.setAttribute("crop", "center");
+                mi.setAttribute("tooltiptext", view.document.displayPath);
+                mi.setAttribute("oncommand", command.replace("%1", index));
+                menu.appendChild(mi);
+            }
+
+            if (menu.hasChildNodes()) {
+                document.getElementById(menuPrefix + "-menuseparator")
+                    .removeAttribute("collapsed");
+            } else {
+                document.getElementById(menuPrefix + "-menuseparator")
+                    .setAttribute("collapsed", "true");
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    isEditOnCurrentView : function(editPos) {
+        //check if the passed position IS the current
+        try {
+            if (editPos) {
+                var currentView = ko.views.manager.currentView;
+
+                if (currentView.document) {
+                    var currPos = currentView.scimoz.currentPos;
+                    var currLine = currentView.scimoz.lineFromPosition(currPos);
+
+                    //if (currentView == editPos.view && currPos == editPos.position) {
+                    if (currentView == editPos.view && currLine == editPos.line) {
+                        return true;
+                    }
+                }
+            }
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+        return false;
+    },
+
+    addListeners : function() {
+        try {
+            var self = this;
+
+            this.handle_current_view_check_status_setup = function(event) {
+                //StatusBar_AddMessage("handle_current_view_check_status_setup", "debugger",5000,true);
+
+                self.pushEdit();
+            };
+
+            this.handle_view_opened_setup = function(event) {
+                self.viewOpened(event.originalTarget);
+            };
+
+            this.handle_view_closed_setup = function(event) {
+                self.viewClosed(event.originalTarget);
+            };
+
+            if (this.prefs.editCompatibility) {
+                window.addEventListener('current_view_check_status',
+                                        this.handle_current_view_check_status_setup, false);
+            };
+
+            window.addEventListener('view_opened',
+                                    this.handle_view_opened_setup, false);
+            window.addEventListener('view_closed',
+                                    this.handle_view_closed_setup, false);
+
+            //DafizillaCommon.log("addEventListener done");
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    removeListeners : function() {
+        try {
+            if (this.prefs.editCompatibility) {
+                window.removeEventListener('current_view_check_status',
+                                        this.handle_current_view_check_status_setup, false);
+            };
+            window.removeEventListener('view_opened',
+                                    this.handle_view_opened_setup, false);
+            window.removeEventListener('view_closed',
+                                    this.handle_view_closed_setup, false);
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    viewClosed : function(view) {
+        try {
+            try {
+                view.removeModifiedHandler(this.viewModifiedHandler);
+            } catch (e) {
+                };
+            this.removeView(view, this.lastEditStack.items);
+            this.removeView(view, this.nextEditStack.items);
+            this.updateCommands();
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    viewModifiedHandler : function(position, modificationType,
+                                   text, length, linesAdded, line,
+                                   foldLevelNow, foldLevelPrev) {
+        try {
+            try {
+                gEditPosition.pushEdit(this, position);
+            } catch (err) {
+                DafizillaCommon.exception(err);
+            };
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    },
+
+    viewOpened : function(view) {
+        try {
+            if (view.document) {
+                if (this.prefs.editShowMarkers) {
+                    var scimoz = view.scimoz;
+
+                    scimoz.markerDefine(MARKNUM_EDITPOSLOC, scimoz.SC_MARK_CIRCLEPLUS);
+                    scimoz.markerSetFore(MARKNUM_EDITPOSLOC, this.fgColor); // black
+                    scimoz.markerSetBack(MARKNUM_EDITPOSLOC, this.bgColor); // cyan
+
+                    //scimoz.setMarginMaskN(2, 0x0FFFF);
+                    scimoz.setMarginMaskN(2,
+                                          ko.markers.MARKERS_MASK_SYMBOLS |
+                                          (1 << MARKNUM_EDITPOSLOC));
+
+                    //ko.statusBar.AddMessage(
+                    //    "history marker patch done",
+                    //    "open_errs", 3000, true);
+                }
+
+                if (!this.prefs.editCompatibility) {
+                    var wantedflags = (
+                           Components.interfaces.ISciMoz.SC_MOD_INSERTTEXT |
+                           Components.interfaces.ISciMoz.SC_MOD_DELETETEXT);
+
+                    view.addModifiedHandler(this.viewModifiedHandler, view,
+                                            100, wantedflags);
+
+                    //DafizillaCommon.log("patch done");
+                };
+                //DafizillaCommon.log("viewOpened");
+            };
+        } catch (err) {
+            DafizillaCommon.exception(err);
+        }
+    }
+}
+
+window.addEventListener("load", function(event) {gEditPosition.onLoad(event)}, false);
+window.addEventListener("unload", function(event) {gEditPosition.onUnLoad(event)}, false);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/htmlutils.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2004 ThoughtWorks, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+ 
+// This script contains some HTML utility functions that
+// make it possible to handle elements in a way that is 
+// compatible with both IE-like and Mozilla-like browsers
+
+// 29/mar/2008 Added globCaseContains by davide ficano <davide.ficano@gmail.com>
+
+String.prototype.trim = function() {
+  var result = this.replace( /^\s+/g, "" );// strip leading
+  return result.replace( /\s+$/g, "" );// strip trailing
+};
+String.prototype.lcfirst = function() {
+   return this.charAt(0).toLowerCase() + this.substr(1);
+};
+String.prototype.ucfirst = function() {
+   return this.charAt(0).toUpperCase() + this.substr(1);
+};
+String.prototype.startsWith = function(str) {
+    return this.indexOf(str) == 0;
+};
+
+// Returns the text in this element
+function getText(element) {
+    text = "";
+
+    if(browserVersion.isFirefox)
+    {
+        var dummyElement = element.cloneNode(true);
+        renderWhitespaceInTextContent(dummyElement);
+        text = dummyElement.textContent;
+    }
+    else if(element.textContent)
+    {
+        text = element.textContent;
+    }
+    else if(element.innerText)
+    {
+        text = element.innerText;
+    }
+
+    text = normalizeNewlines(text);
+    text = normalizeSpaces(text);
+
+    return text.trim();
+}
+
+function renderWhitespaceInTextContent(element) {
+    // Remove non-visible newlines in text nodes
+    if (element.nodeType == Node.TEXT_NODE)
+    {
+        element.data = element.data.replace(/\n|\r/g, " ");
+        return;
+    }
+
+    // Don't modify PRE elements
+    if (element.tagName == "PRE")
+    {
+        return;
+    }
+
+    // Handle inline element that force newlines
+    if (tagIs(element, ["BR", "HR"]))
+    {
+        // Replace this element with a newline text element
+        element.parentNode.replaceChild(document.createTextNode("\n"), element)
+    }
+
+    for (var i = 0; i < element.childNodes.length; i++)
+    {
+        var child = element.childNodes.item(i)
+        renderWhitespaceInTextContent(child);
+    }
+
+    // Handle block elements that introduce newlines
+// -- From HTML spec:
+//<!ENTITY % block
+//     "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT |
+//      BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">
+    if (tagIs(element, ["P", "DIV"]))
+    {
+        element.appendChild(document.createTextNode("\n"), element)
+    }
+}
+
+function tagIs(element, tags)
+{
+    var tag = element.tagName;
+    for (var i = 0; i < tags.length; i++)
+    {
+        if (tags[i] == tag)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * Convert all newlines to \m
+ */
+function normalizeNewlines(text)
+{
+    return text.replace(/\r\n|\r/g, "\n");
+}
+
+/**
+ * Replace multiple sequential spaces with a single space, and then convert &nbsp; to space.
+ */
+function normalizeSpaces(text)
+{
+    // IE has already done this conversion, so doing it again will remove multiple nbsp
+    if (browserVersion.isIE)
+    {
+        return text;
+    }
+
+    // Replace multiple spaces with a single space
+    // TODO - this shouldn't occur inside PRE elements
+    text = text.replace(/\ +/g, " ");
+
+    // Replace &nbsp; with a space
+    var pat = String.fromCharCode(160); // Opera doesn't like /\240/g
+   	var re = new RegExp(pat, "g");
+    return text.replace(re, " ");
+}
+
+// Sets the text in this element
+function setText(element, text) {
+    if(element.textContent) {
+        element.textContent = text;
+    } else if(element.innerText) {
+        element.innerText = text;
+    }
+}
+
+// Get the value of an <input> element
+function getInputValue(inputElement) {
+    if (inputElement.type.toUpperCase() == 'CHECKBOX' || 
+        inputElement.type.toUpperCase() == 'RADIO') 
+    {
+        return (inputElement.checked ? 'on' : 'off');
+    }
+    return inputElement.value;
+}
+
+/* Fire an event in a browser-compatible manner */
+function triggerEvent(element, eventType, canBubble) {
+    canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
+    if (element.fireEvent) {
+        element.fireEvent('on' + eventType);
+    }
+    else {
+        var evt = document.createEvent('HTMLEvents');
+        evt.initEvent(eventType, canBubble, true);
+        element.dispatchEvent(evt);
+    }
+}
+
+function triggerKeyEvent(element, eventType, keycode, canBubble) {
+    canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
+    if (element.fireEvent) {
+		keyEvent = parent.frames['myiframe'].document.createEventObject();
+		keyEvent.keyCode=keycode;
+		element.fireEvent('on' + eventType, keyEvent);
+    }
+    else {
+        var evt = document.createEvent('KeyEvents');
+        evt.initKeyEvent(eventType, true, true, window, false, false, false, false, keycode, keycode);
+        element.dispatchEvent(evt);
+    }
+}
+
+/* Fire a mouse event in a browser-compatible manner */
+function triggerMouseEvent(element, eventType, canBubble) {
+    canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
+    if (element.fireEvent) {
+        element.fireEvent('on' + eventType);
+    }
+    else {
+        var evt = document.createEvent('MouseEvents');
+        if (evt.initMouseEvent)
+        {
+            evt.initMouseEvent(eventType, canBubble, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null)
+        }
+        else
+        {
+            // Safari
+            // TODO we should be initialising other mouse-event related attributes here
+            evt.initEvent(eventType, canBubble, true);
+        }
+        element.dispatchEvent(evt);
+    }
+}
+
+function removeLoadListener(element, command) {
+    if (window.removeEventListener)
+        element.removeEventListener("load", command, true);
+    else if (window.detachEvent)
+        element.detachEvent("onload", command);
+}
+
+function addLoadListener(element, command) {
+    if (window.addEventListener && !browserVersion.isOpera)
+        element.addEventListener("load",command, true);
+    else if (window.attachEvent)
+        element.attachEvent("onload",command);
+}
+
+function addUnloadListener(element, command) {
+    if (window.addEventListener)
+        element.addEventListener("unload",command, true);
+    else if (window.attachEvent)
+        element.attachEvent("onunload",command);
+}
+
+/**
+ * Override the broken getFunctionName() method from JsUnit
+ * This file must be loaded _after_ the jsunitCore.js
+ */
+function getFunctionName(aFunction) {
+  var regexpResult = aFunction.toString().match(/function (\w*)/);
+  if (regexpResult && regexpResult[1]) {
+      return regexpResult[1];
+  }
+  return 'anonymous';
+}
+
+function describe(object, delimiter) {
+    var props = new Array();
+    for (var prop in object) {
+        props.push(prop + " -> " + object[prop]);
+    }
+    return props.join(delimiter || '\n');
+}
+
+PatternMatcher = function(pattern) {
+    this.selectStrategy(pattern);
+};
+PatternMatcher.prototype = {
+
+    selectStrategy: function(pattern) {
+        this.pattern = pattern;
+        var strategyName = 'glob'; // by default
+        if (/^([a-z-]+):(.*)/.test(pattern)) {
+            strategyName = RegExp.$1;
+            pattern = RegExp.$2;
+        }
+        var matchStrategy = PatternMatcher.strategies[strategyName];
+        if (!matchStrategy) {
+            throw new SeleniumError("cannot find PatternMatcher.strategies." + strategyName);
+        }
+        this.strategy = matchStrategy;
+        this.matcher = new matchStrategy(pattern);
+    },
+
+    matches: function(actual) {
+        return this.matcher.matches(actual + '');
+        // Note: appending an empty string avoids a Konqueror bug
+    }
+
+};
+
+/**
+ * A "static" convenience method for easy matching
+ */
+PatternMatcher.matches = function(pattern, actual) {
+    return new PatternMatcher(pattern).matches(actual);
+};
+
+PatternMatcher.strategies = {
+
+    /**
+     * Exact matching, e.g. "exact:***"
+     */
+    exact: function(expected) {
+        this.expected = expected;
+        this.matches = function(actual) {
+            return actual == this.expected;
+        };
+    },
+
+    /**
+     * Match by regular expression, e.g. "regexp:^[0-9]+$"
+     */
+    regexp: function(regexpString) {
+        this.regexp = new RegExp(regexpString);
+        this.matches = function(actual) {
+            return this.regexp.test(actual);
+        };
+    },
+
+    /**
+     * "globContains" (aka "wildmat") patterns, e.g. "glob:one,two,*", 
+     * but don't require a perfect match; instead succeed if actual
+     * contains something that matches globString.
+     * Making this distinction is motivated by a bug in IE6 which 
+     * leads to the browser hanging if we implement *TextPresent tests 
+     * by just matching against a regular expression beginning and 
+     * ending with ".*".  The globcontains strategy allows us to satisfy 
+     * the functional needs of the *TextPresent ops more efficiently 
+     * and so avoid running into this IE6 freeze.
+     */
+    globContains: function(globString) {
+        this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString));
+        this.matches = function(actual) {
+            return this.regexp.test(actual);
+        };
+    },
+    
+    /**
+     * Identical to globContains but allows case insensitive search
+     * 29/Mar/2008 Added by davide ficano <davide.ficano@gmail.com>
+     */
+    globCaseContains: function(globString, matchCase) {
+        if (matchCase) {
+          this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString));
+        } else {
+          this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString), "i");
+        }
+        this.matches = function(actual) {
+            return this.regexp.test(actual);
+        };
+    },
+
+    /**
+     * "glob" (aka "wildmat") patterns, e.g. "glob:one,two,*"
+     */
+    glob: function(globString) {
+        this.regexp = new RegExp(PatternMatcher.regexpFromGlob(globString));
+        this.matches = function(actual) {
+            return this.regexp.test(actual);
+        };
+    }
+    
+};
+
+PatternMatcher.convertGlobMetaCharsToRegexpMetaChars = function(glob) {
+    var re = glob;
+    re = re.replace(/([.^$+(){}\[\]\\|])/g, "\\$1");
+    re = re.replace(/\?/g, "(.|[\r\n])");
+    re = re.replace(/\*/g, "(.|[\r\n])*");
+    return re;
+};
+
+PatternMatcher.regexpFromGlobContains = function(globContains) {
+    return PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(globContains);
+};
+
+PatternMatcher.regexpFromGlob = function(glob) {
+    return "^" + PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(glob) + "$";
+};
+
+var Assert = {
+
+    fail: function(message) {
+        throw new AssertionFailedError(message);
+    },
+
+    /*
+     * Assert.equals(comment?, expected, actual)
+     */
+    equals: function() {
+        var args = new AssertionArguments(arguments);
+        if (args.expected === args.actual) {
+            return;
+        }
+        Assert.fail(args.comment + 
+                    "Expected '" + args.expected + 
+                    "' but was '" + args.actual + "'");
+    },
+
+    /*
+     * Assert.matches(comment?, pattern, actual)
+     */
+    matches: function() {
+        var args = new AssertionArguments(arguments);
+        if (PatternMatcher.matches(args.expected, args.actual)) {
+            return;
+        }
+        Assert.fail(args.comment + 
+                    "Actual value '" + args.actual + 
+                    "' did not match '" + args.expected + "'");
+    },
+    
+    /*
+     * Assert.notMtches(comment?, pattern, actual)
+     */
+    notMatches: function() {
+        var args = new AssertionArguments(arguments);
+        if (!PatternMatcher.matches(args.expected, args.actual)) {
+            return;
+        }
+        Assert.fail(args.comment + 
+                    "Actual value '" + args.actual + 
+                    "' did match '" + args.expected + "'");
+    }
+
+};
+
+// Preprocess the arguments to allow for an optional comment.
+function AssertionArguments(args) {
+    if (args.length == 2) {
+        this.comment = "";
+        this.expected = args[0];
+        this.actual = args[1];
+    } else {
+        this.comment = args[0] + "; ";
+        this.expected = args[1];
+        this.actual = args[2];
+    }
+}
+
+
+
+function AssertionFailedError(message) {
+    this.isAssertionFailedError = true;
+    this.isSeleniumError = true;
+    this.message = message;
+    this.failureMessage = message;
+}
+
+function SeleniumError(message) {
+    var error = new Error(message);
+    error.isSeleniumError = true;
+    return error;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-editposition.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,84 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+var prefs = new TabSwitcherPrefs();
+var maxSizeEditPositionStackWidget;
+var maxVisibleMenuItemsWidget;
+var editGranularityWidget;
+var editClearNextStackWidget;
+var editRememberCurrentPosWidget;
+var editShowMarkersWidget;
+var editCompatibilityWidget;
+ 
+function OnPreferencePageOK(prefset) {
+    prefs.maxSizeEditPositionStack = maxSizeEditPositionStackWidget.value;
+    prefs.maxVisibleMenuItems = maxVisibleMenuItemsWidget.value;
+    prefs.editGranularity = editGranularityWidget.value;
+    prefs.editClearNextStack = editClearNextStackWidget.checked;
+    prefs.editRememberCurrentPos = editRememberCurrentPosWidget.checked;
+    prefs.editShowMarkers = editShowMarkersWidget.checked;
+    prefs.editCompatibility = editCompatibilityWidget.checked;
+
+    prefs.save();
+    var obs = DafizillaCommon.getObserverService();
+    obs.notifyObservers(null, "tabswitcher_pref_changed", null);
+    return true;
+}
+
+function OnPreferencePageInitalize(prefset) {
+    maxSizeEditPositionStackWidget = document.getElementById("maxSizeEditPositionStack");
+    maxVisibleMenuItemsWidget = document.getElementById("maxVisibleMenuItems");
+    editGranularityWidget = document.getElementById("editGranularity");
+    editClearNextStackWidget = document.getElementById("editClearNextStack");
+    editRememberCurrentPosWidget = document.getElementById("editRememberCurrentPos");
+    editShowMarkersWidget = document.getElementById("editShowMarkers");
+    editCompatibilityWidget = document.getElementById("editCompatibility");
+}
+
+function OnPreferencePageLoading(prefset) {
+    prefs.load();
+    maxSizeEditPositionStackWidget.value = prefs.maxSizeEditPositionStack;
+    maxVisibleMenuItemsWidget.value = prefs.maxVisibleMenuItems;
+    editGranularityWidget.value = prefs.editGranularity;
+    editClearNextStackWidget.checked = prefs.editClearNextStack;
+    editRememberCurrentPosWidget.checked = prefs.editRememberCurrentPos;
+    editShowMarkersWidget.checked = prefs.editShowMarkers;
+    editCompatibilityWidget.checked = prefs.editCompatibility;
+}
+
+function editPositionOnLoad() {
+    parent.hPrefWindow.onpageload();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-editposition.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://tabswitcher/locale/pref.dtd" >
+
+<window xmlns:html="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+    orient="vertical"
+    onload="editPositionOnLoad();">
+
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/common.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/commonPrefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/prefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/pref/pref-editposition.js" />
+
+  <groupbox orient="vertical">
+    <caption label="&edit.position.label;"/>
+
+    <grid flex="1">
+        <columns>
+            <column flex="1"/>
+            <column/>
+            <column/>
+        </columns>
+
+        <rows>
+            <row align="center">
+              <label value="&number.edit.position.store;" />
+              <textbox id="maxSizeEditPositionStack" size="4"/>
+            </row>
+            <row id="row-cmdargs" align="center">
+              <label value="&number.visible.menu.items;" />
+              <textbox id="maxVisibleMenuItems" size="4"/>
+            </row>
+            <row align="center">
+              <label value="&edit.position.granularity.label;" />
+              <menulist id="editGranularity">
+                <menupopup>
+                  <menuitem label="&edit.granularity.1;" value="1"/>
+                  <menuitem label="&edit.granularity.2;" value="2"/>
+                  <menuitem label="&edit.granularity.3;" value="3"/>
+                  <menuitem label="&edit.granularity.5;" value="5"/>
+                  <menuitem label="&edit.granularity.7;" value="7"/>
+                  <menuitem label="&edit.granularity.10;" value="10"/>
+                  <menuitem label="&edit.granularity.15;" value="15"/>
+                  <menuitem label="&edit.granularity.single;" value="s"/>
+                </menupopup>
+              </menulist>
+            </row>
+            <row align="center">
+              <checkbox id="editClearNextStack"
+                label="&edit.editClearNextStack.label;"
+                checked="false"/>
+            </row>
+            <row align="center">
+              <checkbox id="editRememberCurrentPos"
+                label="&edit.editRememberCurrentPos.label;"
+                checked="false"/>
+            </row>
+            <row align="center">
+              <checkbox id="editShowMarkers"
+                label="&edit.editShowMarkers.label;"
+                tooltip="&edit.editShowMarkers.tooltip;"
+                checked="false"/>
+            </row>
+            <row align="center">
+              <checkbox id="editCompatibility"
+                label="&edit.editCompatibility.label;"
+                tooltip="&edit.editCompatibility.tooltip;"
+                checked="false"/>
+            </row>
+            <label value="&edit.editCompatibility.text1;" />
+            <label value="&edit.editCompatibility.text2;" />
+
+        </rows>
+    </grid>
+
+  </groupbox>
+</window>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-main.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://tabswitcher/skin/tabSwitcher.css" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://tabswitcher/locale/pref.dtd" >
+
+<window xmlns:html="http://www.w3.org/1999/xhtml"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        orient="vertical">
+
+    <groupbox>
+        <caption label="&tabswitcher.label;"/>
+        <description style="margin-top: 10px;">
+            &tabswitcher.description;
+        </description>
+
+        <separator class="thin"/>
+        <label value="&homepage.label;"
+               id="homepageLink"
+               tooltiptext="&homepage.tooltip;"
+               class="link"
+               url="&homepage.url;"
+               onclick="parent.opener.ko.browse.openUrlInDefaultBrowser(this.getAttribute('url'))"/>
+    </groupbox>
+    <separator class="thin"/>
+
+</window>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-ordertabs.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,73 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+var prefs = new TabSwitcherPrefs();
+var orderTabsAutoWidget;
+var orderTabsType;
+
+function OnPreferencePageOK(prefset) {
+    prefs.orderTabsAuto = orderTabsAutoWidget.checked;
+    prefs.orderTabsType = orderTabsType.value;
+
+    prefs.save();
+    var obs = DafizillaCommon.getObserverService();
+    obs.notifyObservers(null, "tabswitcher_pref_changed", null);
+    return true;
+}
+
+function OnPreferencePageInitalize(prefset) {
+    orderTabsAutoWidget = document.getElementById("orderTabsAuto");
+    orderTabsType =  document.getElementById("orderTabsType");
+    orderTabsAutoWidget.addEventListener("CheckboxStateChange", onChangeOrderTabsAuto, false);
+}
+
+function OnPreferencePageLoading(prefset) {
+    prefs.load();
+    orderTabsAutoWidget.checked = prefs.orderTabsAuto;
+    orderTabsType.value = prefs.orderTabsType;
+}
+
+function orderTabsOnLoad() {
+    parent.hPrefWindow.onpageload();
+}
+
+function onChangeOrderTabsAuto(event) {
+    if (orderTabsAutoWidget.checked) {
+        orderTabsType.removeAttribute("disabled");
+    } else {
+        orderTabsType.setAttribute("disabled", "true");
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-ordertabs.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://tabswitcher/locale/pref.dtd" >
+ 
+<window xmlns:html="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+    orient="vertical"
+    onload="orderTabsOnLoad();">
+
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/common.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/commonPrefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/prefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/pref/pref-ordertabs.js" />
+
+  <groupbox orient="vertical">
+    <caption>
+      <checkbox id="orderTabsAuto"
+                label="&tabs.order.auto.label;"
+                checked="false"/>
+    </caption>
+
+      <menulist id="orderTabsType" disabled="true">
+        <menupopup>
+          <menuitem label="&tabs.order.sort.by.name;" value="n"/>
+          <menuitem label="&tabs.order.group.by.ext;" value="e"/>
+        </menupopup>
+      </menulist>
+  </groupbox>
+</window>
+ 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-switchview.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,60 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+var prefs = new TabSwitcherPrefs();
+var showLastUsedPatternWidget;
+
+function OnPreferencePageOK(prefset) {
+    prefs.showLastUsedPattern = showLastUsedPatternWidget.checked;
+
+    prefs.save();
+    var obs = DafizillaCommon.getObserverService();
+    obs.notifyObservers(null, "tabswitcher_pref_changed", null);
+    return true;
+}
+
+function OnPreferencePageInitalize(prefset) {
+    showLastUsedPatternWidget = document.getElementById("showLastUsedPattern");
+}
+
+function OnPreferencePageLoading(prefset) {
+    prefs.load();
+    showLastUsedPatternWidget.checked = prefs.showLastUsedPattern;
+}
+
+function switchViewOnLoad() {
+    parent.hPrefWindow.onpageload();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/pref-switchview.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://tabswitcher/locale/pref.dtd" >
+ 
+<window xmlns:html="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+    orient="vertical"
+    onload="switchViewOnLoad();">
+
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/common.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/commonPrefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/prefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/pref/pref-switchview.js" />
+
+  <groupbox orient="vertical">
+    <caption label="&switch.view.label;"/>
+
+    <checkbox id="showLastUsedPattern" label="&show.last.used.pattern.label;" />
+
+  </groupbox>
+</window>
+ 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/pref/prefOverlay.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/pref.dtd" >
+
+<overlay id="tabswitcherPrefOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <hbox id="prefsTree">
+        <treechildren id="panelChildren">
+            <treeitem container="true" id="uiTabSwitcherMain">
+                <treerow>
+                    <treecell class="treecell-indent"
+                              url="chrome://tabswitcher/content/pref/pref-main.xul"
+                              label="&tabswitcher.label;"/>
+                </treerow>
+
+                <treechildren id="uiTabSwitcherLastEditPosition">
+                    <treeitem container="false" id="editLastModificationStatusbar">
+                        <treerow>
+                            <treecell class="treecell-indent"
+                              url="chrome://tabswitcher/content/pref/pref-editposition.xul"
+                                      label="&edit.position.label;"/>
+                        </treerow>
+                    </treeitem>
+
+                    <treeitem container="false" id="switchView">
+                        <treerow>
+                            <treecell class="treecell-indent"
+                              url="chrome://tabswitcher/content/pref/pref-switchview.xul"
+                                      label="&switch.view.label;"/>
+                        </treerow>
+                    </treeitem>
+
+                    <treeitem container="false" id="ordertabs">
+                        <treerow>
+                            <treecell class="treecell-indent"
+                              url="chrome://tabswitcher/content/pref/pref-ordertabs.xul"
+                                      label="&tabs.order.label;"/>
+                        </treerow>
+                    </treeitem>
+                </treechildren>
+
+            </treeitem>
+        </treechildren>
+    </hbox>
+</overlay>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/prefs.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,170 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+const TAB_SWITCHER_DEFAULT_MAX_SIZE_STACK = 10;
+const TAB_SWITCHER_DEFAULT_MAX_VISIBILE_ITEMS = 5;
+const TAB_SWITCHER_DEFAULT_CASE_TYPE = "ic";
+const TAB_SWITCHER_DEFAULT_SHOW_LAST_USED_PATTERN = true;
+
+const TAB_SWITCHER_DEFAULT_EDIT_TYPE = "1";
+
+function TabSwitcherPrefs() {
+    DafizillaPrefs.call(this, "extensions.tabswitcher.");
+}
+
+TabSwitcherPrefs.prototype = new DafizillaPrefs();
+
+TabSwitcherPrefs.prototype.__defineGetter__("maxSizeEditPositionStack",
+function() {
+    return this.getString("maxSizeEditPositionStack", TAB_SWITCHER_DEFAULT_MAX_SIZE_STACK);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("maxSizeEditPositionStack",
+function(value) {
+    this.setSafeInt("maxSizeEditPositionStack", value, TAB_SWITCHER_DEFAULT_MAX_SIZE_STACK);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("maxVisibleMenuItems",
+function() {
+    return this.getString("maxVisibleMenuItems", TAB_SWITCHER_DEFAULT_MAX_VISIBILE_ITEMS);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("maxVisibleMenuItems",
+function(value) {
+    this.setSafeInt("maxVisibleMenuItems", value, TAB_SWITCHER_DEFAULT_MAX_VISIBILE_ITEMS);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("editGranularity",
+function() {
+    return this.getString("caseType", TAB_SWITCHER_DEFAULT_EDIT_TYPE);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("editGranularity",
+function(value) {
+    this.setString("caseType", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("editClearNextStack",
+function() {
+    return this.getBool("editClearNextStack", false);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("editClearNextStack",
+function(value) {
+    this.setBool("editClearNextStack", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("editRememberCurrentPos",
+function() {
+    return this.getBool("editRememberCurrentPos", false);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("editRememberCurrentPos",
+function(value) {
+    this.setBool("editRememberCurrentPos", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("editShowMarkers",
+function() {
+    return this.getBool("editShowMarkers", false);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("editShowMarkers",
+function(value) {
+    this.setBool("editShowMarkers", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("editCompatibility",
+function() {
+    return this.getBool("editCompatibility", false);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("editCompatibility",
+function(value) {
+    this.setBool("editCompatibility", value);
+});
+
+
+TabSwitcherPrefs.prototype.__defineGetter__("caseType",
+function() {
+    return this.getString("caseType", TAB_SWITCHER_DEFAULT_CASE_TYPE);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("caseType",
+function(value) {
+    this.setString("caseType", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("showLastUsedPattern",
+function() {
+    return this.getBool("showLastUsedPattern", TAB_SWITCHER_DEFAULT_SHOW_LAST_USED_PATTERN);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("showLastUsedPattern",
+function(value) {
+    this.setBool("showLastUsedPattern", value);
+});
+
+TabSwitcherPrefs.prototype.__defineGetter__("orderTabsAuto",
+function() {
+    return this.getBool("orderTabsAuto", false);
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("orderTabsAuto",
+function(value) {
+    this.setBool("orderTabsAuto", value);
+});
+
+
+TabSwitcherPrefs.prototype.__defineGetter__("orderTabsType",
+function() {
+    return this.getString("orderTabsType", "n");
+});
+
+TabSwitcherPrefs.prototype.__defineSetter__("orderTabsType",
+function(value) {
+    this.setString("orderTabsType", value);
+});
+
+TabSwitcherPrefs.prototype.setSafeInt = function(prefName, prefValue, defPrefValue) {
+    var v = DafizillaPrefs.safeInt(prefValue, defPrefValue,
+                                   function(value) {
+                return DafizillaPrefs.checkers.checkGreaterOrEqualThan(
+                        value, defPrefValue);
+                });
+
+    this.setString(prefName, v);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabSwitcher/tabSwitcher.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,183 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+var gTabSwitcher = {
+    onLoad : function() {
+        try {
+            this.isInputInProgress = false;
+            this.tabTreeView = new TabTreeView(
+                        document.getElementById("view-tree"),
+                        this.getAllOpenDocumentViews());
+            this.tabTreeView.currentWindow = ko.windowManager.getMainWindow();
+            this.tabTreeView.refresh();
+            document.getElementById("view-title").focus();
+            
+            this.caseCheckbox = document.getElementById("switch-case");
+
+            this.prefs = new TabSwitcherPrefs();
+            this.prefs.load();
+            this.setSearchCase(this.prefs.caseType);
+
+            if (this.prefs.showLastUsedPattern) {
+                document.getElementById("view-title").value = window.arguments[0].searchPattern;
+                document.getElementById("view-title").select();
+                this.onInput(document.getElementById("view-title"));
+            }
+        } catch (err) {
+            alert(err);
+        }
+    },
+
+    getAllOpenDocumentViews : function() {
+        var views = [];
+        var windows = ko.windowManager.getWindows();
+        var winInfo = {
+            win : null,
+            number : 0,
+            hasNumberWindow : windows.length > 1
+        };
+        
+        for (var i in windows) {
+            var w = windows[i];
+
+            winInfo.win = w;
+            ++winInfo.number;
+            var arr = w.ko.views.manager.topView.getDocumentViews(true);
+            arr.forEach(this.addWindowAttribute, winInfo);
+            views = views.concat(arr);
+        }
+        return views;
+    },
+    
+    addWindowAttribute : function(element, index, array) {
+        element._ts_window = this.win;
+        element._ts_title = this.hasNumberWindow
+            ? "[" + this.number + "] " + element.title
+            : element.title;
+    },
+    
+    toogleSearchCase : function (event) {
+        switch (this.caseCheckbox.value) {
+            case "ic":
+                this.setSearchCase("mc");
+                break;
+            case "mc":
+                this.setSearchCase("sc");
+                break;
+            case "sc":
+                this.setSearchCase("ic");
+                break;
+            default:
+                return;
+        }
+        this.onInput(document.getElementById("view-title"));
+    },
+    
+    setSearchCase : function(caseType, optionCaseType) {
+        var isCaseTypeValid = caseType == "ic" || caseType == "mc" || caseType == "sc";
+        
+        if (!isCaseTypeValid) {
+            caseType = "ic";
+        }
+        this.caseCheckbox.label = this.caseCheckbox.getAttribute("label-" + caseType);
+        this.caseCheckbox.value = this.caseCheckbox.getAttribute("value-" + caseType);
+        this.caseCheckbox.accessKey = this.caseCheckbox.getAttribute("accessKey-" + caseType);
+        this.caseCheckbox.checked = this.caseCheckbox.getAttribute("checked-" + caseType) == "true";
+    },
+
+    onInput : function(text) {
+        this.isInputInProgress = true;
+        this.tabTreeView.selectText(text.value, this.caseCheckbox.value);
+        this.tabTreeView.refresh();
+        this.tabTreeView.selectAndEnsureVisible(0);
+
+        var selectedItem = this.tabTreeView.currentSelectedItem;
+        var path = "";
+        if (selectedItem && selectedItem.document) {
+            path = selectedItem.document.file.dirName;
+        }
+        document.getElementById("view-path").value = path;
+        this.isInputInProgress = false;
+        
+        return true;
+    },
+
+    onKeyPress : function(event) {
+        if (event.keyCode == KeyEvent.DOM_VK_UP) {
+            this.tabTreeView.moveSelection(true);
+        } else if (event.keyCode == KeyEvent.DOM_VK_DOWN) {
+            this.tabTreeView.moveSelection(false);
+        }
+        return true;
+    },
+
+    onWindowKeyPress : function(event) {
+        if (event.keyCode == KeyEvent.DOM_VK_RETURN
+            || event.keyCode == KeyEvent.DOM_VK_ENTER) {
+            this.onAccept();
+        } else if (event.keyCode == KeyEvent.DOM_VK_ESCAPE) {
+            window.close();
+        }
+        return true;
+    },
+
+    onSelect : function() {
+        if (!this.isInputInProgress) {
+            var selectedItem = this.tabTreeView.currentSelectedItem;
+            if (selectedItem && selectedItem.document) {
+                document.getElementById("view-path").value = selectedItem.document.file.dirName;
+            }
+        }
+    },
+    
+    onDblClick : function() {
+        this.onAccept();
+    },
+
+    onAccept : function() {
+        if (this.tabTreeView.currentSelectedItem) {
+            this.tabTreeView.currentSelectedItem._ts_window.focus();
+            this.tabTreeView.currentSelectedItem.makeCurrent();
+        }
+        this.prefs.caseType = this.caseCheckbox.value;
+        this.prefs.save();
+
+        if (this.prefs.showLastUsedPattern) {
+            window.arguments[0].searchPattern = document.getElementById("view-title").value;
+        }
+        window.close();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabSwitcher/tabSwitcher.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://tabswitcher/skin/tabSwitcher.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/tabswitcher.dtd" >
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+    id="switchview-dialog"
+    title="&switchView.dialog.title;"
+    minwidth="300"
+    minheight="260"
+    onload="return gTabSwitcher.onLoad();"
+    persist="screenX screenY width height"
+    onkeypress="return gTabSwitcher.onWindowKeyPress(event)">
+
+    <!-- Komodo specific code -->
+    <script type="application/x-javascript"
+            src="chrome://komodo/content/library/logging.js" />
+    <script type="application/x-javascript"
+            src="chrome://komodo/content/library/windowManager.js" />
+
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/common.js" />
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/commonPrefs.js" />
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/prefs.js" />
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/htmlutils.js" />
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/tabSwitcher/tabSwitcherTreeview.js" />
+    <script type="application/x-javascript" src="chrome://tabswitcher/content/tabSwitcher/tabSwitcher.js" />
+
+    <vbox flex="1">
+        <textbox id="view-title"
+                  oninput="return gTabSwitcher.onInput(this)"
+                  onkeypress="return gTabSwitcher.onKeyPress(event)"/>
+        <checkbox id="switch-case"
+                  oncommand="gTabSwitcher.toogleSearchCase(event)"
+                  label="&match.case.label;" value="ic" accesskey="&match.case.accesskey;" checked="false"
+                  label-ic="&match.case.label;" value-ic="ic" accessKey-ic="&match.case.accesskey;" checked-ic="false"
+                  label-mc="&match.case.label;" value-mc="mc" accessKey-mc="&match.case.accesskey;" checked-mc="true"
+                  label-sc="&smart.case.label;" value-sc="sc" accessKey-sc="&smart.case.accesskey;" checked-sc="true"
+                  />
+        <textbox id="view-path" readonly="true"/>
+        <tree id="view-tree"
+                flex="1"
+                onselect="gTabSwitcher.onSelect()"
+                ondblclick="gTabSwitcher.onDblClick()"
+                hidecolumnpicker="true">
+          <treecols>
+            <treecol id="view-treecol"
+                      hideheader="true"
+                      flex="1"
+                      persist="width"/>
+          </treecols>
+          <treechildren class="viewListChildren" ondblclick="gTabSwitcher.onDblClick(event);"/>
+        </tree>
+    </vbox>
+</window>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabSwitcher/tabSwitcherTreeview.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,277 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+var selectedItemAtom = Components.classes["@mozilla.org/atom-service;1"]
+            .getService(Components.interfaces.nsIAtomService)
+            .getAtom("selectedItem");
+
+function TabTreeView(treeElement, items) {
+    this.treeElement = treeElement;
+    this.items = items.slice(0, items.length);
+    this.allItems = this.items;
+
+    this.treebox = null;
+    function sortByTitle(a, b) {
+        return a._ts_title.localeCompare(b._ts_title);
+    }
+
+    this.items.sort(sortByTitle);
+    this.treeElement.view = this;
+}
+
+TabTreeView.prototype = {
+
+    invalidate : function() {
+        this.treebox.invalidate();
+    },
+
+    swap : function(idx1, idx2) {
+        if ((idx1 == idx2) || (idx1 < 0) || (idx2 < 0)) {
+            return;
+        }
+        var temp = this.items[idx1];
+
+        this.items[idx1] = this.items[idx2];
+        this.items[idx2] = temp;
+    },
+
+    get currentSelectedItem() {
+        if (this.selection.currentIndex < 0) {
+            return null;
+        }
+        return this.items[this.selection.currentIndex];
+    },
+    
+    get selectedItems() {
+        var ar = [];
+        var selIndexes = this.selectedIndexes;
+
+        for (var i = 0; i < selIndexes.length; i++) {
+            ar.push(this.items[selIndexes[i]]);
+        }
+
+        return ar;
+    },
+
+    get selectedIndexes() {
+        var selection = this.selection;
+        var items = [];
+
+        for (var i = 0; i < selection.getRangeCount(); i++) {
+            var minIdx = {};
+            var maxIdx = {};
+            selection.getRangeAt(i, minIdx, maxIdx);
+            for (var selIdx = minIdx.value; selIdx <= maxIdx.value; selIdx++) {
+                items.push(selIdx);
+            }
+        }
+
+        return items;
+    },
+
+    deleteItems : function(items) {
+        if (items && items.length > 0) {
+            for (var i = items.length - 1; i >= 0; i--) {
+                this.items.splice(items[i], 1);
+            }
+            this.treebox.rowCountChanged(items[0], -items.length);
+        }
+    },
+
+    deleteSelectedItem : function() {
+        try {
+            var selIdx = this.selection.currentIndex;
+
+            if (selIdx < 0) {
+                return;
+            }
+            var newItems = new Array();
+
+            for (var i = 0; i < this.items.length; i++) {
+                if (i != selIdx) {
+                    newItems.push(this.items[i]);
+                }
+            }
+
+            this.items = newItems;
+            // -1 means remove (< 0)
+            this.treebox.rowCountChanged(selIdx, -1);
+
+            if (newItems.length > 0) {
+                this.selection.select(this.rowCount == selIdx ? selIdx - 1 : selIdx);
+            }
+        } catch (err) {
+            alert(err);
+        }
+    },
+
+    moveSelectedItem : function(moveUp) {
+        var view = this.treebox.view;
+        var fromIdx = view.selection.currentIndex;
+        var offset;
+
+        if (moveUp) {
+            if (fromIdx <= 0) {
+                return;
+            }
+            offset = -1;
+        } else {
+            if (fromIdx >= view.rowCount - 1) {
+                return;
+            }
+            offset = +1;
+        }
+
+        var toIdx = fromIdx + offset;
+
+        // swap function must be defined if view
+        this.swap(fromIdx, toIdx);
+        this.invalidate();
+        view.selection.select(toIdx);
+        this.treebox.ensureRowIsVisible(toIdx);
+        this.treebox.focused = true;
+    },
+
+    removeAllItems : function() {
+        this.selection.clearSelection();
+    },
+
+    refresh : function() {
+        this.selection.clearSelection();
+        this.treebox.invalidate();
+    },
+
+    selectText : function(str, caseType) {
+        var selectedItems = [];
+
+        switch (caseType) {
+            case "ic":
+                matchCase = false;
+                break;
+            case "mc":
+                matchCase = true;
+                break;
+            case "sc":
+                matchCase = /[A-Z]+/.test(str);
+                break;
+        }
+
+        var re = new PatternMatcher.strategies.globCaseContains(str, matchCase);
+        for (var i = 0; i < this.allItems.length; i++) {
+            var title = this.allItems[i]._ts_title;
+            
+            if (re.matches(title)) {
+                selectedItems.push(this.allItems[i]);
+            }
+        }
+        this.items = selectedItems;
+    },
+
+    moveSelection : function(moveUp) {
+        var currentIndex = this.selection.currentIndex;
+        if (moveUp) {
+            if (this.selection.currentIndex > 0) {
+                this.selectAndEnsureVisible(--currentIndex);
+            }
+        } else {
+            if (this.selection.currentIndex < (this.items.length - 1)) {
+                this.selectAndEnsureVisible(++currentIndex);
+            }
+        }
+        return currentIndex;
+    },
+    
+    selectAndEnsureVisible : function(index) {
+        this.selection.select(index);
+        this.treebox.ensureRowIsVisible(index);
+    },
+
+    getCellText : function(row, column){
+        switch (column.id || column) {
+            case "view-treecol":
+                return this.items[row]._ts_title;
+        }
+
+        return "";
+    },
+
+    get rowCount() {
+        return this.items.length;
+    },
+
+    cycleCell: function(row, column) {},
+
+    getImageSrc: function (row, column) {
+        return null;
+    },
+
+    setTree: function(treebox){
+        this.treebox = treebox;
+    },
+
+    getCellProperties: function(row, column, props) {
+        if (this.items[row].isCurrent
+            && this.currentWindow == this.items[row]._ts_window) {
+            props.AppendElement(selectedItemAtom);
+        }
+    },
+
+    isContainerOpen: function(index) {},
+    isContainerEmpty: function(index) {},
+    canDrop: function(index, orientation, dataTransfer) {},
+    drop: function(row, orientation, dataTransfer) {},
+    getParentIndex: function(rowIndex) {},
+    hasNextSibling: function(rowIndex, afterIndex) {},
+    getProgressMode: function(row, col) {},
+    getCellValue: function(row, col) {},
+    toggleOpenState: function(index) {},
+    selectionChanged: function() {},
+    isEditable: function(row, col) {},
+    isSelectable: function(row, col) {},
+    setCellValue: function(row, col, value) {},
+    setCellText: function(row, col, value) {},
+    performAction: function(action) {},
+    performActionOnRow: function(action, row) {},
+    performActionOnCell: function(action, row, col) {},
+    cycleHeader: function(col, elem) {},
+    isContainer: function(row){ return false; },
+    isSeparator: function(row){ return false; },
+    isSorted: function(row){ return false; },
+    getLevel: function(row){ return 0; },
+    getRowProperties: function(row,props){},
+    getColumnProperties: function(colid,col,props){}
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabswitchMenuKO5.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/tabswitcher.dtd" >
+
+<overlay id="tabswitchMenuKO5"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <menupopup id="popup_window">
+        <menuitem id="tabswitcher-select-view"
+                    class="menuitem-iconic-wide"
+                    label="&menuitem-tabswitcher-select-view.label;"
+                    command="cmd_tabswitcher_show"
+                    key="key_cmd_tabswitcher_show"
+                    insertbefore="window-menu-separator"/>
+
+        <menu label="&menuitem-sort.tabs.label;" id="tabswitcher-window-sorters"
+          insertbefore="window-menu-separator">
+            <menupopup id="tabswitcher-menupopup-window-sorters">
+              <menuitem id="tabswitcher-window-sort-by-name"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.name.label;"
+                          command="cmd_tabswitcher_sort_by_name"
+                          key="key_cmd_tabswitcher_sort_by_name"/>
+              <menuitem id="tabswitcher-window-sort-by-ext"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.ext.label;"
+                          command="cmd_tabswitcher_sort_by_ext"
+                          key="key_cmd_tabswitcher_sort_by_ext"/>
+            </menupopup>
+        </menu>
+    </menupopup>
+
+    <menupopup id="tabContextMenu">
+        <menuseparator />
+        <menu label="&menuitem-sort.tabs.label;" id="tabswitcher-context-sorters">
+            <menupopup id="tabswitcher-menupopup-context-sorters">
+              <menuitem id="tabswitcher-context-sort-by-name"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.name.label;"
+                          command="cmd_tabswitcher_sort_by_name"
+                          key="key_cmd_tabswitcher_sort_by_name"/>
+              <menuitem id="tabswitcher-context-sort-by-ext"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.ext.label;"
+                          command="cmd_tabswitcher_sort_by_ext"
+                          key="key_cmd_tabswitcher_sort_by_ext"/>
+            </menupopup>
+        </menu>
+    </menupopup>
+
+</overlay>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabswitchMenuKO6.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/tabswitcher.dtd" >
+
+<overlay id="tabswitchMenuKO5"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <menupopup id="naviation_menupopup">
+        <menuitem id="tabswitcher-select-view"
+                    class="menuitem-iconic-wide"
+                    label="&menuitem-tabswitcher-select-view.label;"
+                    command="cmd_tabswitcher_show"
+                    key="key_cmd_tabswitcher_show"
+                    insertbefore="naviation_menupopup_separator_2"/>
+
+        <menu label="&menuitem-sort.tabs.label;" id="tabswitcher-window-sorters"
+          insertbefore="naviation_menupopup_separator_2">
+            <menupopup id="tabswitcher-menupopup-window-sorters">
+              <menuitem id="tabswitcher-window-sort-by-name"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.name.label;"
+                          command="cmd_tabswitcher_sort_by_name"
+                          key="key_cmd_tabswitcher_sort_by_name"/>
+              <menuitem id="tabswitcher-window-sort-by-ext"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.ext.label;"
+                          command="cmd_tabswitcher_sort_by_ext"
+                          key="key_cmd_tabswitcher_sort_by_ext"/>
+            </menupopup>
+        </menu>
+    </menupopup>
+
+    <menupopup id="tabContextMenu">
+        <menuseparator />
+        <menu label="&menuitem-sort.tabs.label;" id="tabswitcher-context-sorters">
+            <menupopup id="tabswitcher-menupopup-context-sorters">
+              <menuitem id="tabswitcher-context-sort-by-name"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.name.label;"
+                          command="cmd_tabswitcher_sort_by_name"
+                          key="key_cmd_tabswitcher_sort_by_name"/>
+              <menuitem id="tabswitcher-context-sort-by-ext"
+                          class="menuitem-iconic-wide"
+                          label="&menuitem-sort.tabs.by.ext.label;"
+                          command="cmd_tabswitcher_sort_by_ext"
+                          key="key_cmd_tabswitcher_sort_by_ext"/>
+            </menupopup>
+        </menu>
+    </menupopup>
+
+</overlay>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabswitchOverlay.js	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,147 @@
+/*
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+# Davide Ficano.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Davide Ficano <davide.ficano@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+*/
+
+var gTabSwitcher = {
+    searchPattern : "",
+    prefs : new TabSwitcherPrefs(),
+
+    onShowTabSwitcher : function(event) {
+        window.openDialog("chrome://tabswitcher/content/tabSwitcher/tabSwitcher.xul",
+                          "_blank",
+                          "chrome,modal,resizable=yes,dependent=yes",
+                          this);
+    },
+    
+    onLoad : function() {
+        var obs = DafizillaCommon.getObserverService();
+        obs.addObserver(this, "tabswitcher_pref_changed", false);
+
+        this.addListeners();
+    },
+
+    onUnLoad : function() {
+        var obs = DafizillaCommon.getObserverService();
+        obs.removeObserver(this, "tabswitcher_pref_changed");
+        this.removeListeners();
+    },
+
+    observe : function(subject, topic, data) {
+        try {
+        switch (topic) {
+            case "tabswitcher_pref_changed":
+                this.prefsChanged(subject, data);
+                break;
+        }
+        } catch (err) {
+            alert(topic + "--" + data + "\n" + err);
+        }
+    },
+
+    prefsChanged : function(subject, data) {
+        this.prefs = new TabSwitcherPrefs();
+        this.sortTabs();
+    },
+    
+    addListeners : function() {
+        var self = this;
+
+        this.handle_current_view_opened_setup = function(event) {
+            self.onCurrentViewOpened(event);
+        };
+
+        window.addEventListener('view_opened',
+                                this.handle_current_view_opened_setup, false);
+    },
+
+    removeListeners : function() {
+        window.removeEventListener('view_opened',
+                                this.handle_current_view_opened_setup, false);
+    },
+
+    onCurrentViewOpened : function(event) {
+        this.sortTabs();
+    },
+
+    sortTabs : function() {
+        if (this.prefs.orderTabsAuto) {
+            switch(this.prefs.orderTabsType) {
+                case "n":
+                    this.sortTabsByName();
+                    break;
+                case "e":
+                    this.sortTabsByExt();
+                    break;
+            }
+        }
+    },
+
+    sortTabsByName : function() {
+        var view = ko.views.manager.currentView;
+        
+        if (view) {
+            DafizillaCommon.sortTabs(view,
+                    function(nodeA, nodeB) {
+                        var labelA = nodeA.label.toLowerCase();
+                        var labelB = nodeB.label.toLowerCase();
+                        return labelA == labelB ? 0 : labelA < labelB ? -1 : 1;
+                    });
+            view.setFocus();
+        }
+    },
+    
+    sortTabsByExt : function() {
+        var view = ko.views.manager.currentView;
+        
+        if (view) {
+            DafizillaCommon.sortTabs(view,
+                    function(nodeA, nodeB) {
+                        var labelA = nodeA.label.toLowerCase();
+                        var labelB = nodeB.label.toLowerCase();
+                        var extA = labelA.replace(/.*\./, '');
+                        var extB = labelB.replace(/.*\./, '');
+                        if (extA == extB) {
+                            return labelA == labelB ? 0 : labelA < labelB ? -1 : 1;
+                        }
+                        return extA < extB ? -1 : 1;
+                    });
+            view.setFocus();
+        }
+    }
+}
+
+window.addEventListener("load", function(event) { gTabSwitcher.onLoad(event); }, false);
+window.addEventListener("unload", function(event) { gTabSwitcher.onUnLoad(event); }, false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabswitchOverlay.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://tabswitcher/locale/tabswitcher.dtd" >
+
+<overlay id="tabswitchOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/commonPrefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/prefs.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/common.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/arrays.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/editPosition/editPosition.js" />
+  <script type="application/x-javascript"
+          src="chrome://tabswitcher/content/tabswitchOverlay.js" />
+
+    <broadcasterset id="broadcasterset_global">
+      <broadcaster
+        id="cmd_tabswitcher_show"
+        key="key_cmd_tabswitcher_show"
+        desc="&switchView.desc;"
+        oncommand="gTabSwitcher.onShowTabSwitcher(event)"/>
+
+      <broadcaster
+        id="cmd_tabswitcher_goto_last_edit_position"
+        key="key_cmd_tabswitcher_goto_last_edit_position"
+        desc="&goto.last.edit.position.desc;"
+        disabled="true"
+        oncommand="gEditPosition.goToLastEdit(0);"/>
+
+      <broadcaster
+        id="cmd_tabswitcher_goto_next_edit_position"
+        key="key_cmd_tabswitcher_goto_next_edit_position"
+        desc="&goto.next.edit.position.desc;"
+        disabled="true"
+        oncommand="gEditPosition.goToNextEdit(0);"/>
+
+      <broadcaster
+        id="cmd_tabswitcher_edit_position_remove_all"
+        key="key_cmd_tabswitcher_edit_position_remove_all"
+        desc="&edit.position.remove.all.desc;"
+        oncommand="gEditPosition.removeAll();"/>
+
+      <broadcaster
+        id="cmd_tabswitcher_sort_by_name"
+        key="key_cmd_tabswitcher_sort_by_name"
+        desc="&sort.by.name.desc;"
+        oncommand="gTabSwitcher.sortTabsByName();"/>
+
+      <broadcaster
+        id="cmd_tabswitcher_sort_by_ext"
+        key="key_cmd_tabswitcher_sort_by_ext"
+        desc="&sort.by.ext.desc;"
+        oncommand="gTabSwitcher.sortTabsByExt();"/>
+    </broadcasterset>
+
+    <toolboxrow id="main-toolboxrow">
+      <toolbar id="standardToolbar">
+          <toolbarbutton id="button-viewswitcher-gotolastedit"
+               persist="buttonstyle"
+               class="button-viewswitcher-goto-last-edit"
+               buttonstyle="pictures"
+               insertbefore="undoButton"
+               type="menu-button"
+               tooltiptext="&toolbar.goto.last.edit.position.tooltip;"
+               observes="cmd_tabswitcher_goto_last_edit_position">
+                <menupopup id="gotolastedit-toolbarMenuPopup"
+                           onpopupshowing="gEditPosition.initLastEditPopupMenu('gotolastedit');"
+                           oncommand="event.stopPropagation();">
+                    <vbox id="gotolastedit-menubox" />
+                    <menuseparator id="gotolastedit-menuseparator" />
+                    <menuitem id="gotolastedit-removeall-menuitem"
+                              label="&edit.position.remove.all.label;"
+                              tooltiptext="&edit.position.remove.all.label;"
+                              command="cmd_tabswitcher_edit_position_remove_all" />
+                </menupopup>
+          </toolbarbutton>
+          <toolbarbutton id="button-viewswitcher-nextedit"
+               persist="buttonstyle"
+               class="button-viewswitcher-goto-next-edit"
+               buttonstyle="pictures"
+               insertbefore="undoButton"
+               type="menu-button"
+               tooltiptext="&toolbar.goto.next.edit.position.tooltip;"
+               observes="cmd_tabswitcher_goto_next_edit_position">
+                <menupopup id="gotolastedit-toolbarMenuPopup"
+                           onpopupshowing="gEditPosition.initNextEditPopupMenu('gotonextedit');"
+                           oncommand="event.stopPropagation();">
+                    <vbox id="gotonextedit-menubox" />
+                    <menuseparator id="gotonextedit-menuseparator" />
+                    <menuitem id="gotonextedit-removeall-menuitem"
+                              label="&edit.position.remove.all.label;"
+                              tooltiptext="&edit.position.remove.all.label;"
+                              command="cmd_tabswitcher_edit_position_remove_all" />
+                </menupopup>
+          </toolbarbutton>
+      </toolbar>
+    </toolboxrow>
+
+</overlay>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/tabswitcher_overlay.xul	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN" "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<overlay id="tabswitcherOverlay"
+         xmlns:html="http://www.w3.org/1999/xhtml"
+         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <commandset id="allcommands">
+    <command id="Tasks:HelloWorld" oncommand="alert('Hello World from tabswitcher');"/>
+  </commandset>
+
+  <menupopup id="popup_tools">
+    <menuitem id="menu_tabswitcher"
+              label="tabswitcher"
+              observes="Tasks:HelloWorld"
+              class="menu-iconic-wide"/>
+  </menupopup>
+    
+</overlay>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install.rdf	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,33 @@
+<?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>tabswitcher@skepticats.com</em:id>
+        <em:name>tabswitcher</em:name>
+        <em:version>1.0.0</em:version>
+        <em:description>This is a port of TabSwitcher 0.9.1 to Komodo 7.  It allows you to easily switch between tabs, sort them, list bookmarks, and more.</em:description>
+        <em:creator>Peter A. Geer</em:creator>
+	<em:contributor>Davide Ficano, aka dafizilla, originally created this extension and did all the hard work.</em:contributor>
+	<em:contributor>Nathan Rijksen for sort tabs idea and code</em:contributor>
+	<em:contributor>Adam Groszer for granularity code</em:contributor>
+        <em:homepageURL>http://linlog.skepticats.com/projects/tabswitcher/</em:homepageURL>
+        <em:type>2</em:type> <!-- type=extension --> 
+
+        <em:targetApplication>
+            <Description>
+                <!-- Komodo IDE's uuid -->
+                <em:id>{36E66FA0-F259-11D9-850E-000D935D3368}</em:id>
+                <em:minVersion>7.0</em:minVersion>
+                <em:maxVersion>7.*</em:maxVersion>
+            </Description>
+        </em:targetApplication>
+        <em:targetApplication>
+            <Description>
+                <!-- Komodo Edit's uuid -->
+                <em:id>{b1042fb5-9e9c-11db-b107-000d935d3368}</em:id>
+                <em:minVersion>7.0</em:minVersion>
+                <em:maxVersion>7.*</em:maxVersion>
+            </Description>
+        </em:targetApplication>
+    </Description>
+</RDF>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/en-US/bookmarks.dtd	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,8 @@
+<!ENTITY viewswitcher.bookmark.tab.title "Bookmark List">
+<!ENTITY viewswitcher.bookmark.refresh.tooltip "Refresh Bookmark List">
+<!ENTITY viewswitcher.bookmark.remove.selected.label "Remove Selected Bookmarks">
+<!ENTITY viewswitcher.bookmark.remove.all.label "Remove All Bookmarks">
+<!ENTITY viewswitcher.bookmark.file.label "File">
+<!ENTITY viewswitcher.bookmark.line.number.label "Line">
+<!ENTITY viewswitcher.bookmark.line.content.label "Content">
+<!ENTITY viewswitcher.bookmark.found "Found &#37;1 bookmark(s) in &#37;2 of &#37;3 view(s)">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/en-US/pref.dtd	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,36 @@
+<!ENTITY tabswitcher.label "TabSwitcher">
+<!ENTITY tabswitcher.description "Tabswitcher enhances tab switching. (and some more stuff ;-)">
+
+<!ENTITY edit.position.label "Last Edit Position">
+<!ENTITY edit.position.granularity.label "Granularity">
+<!ENTITY edit.granularity.single "Single position in a file">
+<!ENTITY edit.granularity.1 "1 line">
+<!ENTITY edit.granularity.2 "2 lines">
+<!ENTITY edit.granularity.3 "3 lines">
+<!ENTITY edit.granularity.5 "5 lines">
+<!ENTITY edit.granularity.7 "7 lines">
+<!ENTITY edit.granularity.10 "10 lines">
+<!ENTITY edit.granularity.15 "15 lines">
+<!ENTITY edit.editClearNextStack.label "Clear next stack on modification">
+<!ENTITY edit.editRememberCurrentPos.label "Remember current position when going back (and next stack is empty)">
+<!ENTITY edit.editShowMarkers.label "Show position markers*">
+<!ENTITY edit.editShowMarkers.tooltip "You need to reopen documents (or restart Komodo)">
+<!ENTITY edit.editCompatibility.label "Install compatibility handler*">
+<!ENTITY edit.editCompatibility.tooltip "Komodo restart required">
+<!ENTITY edit.editCompatibility.text1 "Turn this on if you have Komodo IDE and you can not">
+<!ENTITY edit.editCompatibility.text2 "or do not want to turn off the domviewer@ActiveState.com extension">
+<!ENTITY switch.view.label "Switch View">
+
+<!ENTITY number.edit.position.store "Number of edit positions to store">
+<!ENTITY number.visible.menu.items "Number of visible menu items">
+
+<!ENTITY show.last.used.pattern.label "Show last used pattern">
+
+<!ENTITY tabs.order.label "Tabs Order">
+<!ENTITY tabs.order.auto.label "Order Tabs at every new opened view">
+<!ENTITY tabs.order.sort.by.name "Sort by file name">
+<!ENTITY tabs.order.group.by.ext "Group by file extension">
+
+<!ENTITY homepage.label "Visit Tabswitcher website">
+<!ENTITY homepage.tooltip "Tabswitcher is written by Davide Ficano">
+<!ENTITY homepage.url "http://dafizilla.sourceforge.net/tabswitcher">
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/en-US/tabswitcher.dtd	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,24 @@
+<!ENTITY switchView.desc "TabSwitcher: View - Switch View...">
+<!ENTITY menuitem-tabswitcher-select-view.label "Switch View...">
+<!ENTITY switchView.dialog.title "Switch To View">
+
+<!ENTITY goto.last.edit.position.desc "TabSwitcher: Edit Position - Go To Last">
+<!ENTITY toolbar.goto.last.edit.position.tooltip "Go To Last Edit Position">
+
+<!ENTITY goto.next.edit.position.desc "TabSwitcher: Edit Position - Go To Next">
+<!ENTITY toolbar.goto.next.edit.position.tooltip "Go To Next Edit Position">
+
+<!ENTITY edit.position.remove.all.label "Remove All">
+<!ENTITY edit.position.remove.all.desc "TabSwitcher: Edit Position - Remove All">
+
+<!ENTITY sort.by.name.desc "TabSwitcher: Tabs Order - Sort By Name">
+<!ENTITY menuitem-sort.tabs.label "Tabs Order">
+<!ENTITY menuitem-sort.tabs.by.name.label "Sort by Name">
+
+<!ENTITY sort.by.ext.desc "TabSwitcher: Tabs Order - Group By Extension">
+<!ENTITY menuitem-sort.tabs.by.ext.label "Group by Extension">
+
+<!ENTITY match.case.label "Match Case">
+<!ENTITY match.case.accesskey "c">
+<!ENTITY smart.case.label "Smart Case">
+<!ENTITY smart.case.accesskey "c">
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locale/en-US/tabswitcher.properties	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,1 @@
+extensions.tabswitcher@dafizilla.sourceforge.net.description=Enhance switch between editor views, order tabs
Binary file skin/appicon.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skin/bookmarks.css	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,30 @@
+.button-viewswitcher-refresh {
+  list-style-image: url("chrome://tabswitcher/skin/refresh.png");
+}
+
+.button-viewswitcher-remove-selected {
+  list-style-image: url("chrome://tabswitcher/skin/remove-selected.png");
+}
+
+.button-viewswitcher-remove-all {
+  list-style-image: url("chrome://tabswitcher/skin/remove-all.png");
+}
+
+.button-viewswitcher-goto-last-edit {
+  list-style-image: url("chrome://tabswitcher/skin/goto-last-edit.png");
+}
+
+.button-viewswitcher-goto-last-edit[disabled="true"] {
+  list-style-image: url("chrome://tabswitcher/skin/goto-last-edit.png");
+  opacity: 0.5;
+}
+
+.button-viewswitcher-goto-next-edit {
+  list-style-image: url("chrome://tabswitcher/skin/goto-next-edit.png");
+}
+
+.button-viewswitcher-goto-next-edit[disabled="true"] {
+  list-style-image: url("chrome://tabswitcher/skin/goto-next-edit.png");
+  opacity: 0.5;
+}
+
Binary file skin/goto-last-edit.png has changed
Binary file skin/goto-next-edit.png has changed
Binary file skin/refresh.png has changed
Binary file skin/remove-all.png has changed
Binary file skin/remove-selected.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skin/tabSwitcher.css	Sat Aug 18 13:10:14 2012 -0400
@@ -0,0 +1,14 @@
+.viewListChildren::-moz-tree-cell-text(selectedItem) {
+  font-weight: bold;
+}
+
+#view-path {
+  -moz-appearance: none;
+  border: none;
+}
+
+.link {
+  color: #0000FF;
+  text-decoration: underline !important;
+  cursor: pointer;
+}
\ No newline at end of file
Binary file tabswitcher-0.9.2-ko.xpi has changed