Index: src/orca/braille.py
===================================================================
--- src/orca/braille.py	(revision 4308)
+++ src/orca/braille.py	(working copy)
@@ -874,7 +874,7 @@
 
     _lines = []
     _regionWithFocus = None
-    viewport = [0, 0]
+    viewport = [viewport[0], 0]
 
 def setLines(lines):
     global _lines
@@ -939,18 +939,45 @@
             break
         else:
             lineNum += 1
+    refresh(panToFocus, 0, getLinkMask)
+    
+def writeBraille(string = "", attributeMask = ""):
+    global monitor
+    if string == "":
+        if useBrlAPIBindings:
+            if brlAPIRunning:
+                brlAPI.writeText("", 0)
+        else:
+            brl.writeText(0, "")
+        return    
+        
+    if useBrlAPIBindings:
+        if brlAPIRunning:
+            writeStruct = brlapi.WriteStruct()
+            writeStruct.regionBegin = 1
+            writeStruct.regionSize = len(string.decode("UTF-8"))
+            while writeStruct.regionSize < _displaySize[0]:
+                string += " "
+                if attributeMask:
+                    attributeMask += '\x00'
+                writeStruct.regionSize += 1
+            writeStruct.text = string
+            writeStruct.cursor = cursorCell
+            writeStruct.charset = "UTF-8"
+            if attributeMask:
+                writeStruct.attrOr = attributeMask
+            brlAPI.write(writeStruct) 
+    else:
+        brl.writeText(cursorCell, string)
+    if settings.enableBrailleMonitor:
+        if not monitor:
+            monitor = brlmon.BrlMon(_displaySize[0])
+            monitor.show_all()
+        monitor.writeText(cursorCell, string, attributeMask)
+    elif monitor:
+        monitor.destroy()
+        monitor = None
 
-    line = _lines[viewport[1]]
-    [string, offset, attributeMask] = line.getLineInfo(getLinkMask)
-
-    # If the cursor is too far right, we scroll the viewport
-    # so the cursor will be on the last cell of the display.
-    #
-    if _regionWithFocus.cursorOffset >= _displaySize[0]:
-        offset += _regionWithFocus.cursorOffset - _displaySize[0] + 1
-
-    viewport[0] = max(0, offset)
-
 def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True):
     """Repaints the Braille on the physical display.  This clips the entire
     logical structure by the viewport and also sets the cursor to the
@@ -974,17 +1001,12 @@
       amount of time (AKA Gecko).
     """
 
+    global cursorCell
     global endIsShowing
     global beginningIsShowing
-    global cursorCell
-    global monitor
 
     if len(_lines) == 0:
-        if useBrlAPIBindings:
-            if brlAPIRunning:
-                brlAPI.writeText("", 0)
-        else:
-            brl.writeText(0, "")
+        writeBraille()
         return
 
     # Now determine the location of the cursor.  First, we'll figure
@@ -999,37 +1021,64 @@
     # actually is in the string.
     #
     line = _lines[viewport[1]]
-    [string, focusOffset, attributeMask] = line.getLineInfo(getLinkMask)
-    cursorOffset = -1
-    if focusOffset >= 0:
-        cursorOffset = focusOffset + _regionWithFocus.cursorOffset
+    [string, offset, attributeMask] = line.getLineInfo(getLinkMask)
+    # If the cursor is too far right, we scroll the viewport
+    additionalOffset = _regionWithFocus.cursorOffset
+    totalOffset = offset + additionalOffset
 
-    # Now, if desired, we'll automatically pan the viewport to show
-    # the cursor.  If there's no targetCursorCell, then we favor the
-    # left of the display if we need to pan left, or we favor the
-    # right of the display if we need to pan right.
-    #
-    if panToCursor and (cursorOffset >= 0):
-        if len(string) <= _displaySize[0]:
-            viewport[0] = 0
-        elif targetCursorCell:
-            viewport[0] = max(0, cursorOffset - targetCursorCell + 1)
-        elif cursorOffset < viewport[0]:
-            viewport[0] = max(0, cursorOffset)
-        elif cursorOffset >= (viewport[0] + _displaySize[0]):
-            viewport[0] = max(0, cursorOffset - _displaySize[0] + 1)
+    if panToCursor:
+        # How close the cursor is allowed to the edge of the display.
+        innerLeftMargin = string[viewport[0]:].find(' ') + viewport[0]
+        if innerLeftMargin  < offset:
+            viewport[0] = max(0, offset)
+            innerLeftMargin = string[viewport[0]:].find(' ') + viewport[0]
+        outerLeftMargin = string[:viewport[0]].rfind(' ')
+        rightDisplayEdge = viewport[0] + _displaySize[0]
+        innerRightMargin =  string[:rightDisplayEdge].rfind(' ')
+        if innerRightMargin + 1  == rightDisplayEdge:
+            innerRightMargin =  string[:innerRightMargin].rfind(' ')
+        outerRightMargin = string[rightDisplayEdge:].find(' ') \
+          + rightDisplayEdge
 
