diff --git a/src/orca/braille.py b/src/orca/braille.py
index f069504..2c6e7c7 100644
--- a/src/orca/braille.py
+++ b/src/orca/braille.py
@@ -359,7 +359,7 @@ class Region:
         # Create an empty mask.
         #
         mask = ['\x00'] * maskSize
-        return "".join(mask)
+        return ''.join(mask)
 
     def repositionCursor(self):
         """Reposition the cursor offset for contracted mode.
@@ -455,17 +455,112 @@ class Component(Region):
         """
 
         Region.__init__(self, string, cursorOffset, expandOnCursor)
-        if indicator:
+        self.indicator = indicator
+        if self.indicator:
             if self.string:
-                self.string = indicator + ' ' + self.string
+                self.string = self.indicator + ' ' + self.string
             else:
-                self.string = indicator
+                self.string = self.indicator
 
         self.accessible = accessible
 
     def __str__(self):
         return "Component: '%s', %d" % (self.string, self.cursorOffset)
 
+    def getAttributeMask(self, getLinkMask=True):
+        """Creates a string which can be used as the attrOr field of brltty's
+        write structure for the purpose of indicating text attributes, links,
+        and selection.
+
+        Arguments:
+        - getLinkMask: Whether or not we should take the time to get
+          the attributeMask for links. Reasons we might not want to
+          include knowning that we will fail and/or it taking an
+          unreasonable amount of time (AKA Gecko).
+        """
+
+        try:
+            text = self.accessible.queryText()
+        except NotImplementedError:
+            return Region.getAttributeMask(self, getLinkMask)
+
+        # Start with an empty mask.
+        #
+        lineOffset = 0
+        stringLength = len(self.rawLine)
+        lineEndOffset = lineOffset + stringLength
+        regionMask = [settings.TEXT_ATTR_BRAILLE_NONE]*stringLength
+
+        attrIndicator = settings.textAttributesBrailleIndicator
+        selIndicator = settings.brailleSelectorIndicator
+        linkIndicator = settings.brailleLinkIndicator
+        script = orca_state.activeScript
+
+        if getLinkMask and linkIndicator != settings.BRAILLE_LINK_NONE:
+            try:
+                hyperText = self.accessible.queryHypertext()
+                nLinks = hyperText.getNLinks()
+            except:
+                nLinks = 0
+
+            n = 0
+            while n < nLinks:
+                link = hyperText.getLink(n)
+                if lineOffset <= link.startIndex:
+                    for i in xrange(link.startIndex, link.endIndex):
+                        try:
+                            regionMask[i] |= linkIndicator
+                        except:
+                            pass
+                n += 1
+
+        if attrIndicator:
+            enabledAttributes = script.attributeStringToDictionary(
+                settings.enabledBrailledTextAttributes)
+
+            offset = lineOffset
+            while offset < lineEndOffset:
+                attributes, startOffset, endOffset = \
+                            script.getTextAttributes(self.accessible,
+                                                     offset, True)
+                if endOffset <= offset:
+                    break
+                mask = settings.TEXT_ATTR_BRAILLE_NONE
+                offset = endOffset
+                for attrib in attributes:
+                    if enabledAttributes.get(attrib, '') != '':
+                        if enabledAttributes[attrib] != attributes[attrib]:
+                            mask = attrIndicator
+                            break
+                if mask != settings.TEXT_ATTR_BRAILLE_NONE:
+                    maskStart = max(startOffset - lineOffset, 0)
+                    maskEnd = min(endOffset - lineOffset, stringLength)
+                    for i in xrange(maskStart, maskEnd):
+                        regionMask[i] |= attrIndicator
+
+        if selIndicator:
+            selections = script.getAllTextSelections(self.accessible)
+            for startOffset, endOffset in selections:
+                maskStart = max(startOffset - lineOffset, 0)
+                maskEnd = min(endOffset - lineOffset, stringLength)
+                for i in xrange(maskStart, maskEnd):
+                    regionMask[i] |= selIndicator
+
+        if self.contracted:
+            contractedMask = [0] * len(self.rawLine)
+            outPos = self.outPos
+            for i, m in enumerate(regionMask):
+                try:
+                    contractedMask[outPos[i]] |= m
+                except IndexError:
+                    continue
+            regionMask = contractedMask[:len(self.string)]
+
+        if self.indicator:
+            regionMask = [0]*len(self.indicator + ' ') + regionMask
+
+        return ''.join(map(chr, regionMask))
+
     def getCaretOffset(self, offset):
         """Returns the caret position of the given offset if the object
         has text with a caret.  Otherwise, returns -1.
diff --git a/src/orca/default.py b/src/orca/default.py
index 33cbb3d..d41220c 100644
--- a/src/orca/default.py
+++ b/src/orca/default.py
@@ -3166,7 +3166,7 @@ class Script(script.Script):
         utterances.extend(self.tutorialGenerator.getTutorial(obj, True))
         speech.speak(utterances)
 
-    def updateBraille(self, obj, extraRegion=None):
+    def updateBraille(self, obj, extraRegion=None, targetCursorCell=0):
         """Updates the braille display to show the give object.
 
         Arguments:
@@ -3202,7 +3202,7 @@ class Script(script.Script):
         else:
             braille.setFocus(result[1])
 
-        braille.refresh(True)
+        braille.refresh(True, targetCursorCell=targetCursorCell)
 
     ########################################################################
     #                                                                      #
@@ -3375,7 +3375,10 @@ class Script(script.Script):
 
         return selSpoken
 
-    def _presentTextAtNewCaretPosition(self, event, otherObj=None):
+    def _presentTextAtNewCaretPosition(self,
+                                       event,
+                                       otherObj=None,
+                                       noSpeech=False):
         """Updates braille, magnification, and outputs speech for the
         event.source or the otherObj."""
 
@@ -3385,6 +3388,8 @@ class Script(script.Script):
         if obj:
             mag.magnifyAccessible(event, obj)
 
+        print "HERE", event.source, text.getText(0, -1), text.caretOffset
+
         # Update the Braille display - if we can just reposition
         # the cursor, then go for it.
         #
@@ -3398,8 +3403,18 @@ class Script(script.Script):
                     brailleNeedsRepainting = False
                 break
 
+        if event.type.startswith("object:text-changed:insert") \
+           or event.type.startswith("object:text-changed:delete"):
+            brailleNeedsRepainting = True
+            targetCursorCell = braille.cursorCell
+        elif brailleNeedsRepainting:
+            targetCursorCell = 0
+
         if brailleNeedsRepainting:
-            self.updateBraille(obj)
+            self.updateBraille(obj, targetCursorCell=targetCursorCell)
+
+        if noSpeech:
+            return
 
         if not orca_state.lastInputEvent:
             return
@@ -3601,7 +3616,10 @@ class Script(script.Script):
         # they see will not be the same as what the user normally
         # experiences.]]]
 
-        self.updateBraille(event.source)
+        if self.isTextArea(event.source):
+            self._presentTextAtNewCaretPosition(event, noSpeech=True)
+        else:
+            self.updateBraille(event.source)
 
         # The any_data member of the event object has the deleted text in
         # it - If the last key pressed was a backspace or delete key,
@@ -3699,7 +3717,10 @@ class Script(script.Script):
         if event.source.getRole() == pyatspi.ROLE_SLIDER:
             return
 
-        self.updateBraille(event.source)
+        if self.isTextArea(event.source):
+            self._presentTextAtNewCaretPosition(event, noSpeech=True)
+        else:
+            self.updateBraille(event.source)
 
         text = event.any_data
 
