Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Wed, 22 Feb 2012 19:25:06 -0800
changeset 112171 83cb9381de53b1f9feb7dc15364b8f9955a432b2
parent 112170 b468e66a4fcd8e0042cbdd24f896192bcc5eb520 (current diff)
parent 90333 5e756e59a794f0f95d5dd853a0232e7d400f5983 (diff)
child 112172 08b5f54def63c39e68fa5c3e9670d1a0c35d1e5b
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
accessible/public/nsIAccessibilityService.h
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessibilityService.h
accessible/src/base/nsAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.h
accessible/tests/mochitest/Makefile.in
accessible/tests/mochitest/actions/Makefile.in
accessible/tests/mochitest/actions/test_inputs.html
accessible/tests/mochitest/test_childAtPoint.html
accessible/tests/mochitest/test_childAtPoint.xul
b2g/app/nsBrowserApp.cpp
b2g/installer/package-manifest.in
browser/app/nsBrowserApp.cpp
browser/base/content/browser.xul
browser/base/content/syncSetup.xul
browser/components/tabview/test/Makefile.in
browser/components/tabview/ui.js
browser/devtools/jar.mn
browser/locales/en-US/chrome/browser/syncSetup.dtd
build/mobile/devicemanagerADB.py
build/mobile/devicemanagerSUT.py
config/autoconf.mk.in
configure.in
content/base/src/nsWebSocket.cpp
content/base/src/nsWebSocket.h
content/media/VideoUtils.cpp
content/media/VideoUtils.h
content/media/nsBuiltinDecoderReader.cpp
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/ogg/nsOggCodecState.cpp
content/media/raw/nsRawReader.cpp
content/media/webm/nsWebMReader.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
content/xul/document/src/nsXULPrototypeDocument.cpp
dom/base/nsGlobalWindow.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginStreamListenerPeer.cpp
dom/plugins/base/nsPluginTags.cpp
dom/plugins/base/nsPluginTags.h
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginModuleParent.cpp
dom/sms/src/ril/SmsDatabaseService.cpp
dom/sms/src/ril/SmsDatabaseService.h
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/WorkerScope.cpp
dom/workers/XMLHttpRequest.cpp
embedding/components/find/src/nsWebBrowserFind.cpp
embedding/components/find/src/nsWebBrowserFind.h
image/src/Image.h
image/src/RasterImage.cpp
image/src/RasterImage.h
image/src/VectorImage.cpp
image/src/VectorImage.h
image/src/imgFrame.cpp
image/src/imgFrame.h
image/src/imgLoader.cpp
image/src/imgRequest.cpp
js/ipc/ObjectWrapperParent.cpp
js/src/configure.in
js/src/gc/Barrier.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.cpp
js/src/jsproxy.cpp
js/src/jsproxy.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/jsxdrapi.h
js/src/jsxml.cpp
js/src/methodjit/PolyIC.cpp
js/src/shell/jsworkers.cpp
js/src/vm/Debugger.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCThreadContext.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/nsBidiPresUtils.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsPresShell.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsImageControlFrame.cpp
layout/generic/crashtests/crashtests.list
layout/generic/nsFirstLetterFrame.cpp
layout/generic/nsFirstLetterFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsIScrollableFrame.h
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/reftests/svg/reftest.list
mobile/android/base/GeckoApp.java
mobile/xul/app/nsBrowserApp.cpp
modules/libpref/src/init/all.js
mozglue/android/APKOpen.cpp
mozglue/android/Makefile.in
netwerk/protocol/websocket/WebSocketChannel.cpp
other-licenses/android/Makefile.in
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
security/manager/ssl/src/nsKeygenHandler.cpp
security/manager/ssl/src/nsNSSCertTrust.cpp
security/manager/ssl/src/nsNSSCertificateDB.cpp
security/manager/ssl/src/nsNSSComponent.cpp
services/sync/tests/unit/test_bookmark_engine.js
services/sync/tests/unit/test_bookmark_smart_bookmarks.js
services/sync/tests/unit/test_clients_engine.js
services/sync/tests/unit/test_corrupt_keys.js
services/sync/tests/unit/test_engine_abort.js
services/sync/tests/unit/test_history_engine.js
services/sync/tests/unit/test_hmac_error.js
services/sync/tests/unit/test_interval_triggers.js
services/sync/tests/unit/test_jpakeclient.js
services/sync/tests/unit/test_syncengine_sync.js
services/sync/tests/unit/test_syncscheduler.js
storage/src/VacuumManager.cpp
testing/jetpack/jetpack-location.txt
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/components/satchel/nsFormFillController.cpp
toolkit/components/satchel/nsFormFillController.h
toolkit/components/telemetry/TelemetryPing.js
toolkit/components/telemetry/tests/unit/test_TelemetryPing.js
toolkit/content/widgets/videocontrols.xml
toolkit/crashreporter/client/crashreporter_win.cpp
toolkit/mozapps/installer/packager.mk
toolkit/xre/nsAndroidStartup.cpp
widget/cocoa/nsMenuItemIconX.h
widget/cocoa/nsNativeThemeCocoa.mm
widget/gtk2/nsNativeKeyBindings.cpp
widget/gtk2/nsWindow.cpp
widget/gtk2/nsWindow.h
widget/windows/nsWindow.cpp
xpcom/build/nsXULAppAPI.h
xpcom/glue/standalone/nsGlueLinkingDlopen.cpp
--- a/accessible/public/nsIAccessibilityService.h
+++ b/accessible/public/nsIAccessibilityService.h
@@ -86,20 +86,16 @@ public:
                                                   bool aCanCreate) = 0;
 
   /**
    * Creates accessible for the given DOM node or frame.
    */
   virtual already_AddRefed<nsAccessible>
     CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