+        #print("to=%d,ol=%d,il=%d,ir=%d,or=%d,vp=%d,of=%d" \
+        #  % (totalOffset, outerLeftMargin, innerLeftMargin, innerRightMargin, \
+        #  outerRightMargin, viewport[0], offset))
+        if targetCursorCell:
+            viewport[0] = max(0, totalOffset - targetCursorCell + 1)
+            #print("refresh target cursorCell branch")
+        elif outerLeftMargin <= offset and totalOffset <= innerLeftMargin:
+            viewport[0] =  max(0, offset)
+            #print("refresh snapping to offset branch")
+        elif totalOffset <= outerLeftMargin:
+            viewport[0] = max(0, totalOffset)
+            #print("refresh totalOffset branch")
+        elif totalOffset <= innerLeftMargin:
+            outerLeftMargin = string[:outerLeftMargin].rfind(' ')
+            viewport[0] = max(0, outerLeftMargin+1)
+            #print("refresh totalOffset<innerLeftMargin branch, ol=%d,vp=%d" \
+            #  % (outerLeftMargin, viewport[0]))
+        elif totalOffset >= outerRightMargin:
+            viewport[0] = max(0, totalOffset - _displaySize[0]/2 + 1)
+            #print("refresh totalOffset>outerRightMargin branch")
+        elif totalOffset >= innerRightMargin and \
+          outerRightMargin  >= rightDisplayEdge:
+            outerRightMargin = string[outerRightMargin+1:].find(' ') + \
+              outerRightMargin +1
+            viewport[0] = max(0, (outerRightMargin - _displaySize[0]))
+            #print("refresh totalOffset>innerRightMargin, vp=%d" %viewport[0])
+
     startPos = viewport[0]
     endPos = startPos + _displaySize[0]
-
     # Now normalize the cursor position to BrlTTY, which uses 1 as
     # the first cursor position as opposed to 0.
     #
-    cursorCell = cursorOffset - startPos
+    cursorCell = totalOffset - startPos
     if (cursorCell < 0) or (cursorCell >= _displaySize[0]):
         cursorCell = 0
     else:
         cursorCell += 1 # Normalize to 1-based offset
+    startPos = viewport[0]
+    endPos = startPos + _displaySize[0]
 
     logLine = "BRAILLE LINE:  '%s'" % string
     debug.println(debug.LEVEL_INFO, logLine)
@@ -1038,58 +1087,11 @@
                     (string[startPos:endPos], cursorCell)
     debug.println(debug.LEVEL_INFO, logLine)
     log.info(logLine.encode("UTF-8"))
-
     substring = string[startPos:endPos]
-    if useBrlAPIBindings:
-        if brlAPIRunning:
-            writeStruct = brlapi.WriteStruct()
-            writeStruct.regionBegin = 1
-            writeStruct.regionSize = len(substring)
-            while writeStruct.regionSize < _displaySize[0]:
-                substring += " "
-                if attributeMask:
-                    attributeMask += '\x00'
-                writeStruct.regionSize += 1
-            writeStruct.text = substring
-            writeStruct.cursor = cursorCell
-
-            # [[[WDW - if you want to muck around with the dots on the
-            # display to do things such as add underlines, you can use
-            # the attrOr field of the write structure to do so.  The
-            # attrOr field is a string whose length must be the same
-            # length as the display and whose dots will end up showing
-            # up on the display.  Each character represents a bitfield
-            # where each bit corresponds to a dot (i.e., bit 0 = dot 1,
-            # bit 1 = dot 2, and so on).  Here's an example that underlines
-            # all the text.]]]
-            #
-            #myUnderline = ""
-            #for i in range(0, _displaySize[0]):
-            #    myUnderline += '\xc0'
-            #writeStruct.attrOr = myUnderline
-
-            if attributeMask:
-                writeStruct.attrOr = attributeMask[startPos:endPos]
-
-            brlAPI.write(writeStruct)
-    else:
-        brl.writeText(cursorCell, substring)
-
-    if settings.enableBrailleMonitor:
-        if not monitor:
-            monitor = brlmon.BrlMon(_displaySize[0])
-            monitor.show_all()
-        if attributeMask:
-            subMask = attributeMask[startPos:endPos]
-        else:
-            subMask = None
-        monitor.writeText(cursorCell, substring, subMask)
-    elif monitor:
-        monitor.destroy()
-        monitor = None
-
+    submask = attributeMask[startPos:endPos]
+    writeBraille(substring, submask)
     beginningIsShowing = startPos == 0
-    endIsShowing = endPos >= len(string)
+    endIsShowing = endPos >= len(string)    
 
 def displayRegions(regionInfo):
     """Displays a list of regions on a single line, setting focus to the
@@ -1111,7 +1113,6 @@
         line.addRegion(item)
     addLine(line)
     setFocus(focusedRegion)
-    refresh()
 
 def displayMessage(message, cursor=-1):
     """Displays a single line, setting the cursor to the given position,
@@ -1126,7 +1127,6 @@
     region = Region(message, cursor)
     addLine(Line(region))
     setFocus(region)
-    refresh(True)
 
 def panLeft(panAmount=0):
     """Pans the display to the left, limiting the pan to the beginning
@@ -1200,8 +1200,6 @@
     """
 
     setFocus(_regionWithFocus)
-    refresh(True)
-
     return True
 
 def _processBrailleEvent(command):