-    CreateHTML4ButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
-  virtual already_AddRefed<nsAccessible>
-    CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
-  virtual already_AddRefed<nsAccessible>
     CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -213,27 +213,16 @@ nsAccessibilityService::CreateOuterDocAc
   nsAccessible* accessible = 
     new nsOuterDocAccessible(aContent, 
                              nsAccUtils::GetDocAccessibleFor(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
-nsAccessibilityService::CreateHTML4ButtonAccessible(nsIContent* aContent,
-                                                    nsIPresShell* aPresShell)
-{
-  nsAccessible* accessible = 
-    new nsHTML4ButtonAccessible(aContent, 
-                                nsAccUtils::GetDocAccessibleFor(aPresShell));
-  NS_ADDREF(accessible);
-  return accessible;
-}
-
-already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
                                                    nsIPresShell* aPresShell)
 {
   nsAccessible* accessible = 
     new nsHTMLButtonAccessible(aContent, 
                                nsAccUtils::GetDocAccessibleFor(aPresShell));
   NS_ADDREF(accessible);
   return accessible;
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -84,23 +84,20 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLERETRIEVAL
   NS_DECL_NSIOBSERVER
 
   // nsIAccessibilityService
   virtual nsAccessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
                                                   bool aCanCreate);
-
+  already_AddRefed<nsAccessible>
+    CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  virtual already_AddRefed<nsAccessible>
-    CreateHTML4ButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
-  virtual already_AddRefed<nsAccessible>
-    CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   already_AddRefed<nsAccessible>
     CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -846,17 +846,19 @@ nsAccessible::ChildAtPoint(PRInt32 aX, P
   nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
 
   nsIContent* content = nsnull;
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
-  nsAccessible* accessible = accDocument->GetAccessibleOrContainer(content);
+  nsDocAccessible* contentDocAcc = GetAccService()->
+    GetDocAccessible(content->OwnerDoc());
+  nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
   if (!accessible)
     return fallbackAnswer;
 
   if (accessible == this) {
     // Manually walk through accessible children and see if the are within this
     // point. Skip offscreen or invisible accessibles. This takes care of cases
     // where layout won't walk into things for us, such as image map areas and
     // sub documents (XXX: subdocuments should be handled by methods of
@@ -1053,17 +1055,18 @@ nsAccessible::GetBounds(PRInt32* aX, PRI
 
   nsPresContext* presContext = presShell->GetPresContext();
   *aX = presContext->AppUnitsToDevPixels(unionRectTwips.x);
   *aY = presContext->AppUnitsToDevPixels(unionRectTwips.y);
   *aWidth = presContext->AppUnitsToDevPixels(unionRectTwips.width);
   *aHeight = presContext->AppUnitsToDevPixels(unionRectTwips.height);
 
   // We have the union of the rectangle, now we need to put it in absolute screen coords
-  nsIntRect orgRectPixels = boundingFrame->GetScreenRectExternal();
+  nsIntRect orgRectPixels = boundingFrame->GetScreenRectInAppUnits().
+    ToNearestPixels(presContext->AppUnitsPerDevPixel());
   *aX += orgRectPixels.x;
   *aY += orgRectPixels.y;
 
   return NS_OK;
 }
 
 // helpers
 
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -309,17 +309,17 @@ nsHTMLButtonAccessible::NativeRole()
 {
   return roles::PUSHBUTTON;
 }
 
 nsresult
 nsHTMLButtonAccessible::GetNameInternal(nsAString& aName)
 {
   nsAccessible::GetNameInternal(aName);
-  if (!aName.IsEmpty())
+  if (!aName.IsEmpty() || mContent->Tag() != nsGkAtoms::input)
     return NS_OK;
 
   // No name from HTML or ARIA
   nsAutoString name;
   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
                          name) &&
       !mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt,
                          name)) {
@@ -349,81 +349,16 @@ nsHTMLButtonAccessible::GetNameInternal(
 bool
 nsHTMLButtonAccessible::IsWidget() const
 {
   return true;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsHTML4ButtonAccessible
-////////////////////////////////////////////////////////////////////////////////
-
-nsHTML4ButtonAccessible::
-  nsHTML4ButtonAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsHyperTextAccessibleWrap(aContent, aDoc)
-{
-}
-
-PRUint8
-nsHTML4ButtonAccessible::ActionCount()
-{
-  return 1;
-}
-
-NS_IMETHODIMP nsHTML4ButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
-{
-  if (aIndex == eAction_Click) {
-    aName.AssignLiteral("press"); 
-    return NS_OK;
-  }
-  return NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP
-nsHTML4ButtonAccessible::DoAction(PRUint8 aIndex)
-{
-  if (aIndex != 0)
-    return NS_ERROR_INVALID_ARG;
-
-  DoCommand();
-  return NS_OK;
-}
-
-role
-nsHTML4ButtonAccessible::NativeRole()
-{
-  return roles::PUSHBUTTON;
-}
-
-PRUint64
-nsHTML4ButtonAccessible::NativeState()
-{
-  PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
-
-  state |= states::FOCUSABLE;
-
-  nsEventStates elmState = mContent->AsElement()->State();
-  if (elmState.HasState(NS_EVENT_STATE_DEFAULT))
-    state |= states::DEFAULT;
-
-  return state;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// nsHTML4ButtonAccessible: Widgets
-
-bool
-nsHTML4ButtonAccessible::IsWidget() const
-{
-  return true;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTextFieldAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLTextFieldAccessible::
   nsHTMLTextFieldAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
   nsHyperTextAccessibleWrap(aContent, aDoc)
 {
 }
--- a/accessible/src/html/nsHTMLFormControlAccessible.h
+++ b/accessible/src/html/nsHTMLFormControlAccessible.h
@@ -87,17 +87,17 @@ public:
   virtual PRUint64 NativeState();
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
 };
 
 
 /**
  * Accessible for HTML input@type="button", @type="submit", @type="image"
- * elements.
+ * and HTML button elements.
  */
 class nsHTMLButtonAccessible : public nsHyperTextAccessibleWrap
 {
 
 public:
   enum { eAction_Click = 0 };
 
   nsHTMLButtonAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
@@ -116,43 +116,16 @@ public:
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual bool IsWidget() const;
 };
 
 
 /**
- * Accessible for HTML button element.
- */
-class nsHTML4ButtonAccessible : public nsHyperTextAccessibleWrap
-{
-
-public:
-  enum { eAction_Click = 0 };
-
-  nsHTML4ButtonAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
-
-  // nsIAccessible
-  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
-  NS_IMETHOD DoAction(PRUint8 index);
-
-  // nsAccessible
-  virtual mozilla::a11y::role NativeRole();
-  virtual PRUint64 NativeState();
-
-  // ActionAccessible
-  virtual PRUint8 ActionCount();
-
-  // Widgets
-  virtual bool IsWidget() const;
-};
-
-
-/**
  * Accessible for HTML input@type="text" element.
  */
 class nsHTMLTextFieldAccessible : public nsHyperTextAccessibleWrap
 {
 
 public:
   enum { eAction_Click = 0 };
 
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -40,20 +40,22 @@ DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
 DIRS	= \
   actions \
   attributes \
+  bounds \
   editabletext \
   elm \
   events \
   focus \
+  hittest \
   hyperlink \
   hypertext \
   name \
   pivot \
   relations \
   selectable \
   states \
   table \
@@ -91,18 +93,16 @@ include $(topsrcdir)/config/rules.mk
 		table.js \
 		value.js \
 		test_aria_role_article.html \
 		test_aria_role_equation.html \
 		test_aria_roles.html \
 		test_aria_roles.xul \
 		test_aria_token_attrs.html \
 		test_bug420863.html \
-		test_childAtPoint.html \
-		test_childAtPoint.xul \
 		test_descr.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleImage.html \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
 		test_textboxes.html \
 		test_textboxes.xul \
--- a/accessible/tests/mochitest/actions/Makefile.in
+++ b/accessible/tests/mochitest/actions/Makefile.in
@@ -45,17 +45,17 @@ relativesrcdir  = accessible/actions
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_anchors.html \
 		test_aria.html \
 		test_general.html \
 		test_general.xul \
-		test_inputs.html \
+		test_controls.html \
 		test_keys_menu.xul \
 		test_keys.html \
 		test_link.html \
 		test_media.html \
 		test_select.html \
 		test_tree.xul \
 		test_treegrid.xul \
 		$(NULL)
rename from accessible/tests/mochitest/actions/test_inputs.html
rename to accessible/tests/mochitest/actions/test_controls.html
--- a/accessible/tests/mochitest/actions/test_inputs.html
+++ b/accessible/tests/mochitest/actions/test_controls.html
@@ -21,16 +21,21 @@
     {
       var actionsArray = [
         {
           ID: "button",
           actionName: "press",
           events: CLICK_EVENTS
         },
         {
+          ID: "input_button",
+          actionName: "press",
+          events: CLICK_EVENTS
+        },
+        {
           ID: "checkbox_unchecked",
           actionName: "check",
           events: CLICK_EVENTS
         },
         {
           ID: "checkbox_checked",
           actionName: "uncheck",
           events: CLICK_EVENTS
@@ -63,17 +68,19 @@
      title="nsIAccessible actions testing">
     Mozilla Bug 477975
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
-  <button id="button" value="button">Button</button>
+  <button id="button">Button</button>
+
+  <input id="input_button" type="button" value="normal">
 
   <input id="checkbox_unchecked" type="checkbox">Checkbox</input>
 
   <input id="checkbox_checked" type="checkbox" checked="true">Checkbox</input>
 
   <input id="checkbox_mixed" type="checkbox">Checkbox</input>
 
   <fieldset>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/bounds/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** 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 Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2012
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of 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 *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/bounds
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+		test_zoom.html \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/bounds/test_zoom.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Accessible boundaries when page is zoomed</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+  <script type="application/javascript"
+          src="../browser.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var p1 = currentTabDocument().body.firstElementChild;
+      var p2 = currentTabDocument().body.lastElementChild;
+
+      testBounds(p1);
+      testBounds(p2);
+
+      var docShell = currentTabWindow().
+        QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+        getInterface(Components.interfaces.nsIWebNavigation).
+        QueryInterface(Components.interfaces.nsIDocShell);
+      var docViewer = docShell.contentViewer.
+        QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+      docViewer.fullZoom = 2.0;
+
+      testBounds(p1);
+      testBounds(p2);
+
+      closeBrowserWindow();
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    openBrowserWindow(doTest,
+                      "data:text/html,<html><body><p>para 1</p><p>para 2</p></body></html>",
+                      { left: 0, top: 0, width: 600, height: 600 });
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=650241"
+     title="Location returned by accessibles incorrect when page zoomed">
+    Mozilla Bug 650241
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+</body>
+</html>
--- a/accessible/tests/mochitest/browser.js
+++ b/accessible/tests/mochitest/browser.js
@@ -1,15 +1,16 @@
 /**
  * Load the browser with the given url and then invokes the given function.
  */
-function openBrowserWindow(aFunc, aURL)
+function openBrowserWindow(aFunc, aURL, aRect)
 {
   gBrowserContext.testFunc = aFunc;
   gBrowserContext.startURL = aURL;
+  gBrowserContext.browserRect = aRect;
 
   addLoadEvent(openBrowserWindowIntl);
 }
 
 /**
  * Close the browser window.
  */
 function closeBrowserWindow()
@@ -53,16 +54,24 @@ function currentBrowser()
  * Return DOM document of the current tab.
  */
 function currentTabDocument()
 {
   return currentBrowser().contentDocument;
 }
 
 /**
+ * Return window of the current tab.
+ */
+function currentTabWindow()
+{
+  return currentTabDocument().defaultView;
+}
+
+/**
  * Return browser element of the tab at the given index.
  */
 function browserAt(aIndex)
 {
   return tabBrowser().getBrowserAtIndex(aIndex);
 }
 
 /**
@@ -98,19 +107,32 @@ var gBrowserContext =
 {
   browserWnd: null,
   testFunc: null,
   startURL: ""
 };
 
 function openBrowserWindowIntl()
 {
+  var params = "chrome,all,dialog=no";
+  var rect = gBrowserContext.browserRect;
+  if (rect) {
+    if ("left" in rect)
+      params += ",left=" + rect.left;
+    if ("top" in rect)
+      params += ",top=" + rect.top;
+    if ("width" in rect)
+      params += ",width=" + rect.width;
+    if ("height" in rect)
+      params += ",height=" + rect.height;
+  }
+
   gBrowserContext.browserWnd =
     window.openDialog(Services.prefs.getCharPref("browser.chromeURL"),
-                      "_blank", "chrome,all,dialog=no",
+                      "_blank", params,
                       gBrowserContext.startURL);
 
   addA11yLoadEvent(startBrowserTests, browserWindow());
 }
 
 function startBrowserTests()
 {
   if (gBrowserContext.startURL) // wait for load
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/hittest/Makefile.in
@@ -0,0 +1,55 @@
+#
+# ***** 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 Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2012
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Hubert Figuière <hub@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of 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 *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/hittest
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+		test_general.html \
+		test_general.xul \
+		test_browser.html \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/hittest/test_browser.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>nsIAccessible::childAtPoint() from browser tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // Hit testing. See bug #726097
+      var hititem = getAccessible("hititem");
+      var hittest = getAccessible("hittest");
+
+      var [hitX, hitY, hitWidth, hitHeight] = getBounds(hititem);
+      var tgtX = hitX + hitWidth / 2;
+      var tgtY = hitY + hitHeight / 2;
+
+      var rootAcc = getRootAccessible();
+      var docAcc = getAccessible(document);
+      var outerDocAcc = docAcc.parent;
+
+      var hitAcc = rootAcc.getDeepestChildAtPoint(tgtX, tgtY);
+      is(hitAcc, hititem, "Hit match at " + tgtX + "," + tgtY + 
+                          ". Found: " + prettyName(hitAcc));
+      var hitAcc2 = docAcc.getDeepestChildAtPoint(tgtX, tgtY);
+      is(hitAcc, hitAcc2, "Hit match at " + tgtX + "," + tgtY + 
+                          ". Found: " + prettyName(hitAcc2));
+
+      hitAcc = outerDocAcc.getChildAtPoint(tgtX, tgtY);
+      is(hitAcc, docAcc, "Hit match at " + tgtX + "," + tgtY + 
+                         ". Found: " + prettyName(hitAcc));
+      hitAcc = docAcc.getChildAtPoint(tgtX, tgtY);
+      is(hitAcc, hittest, "Hit match at " + tgtX + "," + tgtY + 
+                          ". Found: " + prettyName(hitAcc));
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=726097"
+     title="nsIAccessible::childAtPoint() from browser tests">Mozilla Bug 726097</a>
+
+  <div id="hittest">
+    <div id="hititem"><span role="image">img</span>item</div>
+  </div>
+</body>
+</html>
rename from accessible/tests/mochitest/test_childAtPoint.html
rename to accessible/tests/mochitest/hittest/test_general.html
--- a/accessible/tests/mochitest/test_childAtPoint.html
+++ b/accessible/tests/mochitest/hittest/test_general.html
@@ -3,19 +3,19 @@
 <head>
   <title>nsIAccessible::childAtPoint() tests</title>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
-          src="common.js"></script>
+          src="../common.js"></script>
   <script type="application/javascript"
-          src="layout.js"></script>
+          src="../layout.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // Not specific case, child and deepchild testing.
       var list = getAccessible("list");
       var listitem = getAccessible("listitem");
       var image = getAccessible("image");
@@ -80,11 +80,10 @@
 
   <span role="button">button1</span><span role="button" id="btn">button2</span>
 
   <span role="textbox">textbox1</span><span role="textbox" id="txt">textbox2</span>
 
   <div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
   </div>
   <div id="area" style="width: 100px; height: 100px; background-color: blue;"></div>
-
 </body>
 </html>
rename from accessible/tests/mochitest/test_childAtPoint.xul
rename to accessible/tests/mochitest/hittest/test_general.xul
--- a/accessible/tests/mochitest/test_childAtPoint.xul
+++ b/accessible/tests/mochitest/hittest/test_general.xul
@@ -5,22 +5,22 @@
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="nsIAccessible::getChildAtPoint and getDeepestChildAtPoint">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
-          src="treeview.js" />
+          src="../treeview.js" />
 
   <script type="application/javascript"
-          src="common.js" />
+          src="../common.js" />
   <script type="application/javascript"
-          src="layout.js" />
+          src="../layout.js" />
 
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       // Initialize the tree
       var view = new nsTableTreeView(5);
 
--- a/accessible/tests/mochitest/layout.js
+++ b/accessible/tests/mochitest/layout.js
@@ -29,51 +29,71 @@ function testChildAtPoint(aIdentifier, a
  * @param aX                 [in] x coordinate of the point relative accessible
  * @param aY                 [in] y coordinate of the point relative accessible
  * @param aFindDeepestChild  [in] points whether deepest or nearest child should
  *                           be returned
  * @return                   the child accessible at the given point
  */
 function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild)
 {
-  var nodeObj = { value: null };
-  var acc = getAccessible(aIdentifier, null, nodeObj);
-  var node = nodeObj.value;
-
-  if (!acc || !node)
+  var acc = getAccessible(aIdentifier);
+  if (!acc)
     return;
 
-  var [deltaX, deltaY] = getScreenCoords(node);
+  var [screenX, screenY] = getBoundsForDOMElm(acc.DOMNode);
 
-  var x = deltaX + aX;
-  var y = deltaY + aY;
+  var x = screenX + aX;
+  var y = screenY + aY;
 
   try {
     if (aFindDeepestChild)
       return acc.getDeepestChildAtPoint(x, y);
     return acc.getChildAtPoint(x, y);
   } catch (e) {  }
 
   return null;
 }
 
 /**
- * Return DOM node coordinates relative screen as pair (x, y).
+ * Test the accessible boundaries.
  */
-function getScreenCoords(aNode)
+function testBounds(aID)
 {
-  if (aNode instanceof nsIDOMXULElement)
-    return [node.boxObject.screenX, node.boxObject.screenY];
+  var [expectedX, expectedY, expectedWidth, expectedHeight] =
+    getBoundsForDOMElm(aID);
+
+  var [x, y, width, height] = getBounds(aID);
+  is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
+  is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
+  is(width, expectedWidth, "Wrong width of " + prettyName(aID));
+  is(height, expectedHeight, "Wrong height of " + prettyName(aID));
+}
 
-  // Ugly hack until bug 486200 is fixed.
-  const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-  var descr = document.createElementNS(XUL_NS, "description");
-  descr.setAttribute("value", "helper description");
-  aNode.parentNode.appendChild(descr);
-  var descrBoxObject = descr.boxObject;
-  var descrRect = descr.getBoundingClientRect();
-  var deltaX = descrBoxObject.screenX - descrRect.left;
-  var deltaY = descrBoxObject.screenY - descrRect.top;
-  aNode.parentNode.removeChild(descr);
+/**
+ * Return the accessible coordinates and size relative to the screen.
+ */
+function getBounds(aID)
+{
+  var accessible = getAccessible(aID);
+  var x = {}, y = {}, width = {}, height = {};
+  accessible.getBounds(x, y, width, height);
+  return [x.value, y.value, width.value, height.value];
+}
 
-  var rect = aNode.getBoundingClientRect();
-  return [rect.left + deltaX, rect.top + deltaY];
+/**
+ * Return DOM node coordinates relative the screen and its size in device
+ * pixels.
+ */
+function getBoundsForDOMElm(aID)
+{
+  var elm = getNode(aID);
+  var elmWindow = elm.ownerDocument.defaultView;
+  var winUtil = elmWindow.
+    QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+    getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+  var ratio = winUtil.screenPixelsPerCSSPixel;
+  var rect = elm.getBoundingClientRect();
+  return [ (rect.left + elmWindow.mozInnerScreenX) * ratio,
+           (rect.top + elmWindow.mozInnerScreenY) * ratio,
+           rect.width * ratio,
+           rect.height * ratio ];
 }
--- a/accessible/tests/mochitest/name/test_browserui.xul
+++ b/accessible/tests/mochitest/name/test_browserui.xul
@@ -50,18 +50,19 @@
 
       this.eventSeq = [
         new focusChecker(tabDocumentAt, 1)
       ];
 
       this.check = function switchTab_check(aEvent)
       {
         var title = getAccessible(browserDocument()).name;
-        ok(title.indexOf(aEvent.accessible.name) != -1,
-           "Window title contains the name of active tab document");
+        isnot(title.indexOf(aEvent.accessible.name), -1,
+              "Window title contains the name of active tab document" +
+              " (Is '" + aEvent.accessible.name + "' in '" + title + "'?)");
       }
 
       this.getID = function switchTab_getID() { return "switch tab"; }
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Tests
 
--- a/accessible/tests/mochitest/states/test_buttons.html
+++ b/accessible/tests/mochitest/states/test_buttons.html
@@ -12,24 +12,26 @@
           src="../common.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
   function doTest()
   {
     // Default state.
-    testStates("f1_image", STATE_DEFAULT);
-    testStates("f2_submit", STATE_DEFAULT);
-    testStates("f3_submitbutton", STATE_DEFAULT);
-    testStates("f4_button", 0, 0, STATE_DEFAULT);
-    testStates("f4_image1", STATE_DEFAULT);
-    testStates("f4_image2", 0, 0, STATE_DEFAULT);
-    testStates("f4_submit", 0, 0, STATE_DEFAULT);
-    testStates("f4_submitbutton", 0, 0, STATE_DEFAULT);
+    testStates("f1_image", STATE_DEFAULT | STATE_FOCUSABLE);
+    testStates("f2_submit", STATE_DEFAULT | STATE_FOCUSABLE);
+    testStates("f3_submitbutton", STATE_DEFAULT | STATE_FOCUSABLE);
+    testStates("f3_disabled_reset", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE, 0);
+    testStates("f4_button", STATE_FOCUSABLE, 0, STATE_DEFAULT);
+    testStates("f4_disabled_button", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE, 0);
+    testStates("f4_image1", STATE_DEFAULT | STATE_FOCUSABLE);
+    testStates("f4_image2", STATE_FOCUSABLE, 0, STATE_DEFAULT);
+    testStates("f4_submit", STATE_FOCUSABLE, 0, STATE_DEFAULT);
+    testStates("f4_submitbutton", STATE_FOCUSABLE, 0, STATE_DEFAULT);
 
     SimpleTest.finish();
   }
 
   SimpleTest.waitForExplicitFinish();
   addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -57,23 +59,25 @@
     <input type="text" name="hi">
     <input id="f2_submit" type="submit">
   </form>
 
   <p>A form with a HTML4 submit button:</p>
   <form name="form3" method="get">
     <input type="text" name="hi">
     <button id="f3_submitbutton" type="submit">submit</button>
+    <button id="f3_disabled_reset" type="reset" disabled>reset</button>
   </form>
 
   <p>A form with normal button, two image buttons, submit button,
     HTML4 submit button:</p>
   <form name="form4" method="get">
     <input type="text" name="hi">
     <input id="f4_button" type="button" value="normal" name="normal-button">
+    <input id="f4_disabled_button" type="button" value="disabled" name="disabled-button" disabled>
     <input id="f4_image1" type="image" value="image-button1" name="image-button1">
     <input id="f4_image2" type="image" value="image-button2" name="image-button2">
     <input id="f4_submit" type="submit" value="real-submit" name="real-submit">
     <button id="f4_submitbutton" type="submit">submit</button>
   </form>
 
   </body>
 </html>
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -31,16 +31,17 @@
  * 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 ***** */
 
+#include "nsXULAppAPI.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -396,16 +396,18 @@
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/nsFilePicker.js
 @BINPATH@/components/nsFilePicker.manifest
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
+@BINPATH@/components/SmsDatabaseService.manifest
+@BINPATH@/components/SmsDatabaseService.js
 @BINPATH@/components/nsWifiWorker.js
 @BINPATH@/components/nsWifiWorker.manifest
 #endif
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts.dylib
 #endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -51,34 +51,38 @@ DIRS		= profile/extensions
 PREF_JS_EXPORTS = $(srcdir)/profile/firefox.js \
 		  $(srcdir)/profile/channel-prefs.js \
 		  $(NULL)
 
 
 # hardcode en-US for the moment
 AB_CD = en-US
 
-DEFINES += -DAB_CD=$(AB_CD)
-
-APP_VERSION = $(shell cat $(srcdir)/../config/version.txt)
-DEFINES += -DAPP_VERSION="$(APP_VERSION)"
+DEFINES += \
+  -DAB_CD=$(AB_CD) \
+  -DAPP_VERSION="$(MOZ_APP_VERSION)" \
+  -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" \
+  -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\" \
+  $(NULL)
 
 ifdef LIBXUL_SDK
 include $(topsrcdir)/config/rules.mk
 else
 # Build a binary bootstrapping with XRE_main
 
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 
 CPPSRCS = nsBrowserApp.cpp
 
-LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
-LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
-LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
-LOCAL_INCLUDES += -I$(DEPTH)/build
+LOCAL_INCLUDES += \
+  -I$(topsrcdir)/toolkit/xre \
+  -I$(topsrcdir)/xpcom/base \
+  -I$(topsrcdir)/xpcom/build \
+  -I$(DEPTH)/build \
+  $(NULL)
 
 DEFINES += -DXPCOM_GLUE
 STL_FLAGS=
 
 LIBS += \
 	$(EXTRA_DSO_LIBS) \
 	$(XPCOM_STANDALONE_GLUE_LDOPTS) \
 	$(NULL)
@@ -109,27 +113,21 @@ endif
 
 ifeq ($(OS_ARCH),WINNT)
 RCINCLUDE = splash.rc
 ifndef GNU_CC
 RCFLAGS += -DMOZ_PHOENIX -I$(srcdir)
 else
 RCFLAGS += -DMOZ_PHOENIX --include-dir $(srcdir)
 endif
-ifdef DEBUG
-RCFLAGS += -DDEBUG
-endif
 endif
 
 ifeq ($(OS_ARCH),OS2)
 RESFILE=splashos2.res
 RCFLAGS += -DMOZ_PHOENIX
-ifdef DEBUG
-RCFLAGS += -DDEBUG
-endif
 RCFLAGS += -DFIREFOX_ICO=\"$(DIST)/branding/firefox-os2.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document-os2.ico\"
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT)
 #
 # Control the default heap size.
@@ -156,18 +154,16 @@ libs::
 	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 
 GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js)
 
 endif
 
 endif # LIBXUL_SDK
 
-DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\"
-
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 libs::
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(DIST)/bin/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(DIST)/bin/chrome/icons/default
 	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(DIST)/bin/chrome/icons/default
 endif
 
@@ -200,27 +196,25 @@ else
 APPFILES = MacOS
 endif
 
 libs repackage:: $(PROGRAM)
 	$(MKDIR) -p $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(MOZ_MACBUNDLE_NAME) --exclude English.lproj
 	$(MKDIR) -p $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/$(AB).lproj
 	rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/$(AB).lproj
-	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%LOWER_MAC_APP_NAME%/$(LOWER_MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Info.plist
+	sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%LOWER_MAC_APP_NAME%/$(LOWER_MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Info.plist
 	sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/$(APPFILES)
-	$(RM) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/$(APPFILES)/mangle $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/$(APPFILES)/shlibsign
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/firefox
 else
 	$(RM) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS
 endif
-	-cp -L $(DIST)/bin/mangle $(DIST)/bin/shlibsign $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/$(APPFILES)
 	cp -RL $(DIST)/branding/firefox.icns $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/firefox.icns
 	cp -RL $(DIST)/branding/document.icns $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/document.icns
 	printf APPLMOZB > $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/PkgInfo
 
 else
 ifdef LIBXUL_SDK
 libs::
 	cp $(LIBXUL_DIST)/bin/$(XULRUNNER_STUB_NAME)$(BIN_SUFFIX) $(DIST)/bin/firefox$(BIN_SUFFIX)
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -31,16 +31,17 @@
  * 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 ***** */
 
+#include "nsXULAppAPI.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -557,17 +557,17 @@ HistoryMenu.prototype = {
       undoMenu.setAttribute("disabled", true);
       return;
     }
 
     // enable menu
     undoMenu.removeAttribute("disabled");
 
     // populate menu
-    var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
+    var undoItems = JSON.parse(this._ss.getClosedTabData(window));
     for (var i = 0; i < undoItems.length; i++) {
       var m = document.createElement("menuitem");
       m.setAttribute("label", undoItems[i].title);
       if (undoItems[i].image) {
         let iconURL = undoItems[i].image;
         // don't initiate a connection just to fetch a favicon (see bug 467828)
         if (/^https?:/.test(iconURL))
           iconURL = "moz-anno:favicon:" + iconURL;
--- a/browser/base/content/browser-thumbnails.js
+++ b/browser/base/content/browser-thumbnails.js
@@ -39,19 +39,16 @@ let gBrowserThumbnails = {
   },
 
   uninit: function Thumbnails_uninit() {
     gBrowser.removeTabsProgressListener(this);
 
     this._tabEvents.forEach(function (aEvent) {
       gBrowser.tabContainer.removeEventListener(aEvent, this, false);
     }, this);
-
-    this._timeouts = null;
-    this._pageThumbs = null;
   },
 
   handleEvent: function Thumbnails_handleEvent(aEvent) {
     switch (aEvent.type) {
       case "scroll":
         let browser = aEvent.currentTarget;
         if (this._timeouts.has(browser))
           this._delayedCapture(browser);
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -1050,21 +1050,17 @@
       <statusbar id="status-bar" ordinal="1000"/>
     </toolbar>
   </vbox>
 
 #ifndef XP_UNIX
   <svg:svg height="0">
     <svg:mask id="winstripe-keyhole-forward-mask" maskContentUnits="objectBoundingBox">
       <svg:rect x="0" y="0" width="1" height="1" fill="white"/>
-      <svg:circle cx="-0.46" cy="0.5" r="0.63"/>
-    </svg:mask>
-    <svg:mask id="winstripe-keyhole-forward-mask-hover" maskContentUnits="objectBoundingBox">
-      <svg:rect x="0" y="0" width="1" height="1" fill="white"/>
-      <svg:circle cx="-0.35" cy="0.5" r="0.58"/>
+      <svg:circle cx="-0.34" cy="0.5" r="0.61"/>
     </svg:mask>
     <svg:mask id="winstripe-urlbar-back-button-mask" maskContentUnits="userSpaceOnUse">
       <svg:rect x="0" y="0" width="10000" height="50" fill="white"/>
       <svg:circle cx="-11" cy="13" r="15"/>
     </svg:mask>
   </svg:svg>
 #endif
 #ifdef XP_MACOSX
--- a/browser/base/content/syncSetup.xul
+++ b/browser/base/content/syncSetup.xul
@@ -190,17 +190,17 @@
         </row>
         <row align="center">
           <label control="server"
                  value="&server.label;"/>
           <menulist id="server"
                     oncommand="gSyncSetup.onServerCommand()"
                     oninput="gSyncSetup.onServerInput()">
             <menupopup>
-              <menuitem label="&serverType.main.label;"
+              <menuitem label="&serverType.default.label;"
                         value="main"/>
               <menuitem label="&serverType.custom2.label;"
                         value="custom"/>
             </menupopup>
           </menulist>
         </row>
         <row id="serverFeedbackRow" align="center" hidden="true">
           <spacer/>
@@ -330,17 +330,17 @@
           </row>
           <row align="center">
             <label control="existingServer"
                    value="&server.label;"/>
             <menulist id="existingServer"
                       oncommand="gSyncSetup.onExistingServerCommand()"
                       oninput="gSyncSetup.onExistingServerInput()">
               <menupopup>
-                <menuitem label="&serverType.main.label;"
+                <menuitem label="&serverType.default.label;"
                           value="main"/>
                 <menuitem label="&serverType.custom2.label;"
                           value="custom"/>
               </menupopup>
             </menulist>
           </row>
           <row id="existingServerFeedbackRow" align="center" hidden="true">
             <spacer/>
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -398,17 +398,18 @@ function gatherTextUnder ( root )
 }
 
 function getShellService()
 {
   var shell = null;
   try {
     shell = Components.classes["@mozilla.org/browser/shell-service;1"]
       .getService(Components.interfaces.nsIShellService);
-  } catch (e) {dump("*** e = " + e + "\n");}
+  } catch (e) {
+  }
   return shell;
 }
 
 function isBidiEnabled() {
   // first check the pref.
   if (getBoolPref("bidi.browser.ui", false))
     return true;
 
--- a/browser/components/sessionstore/test/browser_526613.js
+++ b/browser/components/sessionstore/test/browser_526613.js
@@ -59,17 +59,17 @@ function test() {
   browserWindowsCount(1);
 
   // backup old state
   let oldState = ss.getBrowserState();
   // create a new state for testing
   let testState = {
     windows: [
       { tabs: [{ entries: [{ url: "http://example.com/" }] }], selected: 1 },
-      { tabs: [{ entries: [{ url: "about:robots"        }] }], selected: 1 },
+      { tabs: [{ entries: [{ url: "about:mozilla"       }] }], selected: 1 },
     ],
     // make sure the first window is focused, otherwise when restoring the
     // old state, the first window is closed and the test harness gets unloaded
     selectedWindow: 1
   };
 
   let pass = 1;
   function observer(aSubject, aTopic, aData) {
--- a/browser/components/sessionstore/test/browser_579868.js
+++ b/browser/components/sessionstore/test/browser_579868.js
@@ -30,26 +30,26 @@
  * 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 test() {
-  let tab1 = gBrowser.addTab("about:robots");
+  let tab1 = gBrowser.addTab("about:rights");
   let tab2 = gBrowser.addTab("about:mozilla");
   tab1.linkedBrowser.addEventListener("load", mainPart, true);
   waitForExplicitFinish();
 
   function mainPart() {
     tab1.linkedBrowser.removeEventListener("load", mainPart, true);
 
     // Tell the session storer that the tab is pinned
-    let newTabState = '{"entries":[{"url":"about:robots"}],"pinned":true,"userTypedValue":"Hello World!"}';
+    let newTabState = '{"entries":[{"url":"about:rights"}],"pinned":true,"userTypedValue":"Hello World!"}';
     ss.setTabState(tab1, newTabState);
 
     // Undo pinning
     gBrowser.unpinTab(tab1);
 
     is(tab1.linkedBrowser.__SS_tabStillLoading, true,
        "_tabStillLoading should be true.");
 
--- a/browser/components/sessionstore/test/browser_588426.js
+++ b/browser/components/sessionstore/test/browser_588426.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   let state = { windows: [{ tabs: [
       {entries: [{url: "about:mozilla"}], hidden: true},
-      {entries: [{url: "about:robots"}], hidden: true}
+      {entries: [{url: "about:rights"}], hidden: true}
   ] }] };
 
   waitForExplicitFinish();
 
   newWindowWithState(state, function (win) {
     registerCleanupFunction(function () win.close());
 
     is(win.gBrowser.tabs.length, 2, "two tabs were restored");
--- a/browser/components/sessionstore/test/browser_589246.js
+++ b/browser/components/sessionstore/test/browser_589246.js
@@ -247,17 +247,17 @@ function onLastWindowClosed(aSubject, aT
 // which should actually trigger the bug.
 function onWindowUnloaded() {
   info("test #" + testNum + ": onWindowClosed");
   ok(gotLastWindowClosedTopic, "test #" + testNum + ": browser-lastwindow-close-granted was notified prior");
 
   let previousClosedWindowData = ss.getClosedWindowData();
 
   // Now we want to open a new window
-  let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:robots");
+  let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
   newWin.addEventListener("load", function(aEvent) {
     newWin.removeEventListener("load", arguments.callee, false);
 
     newWin.gBrowser.selectedBrowser.addEventListener("load", function () {
       newWin.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
       // Good enough for checking the state
       afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
--- a/browser/components/sessionstore/test/browser_590563.js
+++ b/browser/components/sessionstore/test/browser_590563.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   let oldState = {
     windows: [{
       tabs: [
-        { entries: [{ url: "about:robots" }], hidden: true },
+        { entries: [{ url: "about:mozilla" }], hidden: true },
         { entries: [{ url: "about:blank" }], hidden: false }
       ]
     }]
   };
   let pageData = {
     url: "about:sessionrestore",
     formdata: { "#sessionData": oldState }
   };
--- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events.js
+++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events.js
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const stateBackup = ss.getBrowserState();
 const testState = {
   windows: [{
     tabs: [
       { entries: [{ url: "about:blank" }] },
-      { entries: [{ url: "about:robots" }] }
+      { entries: [{ url: "about:rights" }] }
     ]
   }]
 };
 const lameMultiWindowState = { windows: [
     {
       tabs: [
         { entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } },
         { entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } },
@@ -169,17 +169,17 @@ function test_duplicateTab() {
     is(ss.getTabValue(newTab, "foo"), "bar");
     ss.setTabValue(newTab, "baz", "qux");
   }
 
   function onSSTabRestored(aEvent) {
     is(busyEventCount, 1);
     is(readyEventCount, 1);
     is(ss.getTabValue(newTab, "baz"), "qux");
-    is(newTab.linkedBrowser.currentURI.spec, "about:robots");
+    is(newTab.linkedBrowser.currentURI.spec, "about:rights");
 
     window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
     window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
     gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
 
     runNextTest();
   }
 
@@ -210,17 +210,17 @@ function test_undoCloseTab() {
     is(ss.getTabValue(reopenedTab, "foo"), "bar");
     ss.setTabValue(reopenedTab, "baz", "qux");
   }
 
   function onSSTabRestored(aEvent) {
     is(busyEventCount, 1);
     is(readyEventCount, 1);
     is(ss.getTabValue(reopenedTab, "baz"), "qux");
-    is(reopenedTab.linkedBrowser.currentURI.spec, "about:robots");
+    is(reopenedTab.linkedBrowser.currentURI.spec, "about:rights");
 
     window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false);
     window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false);
     gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
 
     runNextTest();
   }
 
--- a/browser/components/sessionstore/test/browser_618151.js
+++ b/browser/components/sessionstore/test/browser_618151.js
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const stateBackup = ss.getBrowserState();
 const testState = {
   windows: [{
     tabs: [
       { entries: [{ url: "about:blank" }] },
-      { entries: [{ url: "about:robots" }] }
+      { entries: [{ url: "about:mozilla" }] }
     ]
   }]
 };
 
 
 function test() {
   /** Test for Bug 618151 - Overwriting state can lead to unrestored tabs **/
   waitForExplicitFinish();
--- a/browser/components/sessionstore/test/browser_625016.js
+++ b/browser/components/sessionstore/test/browser_625016.js
@@ -23,17 +23,17 @@ function test() {
   // forgetClosedWindow doesn't trigger a delayed save
   while (ss.getClosedWindowCount()) {
     ss.forgetClosedWindow(0);
   }
   is(ss.getClosedWindowCount(), 0, "starting with no closed windows");
 
   // Open a new window, which should trigger a save event soon.
   waitForSaveState(onSaveState);
-  newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:robots");
+  newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:rights");
 }
 
 function onSaveState() {
   // Double check that we have no closed windows
   is(ss.getClosedWindowCount(), 0, "no closed windows on first save");
 
   Services.obs.addObserver(observe1, "sessionstore-state-write", false);
 
--- a/browser/components/sessionstore/test/browser_628270.js
+++ b/browser/components/sessionstore/test/browser_628270.js
@@ -15,32 +15,32 @@ function test() {
   }
 
   waitForExplicitFinish();
 
   // check prerequisites
   assertNumberOfTabs(1, "we start off with one tab");
 
   // setup
-  let tab = gBrowser.addTab("about:robots");
+  let tab = gBrowser.addTab("about:mozilla");
 
   whenTabIsLoaded(tab, function () {
     // hide the newly created tab
     assertNumberOfVisibleTabs(2, "there are two visible tabs");
     gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
     assertNumberOfVisibleTabs(1, "there is one visible tab");
     ok(tab.hidden, "newly created tab is now hidden");
 
     // close and restore hidden tab
     gBrowser.removeTab(tab);
     tab = ss.undoCloseTab(window, 0);
 
     // check that everything was restored correctly, clean up and finish
     whenTabIsLoaded(tab, function () {
-      is(tab.linkedBrowser.currentURI.spec, "about:robots", "restored tab has correct url");
+      is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "restored tab has correct url");
 
       gBrowser.removeTab(tab);
       finish();
     });
   });
 }
 
 function whenTabIsLoaded(tab, callback) {
--- a/browser/components/sessionstore/test/browser_694378.js
+++ b/browser/components/sessionstore/test/browser_694378.js
@@ -6,17 +6,16 @@
 // 1a. ensure that it doesn't throw.
 
 function test() {
   waitForExplicitFinish();
 
   let brokenState = {
     windows: [
       { tabs: [{ entries: [{ url: "about:mozilla" }] }] }
-      //{ tabs: [{ entries: [{ url: "about:robots" }] }] },
     ],
     selectedWindow: 2
   };
   let brokenStateString = JSON.stringify(brokenState);
 
   let gotError = false;
   try {
     ss.setWindowState(window, brokenStateString, true);
@@ -27,9 +26,8 @@ function test() {
   }
 
   ok(!gotError, "ss.setWindowState did not throw an error");
 
   // Make sure that we reset the state. Use a full state just in case things get crazy.
   let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
   waitForBrowserState(blankState, finish);
 }
-
--- a/browser/components/tabview/test/Makefile.in
+++ b/browser/components/tabview/test/Makefile.in
@@ -164,16 +164,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug685692.js \
                  browser_tabview_bug686654.js \
                  browser_tabview_bug696602.js \
                  browser_tabview_bug697390.js \
                  browser_tabview_bug705621.js \
                  browser_tabview_bug706430.js \
                  browser_tabview_bug706736.js \
                  browser_tabview_bug707466.js \
+                 browser_tabview_bug728887.js \
                  browser_tabview_click_group.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_expander.js \
                  browser_tabview_firstrun_pref.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/tabview/test/browser_tabview_bug728887.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  showTabView(function () {
+    let cw = TabView.getContentWindow();
+    let target = cw.GroupItems.groupItems[0].container;
+    EventUtils.sendMouseEvent({type: "dblclick", button: 0}, target, cw);
+    is(cw.GroupItems.groupItems.length, 1, "one groupItem after double clicking");
+
+    hideTabView(finish);
+  });
+}
--- a/browser/components/tabview/ui.js
+++ b/browser/components/tabview/ui.js
@@ -200,16 +200,19 @@ let UI = {
         if (e.originalTarget.id == "content" &&
             Utils.isLeftClick(e) &&
             e.detail == 1) {
           self._createGroupItemOnDrag(e);
         }
       });
 
       iQ(gTabViewFrame.contentDocument).dblclick(function(e) {
+        if (e.originalTarget.id != "content")
+          return;
+
         // Create a group with one tab on double click
         let box =
           new Rect(e.clientX - Math.floor(TabItems.tabWidth/2),
                    e.clientY - Math.floor(TabItems.tabHeight/2),
                    TabItems.tabWidth, TabItems.tabHeight);
         box.inset(-30, -30);
 
         let opts = {immediately: true, bounds: box};
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -5,15 +5,14 @@ browser.jar:
     content/browser/scratchpad.js                 (scratchpad/scratchpad.js)
     content/browser/splitview.css                 (shared/splitview.css)
 *   content/browser/styleeditor.xul               (styleeditor/styleeditor.xul)
     content/browser/styleeditor.css               (styleeditor/styleeditor.css)
     content/browser/devtools/csshtmltree.xul      (styleinspector/csshtmltree.xul)
     content/browser/devtools/cssruleview.xul      (styleinspector/cssruleview.xul)
     content/browser/devtools/styleinspector.css   (styleinspector/styleinspector.css)
     content/browser/orion.js                      (sourceeditor/orion/orion.js)
-    content/browser/orion.css                     (sourceeditor/orion/orion.css)
     content/browser/source-editor-overlay.xul     (sourceeditor/source-editor-overlay.xul)
 *   content/browser/debugger.xul                  (debugger/debugger.xul)
     content/browser/debugger.css                  (debugger/debugger.css)
     content/browser/debugger.js                   (debugger/debugger.js)
     content/browser/debugger-view.js              (debugger/debugger-view.js)
 
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -801,17 +801,17 @@ var Scratchpad = {
       initialText = state.text;
     }
 
     this.editor = new SourceEditor();
 
     let config = {
       mode: SourceEditor.MODES.JAVASCRIPT,
       showLineNumbers: true,
-      placeholderText: initialText
+      initialText: initialText,
     };
 
     let editorPlaceholder = document.getElementById("scratchpad-editor");
     this.editor.init(editorPlaceholder, config, this.onEditorLoad.bind(this));
   },
 
   /**
    * The load event handler for the source editor. This method does post-load
@@ -1063,17 +1063,25 @@ var Scratchpad = {
     // trigger all observers that implement this named handler
     for (let i = 0; i < this._observers.length; ++i) {
       let observer = this._observers[i];
       let handler = observer["on" + aName];
       if (handler) {
         handler.apply(observer, aArgs);
       }
     }
-  }
+  },
+
+  openDocumentationPage: function SP_openDocumentationPage()
+  {
+    let url = this.strings.GetStringFromName("help.openDocumentationPage");
+    let newTab = this.gBrowser.addTab(url);
+    this.browserWindow.focus();
+    this.gBrowser.selectedTab = newTab;
+  },
 };
 
 XPCOMUtils.defineLazyGetter(Scratchpad, "strings", function () {
   return Services.strings.createBundle(SCRATCHPAD_L10N);
 });
 
 addEventListener("load", Scratchpad.onLoad.bind(Scratchpad), false);
 addEventListener("unload", Scratchpad.onUnload.bind(Scratchpad), false);
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -78,16 +78,17 @@
   <command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
   <command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/>
   <command id="sp-cmd-browserContext" oncommand="Scratchpad.setBrowserContext();" disabled="true"/>
   <command id="sp-cmd-resetContext" oncommand="Scratchpad.resetContext();"/>
   <command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
   <command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
   <command id="sp-cmd-undo" oncommand="Scratchpad.undo();" disabled="true"/>
   <command id="sp-cmd-redo" oncommand="Scratchpad.redo();" disabled="true"/>
+  <command id="sp-cmd-documentationLink" oncommand="Scratchpad.openDocumentationPage();"/>
 </commandset>
 
 <keyset id="sp-keyset">
   <key id="sp-key-window"
        key="&newWindowCmd.commandkey;"
        command="sp-cmd-newWindow"
        modifiers="accel"/>
   <key id="sp-key-open"
@@ -166,16 +167,19 @@
        keycode="VK_F3"
        command="cmd_findPrevious"
        modifiers="shift"/>
 #endif
   <key id="key_gotoLine"
        key="&gotoLineCmd.key;"
        command="cmd_gotoLine"
        modifiers="accel"/>
+  <key id="key_openHelp"
+       keycode="VK_F1"
+       command="sp-cmd-documentationLink"/>
 </keyset>
 
 
 <menubar id="sp-menubar">
   <menu id="sp-file-menu" label="&fileMenu.label;"
         accesskey="&fileMenu.accesskey;">
     <menupopup id="sp-menu-filepopup">
       <menuitem id="sp-menu-newscratchpad"
@@ -311,16 +315,34 @@
                 type="radio"/>
       <menuitem id="sp-menu-browser"
                 command="sp-cmd-browserContext"
                 label="&browserContext.label;"
                 accesskey="&browserContext.accesskey;"
                 type="radio"/>
     </menupopup>
   </menu>
+
+#ifdef XP_WIN
+  <menu id="sp-help-menu"
+        label="&helpMenu.label;"
+        accesskey="&helpMenuWin.accesskey;">
+#else
+  <menu id="sp-help-menu"
+        label="&helpMenu.label;"
+        accesskey="&helpMenu.accesskey;">
+#endif
+    <menupopup id="sp-menu-help">
+      <menuitem id="sp-menu-documentation"
+                label="&documentationLink.label;"
+                accesskey="&documentationLink.accesskey;"
+                command="sp-cmd-documentationLink"
+                key="key_openHelp"/>
+    </menupopup>
+  </menu>
 </menubar>
 
 <popupset id="scratchpad-popups">
   <menupopup id="scratchpad-text-popup"
              onpopupshowing="goUpdateGlobalEditMenuItems()">
     <menuitem id="menu_cut"/>
     <menuitem id="menu_copy"/>
     <menuitem id="menu_paste"/>
--- a/browser/devtools/scratchpad/test/Makefile.in
+++ b/browser/devtools/scratchpad/test/Makefile.in
@@ -58,12 +58,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_scratchpad_bug_679467_falsy.js \
 		browser_scratchpad_bug_699130_edit_ui_updates.js \
 		browser_scratchpad_bug_669612_unsaved.js \
 		browser_scratchpad_bug_653427_confirm_close.js \
 		browser_scratchpad_bug684546_reset_undo.js \
 		browser_scratchpad_bug690552_display_outputs_errors.js \
 		browser_scratchpad_bug650345_find_ui.js \
 		browser_scratchpad_bug714942_goto_line_ui.js \
+		browser_scratchpad_bug_650760_help_key.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_650760_help_key.js
@@ -0,0 +1,60 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  content.location = "data:text/html,Test keybindings for opening Scratchpad MDN Documentation, bug 650760";
+  gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
+
+    ok(window.Scratchpad, "Scratchpad variable exists");
+
+    openScratchpad(runTest);
+  }, true);
+}
+
+function runTest()
+{
+  let sp = gScratchpadWindow.Scratchpad;
+  ok(sp, "Scratchpad object exists in new window");
+  ok(sp.editor.hasFocus(), "the editor has focus");
+
+  let keyid = gScratchpadWindow.document.getElementById("key_openHelp");
+  let modifiers = keyid.getAttribute("modifiers");
+
+  let key = null;
+  if (keyid.getAttribute("keycode"))
+    key = keyid.getAttribute("keycode");
+
+  else if (keyid.getAttribute("key"))
+    key = keyid.getAttribute("key");
+
+  isnot(key, null, "Successfully retrieved keycode/key");
+
+  var aEvent = {
+    shiftKey: modifiers.match("shift"),
+    ctrlKey: modifiers.match("ctrl"),
+    altKey: modifiers.match("alt"),
+    metaKey: modifiers.match("meta"),
+    accelKey: modifiers.match("accel")
+  }
+
+  info("check that the MDN page is opened on \"F1\"");
+  let linkClicked = false;
+  sp.openDocumentationPage = function(event) { linkClicked = true; };
+
+  EventUtils.synthesizeKey(key, aEvent, gScratchpadWindow);
+
+  is(linkClicked, true, "MDN page will open");
+  finishTest();
+}
+
+function finishTest()
+{
+  gScratchpadWindow.close();
+  finish();
+}
--- a/browser/devtools/sourceeditor/orion/Makefile.dryice.js
+++ b/browser/devtools/sourceeditor/orion/Makefile.dryice.js
@@ -44,20 +44,20 @@ const ORION_EDITOR = "org.eclipse.orion.
 var js_src = copy.createDataObject();
 
 copy({
   source: [
     ORION_EDITOR + "/orion/textview/global.js",
     ORION_EDITOR + "/orion/textview/eventTarget.js",
     ORION_EDITOR + "/orion/editor/regex.js",
     ORION_EDITOR + "/orion/textview/keyBinding.js",
+    ORION_EDITOR + "/orion/textview/annotations.js",
     ORION_EDITOR + "/orion/textview/rulers.js",
     ORION_EDITOR + "/orion/textview/undoStack.js",
     ORION_EDITOR + "/orion/textview/textModel.js",
-    ORION_EDITOR + "/orion/textview/annotations.js",
     ORION_EDITOR + "/orion/textview/tooltip.js",
     ORION_EDITOR + "/orion/textview/textView.js",
     ORION_EDITOR + "/orion/textview/textDND.js",
     ORION_EDITOR + "/orion/editor/htmlGrammar.js",
     ORION_EDITOR + "/orion/editor/textMateStyler.js",
     ORION_EDITOR + "/examples/textview/textStyler.js",
   ],
   dest: js_src,
--- a/browser/devtools/sourceeditor/orion/README
+++ b/browser/devtools/sourceeditor/orion/README
@@ -3,25 +3,37 @@
 This is the Orion editor packaged for Mozilla.
 
 The Orion editor web site: http://www.eclipse.org/orion
 
 # Upgrade
 
 To upgrade Orion to a newer version see the UPGRADE file.
 
-Orion version: git clone from 2011-12-09
-               commit hash d8a6dc01d9c561d6eb99f03b64c8c78ce785c59d
-  + patch for Eclipse Bug 366312 - right-clicking outside of the selection causes the caret to move
-    https://github.com/mihaisucan/orion.client/tree/bug-366312
-      see https://bugs.eclipse.org/bugs/show_bug.cgi?id=366312
-  + patch for Mozilla Bug 711737 - Orion should support all the CSS properties from CSS1, CSS2, CSS2.1 and CSS3
-    https://bugzilla.mozilla.org/show_bug.cgi?id=711737
-  + patch for Mozilla Bug 719028 - Style Editor does not highlight a few CSS2.0 and CSS3 properties
-    https://bugzilla.mozilla.org/show_bug.cgi?id=719028
+Orion version: git clone from 2012-01-26
+               commit hash 1d1150131dacecc9f4d9eb3cdda9103ea1819045
+
+  + patch for Eclipse Bug 370584 - [Firefox] Edit menu items in context menus
+    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=137d5a8e9bbc0fa204caae74ebd25a7d9d4729bd
+    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370584
+
+  + patches for Eclipse Bug 370606 - Problems with UndoStack and deletions at
+                                     the beginning of the document
+    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=cec71bddaf32251c34d3728df5da13c130d14f33
+    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=3ce24b94f1d8103b16b9cf16f2f50a6302d43b18
+    http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=27177e9a3dc70c20b4877e3eab3adfff1d56e342
+    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370606
 
 # License
 
 The following files are licensed according to the contents in the LICENSE
 file:
   orion.js
   orion.css
 
+# Theming
+
+The syntax highlighting and the editor UI are themed using a style sheet. The
+default theme file is browser/themes/*/devtools/orion.css - this is based on the
+orion.css found in this folder.
+
+Please note that the orion.css file from this folder is not used. It is kept
+here only as reference.
--- a/browser/devtools/sourceeditor/orion/orion.js
+++ b/browser/devtools/sourceeditor/orion/orion.js
@@ -5,37 +5,36 @@
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
  *		Mihai Sucan (Mozilla Foundation) - fix for Bug#364214
- *		Alex Lakatos (Mozilla Contributor) - fix for Mozilla Bug#719028
  */
 
 /*global window */
 
 /**
  * Evaluates the definition function and mixes in the returned module with
  * the module specified by <code>moduleName</code>.
  * <p>
  * This function is intented to by used when RequireJS is not available.
  * </p>
  *
+ * @param {String} name The mixin module name.
  * @param {String[]} deps The array of dependency names.
  * @param {Function} callback The definition function.
- * @param {String} moduleName The mixin module name.
  */
 if (!window.define) {
-	window.define = function(deps, callback, moduleName) {
+	window.define = function(name, deps, callback) {
 		var module = this;
-		var split = (moduleName || "").split("/"), i, j;
-		for (i = 0; i < split.length; i++) {
+		var split = (name || "").split("/"), i, j;
+		for (i = 0; i < split.length - 1; i++) {
 			module = module[split[i]] = (module[split[i]] || {});
 		}
 		var depModules = [], depModule;
 		for (j = 0; j < deps.length; j++) {
 			depModule = this;
 			split = deps[j].split("/");
 			for (i = 0; i < split.length - 1; i++) {
 				depModule = depModule[split[i]] = (depModule[split[i]] || {});
@@ -91,17 +90,17 @@ if (!window.require) {
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
  ******************************************************************************/
  
 /*global define */
-define([], function() {
+define("orion/textview/eventTarget", [], function() {
 	/** 
 	 * Constructs a new EventTarget object.
 	 * 
 	 * @class 
 	 * @name orion.textview.EventTarget
 	 */
 	function EventTarget() {
 	}
@@ -220,17 +219,17 @@ define([], function() {
 				}
 				if (listeners.length === 0) {
 					delete this._eventTypes[type];
 				}
 			}
 		}
 	};
 	return {EventTarget: EventTarget};
-}, "orion/textview");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  *
@@ -239,17 +238,17 @@ define([], function() {
  *******************************************************************************/
 /*global define */
 /*jslint browser:true regexp:false*/
 /**
  * @name orion.editor.regex
  * @class Utilities for dealing with regular expressions.
  * @description Utilities for dealing with regular expressions.
  */
-define([], function() {
+define("orion/editor/regex", [], function() {
 	/**
 	 * @methodOf orion.editor.regex
 	 * @static
 	 * @description Escapes regex special characters in the input string.
 	 * @param {String} str The string to escape.
 	 * @returns {String} A copy of <code>str</code> with regex special characters escaped.
 	 */
 	function escape(str) {
@@ -277,33 +276,33 @@ define([], function() {
 		}
 		return null;
 	}
 
 	return {
 		escape: escape,
 		parse: parse
 	};
-}, "orion/editor");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
  ******************************************************************************/
 
 /*global window define */
 
-define([], function() {
+define("orion/textview/keyBinding", [], function() {
 	var isMac = window.navigator.platform.indexOf("Mac") !== -1;
 
 	/**
 	 * Constructs a new key binding with the given key code and modifiers.
 	 * 
 	 * @param {String|Number} keyCode the key code.
 	 * @param {Boolean} mod1 the primary modifier (usually Command on Mac and Control on other platforms).
 	 * @param {Boolean} mod2 the secondary modifier (usually Shift).
@@ -362,1579 +361,33 @@ define([], function() {
 			if (this.mod1 !== kb.mod1) { return false; }
 			if (this.mod2 !== kb.mod2) { return false; }
 			if (this.mod3 !== kb.mod3) { return false; }
 			if (this.mod4 !== kb.mod4) { return false; }
 			return true;
 		} 
 	};
 	return {KeyBinding: KeyBinding};
-}, "orion/textview");
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-/*global define setTimeout clearTimeout setInterval clearInterval Node */
-
-define(['orion/textview/tooltip'], function(mTooltip) {
-
-	/**
-	 * Constructs a new ruler. 
-	 * <p>
-	 * The default implementation does not implement all the methods in the interface
-	 * and is useful only for objects implementing rulers.
-	 * <p/>
-	 * 
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {String} [rulerOverview="page"] the overview for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle] the style for the ruler. 
-	 * 
-	 * @class This interface represents a ruler for the text view.
-	 * <p>
-	 * A Ruler is a graphical element that is placed either on the left or on the right side of 
-	 * the view. It can be used to provide the view with per line decoration such as line numbering,
-	 * bookmarks, breakpoints, folding disclosures, etc. 
-	 * </p><p>
-	 * There are two types of rulers: page and document. A page ruler only shows the content for the lines that are
-	 * visible, while a document ruler always shows the whole content.
-	 * </p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.LineNumberRuler}<br/>
-	 * {@link orion.textview.AnnotationRuler}<br/>
-	 * {@link orion.textview.OverviewRuler}<br/> 
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextView#addRuler}
-	 * </p>		 
-	 * @name orion.textview.Ruler
-	 */
-	function Ruler (annotationModel, rulerLocation, rulerOverview, rulerStyle) {
-		this._location = rulerLocation || "left";
-		this._overview = rulerOverview || "page";
-		this._rulerStyle = rulerStyle;
-		this._types = [];
-		this._view = null;
-		var self = this;
-		this._listener = {
-			onTextModelChanged: function(e) {
-				self._onTextModelChanged(e);
-			},
-			onAnnotationModelChanged: function(e) {
-				self._onAnnotationModelChanged(e);
-			}
-		};
-		this.setAnnotationModel(annotationModel);
-	}
-	Ruler.prototype = /** @lends orion.textview.Ruler.prototype */ {
-		/**
-		 * Adds an annotation type to the ruler.
-		 * <p>
-		 * Only annotations of the specified types will be shown by
-		 * this ruler.
-		 * </p>
-		 *
-		 * @param type {Object} the annotation type to be shown
-		 * 
-		 * @see #removeAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		addAnnotationType: function(type) {
-			this._types.push(type);
-		},
-		/**
-		 * Returns the annotations for a given line range merging multiple
-		 * annotations when necessary.
-		 * <p>
-		 * This method is called by the text view when the ruler is redrawn.
-		 * </p>
-		 *
-		 * @param {Number} startLine the start line index
-		 * @param {Number} endLine the end line index
-		 * @return {orion.textview.Annotation[]} the annotations for the line range. The array might be sparse.
-		 */
-		getAnnotations: function(startLine, endLine) {
-			var annotationModel = this._annotationModel;
-			if (!annotationModel) { return []; }
-			var model = this._view.getModel();
-			var start = model.getLineStart(startLine);
-			var end = model.getLineEnd(endLine - 1);
-			var baseModel = model;
-			if (model.getBaseModel) {
-				baseModel = model.getBaseModel();
-				start = model.mapOffset(start);
-				end = model.mapOffset(end);
-			}
-			var annotations = annotationModel.getAnnotations(start, end);
-			var result = [];
-			while (annotations.hasNext()) {
-				var annotation = annotations.next();
-				if (!this.isAnnotationTypeVisible(annotation.type)) { continue; }
-				var annotationLineStart = baseModel.getLineAtOffset(annotation.start);
-				var annotationLineEnd = baseModel.getLineAtOffset(Math.max(annotation.start, annotation.end - 1));
-				for (var lineIndex = annotationLineStart; lineIndex<=annotationLineEnd; lineIndex++) {
-					var visualLineIndex = lineIndex;
-					if (model !== baseModel) {
-						var ls = baseModel.getLineStart(lineIndex);
-						ls = model.mapOffset(ls, true);
-						if (ls === -1) { continue; }
-						visualLineIndex = model.getLineAtOffset(ls);
-					}
-					if (!(startLine <= visualLineIndex && visualLineIndex < endLine)) { continue; }
-					var rulerAnnotation = this._mergeAnnotation(result[visualLineIndex], annotation, lineIndex - annotationLineStart, annotationLineEnd - annotationLineStart + 1);
-					if (rulerAnnotation) {
-						result[visualLineIndex] = rulerAnnotation;
-					}
-				}
-			}
-			if (!this._multiAnnotation && this._multiAnnotationOverlay) {
-				for (var k in result) {
-					if (result[k]._multiple) {
-						result[k].html = result[k].html + this._multiAnnotationOverlay.html;
-					}
-				}
-			}
-			return result;
-		},
-		/**
-		 * Returns the annotation model.
-		 *
-		 * @returns {orion.textview.AnnotationModel} the ruler annotation model.
-		 *
-		 * @see #setAnnotationModel
-		 */
-		getAnnotationModel: function() {
-			return this._annotationModel;
-		},
-		/**
-		 * Returns the ruler location.
-		 *
-		 * @returns {String} the ruler location, which is either "left" or "right".
-		 *
-		 * @see #getOverview
-		 */
-		getLocation: function() {
-			return this._location;
-		},
-		/**
-		 * Returns the ruler overview type.
-		 *
-		 * @returns {String} the overview type, which is either "page" or "document".
-		 *
-		 * @see #getLocation
-		 */
-		getOverview: function() {
-			return this._overview;
-		},
-		/**
-		 * Returns the style information for the ruler.
-		 *
-		 * @returns {orion.textview.Style} the style information.
-		 */
-		getRulerStyle: function() {
-			return this._rulerStyle;
-		},
-		/**
-		 * Returns the widest annotation which determines the width of the ruler.
-		 * <p>
-		 * If the ruler does not have a fixed width it should provide the widest
-		 * annotation to avoid the ruler from changing size as the view scrolls.
-		 * </p>
-		 * <p>
-		 * This method is called by the text view when the ruler is redrawn.
-		 * </p>
-		 *
-		 * @returns {orion.textview.Annotation} the widest annotation.
-		 *
-		 * @see #getAnnotations
-		 */
-		getWidestAnnotation: function() {
-			return null;
-		},
-		/**
-		 * Returns whether the ruler shows annotations of the specified type.
-		 *
-		 * @param {Object} type the annotation type 
-		 * @returns {Boolean} whether the specified annotation type is shown
-		 * 
-		 * @see #addAnnotationType
-		 * @see #removeAnnotationType
-		 */
-		isAnnotationTypeVisible: function(type) {
-			for (var i = 0; i < this._types.length; i++) {
-				if (this._types[i] === type) {
-					return true;
-				}
-			}
-			return false;
-		},
-		/**
-		 * Removes an annotation type from the ruler.
-		 *
-		 * @param {Object} type the annotation type to be removed
-		 * 
-		 * @see #addAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		removeAnnotationType: function(type) {
-			for (var i = 0; i < this._types.length; i++) {
-				if (this._types[i] === type) {
-					this._types.splice(i, 1);
-					break;
-				}
-			}
-		},
-		/**
-		 * Sets the annotation model for the ruler.
-		 *
-		 * @param {orion.textview.AnnotationModel} annotationModel the annotation model.
-		 *
-		 * @see #getAnnotationModel
-		 */
-		setAnnotationModel: function (annotationModel) {
-			if (this._annotationModel) {
-				this._annotationModel.removEventListener("Changed", this._listener.onAnnotationModelChanged); 
-			}
-			this._annotationModel = annotationModel;
-			if (this._annotationModel) {
-				this._annotationModel.addEventListener("Changed", this._listener.onAnnotationModelChanged); 
-			}
-		},
-		/**
-		 * Sets the annotation that is displayed when a given line contains multiple
-		 * annotations.  This annotation is used when there are different types of
-		 * annotations in a given line.
-		 *
-		 * @param {orion.textview.Annotation} annotation the annotation for lines with multiple annotations.
-		 * 
-		 * @see #setMultiAnnotationOverlay
-		 */
-		setMultiAnnotation: function(annotation) {
-			this._multiAnnotation = annotation;
-		},
-		/**
-		 * Sets the annotation that overlays a line with multiple annotations.  This annotation is displayed on
-		 * top of the computed annotation for a given line when there are multiple annotations of the same type
-		 * in the line. It is also used when the multiple annotation is not set.
-		 *
-		 * @param {orion.textview.Annotation} annotation the annotation overlay for lines with multiple annotations.
-		 * 
-		 * @see #setMultiAnnotation
-		 */
-		setMultiAnnotationOverlay: function(annotation) {
-			this._multiAnnotationOverlay = annotation;
-		},
-		/**
-		 * Sets the view for the ruler.
-		 * <p>
-		 * This method is called by the text view when the ruler
-		 * is added to the view.
-		 * </p>
-		 *
-		 * @param {orion.textview.TextView} view the text view.
-		 */
-		setView: function (view) {
-			if (this._onTextModelChanged && this._view) {
-				this._view.removeEventListener("ModelChanged", this._listener.onTextModelChanged); 
-			}
-			this._view = view;
-			if (this._onTextModelChanged && this._view) {
-				this._view.addEventListener("ModelChanged", this._listener.onTextModelChanged);
-			}
-		},
-		/**
-		 * This event is sent when the user clicks a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the click event.
-		 */
-		onClick: function(lineIndex, e) {
-		},
-		/**
-		 * This event is sent when the user double clicks a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the double click event.
-		 */
-		onDblClick: function(lineIndex, e) {
-		},
-		/**
-		 * This event is sent when the user moves the mouse over a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse move event.
-		 */
-		onMouseMove: function(lineIndex, e) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (!tooltip) { return; }
-			if (tooltip.isVisible() && this._tooltipLineIndex === lineIndex) { return; }
-			this._tooltipLineIndex = lineIndex;
-			var self = this;
-			tooltip.setTarget({
-				y: e.clientY,
-				getTooltipInfo: function() {
-					return self._getTooltipInfo(self._tooltipLineIndex, this.y);
-				}
-			});
-		},
-		/**
-		 * This event is sent when the mouse pointer enters a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse over event.
-		 */
-		onMouseOver: function(lineIndex, e) {
-			this.onMouseMove(lineIndex, e);
-		},
-		/**
-		 * This event is sent when the mouse pointer exits a line annotation.
-		 *
-		 * @event
-		 * @param {Number} lineIndex the line index of the annotation under the pointer.
-		 * @param {DOMEvent} e the mouse out event.
-		 */
-		onMouseOut: function(lineIndex, e) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (!tooltip) { return; }
-			tooltip.setTarget(null);
-		},
-		/** @ignore */
-		_getTooltipInfo: function(lineIndex, y) {
-			if (lineIndex === undefined) { return; }
-			var view = this._view;
-			var model = view.getModel();
-			var annotationModel = this._annotationModel;
-			var annotations = [];
-			if (annotationModel) {
-				var start = model.getLineStart(lineIndex);
-				var end = model.getLineEnd(lineIndex);
-				if (model.getBaseModel) {
-					start = model.mapOffset(start);
-					end = model.mapOffset(end);
-				}
-				var iter = annotationModel.getAnnotations(start, end);
-				var annotation;
-				while (iter.hasNext()) {
-					annotation = iter.next();
-					if (!this.isAnnotationTypeVisible(annotation.type)) { continue; }
-					annotations.push(annotation);
-				}
-			}
-			var contents = this._getTooltipContents(lineIndex, annotations);
-			if (!contents) { return null; }
-			var info = {
-				contents: contents,
-				anchor: this.getLocation()
-			};
-			var rect = view.getClientArea();
-			if (this.getOverview() === "document") {
-				rect.y = view.convert({y: y}, "view", "document").y;
-			} else {
-				rect.y = view.getLocationAtOffset(model.getLineStart(lineIndex)).y;
-			}
-			view.convert(rect, "document", "page");
-			info.x = rect.x;
-			info.y = rect.y;
-			if (info.anchor === "right") {
-				info.x += rect.width;
-			}
-			info.maxWidth = rect.width;
-			info.maxHeight = rect.height - (rect.y - view._parent.getBoundingClientRect().top);
-			return info;
-		},
-		/** @ignore */
-		_getTooltipContents: function(lineIndex, annotations) {
-			return annotations;
-		},
-		/** @ignore */
-		_onAnnotationModelChanged: function(e) {
-			var view = this._view;
-			if (!view) { return; }
-			var model = view.getModel(), self = this;
-			var lineCount = model.getLineCount();
-			if (e.textModelChangedEvent) {
-				var start = e.textModelChangedEvent.start;
-				if (model.getBaseModel) { start = model.mapOffset(start, true); }
-				var startLine = model.getLineAtOffset(start);
-				view.redrawLines(startLine, lineCount, self);
-				return;
-			}
-			function redraw(changes) {
-				for (var i = 0; i < changes.length; i++) {
-					if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
-					var start = changes[i].start;
-					var end = changes[i].end;
-					if (model.getBaseModel) {
-						start = model.mapOffset(start, true);
-						end = model.mapOffset(end, true);
-					}
-					if (start !== -1 && end !== -1) {
-						view.redrawLines(model.getLineAtOffset(start), model.getLineAtOffset(Math.max(start, end - 1)) + 1, self);
-					}
-				}
-			}
-			redraw(e.added);
-			redraw(e.removed);
-			redraw(e.changed);
-		},
-		/** @ignore */
-		_mergeAnnotation: function(result, annotation, annotationLineIndex, annotationLineCount) {
-			if (!result) { result = {}; }
-			if (annotationLineIndex === 0) {
-				if (result.html && annotation.html) {
-					if (annotation.html !== result.html) {
-						if (!result._multiple && this._multiAnnotation) {
-							result.html = this._multiAnnotation.html;
-						}
-					} 
-					result._multiple = true;
-				} else {
-					result.html = annotation.html;
-				}
-			}
-			result.style = this._mergeStyle(result.style, annotation.style);
-			return result;
-		},
-		/** @ignore */
-		_mergeStyle: function(result, style) {
-			if (style) {
-				if (!result) { result = {}; }
-				if (result.styleClass && style.styleClass && result.styleClass !== style.styleClass) {
-					result.styleClass += " " + style.styleClass;
-				} else {
-					result.styleClass = style.styleClass;
-				}
-				var prop;
-				if (style.style) {
-					if (!result.style) { result.style  = {}; }
-					for (prop in style.style) {
-						if (!result.style[prop]) {
-							result.style[prop] = style.style[prop];
-						}
-					}
-				}
-				if (style.attributes) {
-					if (!result.attributes) { result.attributes  = {}; }
-					for (prop in style.attributes) {
-						if (!result.attributes[prop]) {
-							result.attributes[prop] = style.attributes[prop];
-						}
-					}
-				}
-			}
-			return result;
-		}
-	};
-
-	/**
-	 * Constructs a new line numbering ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 * @param {orion.textview.Style} [oddStyle={style: {backgroundColor: "white"}] the style for lines with odd line index.
-	 * @param {orion.textview.Style} [evenStyle={backgroundColor: "white"}] the style for lines with even line index.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements a line numbering ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.Ruler}
-	 * </p>
-	 * @name orion.textview.LineNumberRuler
-	 */
-	function LineNumberRuler (annotationModel, rulerLocation, rulerStyle, oddStyle, evenStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
-		this._oddStyle = oddStyle || {style: {backgroundColor: "white"}};
-		this._evenStyle = evenStyle || {style: {backgroundColor: "white"}};
-		this._numOfDigits = 0;
-	}
-	LineNumberRuler.prototype = new Ruler(); 
-	/** @ignore */
-	LineNumberRuler.prototype.getAnnotations = function(startLine, endLine) {
-		var result = Ruler.prototype.getAnnotations.call(this, startLine, endLine);
-		var model = this._view.getModel();
-		for (var lineIndex = startLine; lineIndex < endLine; lineIndex++) {
-			var style = lineIndex & 1 ? this._oddStyle : this._evenStyle;
-			var mapLine = lineIndex;
-			if (model.getBaseModel) {
-				var lineStart = model.getLineStart(mapLine);
-				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
-			}
-			if (!result[lineIndex]) { result[lineIndex] = {}; }
-			result[lineIndex].html = (mapLine + 1) + "";
-			if (!result[lineIndex].style) { result[lineIndex].style = style; }
-		}
-		return result;
-	};
-	/** @ignore */
-	LineNumberRuler.prototype.getWidestAnnotation = function() {
-		var lineCount = this._view.getModel().getLineCount();
-		return this.getAnnotations(lineCount - 1, lineCount)[lineCount - 1];
-	};
-	/** @ignore */
-	LineNumberRuler.prototype._onTextModelChanged = function(e) {
-		var start = e.start;
-		var model = this._view.getModel();
-		var lineCount = model.getBaseModel ? model.getBaseModel().getLineCount() : model.getLineCount();
-		var numOfDigits = (lineCount+"").length;
-		if (this._numOfDigits !== numOfDigits) {
-			this._numOfDigits = numOfDigits;
-			var startLine = model.getLineAtOffset(start);
-			this._view.redrawLines(startLine,  model.getLineCount(), this);
-		}
-	};
-	
-	/** 
-	 * @class This is class represents an annotation for the AnnotationRuler. 
-	 * <p> 
-	 * <b>See:</b><br/> 
-	 * {@link orion.textview.AnnotationRuler}
-	 * </p> 
-	 * 
-	 * @name orion.textview.Annotation 
-	 * 
-	 * @property {String} [html=""] The html content for the annotation, typically contains an image.
-	 * @property {orion.textview.Style} [style] the style for the annotation.
-	 * @property {orion.textview.Style} [overviewStyle] the style for the annotation in the overview ruler.
-	 */ 
-	/**
-	 * Constructs a new annotation ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 * @param {orion.textview.Annotation} [defaultAnnotation] the default annotation.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an annotation ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.Ruler}<br/>
-	 * {@link orion.textview.Annotation}
-	 * </p>
-	 * @name orion.textview.AnnotationRuler
-	 */
-	function AnnotationRuler (annotationModel, rulerLocation, rulerStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
-	}
-	AnnotationRuler.prototype = new Ruler();
-	
-	/**
-	 * Constructs a new overview ruler. 
-	 * <p>
-	 * The overview ruler is used in conjunction with a AnnotationRuler, for each annotation in the 
-	 * AnnotationRuler this ruler displays a mark in the overview. Clicking on the mark causes the 
-	 * view to scroll to the annotated line.
-	 * </p>
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an overview ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.AnnotationRuler} <br/>
-	 * {@link orion.textview.Ruler} 
-	 * </p>
-	 * @name orion.textview.OverviewRuler
-	 */
-	function OverviewRuler (annotationModel, rulerLocation, rulerStyle) {
-		Ruler.call(this, annotationModel, rulerLocation, "document", rulerStyle);
-	}
-	OverviewRuler.prototype = new Ruler();
-	
-	/** @ignore */
-	OverviewRuler.prototype.getRulerStyle = function() {
-		var result = {style: {lineHeight: "1px", fontSize: "1px"}};
-		result = this._mergeStyle(result, this._rulerStyle);
-		return result;
-	};
-	/** @ignore */	
-	OverviewRuler.prototype.onClick = function(lineIndex, e) {
-		if (lineIndex === undefined) { return; }
-		this._view.setTopIndex(lineIndex);
-	};
-	/** @ignore */
-	OverviewRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
-		if (annotations.length === 0) {
-			var model = this._view.getModel();
-			var mapLine = lineIndex;
-			if (model.getBaseModel) {
-				var lineStart = model.getLineStart(mapLine);
-				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
-			}
-			return "Line: " + (mapLine + 1);
-		}
-		return Ruler.prototype._getTooltipContents.call(this, lineIndex, annotations);
-	};
-	/** @ignore */
-	OverviewRuler.prototype._mergeAnnotation = function(previousAnnotation, annotation, annotationLineIndex, annotationLineCount) {
-		if (annotationLineIndex !== 0) { return undefined; }
-		var result = previousAnnotation;
-		if (!result) {
-			//TODO annotationLineCount does not work when there are folded lines
-			var height = 3 * annotationLineCount;
-			result = {html: "&nbsp;", style: { style: {height: height + "px"}}};
-			result.style = this._mergeStyle(result.style, annotation.overviewStyle);
-		}
-		return result;
-	};
-
-	/**
-	 * Constructs a new folding ruler. 
-	 *
-	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
-	 * @param {String} [rulerLocation="left"] the location for the ruler.
-	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
-	 *
-	 * @augments orion.textview.Ruler
-	 * @class This objects implements an overview ruler.
-	 *
-	 * <p><b>See:</b><br/>
-	 * {@link orion.textview.AnnotationRuler} <br/>
-	 * {@link orion.textview.Ruler} 
-	 * </p>
-	 * @name orion.textview.OverviewRuler
-	 */
-	function FoldingRuler (annotationModel, rulerLocation, rulerStyle) {
-		AnnotationRuler.call(this, annotationModel, rulerLocation, rulerStyle);
-	}
-	FoldingRuler.prototype = new AnnotationRuler();
-	
-	/** @ignore */
-	FoldingRuler.prototype.onClick =  function(lineIndex, e) {
-		if (lineIndex === undefined) { return; }
-		var annotationModel = this._annotationModel;
-		if (!annotationModel) { return; }
-		var view = this._view;
-		var model = view.getModel();
-		var start = model.getLineStart(lineIndex);
-		var end = model.getLineEnd(lineIndex, true);
-		if (model.getBaseModel) {
-			start = model.mapOffset(start);
-			end = model.mapOffset(end);
-		}
-		var annotation, iter = annotationModel.getAnnotations(start, end);
-		while (!annotation && iter.hasNext()) {
-			var a = iter.next();
-			if (!this.isAnnotationTypeVisible(a.type)) { continue; }
-			annotation = a;
-		}
-		if (annotation) {
-			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
-			if (tooltip) {
-				tooltip.setTarget(null);
-			}
-			if (annotation.expanded) {
-				annotation.collapse();
-			} else {
-				annotation.expand();
-			}
-			this._annotationModel.modifyAnnotation(annotation);
-		}
-	};
-	/** @ignore */
-	FoldingRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
-		if (annotations.length === 1) {
-			if (annotations[0].expanded) {
-				return null;
-			}
-		}
-		return AnnotationRuler.prototype._getTooltipContents.call(this, lineIndex, annotations);
-	};
-	/** @ignore */
-	FoldingRuler.prototype._onAnnotationModelChanged = function(e) {
-		if (e.textModelChangedEvent) {
-			AnnotationRuler.prototype._onAnnotationModelChanged.call(this, e);
-			return;
-		}
-		var view = this._view;
-		if (!view) { return; }
-		var model = view.getModel(), self = this, i;
-		var lineCount = model.getLineCount(), lineIndex = lineCount;
-		function redraw(changes) {
-			for (i = 0; i < changes.length; i++) {
-				if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
-				var start = changes[i].start;
-				if (model.getBaseModel) {
-					start = model.mapOffset(start, true);
-				}
-				if (start !== -1) {
-					lineIndex = Math.min(lineIndex, model.getLineAtOffset(start));
-				}
-			}
-		}
-		redraw(e.added);
-		redraw(e.removed);
-		redraw(e.changed);
-		var rulers = view.getRulers();
-		for (i = 0; i < rulers.length; i++) {
-			view.redrawLines(lineIndex, lineCount, rulers[i]);
-		}
-	};
-	
-	return {
-		Ruler: Ruler,
-		AnnotationRuler: AnnotationRuler,
-		LineNumberRuler: LineNumberRuler,
-		OverviewRuler: OverviewRuler,
-		FoldingRuler: FoldingRuler
-	};
-}, "orion/textview");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-/*global define */
-
-define([], function() {
-
-	/** 
-	 * Constructs a new Change object.
-	 * 
-	 * @class 
-	 * @name orion.textview.Change
-	 * @private
-	 */
-	function Change(offset, text, previousText) {
-		this.offset = offset;
-		this.text = text;
-		this.previousText = previousText;
-	}
-	Change.prototype = {
-		/** @ignore */
-		undo: function (view, select) {
-			this._doUndoRedo(this.offset, this.previousText, this.text, view, select);
-		},
-		/** @ignore */
-		redo: function (view, select) {
-			this._doUndoRedo(this.offset, this.text, this.previousText, view, select);
-		},
-		_doUndoRedo: function(offset, text, previousText, view, select) {
-			var model = view.getModel();
-			/* 
-			* TODO UndoStack should be changing the text in the base model.
-			* This is code needs to change when modifications in the base
-			* model are supported properly by the projection model.
-			*/
-			if (model.mapOffset && view.annotationModel) {
-				var mapOffset = model.mapOffset(offset, true);
-				if (mapOffset < 0) {
-					var annotationModel = view.annotationModel;
-					var iter = annotationModel.getAnnotations(offset, offset + 1);
-					while (iter.hasNext()) {
-						var annotation = iter.next();
-						if (annotation.type === "orion.annotation.folding") {
-							annotation.expand();
-							mapOffset = model.mapOffset(offset, true);
-							break;
-						}
-					}
-				}
-				if (mapOffset < 0) { return; }
-				offset = mapOffset;
-			}
-			view.setText(text, offset, offset + previousText.length);
-			if (select) {
-				view.setSelection(offset, offset + text.length);
-			}
-		}
-	};
-
-	/** 
-	 * Constructs a new CompoundChange object.
-	 * 
-	 * @class 
-	 * @name orion.textview.CompoundChange
-	 * @private
-	 */
-	function CompoundChange () {
-		this.changes = [];
-	}
-	CompoundChange.prototype = {
-		/** @ignore */
-		add: function (change) {
-			this.changes.push(change);
-		},
-		/** @ignore */
-		end: function (view) {
-			this.endSelection = view.getSelection();
-			this.endCaret = view.getCaretOffset();
-		},
-		/** @ignore */
-		undo: function (view, select) {
-			for (var i=this.changes.length - 1; i >= 0; i--) {
-				this.changes[i].undo(view, false);
-			}
-			if (select) {
-				var start = this.startSelection.start;
-				var end = this.startSelection.end;
-				view.setSelection(this.startCaret ? start : end, this.startCaret ? end : start);
-			}
-		},
-		/** @ignore */
-		redo: function (view, select) {
-			for (var i = 0; i < this.changes.length; i++) {
-				this.changes[i].redo(view, false);
-			}
-			if (select) {
-				var start = this.endSelection.start;
-				var end = this.endSelection.end;
-				view.setSelection(this.endCaret ? start : end, this.endCaret ? end : start);
-			}
-		},
-		/** @ignore */
-		start: function (view) {
-			this.startSelection = view.getSelection();
-			this.startCaret = view.getCaretOffset();
-		}
-	};
-
-	/**
-	 * Constructs a new UndoStack on a text view.
-	 *
-	 * @param {orion.textview.TextView} view the text view for the undo stack.
-	 * @param {Number} [size=100] the size for the undo stack.
-	 *
-	 * @name orion.textview.UndoStack
-	 * @class The UndoStack is used to record the history of a text model associated to an view. Every
-	 * change to the model is added to stack, allowing the application to undo and redo these changes.
-	 *
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * </p>
-	 */
-	function UndoStack (view, size) {
-		this.view = view;
-		this.size = size !== undefined ? size : 100;
-		this.reset();
-		var model = view.getModel();
-		if (model.getBaseModel) {
-			model = model.getBaseModel();
-		}
-		this.model = model;
-		var self = this;
-		this._listener = {
-			onChanging: function(e) {
-				self._onChanging(e);
-			},
-			onDestroy: function(e) {
-				self._onDestroy(e);
-			}
-		};
-		model.addEventListener("Changing", this._listener.onChanging);
-		view.addEventListener("Destroy", this._listener.onDestroy);
-	}
-	UndoStack.prototype = /** @lends orion.textview.UndoStack.prototype */ {
-		/**
-		 * Adds a change to the stack.
-		 * 
-		 * @param change the change to add.
-		 * @param {Number} change.offset the offset of the change
-		 * @param {String} change.text the new text of the change
-		 * @param {String} change.previousText the previous text of the change
-		 */
-		add: function (change) {
-			if (this.compoundChange) {
-				this.compoundChange.add(change);
-			} else {
-				var length = this.stack.length;
-				this.stack.splice(this.index, length-this.index, change);
-				this.index++;
-				if (this.stack.length > this.size) {
-					this.stack.shift();
-					this.index--;
-					this.cleanIndex--;
-				}
-			}
-		},
-		/** 
-		 * Marks the current state of the stack as clean.
-		 *
-		 * <p>
-		 * This function is typically called when the content of view associated with the stack is saved.
-		 * </p>
-		 *
-		 * @see #isClean
-		 */
-		markClean: function() {
-			this.endCompoundChange();
-			this._commitUndo();
-			this.cleanIndex = this.index;
-		},
-		/**
-		 * Returns true if current state of stack is the same
-		 * as the state when markClean() was called.
-		 *
-		 * <p>
-		 * For example, the application calls markClean(), then calls undo() four times and redo() four times.
-		 * At this point isClean() returns true.  
-		 * </p>
-		 * <p>
-		 * This function is typically called to determine if the content of the view associated with the stack
-		 * has changed since the last time it was saved.
-		 * </p>
-		 *
-		 * @return {Boolean} returns if the state is the same as the state when markClean() was called.
-		 *
-		 * @see #markClean
-		 */
-		isClean: function() {
-			return this.cleanIndex === this.getSize().undo;
-		},
-		/**
-		 * Returns true if there is at least one change to undo.
-		 *
-		 * @return {Boolean} returns true if there is at least one change to undo.
-		 *
-		 * @see #canRedo
-		 * @see #undo
-		 */
-		canUndo: function() {
-			return this.getSize().undo > 0;
-		},
-		/**
-		 * Returns true if there is at least one change to redo.
-		 *
-		 * @return {Boolean} returns true if there is at least one change to redo.
-		 *
-		 * @see #canUndo
-		 * @see #redo
-		 */
-		canRedo: function() {
-			return this.getSize().redo > 0;
-		},
-		/**
-		 * Finishes a compound change.
-		 *
-		 * @see #startCompoundChange
-		 */
-		endCompoundChange: function() {
-			if (this.compoundChange) {
-				this.compoundChange.end(this.view);
-			}
-			this.compoundChange = undefined;
-		},
-		/**
-		 * Returns the sizes of the stack.
-		 *
-		 * @return {object} a object where object.undo is the number of changes that can be un-done, 
-		 *  and object.redo is the number of changes that can be re-done.
-		 *
-		 * @see #canUndo
-		 * @see #canRedo
-		 */
-		getSize: function() {
-			var index = this.index;
-			var length = this.stack.length;
-			if (this._undoStart !== undefined) {
-				index++;
-			}
-			return {undo: index, redo: (length - index)};
-		},
-		/**
-		 * Undo the last change in the stack.
-		 *
-		 * @return {Boolean} returns true if a change was un-done.
-		 *
-		 * @see #redo
-		 * @see #canUndo
-		 */
-		undo: function() {
-			this._commitUndo();
-			if (this.index <= 0) {
-				return false;
-			}
-			var change = this.stack[--this.index];
-			this._ignoreUndo = true;
-			change.undo(this.view, true);
-			this._ignoreUndo = false;
-			return true;
-		},
-		/**
-		 * Redo the last change in the stack.
-		 *
-		 * @return {Boolean} returns true if a change was re-done.
-		 *
-		 * @see #undo
-		 * @see #canRedo
-		 */
-		redo: function() {
-			this._commitUndo();
-			if (this.index >= this.stack.length) {
-				return false;
-			}
-			var change = this.stack[this.index++];
-			this._ignoreUndo = true;
-			change.redo(this.view, true);
-			this._ignoreUndo = false;
-			return true;
-		},
-		/**
-		 * Reset the stack to its original state. All changes in the stack are thrown away.
-		 */
-		reset: function() {
-			this.index = this.cleanIndex = 0;
-			this.stack = [];
-			this._undoStart = undefined;
-			this._undoText = "";
-			this._ignoreUndo = false;
-			this._compoundChange = undefined;
-		},
-		/**
-		 * Starts a compound change. 
-		 * <p>
-		 * All changes added to stack from the time startCompoundChange() is called
-		 * to the time that endCompoundChange() is called are compound on one change that can be un-done or re-done
-		 * with one single call to undo() or redo().
-		 * </p>
-		 *
-		 * @see #endCompoundChange
-		 */
-		startCompoundChange: function() {
-			this._commitUndo();
-			var change = new CompoundChange();
-			this.add(change);
-			this.compoundChange = change;
-			this.compoundChange.start(this.view);
-		},
-		_commitUndo: function () {
-			if (this._undoStart !== undefined) {
-				if (this._undoStart < 0) {
-					this.add(new Change(-this._undoStart, "", this._undoText, ""));
-				} else {
-					this.add(new Change(this._undoStart, this._undoText, ""));
-				}
-				this._undoStart = undefined;
-				this._undoText = "";
-			}
-		},
-		_onDestroy: function(evt) {
-			this.model.removeEventListener("Changing", this._listener.onChanging);
-			this.view.removeEventListener("Destroy", this._listener.onDestroy);
-		},
-		_onChanging: function(e) {
-			var newText = e.text;
-			var start = e.start;
-			var removedCharCount = e.removedCharCount;
-			var addedCharCount = e.addedCharCount;
-			if (this._ignoreUndo) {
-				return;
-			}
-			if (this._undoStart !== undefined && 
-				!((addedCharCount === 1 && removedCharCount === 0 && start === this._undoStart + this._undoText.length) ||
-					(addedCharCount === 0 && removedCharCount === 1 && (((start + 1) === -this._undoStart) || (start === -this._undoStart)))))
-			{
-				this._commitUndo();
-			}
-			if (!this.compoundChange) {
-				if (addedCharCount === 1 && removedCharCount === 0) {
-					if (this._undoStart === undefined) {
-						this._undoStart = start;
-					}
-					this._undoText = this._undoText + newText;
-					return;
-				} else if (addedCharCount === 0 && removedCharCount === 1) {
-					var deleting = this._undoText.length > 0 && -this._undoStart === start;
-					this._undoStart = -start;
-					if (deleting) {
-						this._undoText = this._undoText + this.model.getText(start, start + removedCharCount);
-					} else {
-						this._undoText = this.model.getText(start, start + removedCharCount) + this._undoText;
-					}
-					return;
-				}
-			}
-			this.add(new Change(start, newText, this.model.getText(start, start + removedCharCount)));
-		}
-	};
-	
-	return {
-		UndoStack: UndoStack
-	};
-}, "orion/textview");
-/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: 
- *		Felipe Heidrich (IBM Corporation) - initial API and implementation
- *		Silenio Quarti (IBM Corporation) - initial API and implementation
- ******************************************************************************/
- 
-/*global define window*/
-
-define(['orion/textview/eventTarget'], function(mEventTarget) {
-	var isWindows = window.navigator.platform.indexOf("Win") !== -1;
-
-	/**
-	 * Constructs a new TextModel with the given text and default line delimiter.
-	 *
-	 * @param {String} [text=""] the text that the model will store
-	 * @param {String} [lineDelimiter=platform delimiter] the line delimiter used when inserting new lines to the model.
-	 *
-	 * @name orion.textview.TextModel
-	 * @class The TextModel is an interface that provides text for the view. Applications may
-	 * implement the TextModel interface to provide a custom store for the view content. The
-	 * view interacts with its text model in order to access and update the text that is being
-	 * displayed and edited in the view. This is the default implementation.
-	 * <p>
-	 * <b>See:</b><br/>
-	 * {@link orion.textview.TextView}<br/>
-	 * {@link orion.textview.TextView#setModel}
-	 * </p>
-	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
-	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
-	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
-	 */
-	function TextModel(text, lineDelimiter) {
-		this._lastLineIndex = -1;
-		this._text = [""];
-		this._lineOffsets = [0];
-		this.setText(text);
-		this.setLineDelimiter(lineDelimiter);
-	}
-
-	TextModel.prototype = /** @lends orion.textview.TextModel.prototype */ {
-		/**
-		 * Returns the number of characters in the model.
-		 *
-		 * @returns {Number} the number of characters in the model.
-		 */
-		getCharCount: function() {
-			var count = 0;
-			for (var i = 0; i<this._text.length; i++) {
-				count += this._text[i].length;
-			}
-			return count;
-		},
-		/**
-		 * Returns the text of the line at the given index.
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>null</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
-		 * @returns {String} the line text or <code>null</code> if out of range.
-		 *
-		 * @see #getLineAtOffset
-		 */
-		getLine: function(lineIndex, includeDelimiter) {
-			var lineCount = this.getLineCount();
-			if (!(0 <= lineIndex && lineIndex < lineCount)) {
-				return null;
-			}
-			var start = this._lineOffsets[lineIndex];
-			if (lineIndex + 1 < lineCount) {
-				var text = this.getText(start, this._lineOffsets[lineIndex + 1]);
-				if (includeDelimiter) {
-					return text;
-				}
-				var end = text.length, c;
-				while (((c = text.charCodeAt(end - 1)) === 10) || (c === 13)) {
-					end--;
-				}
-				return text.substring(0, end);
-			} else {
-				return this.getText(start); 
-			}
-		},
-		/**
-		 * Returns the line index at the given character offset.
-		 * <p>
-		 * The valid offsets are 0 to char count inclusive. The line index for
-		 * char count is <code>line count - 1</code>. Returns <code>-1</code> if
-		 * the offset is out of range.
-		 * </p>
-		 *
-		 * @param {Number} offset a character offset.
-		 * @returns {Number} the zero based line index or <code>-1</code> if out of range.
-		 */
-		getLineAtOffset: function(offset) {
-			var charCount = this.getCharCount();
-			if (!(0 <= offset && offset <= charCount)) {
-				return -1;
-			}
-			var lineCount = this.getLineCount();
-			if (offset === charCount) {
-				return lineCount - 1; 
-			}
-			var lineStart, lineEnd;
-			var index = this._lastLineIndex;
-			if (0 <= index && index < lineCount) {
-				lineStart = this._lineOffsets[index];
-				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
-				if (lineStart <= offset && offset < lineEnd) {
-					return index;
-				}
-			}
-			var high = lineCount;
-			var low = -1;
-			while (high - low > 1) {
-				index = Math.floor((high + low) / 2);
-				lineStart = this._lineOffsets[index];
-				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
-				if (offset <= lineStart) {
-					high = index;
-				} else if (offset < lineEnd) {
-					high = index;
-					break;
-				} else {
-					low = index;
-				}
-			}
-			this._lastLineIndex = high;
-			return high;
-		},
-		/**
-		 * Returns the number of lines in the model.
-		 * <p>
-		 * The model always has at least one line.
-		 * </p>
-		 *
-		 * @returns {Number} the number of lines.
-		 */
-		getLineCount: function() {
-			return this._lineOffsets.length;
-		},
-		/**
-		 * Returns the line delimiter that is used by the view
-		 * when inserting new lines. New lines entered using key strokes 
-		 * and paste operations use this line delimiter.
-		 *
-		 * @return {String} the line delimiter that is used by the view when inserting new lines.
-		 */
-		getLineDelimiter: function() {
-			return this._lineDelimiter;
-		},
-		/**
-		 * Returns the end character offset for the given line. 
-		 * <p>
-		 * The end offset is not inclusive. This means that when the line delimiter is included, the 
-		 * offset is either the start offset of the next line or char count. When the line delimiter is
-		 * not included, the offset is the offset of the line delimiter.
-		 * </p>
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
-		 * @return {Number} the line end offset or <code>-1</code> if out of range.
-		 *
-		 * @see #getLineStart
-		 */
-		getLineEnd: function(lineIndex, includeDelimiter) {
-			var lineCount = this.getLineCount();
-			if (!(0 <= lineIndex && lineIndex < lineCount)) {
-				return -1;
-			}
-			if (lineIndex + 1 < lineCount) {
-				var end = this._lineOffsets[lineIndex + 1];
-				if (includeDelimiter) {
-					return end;
-				}
-				var text = this.getText(Math.max(this._lineOffsets[lineIndex], end - 2), end);
-				var i = text.length, c;
-				while (((c = text.charCodeAt(i - 1)) === 10) || (c === 13)) {
-					i--;
-				}
-				return end - (text.length - i);
-			} else {
-				return this.getCharCount();
-			}
-		},
-		/**
-		 * Returns the start character offset for the given line.
-		 * <p>
-		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
-		 * if the index is out of range. 
-		 * </p>
-		 *
-		 * @param {Number} lineIndex the zero based index of the line.
-		 * @return {Number} the line start offset or <code>-1</code> if out of range.
-		 *
-		 * @see #getLineEnd
-		 */
-		getLineStart: function(lineIndex) {
-			if (!(0 <= lineIndex && lineIndex < this.getLineCount())) {
-				return -1;
-			}
-			return this._lineOffsets[lineIndex];
-		},
-		/**
-		 * Returns the text for the given range.
-		 * <p>
-		 * The end offset is not inclusive. This means that character at the end offset
-		 * is not included in the returned text.
-		 * </p>
-		 *
-		 * @param {Number} [start=0] the zero based start offset of text range.
-		 * @param {Number} [end=char count] the zero based end offset of text range.
-		 *
-		 * @see #setText
-		 */
-		getText: function(start, end) {
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = this.getCharCount(); }
-			if (start === end) { return ""; }
-			var offset = 0, chunk = 0, length;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (start <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var firstOffset = offset;
-			var firstChunk = chunk;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (end <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var lastOffset = offset;
-			var lastChunk = chunk;
-			if (firstChunk === lastChunk) {
-				return this._text[firstChunk].substring(start - firstOffset, end - lastOffset);
-			}
-			var beforeText = this._text[firstChunk].substring(start - firstOffset);
-			var afterText = this._text[lastChunk].substring(0, end - lastOffset);
-			return beforeText + this._text.slice(firstChunk+1, lastChunk).join("") + afterText; 
-		},
-		/**
-		 * Notifies all listeners that the text is about to change.
-		 * <p>
-		 * This notification is intended to be used only by the view. Application clients should
-		 * use {@link orion.textview.TextView#event:onModelChanging}.
-		 * </p>
-		 * <p>
-		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
-		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
-		 * purposes and to allow integration with other toolkit frameworks.
-		 * </p>
-		 *
-		 * @param {orion.textview.ModelChangingEvent} modelChangingEvent the changing event
-		 */
-		onChanging: function(modelChangingEvent) {
-			return this.dispatchEvent(modelChangingEvent);
-		},
-		/**
-		 * Notifies all listeners that the text has changed.
-		 * <p>
-		 * This notification is intended to be used only by the view. Application clients should
-		 * use {@link orion.textview.TextView#event:onModelChanged}.
-		 * </p>
-		 * <p>
-		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
-		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
-		 * purposes and to allow integration with other toolkit frameworks.
-		 * </p>
-		 *
-		 * @param {orion.textview.ModelChangedEvent} modelChangedEvent the changed event
-		 */
-		onChanged: function(modelChangedEvent) {
-			return this.dispatchEvent(modelChangedEvent);
-		},
-		/**
-		 * Sets the line delimiter that is used by the view
-		 * when new lines are inserted in the model due to key
-		 * strokes  and paste operations.
-		 * <p>
-		 * If lineDelimiter is "auto", the delimiter is computed to be
-		 * the first delimiter found the in the current text. If lineDelimiter
-		 * is undefined or if there are no delimiters in the current text, the
-		 * platform delimiter is used.
-		 * </p>
-		 *
-		 * @param {String} lineDelimiter the line delimiter that is used by the view when inserting new lines.
-		 */
-		setLineDelimiter: function(lineDelimiter) {
-			if (lineDelimiter === "auto") {
-				lineDelimiter = undefined;
-				if (this.getLineCount() > 1) {
-					lineDelimiter = this.getText(this.getLineEnd(0), this.getLineEnd(0, true));
-				}
-			}
-			this._lineDelimiter = lineDelimiter ? lineDelimiter : (isWindows ? "\r\n" : "\n"); 
-		},
-		/**
-		 * Replaces the text in the given range with the given text.
-		 * <p>
-		 * The end offset is not inclusive. This means that the character at the 
-		 * end offset is not replaced.
-		 * </p>
-		 * <p>
-		 * The text model must notify the listeners before and after the
-		 * the text is changed by calling {@link #onChanging} and {@link #onChanged}
-		 * respectively. 
-		 * </p>
-		 *
-		 * @param {String} [text=""] the new text.
-		 * @param {Number} [start=0] the zero based start offset of text range.
-		 * @param {Number} [end=char count] the zero based end offset of text range.
-		 *
-		 * @see #getText
-		 */
-		setText: function(text, start, end) {
-			if (text === undefined) { text = ""; }
-			if (start === undefined) { start = 0; }
-			if (end === undefined) { end = this.getCharCount(); }
-			var startLine = this.getLineAtOffset(start);
-			var endLine = this.getLineAtOffset(end);
-			var eventStart = start;
-			var removedCharCount = end - start;
-			var removedLineCount = endLine - startLine;
-			var addedCharCount = text.length;
-			var addedLineCount = 0;
-			var lineCount = this.getLineCount();
-			
-			var cr = 0, lf = 0, index = 0;
-			var newLineOffsets = [];
-			while (true) {
-				if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
-				if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
-				if (lf === -1 && cr === -1) { break; }
-				if (cr !== -1 && lf !== -1) {
-					if (cr + 1 === lf) {
-						index = lf + 1;
-					} else {
-						index = (cr < lf ? cr : lf) + 1;
-					}
-				} else if (cr !== -1) {
-					index = cr + 1;
-				} else {
-					index = lf + 1;
-				}
-				newLineOffsets.push(start + index);
-				addedLineCount++;
-			}
-		
-			var modelChangingEvent = {
-				type: "Changing",
-				text: text,
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanging(modelChangingEvent);
-			
-			//TODO this should be done the loops below to avoid getText()
-			if (newLineOffsets.length === 0) {
-				var startLineOffset = this.getLineStart(startLine), endLineOffset;
-				if (endLine + 1 < lineCount) {
-					endLineOffset = this.getLineStart(endLine + 1);
-				} else {
-					endLineOffset = this.getCharCount();
-				}
-				if (start !== startLineOffset) {
-					text = this.getText(startLineOffset, start) + text;
-					start = startLineOffset;
-				}
-				if (end !== endLineOffset) {
-					text = text + this.getText(end, endLineOffset);
-					end = endLineOffset;
-				}
-			}
-			
-			var changeCount = addedCharCount - removedCharCount;
-			for (var j = startLine + removedLineCount + 1; j < lineCount; j++) {
-				this._lineOffsets[j] += changeCount;
-			}
-			var args = [startLine + 1, removedLineCount].concat(newLineOffsets);
-			Array.prototype.splice.apply(this._lineOffsets, args);
-			
-			var offset = 0, chunk = 0, length;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (start <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var firstOffset = offset;
-			var firstChunk = chunk;
-			while (chunk<this._text.length) {
-				length = this._text[chunk].length; 
-				if (end <= offset + length) { break; }
-				offset += length;
-				chunk++;
-			}
-			var lastOffset = offset;
-			var lastChunk = chunk;
-			var firstText = this._text[firstChunk];
-			var lastText = this._text[lastChunk];
-			var beforeText = firstText.substring(0, start - firstOffset);
-			var afterText = lastText.substring(end - lastOffset);
-			var params = [firstChunk, lastChunk - firstChunk + 1];
-			if (beforeText) { params.push(beforeText); }
-			if (text) { params.push(text); }
-			if (afterText) { params.push(afterText); }
-			Array.prototype.splice.apply(this._text, params);
-			if (this._text.length === 0) { this._text = [""]; }
-			
-			var modelChangedEvent = {
-				type: "Changed",
-				start: eventStart,
-				removedCharCount: removedCharCount,
-				addedCharCount: addedCharCount,
-				removedLineCount: removedLineCount,
-				addedLineCount: addedLineCount
-			};
-			this.onChanged(modelChangedEvent);
-		}
-	};
-	mEventTarget.EventTarget.addMixin(TextModel.prototype);
-	
-	return {TextModel: TextModel};
-}, "orion/textview");/*******************************************************************************
- * @license
- * Copyright (c) 2010, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
  ******************************************************************************/
 
 /*global define */
 
-define(['orion/textview/eventTarget'], function(mEventTarget) {
+define("orion/textview/annotations", ['orion/textview/eventTarget'], function(mEventTarget) {
 	/**
 	 * @class This object represents a decoration attached to a range of text. Annotations are added to a
 	 * <code>AnnotationModel</code> which is attached to a <code>TextModel</code>.
 	 * <p>
 	 * <b>See:</b><br/>
 	 * {@link orion.textview.AnnotationModel}<br/>
 	 * {@link orion.textview.Ruler}<br/>
 	 * </p>		 
@@ -2001,16 +454,132 @@ define(['orion/textview/eventTarget'], f
 			if (this.expanded) { return; }
 			this.expanded = true;
 			this.html = this._expandedHTML;
 			this.style = this._expandedStyle;
 			this._projectionModel.removeProjection(this._projection);
 		}
 	};
 	
+	/** 
+	 * Constructs a new AnnotationTypeList object.
+	 * 
+	 * @class 
+	 * @name orion.textview.AnnotationTypeList
+	 */
+	function AnnotationTypeList () {
+	}
+	/**
+	 * Adds in the annotation type interface into the specified object.
+	 *
+	 * @param {Object} object The object to add in the annotation type interface.
+	 */
+	AnnotationTypeList.addMixin = function(object) {
+		var proto = AnnotationTypeList.prototype;
+		for (var p in proto) {
+			if (proto.hasOwnProperty(p)) {
+				object[p] = proto[p];
+			}
+		}
+	};	
+	AnnotationTypeList.prototype = /** @lends orion.textview.AnnotationTypeList.prototype */ {
+		/**
+		 * Adds an annotation type to the receiver.
+		 * <p>
+		 * Only annotations of the specified types will be shown by
+		 * the receiver.
+		 * </p>
+		 *
+		 * @param {Object} type the annotation type to be shown
+		 * 
+		 * @see #removeAnnotationType
+		 * @see #isAnnotationTypeVisible
+		 */
+		addAnnotationType: function(type) {
+			if (!this._annotationTypes) { this._annotationTypes = []; }
+			this._annotationTypes.push(type);
+		},
+		/**
+		 * Gets the annotation type priority.  The priority is determined by the
+		 * order the annotation type is added to the receiver.  Annotation types
+		 * added first have higher priority.
+		 * <p>
+		 * Returns <code>0</code> if the annotation type is not added.
+		 * </p>
+		 *
+		 * @param {Object} type the annotation type
+		 * 
+		 * @see #addAnnotationType
+		 * @see #removeAnnotationType
+		 * @see #isAnnotationTypeVisible
+		 */
+		getAnnotationTypePriority: function(type) {
+			if (this._annotationTypes) { 
+				for (var i = 0; i < this._annotationTypes.length; i++) {
+					if (this._annotationTypes[i] === type) {
+						return i + 1;
+					}
+				}
+			}
+			return 0;
+		},
+		/**
+		 * Returns an array of annotations in the specified annotation model for the given range of text sorted by type.
+		 *
+		 * @param {orion.textview.AnnotationModel} annotationModel the annotation model.
+		 * @param {Number} start the start offset of the range.
+		 * @param {Number} end the end offset of the range.
+		 * @return {orion.textview.Annotation[]} an annotation array.
+		 */
+		getAnnotationsByType: function(annotationModel, start, end) {
+			var iter = annotationModel.getAnnotations(start, end);
+			var annotation, annotations = [];
+			while (iter.hasNext()) {
+				annotation = iter.next();
+				var priority = this.getAnnotationTypePriority(annotation.type);
+				if (priority === 0) { continue; }
+				annotations.push(annotation);
+			}
+			var self = this;
+			annotations.sort(function(a, b) {
+				return self.getAnnotationTypePriority(a.type) - self.getAnnotationTypePriority(b.type);
+			});
+			return annotations;
+		},
+		/**
+		 * Returns whether the receiver shows annotations of the specified type.
+		 *
+		 * @param {Object} type the annotation type 
+		 * @returns {Boolean} whether the specified annotation type is shown
+		 * 
+		 * @see #addAnnotationType
+		 * @see #removeAnnotationType
+		 */
+		isAnnotationTypeVisible: function(type) {
+			return this.getAnnotationTypePriority(type) !== 0;
+		},
+		/**
+		 * Removes an annotation type from the receiver.
+		 *
+		 * @param {Object} type the annotation type to be removed
+		 * 
+		 * @see #addAnnotationType
+		 * @see #isAnnotationTypeVisible
+		 */
+		removeAnnotationType: function(type) {
+			if (!this._annotationTypes) { return; }
+			for (var i = 0; i < this._annotationTypes.length; i++) {
+				if (this._annotationTypes[i] === type) {
+					this._annotationTypes.splice(i, 1);
+					break;
+				}
+			}
+		}
+	};
+	
 	/**
 	 * Constructs an annotation model.
 	 * 
 	 * @param {textModel} textModel The text model.
 	 * 
 	 * @class This object manages annotations for a <code>TextModel</code>.
 	 * <p>
 	 * <b>See:</b><br/>
@@ -2317,21 +886,25 @@ define(['orion/textview/eventTarget'], f
 	/**
 	 * Constructs a new styler for annotations.
 	 * 
 	 * @param {orion.textview.TextView} view The styler view.
 	 * @param {orion.textview.AnnotationModel} view The styler annotation model.
 	 * 
 	 * @class This object represents a styler for annotation attached to a text view.
 	 * @name orion.textview.AnnotationStyler
+	 * @borrows orion.textview.AnnotationTypeList#addAnnotationType as #addAnnotationType
+	 * @borrows orion.textview.AnnotationTypeList#getAnnotationTypePriority as #getAnnotationTypePriority
+	 * @borrows orion.textview.AnnotationTypeList#getAnnotationsByType as #getAnnotationsByType
+	 * @borrows orion.textview.AnnotationTypeList#isAnnotationTypeVisible as #isAnnotationTypeVisible
+	 * @borrows orion.textview.AnnotationTypeList#removeAnnotationType as #removeAnnotationType
 	 */
 	function AnnotationStyler (view, annotationModel) {
 		this._view = view;
 		this._annotationModel = annotationModel;
-		this._types = [];
 		var self = this;
 		this._listener = {
 			onDestroy: function(e) {
 				self._onDestroy(e);
 			},
 			onLineStyle: function(e) {
 				self._onLineStyle(e);
 			},
@@ -2340,31 +913,16 @@ define(['orion/textview/eventTarget'], f
 			}
 		};
 		view.addEventListener("Destroy", this._listener.onDestroy);
 		view.addEventListener("LineStyle", this._listener.onLineStyle);
 		annotationModel.addEventListener("Changed", this._listener.onChanged);
 	}
 	AnnotationStyler.prototype = /** @lends orion.textview.AnnotationStyler.prototype */ {
 		/**
-		 * Adds an annotation type to the receiver.
-		 * <p>
-		 * Only annotations of the specified types will be shown by
-		 * this receiver.
-		 * </p>
-		 *
-		 * @param type {Object} the annotation type to be shown
-		 * 
-		 * @see #removeAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		addAnnotationType: function(type) {
-			this._types.push(type);
-		},
-		/**
 		 * Destroys the styler. 
 		 * <p>
 		 * Removes all listeners added by this styler.
 		 * </p>
 		 */
 		destroy: function() {
 			var view = this._view;
 			if (view) {
@@ -2373,49 +931,16 @@ define(['orion/textview/eventTarget'], f
 				this.view = null;
 			}
 			var annotationModel = this._annotationModel;
 			if (annotationModel) {
 				annotationModel.removeEventListener("Changed", this._listener.onChanged);
 				annotationModel = null;
 			}
 		},
-		/**
-		 * Returns whether the receiver shows annotations of the specified type.
-		 *
-		 * @param {Object} type the annotation type 
-		 * @returns {Boolean} whether the specified annotation type is shown
-		 * 
-		 * @see #addAnnotationType
-		 * @see #removeAnnotationType
-		 */
-		isAnnotationTypeVisible: function(type) {
-			for (var i = 0; i < this._types.length; i++) {
-				if (this._types[i] === type) {
-					return true;
-				}
-			}
-			return false;
-		},
-		/**
-		 * Removes an annotation type from the receiver.
-		 *
-		 * @param {Object} type the annotation type to be removed
-		 * 
-		 * @see #addAnnotationType
-		 * @see #isAnnotationTypeVisible
-		 */
-		removeAnnotationType: function(type) {
-			for (var i = 0; i < this._types.length; i++) {
-				if (this._types[i] === type) {
-					this._types.splice(i, 1);
-					break;
-				}
-			}
-		},
 		_mergeStyle: function(result, style) {
 			if (style) {
 				if (!result) { result = {}; }
 				if (result.styleClass && style.styleClass && result.styleClass !== style.styleClass) {
 					result.styleClass += " " + style.styleClass;
 				} else {
 					result.styleClass = style.styleClass;
 				}
@@ -2522,37 +1047,1540 @@ define(['orion/textview/eventTarget'], f
 				}
 				if (annotation.lineStyle) {
 					e.style = this._mergeStyle({}, e.style);
 					e.style = this._mergeStyle(e.style, annotation.lineStyle);
 				}
 			}
 		}
 	};
+	AnnotationTypeList.addMixin(AnnotationStyler.prototype);
 	
 	return {
 		FoldingAnnotation: FoldingAnnotation,
+		AnnotationTypeList: AnnotationTypeList,
 		AnnotationModel: AnnotationModel,
 		AnnotationStyler: AnnotationStyler
 	};
-}, "orion/textview");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
 
 /*global define setTimeout clearTimeout setInterval clearInterval Node */
 
-define(['orion/textview/textView', 'orion/textview/textModel', 'orion/textview/projectionTextModel'], function(mTextView, mTextModel, mProjectionTextModel) {
+define("orion/textview/rulers", ['orion/textview/annotations', 'orion/textview/tooltip'], function(mAnnotations, mTooltip) {
+
+	/**
+	 * Constructs a new ruler. 
+	 * <p>
+	 * The default implementation does not implement all the methods in the interface
+	 * and is useful only for objects implementing rulers.
+	 * <p/>
+	 * 
+	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
+	 * @param {String} [rulerLocation="left"] the location for the ruler.
+	 * @param {String} [rulerOverview="page"] the overview for the ruler.
+	 * @param {orion.textview.Style} [rulerStyle] the style for the ruler. 
+	 * 
+	 * @class This interface represents a ruler for the text view.
+	 * <p>
+	 * A Ruler is a graphical element that is placed either on the left or on the right side of 
+	 * the view. It can be used to provide the view with per line decoration such as line numbering,
+	 * bookmarks, breakpoints, folding disclosures, etc. 
+	 * </p><p>
+	 * There are two types of rulers: page and document. A page ruler only shows the content for the lines that are
+	 * visible, while a document ruler always shows the whole content.
+	 * </p>
+	 * <b>See:</b><br/>
+	 * {@link orion.textview.LineNumberRuler}<br/>
+	 * {@link orion.textview.AnnotationRuler}<br/>
+	 * {@link orion.textview.OverviewRuler}<br/> 
+	 * {@link orion.textview.TextView}<br/>
+	 * {@link orion.textview.TextView#addRuler}
+	 * </p>		 
+	 * @name orion.textview.Ruler
+	 * @borrows orion.textview.AnnotationTypeList#addAnnotationType as #addAnnotationType
+	 * @borrows orion.textview.AnnotationTypeList#getAnnotationTypePriority as #getAnnotationTypePriority
+	 * @borrows orion.textview.AnnotationTypeList#getAnnotationsByType as #getAnnotationsByType
+	 * @borrows orion.textview.AnnotationTypeList#isAnnotationTypeVisible as #isAnnotationTypeVisible
+	 * @borrows orion.textview.AnnotationTypeList#removeAnnotationType as #removeAnnotationType
+	 */
+	function Ruler (annotationModel, rulerLocation, rulerOverview, rulerStyle) {
+		this._location = rulerLocation || "left";
+		this._overview = rulerOverview || "page";
+		this._rulerStyle = rulerStyle;
+		this._view = null;
+		var self = this;
+		this._listener = {
+			onTextModelChanged: function(e) {
+				self._onTextModelChanged(e);
+			},
+			onAnnotationModelChanged: function(e) {
+				self._onAnnotationModelChanged(e);
+			}
+		};
+		this.setAnnotationModel(annotationModel);
+	}
+	Ruler.prototype = /** @lends orion.textview.Ruler.prototype */ {
+		/**
+		 * Returns the annotations for a given line range merging multiple
+		 * annotations when necessary.
+		 * <p>
+		 * This method is called by the text view when the ruler is redrawn.
+		 * </p>
+		 *
+		 * @param {Number} startLine the start line index
+		 * @param {Number} endLine the end line index
+		 * @return {orion.textview.Annotation[]} the annotations for the line range. The array might be sparse.
+		 */
+		getAnnotations: function(startLine, endLine) {
+			var annotationModel = this._annotationModel;
+			if (!annotationModel) { return []; }
+			var model = this._view.getModel();
+			var start = model.getLineStart(startLine);
+			var end = model.getLineEnd(endLine - 1);
+			var baseModel = model;
+			if (model.getBaseModel) {
+				baseModel = model.getBaseModel();
+				start = model.mapOffset(start);
+				end = model.mapOffset(end);
+			}
+			var result = [];
+			var annotations = this.getAnnotationsByType(annotationModel, start, end);
+			for (var i = 0; i < annotations.length; i++) {
+				var annotation = annotations[i];
+				var annotationLineStart = baseModel.getLineAtOffset(annotation.start);
+				var annotationLineEnd = baseModel.getLineAtOffset(Math.max(annotation.start, annotation.end - 1));
+				for (var lineIndex = annotationLineStart; lineIndex<=annotationLineEnd; lineIndex++) {
+					var visualLineIndex = lineIndex;
+					if (model !== baseModel) {
+						var ls = baseModel.getLineStart(lineIndex);
+						ls = model.mapOffset(ls, true);
+						if (ls === -1) { continue; }
+						visualLineIndex = model.getLineAtOffset(ls);
+					}
+					if (!(startLine <= visualLineIndex && visualLineIndex < endLine)) { continue; }
+					var rulerAnnotation = this._mergeAnnotation(result[visualLineIndex], annotation, lineIndex - annotationLineStart, annotationLineEnd - annotationLineStart + 1);
+					if (rulerAnnotation) {
+						result[visualLineIndex] = rulerAnnotation;
+					}
+				}
+			}
+			if (!this._multiAnnotation && this._multiAnnotationOverlay) {
+				for (var k in result) {
+					if (result[k]._multiple) {
+						result[k].html = result[k].html + this._multiAnnotationOverlay.html;
+					}
+				}
+			}
+			return result;
+		},
+		/**
+		 * Returns the annotation model.
+		 *
+		 * @returns {orion.textview.AnnotationModel} the ruler annotation model.
+		 *
+		 * @see #setAnnotationModel
+		 */
+		getAnnotationModel: function() {
+			return this._annotationModel;
+		},
+		/**
+		 * Returns the ruler location.
+		 *
+		 * @returns {String} the ruler location, which is either "left" or "right".
+		 *
+		 * @see #getOverview
+		 */
+		getLocation: function() {
+			return this._location;
+		},
+		/**
+		 * Returns the ruler overview type.
+		 *
+		 * @returns {String} the overview type, which is either "page" or "document".
+		 *
+		 * @see #getLocation
+		 */
+		getOverview: function() {
+			return this._overview;
+		},
+		/**
+		 * Returns the style information for the ruler.
+		 *
+		 * @returns {orion.textview.Style} the style information.
+		 */
+		getRulerStyle: function() {
+			return this._rulerStyle;
+		},
+		/**
+		 * Returns the widest annotation which determines the width of the ruler.
+		 * <p>
+		 * If the ruler does not have a fixed width it should provide the widest
+		 * annotation to avoid the ruler from changing size as the view scrolls.
+		 * </p>
+		 * <p>
+		 * This method is called by the text view when the ruler is redrawn.
+		 * </p>
+		 *
+		 * @returns {orion.textview.Annotation} the widest annotation.
+		 *
+		 * @see #getAnnotations
+		 */
+		getWidestAnnotation: function() {
+			return null;
+		},
+		/**
+		 * Sets the annotation model for the ruler.
+		 *
+		 * @param {orion.textview.AnnotationModel} annotationModel the annotation model.
+		 *
+		 * @see #getAnnotationModel
+		 */
+		setAnnotationModel: function (annotationModel) {
+			if (this._annotationModel) {
+				this._annotationModel.removEventListener("Changed", this._listener.onAnnotationModelChanged); 
+			}
+			this._annotationModel = annotationModel;
+			if (this._annotationModel) {
+				this._annotationModel.addEventListener("Changed", this._listener.onAnnotationModelChanged); 
+			}
+		},
+		/**
+		 * Sets the annotation that is displayed when a given line contains multiple
+		 * annotations.  This annotation is used when there are different types of
+		 * annotations in a given line.
+		 *
+		 * @param {orion.textview.Annotation} annotation the annotation for lines with multiple annotations.
+		 * 
+		 * @see #setMultiAnnotationOverlay
+		 */
+		setMultiAnnotation: function(annotation) {
+			this._multiAnnotation = annotation;
+		},
+		/**
+		 * Sets the annotation that overlays a line with multiple annotations.  This annotation is displayed on
+		 * top of the computed annotation for a given line when there are multiple annotations of the same type
+		 * in the line. It is also used when the multiple annotation is not set.
+		 *
+		 * @param {orion.textview.Annotation} annotation the annotation overlay for lines with multiple annotations.
+		 * 
+		 * @see #setMultiAnnotation
+		 */
+		setMultiAnnotationOverlay: function(annotation) {
+			this._multiAnnotationOverlay = annotation;
+		},
+		/**
+		 * Sets the view for the ruler.
+		 * <p>
+		 * This method is called by the text view when the ruler
+		 * is added to the view.
+		 * </p>
+		 *
+		 * @param {orion.textview.TextView} view the text view.
+		 */
+		setView: function (view) {
+			if (this._onTextModelChanged && this._view) {
+				this._view.removeEventListener("ModelChanged", this._listener.onTextModelChanged); 
+			}
+			this._view = view;
+			if (this._onTextModelChanged && this._view) {
+				this._view.addEventListener("ModelChanged", this._listener.onTextModelChanged);
+			}
+		},
+		/**
+		 * This event is sent when the user clicks a line annotation.
+		 *
+		 * @event
+		 * @param {Number} lineIndex the line index of the annotation under the pointer.
+		 * @param {DOMEvent} e the click event.
+		 */
+		onClick: function(lineIndex, e) {
+		},
+		/**
+		 * This event is sent when the user double clicks a line annotation.
+		 *
+		 * @event
+		 * @param {Number} lineIndex the line index of the annotation under the pointer.
+		 * @param {DOMEvent} e the double click event.
+		 */
+		onDblClick: function(lineIndex, e) {
+		},
+		/**
+		 * This event is sent when the user moves the mouse over a line annotation.
+		 *
+		 * @event
+		 * @param {Number} lineIndex the line index of the annotation under the pointer.
+		 * @param {DOMEvent} e the mouse move event.
+		 */
+		onMouseMove: function(lineIndex, e) {
+			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
+			if (!tooltip) { return; }
+			if (tooltip.isVisible() && this._tooltipLineIndex === lineIndex) { return; }
+			this._tooltipLineIndex = lineIndex;
+			var self = this;
+			tooltip.setTarget({
+				y: e.clientY,
+				getTooltipInfo: function() {
+					return self._getTooltipInfo(self._tooltipLineIndex, this.y);
+				}
+			});
+		},
+		/**
+		 * This event is sent when the mouse pointer enters a line annotation.
+		 *
+		 * @event
+		 * @param {Number} lineIndex the line index of the annotation under the pointer.
+		 * @param {DOMEvent} e the mouse over event.
+		 */
+		onMouseOver: function(lineIndex, e) {
+			this.onMouseMove(lineIndex, e);
+		},
+		/**
+		 * This event is sent when the mouse pointer exits a line annotation.
+		 *
+		 * @event
+		 * @param {Number} lineIndex the line index of the annotation under the pointer.
+		 * @param {DOMEvent} e the mouse out event.
+		 */
+		onMouseOut: function(lineIndex, e) {
+			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
+			if (!tooltip) { return; }
+			tooltip.setTarget(null);
+		},
+		/** @ignore */
+		_getTooltipInfo: function(lineIndex, y) {
+			if (lineIndex === undefined) { return; }
+			var view = this._view;
+			var model = view.getModel();
+			var annotationModel = this._annotationModel;
+			var annotations = [];
+			if (annotationModel) {
+				var start = model.getLineStart(lineIndex);
+				var end = model.getLineEnd(lineIndex);
+				if (model.getBaseModel) {
+					start = model.mapOffset(start);
+					end = model.mapOffset(end);
+				}
+				annotations = this.getAnnotationsByType(annotationModel, start, end);
+			}
+			var contents = this._getTooltipContents(lineIndex, annotations);
+			if (!contents) { return null; }
+			var info = {
+				contents: contents,
+				anchor: this.getLocation()
+			};
+			var rect = view.getClientArea();
+			if (this.getOverview() === "document") {
+				rect.y = view.convert({y: y}, "view", "document").y;
+			} else {
+				rect.y = view.getLocationAtOffset(model.getLineStart(lineIndex)).y;
+			}
+			view.convert(rect, "document", "page");
+			info.x = rect.x;
+			info.y = rect.y;
+			if (info.anchor === "right") {
+				info.x += rect.width;
+			}
+			info.maxWidth = rect.width;
+			info.maxHeight = rect.height - (rect.y - view._parent.getBoundingClientRect().top);
+			return info;
+		},
+		/** @ignore */
+		_getTooltipContents: function(lineIndex, annotations) {
+			return annotations;
+		},
+		/** @ignore */
+		_onAnnotationModelChanged: function(e) {
+			var view = this._view;
+			if (!view) { return; }
+			var model = view.getModel(), self = this;
+			var lineCount = model.getLineCount();
+			if (e.textModelChangedEvent) {
+				var start = e.textModelChangedEvent.start;
+				if (model.getBaseModel) { start = model.mapOffset(start, true); }
+				var startLine = model.getLineAtOffset(start);
+				view.redrawLines(startLine, lineCount, self);
+				return;
+			}
+			function redraw(changes) {
+				for (var i = 0; i < changes.length; i++) {
+					if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
+					var start = changes[i].start;
+					var end = changes[i].end;
+					if (model.getBaseModel) {
+						start = model.mapOffset(start, true);
+						end = model.mapOffset(end, true);
+					}
+					if (start !== -1 && end !== -1) {
+						view.redrawLines(model.getLineAtOffset(start), model.getLineAtOffset(Math.max(start, end - 1)) + 1, self);
+					}
+				}
+			}
+			redraw(e.added);
+			redraw(e.removed);
+			redraw(e.changed);
+		},
+		/** @ignore */
+		_mergeAnnotation: function(result, annotation, annotationLineIndex, annotationLineCount) {
+			if (!result) { result = {}; }
+			if (annotationLineIndex === 0) {
+				if (result.html && annotation.html) {
+					if (annotation.html !== result.html) {
+						if (!result._multiple && this._multiAnnotation) {
+							result.html = this._multiAnnotation.html;
+						}
+					} 
+					result._multiple = true;
+				} else {
+					result.html = annotation.html;
+				}
+			}
+			result.style = this._mergeStyle(result.style, annotation.style);
+			return result;
+		},
+		/** @ignore */
+		_mergeStyle: function(result, style) {
+			if (style) {
+				if (!result) { result = {}; }
+				if (result.styleClass && style.styleClass && result.styleClass !== style.styleClass) {
+					result.styleClass += " " + style.styleClass;
+				} else {
+					result.styleClass = style.styleClass;
+				}
+				var prop;
+				if (style.style) {
+					if (!result.style) { result.style  = {}; }
+					for (prop in style.style) {
+						if (!result.style[prop]) {
+							result.style[prop] = style.style[prop];
+						}
+					}
+				}
+				if (style.attributes) {
+					if (!result.attributes) { result.attributes  = {}; }
+					for (prop in style.attributes) {
+						if (!result.attributes[prop]) {
+							result.attributes[prop] = style.attributes[prop];
+						}
+					}
+				}
+			}
+			return result;
+		}
+	};
+	mAnnotations.AnnotationTypeList.addMixin(Ruler.prototype);
+
+	/**
+	 * Constructs a new line numbering ruler. 
+	 *
+	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
+	 * @param {String} [rulerLocation="left"] the location for the ruler.
+	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
+	 * @param {orion.textview.Style} [oddStyle={style: {backgroundColor: "white"}] the style for lines with odd line index.
+	 * @param {orion.textview.Style} [evenStyle={backgroundColor: "white"}] the style for lines with even line index.
+	 *
+	 * @augments orion.textview.Ruler
+	 * @class This objects implements a line numbering ruler.
+	 *
+	 * <p><b>See:</b><br/>
+	 * {@link orion.textview.Ruler}
+	 * </p>
+	 * @name orion.textview.LineNumberRuler
+	 */
+	function LineNumberRuler (annotationModel, rulerLocation, rulerStyle, oddStyle, evenStyle) {
+		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
+		this._oddStyle = oddStyle || {style: {backgroundColor: "white"}};
+		this._evenStyle = evenStyle || {style: {backgroundColor: "white"}};
+		this._numOfDigits = 0;
+	}
+	LineNumberRuler.prototype = new Ruler(); 
+	/** @ignore */
+	LineNumberRuler.prototype.getAnnotations = function(startLine, endLine) {
+		var result = Ruler.prototype.getAnnotations.call(this, startLine, endLine);
+		var model = this._view.getModel();
+		for (var lineIndex = startLine; lineIndex < endLine; lineIndex++) {
+			var style = lineIndex & 1 ? this._oddStyle : this._evenStyle;
+			var mapLine = lineIndex;
+			if (model.getBaseModel) {
+				var lineStart = model.getLineStart(mapLine);
+				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
+			}
+			if (!result[lineIndex]) { result[lineIndex] = {}; }
+			result[lineIndex].html = (mapLine + 1) + "";
+			if (!result[lineIndex].style) { result[lineIndex].style = style; }
+		}
+		return result;
+	};
+	/** @ignore */
+	LineNumberRuler.prototype.getWidestAnnotation = function() {
+		var lineCount = this._view.getModel().getLineCount();
+		return this.getAnnotations(lineCount - 1, lineCount)[lineCount - 1];
+	};
+	/** @ignore */
+	LineNumberRuler.prototype._onTextModelChanged = function(e) {
+		var start = e.start;
+		var model = this._view.getModel();
+		var lineCount = model.getBaseModel ? model.getBaseModel().getLineCount() : model.getLineCount();
+		var numOfDigits = (lineCount+"").length;
+		if (this._numOfDigits !== numOfDigits) {
+			this._numOfDigits = numOfDigits;
+			var startLine = model.getLineAtOffset(start);
+			this._view.redrawLines(startLine,  model.getLineCount(), this);
+		}
+	};
+	
+	/** 
+	 * @class This is class represents an annotation for the AnnotationRuler. 
+	 * <p> 
+	 * <b>See:</b><br/> 
+	 * {@link orion.textview.AnnotationRuler}
+	 * </p> 
+	 * 
+	 * @name orion.textview.Annotation 
+	 * 
+	 * @property {String} [html=""] The html content for the annotation, typically contains an image.
+	 * @property {orion.textview.Style} [style] the style for the annotation.
+	 * @property {orion.textview.Style} [overviewStyle] the style for the annotation in the overview ruler.
+	 */ 
+	/**
+	 * Constructs a new annotation ruler. 
+	 *
+	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
+	 * @param {String} [rulerLocation="left"] the location for the ruler.
+	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
+	 * @param {orion.textview.Annotation} [defaultAnnotation] the default annotation.
+	 *
+	 * @augments orion.textview.Ruler
+	 * @class This objects implements an annotation ruler.
+	 *
+	 * <p><b>See:</b><br/>
+	 * {@link orion.textview.Ruler}<br/>
+	 * {@link orion.textview.Annotation}
+	 * </p>
+	 * @name orion.textview.AnnotationRuler
+	 */
+	function AnnotationRuler (annotationModel, rulerLocation, rulerStyle) {
+		Ruler.call(this, annotationModel, rulerLocation, "page", rulerStyle);
+	}
+	AnnotationRuler.prototype = new Ruler();
+	
+	/**
+	 * Constructs a new overview ruler. 
+	 * <p>
+	 * The overview ruler is used in conjunction with a AnnotationRuler, for each annotation in the 
+	 * AnnotationRuler this ruler displays a mark in the overview. Clicking on the mark causes the 
+	 * view to scroll to the annotated line.
+	 * </p>
+	 *
+	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
+	 * @param {String} [rulerLocation="left"] the location for the ruler.
+	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
+	 *
+	 * @augments orion.textview.Ruler
+	 * @class This objects implements an overview ruler.
+	 *
+	 * <p><b>See:</b><br/>
+	 * {@link orion.textview.AnnotationRuler} <br/>
+	 * {@link orion.textview.Ruler} 
+	 * </p>
+	 * @name orion.textview.OverviewRuler
+	 */
+	function OverviewRuler (annotationModel, rulerLocation, rulerStyle) {
+		Ruler.call(this, annotationModel, rulerLocation, "document", rulerStyle);
+	}
+	OverviewRuler.prototype = new Ruler();
+	
+	/** @ignore */
+	OverviewRuler.prototype.getRulerStyle = function() {
+		var result = {style: {lineHeight: "1px", fontSize: "1px"}};
+		result = this._mergeStyle(result, this._rulerStyle);
+		return result;
+	};
+	/** @ignore */	
+	OverviewRuler.prototype.onClick = function(lineIndex, e) {
+		if (lineIndex === undefined) { return; }
+		this._view.setTopIndex(lineIndex);
+	};
+	/** @ignore */
+	OverviewRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
+		if (annotations.length === 0) {
+			var model = this._view.getModel();
+			var mapLine = lineIndex;
+			if (model.getBaseModel) {
+				var lineStart = model.getLineStart(mapLine);
+				mapLine = model.getBaseModel().getLineAtOffset(model.mapOffset(lineStart));
+			}
+			return "Line: " + (mapLine + 1);
+		}
+		return Ruler.prototype._getTooltipContents.call(this, lineIndex, annotations);
+	};
+	/** @ignore */
+	OverviewRuler.prototype._mergeAnnotation = function(previousAnnotation, annotation, annotationLineIndex, annotationLineCount) {
+		if (annotationLineIndex !== 0) { return undefined; }
+		var result = previousAnnotation;
+		if (!result) {
+			//TODO annotationLineCount does not work when there are folded lines
+			var height = 3 * annotationLineCount;
+			result = {html: "&nbsp;", style: { style: {height: height + "px"}}};
+			result.style = this._mergeStyle(result.style, annotation.overviewStyle);
+		}
+		return result;
+	};
+
+	/**
+	 * Constructs a new folding ruler. 
+	 *
+	 * @param {orion.textview.AnnotationModel} annotationModel the annotation model for the ruler.
+	 * @param {String} [rulerLocation="left"] the location for the ruler.
+	 * @param {orion.textview.Style} [rulerStyle=undefined] the style for the ruler.
+	 *
+	 * @augments orion.textview.Ruler
+	 * @class This objects implements an overview ruler.
+	 *
+	 * <p><b>See:</b><br/>
+	 * {@link orion.textview.AnnotationRuler} <br/>
+	 * {@link orion.textview.Ruler} 
+	 * </p>
+	 * @name orion.textview.OverviewRuler
+	 */
+	function FoldingRuler (annotationModel, rulerLocation, rulerStyle) {
+		AnnotationRuler.call(this, annotationModel, rulerLocation, rulerStyle);
+	}
+	FoldingRuler.prototype = new AnnotationRuler();
+	
+	/** @ignore */
+	FoldingRuler.prototype.onClick =  function(lineIndex, e) {
+		if (lineIndex === undefined) { return; }
+		var annotationModel = this._annotationModel;
+		if (!annotationModel) { return; }
+		var view = this._view;
+		var model = view.getModel();
+		var start = model.getLineStart(lineIndex);
+		var end = model.getLineEnd(lineIndex, true);
+		if (model.getBaseModel) {
+			start = model.mapOffset(start);
+			end = model.mapOffset(end);
+		}
+		var annotation, iter = annotationModel.getAnnotations(start, end);
+		while (!annotation && iter.hasNext()) {
+			var a = iter.next();
+			if (!this.isAnnotationTypeVisible(a.type)) { continue; }
+			annotation = a;
+		}
+		if (annotation) {
+			var tooltip = mTooltip.Tooltip.getTooltip(this._view);
+			if (tooltip) {
+				tooltip.setTarget(null);
+			}
+			if (annotation.expanded) {
+				annotation.collapse();
+			} else {
+				annotation.expand();
+			}
+			this._annotationModel.modifyAnnotation(annotation);
+		}
+	};
+	/** @ignore */
+	FoldingRuler.prototype._getTooltipContents = function(lineIndex, annotations) {
+		if (annotations.length === 1) {
+			if (annotations[0].expanded) {
+				return null;
+			}
+		}
+		return AnnotationRuler.prototype._getTooltipContents.call(this, lineIndex, annotations);
+	};
+	/** @ignore */
+	FoldingRuler.prototype._onAnnotationModelChanged = function(e) {
+		if (e.textModelChangedEvent) {
+			AnnotationRuler.prototype._onAnnotationModelChanged.call(this, e);
+			return;
+		}
+		var view = this._view;
+		if (!view) { return; }
+		var model = view.getModel(), self = this, i;
+		var lineCount = model.getLineCount(), lineIndex = lineCount;
+		function redraw(changes) {
+			for (i = 0; i < changes.length; i++) {
+				if (!self.isAnnotationTypeVisible(changes[i].type)) { continue; }
+				var start = changes[i].start;
+				if (model.getBaseModel) {
+					start = model.mapOffset(start, true);
+				}
+				if (start !== -1) {
+					lineIndex = Math.min(lineIndex, model.getLineAtOffset(start));
+				}
+			}
+		}
+		redraw(e.added);
+		redraw(e.removed);
+		redraw(e.changed);
+		var rulers = view.getRulers();
+		for (i = 0; i < rulers.length; i++) {
+			view.redrawLines(lineIndex, lineCount, rulers[i]);
+		}
+	};
+	
+	return {
+		Ruler: Ruler,
+		AnnotationRuler: AnnotationRuler,
+		LineNumberRuler: LineNumberRuler,
+		OverviewRuler: OverviewRuler,
+		FoldingRuler: FoldingRuler
+	};
+});
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+/*global define */
+
+define("orion/textview/undoStack", [], function() {
+
+	/** 
+	 * Constructs a new Change object.
+	 * 
+	 * @class 
+	 * @name orion.textview.Change
+	 * @private
+	 */
+	function Change(offset, text, previousText) {
+		this.offset = offset;
+		this.text = text;
+		this.previousText = previousText;
+	}
+	Change.prototype = {
+		/** @ignore */
+		undo: function (view, select) {
+			this._doUndoRedo(this.offset, this.previousText, this.text, view, select);
+		},
+		/** @ignore */
+		redo: function (view, select) {
+			this._doUndoRedo(this.offset, this.text, this.previousText, view, select);
+		},
+		_doUndoRedo: function(offset, text, previousText, view, select) {
+			var model = view.getModel();
+			/* 
+			* TODO UndoStack should be changing the text in the base model.
+			* This is code needs to change when modifications in the base
+			* model are supported properly by the projection model.
+			*/
+			if (model.mapOffset && view.annotationModel) {
+				var mapOffset = model.mapOffset(offset, true);
+				if (mapOffset < 0) {
+					var annotationModel = view.annotationModel;
+					var iter = annotationModel.getAnnotations(offset, offset + 1);
+					while (iter.hasNext()) {
+						var annotation = iter.next();
+						if (annotation.type === "orion.annotation.folding") {
+							annotation.expand();
+							mapOffset = model.mapOffset(offset, true);
+							break;
+						}
+					}
+				}
+				if (mapOffset < 0) { return; }
+				offset = mapOffset;
+			}
+			view.setText(text, offset, offset + previousText.length);
+			if (select) {
+				view.setSelection(offset, offset + text.length);
+			}
+		}
+	};
+
+	/** 
+	 * Constructs a new CompoundChange object.
+	 * 
+	 * @class 
+	 * @name orion.textview.CompoundChange
+	 * @private
+	 */
+	function CompoundChange () {
+		this.changes = [];
+	}
+	CompoundChange.prototype = {
+		/** @ignore */
+		add: function (change) {
+			this.changes.push(change);
+		},
+		/** @ignore */
+		end: function (view) {
+			this.endSelection = view.getSelection();
+			this.endCaret = view.getCaretOffset();
+		},
+		/** @ignore */
+		undo: function (view, select) {
+			for (var i=this.changes.length - 1; i >= 0; i--) {
+				this.changes[i].undo(view, false);
+			}
+			if (select) {
+				var start = this.startSelection.start;
+				var end = this.startSelection.end;
+				view.setSelection(this.startCaret ? start : end, this.startCaret ? end : start);
+			}
+		},
+		/** @ignore */
+		redo: function (view, select) {
+			for (var i = 0; i < this.changes.length; i++) {
+				this.changes[i].redo(view, false);
+			}
+			if (select) {
+				var start = this.endSelection.start;
+				var end = this.endSelection.end;
+				view.setSelection(this.endCaret ? start : end, this.endCaret ? end : start);
+			}
+		},
+		/** @ignore */
+		start: function (view) {
+			this.startSelection = view.getSelection();
+			this.startCaret = view.getCaretOffset();
+		}
+	};
+
+	/**
+	 * Constructs a new UndoStack on a text view.
+	 *
+	 * @param {orion.textview.TextView} view the text view for the undo stack.
+	 * @param {Number} [size=100] the size for the undo stack.
+	 *
+	 * @name orion.textview.UndoStack
+	 * @class The UndoStack is used to record the history of a text model associated to an view. Every
+	 * change to the model is added to stack, allowing the application to undo and redo these changes.
+	 *
+	 * <p>
+	 * <b>See:</b><br/>
+	 * {@link orion.textview.TextView}<br/>
+	 * </p>
+	 */
+	function UndoStack (view, size) {
+		this.view = view;
+		this.size = size !== undefined ? size : 100;
+		this.reset();
+		var model = view.getModel();
+		if (model.getBaseModel) {
+			model = model.getBaseModel();
+		}
+		this.model = model;
+		var self = this;
+		this._listener = {
+			onChanging: function(e) {
+				self._onChanging(e);
+			},
+			onDestroy: function(e) {
+				self._onDestroy(e);
+			}
+		};
+		model.addEventListener("Changing", this._listener.onChanging);
+		view.addEventListener("Destroy", this._listener.onDestroy);
+	}
+	UndoStack.prototype = /** @lends orion.textview.UndoStack.prototype */ {
+		/**
+		 * Adds a change to the stack.
+		 * 
+		 * @param change the change to add.
+		 * @param {Number} change.offset the offset of the change
+		 * @param {String} change.text the new text of the change
+		 * @param {String} change.previousText the previous text of the change
+		 */
+		add: function (change) {
+			if (this.compoundChange) {
+				this.compoundChange.add(change);
+			} else {
+				var length = this.stack.length;
+				this.stack.splice(this.index, length-this.index, change);
+				this.index++;
+				if (this.stack.length > this.size) {
+					this.stack.shift();
+					this.index--;
+					this.cleanIndex--;
+				}
+			}
+		},
+		/** 
+		 * Marks the current state of the stack as clean.
+		 *
+		 * <p>
+		 * This function is typically called when the content of view associated with the stack is saved.
+		 * </p>
+		 *
+		 * @see #isClean
+		 */
+		markClean: function() {
+			this.endCompoundChange();
+			this._commitUndo();
+			this.cleanIndex = this.index;
+		},
+		/**
+		 * Returns true if current state of stack is the same
+		 * as the state when markClean() was called.
+		 *
+		 * <p>
+		 * For example, the application calls markClean(), then calls undo() four times and redo() four times.
+		 * At this point isClean() returns true.  
+		 * </p>
+		 * <p>
+		 * This function is typically called to determine if the content of the view associated with the stack
+		 * has changed since the last time it was saved.
+		 * </p>
+		 *
+		 * @return {Boolean} returns if the state is the same as the state when markClean() was called.
+		 *
+		 * @see #markClean
+		 */
+		isClean: function() {
+			return this.cleanIndex === this.getSize().undo;
+		},
+		/**
+		 * Returns true if there is at least one change to undo.
+		 *
+		 * @return {Boolean} returns true if there is at least one change to undo.
+		 *
+		 * @see #canRedo
+		 * @see #undo
+		 */
+		canUndo: function() {
+			return this.getSize().undo > 0;
+		},
+		/**
+		 * Returns true if there is at least one change to redo.
+		 *
+		 * @return {Boolean} returns true if there is at least one change to redo.
+		 *
+		 * @see #canUndo
+		 * @see #redo
+		 */
+		canRedo: function() {
+			return this.getSize().redo > 0;
+		},
+		/**
+		 * Finishes a compound change.
+		 *
+		 * @see #startCompoundChange
+		 */
+		endCompoundChange: function() {
+			if (this.compoundChange) {
+				this.compoundChange.end(this.view);
+			}
+			this.compoundChange = undefined;
+		},
+		/**
+		 * Returns the sizes of the stack.
+		 *
+		 * @return {object} a object where object.undo is the number of changes that can be un-done, 
+		 *  and object.redo is the number of changes that can be re-done.
+		 *
+		 * @see #canUndo
+		 * @see #canRedo
+		 */
+		getSize: function() {
+			var index = this.index;
+			var length = this.stack.length;
+			if (this._undoStart !== undefined) {
+				index++;
+			}
+			return {undo: index, redo: (length - index)};
+		},
+		/**
+		 * Undo the last change in the stack.
+		 *
+		 * @return {Boolean} returns true if a change was un-done.
+		 *
+		 * @see #redo
+		 * @see #canUndo
+		 */
+		undo: function() {
+			this._commitUndo();
+			if (this.index <= 0) {
+				return false;
+			}
+			var change = this.stack[--this.index];
+			this._ignoreUndo = true;
+			change.undo(this.view, true);
+			this._ignoreUndo = false;
+			return true;
+		},
+		/**
+		 * Redo the last change in the stack.
+		 *
+		 * @return {Boolean} returns true if a change was re-done.
+		 *
+		 * @see #undo
+		 * @see #canRedo
+		 */
+		redo: function() {
+			this._commitUndo();
+			if (this.index >= this.stack.length) {
+				return false;
+			}
+			var change = this.stack[this.index++];
+			this._ignoreUndo = true;
+			change.redo(this.view, true);
+			this._ignoreUndo = false;
+			return true;
+		},
+		/**
+		 * Reset the stack to its original state. All changes in the stack are thrown away.
+		 */
+		reset: function() {
+			this.index = this.cleanIndex = 0;
+			this.stack = [];
+			this._undoStart = undefined;
+			this._undoText = "";
+			this._undoType = 0;
+			this._ignoreUndo = false;
+			this._compoundChange = undefined;
+		},
+		/**
+		 * Starts a compound change. 
+		 * <p>
+		 * All changes added to stack from the time startCompoundChange() is called
+		 * to the time that endCompoundChange() is called are compound on one change that can be un-done or re-done
+		 * with one single call to undo() or redo().
+		 * </p>
+		 *
+		 * @see #endCompoundChange
+		 */
+		startCompoundChange: function() {
+			this._commitUndo();
+			var change = new CompoundChange();
+			this.add(change);
+			this.compoundChange = change;
+			this.compoundChange.start(this.view);
+		},
+		_commitUndo: function () {
+			if (this._undoStart !== undefined) {
+				if (this._undoType === -1) {
+					this.add(new Change(this._undoStart, "", this._undoText, ""));
+				} else {
+					this.add(new Change(this._undoStart, this._undoText, ""));
+				}
+				this._undoStart = undefined;
+				this._undoText = "";
+				this._undoType = 0;
+			}
+		},
+		_onDestroy: function(evt) {
+			this.model.removeEventListener("Changing", this._listener.onChanging);
+			this.view.removeEventListener("Destroy", this._listener.onDestroy);
+		},
+		_onChanging: function(e) {
+			var newText = e.text;
+			var start = e.start;
+			var removedCharCount = e.removedCharCount;
+			var addedCharCount = e.addedCharCount;
+			if (this._ignoreUndo) {
+				return;
+			}
+			if (this._undoStart !== undefined && 
+				!((addedCharCount === 1 && removedCharCount === 0 && this._undoType === 1 && start === this._undoStart + this._undoText.length) ||
+					(addedCharCount === 0 && removedCharCount === 1 && this._undoType === -1 && (((start + 1) === this._undoStart) || (start === this._undoStart)))))
+			{
+				this._commitUndo();
+			}
+			if (!this.compoundChange) {
+				if (addedCharCount === 1 && removedCharCount === 0) {
+					if (this._undoStart === undefined) {
+						this._undoStart = start;
+					}
+					this._undoText = this._undoText + newText;
+					this._undoType = 1;
+					return;
+				} else if (addedCharCount === 0 && removedCharCount === 1) {
+					var deleting = this._undoText.length > 0 && this._undoStart === start;
+					this._undoStart = start;
+					this._undoType = -1;
+					if (deleting) {
+						this._undoText = this._undoText + this.model.getText(start, start + removedCharCount);
+					} else {
+						this._undoText = this.model.getText(start, start + removedCharCount) + this._undoText;
+					}
+					return;
+				}
+			}
+			this.add(new Change(start, newText, this.model.getText(start, start + removedCharCount)));
+		}
+	};
+	
+	return {
+		UndoStack: UndoStack
+	};
+});
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: 
+ *		Felipe Heidrich (IBM Corporation) - initial API and implementation
+ *		Silenio Quarti (IBM Corporation) - initial API and implementation
+ ******************************************************************************/
+ 
+/*global define window*/
+
+define("orion/textview/textModel", ['orion/textview/eventTarget'], function(mEventTarget) {
+	var isWindows = window.navigator.platform.indexOf("Win") !== -1;
+
+	/**
+	 * Constructs a new TextModel with the given text and default line delimiter.
+	 *
+	 * @param {String} [text=""] the text that the model will store
+	 * @param {String} [lineDelimiter=platform delimiter] the line delimiter used when inserting new lines to the model.
+	 *
+	 * @name orion.textview.TextModel
+	 * @class The TextModel is an interface that provides text for the view. Applications may
+	 * implement the TextModel interface to provide a custom store for the view content. The
+	 * view interacts with its text model in order to access and update the text that is being
+	 * displayed and edited in the view. This is the default implementation.
+	 * <p>
+	 * <b>See:</b><br/>
+	 * {@link orion.textview.TextView}<br/>
+	 * {@link orion.textview.TextView#setModel}
+	 * </p>
+	 * @borrows orion.textview.EventTarget#addEventListener as #addEventListener
+	 * @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
+	 * @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
+	 */
+	function TextModel(text, lineDelimiter) {
+		this._lastLineIndex = -1;
+		this._text = [""];
+		this._lineOffsets = [0];
+		this.setText(text);
+		this.setLineDelimiter(lineDelimiter);
+	}
+
+	TextModel.prototype = /** @lends orion.textview.TextModel.prototype */ {
+		/**
+		 * Returns the number of characters in the model.
+		 *
+		 * @returns {Number} the number of characters in the model.
+		 */
+		getCharCount: function() {
+			var count = 0;
+			for (var i = 0; i<this._text.length; i++) {
+				count += this._text[i].length;
+			}
+			return count;
+		},
+		/**
+		 * Returns the text of the line at the given index.
+		 * <p>
+		 * The valid indices are 0 to line count exclusive.  Returns <code>null</code> 
+		 * if the index is out of range. 
+		 * </p>
+		 *
+		 * @param {Number} lineIndex the zero based index of the line.
+		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
+		 * @returns {String} the line text or <code>null</code> if out of range.
+		 *
+		 * @see #getLineAtOffset
+		 */
+		getLine: function(lineIndex, includeDelimiter) {
+			var lineCount = this.getLineCount();
+			if (!(0 <= lineIndex && lineIndex < lineCount)) {
+				return null;
+			}
+			var start = this._lineOffsets[lineIndex];
+			if (lineIndex + 1 < lineCount) {
+				var text = this.getText(start, this._lineOffsets[lineIndex + 1]);
+				if (includeDelimiter) {
+					return text;
+				}
+				var end = text.length, c;
+				while (((c = text.charCodeAt(end - 1)) === 10) || (c === 13)) {
+					end--;
+				}
+				return text.substring(0, end);
+			} else {
+				return this.getText(start); 
+			}
+		},
+		/**
+		 * Returns the line index at the given character offset.
+		 * <p>
+		 * The valid offsets are 0 to char count inclusive. The line index for
+		 * char count is <code>line count - 1</code>. Returns <code>-1</code> if
+		 * the offset is out of range.
+		 * </p>
+		 *
+		 * @param {Number} offset a character offset.
+		 * @returns {Number} the zero based line index or <code>-1</code> if out of range.
+		 */
+		getLineAtOffset: function(offset) {
+			var charCount = this.getCharCount();
+			if (!(0 <= offset && offset <= charCount)) {
+				return -1;
+			}
+			var lineCount = this.getLineCount();
+			if (offset === charCount) {
+				return lineCount - 1; 
+			}
+			var lineStart, lineEnd;
+			var index = this._lastLineIndex;
+			if (0 <= index && index < lineCount) {
+				lineStart = this._lineOffsets[index];
+				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
+				if (lineStart <= offset && offset < lineEnd) {
+					return index;
+				}
+			}
+			var high = lineCount;
+			var low = -1;
+			while (high - low > 1) {
+				index = Math.floor((high + low) / 2);
+				lineStart = this._lineOffsets[index];
+				lineEnd = index + 1 < lineCount ? this._lineOffsets[index + 1] : charCount;
+				if (offset <= lineStart) {
+					high = index;
+				} else if (offset < lineEnd) {
+					high = index;
+					break;
+				} else {
+					low = index;
+				}
+			}
+			this._lastLineIndex = high;
+			return high;
+		},
+		/**
+		 * Returns the number of lines in the model.
+		 * <p>
+		 * The model always has at least one line.
+		 * </p>
+		 *
+		 * @returns {Number} the number of lines.
+		 */
+		getLineCount: function() {
+			return this._lineOffsets.length;
+		},
+		/**
+		 * Returns the line delimiter that is used by the view
+		 * when inserting new lines. New lines entered using key strokes 
+		 * and paste operations use this line delimiter.
+		 *
+		 * @return {String} the line delimiter that is used by the view when inserting new lines.
+		 */
+		getLineDelimiter: function() {
+			return this._lineDelimiter;
+		},
+		/**
+		 * Returns the end character offset for the given line. 
+		 * <p>
+		 * The end offset is not inclusive. This means that when the line delimiter is included, the 
+		 * offset is either the start offset of the next line or char count. When the line delimiter is
+		 * not included, the offset is the offset of the line delimiter.
+		 * </p>
+		 * <p>
+		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
+		 * if the index is out of range. 
+		 * </p>
+		 *
+		 * @param {Number} lineIndex the zero based index of the line.
+		 * @param {Boolean} [includeDelimiter=false] whether or not to include the line delimiter. 
+		 * @return {Number} the line end offset or <code>-1</code> if out of range.
+		 *
+		 * @see #getLineStart
+		 */
+		getLineEnd: function(lineIndex, includeDelimiter) {
+			var lineCount = this.getLineCount();
+			if (!(0 <= lineIndex && lineIndex < lineCount)) {
+				return -1;
+			}
+			if (lineIndex + 1 < lineCount) {
+				var end = this._lineOffsets[lineIndex + 1];
+				if (includeDelimiter) {
+					return end;
+				}
+				var text = this.getText(Math.max(this._lineOffsets[lineIndex], end - 2), end);
+				var i = text.length, c;
+				while (((c = text.charCodeAt(i - 1)) === 10) || (c === 13)) {
+					i--;
+				}
+				return end - (text.length - i);
+			} else {
+				return this.getCharCount();
+			}
+		},
+		/**
+		 * Returns the start character offset for the given line.
+		 * <p>
+		 * The valid indices are 0 to line count exclusive.  Returns <code>-1</code> 
+		 * if the index is out of range. 
+		 * </p>
+		 *
+		 * @param {Number} lineIndex the zero based index of the line.
+		 * @return {Number} the line start offset or <code>-1</code> if out of range.
+		 *
+		 * @see #getLineEnd
+		 */
+		getLineStart: function(lineIndex) {
+			if (!(0 <= lineIndex && lineIndex < this.getLineCount())) {
+				return -1;
+			}
+			return this._lineOffsets[lineIndex];
+		},
+		/**
+		 * Returns the text for the given range.
+		 * <p>
+		 * The end offset is not inclusive. This means that character at the end offset
+		 * is not included in the returned text.
+		 * </p>
+		 *
+		 * @param {Number} [start=0] the zero based start offset of text range.
+		 * @param {Number} [end=char count] the zero based end offset of text range.
+		 *
+		 * @see #setText
+		 */
+		getText: function(start, end) {
+			if (start === undefined) { start = 0; }
+			if (end === undefined) { end = this.getCharCount(); }
+			if (start === end) { return ""; }
+			var offset = 0, chunk = 0, length;
+			while (chunk<this._text.length) {
+				length = this._text[chunk].length; 
+				if (start <= offset + length) { break; }
+				offset += length;
+				chunk++;
+			}
+			var firstOffset = offset;
+			var firstChunk = chunk;
+			while (chunk<this._text.length) {
+				length = this._text[chunk].length; 
+				if (end <= offset + length) { break; }
+				offset += length;
+				chunk++;
+			}
+			var lastOffset = offset;
+			var lastChunk = chunk;
+			if (firstChunk === lastChunk) {
+				return this._text[firstChunk].substring(start - firstOffset, end - lastOffset);
+			}
+			var beforeText = this._text[firstChunk].substring(start - firstOffset);
+			var afterText = this._text[lastChunk].substring(0, end - lastOffset);
+			return beforeText + this._text.slice(firstChunk+1, lastChunk).join("") + afterText; 
+		},
+		/**
+		 * Notifies all listeners that the text is about to change.
+		 * <p>
+		 * This notification is intended to be used only by the view. Application clients should
+		 * use {@link orion.textview.TextView#event:onModelChanging}.
+		 * </p>
+		 * <p>
+		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
+		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
+		 * purposes and to allow integration with other toolkit frameworks.
+		 * </p>
+		 *
+		 * @param {orion.textview.ModelChangingEvent} modelChangingEvent the changing event
+		 */
+		onChanging: function(modelChangingEvent) {
+			return this.dispatchEvent(modelChangingEvent);
+		},
+		/**
+		 * Notifies all listeners that the text has changed.
+		 * <p>
+		 * This notification is intended to be used only by the view. Application clients should
+		 * use {@link orion.textview.TextView#event:onModelChanged}.
+		 * </p>
+		 * <p>
+		 * NOTE: This method is not meant to called directly by application code. It is called internally by the TextModel
+		 * as part of the implementation of {@link #setText}. This method is included in the public API for documentation
+		 * purposes and to allow integration with other toolkit frameworks.
+		 * </p>
+		 *
+		 * @param {orion.textview.ModelChangedEvent} modelChangedEvent the changed event
+		 */
+		onChanged: function(modelChangedEvent) {
+			return this.dispatchEvent(modelChangedEvent);
+		},
+		/**
+		 * Sets the line delimiter that is used by the view
+		 * when new lines are inserted in the model due to key
+		 * strokes  and paste operations.
+		 * <p>
+		 * If lineDelimiter is "auto", the delimiter is computed to be
+		 * the first delimiter found the in the current text. If lineDelimiter
+		 * is undefined or if there are no delimiters in the current text, the
+		 * platform delimiter is used.
+		 * </p>
+		 *
+		 * @param {String} lineDelimiter the line delimiter that is used by the view when inserting new lines.
+		 */
+		setLineDelimiter: function(lineDelimiter) {
+			if (lineDelimiter === "auto") {
+				lineDelimiter = undefined;
+				if (this.getLineCount() > 1) {
+					lineDelimiter = this.getText(this.getLineEnd(0), this.getLineEnd(0, true));
+				}
+			}
+			this._lineDelimiter = lineDelimiter ? lineDelimiter : (isWindows ? "\r\n" : "\n"); 
+		},
+		/**
+		 * Replaces the text in the given range with the given text.
+		 * <p>
+		 * The end offset is not inclusive. This means that the character at the 
+		 * end offset is not replaced.
+		 * </p>
+		 * <p>
+		 * The text model must notify the listeners before and after the
+		 * the text is changed by calling {@link #onChanging} and {@link #onChanged}
+		 * respectively. 
+		 * </p>
+		 *
+		 * @param {String} [text=""] the new text.
+		 * @param {Number} [start=0] the zero based start offset of text range.
+		 * @param {Number} [end=char count] the zero based end offset of text range.
+		 *
+		 * @see #getText
+		 */
+		setText: function(text, start, end) {
+			if (text === undefined) { text = ""; }
+			if (start === undefined) { start = 0; }
+			if (end === undefined) { end = this.getCharCount(); }
+			if (start === end && text === "") { return; }
+			var startLine = this.getLineAtOffset(start);
+			var endLine = this.getLineAtOffset(end);
+			var eventStart = start;
+			var removedCharCount = end - start;
+			var removedLineCount = endLine - startLine;
+			var addedCharCount = text.length;
+			var addedLineCount = 0;
+			var lineCount = this.getLineCount();
+			
+			var cr = 0, lf = 0, index = 0;
+			var newLineOffsets = [];
+			while (true) {
+				if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
+				if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
+				if (lf === -1 && cr === -1) { break; }
+				if (cr !== -1 && lf !== -1) {
+					if (cr + 1 === lf) {
+						index = lf + 1;
+					} else {
+						index = (cr < lf ? cr : lf) + 1;
+					}
+				} else if (cr !== -1) {
+					index = cr + 1;
+				} else {
+					index = lf + 1;
+				}
+				newLineOffsets.push(start + index);
+				addedLineCount++;
+			}
+		
+			var modelChangingEvent = {
+				type: "Changing",
+				text: text,
+				start: eventStart,
+				removedCharCount: removedCharCount,
+				addedCharCount: addedCharCount,
+				removedLineCount: removedLineCount,
+				addedLineCount: addedLineCount
+			};
+			this.onChanging(modelChangingEvent);
+			
+			//TODO this should be done the loops below to avoid getText()
+			if (newLineOffsets.length === 0) {
+				var startLineOffset = this.getLineStart(startLine), endLineOffset;
+				if (endLine + 1 < lineCount) {
+					endLineOffset = this.getLineStart(endLine + 1);
+				} else {
+					endLineOffset = this.getCharCount();
+				}
+				if (start !== startLineOffset) {
+					text = this.getText(startLineOffset, start) + text;
+					start = startLineOffset;
+				}
+				if (end !== endLineOffset) {
+					text = text + this.getText(end, endLineOffset);
+					end = endLineOffset;
+				}
+			}
+			
+			var changeCount = addedCharCount - removedCharCount;
+			for (var j = startLine + removedLineCount + 1; j < lineCount; j++) {
+				this._lineOffsets[j] += changeCount;
+			}
+			var args = [startLine + 1, removedLineCount].concat(newLineOffsets);
+			Array.prototype.splice.apply(this._lineOffsets, args);
+			
+			var offset = 0, chunk = 0, length;
+			while (chunk<this._text.length) {
+				length = this._text[chunk].length; 
+				if (start <= offset + length) { break; }
+				offset += length;
+				chunk++;
+			}
+			var firstOffset = offset;
+			var firstChunk = chunk;
+			while (chunk<this._text.length) {
+				length = this._text[chunk].length; 
+				if (end <= offset + length) { break; }
+				offset += length;
+				chunk++;
+			}
+			var lastOffset = offset;
+			var lastChunk = chunk;
+			var firstText = this._text[firstChunk];
+			var lastText = this._text[lastChunk];
+			var beforeText = firstText.substring(0, start - firstOffset);
+			var afterText = lastText.substring(end - lastOffset);
+			var params = [firstChunk, lastChunk - firstChunk + 1];
+			if (beforeText) { params.push(beforeText); }
+			if (text) { params.push(text); }
+			if (afterText) { params.push(afterText); }
+			Array.prototype.splice.apply(this._text, params);
+			if (this._text.length === 0) { this._text = [""]; }
+			
+			var modelChangedEvent = {
+				type: "Changed",
+				start: eventStart,
+				removedCharCount: removedCharCount,
+				addedCharCount: addedCharCount,
+				removedLineCount: removedLineCount,
+				addedLineCount: addedLineCount
+			};
+			this.onChanged(modelChangedEvent);
+		}
+	};
+	mEventTarget.EventTarget.addMixin(TextModel.prototype);
+	
+	return {TextModel: TextModel};
+});/*******************************************************************************
+ * @license
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+/*global define setTimeout clearTimeout setInterval clearInterval Node */
+
+define("orion/textview/tooltip", ['orion/textview/textView', 'orion/textview/textModel', 'orion/textview/projectionTextModel'], function(mTextView, mTextModel, mProjectionTextModel) {
 
 	/** @private */
 	function Tooltip (view) {
 		this._view = view;
 		//TODO add API to get the parent of the view
 		this._create(view._parent.ownerDocument);
 		view.addEventListener("Destroy", this, this.destroy);
 	}
@@ -2723,34 +2751,34 @@ define(['orion/textview/textView', 'orio
 				var textEnd = baseModel.getLineEnd(baseModel.getLineAtOffset(end), true);
 				return baseModel.getText(textStart, textEnd);
 			}
 			var title;
 			if (annotations.length === 1) {
 				annotation = annotations[0];
 				if (annotation.title) {
 					title = annotation.title.replace(/</g, "&lt;").replace(/>/g, "&gt;");
-					return "<div>" + annotation.html + "&nbsp;<span style='vertical-align:mddle;'>" + title + "</span><div>";
+					return "<div>" + annotation.html + "&nbsp;<span style='vertical-align:middle;'>" + title + "</span><div>";
 				} else {
 					var newModel = new mProjectionTextModel.ProjectionTextModel(baseModel);
 					var lineStart = baseModel.getLineStart(baseModel.getLineAtOffset(annotation.start));
 					newModel.addProjection({start: annotation.end, end: newModel.getCharCount()});
 					newModel.addProjection({start: 0, end: lineStart});
 					return newModel;
 				}
 			} else {
 				var tooltipHTML = "<div><em>Multiple annotations:</em></div>";
 				for (var i = 0; i < annotations.length; i++) {
 					annotation = annotations[i];
 					title = annotation.title;
 					if (!title) {
 						title = getText(annotation.start, annotation.end);
 					}
 					title = title.replace(/</g, "&lt;").replace(/>/g, "&gt;");
-					tooltipHTML += "<div>" + annotation.html + "&nbsp;<span style='vertical-align:mddle;'>" + title + "</span><div>";
+					tooltipHTML += "<div>" + annotation.html + "&nbsp;<span style='vertical-align:middle;'>" + title + "</span><div>";
 				}
 				return tooltipHTML;
 			}
 		},
 		_getNodeStyle: function(node, prop, defaultValue) {
 			var value;
 			if (node) {
 				value = node.style[prop];
@@ -2766,34 +2794,34 @@ define(['orion/textview/textView', 'orio
 						value = css ? css.getPropertyValue(prop) : null;
 					}
 				}
 			}
 			return value || defaultValue;
 		}
 	};
 	return {Tooltip: Tooltip};
-}, "orion/textview");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
- *		Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#362835 Bug#362428 Bug#362286 Bug#354270 Bug#361474 Bug#363945 Bug#366312
+ *		Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#362835 Bug#362428 Bug#362286 Bug#354270 Bug#361474 Bug#363945 Bug#366312 Bug#370584
  ******************************************************************************/
 
-/*global window document navigator setTimeout clearTimeout XMLHttpRequest define */
-
-define(['orion/textview/textModel', 'orion/textview/keyBinding', 'orion/textview/eventTarget'], function(mTextModel, mKeyBinding, mEventTarget) {
+/*global window document navigator setTimeout clearTimeout XMLHttpRequest define DOMException */
+
+define("orion/textview/textView", ['orion/textview/textModel', 'orion/textview/keyBinding', 'orion/textview/eventTarget'], function(mTextModel, mKeyBinding, mEventTarget) {
 
 	/** @private */
 	function addHandler(node, type, handler, capture) {
 		if (typeof node.addEventListener === "function") {
 			node.addEventListener(type, handler, capture === true);
 		} else {
 			node.attachEvent("on" + type, handler);
 		}
@@ -2906,18 +2934,18 @@ define(['orion/textview/textModel', 'ori
 	 * </p>		 
 	 * @name orion.textview.TextViewOptions
 	 *
 	 * @property {String|DOMElement} parent the parent element for the view, it can be either a DOM element or an ID for a DOM element.
 	 * @property {orion.textview.TextModel} [model] the text model for the view. If it is not set the view creates an empty {@link orion.textview.TextModel}.
 	 * @property {Boolean} [readonly=false] whether or not the view is read-only.
 	 * @property {Boolean} [fullSelection=true] whether or not the view is in full selection mode.
 	 * @property {Boolean} [sync=false] whether or not the view creation should be synchronous (if possible).
-	 * @property {Boolean} [expandTab=false] whether or not the tab key inserts white spaces
-	 * @property {String|String[]} [stylesheet] one or more stylesheet URIs for the view.
+	 * @property {Boolean} [expandTab=false] whether or not the tab key inserts white spaces.
+	 * @property {String|String[]} [stylesheet] one or more stylesheet for the view. Each stylesheet can be either a URI or a string containing the CSS rules.
 	 * @property {String} [themeClass] the CSS class for the view theming.
 	 * @property {Number} [tabSize] The number of spaces in a tab.
 	 */
 	/**
 	 * Constructs a new text view.
 	 * 
 	 * @param {orion.textview.TextViewOptions} options the view options.
 	 * 
@@ -3525,16 +3553,26 @@ define(['orion/textview/textModel', 'ori
 						if (a.userHandler()) { return; }
 					}
 					if (a.defaultHandler) { return a.defaultHandler(); }
 					return false;
 				}
 			}
 			return false;
 		},
+		/**
+		* Returns if the view is loaded.
+		* <p>
+		* @returns {Boolean} <code>true</code> if the view is loaded.
+		*
+		* @see #onLoad
+		*/
+		isLoaded: function () {
+			return !!this._clientDiv;
+		},
 		/** 
 		 * @class This is the event sent when the user right clicks or otherwise invokes the context menu of the view. 
 		 * <p> 
 		 * <b>See:</b><br/> 
 		 * {@link orion.textview.TextView}<br/> 
 		 * {@link orion.textview.TextView#event:onContextMenu} 
 		 * </p> 
 		 * 
@@ -4184,17 +4222,19 @@ define(['orion/textview/textModel', 'ori
 			for (option in options) {
 				if (options.hasOwnProperty(option)) {
 					var newValue = options[option], oldValue = this["_" + option];
 					if (this._compare(oldValue, newValue)) { continue; }
 					changed = true;
 					if (!recreate) {
 						var update = defaultOptions[option].update;
 						if (created && update) {
-							update.call(this, newValue);
+							if (update.call(this, newValue)) {
+								recreate = true;
+							}
 							continue;
 						}
 					}
 					this["_" + option] = this._clone(newValue);
 				}
 			}
 			if (changed) {
 				if (recreate) {
@@ -4262,17 +4302,17 @@ define(['orion/textview/textModel', 'ori
 			this._modifyContent({text: text, start: start, end: end, _code: true}, !reset);
 			if (reset) {
 				this._columnX = -1;
 				this._setSelection(new Selection (0, 0, false), true);
 				
 				/*
 				* Bug in Firefox.  For some reason, the caret does not show after the
 				* view is refreshed.  The fix is to toggle the contentEditable state and
-				* force the clientDiv to loose and receive focus if the it is focused.
+				* force the clientDiv to loose and receive focus if it is focused.
 				*/
 				if (isFirefox) {
 					this._fixCaret();
 				}
 			}
 		},
 		/**
 		 * Sets the top index.
@@ -4335,17 +4375,17 @@ define(['orion/textview/textModel', 'ori
 		 */
 		showSelection: function() {
 			return this._showCaret(true);
 		},
 		
 		/**************************************** Event handlers *********************************/
 		_handleBodyMouseDown: function (e) {
 			if (!e) { e = window.event; }
-			if (isFirefox) {
+			if (isFirefox && e.which === 1) {
 				this._clientDiv.contentEditable = false;
 				(this._overlayDiv || this._clientDiv).draggable = true;
 				this._ignoreBlur = true;
 			}
 			
 			/*
 			 * Prevent clicks outside of the view from taking focus 
 			 * away the view. Note that in Firefox and Opera clicking on the 
@@ -4370,26 +4410,26 @@ define(['orion/textview/textModel', 'ori
 				*  setCapture/releaseCapture. 
 				*/ 
 				topNode.setCapture();
 				setTimeout(function() { topNode.releaseCapture(); }, 0);
 			}
 		},
 		_handleBodyMouseUp: function (e) {
 			if (!e) { e = window.event; }
-			if (isFirefox) {
+			if (isFirefox && e.which === 1) {
 				this._clientDiv.contentEditable = true;
 				(this._overlayDiv || this._clientDiv).draggable = false;
 				
 				/*
 				* Bug in Firefox.  For some reason, Firefox stops showing the caret
 				* in some cases. For example when the user cancels a drag operation 
 				* by pressing ESC.  The fix is to detect that the drag operation was
 				* cancelled,  toggle the contentEditable state and force the clientDiv
-				* to loose and receive focus if the it is focused.
+				* to loose and receive focus if it is focused.
 				*/
 				this._fixCaret();
 				this._ignoreBlur = false;
 			}
 		},
 		_handleBlur: function (e) {
 			if (!e) { e = window.event; }
 			if (this._ignoreBlur) { return; }
@@ -4515,16 +4555,24 @@ define(['orion/textview/textModel', 'ori
 			if (!e) { e = window.event; }
 			this._dropTarget = false;
 			this._dragOffset = -1;
 			if (this.isListening("DragEnd")) {
 				this.onDragEnd(this._createMouseEvent("DragEnd", e));
 			}
 			if (isFirefox) {
 				this._fixCaret();
+				/*
+				* Bug in Firefox.  For some reason, Firefox stops showing the caret when the 
+				* selection is dropped onto itself. The fix is to detected the case and 
+				* call fixCaret() a second time.
+				*/
+				if (e.dataTransfer.dropEffect === "none" && !e.dataTransfer.mozUserCancelled) {
+					this._fixCaret();
+				}
 			}
 		},
 		_handleDragEnter: function (e) {
 			if (!e) { e = window.event; }
 			var prevent = true;
 			this._dropTarget = true;
 			if (this.isListening("DragEnter")) {
 				prevent = false;
@@ -4627,17 +4675,32 @@ define(['orion/textview/textModel', 'ori
 				default:
 					this._setLinksVisible(false);
 			}
 			if (e.keyCode === 229) {
 				if (this._readonly) {
 					if (e.preventDefault) { e.preventDefault(); }
 					return false;
 				}
-				this._startIME();
+				var startIME = true;
+				
+				/*
+				* Bug in Safari. Some Control+key combinations send key events
+				* with keyCode equals to 229. This is unexpected and causes the
+				* view to start an IME composition. The fix is to ignore these
+				* events.
+				*/
+				if (isSafari && isMac) {
+					if (e.ctrlKey) {
+						startIME = false;
+					}
+				}
+				if (startIME) {
+					this._startIME();
+				}
 			} else {
 				this._commitIME();
 			}
 			/*
 			* Feature in Firefox. When a key is held down the browser sends 
 			* right number of keypress events but only one keydown. This is
 			* unexpected and causes the view to only execute an action
 			* just one time. The fix is to ignore the keydown event and 
@@ -4866,19 +4929,17 @@ define(['orion/textview/textModel', 'ori
 			* down which causes the view to enter link mode.  Link mode does not end
 			* because there are no further events.  The fix is to only enter link
 			* mode when the coordinates of the mouse move event have changed.
 			*/
 			var changed = this._linksVisible || this._lastMouseMoveX !== e.clientX || this._lastMouseMoveY !== e.clientY;
 			this._lastMouseMoveX = e.clientX;
 			this._lastMouseMoveY = e.clientY;
 			this._setLinksVisible(changed && !this._isMouseDown && (isMac ? e.metaKey : e.ctrlKey));
-			if (!this._isMouseDown || this._dragOffset !== -1) {
-				return;
-			}
+
 			/*
 			* Feature in IE8 and older, the sequence of events in the IE8 event model
 			* for a doule-click is:
 			*
 			*	down
 			*	up
 			*	up
 			*	dblclick
@@ -4896,16 +4957,19 @@ define(['orion/textview/textModel', 'ori
 					this._setGrab(null);
 					return true;
 				}
 				if (!this._isMouseDown && e.button === 1 && (this._clickCount & 1) !== 0) {
 					this._clickCount = 2;
 					return this._handleMouse(e, this._clickCount);
 				}
 			}
+			if (!this._isMouseDown || this._dragOffset !== -1) {
+				return;
+			}
 			
 			var x = e.clientX;
 			var y = e.clientY;
 			if (isChrome) {
 				if (e.currentTarget !== this._frameWindow) {
 					var rect = this._frame.getBoundingClientRect();
 					x -= rect.left;
 					y -= rect.top;
@@ -5099,17 +5163,26 @@ define(['orion/textview/textModel', 'ori
 		_handleResize: function (e) {
 			if (!e) { e = window.event; }
 			var element = this._frameDocument.documentElement;
 			var newWidth = element.clientWidth;
 			var newHeight = element.clientHeight;
 			if (this._frameWidth !== newWidth || this._frameHeight !== newHeight) {
 				this._frameWidth = newWidth;
 				this._frameHeight = newHeight;
-				this._updatePage();
+				/*
+				* Feature in IE7. For some reason, sometimes Internet Explorer 7 
+				* returns incorrect values for element.getBoundingClientRect() when 
+				* inside a resize handler. The fix is to queue the work.
+				*/
+				if (isIE < 9) {
+					this._queueUpdatePage();
+				} else {
+					this._updatePage();
+				}
 			}
 		},
 		_handleRulerEvent: function (e) {
 			if (!e) { e = window.event; }
 			var target = e.target ? e.target : e.srcElement;
 			var lineIndex = target.lineIndex;
 			var element = target;
 			while (element && !element._ruler) {
@@ -5676,17 +5749,19 @@ define(['orion/textview/textModel', 'ori
 			return true;
 		},
 		
 		/************************************ Internals ******************************************/
 		_applyStyle: function(style, node, reset) {
 			if (reset) {
 				var attrs = node.attributes;
 				for (var i= attrs.length; i-->0;) {
-					node.removeAttributeNode(attrs[i]); 
+					if (attrs[i].specified) {
+						node.removeAttributeNode(attrs[i]); 
+					}
 				}
 			}
 			if (!style) {
 				return;
 			}
 			if (style.styleClass) {
 				node.className = style.styleClass;
 			}
@@ -6148,31 +6223,31 @@ define(['orion/textview/textModel', 'ori
 				var modelChangedEvent = div.modelChangedEvent;
 				if (modelChangedEvent) {
 					if (modelChangedEvent.removedLineCount === 0 && modelChangedEvent.addedLineCount === 0) {
 						changeStart = modelChangedEvent.start - lineStart;
 						changeCount = modelChangedEvent.addedCharCount - modelChangedEvent.removedCharCount;
 					} else {
 						changeStart = -1;
 					}
-					delete div.modelChangedEvent;
+					div.modelChangedEvent = undefined;
 				}
 				oldSpan = div.firstChild;
 			}
 			for (var i = 0; i < ranges.length; i++) {
 				range = ranges[i];
 				text = range.text;
 				end += text.length;
 				style = range.style;
 				if (oldSpan) {
 					oldText = oldSpan.firstChild.data;
 					oldStyle = oldSpan.viewStyle;
 					if (oldText === text && this._compare(style, oldStyle)) {
 						oldEnd += oldText.length;
-						delete oldSpan._rectsCache;
+						oldSpan._rectsCache = undefined;
 						span = oldSpan = oldSpan.nextSibling;
 						continue;
 					} else {
 						while (oldSpan) {
 							if (changeStart !== -1) {
 								var spanEnd = end;
 								if (spanEnd >= changeStart) {
 									spanEnd -= changeCount;
@@ -6388,33 +6463,46 @@ define(['orion/textview/textModel', 'ori
 			html.push("<style>");
 			html.push(".viewContainer {font-family: monospace; font-size: 10pt;}");
 			html.push(".view {padding: 1px 2px;}");
 			html.push(".viewContent {}");
 			html.push("</style>");
 			if (this._stylesheet) {
 				var stylesheet = typeof(this._stylesheet) === "string" ? [this._stylesheet] : this._stylesheet;
 				for (var i = 0; i < stylesheet.length; i++) {
-					if (this._sync) {
+					var sheet = stylesheet[i];
+					var isLink = this._isLinkURL(sheet);
+					if (isLink && this._sync) {
 						try {
 							var objXml = new XMLHttpRequest();
 							if (objXml.overrideMimeType) {
 								objXml.overrideMimeType("text/css");
 							}
-							objXml.open("GET", stylesheet[i], false);
+							objXml.open("GET", sheet, false);
 							objXml.send(null);
-							html.push("<style>");
-							html.push(objXml.responseText);
-							html.push("</style>");
-							continue;
+							sheet = objXml.responseText;
+							isLink = false;
 						} catch (e) {}
 					}
-					html.push("<link rel='stylesheet' type='text/css' href='");
-					html.push(stylesheet[i]);
-					html.push("'></link>");
+					if (isLink) {
+						html.push("<link rel='stylesheet' type='text/css' ");
+						/*
+						* Bug in IE7. The window load event is not sent unless a load handler is added to the link node.
+						*/
+						if (isIE < 9) {
+							html.push("onload='window' ");
+						}
+						html.push("href='");
+						html.push(sheet);
+						html.push("'></link>");
+					} else {
+						html.push("<style>");
+						html.push(sheet);
+						html.push("</style>");
+					}
 				}
 			}
 			/*
 			* Feature in WebKit.  In WebKit, window load will not wait for the style sheets
 			* to be loaded unless there is script element after the style sheet link elements.
 			*/
 			html.push("<script>");
 			html.push("var waitForStyleSheets = true;");
@@ -6425,54 +6513,97 @@ define(['orion/textview/textModel', 'ori
 			return html.join("");
 		},
 		_createView: function() {
 			if (this._frameDocument) { return; }
 			var frameWindow = this._frameWindow = this._frame.contentWindow;
 			var frameDocument = this._frameDocument = frameWindow.document;
 			var self = this;
 			function write() {
-				frameDocument.open();
+				frameDocument.open("text/html", "replace");
 				frameDocument.write(self._getFrameHTML());
 				frameDocument.close();
 				self._windowLoadHandler = function(e) {
-					self._createContent();
+					/*
+					* Bug in Safari.  Safari sends the window load event before the
+					* style sheets are loaded. The fix is to defer creation of the
+					* contents until the document readyState changes to complete.
+					*/
+					if (self._isDocumentReady()) {
+						self._createContent();
+					}
 				};
 				addHandler(frameWindow, "load", self._windowLoadHandler);
 			}
-			/*
-			* Bug in Firefox.  Firefox does not send window load event if document.write
-			* is done inside of the frame load event handler.
-			*/
-			if (isFirefox && !this._sync) {
-				setTimeout(write, 0);
-			} else {
-				write();
-			}
+			write();
 			if (this._sync) {
 				this._createContent();
-			}
+			} else {
+				/*
+				* Bug in Webkit. Webkit does not send the load event for the iframe window when the main page
+				* loads as a result of backward or forward navigation.
+				* The fix is to use a timer to create the content only when the document is ready.
+				*/
+				this._createViewTimer = function() {
+					if (self._clientDiv) { return; }
+					if (self._isDocumentReady()) {
+						self._createContent();
+					} else {
+						setTimeout(self._createViewTimer, 10);
+					}
+				};
+				setTimeout(this._createViewTimer, 10);
+			}
+		},
+		_isDocumentReady: function() {
+			var frameDocument = this._frameDocument;
+			if (!frameDocument) { return false; }
+			if (frameDocument.readyState === "complete") {
+				return true;
+			} else if (frameDocument.readyState === "interactive" && isFirefox) {
+				/*
+				* Bug in Firefox. Firefox does not change the document ready state to complete 
+				* all the time. The fix is to wait for the ready state to be "interactive" and check that 
+				* all css rules are initialized.
+				*/
+				var styleSheets = frameDocument.styleSheets;
+				var styleSheetCount = 1;
+				if (this._stylesheet) {
+					styleSheetCount += typeof(this._stylesheet) === "string" ? 1 : this._stylesheet.length;
+				}
+				if (styleSheetCount === styleSheets.length) {
+					var index = 0;
+					while (index < styleSheets.length) {
+						var count = 0;
+						try {
+							count = styleSheets.item(index).cssRules.length;
+						} catch (ex) {
+							/*
+							* Feature in Firefox. To determine if a stylesheet is loaded the number of css rules is used, if the 
+							* stylesheet is not loaded this operation will throw an invalid access error. When a stylesheet from
+							* a different domain is loaded, accessing the css rules will result in a security exception. In this
+							* case count is set to 1 to indicate the stylesheet is loaded.
+							*/
+							if (ex.code !== DOMException.INVALID_ACCESS_ERR) {
+								count = 1;
+							}
+						}
+						if (count === 0) { break; }
+						index++;
+					}
+					return index === styleSheets.length;
+				}	
+			}
+			return false;
 		},
 		_createContent: function() {
 			if (this._clientDiv) { return; }
 			var parent = this._parent;
 			var parentDocument = this._parentDocument;
 			var frameDocument = this._frameDocument;
-			/*
-			* Bug in Safari.  Safari sends the window load event before the
-			* style sheets are loaded. The fix is to defer creation of the
-			* contents until the document readyState changes to complete.
-			*/
-			var self = this;
-			if (!this._sync && frameDocument.readyState !== "complete") {
-				setTimeout(function() {
-					self._createContent();
-				}, 10);
-				return;
-			}
 			var body = frameDocument.body;
 			this._setThemeClass(this._themeClass, true);
 			body.style.margin = "0px";
 			body.style.borderWidth = "0px";
 			body.style.padding = "0px";
 			
 			var textArea;
 			if (isPad) {
@@ -6489,18 +6620,18 @@ define(['orion/textview/textModel', 'ori
 				parent.appendChild(touchDiv);
 
 				textArea = parentDocument.createElement("TEXTAREA");
 				this._textArea = textArea;
 				textArea.style.position = "absolute";
 				textArea.style.whiteSpace = "pre";
 				textArea.style.left = "-1000px";
 				textArea.tabIndex = 1;
-				textArea.autocapitalize = false;
-				textArea.autocorrect = false;
+				textArea.autocapitalize = "off";
+				textArea.autocorrect = "off";
 				textArea.className = "viewContainer";
 				textArea.style.background = "transparent";
 				textArea.style.color = "transparent";
 				textArea.style.border = "0px";
 				textArea.style.padding = "0px";
 				textArea.style.margin = "0px";
 				textArea.style.borderRadius = "0px";
 				textArea.style.WebkitAppearance = "none";
@@ -6615,17 +6746,17 @@ define(['orion/textview/textModel', 'ori
 		_defaultOptions: function() {
 			return {
 				parent: {value: undefined, recreate: true, update: null},
 				model: {value: undefined, recreate: false, update: this.setModel},
 				readonly: {value: false, recreate: false, update: null},
 				fullSelection: {value: true, recreate: false, update: this._setFullSelection},
 				tabSize: {value: 8, recreate: false, update: this._setTabSize},
 				expandTab: {value: false, recreate: false, update: null},
-				stylesheet: {value: [], recreate: true, update: null},
+				stylesheet: {value: [], recreate: false, update: this._setStyleSheet},
 				themeClass: {value: undefined, recreate: false, update: this._setThemeClass},
 				sync: {value: false, recreate: false, update: null}
 			};
 		},
 		_destroyFrame: function() {
 			var frame = this._frame;
 			if (!frame) { return; }
 			if (this._loadHandler) {
@@ -7562,16 +7693,19 @@ define(['orion/textview/textModel', 'ori
 
 			/* IME */
 			this._imeOffset = -1;
 			
 			/* Create elements */
 			this._createActions();
 			this._createFrame();
 		},
+		_isLinkURL: function(string) {
+			return string.toLowerCase().lastIndexOf(".css") === string.length - 4;
+		},
 		_modifyContent: function(e, updateCaret) {
 			if (this._readonly && !e._code) {
 				return;
 			}
 			e.type = "Verify";
 			this.onVerify(e);
 
 			if (e.text === null || e.text === undefined) { return; }
@@ -7670,17 +7804,17 @@ define(['orion/textview/textModel', 'ori
 				var child = clientDiv.firstChild;
 				while (child) {
 					child.lineRemoved = true;
 					child = child.nextSibling;
 				}
 				/*
 				* Bug in Firefox.  For some reason, the caret does not show after the
 				* view is refreshed.  The fix is to toggle the contentEditable state and
-				* force the clientDiv to loose and receive focus if the it is focused.
+				* force the clientDiv to loose and receive focus if it is focused.
 				*/
 				if (isFirefox) {
 					this._ignoreFocus = false;
 					var hasFocus = this._hasFocus;
 					if (hasFocus) { clientDiv.blur(); }
 					clientDiv.contentEditable = false;
 					clientDiv.contentEditable = true;
 					if (hasFocus) { clientDiv.focus(); }
@@ -8131,16 +8265,82 @@ define(['orion/textview/textModel', 'ori
 					}
 				}
 				selection.setCaret(start);
 				selection.extend(end);
 			} 
 			this._setSelection(selection, true, true);
 			return true;
 		},
+		_setStyleSheet: function(stylesheet) {
+			var oldstylesheet = this._stylesheet;
+			if (!(oldstylesheet instanceof Array)) {
+				oldstylesheet = [oldstylesheet];
+			}
+			this._stylesheet = stylesheet;
+			if (!(stylesheet instanceof Array)) {
+				stylesheet = [stylesheet];
+			}
+			var document = this._frameDocument;
+			var documentStylesheet = document.styleSheets;
+			var head = document.getElementsByTagName("head")[0];
+			var changed = false;
+			var i = 0, sheet, oldsheet, documentSheet, ownerNode, styleNode, textNode;
+			while (i < stylesheet.length) {
+				if (i >= oldstylesheet.length) { break; }
+				sheet = stylesheet[i];
+				oldsheet = oldstylesheet[i];
+				if (sheet !== oldsheet) {
+					if (this._isLinkURL(sheet)) {
+						return true;
+					} else {
+						documentSheet = documentStylesheet[i+1];
+						ownerNode = documentSheet.ownerNode;
+						styleNode = document.createElement('STYLE');
+						textNode = document.createTextNode(sheet);
+						styleNode.appendChild(textNode);
+						head.replaceChild(styleNode, ownerNode);
+						changed = true;
+					}
+				}
+				i++;
+			}
+			if (i < oldstylesheet.length) {
+				while (i < oldstylesheet.length) {
+					sheet = oldstylesheet[i];
+					if (this._isLinkURL(sheet)) {
+						return true;
+					} else {
+						documentSheet = documentStylesheet[i+1];
+						ownerNode = documentSheet.ownerNode;
+						head.removeChild(ownerNode);
+						changed = true;
+					}
+					i++;
+				}
+			} else {
+				while (i < stylesheet.length) {
+					sheet = stylesheet[i];
+					if (this._isLinkURL(sheet)) {
+						return true;
+					} else {
+						styleNode = document.createElement('STYLE');
+						textNode = document.createTextNode(sheet);
+						styleNode.appendChild(textNode);
+						head.appendChild(styleNode);
+						changed = true;
+					}
+					i++;
+				}
+			}
+			if (changed) {
+				this._updateStyle();
+			}
+			return false;
+		},
 		_setFullSelection: function(fullSelection, init) {
 			this._fullSelection = fullSelection;
 			
 			/* 
 			* Bug in IE 8. For some reason, during scrolling IE does not reflow the elements
 			* that are used to compute the location for the selection divs. This causes the
 			* divs to be placed at the wrong location. The fix is to disabled full selection for IE8.
 			*/
@@ -8267,25 +8467,17 @@ define(['orion/textview/textModel', 'ori
 		_setThemeClass: function (themeClass, init) {
 			this._themeClass = themeClass;
 			var document = this._frameDocument;
 			if (document) {
 				var viewContainerClass = "viewContainer";
 				if (this._themeClass) { viewContainerClass += " " + this._themeClass; }
 				document.body.className = viewContainerClass;
 				if (!init) {
-					if (isIE) {
-						document.body.style.lineHeight = "normal";
-					}
-					this._lineHeight = this._calculateLineHeight();
-					this._viewPadding = this._calculatePadding();
-					if (isIE) {
-						document.body.style.lineHeight = this._lineHeight + "px";
-					}
-					this.redraw();
+					this._updateStyle();
 				}
 			}
 		},
 		_showCaret: function (allSelection, pageScroll) {
 			if (!this._clientDiv) { return; }
 			var model = this._model;
 			var selection = this._getSelection();
 			var scroll = this._getScroll();
@@ -8812,39 +9004,51 @@ define(['orion/textview/textModel', 'ori
 							lineDiv = lineDiv.nextSibling;
 						}
 					}
 					div._oldTrackHeight = trackHeight;
 				}
 				div.rulerChanged = false;
 				div = div.nextSibling;
 			}
+		},
+		_updateStyle: function () {
+			var document = this._frameDocument;
+			if (isIE) {
+				document.body.style.lineHeight = "normal";
+			}
+			this._lineHeight = this._calculateLineHeight();
+			this._viewPadding = this._calculatePadding();
+			if (isIE) {
+				document.body.style.lineHeight = this._lineHeight + "px";
+			}
+			this.redraw();
 		}
 	};//end prototype
 	mEventTarget.EventTarget.addMixin(TextView.prototype);
 	
 	return {TextView: TextView};
-}, "orion/textview");
+});
 
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: 
  *		Felipe Heidrich (IBM Corporation) - initial API and implementation
  *		Silenio Quarti (IBM Corporation) - initial API and implementation
  ******************************************************************************/
  
 /*global define */
 
-define([], function() {
+define("orion/textview/textDND", [], function() {
 
 	function TextDND(view, undoStack) {
 		this._view = view;
 		this._undoStack = undoStack;
 		this._dragSelection = null;
 		this._dropOffset = -1;
 		this._dropText = null;
 		var self = this;
@@ -8957,135 +9161,119 @@ define([], function() {
 					view.setText(text, offset, offset);
 					view.setSelection(offset, offset + text.length);
 				}
 			}
 		}
 	};
 
 	return {TextDND: TextDND};
-}, "orion/textview");/******************************************************************************* 
+});/******************************************************************************* 
  * @license
  * Copyright (c) 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: IBM Corporation - initial API and implementation 
  ******************************************************************************/
 
 /*jslint */
 /*global define */
 
-define([], function() {
+define("orion/editor/htmlGrammar", [], function() {
 
 	/**
 	 * Provides a grammar that can do some very rough syntax highlighting for HTML.
 	 * @class orion.syntax.HtmlGrammar
 	 */
 	function HtmlGrammar() {
+		/**
+		 * Object containing the grammar rules.
+		 * @public
+		 * @type Object
+		 */
 		return {
-			/**
-			 * What kind of highlight provider we are.
-			 * @public
-			 * @type String
-			 */
-			type: "grammar",
-			
-			/**
-			 * The file extensions that we provide rules for.
-			 * @public
-			 * @type String[]
-			 */
-			fileTypes: [ "html", "htm" ],
-			
-			/**
-			 * Object containing the grammar rules.
-			 * @public
-			 * @type Object
-			 */
-			grammar: {
-				"name": "HTML",
-				"scopeName": "source.html",
-				"uuid": "3B5C76FB-EBB5-D930-F40C-047D082CE99B",
-				"patterns": [
-					// TODO unicode?
-					{
-						"match": "<!(doctype|DOCTYPE)[^>]+>",
-						"name": "entity.name.tag.doctype.html"
+			"name": "HTML",
+			"scopeName": "source.html",
+			"uuid": "3B5C76FB-EBB5-D930-F40C-047D082CE99B",
+			"patterns": [
+				// TODO unicode?
+				{
+					"match": "<!(doctype|DOCTYPE)[^>]+>",
+					"name": "entity.name.tag.doctype.html"
+				},
+				{
+					"begin": "<!--",
+					"end": "-->",
+					"beginCaptures": {
+						"0": { "name": "punctuation.definition.comment.html" }
+					},
+					"endCaptures": {
+						"0": { "name": "punctuation.definition.comment.html" }
 					},
-					{
-						"begin": "<!--",
-						"end": "-->",
-						"beginCaptures": {
-							"0": { "name": "punctuation.definition.comment.html" }
-						},
-						"endCaptures": {
-							"0": { "name": "punctuation.definition.comment.html" }
-						},
-						"patterns": [
-							{
-								"match": "--",
-								"name": "invalid.illegal.badcomment.html"
-							}
-						],
-						"contentName": "comment.block.html"
-					},
-					{ // startDelimiter + tagName
-						"match": "<[A-Za-z0-9_\\-:]+(?= ?)",
-						"name": "entity.name.tag.html"
-					},
-					{ "include": "#attrName" },
-					{ "include": "#qString" },
-					{ "include": "#qqString" },
-					// TODO attrName, qString, qqString should be applied first while inside a tag
-					{ // startDelimiter + slash + tagName + endDelimiter
-						"match": "</[A-Za-z0-9_\\-:]+>",
-						"name": "entity.name.tag.html"
-					},
-					{ // end delimiter of open tag
-						"match": ">", 
-						"name": "entity.name.tag.html"
-					} ],
-				"repository": {
-					"attrName": { // attribute name
-						"match": "[A-Za-z\\-:]+(?=\\s*=\\s*['\"])",
-						"name": "entity.other.attribute.name.html"
-					},
-					"qqString": { // double quoted string
-						"match": "(\")[^\"]+(\")",
-						"name": "string.quoted.double.html"
-					},
-					"qString": { // single quoted string
-						"match": "(')[^']+(\')",
-						"name": "string.quoted.single.html"
-					}
+					"patterns": [
+						{
+							"match": "--",
+							"name": "invalid.illegal.badcomment.html"
+						}
+					],
+					"contentName": "comment.block.html"
+				},
+				{ // startDelimiter + tagName
+					"match": "<[A-Za-z0-9_\\-:]+(?= ?)",
+					"name": "entity.name.tag.html"
+				},
+				{ "include": "#attrName" },
+				{ "include": "#qString" },
+				{ "include": "#qqString" },
+				// TODO attrName, qString, qqString should be applied first while inside a tag
+				{ // startDelimiter + slash + tagName + endDelimiter
+					"match": "</[A-Za-z0-9_\\-:]+>",
+					"name": "entity.name.tag.html"
+				},
+				{ // end delimiter of open tag
+					"match": ">", 
+					"name": "entity.name.tag.html"
+				} ],
+			"repository": {
+				"attrName": { // attribute name
+					"match": "[A-Za-z\\-:]+(?=\\s*=\\s*['\"])",
+					"name": "entity.other.attribute.name.html"
+				},
+				"qqString": { // double quoted string
+					"match": "(\")[^\"]+(\")",
+					"name": "string.quoted.double.html"
+				},
+				"qString": { // single quoted string
+					"match": "(')[^']+(\')",
+					"name": "string.quoted.single.html"
 				}
 			}
 		};
 	}
 
 	return {HtmlGrammar: HtmlGrammar};
-}, "orion/editor");
+});
 /******************************************************************************* 
  * @license
  * Copyright (c) 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: IBM Corporation - initial API and implementation 
  ******************************************************************************/
 
 /*jslint regexp:false laxbreak:true*/
 /*global define */
 
-define(['orion/editor/regex'], function(mRegex) {
+define("orion/editor/textMateStyler", ['orion/editor/regex'], function(mRegex) {
 
 var RegexUtil = {
 	// Rules to detect some unsupported Oniguruma features
 	unsupported: [
 		{regex: /\(\?[ims\-]:/, func: function(match) { return "option on/off for subexp"; }},
 		{regex: /\(\?<([=!])/, func: function(match) { return (match[1] === "=") ? "lookbehind" : "negative lookbehind"; }},
 		{regex: /\(\?>/, func: function(match) { return "atomic group"; }}
 	],
@@ -10416,31 +10604,32 @@ var RegexUtil = {
 			return styleRanges;
 		}
 	};
 	
 	return {
 		RegexUtil: RegexUtil,
 		TextMateStyler: TextMateStyler
 	};
-}, "orion/editor");
+});
 /*******************************************************************************
  * @license
  * Copyright (c) 2010, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials are made 
  * available under the terms of the Eclipse Public License v1.0 
  * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
  * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
  * 
  * Contributors: IBM Corporation - initial API and implementation
+ *               Alex Lakatos - fix for bug#369781
  ******************************************************************************/
 
 /*global document window navigator define */
 
-define(['orion/textview/annotations'], function(mAnnotations) {
+define("examples/textview/textStyler", ['orion/textview/annotations'], function(mAnnotations) {
 
 	var JS_KEYWORDS =
 		["break",
 		 "case", "class", "catch", "continue", "const", 
 		 "debugger", "default", "delete", "do",
 		 "else", "enum", "export", "extends",  
 		 "false", "finally", "for", "function",
 		 "if", "implements", "import", "in", "instanceof", "interface", 
@@ -10863,16 +11052,32 @@ define(['orion/textview/annotations'], f
 		view.addEventListener("Destroy", this._listener.onDestroy);
 		view.addEventListener("LineStyle", this._listener.onLineStyle);
 		this._computeComments ();
 		this._computeFolding();
 		view.redrawLines();
 	}
 	
 	TextStyler.prototype = {
+		getClassNameForToken: function(token) {
+			switch (token) {
+				case "singleLineComment": return singleCommentStyle.styleClass;
+				case "multiLineComment": return multiCommentStyle.styleClass;
+				case "docComment": return docCommentStyle.styleClass;
+				case "docHtmlComment": return htmlMarkupStyle.styleClass;
+				case "tasktag": return tasktagStyle.styleClass;
+				case "doctag": return doctagStyle.styleClass;
+				case "string": return stringStyle.styleClass;
+				case "keyword": return keywordStyle.styleClass;
+				case "space": return spaceStyle.styleClass;
+				case "tab": return tabStyle.styleClass;
+				case "caretLine": return caretLineStyle.styleClass;
+			}
+			return null;
+		},
 		destroy: function() {
 			var view = this.view;
 			if (view) {
 				var model = view.getModel();
 				if (model.getBaseModel) {
 					model.getBaseModel().removeEventListener("Changed", this._listener.onChanged);
 				} else {
 					view.removeEventListener("ModelChanged", this._listener.onChanged);
@@ -11511,9 +11716,9 @@ define(['orion/textview/annotations'], f
 					}
 				}
 				annotationModel.replaceAnnotations(remove, add);
 			}
 		}
 	};
 	
 	return {TextStyler: TextStyler};
-}, "examples/textview");
+});
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -49,33 +49,43 @@ Cu.import("resource:///modules/source-ed
 
 XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
                                    "@mozilla.org/widget/clipboardhelper;1",
                                    "nsIClipboardHelper");
 
 const ORION_SCRIPT = "chrome://browser/content/orion.js";
 const ORION_IFRAME = "data:text/html;charset=utf8,<!DOCTYPE html>" +
   "<html style='height:100%' dir='ltr'>" +
+  "<head><link rel='stylesheet'" +
+  " href='chrome://browser/skin/devtools/orion-container.css'></head>" +
   "<body style='height:100%;margin:0;overflow:hidden'>" +
   "<div id='editor' style='height:100%'></div>" +
   "</body></html>";
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /**
+ * The primary selection update delay. On Linux, the X11 primary selection is
+ * updated to hold the currently selected text.
+ *
+ * @type number
+ */
+const PRIMARY_SELECTION_DELAY = 100;
+
+/**
  * Predefined themes for syntax highlighting. This objects maps
  * SourceEditor.THEMES to Orion CSS files.
  */
 const ORION_THEMES = {
   mozilla: ["chrome://browser/skin/devtools/orion.css"],
 };
 
 /**
- * Known editor events you can listen for. This object maps SourceEditor.EVENTS
- * to Orion events.
+ * Known Orion editor events you can listen for. This object maps several of the
+ * SourceEditor.EVENTS to Orion events.
  */
 const ORION_EVENTS = {
   ContextMenu: "ContextMenu",
   TextChanged: "ModelChanged",
   Selection: "Selection",
   Focus: "Focus",
   Blur: "Blur",
   MouseOver: "MouseOver",
@@ -84,16 +94,19 @@ const ORION_EVENTS = {
 };
 
 /**
  * Known Orion annotation types.
  */
 const ORION_ANNOTATION_TYPES = {
   currentBracket: "orion.annotation.currentBracket",
   matchingBracket: "orion.annotation.matchingBracket",
+  breakpoint: "orion.annotation.breakpoint",
+  task: "orion.annotation.task",
+  currentLine: "orion.annotation.currentLine",
 };
 
 /**
  * Default key bindings in the Orion editor.
  */
 const DEFAULT_KEYBINDINGS = [
   {
     action: "undo",
@@ -122,40 +135,48 @@ var EXPORTED_SYMBOLS = ["SourceEditor"];
  *
  * The editor used here is Eclipse Orion (see http://www.eclipse.org/orion).
  *
  * @constructor
  */
 function SourceEditor() {
   // Update the SourceEditor defaults from user preferences.
 
-  SourceEditor.DEFAULTS.TAB_SIZE =
+  SourceEditor.DEFAULTS.tabSize =
     Services.prefs.getIntPref(SourceEditor.PREFS.TAB_SIZE);
-  SourceEditor.DEFAULTS.EXPAND_TAB =
+  SourceEditor.DEFAULTS.expandTab =
     Services.prefs.getBoolPref(SourceEditor.PREFS.EXPAND_TAB);
 
   this._onOrionSelection = this._onOrionSelection.bind(this);
 
+  this._eventTarget = {};
+  this._eventListenersQueue = [];
   this.ui = new SourceEditorUI(this);
 }
 
 SourceEditor.prototype = {
   _view: null,
   _iframe: null,
   _model: null,
   _undoStack: null,
   _linesRuler: null,
+  _annotationRuler: null,
+  _overviewRuler: null,
   _styler: null,
   _annotationStyler: null,
   _annotationModel: null,
   _dragAndDrop: null,
+  _currentLineAnnotation: null,
+  _primarySelectionTimeout: null,
   _mode: null,
   _expandTab: null,
   _tabSize: null,
   _iframeWindow: null,
+  _eventTarget: null,
+  _eventListenersQueue: null,
 
   /**
    * The Source Editor user interface manager.
    * @type object
    *       An instance of the SourceEditorUI.
    */
   ui: null,
 
@@ -166,40 +187,22 @@ SourceEditor.prototype = {
   parentElement: null,
 
   /**
    * Initialize the editor.
    *
    * @param nsIDOMElement aElement
    *        The DOM element where you want the editor to show.
    * @param object aConfig
-   *        Editor configuration object. Properties:
-   *          - placeholderText - the text you want to be shown by default.
-   *          - theme - the syntax highlighting theme you want. You can use one
-   *          of the predefined themes, or you can point to your CSS file.
-   *          - mode - the editor mode, based on the file type you want to edit.
-   *          You can use one of the predefined modes.
-   *          - tabSize - define how many spaces to use for a tab character.
-   *          - expandTab - tells if you want tab characters to be expanded to
-   *          spaces.
-   *          - readOnly - make the editor read only.
-   *          - showLineNumbers - display the line numbers gutter.
-   *          - undoLimit - how many steps should the undo stack hold.
-   *          - keys - is an array of objects that allows you to define custom
-   *          editor keyboard bindings. Each object can have:
-   *              - action - name of the editor action to invoke.
-   *              - code - keyCode for the shortcut.
-   *              - accel - boolean for the Accel key (cmd/ctrl).
-   *              - shift - boolean for the Shift key.
-   *              - alt - boolean for the Alt key.
-   *              - callback - optional function to invoke, if the action is not
-   *              predefined in the editor.
+   *        Editor configuration object. See SourceEditor.DEFAULTS for the
+   *        available configuration options.
    * @param function [aCallback]
    *        Function you want to execute once the editor is loaded and
    *        initialized.
+   * @see SourceEditor.DEFAULTS
    */
   init: function SE_init(aElement, aConfig, aCallback)
   {
     if (this._iframe) {
       throw new Error("SourceEditor is already initialized!");
     }
 
     let doc = aElement.ownerDocument;
@@ -213,17 +216,31 @@ SourceEditor.prototype = {
     }).bind(this);
 
     this._iframe.addEventListener("load", onIframeLoad, true);
 
     this._iframe.setAttribute("src", ORION_IFRAME);
 
     aElement.appendChild(this._iframe);
     this.parentElement = aElement;
-    this._config = aConfig;
+
+    this._config = {};
+    for (let key in SourceEditor.DEFAULTS) {
+      this._config[key] = key in aConfig ?
+                          aConfig[key] :
+                          SourceEditor.DEFAULTS[key];
+    }
+
+    // TODO: Bug 725677 - Remove the deprecated placeholderText option from the
+    // Source Editor initialization.
+    if (aConfig.placeholderText) {
+      this._config.initialText = aConfig.placeholderText;
+      Services.console.logStringMessage("SourceEditor.init() was called with the placeholderText option which is deprecated, please use initialText.");
+    }
+
     this._onReadyCallback = aCallback;
     this.ui.init();
   },
 
   /**
    * The editor iframe load event handler.
    * @private
    */
@@ -233,64 +250,97 @@ SourceEditor.prototype = {
     let window = this._iframeWindow;
     let config = this._config;
 
     Services.scriptloader.loadSubScript(ORION_SCRIPT, window, "utf8");
 
     let TextModel = window.require("orion/textview/textModel").TextModel;
     let TextView = window.require("orion/textview/textView").TextView;
 
-    this._expandTab = typeof config.expandTab != "undefined" ?
-                      config.expandTab : SourceEditor.DEFAULTS.EXPAND_TAB;
-    this._tabSize = config.tabSize || SourceEditor.DEFAULTS.TAB_SIZE;
+    this._expandTab = config.expandTab;
+    this._tabSize = config.tabSize;
 
-    let theme = config.theme || SourceEditor.DEFAULTS.THEME;
+    let theme = config.theme;
     let stylesheet = theme in ORION_THEMES ? ORION_THEMES[theme] : theme;
 
-    this._model = new TextModel(config.placeholderText);
+    this._model = new TextModel(config.initialText);
     this._view = new TextView({
       model: this._model,
       parent: "editor",
       stylesheet: stylesheet,
       tabSize: this._tabSize,
       expandTab: this._expandTab,
       readonly: config.readOnly,
       themeClass: "mozilla" + (config.readOnly ? " readonly" : ""),
     });
 
     let onOrionLoad = function() {
       this._view.removeEventListener("Load", onOrionLoad);
       this._onOrionLoad();
     }.bind(this);
 
     this._view.addEventListener("Load", onOrionLoad);
-    if (Services.appinfo.OS == "Linux") {
+    if (config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
       this._view.addEventListener("Selection", this._onOrionSelection);
     }
 
     let KeyBinding = window.require("orion/textview/keyBinding").KeyBinding;
     let TextDND = window.require("orion/textview/textDND").TextDND;
-    let LineNumberRuler = window.require("orion/textview/rulers").LineNumberRuler;
+    let Rulers = window.require("orion/textview/rulers");
+    let LineNumberRuler = Rulers.LineNumberRuler;
+    let AnnotationRuler = Rulers.AnnotationRuler;
+    let OverviewRuler = Rulers.OverviewRuler;
     let UndoStack = window.require("orion/textview/undoStack").UndoStack;
     let AnnotationModel = window.require("orion/textview/annotations").AnnotationModel;
 
     this._annotationModel = new AnnotationModel(this._model);
 
+    if (config.showAnnotationRuler) {
+      this._annotationRuler = new AnnotationRuler(this._annotationModel, "left",
+        {styleClass: "ruler annotations"});
+      this._annotationRuler.onClick = this._annotationRulerClick.bind(this);
+      this._annotationRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
+      this._annotationRuler.setMultiAnnotation({
+        html: "<div class='annotationHTML multiple'></div>"
+      });
+      this._annotationRuler.setMultiAnnotationOverlay({
+        html: "<div class='annotationHTML overlay'></div>"
+      });
+      this._view.addRuler(this._annotationRuler);
+    }
+
     if (config.showLineNumbers) {
+      let rulerClass = this._annotationRuler ?
+                       "ruler lines linesWithAnnotations" :
+                       "ruler lines";
+
       this._linesRuler = new LineNumberRuler(this._annotationModel, "left",
-        {styleClass: "rulerLines"}, {styleClass: "rulerLine odd"},
-        {styleClass: "rulerLine even"});
+        {styleClass: rulerClass}, {styleClass: "rulerLines odd"},
+        {styleClass: "rulerLines even"});
 
+      this._linesRuler.onClick = this._linesRulerClick.bind(this);
+      this._linesRuler.onDblClick = this._linesRulerDblClick.bind(this);
       this._view.addRuler(this._linesRuler);
     }
 
-    this.setMode(config.mode || SourceEditor.DEFAULTS.MODE);
+    if (config.showOverviewRuler) {
+      this._overviewRuler = new OverviewRuler(this._annotationModel, "right",
+        {styleClass: "ruler overview"});
+      this._overviewRuler.onClick = this._overviewRulerClick.bind(this);
 
-    this._undoStack = new UndoStack(this._view,
-      config.undoLimit || SourceEditor.DEFAULTS.UNDO_LIMIT);
+      this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
+      this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
+      this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
+      this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
+      this._view.addRuler(this._overviewRuler);
+    }
+
+    this.setMode(config.mode);
+
+    this._undoStack = new UndoStack(this._view, config.undoLimit);
 
     this._dragAndDrop = new TextDND(this._view, this._undoStack);
 
     let actions = {
       "undo": [this.undo, this],
       "redo": [this.redo, this],
       "tab": [this._doTab, this],
       "Unindent Lines": [this._doUnindentLines, this],
@@ -310,16 +360,53 @@ SourceEditor.prototype = {
     keys.forEach(function(aKey) {
       let binding = new KeyBinding(aKey.code, aKey.accel, aKey.shift, aKey.alt);
       this._view.setKeyBinding(binding, aKey.action);
 
       if (aKey.callback) {
         this._view.setAction(aKey.action, aKey.callback);
       }
     }, this);
+
+    this._initEventTarget();
+  },
+
+  /**
+   * Initialize the private Orion EventTarget object. This is used for tracking
+   * our own event listeners for events outside of Orion's scope.
+   * @private
+   */
+  _initEventTarget: function SE__initEventTarget()
+  {
+    let EventTarget =
+      this._iframeWindow.require("orion/textview/eventTarget").EventTarget;
+    EventTarget.addMixin(this._eventTarget);
+
+    this._eventListenersQueue.forEach(function(aRequest) {
+      if (aRequest[0] == "add") {
+        this.addEventListener(aRequest[1], aRequest[2]);
+      } else {
+        this.removeEventListener(aRequest[1], aRequest[2]);
+      }
+    }, this);
+
+    this._eventListenersQueue = [];
+  },
+
+  /**
+   * Dispatch an event to the SourceEditor event listeners. This covers only the
+   * SourceEditor-specific events.
+   *
+   * @private
+   * @param object aEvent
+   *        The event object to dispatch to all listeners.
+   */
+  _dispatchEvent: function SE__dispatchEvent(aEvent)
+  {
+    this._eventTarget.dispatchEvent(aEvent);
   },
 
   /**
    * The Orion "Load" event handler. This is called when the Orion editor
    * completes the initialization.
    * @private
    */
   _onOrionLoad: function SE__onOrionLoad()
@@ -469,35 +556,267 @@ SourceEditor.prototype = {
     }
 
     this.setText(this.getLineDelimiter() + prefix, selection.start,
                  selection.end);
     return true;
   },
 
   /**
-   * Orion Selection event handler for the X Window System users. This allows
-   * one to select text and have it copied into the X11 PRIMARY.
+   * The Orion Selection event handler. The current caret line is
+   * highlighted and for Linux users the selected text is copied into the X11
+   * PRIMARY buffer.
    *
    * @private
    * @param object aEvent
    *        The Orion Selection event object.
    */
   _onOrionSelection: function SE__onOrionSelection(aEvent)
   {
-    let text = this.getText(aEvent.newValue.start, aEvent.newValue.end);
+    if (this._config.highlightCurrentLine) {
+      this._highlightCurrentLine(aEvent);
+    }
+
+    if (Services.appinfo.OS == "Linux") {
+      let window = this.parentElement.ownerDocument.defaultView;
+
+      if (this._primarySelectionTimeout) {
+        window.clearTimeout(this._primarySelectionTimeout);
+      }
+      this._primarySelectionTimeout =
+        window.setTimeout(this._updatePrimarySelection.bind(this),
+                          PRIMARY_SELECTION_DELAY);
+    }
+  },
+
+  /**
+   * Update the X11 PRIMARY buffer to hold the current selection.
+   * @private
+   */
+  _updatePrimarySelection: function SE__updatePrimarySelection()
+  {
+    this._primarySelectionTimeout = null;
+
+    let text = this.getSelectedText();
     if (!text) {
       return;
     }
 
     clipboardHelper.copyStringToClipboard(text,
                                           Ci.nsIClipboard.kSelectionClipboard);
   },
 
   /**
+   * Highlight the current line using the Orion annotation model.
+   *
+   * @private
+   * @param object aEvent
+   *        The Selection event object.
+   */
+  _highlightCurrentLine: function SE__highlightCurrentLine(aEvent)
+  {
+    let annotationModel = this._annotationModel;
+    let model = this._model;
+    let oldAnnotation = this._currentLineAnnotation;
+    let newSelection = aEvent.newValue;
+
+    let collapsed = newSelection.start == newSelection.end;
+    if (!collapsed) {
+      if (oldAnnotation) {
+        annotationModel.removeAnnotation(oldAnnotation);
+        this._currentLineAnnotation = null;
+      }
+      return;
+    }
+
+    let line = model.getLineAtOffset(newSelection.start);
+    let lineStart = model.getLineStart(line);
+    let lineEnd = model.getLineEnd(line);
+
+    let title = oldAnnotation ? oldAnnotation.title :
+                SourceEditorUI.strings.GetStringFromName("annotation.currentLine");
+
+    this._currentLineAnnotation = {
+      start: lineStart,
+      end: lineEnd,
+      type: ORION_ANNOTATION_TYPES.currentLine,
+      title: title,
+      html: "<div class='annotationHTML currentLine'></div>",
+      overviewStyle: {styleClass: "annotationOverview currentLine"},
+      lineStyle: {styleClass: "annotationLine currentLine"},
+    };
+
+    annotationModel.replaceAnnotations(oldAnnotation ? [oldAnnotation] : null,
+                                       [this._currentLineAnnotation]);
+  },
+
+  /**
+   * The click event handler for the lines gutter. This function allows the user
+   * to jump to a line or to perform line selection while holding the Shift key
+   * down.
+   *
+   * @private
+   * @param number aLineIndex
+   *        The line index where the click event occurred.
+   * @param object aEvent
+   *        The DOM click event object.
+   */
+  _linesRulerClick: function SE__linesRulerClick(aLineIndex, aEvent)
+  {
+    if (aLineIndex === undefined) {
+      return;
+    }
+
+    if (aEvent.shiftKey) {
+      let model = this._model;
+      let selection = this.getSelection();
+      let selectionLineStart = model.getLineAtOffset(selection.start);
+      let selectionLineEnd = model.getLineAtOffset(selection.end);
+      let newStart = aLineIndex <= selectionLineStart ?
+                     model.getLineStart(aLineIndex) : selection.start;
+      let newEnd = aLineIndex <= selectionLineStart ?
+                   selection.end : model.getLineEnd(aLineIndex);
+      this.setSelection(newStart, newEnd);
+    } else {
+      this.setCaretPosition(aLineIndex);
+    }
+  },
+
+  /**
+   * The dblclick event handler for the lines gutter. This function selects the
+   * whole line where the event occurred.
+   *
+   * @private
+   * @param number aLineIndex
+   *        The line index where the double click event occurred.
+   * @param object aEvent
+   *        The DOM dblclick event object.
+   */
+  _linesRulerDblClick: function SE__linesRulerDblClick(aLineIndex)
+  {
+    if (aLineIndex === undefined) {
+      return;
+    }
+
+    let newStart = this._model.getLineStart(aLineIndex);
+    let newEnd = this._model.getLineEnd(aLineIndex);
+    this.setSelection(newStart, newEnd);
+  },
+
+  /**
+   * Highlight the Orion annotations. This updates the annotation styler as
+   * needed.
+   * @private
+   */
+  _highlightAnnotations: function SE__highlightAnnotations()
+  {
+    if (this._annotationStyler) {
+      this._annotationStyler.destroy();
+      this._annotationStyler = null;
+    }
+
+    let AnnotationStyler =
+      this._iframeWindow.require("orion/textview/annotations").AnnotationStyler;
+
+    let styler = new AnnotationStyler(this._view, this._annotationModel);
+    this._annotationStyler = styler;
+
+    styler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
+    styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
+    styler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
+
+    if (this._config.highlightCurrentLine) {
+      styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentLine);
+    }
+  },
+
+  /**
+   * Retrieve the list of Orion Annotations filtered by type for the given text range.
+   *
+   * @private
+   * @param string aType
+   *        The annotation type to filter annotations for.
+   * @param number aStart
+   *        Offset from where to start finding the annotations.
+   * @param number aEnd
+   *        End offset for retrieving the annotations.
+   * @return array
+   *         The array of annotations, filtered by type, within the given text
+   *         range.
+   */
+  _getAnnotationsByType: function SE__getAnnotationsByType(aType, aStart, aEnd)
+  {
+    let annotations = this._annotationModel.getAnnotations(aStart, aEnd);
+    let annotation, result = [];
+    while (annotation = annotations.next()) {
+      if (annotation.type == ORION_ANNOTATION_TYPES[aType]) {
+        result.push(annotation);
+      }
+    }
+
+    return result;
+  },
+
+  /**
+   * The click event handler for the annotation ruler.
+   *
+   * @private
+   * @param number aLineIndex
+   *        The line index where the click event occurred.
+   * @param object aEvent
+   *        The DOM click event object.
+   */
+  _annotationRulerClick: function SE__annotationRulerClick(aLineIndex, aEvent)
+  {
+    if (aLineIndex === undefined || aLineIndex == -1) {
+      return;
+    }
+
+    let lineStart = this._model.getLineStart(aLineIndex);
+    let lineEnd = this._model.getLineEnd(aLineIndex);
+    let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
+    if (annotations.length > 0) {
+      this.removeBreakpoint(aLineIndex);
+    } else {
+      this.addBreakpoint(aLineIndex);
+    }
+  },
+
+  /**
+   * The click event handler for the overview ruler. When the user clicks on an
+   * annotation the editor jumps to the associated line.
+   *
+   * @private
+   * @param number aLineIndex
+   *        The line index where the click event occurred.
+   * @param object aEvent
+   *        The DOM click event object.
+   */
+  _overviewRulerClick: function SE__overviewRulerClick(aLineIndex, aEvent)
+  {
+    if (aLineIndex === undefined || aLineIndex == -1) {
+      return;
+    }
+
+    let model = this._model;
+    let lineStart = model.getLineStart(aLineIndex);
+    let lineEnd = model.getLineEnd(aLineIndex);
+    let annotations = this._annotationModel.getAnnotations(lineStart, lineEnd);
+    let annotation = annotations.next();
+
+    // Jump to the line where annotation is. If the annotation is specific to
+    // a substring part of the line, then select the substring.
+    if (!annotation || lineStart == annotation.start && lineEnd == annotation.end) {
+      this.setSelection(lineStart, lineStart);
+    } else {
+      this.setSelection(annotation.start, annotation.end);
+    }
+  },
+
+  /**
    * Get the editor element.
    *
    * @return nsIDOMElement
    *         In this implementation a xul:iframe holds the editor.
    */
   get editorElement() {
     return this._iframe;
   },
@@ -507,63 +826,63 @@ SourceEditor.prototype = {
    *
    * @see SourceEditor.EVENTS
    *
    * @param string aEventType
    *        The event type you want to listen for.
    * @param function aCallback
    *        The function you want executed when the event is triggered.
    */
-  addEventListener:
-  function SE_addEventListener(aEventType, aCallback)
+  addEventListener: function SE_addEventListener(aEventType, aCallback)
   {
-    if (aEventType in ORION_EVENTS) {
+    if (this._view && aEventType in ORION_EVENTS) {
       this._view.addEventListener(ORION_EVENTS[aEventType], aCallback);
+    } else if (this._eventTarget.addEventListener) {
+      this._eventTarget.addEventListener(aEventType, aCallback);
     } else {
-      throw new Error("SourceEditor.addEventListener() unknown event " +
-                      "type " + aEventType);
+      this._eventListenersQueue.push(["add", aEventType, aCallback]);
     }
   },
 
   /**
    * Remove an event listener from the editor. You can use one of the known
    * events.
    *
    * @see SourceEditor.EVENTS
    *
    * @param string aEventType
    *        The event type you have a listener for.
    * @param function aCallback
    *        The function you have as the event handler.
    */
-  removeEventListener:
-  function SE_removeEventListener(aEventType, aCallback)
+  removeEventListener: function SE_removeEventListener(aEventType, aCallback)
   {
-    if (aEventType in ORION_EVENTS) {
+    if (this._view && aEventType in ORION_EVENTS) {
       this._view.removeEventListener(ORION_EVENTS[aEventType], aCallback);
+    } else if (this._eventTarget.removeEventListener) {
+      this._eventTarget.removeEventListener(aEventType, aCallback);
     } else {
-      throw new Error("SourceEditor.removeEventListener() unknown event " +
-                      "type " + aEventType);
+      this._eventListenersQueue.push(["remove", aEventType, aCallback]);
     }
   },
 
   /**
    * Undo a change in the editor.
    */
   undo: function SE_undo()
   {
-    this._undoStack.undo();
+    return this._undoStack.undo();
   },
 
   /**
    * Redo a change in the editor.
    */
   redo: function SE_redo()
   {
-    this._undoStack.redo();
+    return this._undoStack.redo();
   },
 
   /**
    * Check if there are changes that can be undone.
    *
    * @return boolean
    *         True if there are changes that can be undone, false otherwise.
    */
@@ -836,54 +1155,40 @@ SourceEditor.prototype = {
    *        One of the predefined SourceEditor.MODES.
    */
   setMode: function SE_setMode(aMode)
   {
     if (this._styler) {
       this._styler.destroy();
       this._styler = null;
     }
-    if (this._annotationStyler) {
-      this._annotationStyler.destroy();
-      this._annotationStyler = null;
-    }
 
     let window = this._iframeWindow;
 
     switch (aMode) {
       case SourceEditor.MODES.JAVASCRIPT:
       case SourceEditor.MODES.CSS:
         let TextStyler =
           window.require("examples/textview/textStyler").TextStyler;
 
         this._styler = new TextStyler(this._view, aMode, this._annotationModel);
         this._styler.setFoldingEnabled(false);
-        this._styler.setHighlightCaretLine(true);
-
-        let AnnotationStyler =
-          window.require("orion/textview/annotations").AnnotationStyler;
-
-        this._annotationStyler =
-          new AnnotationStyler(this._view, this._annotationModel);
-        this._annotationStyler.
-          addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
-        this._annotationStyler.
-          addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
         break;
 
       case SourceEditor.MODES.HTML:
       case SourceEditor.MODES.XML:
         let TextMateStyler =
           window.require("orion/editor/textMateStyler").TextMateStyler;
         let HtmlGrammar =
           window.require("orion/editor/htmlGrammar").HtmlGrammar;
-        this._styler = new TextMateStyler(this._view, new HtmlGrammar().grammar);
+        this._styler = new TextMateStyler(this._view, new HtmlGrammar());
         break;
     }
 
+    this._highlightAnnotations();
     this._mode = aMode;
   },
 
   /**
    * Get the current source editor mode.
    *
    * @return string
    *         Returns one of the predefined SourceEditor.MODES.
@@ -911,37 +1216,148 @@ SourceEditor.prototype = {
    * @type boolean
    */
   get readOnly()
   {
     return this._view.getOptions("readonly");
   },
 
   /**
+   * Add a breakpoint at the given line index.
+   *
+   * @param number aLineIndex
+   *        Line index where to add the breakpoint (starts from 0).
+   * @param string [aCondition]
+   *        Optional breakpoint condition.
+   */
+  addBreakpoint: function SE_addBreakpoint(aLineIndex, aCondition)
+  {
+    let lineStart = this._model.getLineStart(aLineIndex);
+    let lineEnd = this._model.getLineEnd(aLineIndex);
+
+    let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
+    if (annotations.length > 0) {
+      return;
+    }
+
+    let lineText = this._model.getLine(aLineIndex);
+    let title = SourceEditorUI.strings.
+                formatStringFromName("annotation.breakpoint.title",
+                                     [lineText], 1);
+
+    let annotation = {
+      type: ORION_ANNOTATION_TYPES.breakpoint,
+      start: lineStart,
+      end: lineEnd,
+      breakpointCondition: aCondition,
+      title: title,
+      style: {styleClass: "annotation breakpoint"},
+      html: "<div class='annotationHTML breakpoint'></div>",
+      overviewStyle: {styleClass: "annotationOverview breakpoint"},
+      rangeStyle: {styleClass: "annotationRange breakpoint"}
+    };
+    this._annotationModel.addAnnotation(annotation);
+
+    let event = {
+      type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
+      added: [{line: aLineIndex, condition: aCondition}],
+      removed: [],
+    };
+
+    this._dispatchEvent(event);
+  },
+
+  /**
+   * Remove the current breakpoint from the given line index.
+   *
+   * @param number aLineIndex
+   *        Line index from where to remove the breakpoint (starts from 0).
+   * @return boolean
+   *         True if a breakpoint was removed, false otherwise.
+   */
+  removeBreakpoint: function SE_removeBreakpoint(aLineIndex)
+  {
+    let lineStart = this._model.getLineStart(aLineIndex);
+    let lineEnd = this._model.getLineEnd(aLineIndex);
+
+    let event = {
+      type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
+      added: [],
+      removed: [],
+    };
+
+    let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
+
+    annotations.forEach(function(annotation) {
+      this._annotationModel.removeAnnotation(annotation);
+      event.removed.push({line: aLineIndex,
+                          condition: annotation.breakpointCondition});
+    }, this);
+
+    if (event.removed.length > 0) {
+      this._dispatchEvent(event);
+    }
+
+    return event.removed.length > 0;
+  },
+
+  /**
+   * Get the list of breakpoints in the Source Editor instance.
+   *
+   * @return array
+   *         The array of breakpoints. Each item is an object with two
+   *         properties: line and condition.
+   */
+  getBreakpoints: function SE_getBreakpoints()
+  {
+    let annotations = this._getAnnotationsByType("breakpoint", 0,
+                                                 this.getCharCount());
+    let breakpoints = [];
+
+    annotations.forEach(function(annotation) {
+      breakpoints.push({line: this._model.getLineAtOffset(annotation.start),
+                        condition: annotation.breakpointCondition});
+    }, this);
+
+    return breakpoints;
+  },
+
+  /**
    * Destroy/uninitialize the editor.
    */
   destroy: function SE_destroy()
   {
-    if (Services.appinfo.OS == "Linux") {
+    if (this._config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
       this._view.removeEventListener("Selection", this._onOrionSelection);
     }
     this._onOrionSelection = null;
 
+    if (this._primarySelectionTimeout) {
+      let window = this.parentElement.ownerDocument.defaultView;
+      window.clearTimeout(this._primarySelectionTimeout);
+      this._primarySelectionTimeout = null;
+    }
+
     this._view.destroy();
     this.ui.destroy();
     this.ui = null;
 
     this.parentElement.removeChild(this._iframe);
     this.parentElement = null;
     this._iframeWindow = null;
     this._iframe = null;
     this._undoStack = null;
     this._styler = null;
     this._linesRuler = null;
+    this._annotationRuler = null;
+    this._overviewRuler = null;
     this._dragAndDrop = null;
     this._annotationModel = null;
     this._annotationStyler = null;
+    this._currentLineAnnotation = null;
+    this._eventTarget = null;
+    this._eventListenersQueue = null;
     this._view = null;
     this._model = null;
     this._config = null;
     this._lastFind = null;
   },
 };
--- a/browser/devtools/sourceeditor/source-editor.jsm
+++ b/browser/devtools/sourceeditor/source-editor.jsm
@@ -101,23 +101,109 @@ SourceEditor.MODES = {
  * Predefined themes for syntax highlighting.
  */
 SourceEditor.THEMES = {
   MOZILLA: "mozilla",
 };
 
 /**
  * Source editor configuration defaults.
+ * @see SourceEditor.init
  */
 SourceEditor.DEFAULTS = {
-  MODE: SourceEditor.MODES.TEXT,
-  THEME: SourceEditor.THEMES.MOZILLA,
-  UNDO_LIMIT: 200,
-  TAB_SIZE: 4, // overriden by pref
-  EXPAND_TAB: true, // overriden by pref
+  /**
+   * The text you want shown when the editor opens up.
+   * @type string
+   */
+  initialText: "",
+
+  /**
+   * The editor mode, based on the file type you want to edit. You can use one of
+   * the predefined modes.
+   *
+   * @see SourceEditor.MODES
+   * @type string
+   */
+  mode: SourceEditor.MODES.TEXT,
+
+  /**
+   * The syntax highlighting theme you want. You can use one of the predefined
+   * themes, or you can point to your CSS file.
+   *
+   * @see SourceEditor.THEMES.
+   * @type string
+   */
+  theme: SourceEditor.THEMES.MOZILLA,
+
+  /**
+   * How many steps should the undo stack hold.
+   * @type number
+   */
+  undoLimit: 200,
+
+  /**
+   * Define how many spaces to use for a tab character. This value is overridden
+   * by a user preference, see SourceEditor.PREFS.TAB_SIZE.
+   *
+   * @type number
+   */
+  tabSize: 4,
+
+  /**
+   * Tells if you want tab characters to be expanded to spaces. This value is
+   * overridden by a user preference, see SourceEditor.PREFS.EXPAND_TAB.
+   * @type boolean
+   */
+  expandTab: true,
+
+  /**
+   * Tells if you want the editor to be read only or not.
+   * @type boolean
+   */
+  readOnly: false,
+
+  /**
+   * Display the line numbers gutter.
+   * @type boolean
+   */
+  showLineNumbers: false,
+
+  /**
+   * Display the annotations gutter/ruler. This gutter currently supports
+   * annotations of breakpoint type.
+   * @type boolean
+   */
+  showAnnotationRuler: false,
+
+  /**
+   * Display the overview gutter/ruler. This gutter presents an overview of the
+   * current annotations in the editor, for example the breakpoints.
+   * @type boolean
+   */
+  showOverviewRuler: false,
+
+  /**
+   * Highlight the current line.
+   * @type boolean
+   */
+  highlightCurrentLine: true,
+
+  /**
+   * An array of objects that allows you to define custom editor keyboard
+   * bindings. Each object can have:
+   *   - action - name of the editor action to invoke.
+   *   - code - keyCode for the shortcut.
+   *   - accel - boolean for the Accel key (Cmd on Macs, Ctrl on Linux/Windows).
+   *   - shift - boolean for the Shift key.
+   *   - alt - boolean for the Alt key.
+   *   - callback - optional function to invoke, if the action is not predefined
+   *   in the editor.
+   * @type array
+   */
+  keys: null,
 };
 
 /**
  * Known editor events you can listen for.
  */
 SourceEditor.EVENTS = {
   /**
    * The contextmenu event is fired when the editor context menu is invoked. The
@@ -180,16 +266,27 @@ SourceEditor.EVENTS = {
 
   /**
    * This MouseOut event is sent when the mouse pointer exits a line
    * annotation. The event object properties:
    *   - event - the DOM mouseout event object.
    *   - x and y - the mouse coordinates relative to the document being edited.
    */
   MOUSE_OUT: "MouseOut",
+
+  /**
+   * The BreakpointChange event is fired when a new breakpoint is added or when
+   * a breakpoint is removed - either through API use or through the editor UI.
+   * Event object properties:
+   *   - added - array that holds the new breakpoints.
+   *   - removed - array that holds the breakpoints that have been removed.
+   * Each object in the added/removed arrays holds two properties: line and
+   * condition.
+   */
+  BREAKPOINT_CHANGE: "BreakpointChange",
 };
 
 /**
  * Extend a destination object with properties from a source object.
  *
  * @param object aDestination
  * @param object aSource
  */
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -51,12 +51,14 @@ include $(topsrcdir)/config/rules.mk
 		browser_bug687568_pagescroll.js \
 		browser_bug687580_drag_and_drop.js \
 		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		browser_bug650345_find.js \
 		browser_bug703692_focus_blur.js \
 		browser_bug725388_mouse_events.js \
+		browser_bug707987_debugger_breakpoints.js \
+		browser_bug712982_line_ruler_click.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/sourceeditor/test/browser_bug687573_vscroll.js
+++ b/browser/devtools/sourceeditor/test/browser_bug687573_vscroll.js
@@ -43,17 +43,17 @@ function initEditor()
              "abbaabbaabbaabbaabbaabbaabbaabbaabbaabba\n" +
              "abbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba\n" +
              "abbaabbaabbaabbaabbaabbaabbaabbaabbaabba\n" +
              "\n" +
              "abba\n";
 
   let config = {
     showLineNumbers: true,
-    placeholderText: text,
+    initialText: text,
   };
 
   editor = new SourceEditor();
   editor.init(box, config, editorLoaded);
 }
 
 function editorLoaded()
 {
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug707987_debugger_breakpoints.js
@@ -0,0 +1,169 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+
+  let temp = {};
+  Cu.import("resource:///modules/source-editor.jsm", temp);
+  let SourceEditor = temp.SourceEditor;
+
+  let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT);
+  if (component == "textarea") {
+    ok(true, "skip test for bug 707987: only applicable for non-textarea components");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  let editor;
+
+  const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 707987' width='600' height='500'><hbox flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  let testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+
+  function initEditor()
+  {
+    let hbox = testWin.document.querySelector("hbox");
+    editor = new SourceEditor();
+    editor.init(hbox, {showAnnotationRuler: true}, editorLoaded);
+  }
+
+  function editorLoaded()
+  {
+    editor.focus();
+
+    editor.setText("line1\nline2\nline3\nline4");
+
+    is(editor.getBreakpoints().length, 0, "no breakpoints");
+
+    let event = null;
+    let eventHandler = function(aEvent) {
+      event = aEvent;
+    };
+    editor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, eventHandler);
+
+    // Add breakpoint at line 0
+
+    editor.addBreakpoint(0);
+
+    let breakpoints = editor.getBreakpoints();
+    is(breakpoints.length, 1, "one breakpoint added");
+    is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
+    ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
+
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 1, "one breakpoint added (confirmed)");
+    is(event.removed.length, 0, "no breakpoint removed");
+    is(event.added[0].line, 0, "event added[0].line is correct");
+    ok(!event.added[0].condition, "event added[0].condition is correct");
+
+    // Add breakpoint at line 3
+
+    event = null;
+    editor.addBreakpoint(3, "foo == 'bar'");
+
+    breakpoints = editor.getBreakpoints();
+    is(breakpoints.length, 2, "another breakpoint added");
+    is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
+    ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
+    is(breakpoints[1].line, 3, "breakpoint[1].line is correct");
+    is(breakpoints[1].condition, "foo == 'bar'",
+       "breakpoint[1].condition is correct");
+
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 1, "another breakpoint added (confirmed)");
+    is(event.removed.length, 0, "no breakpoint removed");
+    is(event.added[0].line, 3, "event added[0].line is correct");
+    is(event.added[0].condition, "foo == 'bar'",
+       "event added[0].condition is correct");
+
+    // Try to add another breakpoint at line 0
+
+    event = null;
+    editor.addBreakpoint(0);
+
+    is(editor.getBreakpoints().length, 2, "no breakpoint added");
+    is(event, null, "no breakpoint event fired");
+
+    // Try to remove a breakpoint from line 1
+
+    is(editor.removeBreakpoint(1), false, "removeBreakpoint(1) returns false");
+    is(editor.getBreakpoints().length, 2, "no breakpoint removed");
+    is(event, null, "no breakpoint event fired");
+
+    // Remove the breakpoint from line 0
+
+    is(editor.removeBreakpoint(0), true, "removeBreakpoint(0) returns true");
+
+    breakpoints = editor.getBreakpoints();
+    is(breakpoints[0].line, 3, "breakpoint[0].line is correct");
+    is(breakpoints[0].condition, "foo == 'bar'",
+       "breakpoint[0].condition is correct");
+
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 0, "no breakpoint added");
+    is(event.removed.length, 1, "one breakpoint removed");
+    is(event.removed[0].line, 0, "event removed[0].line is correct");
+    ok(!event.removed[0].condition, "event removed[0].condition is correct");
+
+    // Remove the breakpoint from line 3
+
+    event = null;
+    is(editor.removeBreakpoint(3), true, "removeBreakpoint(3) returns true");
+
+    is(editor.getBreakpoints().length, 0, "no breakpoints");
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 0, "no breakpoint added");
+    is(event.removed.length, 1, "one breakpoint removed");
+    is(event.removed[0].line, 3, "event removed[0].line is correct");
+    is(event.removed[0].condition, "foo == 'bar'",
+       "event removed[0].condition is correct");
+
+    // Add a breakpoint with the mouse
+
+    event = null;
+    EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
+
+    breakpoints = editor.getBreakpoints();
+    is(breakpoints.length, 1, "one breakpoint added");
+    is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
+    ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
+
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 1, "one breakpoint added (confirmed)");
+    is(event.removed.length, 0, "no breakpoint removed");
+    is(event.added[0].line, 0, "event added[0].line is correct");
+    ok(!event.added[0].condition, "event added[0].condition is correct");
+
+    // Remove a breakpoint with the mouse
+
+    event = null;
+    EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
+
+    breakpoints = editor.getBreakpoints();
+    is(breakpoints.length, 0, "one breakpoint removed");
+
+    ok(event, "breakpoint event fired");
+    is(event.added.length, 0, "no breakpoint added");
+    is(event.removed.length, 1, "one breakpoint removed (confirmed)");
+    is(event.removed[0].line, 0, "event removed[0].line is correct");
+    ok(!event.removed[0].condition, "event removed[0].condition is correct");
+
+    editor.destroy();
+
+    testWin.close();
+    testWin = editor = null;
+
+    waitForFocus(finish, window);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug712982_line_ruler_click.js
@@ -0,0 +1,74 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function test() {
+
+  let temp = {};
+  Cu.import("resource:///modules/source-editor.jsm", temp);
+  let SourceEditor = temp.SourceEditor;
+
+  let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT);
+  if (component == "textarea") {
+    ok(true, "skip test for bug 712982: only applicable for non-textarea components");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  let editor;
+
+  const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 712982' width='600' height='500'><hbox flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  let testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+
+  function initEditor()
+  {
+    let hbox = testWin.document.querySelector("hbox");
+    editor = new SourceEditor();
+    editor.init(hbox, {showLineNumbers: true}, editorLoaded);
+  }
+
+  function editorLoaded()
+  {
+    editor.focus();
+
+    editor.setText("line1\nline2\nline3\nline4");
+
+    editor.setCaretPosition(3);
+    let pos = editor.getCaretPosition();
+    ok(pos.line == 3 && pos.col == 0, "initial caret location is correct");
+
+    EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
+
+    is(editor.getCaretOffset(), 0, "click on line 0 worked");
+
+    editor.setCaretPosition(2);
+    EventUtils.synthesizeMouse(editor.editorElement, 11, 11,
+                               {shiftKey: true}, testWin);
+    is(editor.getSelectedText().trim(), "line1\nline2", "shift+click works");
+
+    editor.setCaretOffset(0);
+
+    EventUtils.synthesizeMouse(editor.editorElement, 10, 10,
+                               {clickCount: 2}, testWin);
+
+    is(editor.getSelectedText().trim(), "line1", "double click works");
+
+    editor.destroy();
+
+    testWin.close();
+    testWin = editor = null;
+
+    waitForFocus(finish, window);
+  }
+}
--- a/browser/devtools/sourceeditor/test/browser_bug725388_mouse_events.js
+++ b/browser/devtools/sourceeditor/test/browser_bug725388_mouse_events.js
@@ -32,59 +32,69 @@ function initEditor()
   let hbox = testWin.document.querySelector("hbox");
 
   editor = new SourceEditor();
   editor.init(hbox, {}, editorLoaded);
 }
 
 function editorLoaded()
 {
+  editor.focus();
+  testWin.resizeBy(1, 2);
+
   let text = "BrowserBug - 725388";
   editor.setText(text);
 
   let target = editor.editorElement;
   let targetWin = target.ownerDocument.defaultView;
 
+  let eventsFired = 0;
+
+  let done = function() {
+    eventsFired++;
+    if (eventsFired == 3) {
+      executeSoon(testEnd);
+    }
+  };
+
   let mMoveHandler = function(aEvent) {
     editor.removeEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
 
     is(aEvent.event.type, "mousemove", "MouseMove event fired.");
 
-    editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
-    waitForFocus(function() {
-      EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
-                                 targetWin);
-    });
+    executeSoon(done);
   };
 
   let mOverHandler = function(aEvent) {
     editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
 
     is(aEvent.event.type, "mouseover", "MouseOver event fired.");
 
-    editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
-    waitForFocus(function() {
-      EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
-                                 targetWin);
-    }, targetWin);
+    executeSoon(done);
   };
 
   let mOutHandler = function(aEvent) {
     editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
 
     is(aEvent.event.type, "mouseout", "MouseOut event fired.");
-    executeSoon(testEnd);
+
+    executeSoon(done);
   };
 
+  editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
   editor.addEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
+  editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
 
-  editor.focus();
   waitForFocus(function() {
-  EventUtils.synthesizeMouse(target, 1, 1, {type: "mousemove"},
-                             targetWin);
+    EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
+                               targetWin);
+    EventUtils.synthesizeMouse(target, 15, 17, {type: "mousemove"},
+                               targetWin);
+    EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
+                               targetWin);
   }, targetWin);
 }
 
 function testEnd()
 {
   if (editor) {
     editor.destroy();
   }
--- a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
+++ b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js
@@ -32,34 +32,34 @@ function initEditor()
 {
   testDoc = testWin.document;
 
   let hbox = testDoc.querySelector("hbox");
 
   editor = new SourceEditor();
   let config = {
     showLineNumbers: true,
-    placeholderText: "foobarbaz",
+    initialText: "foobarbaz",
     tabSize: 7,
     expandTab: true,
   };
 
   editor.init(hbox, config, editorLoaded);
 }
 
 function editorLoaded()
 {
   ok(editor.editorElement, "editor loaded");
 
   is(editor.parentElement, testDoc.querySelector("hbox"),
      "parentElement is correct");
 
   editor.focus();
 
-  is(editor.getMode(), SourceEditor.DEFAULTS.MODE, "default editor mode");
+  is(editor.getMode(), SourceEditor.DEFAULTS.mode, "default editor mode");
 
   // Test general editing methods.
 
   ok(!editor.canUndo(), "canUndo() works (nothing to undo), just loaded");
 
   ok(!editor.readOnly, "editor is not read-only");
 
   is(editor.getText(), "foobarbaz", "placeholderText works");
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -217,17 +217,17 @@ StyleEditor.prototype = {
     // attach to new input element
     this.window.addEventListener("unload", this._onWindowUnloadBinding, false);
     this._focusOnSourceEditorReady = false;
 
     this._sourceEditor = null; // set it only when ready (safe to use)
 
     let sourceEditor = new SourceEditor();
     let config = {
-      placeholderText: this._state.text, //! this is initialText (bug 680371)
+      initialText: this._state.text,
       showLineNumbers: true,
       mode: SourceEditor.MODES.CSS,
       readOnly: this._state.readOnly,
       keys: this._getKeyBindings()
     };
 
     sourceEditor.init(aElement, config, function onSourceEditorReady() {
       setupBracketCompletion(sourceEditor);
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -374,16 +374,18 @@
 @BINPATH@/components/nsInputListAutoComplete.js
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
+@BINPATH@/components/SmsDatabaseService.manifest
+@BINPATH@/components/SmsDatabaseService.js
 @BINPATH@/components/nsWifiWorker.js
 @BINPATH@/components/nsWifiWorker.manifest
 #endif
 @BINPATH@/components/BrowserProfileMigrators.manifest
 @BINPATH@/components/ChromeProfileMigrator.js
 @BINPATH@/components/FirefoxProfileMigrator.js
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts.dylib
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd
@@ -116,16 +116,28 @@
   -  to select an execution environment for the browser window itself as opposed
   -  to content. This is a feature for browser and addon developers and only
   -  enabled via the devtools.chrome.enabled preference. Formerly, this label
   -  was called "Chrome".
   -->
 <!ENTITY browserContext.label         "Browser">
 <!ENTITY browserContext.accesskey     "B">
 
+<!-- LOCALIZATION NOTE some localizations of Windows (ex:french, german) use "?"
+  -  for the help button in the menubar but Gnome does not.
+  -->
+<!ENTITY helpMenu.label               "Help">
+<!ENTITY helpMenu.accesskey           "H">
+<!ENTITY helpMenuWin.label            "Help">
+<!ENTITY helpMenuWin.accesskey        "H">
+
+<!ENTITY documentationLink.label      "Scratchpad Help on MDN">
+<!ENTITY documentationLink.accesskey  "D">
+
+
 <!-- LOCALIZATION NOTE (resetContext2.label): This command allows the developer
   -  to reset/clear the global object of the environment where the code executes.
   -->
 <!ENTITY resetContext2.label          "Reset Variables">
 <!ENTITY resetContext2.accesskey      "T">
 
 <!ENTITY executeMenu.label            "Execute">
 <!ENTITY executeMenu.accesskey        "X">
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -49,8 +49,12 @@ confirmClose.title=Unsaved Changes
 # LOCALIZATION NOTE  (scratchpadIntro): This is a multi-line comment explaining
 # how to use the Scratchpad. Note that this should be a valid JavaScript
 # comment inside /* and */.
 scratchpadIntro=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaScript, then Right Click or choose from the Execute Menu:\n * 1. Run to evaluate the selected text,\n * 2. Inspect to bring up an Object Inspector on the result, or,\n * 3. Display to insert the result in a comment after the selection.\n */\n\n
 
 # LOCALIZATION NOTE  (notification.browserContext): This is the message displayed
 # over the top of the editor when the user has switched to browser context.
 browserContext.notification=This scratchpad executes in the Browser context.
+
+# LOCALIZATION NOTE (help.openDocumentationPage): This returns a localized link with
+# documentation for Scratchpad on MDN.
+help.openDocumentationPage=https://developer.mozilla.org/en/Tools/Scratchpad
--- a/browser/locales/en-US/chrome/browser/devtools/sourceeditor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.properties
@@ -23,8 +23,18 @@ findCmd.promptMessage=Search for:
 # when the user wants to jump to a specific line number in the code. You can
 # access this feature by pressing Ctrl-J on Windows/Linux or Cmd-J on Mac.
 gotoLineCmd.promptTitle=Go to line…
 
 # LOCALIZATION NOTE  (gotoLineCmd.promptMessage): This is the message shown when
 # the user wants to jump to a specific line number in the code. You can
 # access this feature by pressing Ctrl-J on Windows/Linux or Cmd-J on Mac.
 gotoLineCmd.promptMessage=Jump to line number:
+
+# LOCALIZATION NOTE  (annotation.breakpoint.title): This is the text shown in
+# front of any breakpoint annotation when it is displayed as a tooltip in one of
+# the editor gutters. This feature is used in the JavaScript Debugger.
+annotation.breakpoint.title=Breakpoint: %S
+
+# LOCALIZATION NOTE  (annotation.currentLine): This is the text shown in
+# a tooltip displayed in any of the editor gutters when the user hovers the
+# current line.
+annotation.currentLine=Current line
--- a/browser/locales/en-US/chrome/browser/syncSetup.dtd
+++ b/browser/locales/en-US/chrome/browser/syncSetup.dtd
@@ -7,17 +7,17 @@
 <!ENTITY button.haveAccount.label      "I Have an Account">
 
 <!ENTITY setup.choicePage.title.label     "Have you used &syncBrand.fullName.label; before?">
 <!ENTITY setup.choicePage.new.label       "I've never used &syncBrand.shortName.label; before">
 <!ENTITY setup.choicePage.existing.label  "I'm already using &syncBrand.shortName.label; on another computer">
 
 <!-- New Account AND Existing Account -->
 <!ENTITY server.label               "Server">
-<!ENTITY serverType.main.label      "&syncBrand.fullName.label; Server">
+<!ENTITY serverType.default.label      "Default: Mozilla &syncBrand.fullName.label; server">
 <!ENTITY serverType.custom2.label   "Use a custom server…">
 <!ENTITY signIn.account2.label      "Account">
 <!ENTITY signIn.account2.accesskey  "A">
 <!ENTITY signIn.password.label      "Password">
 <!ENTITY signIn.password.accesskey  "P">
 <!ENTITY signIn.recoveryKey.label       "Recovery Key">
 <!ENTITY signIn.recoveryKey.accesskey   "K">
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..85f73d972841e7266223899044cc7fcd38552844
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS0006hNkl<ZIE|%~Pfrt36vcm2+i9V+H2q6uYN5t1s0tx0j0uUNF)nb&mvGJA
zh5N=OU&5UbjSDwyG#Hg=jOkEHaV$)yQ|Leo9cZ76+JZJ3qi6YYa^AW3oGS?-_#Zfb
zeJE<Wc={|yVN;{FZv!wKkQq-YEIde)RASP3zI5I}c4<}QRE=8;nZBP&YMH_(gYlHY
z;=@^~PawOrD$1t8<r~T$E$3frL_?9Dh_h=ur)pfgqhLEA=pA5Wc!==OAOMxa2D`OG
zs`VohHx)iE=P7EsNGdT&5<-w&S`~XoHM|KAVZWELXo#2Zwpf0<3BdeJihI*zY?Vza
zRviGj;%4#TtmFj9sT!jhA1Br^Bk?HD-{g6+{Jv-V%hxKclNPtHj<Tbf0BorS0FExH
zUNNaxOo9V0R@OH9W?xy`AUNRa@fru6gq#4DX@lGZz;3o^xBI)%ZVT*Yi~YS0@6>jm
zIdIBw>Tq-FaI>vj%w-aN0&|%J+q%``Ic3fqOiicwW*E3UU{)K<&s@PHyLhp_4Z!`$
zOWeIahMM0c9uCo{+Kf&|fFC_5YPxuweMLOsqtUjBh5U?P3=)qF1F&P%D3q$`rbS@T
zPf;~^v^YmniFHy)Dlusyt%yR&AR70hmyglQC7|@v7y+N3@{YwsTIp4~ugafu8sUf!
zZ@`1s-C0z<*`&UIOvN~0BK?~xchNnj59=DVI#F>!W@_>;j_F_U9rBU^VLv*CRsaA1
M07*qoM6N<$g4fs>mH+?%
new file mode 100644
--- /dev/null
+++ b/browser/themes/gnomestripe/devtools/orion-container.css
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.viewTooltip {
+  display: none; /* TODO: add tooltips support, see bug 721752 */
+  font-family: monospace;
+  font-size: 13px;
+  background-color: InfoBackground;
+  color: InfoText;
+  padding: 2px;
+  border-radius: 4px;
+  border: 1px solid black;
+  z-index: 100;
+  position: fixed;
+  overflow: hidden;
+  white-space: pre;
+}
+
+.viewTooltip em {
+  font-style: normal;
+  font-weight: bold;
+}
+
+.annotationHTML {
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.annotationHTML.task {
+  background-image: url("chrome://browser/skin/devtools/orion-task.png");
+}
+.annotationHTML.breakpoint {
+  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..42dbc00b655fffeae488cc2241d97407977f6dec
GIT binary patch
literal 413
zc$@*90b>4%P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00040Nkl<ZIE|%~u}i~16vn@pq%A@Qrwm#9F9;&tTwLl9kf07-L_ra;gU}&J
z5eYchMTBm4P%DKFI=Occ{1*xi(xHPm6eO3s%Q@wm*hB+;@WH)1zTdsayHkV^m?yMo
zF&I9H`?t$nrtRfZRLUC)04Pxf2M-ldURuco7=FFtW^14%DhRni!2Dc*kWbs50+;~#
z2e7+#0n0G4ce^?Z;4}oG-<jsa^%g9{#Aq@Gr{OGs{Q;;~+tPgXybl%wEJ#2Qf>0mz
zY8!<5QgO4_uYph>EXV*f><%o$M8obN;J(a9lQEh-2LbmH@C*Pa9B$XfXflRnm^j;f
zlxDYUgK;Xw2~V#;Q*|_Zj)X)vYpR}5W(x(igo0Xv*RSFI^8;SLCimis0}^8_>Lqz_
z{c@DZ<B>5&fug>cYWN+Dro6;sr-{~`n+tHVb1v7)yx;i;N{ha1Q$r5E00000NkvXX
Hu0mjf2D_^v
--- a/browser/themes/gnomestripe/devtools/orion.css
+++ b/browser/themes/gnomestripe/devtools/orion.css
@@ -6,38 +6,103 @@
   background: #cddae5; /* This will be seen as the continuation of the ruler */
   font-family: monospace;
   font-size: inherit; /* inherit browser's default monospace font size */
 }
 
 .view {
   color: black; /* Default text color */
   background: #f0f0ff; /* Background of the editor */
-  padding-left: 0;
+  padding-left: 4px;
 }
 
 .readonly > .view {
   background: #f0f0ff;
 }
 
-/* One line */
-.viewContent > div {
-  padding-left: 4px; /* Margin between the ruler and the editor */
-}
-
-/* Styles for the line number ruler */
-.rulerLines {
-  border-right: 1px solid #b4c4d3;
+.ruler {
   background: #cddae5;
   color: #7a8a99;
+}
+.ruler.annotations {
+  width: 16px;
+  padding-left: 4px;
+}
+.ruler.lines {
+  border-right: 1px solid #b4c4d3;
+  min-width: 1.4em;
   padding-left: 4px;
   padding-right: 4px;
   text-align: end;
 }
 
+.ruler.linesWithAnnotations {
+  min-width: 0;
+  padding-left: 0;
+}
+
+.ruler.overview {
+  border-left: 1px solid #b4c4d3;
+  width: 14px;
+  text-align: start;
+}
+
+/* Styles for the annotation ruler (first line) */
+.annotationHTML {
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.annotationHTML.task {
+  background-image: url("chrome://browser/skin/devtools/orion-task.png");
+}
+.annotationHTML.breakpoint {
+  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+}
+
+/* Styles for the overview ruler  */
+.annotationOverview {
+  cursor: pointer;
+  border-radius: 2px;
+  left: 2px;
+  width: 8px;
+}
+.annotationOverview.task {
+  background-color: lightgreen;
+  border: 1px solid green;
+}
+.annotationOverview.breakpoint {
+  background-color: lightblue;
+  border: 1px solid blue;
+}
+.annotationOverview.currentBracket {
+  background-color: lightgray;
+  border: 1px solid red;
+}
+.annotationOverview.matchingBracket {
+  background-color: lightgray;
+  border: 1px solid red;
+}
+
+/* Styles for text range */
+.annotationRange {
+  background-repeat: repeat-x;
+  background-position: left bottom;
+}
+.annotationRange.task {
+  outline: 1px dashed rgba(0, 255, 0, 0.5);
+}
+.annotationRange.matchingBracket {
+  outline: 1px solid grey;
+}
+
 .token_singleline_comment {
   color: #45a946; /* green */
 }
 
 .token_multiline_comment {
   color: #45a946; /* green */
 }
 
@@ -76,21 +141,23 @@
 
 .token_tab {
   /* images/white_tab.png */
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAJCAIAAACJ2loDAAAABnRSTlMA/wD/AP83WBt9AAAAMklEQVR4nGP4TwRgoK6i52c3bz5w6zMSA6tJn28d2Lx589nnCAYu63AaSLxJRLoJPwAAeNk0aG4opfMAAAAASUVORK5CYII=");
   background-repeat: no-repeat;
   background-position: left center;
 }
 
-.line_caret { /* Current line */
+.line_caret,
+.annotationLine.currentLine { /* Current line */
   background: #dae2ee; /* lighter than the background */
 }
 
-.readonly .line_caret {
+.readonly .line_caret,
+.readonly .annotationLine.currentLine {
   background: #cddae5; /* a bit darker than the background */
 }
 
 /* Styling for html syntax highlighting */
 .entity-name-tag {
   color: #dd0058; /* purple */
 }
 
@@ -110,12 +177,8 @@
   color: #1e66b1; /* blue */
   font-style: italic;
 }
 
 .invalid {
   color: red;
   font-weight: bold;
 }
-
-.annotationRange.matchingBracket {
-  outline: 1px solid grey;
-}
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -90,16 +90,19 @@ browser.jar:
   skin/classic/browser/devtools/commandline.png       (devtools/commandline.png)
   skin/classic/browser/devtools/goto-mdn.png          (devtools/goto-mdn.png)
   skin/classic/browser/devtools/csshtmltree.css       (devtools/csshtmltree.css)
   skin/classic/browser/devtools/webconsole.css                  (devtools/webconsole.css)
   skin/classic/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
   skin/classic/browser/devtools/webconsole.png                  (devtools/webconsole.png)
   skin/classic/browser/devtools/gcli.css              (devtools/gcli.css)
   skin/classic/browser/devtools/orion.css             (devtools/orion.css)
+  skin/classic/browser/devtools/orion-container.css   (devtools/orion-container.css)
+  skin/classic/browser/devtools/orion-task.png        (devtools/orion-task.png)
+  skin/classic/browser/devtools/orion-breakpoint.png  (devtools/orion-breakpoint.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png           (devtools/breadcrumbs/ltr-middle-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png  (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png          (devtools/breadcrumbs/ltr-middle-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle.png                   (devtools/breadcrumbs/ltr-middle.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..85f73d972841e7266223899044cc7fcd38552844
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS0006hNkl<ZIE|%~Pfrt36vcm2+i9V+H2q6uYN5t1s0tx0j0uUNF)nb&mvGJA
zh5N=OU&5UbjSDwyG#Hg=jOkEHaV$)yQ|Leo9cZ76+JZJ3qi6YYa^AW3oGS?-_#Zfb
zeJE<Wc={|yVN;{FZv!wKkQq-YEIde)RASP3zI5I}c4<}QRE=8;nZBP&YMH_(gYlHY
z;=@^~PawOrD$1t8<r~T$E$3frL_?9Dh_h=ur)pfgqhLEA=pA5Wc!==OAOMxa2D`OG
zs`VohHx)iE=P7EsNGdT&5<-w&S`~XoHM|KAVZWELXo#2Zwpf0<3BdeJihI*zY?Vza
zRviGj;%4#TtmFj9sT!jhA1Br^Bk?HD-{g6+{Jv-V%hxKclNPtHj<Tbf0BorS0FExH
zUNNaxOo9V0R@OH9W?xy`AUNRa@fru6gq#4DX@lGZz;3o^xBI)%ZVT*Yi~YS0@6>jm
zIdIBw>Tq-FaI>vj%w-aN0&|%J+q%``Ic3fqOiicwW*E3UU{)K<&s@PHyLhp_4Z!`$
zOWeIahMM0c9uCo{+Kf&|fFC_5YPxuweMLOsqtUjBh5U?P3=)qF1F&P%D3q$`rbS@T
zPf;~^v^YmniFHy)Dlusyt%yR&AR70hmyglQC7|@v7y+N3@{YwsTIp4~ugafu8sUf!
zZ@`1s-C0z<*`&UIOvN~0BK?~xchNnj59=DVI#F>!W@_>;j_F_U9rBU^VLv*CRsaA1
M07*qoM6N<$g4fs>mH+?%
new file mode 100644
--- /dev/null
+++ b/browser/themes/pinstripe/devtools/orion-container.css
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.viewTooltip {
+  display: none; /* TODO: add tooltips support, see bug 721752 */
+  font-family: monospace;
+  font-size: 13px;
+  background-color: InfoBackground;
+  color: InfoText;
+  padding: 2px;
+  border-radius: 4px;
+  border: 1px solid black;
+  z-index: 100;
+  position: fixed;
+  overflow: hidden;
+  white-space: pre;
+}
+
+.viewTooltip em {
+  font-style: normal;
+  font-weight: bold;
+}
+
+.annotationHTML {
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.annotationHTML.task {
+  background-image: url("chrome://browser/skin/devtools/orion-task.png");
+}
+.annotationHTML.breakpoint {
+  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..42dbc00b655fffeae488cc2241d97407977f6dec
GIT binary patch
literal 413
zc$@*90b>4%P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00040Nkl<ZIE|%~u}i~16vn@pq%A@Qrwm#9F9;&tTwLl9kf07-L_ra;gU}&J
z5eYchMTBm4P%DKFI=Occ{1*xi(xHPm6eO3s%Q@wm*hB+;@WH)1zTdsayHkV^m?yMo
zF&I9H`?t$nrtRfZRLUC)04Pxf2M-ldURuco7=FFtW^14%DhRni!2Dc*kWbs50+;~#
z2e7+#0n0G4ce^?Z;4}oG-<jsa^%g9{#Aq@Gr{OGs{Q;;~+tPgXybl%wEJ#2Qf>0mz
zY8!<5QgO4_uYph>EXV*f><%o$M8obN;J(a9lQEh-2LbmH@C*Pa9B$XfXflRnm^j;f
zlxDYUgK;Xw2~V#;Q*|_Zj)X)vYpR}5W(x(igo0Xv*RSFI^8;SLCimis0}^8_>Lqz_
z{c@DZ<B>5&fug>cYWN+Dro6;sr-{~`n+tHVb1v7)yx;i;N{ha1Q$r5E00000NkvXX
Hu0mjf2D_^v
--- a/browser/themes/pinstripe/devtools/orion.css
+++ b/browser/themes/pinstripe/devtools/orion.css
@@ -6,38 +6,103 @@
   background: #cddae5; /* This will be seen as the continuation of the ruler */
   font-family: monospace;
   font-size: inherit; /* inherit browser's default monospace font size */
 }
 
 .view {
   color: black; /* Default text color */
   background: #f0f0ff; /* Background of the editor */
-  padding-left: 0;
+  padding-left: 4px;
 }
 
 .readonly > .view {
   background: #f0f0ff;
 }
 
-/* One line */
-.viewContent > div {
-  padding-left: 4px; /* Margin between the ruler and the editor */
-}
-
-/* Styles for the line number ruler */
-.rulerLines {
-  border-right: 1px solid #b4c4d3;
+.ruler {
   background: #cddae5;
   color: #7a8a99;
+}
+.ruler.annotations {
+  width: 16px;
+  padding-left: 4px;
+}
+.ruler.lines {
+  border-right: 1px solid #b4c4d3;
+  min-width: 1.4em;
   padding-left: 4px;
   padding-right: 4px;
   text-align: end;
 }
 
+.ruler.linesWithAnnotations {
+  min-width: 0;
+  padding-left: 0;
+}
+
+.ruler.overview {
+  border-left: 1px solid #b4c4d3;
+  width: 14px;
+  text-align: start;
+}
+
+/* Styles for the annotation ruler (first line) */
+.annotationHTML {
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.annotationHTML.task {
+  background-image: url("chrome://browser/skin/devtools/orion-task.png");
+}
+.annotationHTML.breakpoint {
+  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+}
+
+/* Styles for the overview ruler  */
+.annotationOverview {
+  cursor: pointer;
+  border-radius: 2px;
+  left: 2px;
+  width: 8px;
+}
+.annotationOverview.task {
+  background-color: lightgreen;
+  border: 1px solid green;
+}
+.annotationOverview.breakpoint {
+  background-color: lightblue;
+  border: 1px solid blue;
+}
+.annotationOverview.currentBracket {
+  background-color: lightgray;
+  border: 1px solid red;
+}
+.annotationOverview.matchingBracket {
+  background-color: lightgray;
+  border: 1px solid red;
+}
+
+/* Styles for text range */
+.annotationRange {
+  background-repeat: repeat-x;
+  background-position: left bottom;
+}
+.annotationRange.task {
+  outline: 1px dashed rgba(0, 255, 0, 0.5);
+}
+.annotationRange.matchingBracket {
+  outline: 1px solid grey;
+}
+
 .token_singleline_comment {
   color: #45a946; /* green */
 }
 
 .token_multiline_comment {
   color: #45a946; /* green */
 }
 
@@ -76,21 +141,23 @@
 
 .token_tab {
   /* images/white_tab.png */
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAJCAIAAACJ2loDAAAABnRSTlMA/wD/AP83WBt9AAAAMklEQVR4nGP4TwRgoK6i52c3bz5w6zMSA6tJn28d2Lx589nnCAYu63AaSLxJRLoJPwAAeNk0aG4opfMAAAAASUVORK5CYII=");
   background-repeat: no-repeat;
   background-position: left center;
 }
 
-.line_caret { /* Current line */
+.line_caret,
+.annotationLine.currentLine { /* Current line */
   background: #dae2ee; /* lighter than the background */
 }
 
-.readonly .line_caret {
+.readonly .line_caret,
+.readonly .annotationLine.currentLine {
   background: #cddae5; /* a bit darker than the background */
 }
 
 /* Styling for html syntax highlighting */
 .entity-name-tag {
   color: #dd0058; /* purple */
 }
 
@@ -110,12 +177,8 @@
   color: #1e66b1; /* blue */
   font-style: italic;
 }
 
 .invalid {
   color: red;
   font-weight: bold;
 }
-
-.annotationRange.matchingBracket {
-  outline: 1px solid grey;
-}
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -126,16 +126,19 @@ browser.jar:
   skin/classic/browser/tabview/tabview.css                  (tabview/tabview.css)
 * skin/classic/browser/devtools/common.css                  (devtools/common.css)
   skin/classic/browser/devtools/arrows.png                  (devtools/arrows.png)
   skin/classic/browser/devtools/commandline.png             (devtools/commandline.png)
   skin/classic/browser/devtools/goto-mdn.png                (devtools/goto-mdn.png)
   skin/classic/browser/devtools/csshtmltree.css             (devtools/csshtmltree.css)
   skin/classic/browser/devtools/gcli.css                    (devtools/gcli.css)
   skin/classic/browser/devtools/orion.css                   (devtools/orion.css)
+  skin/classic/browser/devtools/orion-container.css         (devtools/orion-container.css)
+  skin/classic/browser/devtools/orion-task.png              (devtools/orion-task.png)
+  skin/classic/browser/devtools/orion-breakpoint.png        (devtools/orion-breakpoint.png)
   skin/classic/browser/devtools/toolbarbutton-close.png     (devtools/toolbarbutton-close.png)
 * skin/classic/browser/devtools/webconsole.css                  (devtools/webconsole.css)
   skin/classic/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
   skin/classic/browser/devtools/webconsole.png                  (devtools/webconsole.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -169,30 +169,30 @@
   }
   #main-window[sizemode=normal] #browser-bottombox {
     border: 1px solid @toolbarShadowColor@;
     border-top-style: none;
     background-clip: padding-box;
   }
 
   #main-window[sizemode=normal][tabsontop=false] #PersonalToolbar:not(:-moz-lwtheme) {
-    border-top-left-radius: 3.5px;
-    border-top-right-radius: 3.5px;
+    border-top-left-radius: 2.5px;
+    border-top-right-radius: 2.5px;
   }
 
   /* Toolbar shadow behind tabs */
   /* This code is only needed for restored windows (i.e. sizemode=normal)
      because of the border radius on the toolbar below the tab bar. */
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar:not(:-moz-lwtheme),
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme),
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
   #main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
     border-top: 1px solid @toolbarShadowColor@;
-    border-top-left-radius: 3.5px;
-    border-top-right-radius: 3.5px;
+    border-top-left-radius: 2.5px;
+    border-top-right-radius: 2.5px;
     background-clip: padding-box;
   }
   #main-window[sizemode=normal] #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) {
     margin-bottom: -1px;
     background-image: none !important;
   }
   #main-window[sizemode=normal] #tabbrowser-tabs[tabsontop=true] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox > .scrollbox-innerbox:not(:-moz-lwtheme) {
     position: relative;
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -681,27 +681,32 @@ menuitem.bookmark-item {
   list-style-image: url("chrome://browser/skin/Toolbar.png") !important;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
 @navbarLargeIcons@ .toolbarbutton-1 {
   -moz-appearance: none;
   padding: 1px 5px;
-  background: rgba(151,152,153,.05)
-              -moz-linear-gradient(rgba(251,252,253,.95), rgba(246,247,248,.47) 49%, 
-                                   rgba(231,232,233,.45) 51%, rgba(225,226,229,.3));
-  background-clip: padding-box;
+  background: hsla(210,48%,90%,.1)
+              -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.45) 49%,
+                                   rgba(255,255,255,.35) 51%, rgba(255,255,255,.1))
+              padding-box;
   border-radius: 2.5px;
   border: 1px solid;
-  border-color: rgba(0,0,0,.12) rgba(0,0,0,.19) rgba(0,0,0,.38);
-  box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
-              0 0 0 2px rgba(255,255,255,.1) inset;
+  border-color: hsla(210,54%,20%,.13) hsla(210,54%,20%,.16) hsla(210,54%,20%,.2);
+  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
+              0 0 0 1px rgba(255,255,255,.3) inset,
+              0 1px 0 hsla(210,54%,20%,.02),
+              /* allows winstripe-keyhole-forward-mask to be used for non-hover as well as hover: */
+              0 0 2px hsla(210,54%,20%,0);
   color: black;
   text-shadow: 0 0 2px white;
+  -moz-transition-property: background-color, border-color, box-shadow;
+  -moz-transition-duration: 250ms;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   padding-left: 3px;
   padding-right: 3px;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1[type="menu-button"] {
@@ -750,40 +755,40 @@ menuitem.bookmark-item {
 
 @navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
 @navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
   opacity: 1;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
 @navbarLargeIcons@ .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
-@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover,
-@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon {
-  background-color: hsla(190,60%,70%,.5);
-  border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8);
-  box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
-              0 0 0 1.5px rgba(255,255,255,.1) inset,
-              0 0 3.5px hsl(190,90%,80%);
-  -moz-transition: background-color .4s ease-in,
-                   border-color .3s ease-in,
-                   box-shadow .3s ease-in;
+@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover {
+  background-color: hsla(210,48%,96%,.75);
+  border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
+  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
+              0 0 0 1px rgba(255,255,255,.3) inset,
+              0 1px 0 hsla(210,54%,20%,.03),
+              0 0 2px hsla(210,54%,20%,.1);
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
 @navbarLargeIcons@ .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
 @navbarLargeIcons@ .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker,
 @navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active,
 @navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"])[checked="true"],
 @navbarLargeIcons@ .toolbarbutton-1[open="true"] {
-  background-color: transparent;
-  border-color: rgba(0,0,0,.65) rgba(0,0,0,.55) rgba(0,0,0,.5);
-  box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
-              0 0 2px rgba(0,0,0,.4) inset,
-              0 1px 0 rgba(255,255,255,.4);
+  background-color: hsla(210,54%,20%,.2);
+  border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
+  box-shadow: 0 1px 1px rgba(0,0,0,.1) inset,
+              0 0 2px rgba(0,0,0,.3) inset,
+              /* allows winstripe-keyhole-forward-mask to be used for non-hover as well as hover: */
+              0 1px 0 hsla(210,54%,20%,0),
+              0 0 2px hsla(210,54%,20%,0);
   text-shadow: none;
+  -moz-transition: none;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1[checked="true"]:not(:active):hover {
   background-color: rgba(90%,90%,90%,.4);
   -moz-transition: background-color .4s;
 }
 
 .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
@@ -899,38 +904,43 @@ toolbar[mode="full"] .toolbarbutton-1 > 
 @navbarLargeIcons@ #back-button:-moz-locale-dir(rtl) {
   border-radius: 10000px 0 0 10000px;
 }
 
 @navbarLargeIcons@ #back-button > .toolbarbutton-icon {
   border-radius: 10000px;
   padding: 5px;
   border: none;
-  background-image: -moz-linear-gradient(rgba(251,252,253,.97), rgba(246,247,248,.5) 49%, 
-                                         rgba(231,232,233,.45) 51%, rgba(225,226,229,.2));
-  box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
-              0 0 0 2px rgba(255,255,255,.1) inset,
-              0 0 0 1px rgba(0,0,0,.15),
-              0 1px 0 rgba(0,0,0,.4);
+  background: hsla(210,48%,90%,.1)
+              -moz-linear-gradient(rgba(255,255,255,.88), rgba(255,255,255,.45) 49%,
+                                   rgba(255,255,255,.35) 51%, rgba(255,255,255,.67));
+  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
+              0 0 0 1px rgba(255,255,255,.3) inset,
+              0 1px 0 hsla(210,54%,20%,.02),
+              0 0 0 1px rgba(0,0,0,.15);
+  -moz-transition-property: background-color, box-shadow;
+  -moz-transition-duration: 250ms;
 }
 
 @navbarLargeIcons@ #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
-  box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
-              0 0 0 2px rgba(255,255,255,.1) inset,
-              0 0 0 1px hsla(190,50%,40%,.3),
-              0 1px 0 rgba(0,0,0,.4),
-              0 0 5px 1px hsl(190,90%,80%);
+  background-color: hsla(210,48%,96%,.75);
+  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
+              0 0 0 1px rgba(255,255,255,.1) inset,
+              0 1px 0 hsla(210,54%,20%,.03),
+              0 0 0 1px rgba(0,0,0,.2),
+              0 0 2px 1px hsla(210,54%,20%,.2);
 }
 
 @navbarLargeIcons@ #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
 @navbarLargeIcons@ #back-button[open="true"] > .toolbarbutton-icon {
-  box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
-              0 0 2px rgba(0,0,0,.4) inset,
-              0 0 0 1px rgba(0,0,0,.65),
-              0 2px 0 rgba(255,255,255,.4);
+  background-color: hsla(210,54%,20%,.2);
+  box-shadow: 0 1px 1px rgba(0,0,0,.1) inset,
+              0 0 2px rgba(0,0,0,.3) inset,
+              0 0 0 1px rgba(0,0,0,.2);
+  -moz-transition: none;
 }
 
 @navbarLargeIcons@[currentset*="unified-back-forward-button"],
 @navbarLargeIcons@:not([currentset]) {
   padding-top: 3px;
   padding-bottom: 5px;
 }
 
@@ -942,23 +952,16 @@ toolbar[mode="full"] .toolbarbutton-1 > 
 @navbarLargeIcons@ #forward-button {
   /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
   -moz-margin-start: -6px !important;
   padding-left: 7px;
   padding-right: 3px;
 }
 
-@navbarLargeIcons@ #forward-button:not([disabled="true"]):not(:active):hover {
-  /*mask: url(keyhole-forward-mask.svg#mask-hover);*/
-  mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask-hover);
-  /* Don't animate the box shadow, as the blur and spread radii affect the mask. */
-  -moz-transition: background-color .4s ease-in;
-}
-
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
   list-style-image: url("chrome://browser/skin/menu-back.png") !important;
 }
 
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(rtl) {
   list-style-image: url("chrome://browser/skin/menu-forward.png") !important;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..85f73d972841e7266223899044cc7fcd38552844
GIT binary patch
literal 626
zc$@)p0*(ENP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS0006hNkl<ZIE|%~Pfrt36vcm2+i9V+H2q6uYN5t1s0tx0j0uUNF)nb&mvGJA
zh5N=OU&5UbjSDwyG#Hg=jOkEHaV$)yQ|Leo9cZ76+JZJ3qi6YYa^AW3oGS?-_#Zfb
zeJE<Wc={|yVN;{FZv!wKkQq-YEIde)RASP3zI5I}c4<}QRE=8;nZBP&YMH_(gYlHY
z;=@^~PawOrD$1t8<r~T$E$3frL_?9Dh_h=ur)pfgqhLEA=pA5Wc!==OAOMxa2D`OG
zs`VohHx)iE=P7EsNGdT&5<-w&S`~XoHM|KAVZWELXo#2Zwpf0<3BdeJihI*zY?Vza
zRviGj;%4#TtmFj9sT!jhA1Br^Bk?HD-{g6+{Jv-V%hxKclNPtHj<Tbf0BorS0FExH
zUNNaxOo9V0R@OH9W?xy`AUNRa@fru6gq#4DX@lGZz;3o^xBI)%ZVT*Yi~YS0@6>jm
zIdIBw>Tq-FaI>vj%w-aN0&|%J+q%``Ic3fqOiicwW*E3UU{)K<&s@PHyLhp_4Z!`$
zOWeIahMM0c9uCo{+Kf&|fFC_5YPxuweMLOsqtUjBh5U?P3=)qF1F&P%D3q$`rbS@T
zPf;~^v^YmniFHy)Dlusyt%yR&AR70hmyglQC7|@v7y+N3@{YwsTIp4~ugafu8sUf!
zZ@`1s-C0z<*`&UIOvN~0BK?~xchNnj59=DVI#F>!W@_>;j_F_U9rBU^VLv*CRsaA1
M07*qoM6N<$g4fs>mH+?%
new file mode 100644
--- /dev/null
+++ b/browser/themes/winstripe/devtools/orion-container.css
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.viewTooltip {
+  display: none; /* TODO: add tooltips support, see bug 721752 */
+  font-family: monospace;
+  font-size: 13px;
+  background-color: InfoBackground;
+  color: InfoText;
+  padding: 2px;
+  border-radius: 4px;
+  border: 1px solid black;
+  z-index: 100;
+  position: fixed;
+  overflow: hidden;
+  white-space: pre;
+}
+
+.viewTooltip em {
+  font-style: normal;
+  font-weight: bold;
+}
+
+.annotationHTML {
+  cursor: pointer;
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.annotationHTML.task {
+  background-image: url("chrome://browser/skin/devtools/orion-task.png");
+}
+.annotationHTML.breakpoint {
+  background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..42dbc00b655fffeae488cc2241d97407977f6dec
GIT binary patch
literal 413
zc$@*90b>4%P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00040Nkl<ZIE|%~u}i~16vn@pq%A@Qrwm#9F9;&tTwLl9kf07-L_ra;gU}&J
z5eYchMTBm4P%DKFI=Occ{1*xi(xHPm6eO3s%Q@wm*hB+;@WH)1zTdsayHkV^m?yMo
zF&I9H`?t$nrtRfZRLUC)04Pxf2M-ldURuco7=FFtW^14%DhRni!2Dc*kWbs50+;~#
z2e7+#0n0G4ce^?Z;4}oG-<jsa^%g9{#Aq@Gr{OGs{Q;;~+tPgXybl%wEJ#2Qf>0mz
zY8!<5QgO4_uYph>EXV*f><%o$M8obN;J(a9lQEh-2LbmH@C*Pa9B$XfXflRnm^j;f
zlxDYUgK;Xw2~V#;Q*|_Zj)X)vYpR}5W(x(igo0Xv*RSFI^8;SLCimis0}^8_>Lqz_
z{c@DZ<B>5&fug>cYWN+Dro6;sr-{~`n+tHVb1v7)yx;i;N{ha1Q$r5E00000NkvXX
Hu0mjf2D_^v
--- a/browser/themes/winstripe/devtools/orion.css
+++ b/browser/themes/winstripe/devtools/orion.css
@@ -6,38 +6,103 @@
   background: #cddae5; /* This will be seen as the continuation of the ruler */
   font-family: monospace;
   font-size: inherit; /* inherit browser's default monospace font size */
 }
 
 .view {
   color: black; /* Default text color */
   background: #f0f0ff; /* Background of the editor */
-  padding-left: 0;
+  padding-left: 4px;
 }
 
 .readonly > .view {
   background: #f0f0ff;
 }
 
-/* One line */
-.viewContent > div {
-  padding-left: 4px