commit/nvda: 14 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Sep 2013 11:13:37 -0000

14 new commits in nvda:

https://bitbucket.org/nvdaaddonteam/nvda/commits/b43f7b02c78a/
Changeset:   b43f7b02c78a
Branch:      None
User:        manish_agrawal
Date:        2013-08-23 01:49:04
Summary:     Initial try at supporting MS word 2010 protected view. Fixes a 
crash, but focus on some systems is still not right.

Affected #:  3 files

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index 9c2aaf5..6535727 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -50,6 +50,9 @@ using namespace std;
 #define wdDISPID_STYLE_NAMELOCAL 0
 #define wdDISPID_RANGE_SPELLINGERRORS 316
 #define wdDISPID_SPELLINGERRORS_COUNT 1
+#define wdDISPID_RANGE_APPLICATION 1000
+#define wdDISPID_APPLICATION_ISSANDBOX 492
+
 #define wdDISPID_RANGE_FONT 5
 #define wdDISPID_FONT_COLOR 159
 #define wdDISPID_FONT_BOLD 130
@@ -409,11 +412,20 @@ void generateXMLAttribsForFormatting(IDispatch* 
pDispatchRange, int startOffset,
                }
        } 
        if(formatConfig&formatConfig_reportSpellingErrors) {
-               IDispatchPtr pDispatchSpellingErrors=NULL;
-               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_SPELLINGERRORS,VT_DISPATCH,&pDispatchSpellingErrors)==S_OK&&pDispatchSpellingErrors)
 {
-                       
_com_dispatch_raw_propget(pDispatchSpellingErrors,wdDISPID_SPELLINGERRORS_COUNT,VT_I4,&iVal);
-                       if(iVal>0) {
-                               
formatAttribsStream<<L"invalid-spelling=\""<<iVal<<L"\" ";
+               IDispatchPtr pDispatchApplication=NULL;
+               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_APPLICATION 
,VT_DISPATCH,&pDispatchApplication)==S_OK && pDispatchApplication) {
+                       bool isSandbox = true;
+                       // We need to ironically enter the if block if the call 
to get IsSandbox property fails
+                       // for backward compatibility because IsSandbox was 
introduced with word 2010 and earlier versions will return a failure for this 
property access.
+                       // This however, means that if this property access 
fails for some reason in word 2010, then we will incorrectly enter this section.
+                       
if(_com_dispatch_raw_propget(pDispatchApplication,wdDISPID_APPLICATION_ISSANDBOX
 ,VT_BOOL,&isSandbox)!=S_OK || !isSandbox ) {
+                               IDispatchPtr pDispatchSpellingErrors=NULL;
+                               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_SPELLINGERRORS,VT_DISPATCH,&pDispatchSpellingErrors)==S_OK&&pDispatchSpellingErrors)
 {
+                                       
_com_dispatch_raw_propget(pDispatchSpellingErrors,wdDISPID_SPELLINGERRORS_COUNT,VT_I4,&iVal);
+                                       if(iVal>0) {
+                                               
formatAttribsStream<<L"invalid-spelling=\""<<iVal<<L"\" ";
+                                       }
+                               }
                        }
                }
        }

diff --git a/source/NVDAObjects/IAccessible/__init__.py 
b/source/NVDAObjects/IAccessible/__init__.py
index 40f2151..08d9e46 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1797,4 +1797,5 @@ _staticMap={
        ("NUIDialog",oleacc.ROLE_SYSTEM_CLIENT):"NUIDialogClient",
        ("_WwN",oleacc.ROLE_SYSTEM_TEXT):"winword.SpellCheckErrorField",
        ("_WwO",oleacc.ROLE_SYSTEM_TEXT):"winword.SpellCheckErrorField",
+       ("_WwB",oleacc.ROLE_SYSTEM_CLIENT):"winword.ProtectedDocumentPane",
 }

diff --git a/source/NVDAObjects/IAccessible/winword.py 
b/source/NVDAObjects/IAccessible/winword.py
index c7080285..f89fc19 100644
--- a/source/NVDAObjects/IAccessible/winword.py
+++ b/source/NVDAObjects/IAccessible/winword.py
@@ -13,6 +13,8 @@ import winUser
 import speech
 import controlTypes
 import textInfos
+import eventHandler
+import wx
 
 from . import IAccessible
 from NVDAObjects.window.winword import WordDocument 
@@ -66,3 +68,20 @@ class SpellCheckErrorField(IAccessible,WordDocument):
                if errorText:
                        speech.speakText(errorText)
                        speech.speakSpelling(errorText)
+
+
+class ProtectedDocumentPane(IAccessible):
+       """The pane that gets focus in case a document opens in protected mode 
in word
+       This is mapped to the window class _WWB and role 
oleacc.ROLE_SYSTEM_CLIENT
+       """
+       
+       def event_gainFocus(self):
+               """On gaining focus, simply set the focus on a child of type 
word document. 
+               This is just a container window.
+               """
+               if eventHandler.isPendingEvents("gainFocus"):
+                       return
+               document=next((x for x in self.children if 
isinstance(x,WordDocument)), None)  
+               if document:
+                       wx.CallLater(50, document.setFocus)
+


https://bitbucket.org/nvdaaddonteam/nvda/commits/67071d5d87f6/
Changeset:   67071d5d87f6
Branch:      None
User:        mdcurran
Date:        2013-08-23 01:58:37
Summary:     MS word  2010 protected view support: When focus lands on the _WwB 
outer window, bounce focus to the document by instructing Windows to set focus 
to the document window using user32's SetFocus, and then also make  sure that 
the document has been activated if not already. Re #1686

Affected #:  1 file

diff --git a/source/NVDAObjects/IAccessible/winword.py 
b/source/NVDAObjects/IAccessible/winword.py
index f89fc19..5bbd315 100644
--- a/source/NVDAObjects/IAccessible/winword.py
+++ b/source/NVDAObjects/IAccessible/winword.py
@@ -6,6 +6,7 @@
 from comtypes import COMError
 import comtypes.automation
 import comtypes.client
+import ctypes
 import NVDAHelper
 from logHandler import log
 import oleacc
@@ -14,7 +15,6 @@ import speech
 import controlTypes
 import textInfos
 import eventHandler
-import wx
 
 from . import IAccessible
 from NVDAObjects.window.winword import WordDocument 
@@ -83,5 +83,10 @@ class ProtectedDocumentPane(IAccessible):
                        return
                document=next((x for x in self.children if 
isinstance(x,WordDocument)), None)  
                if document:
-                       wx.CallLater(50, document.setFocus)
-
+                       curThreadID=ctypes.windll.kernel32.GetCurrentThreadId()
+                       
ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,True)
+                       ctypes.windll.user32.SetFocus(document.windowHandle)
+                       
ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,False)
+                       if not document.WinwordWindowObject.active:
+                               document.WinwordWindowObject.activate()
+                               


https://bitbucket.org/nvdaaddonteam/nvda/commits/25cd26b0c208/
Changeset:   25cd26b0c208
Branch:      None
User:        mdcurran
Date:        2013-09-13 05:11:48
Summary:     expose the last sayAll mode used (CURSOR_CARET or CURSOR_REVIEW) 
via sayAllHandler.lastSayAllMode.

Affected #:  1 file

diff --git a/source/sayAllHandler.py b/source/sayAllHandler.py
index e2cb085..1d9d531 100644
--- a/source/sayAllHandler.py
+++ b/source/sayAllHandler.py
@@ -19,6 +19,7 @@ CURSOR_CARET=0
 CURSOR_REVIEW=1
 
 _generatorID = None
+lastSayAllMode=None
 
 def _startGenerator(generator):
        global _generatorID
@@ -90,6 +91,8 @@ def readObjectsHelper_generator(obj):
                yield
 
 def readText(cursor):
+       global lastSayAllMode
+       lastSayAllMode=cursor
        _startGenerator(readTextHelper_generator(cursor))
 
 def readTextHelper_generator(cursor):


https://bitbucket.org/nvdaaddonteam/nvda/commits/fd2b84e52960/
Changeset:   fd2b84e52960
Branch:      None
User:        mdcurran
Date:        2013-09-13 05:23:50
Summary:     Allow scripts to request that sayAll should be restarted after 
they execute, via an optional script property: resumeSayAllMode, which should 
be set to one of the sayAll modes (CURSOR_CARET or CURSOR_REVIEW).

* inputCore: Gestures now contain a 'wasInSayAll' property which is set to true 
if this gesture should be considered as having been executed while in sayAll. 
All gestures still cause sayAll to stop, but this allows communication that 
sayAll was running, back to scriptHandler. Modifiers are handled specifically 
so that sayAll is tracked via modifiers all the way up to a regular 
(non-modifier) gesture.
* keyboardHandler keyUp event function: ensure that inputCore forgets about 
sayAll if there are no modifier keys held down at all. This is currently needed 
as inputCore does not have any concept of gesture releases.
* config: add an 'allowSkimReadingInSayAll' boolean setting to the keyboard 
section of the config.
* scriptHandler.executeScript: if the gesture was in sayAll, and the current 
script's resumeSayall mode agrees with sayAllhandlers last sayAll mode, and the 
user has confiered NVDA to handle skim reading in sayAll, then temporarily turn 
off speech while the script executes, and then restart the last sayAll mode.

Affected #:  4 files

diff --git a/source/config/__init__.py b/source/config/__init__.py
index 5e0a4ee..0e0fb20 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -127,6 +127,7 @@ confspec = ConfigObj(StringIO(
        speakCommandKeys = boolean(default=false)
        speechInterruptForCharacters = boolean(default=true)
        speechInterruptForEnter = boolean(default=true)
+       allowSkimReadingInSayAll = boolean(default=False)
 
 [virtualBuffers]
        maxLineLength = integer(default=100)

diff --git a/source/inputCore.py b/source/inputCore.py
index 9feaf8f..977f9ea 100644
--- a/source/inputCore.py
+++ b/source/inputCore.py
@@ -14,6 +14,7 @@ import sys
 import os
 import itertools
 import configobj
+import sayAllHandler
 import baseObject
 import scriptHandler
 import queueHandler
@@ -38,6 +39,10 @@ class InputGesture(baseObject.AutoPropertyObject):
        """
        cachePropertiesByDefault = True
 
+       #: indicates that sayAll was running before this gesture
+       #: @type: bool
+       wasInSayAll=False
+
        def _get_identifiers(self):
                """The identifier(s) which will be used in input gesture maps 
to represent this gesture.
                These identifiers will be looked up in order until a match is 
found.
@@ -254,6 +259,10 @@ class InputManager(baseObject.AutoPropertyObject):
        Input includes key presses on the keyboard, as well as key presses on 
Braille displays, etc.
        """
 
+       #: a modifier gesture was just executed while sayAll was running
+       #: @type: bool
+       lastModifierWasInSayAll=False
+
        def __init__(self):
                #: Whether input help is enabled, wherein the function of each 
key pressed by the user is reported but not executed.
                #: @type: bool
@@ -284,6 +293,18 @@ class InputManager(baseObject.AutoPropertyObject):
                if focus.sleepMode is focus.SLEEP_FULL or (focus.sleepMode and 
not getattr(script, 'allowInSleepMode', False)):
                        raise NoInputGestureAction
 
+               wasInSayAll=False
+               if gesture.isModifier:
+                       if not self.lastModifierWasInSayAll:
+                               
wasInSayAll=self.lastModifierWasInSayAll=sayAllHandler.isRunning()
+               elif self.lastModifierWasInSayAll:
+                       wasInSayAll=True
+                       self.lastModifierWasInSayAll=False
+               else:
+                       wasInSayAll=sayAllHandler.isRunning()
+               if wasInSayAll:
+                       gesture.wasInSayAll=True
+
                speechEffect = gesture.speechEffectWhenExecuted
                if speechEffect == gesture.SPEECHEFFECT_CANCEL:
                        queueHandler.queueFunction(queueHandler.eventQueue, 
speech.cancelSpeech)

diff --git a/source/keyboardHandler.py b/source/keyboardHandler.py
index e934d75..b7d68ce 100644
--- a/source/keyboardHandler.py
+++ b/source/keyboardHandler.py
@@ -191,6 +191,11 @@ def internal_keyUpEvent(vkCode,scanCode,extended,injected):
                if keyCode != stickyNVDAModifier:
                        currentModifiers.discard(keyCode)
 
+               # help inputCore  manage its sayAll state for keyboard 
modifiers -- inputCore itself has no concept of key releases
+               if not currentModifiers:
+                       inputCore.manager.lastModifierWasInSayAll=False
+
+
                if keyCode in trappedKeys:
                        trappedKeys.remove(keyCode)
                        return False

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 6e107ee..fa8dabc 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -7,6 +7,9 @@
 import time
 import weakref
 import inspect
+import config
+import speech
+import sayAllHandler
 import appModuleHandler
 import api
 import queueHandler
@@ -153,6 +156,12 @@ def executeScript(script,gesture):
        if _isScriptRunning and lastScriptRef==scriptFunc:
                return gesture.send()
        _isScriptRunning=True
+       resumeSayAllMode=None
+       if config.conf['keyboard']['allowSkimReadingInSayAll']and 
gesture.wasInSayAll and 
getattr(script,'resumeSayAllMode',None)==sayAllHandler.lastSayAllMode:
+               resumeSayAllMode=sayAllHandler.lastSayAllMode
+       if resumeSayAllMode is not None:
+               oldSpeechMode=speech.speechMode
+               speech.speechMode=speech.speechMode_off
        try:
                scriptTime=time.time()
                scriptRef=weakref.ref(scriptFunc)
@@ -167,6 +176,9 @@ def executeScript(script,gesture):
                log.exception("error executing script: %s with gesture 
%r"%(script,gesture.displayName))
        finally:
                _isScriptRunning=False
+               if resumeSayAllMode is not None:
+                       speech.speechMode=oldSpeechMode
+                       sayAllHandler.readText(resumeSayAllMode)
 
 def getLastScriptRepeatCount():
        """The count of how many times the most recent script has been executed.
@@ -206,3 +218,4 @@ def isCurrentScript(scriptFunc):
                log.debugWarning("Could not get unbound method from parent 
frame instance",exc_info=True)
                return False
        return givenFunc==realFunc
+


https://bitbucket.org/nvdaaddonteam/nvda/commits/35cf14d1c4d6/
Changeset:   35cf14d1c4d6
Branch:      None
User:        mdcurran
Date:        2013-09-13 05:24:33
Summary:     Mark various scripts with the appropriate resumeSayAllMode 
property. These include browse mode quick nav, cursor manager line, paragraph 
and page movement, all marked as caret. Editable text line and paragraph marked 
as caret. And review previous line / next line marked as review.

Affected #:  4 files

diff --git a/source/cursorManager.py b/source/cursorManager.py
index 9ae3b89..4ad30dd 100644
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -12,6 +12,7 @@ A cursor manager provides caret navigation and selection 
commands for a virtual
 import wx
 import baseObject
 import gui
+import sayAllHandler
 import textInfos
 import api
 import speech
@@ -127,9 +128,11 @@ class CursorManager(baseObject.ScriptableObject):
 
        def script_moveByPage_back(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_LINE,-config.conf["virtualBuffers"]["linesPerPage"],extraDetail=False)
+       script_moveByPage_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByPage_forward(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_LINE,config.conf["virtualBuffers"]["linesPerPage"],extraDetail=False)
+       script_moveByPage_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByCharacter_back(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_CHARACTER,-1,extraDetail=True,handleSymbols=True)
@@ -145,15 +148,19 @@ class CursorManager(baseObject.ScriptableObject):
 
        def script_moveByLine_back(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_LINE,-1)
+       script_moveByLine_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByLine_forward(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_LINE,1)
+       script_moveByLine_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByParagraph_back(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_PARAGRAPH,-1)
+       script_moveByParagraph_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByParagraph_forward(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_PARAGRAPH,1)
+       
script_moveByParagraph_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_startOfLine(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_CHARACTER,posUnit=textInfos.UNIT_LINE,extraDetail=True,handleSymbols=True)

diff --git a/source/editableText.py b/source/editableText.py
index 4301556..57a8704 100755
--- a/source/editableText.py
+++ b/source/editableText.py
@@ -10,6 +10,7 @@
 """
 
 import time
+import sayAllHandler
 import api
 import review
 from baseObject import ScriptableObject
@@ -99,6 +100,7 @@ class EditableText(ScriptableObject):
 
        def script_caret_moveByLine(self,gesture):
                self._caretMovementScriptHelper(gesture, textInfos.UNIT_LINE)
+       script_caret_moveByLine.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_caret_moveByCharacter(self,gesture):
                self._caretMovementScriptHelper(gesture, 
textInfos.UNIT_CHARACTER)
@@ -108,6 +110,8 @@ class EditableText(ScriptableObject):
 
        def script_caret_moveByParagraph(self,gesture):
                self._caretMovementScriptHelper(gesture, 
textInfos.UNIT_PARAGRAPH)
+       script_caret_moveByParagraph.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+
 
        def _backspaceScriptHelper(self,unit,gesture):
                try:

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 7283e14..614204e 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -521,6 +521,7 @@ class GlobalCommands(ScriptableObject):
                
speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
        # Translators: Input help mode message for move review cursor to 
previous line command.
        script_review_previousLine.__doc__=_("Moves the review cursor to the 
previous line of the current navigator object and speaks it")
+       script_review_previousLine.resumeSayAllMode=sayAllHandler.CURSOR_REVIEW
 
        def script_review_currentLine(self,gesture):
                info=api.getReviewPosition().copy()
@@ -546,6 +547,7 @@ class GlobalCommands(ScriptableObject):
                
speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
        # Translators: Input help mode message for move review cursor to next 
line command.
        script_review_nextLine.__doc__=_("Moves the review cursor to the next 
line of the current navigator object and speaks it")
+       script_review_nextLine.resumeSayAllMode=sayAllHandler.CURSOR_REVIEW
 
        def script_review_bottom(self,gesture):
                
info=api.getReviewPosition().obj.makeTextInfo(textInfos.POSITION_LAST)

diff --git a/source/virtualBuffers/__init__.py 
b/source/virtualBuffers/__init__.py
index 0cdccd6..9468894 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -929,6 +929,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
                script = lambda self,gesture: self._quickNavScript(gesture, 
nodeType, "next", nextError, readUnit)
                script.__doc__ = nextDoc
                script.__name__ = funcName
+               script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
                setattr(cls, funcName, script)
                cls.__gestures["kb:%s" % key] = scriptName
                scriptName = "previous%s" % scriptSuffix
@@ -936,6 +937,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
                script = lambda self,gesture: self._quickNavScript(gesture, 
nodeType, "previous", prevError, readUnit)
                script.__doc__ = prevDoc
                script.__name__ = funcName
+               script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
                setattr(cls, funcName, script)
                cls.__gestures["kb:shift+%s" % key] = scriptName
 
@@ -1339,6 +1341,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
        # Translators: the description for the next table row script on 
virtualBuffers.
        script_nextRow.__doc__ = _("moves to the next table row")
 
+
        def script_previousRow(self, gesture):
                self._tableMovementScriptHelper(axis="row", movement="previous")
        # Translators: the description for the previous table row script on 
virtualBuffers.


https://bitbucket.org/nvdaaddonteam/nvda/commits/61f17c11034f/
Changeset:   61f17c11034f
Branch:      None
User:        mdcurran
Date:        2013-09-13 05:27:47
Summary:     GUI: add an 'allow skim reading in say all' option  to the 
keyboard settings dialog.

Affected #:  1 file

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index 534532d..8635c77 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -639,6 +639,11 @@ class KeyboardSettingsDialog(SettingsDialog):
                
settingsSizer.Add(self.speechInterruptForEnterCheckBox,border=10,flag=wx.BOTTOM)
                # Translators: This is the label for a checkbox in the
                # keyboard settings dialog.
+               
self.skimReadingInSayAllCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Allow 
skim &reading in Say All"))
+               
self.skimReadingInSayAllCheckBox.SetValue(config.conf["keyboard"]["allowSkimReadingInSayAll"])
+               
settingsSizer.Add(self.skimReadingInSayAllCheckBox,border=10,flag=wx.BOTTOM)
+               # Translators: This is the label for a checkbox in the
+               # keyboard settings dialog.
                
self.beepLowercaseCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Beep if typing 
lowercase letters when caps lock is on"))
                
self.beepLowercaseCheckBox.SetValue(config.conf["keyboard"]["beepForLowercaseWithCapslock"])
                
settingsSizer.Add(self.beepLowercaseCheckBox,border=10,flag=wx.BOTTOM)
@@ -661,6 +666,7 @@ class KeyboardSettingsDialog(SettingsDialog):
                
config.conf["keyboard"]["speakTypedWords"]=self.wordsCheckBox.IsChecked()
                
config.conf["keyboard"]["speechInterruptForCharacters"]=self.speechInterruptForCharsCheckBox.IsChecked()
                
config.conf["keyboard"]["speechInterruptForEnter"]=self.speechInterruptForEnterCheckBox.IsChecked()
+               
config.conf["keyboard"]["allowSkimReadingInSayAll"]=self.skimReadingInSayAllCheckBox.IsChecked()
                
config.conf["keyboard"]["beepForLowercaseWithCapslock"]=self.beepLowercaseCheckBox.IsChecked()
                
config.conf["keyboard"]["speakCommandKeys"]=self.commandKeysCheckBox.IsChecked()
                super(KeyboardSettingsDialog, self).onOk(evt)


https://bitbucket.org/nvdaaddonteam/nvda/commits/9ad7d6ae94f9/
Changeset:   9ad7d6ae94f9
Branch:      None
User:        mdcurran
Date:        2013-09-13 05:28:37
Summary:     Update the user guide to mention the 'allow skim reading in say 
all' setting.

Affected #:  1 file

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 7d42534..fe20e7f 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -800,6 +800,9 @@ If on, this option will cause speech to be interrupted each 
time a character is
 ==== Speech interrupt for Enter key ====
 If on, this option will cause speech to be interrupted each time the Enter key 
is pressed. This is on by default.
 
+==== Allow skim reading in Say All ====
+If on, certain navigation commands (such as quick navigation in browse mode or 
moving by line or paragraph) do not stop Say All, rather Say All jumps to the 
new position and continues reading.
+ 
 ==== Beep if Typing Lowercase Letters when Caps Lock is On ====
 When enabled, a warning beep will be heard if a letter is typed with the shift 
key while caps lock is on.
 Generally, typing shifted letters with caps lock is unintentional and is 
usually due to not realising that caps lock is enabled.


https://bitbucket.org/nvdaaddonteam/nvda/commits/17c8f977a349/
Changeset:   17c8f977a349
Branch:      None
User:        mdcurran
Date:        2013-09-16 03:13:02
Summary:     Merge branch 'master' into next

Affected #:  1 file

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 1d56024..512f347 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -21,6 +21,7 @@
 - NVDA will now report the pinned state for pinned controls such as tabs in 
Mozilla Firefox. (#3372)
 - It is now possible to bind scripts to keyboard gestures containing Alt 
and/or Windows keys as modifiers. Previously, if this was done, performing the 
script would cause the Start Menu or menu bar to be activated. (#3472)
 - Selecting text in browse mode documents (e.g. using control+shift+end) no 
longer causes the keyboard layout to be switched on systems with multiple 
keyboard layouts installed. (#3472)
+- Internet Explorer should no longer crash or become unusable when closing 
NVDA. (#3397)
 
 
 = 2013.2 =


https://bitbucket.org/nvdaaddonteam/nvda/commits/04dff7b9aec1/
Changeset:   04dff7b9aec1
Branch:      None
User:        mdcurran
Date:        2013-09-16 03:39:59
Summary:     Merge branch 't2766' into next. Incubates #2766

Affected #:  11 files

diff --git a/source/config/__init__.py b/source/config/__init__.py
index 1bf36dc..01cad05 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -103,6 +103,7 @@ confspec = ConfigObj(StringIO(
        speakCommandKeys = boolean(default=false)
        speechInterruptForCharacters = boolean(default=true)
        speechInterruptForEnter = boolean(default=true)
+       allowSkimReadingInSayAll = boolean(default=False)
 
 [virtualBuffers]
        maxLineLength = integer(default=100)

diff --git a/source/cursorManager.py b/source/cursorManager.py
index 74c2f51..7433508 100644
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -12,6 +12,7 @@ A cursor manager provides caret navigation and selection 
commands for a virtual
 import wx
 import baseObject
 import gui
+import sayAllHandler
 import textInfos
 import api
 import speech
@@ -131,9 +132,11 @@ class CursorManager(baseObject.ScriptableObject):
 
        def script_moveByPage_back(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_LINE,-config.conf["virtualBuffers"]["linesPerPage"],extraDetail=False)
+       script_moveByPage_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByPage_forward(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_LINE,config.conf["virtualBuffers"]["linesPerPage"],extraDetail=False)
+       script_moveByPage_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByCharacter_back(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_CHARACTER,-1,extraDetail=True,handleSymbols=True)
@@ -149,15 +152,19 @@ class CursorManager(baseObject.ScriptableObject):
 
        def script_moveByLine_back(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_LINE,-1)
+       script_moveByLine_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByLine_forward(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_LINE,1)
+       script_moveByLine_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByParagraph_back(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_PARAGRAPH,-1)
+       script_moveByParagraph_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_moveByParagraph_forward(self,gesture):
                self._caretMovementScriptHelper(textInfos.UNIT_PARAGRAPH,1)
+       
script_moveByParagraph_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_startOfLine(self,gesture):
                
self._caretMovementScriptHelper(textInfos.UNIT_CHARACTER,posUnit=textInfos.UNIT_LINE,extraDetail=True,handleSymbols=True)

diff --git a/source/editableText.py b/source/editableText.py
index 4301556..57a8704 100755
--- a/source/editableText.py
+++ b/source/editableText.py
@@ -10,6 +10,7 @@
 """
 
 import time
+import sayAllHandler
 import api
 import review
 from baseObject import ScriptableObject
@@ -99,6 +100,7 @@ class EditableText(ScriptableObject):
 
        def script_caret_moveByLine(self,gesture):
                self._caretMovementScriptHelper(gesture, textInfos.UNIT_LINE)
+       script_caret_moveByLine.resumeSayAllMode=sayAllHandler.CURSOR_CARET
 
        def script_caret_moveByCharacter(self,gesture):
                self._caretMovementScriptHelper(gesture, 
textInfos.UNIT_CHARACTER)
@@ -108,6 +110,8 @@ class EditableText(ScriptableObject):
 
        def script_caret_moveByParagraph(self,gesture):
                self._caretMovementScriptHelper(gesture, 
textInfos.UNIT_PARAGRAPH)
+       script_caret_moveByParagraph.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+
 
        def _backspaceScriptHelper(self,unit,gesture):
                try:

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 3b9b975..18ea815 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -590,6 +590,7 @@ class GlobalCommands(ScriptableObject):
        # Translators: Input help mode message for move review cursor to 
previous line command.
        script_review_previousLine.__doc__=_("Moves the review cursor to the 
previous line of the current navigator object and speaks it")
        script_review_previousLine.category=SCRCAT_TEXTREVIEW
+       script_review_previousLine.resumeSayAllMode=sayAllHandler.CURSOR_REVIEW
 
        def script_review_currentLine(self,gesture):
                info=api.getReviewPosition().copy()
@@ -617,6 +618,7 @@ class GlobalCommands(ScriptableObject):
        # Translators: Input help mode message for move review cursor to next 
line command.
        script_review_nextLine.__doc__=_("Moves the review cursor to the next 
line of the current navigator object and speaks it")
        script_review_nextLine.category=SCRCAT_TEXTREVIEW
+       script_review_nextLine.resumeSayAllMode=sayAllHandler.CURSOR_REVIEW
 
        def script_review_bottom(self,gesture):
                
info=api.getReviewPosition().obj.makeTextInfo(textInfos.POSITION_LAST)

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index e6b8ce3..0fdf86a 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -640,6 +640,11 @@ class KeyboardSettingsDialog(SettingsDialog):
                
settingsSizer.Add(self.speechInterruptForEnterCheckBox,border=10,flag=wx.BOTTOM)
                # Translators: This is the label for a checkbox in the
                # keyboard settings dialog.
+               
self.skimReadingInSayAllCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Allow 
skim &reading in Say All"))
+               
self.skimReadingInSayAllCheckBox.SetValue(config.conf["keyboard"]["allowSkimReadingInSayAll"])
+               
settingsSizer.Add(self.skimReadingInSayAllCheckBox,border=10,flag=wx.BOTTOM)
+               # Translators: This is the label for a checkbox in the
+               # keyboard settings dialog.
                
self.beepLowercaseCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Beep if typing 
lowercase letters when caps lock is on"))
                
self.beepLowercaseCheckBox.SetValue(config.conf["keyboard"]["beepForLowercaseWithCapslock"])
                
settingsSizer.Add(self.beepLowercaseCheckBox,border=10,flag=wx.BOTTOM)
@@ -662,6 +667,7 @@ class KeyboardSettingsDialog(SettingsDialog):
                
config.conf["keyboard"]["speakTypedWords"]=self.wordsCheckBox.IsChecked()
                
config.conf["keyboard"]["speechInterruptForCharacters"]=self.speechInterruptForCharsCheckBox.IsChecked()
                
config.conf["keyboard"]["speechInterruptForEnter"]=self.speechInterruptForEnterCheckBox.IsChecked()
+               
config.conf["keyboard"]["allowSkimReadingInSayAll"]=self.skimReadingInSayAllCheckBox.IsChecked()
                
config.conf["keyboard"]["beepForLowercaseWithCapslock"]=self.beepLowercaseCheckBox.IsChecked()
                
config.conf["keyboard"]["speakCommandKeys"]=self.commandKeysCheckBox.IsChecked()
                super(KeyboardSettingsDialog, self).onOk(evt)

diff --git a/source/inputCore.py b/source/inputCore.py
index 67292d3..30f6c4b 100644
--- a/source/inputCore.py
+++ b/source/inputCore.py
@@ -15,6 +15,7 @@ import os
 import itertools
 import weakref
 import configobj
+import sayAllHandler
 import baseObject
 import scriptHandler
 import queueHandler
@@ -49,6 +50,10 @@ class InputGesture(baseObject.AutoPropertyObject):
        """
        cachePropertiesByDefault = True
 
+       #: indicates that sayAll was running before this gesture
+       #: @type: bool
+       wasInSayAll=False
+
        def _get_identifiers(self):
                """The identifier(s) which will be used in input gesture maps 
to represent this gesture.
                These identifiers will be looked up in order until a match is 
found.
@@ -348,6 +353,10 @@ class InputManager(baseObject.AutoPropertyObject):
        Input includes key presses on the keyboard, as well as key presses on 
Braille displays, etc.
        """
 
+       #: a modifier gesture was just executed while sayAll was running
+       #: @type: bool
+       lastModifierWasInSayAll=False
+
        def __init__(self):
                #: The function to call when capturing gestures.
                #: If it returns C{False}, normal execution will be prevented.
@@ -379,6 +388,18 @@ class InputManager(baseObject.AutoPropertyObject):
                if focus.sleepMode is focus.SLEEP_FULL or (focus.sleepMode and 
not getattr(script, 'allowInSleepMode', False)):
                        raise NoInputGestureAction
 
+               wasInSayAll=False
+               if gesture.isModifier:
+                       if not self.lastModifierWasInSayAll:
+                               
wasInSayAll=self.lastModifierWasInSayAll=sayAllHandler.isRunning()
+               elif self.lastModifierWasInSayAll:
+                       wasInSayAll=True
+                       self.lastModifierWasInSayAll=False
+               else:
+                       wasInSayAll=sayAllHandler.isRunning()
+               if wasInSayAll:
+                       gesture.wasInSayAll=True
+
                speechEffect = gesture.speechEffectWhenExecuted
                if speechEffect == gesture.SPEECHEFFECT_CANCEL:
                        queueHandler.queueFunction(queueHandler.eventQueue, 
speech.cancelSpeech)

diff --git a/source/keyboardHandler.py b/source/keyboardHandler.py
index 139eed2..63d34c7 100644
--- a/source/keyboardHandler.py
+++ b/source/keyboardHandler.py
@@ -192,6 +192,11 @@ def internal_keyUpEvent(vkCode,scanCode,extended,injected):
                if keyCode != stickyNVDAModifier:
                        currentModifiers.discard(keyCode)
 
+               # help inputCore  manage its sayAll state for keyboard 
modifiers -- inputCore itself has no concept of key releases
+               if not currentModifiers:
+                       inputCore.manager.lastModifierWasInSayAll=False
+
+
                if keyCode in trappedKeys:
                        trappedKeys.remove(keyCode)
                        return False

diff --git a/source/sayAllHandler.py b/source/sayAllHandler.py
index 1a3043f..d62e46d 100644
--- a/source/sayAllHandler.py
+++ b/source/sayAllHandler.py
@@ -19,6 +19,7 @@ CURSOR_CARET=0
 CURSOR_REVIEW=1
 
 _generatorID = None
+lastSayAllMode=None
 
 def _startGenerator(generator):
        global _generatorID
@@ -90,6 +91,8 @@ def readObjectsHelper_generator(obj):
                yield
 
 def readText(cursor):
+       global lastSayAllMode
+       lastSayAllMode=cursor
        _startGenerator(readTextHelper_generator(cursor))
 
 def readTextHelper_generator(cursor):

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 6e107ee..fa8dabc 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -7,6 +7,9 @@
 import time
 import weakref
 import inspect
+import config
+import speech
+import sayAllHandler
 import appModuleHandler
 import api
 import queueHandler
@@ -153,6 +156,12 @@ def executeScript(script,gesture):
        if _isScriptRunning and lastScriptRef==scriptFunc:
                return gesture.send()
        _isScriptRunning=True
+       resumeSayAllMode=None
+       if config.conf['keyboard']['allowSkimReadingInSayAll']and 
gesture.wasInSayAll and 
getattr(script,'resumeSayAllMode',None)==sayAllHandler.lastSayAllMode:
+               resumeSayAllMode=sayAllHandler.lastSayAllMode
+       if resumeSayAllMode is not None:
+               oldSpeechMode=speech.speechMode
+               speech.speechMode=speech.speechMode_off
        try:
                scriptTime=time.time()
                scriptRef=weakref.ref(scriptFunc)
@@ -167,6 +176,9 @@ def executeScript(script,gesture):
                log.exception("error executing script: %s with gesture 
%r"%(script,gesture.displayName))
        finally:
                _isScriptRunning=False
+               if resumeSayAllMode is not None:
+                       speech.speechMode=oldSpeechMode
+                       sayAllHandler.readText(resumeSayAllMode)
 
 def getLastScriptRepeatCount():
        """The count of how many times the most recent script has been executed.
@@ -206,3 +218,4 @@ def isCurrentScript(scriptFunc):
                log.debugWarning("Could not get unbound method from parent 
frame instance",exc_info=True)
                return False
        return givenFunc==realFunc
+

diff --git a/source/virtualBuffers/__init__.py 
b/source/virtualBuffers/__init__.py
index 0cdccd6..9468894 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -929,6 +929,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
                script = lambda self,gesture: self._quickNavScript(gesture, 
nodeType, "next", nextError, readUnit)
                script.__doc__ = nextDoc
                script.__name__ = funcName
+               script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
                setattr(cls, funcName, script)
                cls.__gestures["kb:%s" % key] = scriptName
                scriptName = "previous%s" % scriptSuffix
@@ -936,6 +937,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
                script = lambda self,gesture: self._quickNavScript(gesture, 
nodeType, "previous", prevError, readUnit)
                script.__doc__ = prevDoc
                script.__name__ = funcName
+               script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
                setattr(cls, funcName, script)
                cls.__gestures["kb:shift+%s" % key] = scriptName
 
@@ -1339,6 +1341,7 @@ class VirtualBuffer(cursorManager.CursorManager, 
treeInterceptorHandler.TreeInte
        # Translators: the description for the next table row script on 
virtualBuffers.
        script_nextRow.__doc__ = _("moves to the next table row")
 
+
        def script_previousRow(self, gesture):
                self._tableMovementScriptHelper(axis="row", movement="previous")
        # Translators: the description for the previous table row script on 
virtualBuffers.

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 4967ef7..df6f381 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -800,6 +800,9 @@ If on, this option will cause speech to be interrupted each 
time a character is
 ==== Speech interrupt for Enter key ====
 If on, this option will cause speech to be interrupted each time the Enter key 
is pressed. This is on by default.
 
+==== Allow skim reading in Say All ====
+If on, certain navigation commands (such as quick navigation in browse mode or 
moving by line or paragraph) do not stop Say All, rather Say All jumps to the 
new position and continues reading.
+ 
 ==== Beep if Typing Lowercase Letters when Caps Lock is On ====
 When enabled, a warning beep will be heard if a letter is typed with the shift 
key while caps lock is on.
 Generally, typing shifted letters with caps lock is unintentional and is 
usually due to not realising that caps lock is enabled.


https://bitbucket.org/nvdaaddonteam/nvda/commits/603494add2b7/
Changeset:   603494add2b7
Branch:      None
User:        mdcurran
Date:        2013-09-16 04:01:39
Summary:     Merge branch 'master' into t1686

Affected #:  83 files

diff --git a/contributors.txt b/contributors.txt
index ed1df41..8e64bbc 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -131,5 +131,8 @@ Juan Pablo Martínez Cortés
 Marat Suleymanov
 Rui Fontes (Tiflotecnia, lda.)
 Kevin Scannell
+Ali Aslani
 Hamid Rezaey
 Bue Vester-Andersen
+Yogesh Kumar
+Grzegorz Zlotowicz

diff --git a/include/minhook b/include/minhook
index ff0888d..e21b54a 160000
--- a/include/minhook
+++ b/include/minhook
@@ -1 +1 @@
-Subproject commit ff0888de0d34399e69155481f70b9e11b771eebe
+Subproject commit e21b54a88190ca477ed73fb7ab24203dfaef28a0

diff --git a/nvdaHelper/minHook/dllmain.cpp b/nvdaHelper/minHook/dllmain.cpp
new file mode 100644
index 0000000..25d6823
--- /dev/null
+++ b/nvdaHelper/minHook/dllmain.cpp
@@ -0,0 +1,28 @@
+/*
+This file is a part of the NVDA project.
+URL: http://www.nvda-project.org/
+Copyright 2006-2010 NVDA contributers.
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2.0, as 
published by
+    the Free Software Foundation.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+This license can be found at:
+http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+*/
+
+#include <windows.h>
+#include <minhook.h>
+
+BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) {
+       //Process exiting, we must clean up any pending hooks
+       if(reason==DLL_PROCESS_DETACH&&lpReserved) {
+               if(MH_DisableAllHooks()!=MH_ERROR_NOT_INITIALIZED) {
+                       //Give enough time for all hook functions to complete.
+                       Sleep(250);
+                       MH_Uninitialize();
+               }
+       }
+       return 1;
+}

diff --git a/nvdaHelper/minHook/minHook.def b/nvdaHelper/minHook/minHook.def
deleted file mode 100644
index 75e1b07..0000000
--- a/nvdaHelper/minHook/minHook.def
+++ /dev/null
@@ -1,8 +0,0 @@
-EXPORTS
-       MH_Initialize
-       MH_Uninitialize
-       MH_CreateHook
-       MH_EnableHook
-       MH_DisableHook
-       MH_EnableAllHooks
-       MH_DisableAllHooks

diff --git a/nvdaHelper/minHook/newHook.cpp b/nvdaHelper/minHook/newHook.cpp
deleted file mode 100644
index 06778b8..0000000
--- a/nvdaHelper/minHook/newHook.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-This file is a part of the NVDA project.
-URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License version 2.0, as 
published by
-    the Free Software Foundation.
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-This license can be found at:
-http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-*/
-
-#include <windows.h>
-#include "hook.cpp"
-
-using namespace MinHook;
-
-//Based on MH_EnableHook from minHook
-MH_STATUS _doAllHooks(bool enable) {
-       CriticalSection::ScopedLock lock(gCS);
-       if (!gIsInitialized) {
-               return MH_ERROR_NOT_INITIALIZED;
-       }
-       std::vector<uintptr_t> oldIPs;
-       std::vector<uintptr_t> newIPs;
-       for(std::vector<HOOK_ENTRY>::iterator 
hooksIter=gHooks.begin();hooksIter!=gHooks.end();++hooksIter) {
-               
oldIPs.insert(oldIPs.end(),hooksIter->oldIPs.begin(),hooksIter->oldIPs.end());
-               
newIPs.insert(newIPs.end(),hooksIter->newIPs.begin(),hooksIter->newIPs.end());
-       }
-       {
-               ScopedThreadExclusive tex(oldIPs, newIPs);
-               for(std::vector<HOOK_ENTRY>::iterator 
hooksIter=gHooks.begin();hooksIter!=gHooks.end();++hooksIter) {
-                       HOOK_ENTRY*pHook=&(*hooksIter);
-                       if (pHook->isEnabled==enable) continue;
-                       DWORD oldProtect;
-                       if (!VirtualProtect(pHook->pTarget, sizeof(JMP_REL), 
PAGE_EXECUTE_READWRITE, &oldProtect)) {
-                               return MH_ERROR_MEMORY_PROTECT;
-                       }
-                       if(enable) {
-#if defined _M_X64
-                               WriteRelativeJump(pHook->pTarget, 
pHook->pRelay);
-#elif defined _M_IX86
-                               WriteRelativeJump(pHook->pTarget, 
pHook->pDetour);
-#endif
-                       } else {
-                               memcpy(pHook->pTarget, pHook->pBackup, 
sizeof(JMP_REL));
-                       }
-                       VirtualProtect(pHook->pTarget, sizeof(JMP_REL), 
oldProtect, &oldProtect);
-                               pHook->isEnabled = enable;
-               }
-       }
-       return MH_OK;
-}
-
-MH_STATUS MH_EnableAllHooks() {
-       return _doAllHooks(true);
-}
-
-MH_STATUS MH_DisableAllHooks() {
-       return _doAllHooks(false);
-}
-
-BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) {
-       //Process exiting, we must clean up any pending hooks
-       if(reason==DLL_PROCESS_DETACH&&lpReserved) {
-               if(gIsInitialized) {
-                       MH_DisableAllHooks();
-                       //Give enough time for all hook functions to complete.
-                       Sleep(250);
-                       MH_Uninitialize();
-               }
-       }
-       return 1;
-}

diff --git a/nvdaHelper/minHook/newMinHook.h b/nvdaHelper/minHook/newMinHook.h
deleted file mode 100644
index 831d612..0000000
--- a/nvdaHelper/minHook/newMinHook.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-This file is a part of the NVDA project.
-URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License version 2.0, as 
published by
-    the Free Software Foundation.
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-This license can be found at:
-http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-*/
-
-#ifndef NVDAHELPER_NEWMINHOOK_H
-#define NVDAHELPER_NEWMINHOOK_H
-
-#include <minhook/libMinHook/minHook.h>
-
-//Some new batch calls
-MH_STATUS MH_EnableAllHooks();
-MH_STATUS MH_DisableAllHooks();
-
-//function pointer typedefs for all minHook functions for use with 
getProcAddress
-typedef MH_STATUS(WINAPI *MH_Initialize_funcType)();
-typedef MH_STATUS(WINAPI *MH_Uninitialize_funcType)();
-typedef MH_STATUS(WINAPI *MH_CreateHook_funcType)(void*,void*,void**);
-typedef MH_STATUS(WINAPI *MH_EnableHook_funcType)(void*);
-typedef MH_STATUS(WINAPI *MH_DisableHook_funcType)(void*);
-typedef MH_STATUS(*MH_EnableAllHooks_funcType)();
-typedef MH_STATUS(*MH_DisableAllHooks_funcType)();
-
-#endif

diff --git a/nvdaHelper/minHook/sconscript b/nvdaHelper/minHook/sconscript
index c076a68..497a242 100644
--- a/nvdaHelper/minHook/sconscript
+++ b/nvdaHelper/minHook/sconscript
@@ -2,19 +2,27 @@ Import([
        'env',
 ])
 
+
+minhookPath=Dir('#include/minhook')
+env=env.Clone(CPPPATH=minhookPath.Dir('include'))
+
 HDESourceFile='HDE64/src/HDE64.c' if env['TARGET_ARCH']=='x86_64' else 
'HDE32/HDE32.c'
 
 sourceFiles=[
        HDESourceFile,
        'buffer.cpp',
        'export.cpp',
+       'hook.cpp',
        'thread.cpp',
        'trampoline.cpp',
 ]
 
-objFiles=[env.Object('_minHook_%s.obj'%x.replace('/','_'),'#/include/minhook/libMinHook/src/%s'%x)
 for x in sourceFiles]
-objFiles.append(env.Object('newHook.cpp',CPPPATH=['#include/minhook/libMinHook/src','${CPPPATH}']))
+objFiles=[env.Object('_minHook_%s.obj'%x.replace('/','_'),minhookPath.File('src/%s'%x))
 for x in sourceFiles]
+objFiles.append('dllmain.cpp')
 
-minHookLib=env.SharedLibrary('minHook',objFiles+['minHook.def'])
+minHookLib=env.SharedLibrary(
+       target='minHook',
+       source=objFiles+[minhookPath.File('dll_resources/minHook.def')],
+)
 
 Return('minHookLib')

diff --git a/nvdaHelper/remote/apiHook.cpp b/nvdaHelper/remote/apiHook.cpp
index 3a5955b..0a3430b 100644
--- a/nvdaHelper/remote/apiHook.cpp
+++ b/nvdaHelper/remote/apiHook.cpp
@@ -17,7 +17,7 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 #define WIN32_LEAN_AND_MEAN 
 #include <windows.h>
 #include <delayimp.h>
-#include <minHook/newMinHook.h>
+#include <minhook/include/minhook.h>
 #include "nvdaControllerInternal.h"
 #include <common/log.h>
 #include "dllmain.h"
@@ -33,6 +33,15 @@ functionSet_t g_hookedFunctions;
 HMODULE minhookLibHandle=NULL;
 bool error_setNHFP=false;
 
+//function pointer typedefs for all minHook functions for use with 
getProcAddress
+typedef MH_STATUS(WINAPI *MH_Initialize_funcType)();
+typedef MH_STATUS(WINAPI *MH_Uninitialize_funcType)();
+typedef MH_STATUS(WINAPI *MH_CreateHook_funcType)(void*,void*,void**);
+typedef MH_STATUS(WINAPI *MH_EnableHook_funcType)(void*);
+typedef MH_STATUS(WINAPI *MH_DisableHook_funcType)(void*);
+typedef MH_STATUS(*MH_EnableAllHooks_funcType)();
+typedef MH_STATUS(*MH_DisableAllHooks_funcType)();
+
 #define defMHFP(funcName) funcName##_funcType funcName##_fp=NULL
 
 #define setMHFP(funcName) {\

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index 6535727..7743ad5 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -35,6 +35,11 @@ using namespace std;
 #define wdDISPID_SELECTION_RANGE 400
 #define wdDISPID_SELECTION_SETRANGE 100
 #define wdDISPID_SELECTION_STARTISACTIVE 404
+#define wdDISPID_RANGE_INRANGE 126
+#define wdDISPID_RANGE_DUPLICATE 6
+#define wdDISPID_RANGE_REVISIONS 150
+#define wdDISPID_REVISIONS_ITEM 0
+#define wdDISPID_REVISION_TYPE 4
 #define wdDISPID_RANGE_STORYTYPE 7
 #define wdDISPID_RANGE_MOVEEND 111
 #define wdDISPID_RANGE_COLLAPSE 101
@@ -47,6 +52,19 @@ using namespace std;
 #define wdDISPID_RANGE_INFORMATION 313
 #define wdDISPID_RANGE_STYLE 151
 #define wdDISPID_RANGE_LANGUAGEID 153
+#define wdDISPID_RANGE_DUPLICATE 6
+#define wdDISPID_RANGE_FORMFIELDS 65
+#define wdDISPID_RANGE_CONTENTCONTROLS 424
+#define wdDISPID_FORMFIELDS_ITEM 0
+#define wdDISPID_FORMFIELD_RANGE 17
+#define wdDISPID_FORMFIELD_TYPE 0
+#define wdDISPID_FORMFIELD_RESULT 10
+#define wdDISPID_FORMFIELD_STATUSTEXT 8
+#define wdDISPID_CONTENTCONTROLS_ITEM 0
+#define wdDISPID_CONTENTCONTROL_RANGE 1
+#define wdDISPID_CONTENTCONTROL_TYPE 5
+#define wdDISPID_CONTENTCONTROL_CHECKED 28
+#define wdDISPID_CONTENTCONTROL_TITLE 12
 #define wdDISPID_STYLE_NAMELOCAL 0
 #define wdDISPID_RANGE_SPELLINGERRORS 316
 #define wdDISPID_SPELLINGERRORS_COUNT 1
@@ -105,6 +123,7 @@ using namespace std;
 
 #define wdCharacter 1
 #define wdWord 2
+#define wdParagraph 4
 #define wdLine 5
 #define wdCharacterFormatting 13
 
@@ -142,6 +161,7 @@ using namespace std;
 #define formatConfig_reportComments 4096
 #define formatConfig_reportHeadings 8192
 #define formatConfig_reportLanguage 16384
+#define formatConfig_reportRevisions 32768
 
 #define formatConfig_fontFlags 
(formatConfig_reportFontName|formatConfig_reportFontSize|formatConfig_reportFontAttributes|formatConfig_reportColor)
 #define formatConfig_initialFormatFlags 
(formatConfig_reportPage|formatConfig_reportLineNumber|formatConfig_reportTables|formatConfig_reportHeadings)
@@ -195,6 +215,70 @@ void winword_expandToLine_helper(HWND hwnd, 
winword_expandToLine_args* args) {
        
_com_dispatch_raw_propput(pDispatchApplication,wdDISPID_APPLICATION_SCREENUPDATING,VT_BOOL,true);
 }
 
+BOOL generateFormFieldXML(IDispatch* pDispatchRange, wostringstream& 
XMLStream, int& chunkEnd) {
+       IDispatchPtr pDispatchRange2=NULL;
+       
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_DUPLICATE,VT_DISPATCH,&pDispatchRange2)!=S_OK||!pDispatchRange2)
 {
+               return false;
+       }
+       
_com_dispatch_raw_method(pDispatchRange2,wdDISPID_RANGE_EXPAND,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdParagraph,1);
+       BOOL foundFormField=false;
+       IDispatchPtr pDispatchFormFields=NULL;
+       
_com_dispatch_raw_propget(pDispatchRange2,wdDISPID_RANGE_FORMFIELDS,VT_DISPATCH,&pDispatchFormFields);
+       if(pDispatchFormFields) for(int 
count=1;!foundFormField&&count<100;++count) {
+               IDispatchPtr pDispatchFormField=NULL;
+               
if(_com_dispatch_raw_method(pDispatchFormFields,wdDISPID_FORMFIELDS_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchFormField,L"\x0003",count)!=S_OK||!pDispatchFormField)
 {
+                       break;
+               }
+               IDispatchPtr pDispatchFormFieldRange=NULL;
+               
if(_com_dispatch_raw_propget(pDispatchFormField,wdDISPID_FORMFIELD_RANGE,VT_DISPATCH,&pDispatchFormFieldRange)!=S_OK||!pDispatchFormFieldRange)
 {
+                       break;
+               }
+               
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_INRANGE,DISPATCH_METHOD,VT_BOOL,&foundFormField,L"\x0009",pDispatchFormFieldRange)!=S_OK||!foundFormField)
 {
+                       continue;
+               }
+               long fieldType=-1;
+               
_com_dispatch_raw_propget(pDispatchFormField,wdDISPID_FORMFIELD_TYPE,VT_I4,&fieldType);
+               BSTR fieldResult=NULL;
+               
_com_dispatch_raw_propget(pDispatchFormField,wdDISPID_FORMFIELD_RESULT,VT_BSTR,&fieldResult);
+               BSTR fieldStatusText=NULL;
+               
_com_dispatch_raw_propget(pDispatchFormField,wdDISPID_FORMFIELD_STATUSTEXT,VT_BSTR,&fieldStatusText);
+               XMLStream<<L"<control wdFieldType=\""<<fieldType<<L"\" 
wdFieldResult=\""<<(fieldResult?fieldResult:L"")<<L"\" 
wdFieldStatusText=\""<<(fieldStatusText?fieldStatusText:L"")<<L"\">";
+               if(fieldResult) SysFreeString(fieldResult);
+               if(fieldStatusText) SysFreeString(fieldStatusText);
+               
_com_dispatch_raw_propget(pDispatchFormFieldRange,wdDISPID_RANGE_END,VT_I4,&chunkEnd);
+               
_com_dispatch_raw_propput(pDispatchRange,wdDISPID_RANGE_END,VT_I4,chunkEnd);
+               break;
+       }
+       if(foundFormField) return true;
+       IDispatchPtr pDispatchContentControls=NULL;
+       
_com_dispatch_raw_propget(pDispatchRange2,wdDISPID_RANGE_CONTENTCONTROLS,VT_DISPATCH,&pDispatchContentControls);
+       if(pDispatchContentControls)for(int 
count=1;!foundFormField&&count<100;++count) {
+               IDispatchPtr pDispatchContentControl=NULL;
+               
if(_com_dispatch_raw_method(pDispatchContentControls,wdDISPID_CONTENTCONTROLS_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchContentControl,L"\x0003",count)!=S_OK||!pDispatchContentControl)
 {
+                       break;
+               }
+               IDispatchPtr pDispatchContentControlRange=NULL;
+               
if(_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_RANGE,VT_DISPATCH,&pDispatchContentControlRange)!=S_OK||!pDispatchContentControlRange)
 {
+                       break;
+               }
+               
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_INRANGE,DISPATCH_METHOD,VT_BOOL,&foundFormField,L"\x0009",pDispatchContentControlRange)!=S_OK||!foundFormField)
 {
+                       continue;
+               }
+               long fieldType=-1;
+               
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_TYPE,VT_I4,&fieldType);
+               BOOL fieldChecked=false;
+               
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_CHECKED,VT_BOOL,&fieldChecked);
+               BSTR fieldTitle=NULL;
+               
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_TITLE,VT_BSTR,&fieldTitle);
+               XMLStream<<L"<control wdContentControlType=\""<<fieldType<<L"\" 
wdContentControlChecked=\""<<fieldChecked<<L"\" 
wdContentControlTitle=\""<<(fieldTitle?fieldTitle:L"")<<L"\">";
+               if(fieldTitle) SysFreeString(fieldTitle);
+               
_com_dispatch_raw_propget(pDispatchContentControlRange,wdDISPID_RANGE_END,VT_I4,&chunkEnd);
+               
_com_dispatch_raw_propput(pDispatchRange,wdDISPID_RANGE_END,VT_I4,chunkEnd);
+               break;
+       }
+       return foundFormField;
+}
+
 int generateHeadingXML(IDispatch* pDispatchRange, wostringstream& XMLStream) {
        IDispatchPtr pDispatchParagraphs=NULL;
        IDispatchPtr pDispatchParagraph=NULL;
@@ -212,6 +296,25 @@ int generateHeadingXML(IDispatch* pDispatchRange, 
wostringstream& XMLStream) {
        return 1;
 }
 
+int getRevisionType(IDispatch* pDispatchOrigRange) {
+       IDispatchPtr pDispatchRange=NULL;
+       //If range is not duplicated here, revisions collection represents 
revisions at the start of the range when it was first created
+       
if(_com_dispatch_raw_propget(pDispatchOrigRange,wdDISPID_RANGE_DUPLICATE,VT_DISPATCH,&pDispatchRange)!=S_OK||!pDispatchRange)
 {
+               return 0;
+       }
+       IDispatchPtr pDispatchRevisions=NULL;
+       
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_REVISIONS,VT_DISPATCH,&pDispatchRevisions)!=S_OK||!pDispatchRevisions)
 {
+               return 0;
+       }
+       IDispatchPtr pDispatchRevision=NULL;
+       
if(_com_dispatch_raw_method(pDispatchRevisions,wdDISPID_REVISIONS_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchRevision,L"\x0003",1)!=S_OK||!pDispatchRevision)
 {
+               return 0;
+       }
+       long revisionType=0;
+       
_com_dispatch_raw_propget(pDispatchRevision,wdDISPID_REVISION_TYPE,VT_I4,&revisionType);
+       return revisionType;
+}
+
 int getHyperlinkCount(IDispatch* pDispatchRange) {
        IDispatchPtr pDispatchHyperlinks=NULL;
        int count=0;
@@ -365,6 +468,10 @@ void generateXMLAttribsForFormatting(IDispatch* 
pDispatchRange, int startOffset,
        
if((formatConfig&formatConfig_reportLinks)&&getHyperlinkCount(pDispatchRange)>0)
 {
                formatAttribsStream<<L"link=\"1\" ";
        }
+       if(formatConfig&formatConfig_reportRevisions) {
+               long revisionType=getRevisionType(pDispatchRange);
+               formatAttribsStream<<L"wdRevisionType=\""<<revisionType<<L"\" ";
+       }
        if(formatConfig&formatConfig_reportStyle) {
                IDispatchPtr pDispatchStyle=NULL;
                
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_STYLE,VT_DISPATCH,&pDispatchStyle)==S_OK&&pDispatchStyle)
 {
@@ -556,15 +663,28 @@ void winword_getTextInRange_helper(HWND hwnd, 
winword_getTextInRange_args* args)
        int chunkEndOffset=chunkStartOffset;
        int unitsMoved=0;
        BSTR text=NULL;
+       if(initialFormatConfig&formatConfig_reportTables) {
+               
neededClosingControlTagCount+=generateTableXML(pDispatchRange,args->startOffset,args->endOffset,XMLStream);
+       }
+       if(initialFormatConfig&formatConfig_reportHeadings) {
+               
neededClosingControlTagCount+=generateHeadingXML(pDispatchRange,XMLStream);
+       }
+       
generateXMLAttribsForFormatting(pDispatchRange,chunkStartOffset,chunkEndOffset,initialFormatConfig,initialFormatAttribsStream);
+       bool firstLoop=true;
        //Walk the range from the given start to end by characterFormatting or 
word units
        //And grab any text and formatting and generate appropriate xml
-       bool firstLoop=true;
        do {
-               //Move the end by word
-               
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdWord,1)!=S_OK||unitsMoved<=0)
 {
-                       break;
+               int curDisabledFormatConfig=0;
+               //generated form field xml if in a form field
+               //Also automatically extends the range and chunkEndOffset to 
the end of the field
+               BOOL 
isFormField=generateFormFieldXML(pDispatchRange,XMLStream,chunkEndOffset);
+               if(!isFormField) {
+                       //Move the end by word
+                       
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdWord,1)!=S_OK||unitsMoved<=0)
 {
+                               break;
+                       }
+                       
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_END,VT_I4,&chunkEndOffset);
                }
-               
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_END,VT_I4,&chunkEndOffset);
                //Make sure  that the end is not past the requested end after 
the move
                if(chunkEndOffset>(args->endOffset)) {
                        
_com_dispatch_raw_propput(pDispatchRange,wdDISPID_RANGE_END,VT_I4,args->endOffset);
@@ -576,34 +696,33 @@ void winword_getTextInRange_helper(HWND hwnd, 
winword_getTextInRange_args* args)
                        break;
                }
                
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_TEXT,VT_BSTR,&text);
+               if(!text) SysAllocString(L"");
                if(text) {
-                       //Force a new chunk before and after control+b (note 
characters)
                        int noteCharOffset=-1;
-                       for(int i=0;text[i]!=L'\0';++i) {
-                               if(text[i]==L'\x0002') {
-                                       noteCharOffset=i;
-                                       if(i==0) text[i]=L' ';
-                                       break;
-                               }
-                       }
-                       bool isNoteChar=(noteCharOffset==0);
-                       if(noteCharOffset==0) noteCharOffset=1;
-                       if(noteCharOffset>0) {
-                               text[noteCharOffset]=L'\0';
-                               
_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_COLLAPSE,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdCollapseStart);
-                               
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdCharacter,noteCharOffset)!=S_OK||unitsMoved<=0)
 {
-                                       break;
-                               }
-                               
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_END,VT_I4,&chunkEndOffset);
-                       }
-                       if(firstLoop) {
-                               
if(initialFormatConfig&formatConfig_reportTables) {
-                                       
neededClosingControlTagCount+=generateTableXML(pDispatchRange,args->startOffset,args->endOffset,XMLStream);
+                       bool isNoteChar=false;
+                       if(!isFormField) {
+                               //Force a new chunk before and after control+b 
(note characters)
+                               for(int i=0;text[i]!=L'\0';++i) {
+                                       if(text[i]==L'\x0002') {
+                                               noteCharOffset=i;
+                                               if(i==0) text[i]=L' ';
+                                               break;
+                                       }  else 
if(text[i]==L'\x0007'&&(chunkEndOffset-chunkStartOffset)==1) {
+                                               text[i]=L'\0';
+                                               //Collecting revision info does 
not work on cell delimiters
+                                               
curDisabledFormatConfig|=formatConfig_reportRevisions;
+                                       }
                                }
-                               
if(initialFormatConfig&formatConfig_reportHeadings) {
-                                       
neededClosingControlTagCount+=generateHeadingXML(pDispatchRange,XMLStream);
+                               isNoteChar=(noteCharOffset==0);
+                               if(noteCharOffset==0) noteCharOffset=1;
+                               if(noteCharOffset>0) {
+                                       text[noteCharOffset]=L'\0';
+                                       
_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_COLLAPSE,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdCollapseStart);
+                                       
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdCharacter,noteCharOffset)!=S_OK||unitsMoved<=0)
 {
+                                               break;
+                                       }
+                                       
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_END,VT_I4,&chunkEndOffset);
                                }
-                               
generateXMLAttribsForFormatting(pDispatchRange,chunkStartOffset,chunkEndOffset,initialFormatConfig,initialFormatAttribsStream);
                        }
                        if(isNoteChar) {
                                
isNoteChar=generateFootnoteEndnoteXML(pDispatchRange,XMLStream,true);
@@ -619,9 +738,9 @@ void winword_getTextInRange_helper(HWND hwnd, 
winword_getTextInRange_args* args)
                                }
                                
_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_END,VT_I4,&chunkEndOffset);
                        }
-                       XMLStream<<L"<text ";
+                       XMLStream<<L"<text 
_startOffset=\""<<chunkStartOffset<<L"\" _endOffset=\""<<chunkEndOffset<<L"\" ";
                        XMLStream<<initialFormatAttribsStream.str();
-                       
generateXMLAttribsForFormatting(pDispatchRange,chunkStartOffset,chunkEndOffset,formatConfig,XMLStream);
+                       
generateXMLAttribsForFormatting(pDispatchRange,chunkStartOffset,chunkEndOffset,formatConfig&(~curDisabledFormatConfig),XMLStream);
                        XMLStream<<L">";
                        if(firstLoop) {
                                formatConfig&=(~formatConfig_reportLists);
@@ -637,6 +756,7 @@ void winword_getTextInRange_helper(HWND hwnd, 
winword_getTextInRange_args* args)
                        SysFreeString(text);
                        text=NULL;
                        XMLStream<<L"</text>";
+                       if(isFormField) XMLStream<<L"</control>";
                        if(isNoteChar) XMLStream<<L"</control>";
                        if(inlineShapesCount>0) XMLStream<<L"</control>";
                }

diff --git a/nvdaHelper/sconscript b/nvdaHelper/sconscript
index 168b499..585d72d 100644
--- a/nvdaHelper/sconscript
+++ b/nvdaHelper/sconscript
@@ -32,6 +32,6 @@ archClientInstallDirs={
 
 #Build nvdaHelper for needed architectures
 for arch in env['targetArchitectures']: 
-       
archEnv=env.Clone(TARGET_ARCH=arch,tools=['windowsSdk','midl','msrpc','boost','default'])
+       
archEnv=env.Clone(TARGET_ARCH=arch,tools=['windowsSdk','midl','msrpc','default'])
        
archEnv.SConscript('archBuild_sconscript',exports={'env':archEnv,'clientInstallDir':archClientInstallDirs[arch],'libInstallDir':archLibInstallDirs[arch]},variant_dir='build/%s'%arch)
 

diff --git a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp 
b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
index 8f2adb6..e8590b4 100755
--- a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
@@ -561,8 +561,12 @@ inline void fillTextFormattingForNode(IHTMLDOMNode* 
pHTMLDOMNode, VBufStorage_fi
 inline void fillTextFormattingForTextNode(VBufStorage_controlFieldNode_t* 
parentNode, VBufStorage_textFieldNode_t* textNode)
        //text nodes don't support IHTMLElement2 interface, so using style 
information from parent node
        {
-       IHTMLElement2* 
pHTMLElement2=(static_cast<MshtmlVBufStorage_controlFieldNode_t*>(parentNode))->pHTMLElement2;
-       fillTextFormatting_helper(pHTMLElement2,textNode);
+       IHTMLElement2* pHTMLElement2=NULL; 
+       
static_cast<MshtmlVBufStorage_controlFieldNode_t*>(parentNode)->pHTMLDOMNode->QueryInterface(IID_IHTMLElement2,(void**)&pHTMLElement2);
+       if(pHTMLElement2) {
+               fillTextFormatting_helper(pHTMLElement2,textNode);
+               pHTMLElement2->Release();
+       }
 }
 
 const int TABLEHEADER_COLUMN = 0x1;
@@ -1227,11 +1231,11 @@ void MshtmlVBufBackend_t::render(VBufStorage_buffer_t* 
buffer, int docHandle, in
                LOG_DEBUG(L"Error getting document using WM_HTML_GETOBJECT");
                return;
        }
-IHTMLDOMNode* pHTMLDOMNode=NULL;
+       IHTMLDOMNode* pHTMLDOMNode=NULL;
        if(oldNode!=NULL) {
-               IHTMLElement2* 
pHTMLElement2=(static_cast<MshtmlVBufStorage_controlFieldNode_t*>(oldNode))->pHTMLElement2;
-               nhAssert(pHTMLElement2);
-               
pHTMLElement2->QueryInterface(IID_IHTMLDOMNode,(void**)&pHTMLDOMNode);
+               
pHTMLDOMNode=(static_cast<MshtmlVBufStorage_controlFieldNode_t*>(oldNode))->pHTMLDOMNode;
+               nhAssert(pHTMLDOMNode);
+               pHTMLDOMNode->AddRef();
        } else {
                IHTMLDocument3* pHTMLDocument3=NULL;
                
if(ObjectFromLresult(res,IID_IHTMLDocument3,0,(void**)&pHTMLDocument3)!=S_OK) {

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp 
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index c7d9b5b..84f44a8 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -14,8 +14,10 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
 #include <list>
 #include <windows.h>
+#include <objbase.h>
 #include <oleidl.h>
 #include <mshtml.h>
+#include <mshtmdid.h>
 #include <common/log.h>
 #include "mshtml.h"
 #include "node.h"
@@ -25,33 +27,66 @@ using namespace std;
 class CDispatchChangeSink : public IDispatch {
        private:
        ULONG refCount;
-       bool hasFired;
+       MshtmlVBufStorage_controlFieldNode_t* storageNode;
+       IConnectionPoint* pConnectionPoint;
+       DWORD dwCookie;
 
        public:
-       MshtmlVBufStorage_controlFieldNode_t* storageNode;
-       bool allowDelete;
 
-       CDispatchChangeSink(MshtmlVBufStorage_controlFieldNode_t* storageNode):
-       refCount(1),
-       hasFired(false),
-       allowDelete(true) {
+       CDispatchChangeSink(MshtmlVBufStorage_controlFieldNode_t* storageNode) :
+       refCount(1), dwCookie(0), pConnectionPoint(NULL) {
                nhAssert(storageNode);
                this->storageNode=storageNode;
                incBackendLibRefCount();
        }
 
-       ~CDispatchChangeSink() {
-               decBackendLibRefCount();
+       BOOL connect(IHTMLDOMNode* pHTMLDOMNode, REFIID iid) {
+               if(dwCookie) {
+                       LOG_DEBUGWARNING(L"Already connected");
+                       return false;
+               }
+               IHTMLElement* pHTMLElement=NULL;
+               
pHTMLDOMNode->QueryInterface(IID_IHTMLElement,(void**)&pHTMLElement);
+               if(!pHTMLElement) {
+                       LOG_DEBUGWARNING(L"QueryInterface to IHTMLElement 
failed");
+                       return false;
+               }
+               IConnectionPointContainer* pConnectionPointContainer=NULL;
+               
pHTMLElement->QueryInterface(IID_IConnectionPointContainer,(void**)&pConnectionPointContainer);
+               pHTMLElement->Release();
+               if(!pConnectionPointContainer) {
+                       LOG_DEBUGWARNING(L"QueryInterface to 
IConnectionPointContainer failed");
+                       return false;
+               }
+               IConnectionPoint* pConnectionPoint=NULL;
+               
pConnectionPointContainer->FindConnectionPoint(iid,&pConnectionPoint);
+               pConnectionPointContainer->Release();
+               if(!pConnectionPoint) {
+                       return false;
+               }
+               DWORD dwCookie=0;
+               pConnectionPoint->Advise(this,&dwCookie);
+               if(!dwCookie) {
+                       pConnectionPoint->Release();
+                       return false;
+               }
+               this->pConnectionPoint=pConnectionPoint;
+               this->dwCookie=dwCookie;
+               return true;
        }
 
-       void onChange() {
-               if(hasFired||allowDelete) {
-                       return;
-               }
-               hasFired=true;
-               LOG_DEBUG(L"Marking storage node as invalid");
-               
this->storageNode->backend->invalidateSubtree(this->storageNode);
-               LOG_DEBUG(L"Done");
+       BOOL disconnect() {
+               if(this->dwCookie==0) return false;
+               this->pConnectionPoint->Unadvise(this->dwCookie);
+               this->dwCookie=0;
+               this->pConnectionPoint->Release();
+               this->pConnectionPoint=NULL;
+               return true;
+       }
+
+       ~CDispatchChangeSink() {
+               this->disconnect();
+               decBackendLibRefCount();
        }
 
        HRESULT STDMETHODCALLTYPE IUnknown::QueryInterface(REFIID riid, void** 
pvpObject) {
@@ -77,28 +112,18 @@ class CDispatchChangeSink : public IDispatch {
                if(this->refCount>0)
                        this->refCount--;
                if(this->refCount==0) {
-                       if (this->allowDelete) {
-                               delete this;
-                       } else {
-                               #ifdef DEBUG
-                               Beep(660,50);
-                               #endif
-                               LOG_DEBUG(L"refCount hit 0 before it should, 
not deleting, node info: " << this->storageNode->getDebugInfo());
-                       }
+                       delete this;
                        return 0;
                }
                return this->refCount;
        }
 
        HRESULT STDMETHODCALLTYPE IDispatch::Invoke(DISPID  dispIdMember, 
REFIID  riid, LCID  lcid, WORD  wFlags, DISPPARAMS FAR*  pDispParams, VARIANT 
FAR*  pVarResult, EXCEPINFO FAR*  pExcepInfo, unsigned int FAR*  puArgErr) {
-               if(dispIdMember==0) {
-                       LOG_DEBUG(L"calling onChange");
-                       this->onChange();
-                       LOG_DEBUG(L"Done, returning S_OK");
+               
if(dispIdMember==DISPID_EVMETH_ONPROPERTYCHANGE||dispIdMember==DISPID_EVMETH_ONLOAD)
 {
+                       
this->storageNode->backend->invalidateSubtree(this->storageNode);
                        return S_OK;
                }
-               LOG_DEBUG(L"invoke called with unknown member ID, returning 
E_INVALIDARG");
-               return E_INVALIDARG;
+               return E_FAIL;
        }
 
        HRESULT STDMETHODCALLTYPE  IDispatch::GetTypeInfoCount(UINT* count) {
@@ -238,48 +263,22 @@ class CHTMLChangeSink : public IHTMLChangeSink {
 };
 
 MshtmlVBufStorage_controlFieldNode_t::MshtmlVBufStorage_controlFieldNode_t(int 
docHandle, int ID, bool isBlock, MshtmlVBufBackend_t* backend, IHTMLDOMNode* 
pHTMLDOMNode,const wstring& lang): 
VBufStorage_controlFieldNode_t(docHandle,ID,isBlock), language(lang) {
-       VARIANT_BOOL varBool;
        nhAssert(backend);
        nhAssert(pHTMLDOMNode);
        this->backend=backend;
-       this->pHTMLElement2=NULL;
+       pHTMLDOMNode->AddRef();
+       this->pHTMLDOMNode=pHTMLDOMNode;
        this->propChangeSink=NULL;
        this->loadSink=NULL;
        this->pHTMLChangeSink=NULL;
        this->HTMLChangeSinkCookey=0;
-       
pHTMLDOMNode->QueryInterface(IID_IHTMLElement2,(void**)&(this->pHTMLElement2));
-       if(!this->pHTMLElement2) {
-               LOG_DEBUG(L"Could not queryInterface from IHTMLDOMNode to 
IHTMLElement2");
-       }
-       if(this->pHTMLElement2) {
-               CDispatchChangeSink* propChangeSink=new 
CDispatchChangeSink(this);
-               // It seems that IE 6 sometimes calls Release() once too many 
times.
-               // We don't want propChangeSink to be deleted until we're 
finished with it.
-               propChangeSink->allowDelete=false;
-               
if((pHTMLElement2->attachEvent(L"onpropertychange",propChangeSink,&varBool)==S_OK)&&varBool)
 {
-                       this->propChangeSink=propChangeSink;
-               } else {
-                       LOG_DEBUG(L"Error attaching onPropertyChange event sink 
to IHTMLElement2 at "<<pHTMLElement2);
-                       propChangeSink->allowDelete=true;
-                       propChangeSink->Release();
-               }
-       }
        BSTR nodeName=NULL;
        pHTMLDOMNode->get_nodeName(&nodeName);
-       
if(nodeName!=NULL&&(_wcsicmp(nodeName,L"frame")==0||_wcsicmp(nodeName,L"iframe")==0||_wcsicmp(nodeName,L"img")==0||_wcsicmp(nodeName,L"input")==0))
 {
-               if(this->pHTMLElement2) {
-                       CDispatchChangeSink* loadSink=new 
CDispatchChangeSink(this);
-                       // It seems that IE 6 sometimes calls Release() once 
too many times.
-                       // We don't want loadSink to be deleted until we're 
finished with it.
-                       loadSink->allowDelete=false;
-                       
if((pHTMLElement2->attachEvent(L"onload",loadSink,&varBool)==S_OK)&&varBool) {
-                               this->loadSink=loadSink;
-                       } else {
-                               LOG_DEBUG(L"Error attaching onload event sink 
to IHTMLElement2 at "<<pHTMLElement2);
-                               loadSink->allowDelete=true;
-                               loadSink->Release();
-                       }
-               }
+       CDispatchChangeSink* propChangeSink=new CDispatchChangeSink(this);
+       if(propChangeSink->connect(pHTMLDOMNode,IID_IDispatch)) {
+               this->propChangeSink=propChangeSink;
+       } else {
+               propChangeSink->Release();
        }
        
if(nodeName!=NULL&&(_wcsicmp(nodeName,L"body")==0||_wcsicmp(nodeName,L"frameset")==0))
 {
                IHTMLDOMNode2* pHTMLDOMNode2=NULL;
@@ -317,23 +316,15 @@ 
MshtmlVBufStorage_controlFieldNode_t::MshtmlVBufStorage_controlFieldNode_t(int d
  
 MshtmlVBufStorage_controlFieldNode_t::~MshtmlVBufStorage_controlFieldNode_t() {
        if(this->propChangeSink) {
-               nhAssert(this->pHTMLElement2);
-               
if(pHTMLElement2->detachEvent(L"onpropertychange",this->propChangeSink)!=S_OK) {
-                       LOG_DEBUG(L"Error detaching onpropertychange event sink 
from IHTMLElement2");
+               
if(!(static_cast<CDispatchChangeSink*>(this->propChangeSink)->disconnect())) {
+                       LOG_DEBUGWARNING(L"Failed to stop listening with 
HTMLElementEvents2 for node "<<this->getDebugInfo());
                }
-               
static_cast<CDispatchChangeSink*>(this->propChangeSink)->allowDelete=true;
                this->propChangeSink->Release();
+               this->propChangeSink=NULL;
        }
-       if(this->loadSink) {
-               nhAssert(this->pHTMLElement2);
-               if(pHTMLElement2->detachEvent(L"onload",this->loadSink)!=S_OK) {
-                       LOG_DEBUG(L"Error detaching onload event sink from 
IHTMLElement2");
-               }
-               
static_cast<CDispatchChangeSink*>(this->loadSink)->allowDelete=true;
-               this->loadSink->Release();
-       }
-       if(this->pHTMLElement2) {
-               this->pHTMLElement2->Release();
+       if(this->pHTMLDOMNode) {
+               this->pHTMLDOMNode->Release();
+               this->pHTMLDOMNode=NULL;
        }
        if(this->pHTMLChangeSink) {
                nhAssert(this->pMarkupContainer2);

diff --git a/nvdaHelper/vbufBackends/mshtml/node.h 
b/nvdaHelper/vbufBackends/mshtml/node.h
index 7fc7ae6..ec43b80 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.h
+++ b/nvdaHelper/vbufBackends/mshtml/node.h
@@ -24,7 +24,7 @@ class MshtmlVBufStorage_controlFieldNode_t : public 
VBufStorage_controlFieldNode
 
        public:
        MshtmlVBufBackend_t* backend;
-       IHTMLElement2* pHTMLElement2;
+       IHTMLDOMNode* pHTMLDOMNode;
        IDispatch* propChangeSink;
        IDispatch* loadSink;
        IMarkupContainer2* pMarkupContainer2;

diff --git a/readme.txt b/readme.txt
index 236cd17..e5ea569 100644
--- a/readme.txt
+++ b/readme.txt
@@ -42,12 +42,8 @@ General dependencies:
                * Copy the txt2tags Python script to the global Python 
site-packages directory, naming it txt2tags.py.
        * Microsoft Windows SDK, version 7.0: 
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en
                * You need to install both the 32 bit and 64 bit libraries and 
tools.
-       * MinHook, version 1.1.0: 
http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
+       * MinHook, rev e21b54a: 
http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
                * This is included as a git submodule
-       * Boost C++ Libraries, version 1.47:
-               * You can download the latest Windows installer from 
http://www.boostpro.com/download
-               * On the components page of the installer, make sure to install 
at least all of the defaults (whatever is already checked).
-               * NVDA only uses the Boost headers; none of the pre-compiled 
libraries are necessary.
        * SCons, version 2.2.0: http://www.scons.org/
                * As the scons command (scons.bat) is installed in to the 
scripts directory inside the directory where you installed Python, it is 
necessary to add the scripts  directory to your path variable so that you can 
run scons from anywhere. The rest of this readme assumes that scons can be run 
in this way.
 

diff --git a/site_scons/site_tools/boost.py b/site_scons/site_tools/boost.py
deleted file mode 100644
index e9cffdb..0000000
--- a/site_scons/site_tools/boost.py
+++ /dev/null
@@ -1,50 +0,0 @@
-###
-#This file is a part of the NVDA project.
-#URL: http://www.nvda-project.org/
-#Copyright 2006-2010 NVDA contributers.
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU General Public License version 2.0, as 
published by
-#the Free Software Foundation.
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#This license can be found at:
-#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-###
-
-import _winreg
-
-_boostRoot=None
-
-def findBoostRoot():
-       global _boostRoot
-       if _boostRoot is None:
-               try:
-                       
k=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,r'Software\boostpro.com')
-               except:
-                       print "boost tool: can't find bostpro.com registry key"
-                       return None
-               kLen=_winreg.QueryInfoKey(k)[0]
-               if kLen<1:
-                       print "boost tool: no subkeys in boostpro.com registry 
key"
-                       return None
-               subkeyString=_winreg.EnumKey(k,kLen-1)
-               try:
-                       k=_winreg.OpenKey(k,subkeyString)
-               except:
-                       print "boost tool: failed to open %s subkey of 
boostpro.com registry key"%subkeyString
-                       return None
-               try:
-                       boostRoot=_winreg.QueryValueEx(k,"InstallRoot")
-               except:
-                       print "no InstallRoot value in %s subkey of 
boostpro.com registry key"%subkeyString
-                       return None
-               _boostRoot=boostRoot
-       return _boostRoot
-
-def exists():
-       return True if findBoostRoot() is not None else False
-
-def generate(env):
-       boostRoot=findBoostRoot()
-       env.Append(CPPPATH=boostRoot)

diff --git a/source/IAccessibleHandler.py b/source/IAccessibleHandler.py
index 572a564..94db85d 100644
--- a/source/IAccessibleHandler.py
+++ b/source/IAccessibleHandler.py
@@ -302,6 +302,7 @@ IAccessible2StatesToNVDAStates={
        IA2_STATE_MULTI_LINE:controlTypes.STATE_MULTILINE,
        IA2_STATE_ICONIFIED:controlTypes.STATE_ICONIFIED,
        IA2_STATE_EDITABLE:controlTypes.STATE_EDITABLE,
+       IA2_STATE_PINNED:controlTypes.STATE_PINNED,
 }
 
 #A list to store handles received from setWinEventHook, for use with 
unHookWinEvent  

diff --git a/source/NVDAObjects/window/__init__.py 
b/source/NVDAObjects/window/__init__.py
index f2d78b2..4cd8451 100644
--- a/source/NVDAObjects/window/__init__.py
+++ b/source/NVDAObjects/window/__init__.py
@@ -84,6 +84,9 @@ An NVDAObject for a window
                if windowClassName=="EXCEL7" and (relation=='focus' or 
isinstance(relation,tuple)): 
                        from . import excel
                        yield excel.ExcelCell 
+               if windowClassName=="EXCEL:":
+                       from .excel import ExcelDropdown as newCls
+                       yield newCls
                import JABHandler
                if JABHandler.isJavaWindow(windowHandle):
                        import NVDAObjects.JAB

diff --git a/source/NVDAObjects/window/excel.py 
b/source/NVDAObjects/window/excel.py
index c68ff94..a87bae6 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -16,6 +16,7 @@ import colors
 import eventHandler
 import gui
 import winUser
+from displayModel import DisplayModelTextInfo
 import controlTypes
 from . import Window
 from .. import NVDAObjectTextInfo
@@ -168,6 +169,22 @@ class ExcelCell(ExcelBase):
                if rowHeaderColumn and columnNumber>rowHeaderColumn:
                        return 
self.excelCellObject.parent.cells(rowNumber,rowHeaderColumn).text
 
+       def _get_dropdown(self):
+               w=winUser.getAncestor(self.windowHandle,winUser.GA_ROOT)
+               if not w: return
+               obj=Window(windowHandle=w,chooseBestAPI=False)
+               if not obj: return
+               prev=obj.previous
+               if not prev or prev.windowClassName!='EXCEL:': return
+               return prev
+
+       def script_openDropdown(self,gesture):
+               gesture.send()
+               d=self.dropdown
+               if d:
+                       d.parent=self
+                       eventHandler.queueEvent("gainFocus",d)
+
        def script_setColumnHeaderRow(self,gesture):
                scriptCount=scriptHandler.getLastScriptRepeatCount()
                tableID=self.tableID
@@ -290,6 +307,7 @@ class ExcelCell(ExcelBase):
        __gestures = {
                "kb:NVDA+shift+c": "setColumnHeaderRow",
                "kb:NVDA+shift+r": "setRowHeaderColumn",
+               "kb:alt+downArrow":"openDropdown",
        }
 
 class ExcelSelection(ExcelBase):
@@ -321,3 +339,107 @@ class ExcelSelection(ExcelBase):
                if position==textInfos.POSITION_SELECTION:
                        position=textInfos.POSITION_ALL
                return super(ExcelSelection,self).makeTextInfo(position)
+
+class ExcelDropdownItem(Window):
+
+       firstChild=None
+       lastChild=None
+       children=[]
+       role=controlTypes.ROLE_LISTITEM
+
+       def __init__(self,parent=None,name=None,states=None,index=None):
+               self.name=name
+               self.states=states
+               self.parent=parent
+               self.index=index
+               
super(ExcelDropdownItem,self).__init__(windowHandle=parent.windowHandle)
+
+       def _get_previous(self):
+               newIndex=self.index-1
+               if newIndex>=0:
+                       return self.parent.children[newIndex]
+
+       def _get_next(self):
+               newIndex=self.index+1
+               if newIndex<self.parent.childCount:
+                       return self.parent.children[newIndex]
+
+       def _get_positionInfo(self):
+               return 
{'indexInGroup':self.index+1,'similarItemsInGroup':self.parent.childCount,}
+
+class ExcelDropdown(Window):
+
+       @classmethod
+       def kwargsFromSuper(cls,kwargs,relation=None):
+               return kwargs
+
+       role=controlTypes.ROLE_LIST
+       excelCell=None
+
+       def _get__highlightColors(self):
+               
background=colors.RGB.fromCOLORREF(winUser.user32.GetSysColor(13))
+               
foreground=colors.RGB.fromCOLORREF(winUser.user32.GetSysColor(14))
+               self._highlightColors=(background,foreground)
+               return self._highlightColors
+
+       def _get_children(self):
+               children=[]
+               index=0
+               states=set()
+               for item in 
DisplayModelTextInfo(self,textInfos.POSITION_ALL).getTextWithFields(): 
+                       if isinstance(item,textInfos.FieldCommand) and 
item.command=="formatChange":
+                               states=set([controlTypes.STATE_SELECTABLE])
+                               foreground=item.field.get('color',None)
+                               
background=item.field.get('background-color',None)
+                               if 
(background,foreground)==self._highlightColors: 
+                                       states.add(controlTypes.STATE_SELECTED)
+                       if isinstance(item,basestring):
+                               
obj=ExcelDropdownItem(parent=self,name=item,states=states,index=index)
+                               children.append(obj)
+                               index+=1
+               return children
+
+       def _get_childCount(self):
+               return len(self.children)
+
+       def _get_firstChild(self):
+               return self.children[0]
+       def _get_selection(self):
+               for child in self.children:
+                       if controlTypes.STATE_SELECTED in child.states:
+                               return child
+
+       def script_selectionChange(self,gesture):
+               gesture.send()
+               newFocus=self.selection or self
+               if eventHandler.lastQueuedFocusObject is newFocus: return
+               eventHandler.queueEvent("gainFocus",newFocus)
+       script_selectionChange.canPropagate=True
+
+       def script_closeDropdown(self,gesture):
+               gesture.send()
+               eventHandler.queueEvent("gainFocus",self.parent)
+       script_closeDropdown.canPropagate=True
+
+       __gestures={
+               "kb:downArrow":"selectionChange",
+               "kb:upArrow":"selectionChange",
+               "kb:leftArrow":"selectionChange",
+               "kb:rightArrow":"selectionChange",
+               "kb:home":"selectionChange",
+               "kb:end":"selectionChange",
+               "kb:escape":"closeDropdown",
+               "kb:enter":"closeDropdown",
+               "kb:space":"closeDropdown",
+       }
+
+       def event_gainFocus(self):
+               child=self.selection
+               if not child and self.childCount>0:
+                       child=self.children[0]
+               if child:
+                       eventHandler.queueEvent("focusEntered",self)
+                       eventHandler.queueEvent("gainFocus",child)
+               else:
+                       super(ExcelDropdown,self).event_gainFocus()
+                       

diff --git a/source/NVDAObjects/window/winword.py 
b/source/NVDAObjects/window/winword.py
index d43cdbf..a2e7830 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -10,6 +10,7 @@ import comtypes.client
 import comtypes.automation
 import operator
 import locale
+import braille
 import languageHandler
 import ui
 import NVDAHelper
@@ -81,6 +82,78 @@ wdPrimaryFooterStory=9
 wdPrimaryHeaderStory=7
 wdTextFrameStory=5
 
+wdFieldFormTextInput=70
+wdFieldFormCheckBox=71
+wdFieldFormDropDown=83
+wdContentControlRichText=0
+wdContentControlText=1
+wdContentControlPicture=2
+wdContentControlComboBox=3
+wdContentControlDropdownList=4
+wdContentControlBuildingBlockGallery=5
+wdContentControlDate=6
+wdContentControlGroup=7
+wdContentControlCheckBox=8
+
+wdNoRevision=0
+wdRevisionInsert=1
+wdRevisionDelete=2
+wdRevisionProperty=3
+wdRevisionParagraphNumber=4
+wdRevisionDisplayField=5
+wdRevisionReconcile=6
+wdRevisionConflict=7
+wdRevisionStyle=8
+wdRevisionReplace=9
+wdRevisionParagraphProperty=10
+wdRevisionTableProperty=11
+wdRevisionSectionProperty=12
+wdRevisionStyleDefinition=13
+wdRevisionMovedFrom=14
+wdRevisionMovedTo=15
+wdRevisionCellInsertion=16
+wdRevisionCellDeletion=17
+wdRevisionCellMerge=18
+
+wdRevisionTypeLabels={
+       # Translators: a Microsoft Word revision type (inserted content) 
+       wdRevisionInsert:_("insertion"),
+       # Translators: a Microsoft Word revision type (deleted content) 
+       wdRevisionDelete:_("deletion"),
+       # Translators: a Microsoft Word revision type (changed content 
property, e.g. font, color)
+       wdRevisionProperty:_("property"),
+       # Translators: a Microsoft Word revision type (changed paragraph number)
+       wdRevisionParagraphNumber:_("paragraph number"),
+       # Translators: a Microsoft Word revision type (display field)
+       wdRevisionDisplayField:_("display field"),
+       # Translators: a Microsoft Word revision type (reconcile) 
+       wdRevisionReconcile:_("reconcile"),
+       # Translators: a Microsoft Word revision type (conflicting revision)
+       wdRevisionConflict:_("conflict"),
+       # Translators: a Microsoft Word revision type (style change)
+       wdRevisionStyle:_("style"),
+       # Translators: a Microsoft Word revision type (replaced content) 
+       wdRevisionReplace:_("replace"),
+       # Translators: a Microsoft Word revision type (changed paragraph 
property, e.g. alignment)
+       wdRevisionParagraphProperty:_("paragraph property"),
+       # Translators: a Microsoft Word revision type (table)
+       wdRevisionTableProperty:_("table property"),
+       # Translators: a Microsoft Word revision type (section property) 
+       wdRevisionSectionProperty:_("section property"),
+       # Translators: a Microsoft Word revision type (style definition)
+       wdRevisionStyleDefinition:_("style definition"),
+       # Translators: a Microsoft Word revision type (moved from)
+       wdRevisionMovedFrom:_("moved from"),
+       # Translators: a Microsoft Word revision type (moved to)
+       wdRevisionMovedTo:_("moved to"),
+       # Translators: a Microsoft Word revision type (inserted table cell)
+       wdRevisionCellInsertion:_("cell insertion"),
+       # Translators: a Microsoft Word revision type (deleted table cell)
+       wdRevisionCellDeletion:_("cell deletion"),
+       # Translators: a Microsoft Word revision type (merged table cells)
+       wdRevisionCellMerge:_("cell merge"),
+}
+
 storyTypeLocalizedLabels={
        wdCommentsStory:_("Comments"),
        wdEndnotesStory:_("Endnotes"),
@@ -94,6 +167,23 @@ storyTypeLocalizedLabels={
        wdTextFrameStory:_("Text frame"),
 }
 
+wdFieldTypesToNVDARoles={
+       wdFieldFormTextInput:controlTypes.ROLE_EDITABLETEXT,
+       wdFieldFormCheckBox:controlTypes.ROLE_CHECKBOX,
+       wdFieldFormDropDown:controlTypes.ROLE_COMBOBOX,
+}
+
+wdContentControlTypesToNVDARoles={
+       wdContentControlRichText:controlTypes.ROLE_EDITABLETEXT,
+       wdContentControlText:controlTypes.ROLE_EDITABLETEXT,
+       wdContentControlPicture:controlTypes.ROLE_GRAPHIC,
+       wdContentControlComboBox:controlTypes.ROLE_COMBOBOX,
+       wdContentControlDropdownList:controlTypes.ROLE_COMBOBOX,
+       wdContentControlDate:controlTypes.ROLE_EDITABLETEXT,
+       wdContentControlGroup:controlTypes.ROLE_GROUPING,
+       wdContentControlCheckBox:controlTypes.ROLE_CHECKBOX,
+}
+
 winwordWindowIid=GUID('{00020962-0000-0000-C000-000000000046}')
 
 
wm_winword_expandToLine=ctypes.windll.user32.RegisterWindowMessageW(u"wm_winword_expandToLine")
@@ -128,6 +218,7 @@ formatConfigFlagsMap={
        "reportComments":4096,
        "reportHeadings":8192,
        "autoLanguageSwitching":16384,  
+       "reportRevisions":32768,
 }
 
 class WordDocumentTextInfo(textInfos.TextInfo):
@@ -136,7 +227,7 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                lineStart=ctypes.c_int()
                lineEnd=ctypes.c_int()
                
res=NVDAHelper.localLib.nvdaInProcUtils_winword_expandToLine(self.obj.appModule.helperLocalBindingHandle,self.obj.windowHandle,self._rangeObj.start,ctypes.byref(lineStart),ctypes.byref(lineEnd))
-               if res!=0 or (lineStart.value==lineEnd.value==-1): 
+               if res!=0 or lineStart.value==lineEnd.value or 
lineStart.value==-1 or lineEnd.value==-1: 
                        log.debugWarning("winword_expandToLine failed")
                        self._rangeObj.expand(wdParagraph)
                        return
@@ -174,13 +265,12 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                        raise NotImplementedError("position: %s"%position)
 
        def getTextWithFields(self,formatConfig=None):
+               extraDetail=formatConfig.get('extraDetail',False) if 
formatConfig else False
                if not formatConfig:
                        formatConfig=config.conf['documentFormatting']
                
formatConfig['autoLanguageSwitching']=config.conf['speech'].get('autoLanguageSwitching',False)
                startOffset=self._rangeObj.start
                endOffset=self._rangeObj.end
-               if startOffset==endOffset:
-                       return []
                text=BSTR()
                formatConfigFlags=sum(y for x,y in 
formatConfigFlagsMap.iteritems() if formatConfig.get(x,False))
                
res=NVDAHelper.localLib.nvdaInProcUtils_winword_getTextInRange(self.obj.appModule.helperLocalBindingHandle,self.obj.windowHandle,startOffset,endOffset,formatConfigFlags,ctypes.byref(text))
@@ -194,7 +284,7 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                                if isinstance(field,textInfos.ControlField):
                                        
item.field=self._normalizeControlField(field)
                                elif isinstance(field,textInfos.FormatField):
-                                       
item.field=self._normalizeFormatField(field)
+                                       
item.field=self._normalizeFormatField(field,extraDetail=extraDetail)
                        elif index>0 and isinstance(item,basestring) and 
item.isspace():
                                 #2047: don't expose language for whitespace as 
its incorrect for east-asian languages 
                                lastItem=commandList[index-1]
@@ -226,8 +316,30 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                elif role=="object":
                        role=controlTypes.ROLE_EMBEDDEDOBJECT
                else:
-                       role=controlTypes.ROLE_UNKNOWN
-               field['role']=role
+                       fieldType=int(field.pop('wdFieldType',-1))
+                       if fieldType!=-1:
+                               
role=wdFieldTypesToNVDARoles.get(fieldType,controlTypes.ROLE_UNKNOWN)
+                               if fieldType==wdFieldFormCheckBox and 
int(field.get('wdFieldResult','0'))>0:
+                                       
field['states']=set([controlTypes.STATE_CHECKED])
+                               elif fieldType==wdFieldFormDropDown:
+                                       
field['value']=field.get('wdFieldResult',None)
+                       fieldStatusText=field.pop('wdFieldStatusText',None)
+                       if fieldStatusText:
+                               field['name']=fieldStatusText
+                               field['alwaysReportName']=True
+                       else:
+                               
fieldType=int(field.get('wdContentControlType',-1))
+                               if fieldType!=-1:
+                                       
role=wdContentControlTypesToNVDARoles.get(fieldType,controlTypes.ROLE_UNKNOWN)
+                                       if role==controlTypes.ROLE_CHECKBOX:
+                                               
fieldChecked=bool(int(field.get('wdContentControlChecked','0')))
+                                               if fieldChecked:
+                                                       
field['states']=set([controlTypes.STATE_CHECKED])
+                                       
fieldTitle=field.get('wdContentControlTitle',None)
+                                       if fieldTitle:
+                                               field['name']=fieldTitle
+                                               field['alwaysReportName']=True
+               if role is not None: field['role']=role
                storyType=int(field.pop('wdStoryType',0))
                if storyType:
                        name=storyTypeLocalizedLabels.get(storyType,None)
@@ -237,7 +349,25 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                                field['role']=controlTypes.ROLE_FRAME
                return field
 
-       def _normalizeFormatField(self,field):
+       def _normalizeFormatField(self,field,extraDetail=False):
+               _startOffset=int(field.pop('_startOffset'))
+               _endOffset=int(field.pop('_endOffset'))
+               revisionType=int(field.pop('wdRevisionType',0))
+               revisionLabel=wdRevisionTypeLabels.get(revisionType,None)
+               if revisionLabel:
+                       if extraDetail:
+                               try:
+                                       r=self.obj.WinwordSelectionObject.range
+                                       r.setRange(_startOffset,_endOffset)
+                                       rev=r.revisions.item(1)
+                                       author=rev.author
+                                       date=rev.date
+                               except COMError:
+                                       author=_("unknown author")
+                                       date=_("unknown date")
+                               field['revision']=_("{revisionType} by 
{revisionAuthor} on 
{revisionDate}").format(revisionType=revisionLabel,revisionAuthor=author,revisionDate=date)
+                       else:
+                               field['revision']=revisionLabel
                color=field.pop('color',None)
                if color is not None:
                        field['color']=colors.RGB.fromCOLORREF(int(color))      
        
@@ -413,10 +543,10 @@ class 
WordDocument(EditableTextWithoutAutoSelectDetection, Window):
 
        def script_tab(self,gesture):
                gesture.send()
-               info=self.makeTextInfo(textInfos.POSITION_CARET)
-               if info._rangeObj.tables.count>0:
-                       info.expand(textInfos.UNIT_LINE)
-                       
speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
+               info=self.makeTextInfo(textInfos.POSITION_SELECTION)
+               if not info.isCollapsed or info._rangeObj.tables.count>0:
+                       
speech.speakTextInfo(info,reason=controlTypes.REASON_FOCUS)
+               braille.handler.handleCaretMove(info)
 
        def _moveInTable(self,row=True,forward=True):
                info=self.makeTextInfo(textInfos.POSITION_CARET)

diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py
index affdf80..989ccd1 100644
--- a/source/_UIAHandler.py
+++ b/source/_UIAHandler.py
@@ -130,11 +130,11 @@ class UIAHandler(COMObject):
                        raise self.MTAThreadInitException
 
        def terminate(self):
-               
MTAThreadHandle=HANDLE(windll.kernel32.OpenThread(self.MTAThread.ident,False,winKernel.SYNCHRONIZE))
+               
MTAThreadHandle=HANDLE(windll.kernel32.OpenThread(winKernel.SYNCHRONIZE,False,self.MTAThread.ident))
                self.MTAThreadStopEvent.set()
-               index=c_int()
-               #Wait for the MTAA thread to die (while still message pumping)
-               
windll.user32.MsgWaitForMultipleObjects(1,byref(MTAThreadHandle),False,5000,0)
+               #Wait for the MTA thread to die (while still message pumping)
+               if 
windll.user32.MsgWaitForMultipleObjects(1,byref(MTAThreadHandle),False,200,0)!=0:
+                       log.debugWarning("Timeout or error while waiting for 
UIAHandler MTA thread")
                windll.kernel32.CloseHandle(MTAThreadHandle)
                del self.MTAThread
 
@@ -167,7 +167,7 @@ class UIAHandler(COMObject):
                self.clientObject.RemoveAllEventHandlers()
 
        def 
IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID):
-               if not self.MTAThreadInitEvent.isSet:
+               if not self.MTAThreadInitEvent.isSet():
                        # UIAHandler hasn't finished initialising yet, so just 
ignore this event.
                        return
                if eventID==UIA_MenuOpenedEventId and 
eventHandler.isPendingEvents("gainFocus"):
@@ -186,7 +186,7 @@ class UIAHandler(COMObject):
                eventHandler.queueEvent(NVDAEventName,obj)
 
        def 
IUIAutomationFocusChangedEventHandler_HandleFocusChangedEvent(self,sender):
-               if not self.MTAThreadInitEvent.isSet:
+               if not self.MTAThreadInitEvent.isSet():
                        # UIAHandler hasn't finished initialising yet, so just 
ignore this event.
                        return
                if not self.isNativeUIAElement(sender):
@@ -211,7 +211,7 @@ class UIAHandler(COMObject):
                eventHandler.queueEvent("gainFocus",obj)
 
        def 
IUIAutomationPropertyChangedEventHandler_HandlePropertyChangedEvent(self,sender,propertyId,newValue):
-               if not self.MTAThreadInitEvent.isSet:
+               if not self.MTAThreadInitEvent.isSet():
                        # UIAHandler hasn't finished initialising yet, so just 
ignore this event.
                        return
                
NVDAEventName=UIAPropertyIdsToNVDAEventNames.get(propertyId,None)

diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
index 5506930..761f5dc 100644
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -86,7 +86,9 @@ class AppModule(appModuleHandler.AppModule):
                windowClassName=obj.windowClassName
                states=obj.states
                controlID=obj.windowControlID
-               if role==controlTypes.ROLE_LISTITEM and 
(windowClassName.startswith("REListBox") or 
windowClassName.startswith("NetUIHWND")):
+               if windowClassName=="REListBox20W" and 
role==controlTypes.ROLE_CHECKBOX:
+                       clsList.insert(0,REListBox20W_CheckBox)
+               elif role==controlTypes.ROLE_LISTITEM and 
(windowClassName.startswith("REListBox") or 
windowClassName.startswith("NetUIHWND")):
                        clsList.insert(0,AutoCompleteListItem)
                if role==controlTypes.ROLE_LISTITEM and 
windowClassName=="OUTEXVLB":
                        clsList.insert(0, AddressBookEntry)
@@ -98,6 +100,16 @@ class AppModule(appModuleHandler.AppModule):
                        elif isinstance(obj,IAccessible) and 
obj.event_objectID==winUser.OBJID_CLIENT and obj.event_childID==0:
                                clsList.insert(0,SuperGridClient2010)
 
+class REListBox20W_CheckBox(IAccessible):
+
+       def script_checkbox(self, gesture):
+               gesture.send()
+               self.event_stateChange()
+
+       __gestures={
+               "kb:space":"checkbox",
+       }
+
 class SuperGridClient2010(IAccessible):
 
        def isDuplicateIAccessibleEvent(self,obj):

diff --git a/source/appModules/zendstudio.py b/source/appModules/zendstudio.py
new file mode 100644
index 0000000..d5ab377
--- /dev/null
+++ b/source/appModules/zendstudio.py
@@ -0,0 +1,5 @@
+"""App module for Zend Studio
+This simply uses the app module for Eclipse.
+"""
+
+from eclipse import *

diff --git a/source/config/__init__.py b/source/config/__init__.py
index 6bc5d65..5e0a4ee 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -144,6 +144,7 @@ confspec = ConfigObj(StringIO(
        reportFontName = boolean(default=false)
        reportFontSize = boolean(default=false)
        reportFontAttributes = boolean(default=false)
+       reportRevisions = boolean(default=false)
        reportColor = boolean(default=False)
        reportAlignment = boolean(default=false)
        reportStyle = boolean(default=false)

diff --git a/source/controlTypes.py b/source/controlTypes.py
index b4d92f0..35745c8 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -183,6 +183,7 @@ STATE_SORTED_ASCENDING=0x100000000
 STATE_SORTED_DESCENDING=0x200000000
 
STATES_SORTED=frozenset([STATE_SORTED,STATE_SORTED_ASCENDING,STATE_SORTED_DESCENDING])
 STATE_HASLONGDESC=0x400000000
+STATE_PINNED=0x800000000
 
 roleLabels={
        # Translators: The word for an unknown control type.
@@ -514,6 +515,8 @@ stateLabels={
        STATE_SORTED_DESCENDING:_("sorted descending"),
        # Translators: a state that denotes that an object (usually a graphic) 
has a long description.
        STATE_HASLONGDESC:_("has long description"),
+       # Translators: a state that denotes that an object is pinned in its 
current location 
+       STATE_PINNED:_("pinned"),
 }
 
 negativeStateLabels={

diff --git a/source/globalCommands.py b/source/globalCommands.py
index d0a3258..7283e14 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -748,7 +748,7 @@ class GlobalCommands(ScriptableObject):
        def script_reportFormatting(self,gesture):
                formatConfig={
                        "detectFormatAfterCursor":False,
-                       
"reportFontName":True,"reportFontSize":True,"reportFontAttributes":True,"reportColor":True,
+                       
"reportFontName":True,"reportFontSize":True,"reportFontAttributes":True,"reportColor":True,"reportRevisions":False,
                        
"reportStyle":True,"reportAlignment":True,"reportSpellingErrors":True,
                        
"reportPage":False,"reportLineNumber":False,"reportTables":False,
                        
"reportLinks":False,"reportHeadings":False,"reportLists":False,

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index 28d89ea..534532d 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -1010,6 +1010,11 @@ class DocumentFormattingDialog(SettingsDialog):
                settingsSizer.Add(self.colorCheckBox,border=10,flag=wx.BOTTOM)
                # Translators: This is the label for a checkbox in the
                # document formatting settings dialog.
+               
self.revisionsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &editor 
revisions"))
+               
self.revisionsCheckBox.SetValue(config.conf["documentFormatting"]["reportRevisions"])
+               
settingsSizer.Add(self.revisionsCheckBox,border=10,flag=wx.BOTTOM)
+               # Translators: This is the label for a checkbox in the
+               # document formatting settings dialog.
                self.styleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report 
st&yle"))
                
self.styleCheckBox.SetValue(config.conf["documentFormatting"]["reportStyle"])
                settingsSizer.Add(self.styleCheckBox,border=10,flag=wx.BOTTOM)
@@ -1089,6 +1094,7 @@ class DocumentFormattingDialog(SettingsDialog):
                
config.conf["documentFormatting"]["reportFontSize"]=self.fontSizeCheckBox.IsChecked()
                
config.conf["documentFormatting"]["reportFontAttributes"]=self.fontAttrsCheckBox.IsChecked()
                
config.conf["documentFormatting"]["reportColor"]=self.colorCheckBox.IsChecked()
+               
config.conf["documentFormatting"]["reportRevisions"]=self.revisionsCheckBox.IsChecked()
                
config.conf["documentFormatting"]["reportAlignment"]=self.alignmentCheckBox.IsChecked()
                
config.conf["documentFormatting"]["reportStyle"]=self.styleCheckBox.IsChecked()
                
config.conf["documentFormatting"]["reportSpellingErrors"]=self.spellingErrorsCheckBox.IsChecked()

diff --git a/source/keyboardHandler.py b/source/keyboardHandler.py
index 7ae3e9c..e934d75 100644
--- a/source/keyboardHandler.py
+++ b/source/keyboardHandler.py
@@ -145,6 +145,13 @@ def 
internal_keyDownEvent(vkCode,scanCode,extended,injected):
                try:
                        inputCore.manager.executeGesture(gesture)
                        trappedKeys.add(keyCode)
+                       if 
canModifiersPerformAction(gesture.generalizedModifiers):
+                               # #3472: These modifiers can perform an action 
if pressed alone
+                               # and we've just consumed the main key.
+                               # Send special reserved vkcode (0xff) to at 
least notify the app's key state that something happendd.
+                               # This allows alt and windows to be bound to 
scripts and
+                               # stops control+shift from switching keyboard 
layouts in cursorManager selection scripts.
+                               KeyboardInputGesture((),0xff,0,False).send()
                        return False
                except inputCore.NoInputGestureAction:
                        if gesture.isNVDAModifierKey:
@@ -212,6 +219,30 @@ def getInputHkl():
                thread = 0
        return winUser.user32.GetKeyboardLayout(thread)
 
+def canModifiersPerformAction(modifiers):
+       """Determine whether given generalized modifiers can perform an action 
if pressed alone.
+       For example, alt activates the menu bar if it isn't modifying another 
key.
+       """
+       if inputCore.manager.isInputHelpActive:
+               return False
+       control = shift = other = False
+       for vk, ext in modifiers:
+               if vk in (winUser.VK_MENU, VK_WIN):
+                       # Alt activates the menu bar.
+                       # Windows activates the Start Menu.
+                       return True
+               elif vk == winUser.VK_CONTROL:
+                       control = True
+               elif vk == winUser.VK_SHIFT:
+                       shift = True
+               elif (vk, ext) not in trappedKeys :
+                       # Trapped modifiers aren't relevant.
+                       other = True
+       if control and shift and not other:
+               # Shift+control switches keyboard layouts.
+               return True
+       return False
+
 class KeyboardInputGesture(inputCore.InputGesture):
        """A key pressed on the traditional system keyboard.
        """

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/nvdaaddonteam/nvda/commits/00d104a9840b/
Changeset:   00d104a9840b
Branch:      None
User:        mdcurran
Date:        2013-09-16 04:08:06
Summary:     Merge branch 't1686' into next. Incubates #1686

Affected #:  3 files

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index 07ac388..7743ad5 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -68,6 +68,9 @@ using namespace std;
 #define wdDISPID_STYLE_NAMELOCAL 0
 #define wdDISPID_RANGE_SPELLINGERRORS 316
 #define wdDISPID_SPELLINGERRORS_COUNT 1
+#define wdDISPID_RANGE_APPLICATION 1000
+#define wdDISPID_APPLICATION_ISSANDBOX 492
+
 #define wdDISPID_RANGE_FONT 5
 #define wdDISPID_FONT_COLOR 159
 #define wdDISPID_FONT_BOLD 130
@@ -516,11 +519,20 @@ void generateXMLAttribsForFormatting(IDispatch* 
pDispatchRange, int startOffset,
                }
        } 
        if(formatConfig&formatConfig_reportSpellingErrors) {
-               IDispatchPtr pDispatchSpellingErrors=NULL;
-               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_SPELLINGERRORS,VT_DISPATCH,&pDispatchSpellingErrors)==S_OK&&pDispatchSpellingErrors)
 {
-                       
_com_dispatch_raw_propget(pDispatchSpellingErrors,wdDISPID_SPELLINGERRORS_COUNT,VT_I4,&iVal);
-                       if(iVal>0) {
-                               
formatAttribsStream<<L"invalid-spelling=\""<<iVal<<L"\" ";
+               IDispatchPtr pDispatchApplication=NULL;
+               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_APPLICATION 
,VT_DISPATCH,&pDispatchApplication)==S_OK && pDispatchApplication) {
+                       bool isSandbox = true;
+                       // We need to ironically enter the if block if the call 
to get IsSandbox property fails
+                       // for backward compatibility because IsSandbox was 
introduced with word 2010 and earlier versions will return a failure for this 
property access.
+                       // This however, means that if this property access 
fails for some reason in word 2010, then we will incorrectly enter this section.
+                       
if(_com_dispatch_raw_propget(pDispatchApplication,wdDISPID_APPLICATION_ISSANDBOX
 ,VT_BOOL,&isSandbox)!=S_OK || !isSandbox ) {
+                               IDispatchPtr pDispatchSpellingErrors=NULL;
+                               
if(_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_SPELLINGERRORS,VT_DISPATCH,&pDispatchSpellingErrors)==S_OK&&pDispatchSpellingErrors)
 {
+                                       
_com_dispatch_raw_propget(pDispatchSpellingErrors,wdDISPID_SPELLINGERRORS_COUNT,VT_I4,&iVal);
+                                       if(iVal>0) {
+                                               
formatAttribsStream<<L"invalid-spelling=\""<<iVal<<L"\" ";
+                                       }
+                               }
                        }
                }
        }

diff --git a/source/NVDAObjects/IAccessible/__init__.py 
b/source/NVDAObjects/IAccessible/__init__.py
index 40f2151..08d9e46 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1797,4 +1797,5 @@ _staticMap={
        ("NUIDialog",oleacc.ROLE_SYSTEM_CLIENT):"NUIDialogClient",
        ("_WwN",oleacc.ROLE_SYSTEM_TEXT):"winword.SpellCheckErrorField",
        ("_WwO",oleacc.ROLE_SYSTEM_TEXT):"winword.SpellCheckErrorField",
+       ("_WwB",oleacc.ROLE_SYSTEM_CLIENT):"winword.ProtectedDocumentPane",
 }

diff --git a/source/NVDAObjects/IAccessible/winword.py 
b/source/NVDAObjects/IAccessible/winword.py
index c7080285..5bbd315 100644
--- a/source/NVDAObjects/IAccessible/winword.py
+++ b/source/NVDAObjects/IAccessible/winword.py
@@ -6,6 +6,7 @@
 from comtypes import COMError
 import comtypes.automation
 import comtypes.client
+import ctypes
 import NVDAHelper
 from logHandler import log
 import oleacc
@@ -13,6 +14,7 @@ import winUser
 import speech
 import controlTypes
 import textInfos
+import eventHandler
 
 from . import IAccessible
 from NVDAObjects.window.winword import WordDocument 
@@ -66,3 +68,25 @@ class SpellCheckErrorField(IAccessible,WordDocument):
                if errorText:
                        speech.speakText(errorText)
                        speech.speakSpelling(errorText)
+
+
+class ProtectedDocumentPane(IAccessible):
+       """The pane that gets focus in case a document opens in protected mode 
in word
+       This is mapped to the window class _WWB and role 
oleacc.ROLE_SYSTEM_CLIENT
+       """
+       
+       def event_gainFocus(self):
+               """On gaining focus, simply set the focus on a child of type 
word document. 
+               This is just a container window.
+               """
+               if eventHandler.isPendingEvents("gainFocus"):
+                       return
+               document=next((x for x in self.children if 
isinstance(x,WordDocument)), None)  
+               if document:
+                       curThreadID=ctypes.windll.kernel32.GetCurrentThreadId()
+                       
ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,True)
+                       ctypes.windll.user32.SetFocus(document.windowHandle)
+                       
ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,False)
+                       if not document.WinwordWindowObject.active:
+                               document.WinwordWindowObject.activate()
+                               


https://bitbucket.org/nvdaaddonteam/nvda/commits/ca1d151113ff/
Changeset:   ca1d151113ff
Branch:      None
User:        mdcurran
Date:        2013-09-16 08:45:39
Summary:     Lists in browse mode: report the number of controls (items) in the 
list, rather than also including text nodes (spaces).

E.g. navbar on www.nvaccess.org now reports as 8 items, rather than 14.
Note that a new _childControlCount attribute has been exposed on controlField 
nodes coming from virtualBuffers.

Affected #:  2 files

diff --git a/nvdaHelper/vbufBase/storage.cpp b/nvdaHelper/vbufBase/storage.cpp
index 7a9854a..a5eb6d9 100644
--- a/nvdaHelper/vbufBase/storage.cpp
+++ b/nvdaHelper/vbufBase/storage.cpp
@@ -207,8 +207,10 @@ void 
VBufStorage_fieldNode_t::generateAttributesForMarkupOpeningTag(std::wstring
        s<<L"isBlock=\""<<this->isBlock<<L"\" ";
        s<<L"isHidden=\""<<this->isHidden<<L"\" ";
        int childCount=0;
+       int childControlCount=0;
        for(VBufStorage_fieldNode_t* 
child=this->firstChild;child!=NULL;child=child->next) {
                ++childCount;
+               if((child->length)>0&&child->firstChild) ++childControlCount;
        }
        int parentChildCount=1;
        int indexInParent=0;
@@ -219,7 +221,7 @@ void 
VBufStorage_fieldNode_t::generateAttributesForMarkupOpeningTag(std::wstring
        for(VBufStorage_fieldNode_t* 
next=this->next;next!=NULL;next=next->next) {
                ++parentChildCount;
        }
-       s<<L"_childcount=\""<<childCount<<L"\" 
_indexInParent=\""<<indexInParent<<L"\" 
_parentChildCount=\""<<parentChildCount<<L"\" ";
+       s<<L"_childcount=\""<<childCount<<L"\" 
_childcontrolcount=\""<<childControlCount<<L"\" 
_indexInParent=\""<<indexInParent<<L"\" 
_parentChildCount=\""<<parentChildCount<<L"\" ";
        text+=s.str();
        for(VBufStorage_attributeMap_t::iterator 
i=this->attributes.begin();i!=this->attributes.end();++i) {
                text+=i->first;

diff --git a/source/speech.py b/source/speech.py
index 8278fba..24e2a66 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -888,7 +888,7 @@ def 
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
                formatConfig=config.conf["documentFormatting"]
 
        presCat=attrs.getPresentationCategory(ancestorAttrs,formatConfig, 
reason=reason)
-       childCount=int(attrs.get('_childcount',"0"))
+       childControlCount=int(attrs.get('_childcontrolcount',"0"))
        if reason==controlTypes.REASON_FOCUS or 
attrs.get('alwaysReportName',False):
                name=attrs.get('name',"")
        else:
@@ -945,7 +945,7 @@ def 
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
        if speakEntry and fieldType=="start_addedToControlFieldStack" and 
role==controlTypes.ROLE_LIST and controlTypes.STATE_READONLY in states:
                # List.
                # Translators: Speaks number of items in a list (example 
output: list with 5 items).
-               return roleText+" "+_("with %s items")%childCount
+               return roleText+" "+_("with %s items")%childControlCount
        elif fieldType=="start_addedToControlFieldStack" and 
role==controlTypes.ROLE_TABLE and tableID:
                # Table.
                return " ".join((roleText, 
getSpeechTextForProperties(_tableID=tableID, 
rowCount=attrs.get("table-rowcount"), 
columnCount=attrs.get("table-columncount")),levelText))


https://bitbucket.org/nvdaaddonteam/nvda/commits/051bc82be1bf/
Changeset:   051bc82be1bf
Branch:      None
User:        mdcurran
Date:        2013-09-16 08:49:09
Summary:     Merge branch 't2151' into next. Incubates #2151

Affected #:  2 files

diff --git a/nvdaHelper/vbufBase/storage.cpp b/nvdaHelper/vbufBase/storage.cpp
index 7a9854a..a5eb6d9 100644
--- a/nvdaHelper/vbufBase/storage.cpp
+++ b/nvdaHelper/vbufBase/storage.cpp
@@ -207,8 +207,10 @@ void 
VBufStorage_fieldNode_t::generateAttributesForMarkupOpeningTag(std::wstring
        s<<L"isBlock=\""<<this->isBlock<<L"\" ";
        s<<L"isHidden=\""<<this->isHidden<<L"\" ";
        int childCount=0;
+       int childControlCount=0;
        for(VBufStorage_fieldNode_t* 
child=this->firstChild;child!=NULL;child=child->next) {
                ++childCount;
+               if((child->length)>0&&child->firstChild) ++childControlCount;
        }
        int parentChildCount=1;
        int indexInParent=0;
@@ -219,7 +221,7 @@ void 
VBufStorage_fieldNode_t::generateAttributesForMarkupOpeningTag(std::wstring
        for(VBufStorage_fieldNode_t* 
next=this->next;next!=NULL;next=next->next) {
                ++parentChildCount;
        }
-       s<<L"_childcount=\""<<childCount<<L"\" 
_indexInParent=\""<<indexInParent<<L"\" 
_parentChildCount=\""<<parentChildCount<<L"\" ";
+       s<<L"_childcount=\""<<childCount<<L"\" 
_childcontrolcount=\""<<childControlCount<<L"\" 
_indexInParent=\""<<indexInParent<<L"\" 
_parentChildCount=\""<<parentChildCount<<L"\" ";
        text+=s.str();
        for(VBufStorage_attributeMap_t::iterator 
i=this->attributes.begin();i!=this->attributes.end();++i) {
                text+=i->first;

diff --git a/source/speech.py b/source/speech.py
index 8278fba..24e2a66 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -888,7 +888,7 @@ def 
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
                formatConfig=config.conf["documentFormatting"]
 
        presCat=attrs.getPresentationCategory(ancestorAttrs,formatConfig, 
reason=reason)
-       childCount=int(attrs.get('_childcount',"0"))
+       childControlCount=int(attrs.get('_childcontrolcount',"0"))
        if reason==controlTypes.REASON_FOCUS or 
attrs.get('alwaysReportName',False):
                name=attrs.get('name',"")
        else:
@@ -945,7 +945,7 @@ def 
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
        if speakEntry and fieldType=="start_addedToControlFieldStack" and 
role==controlTypes.ROLE_LIST and controlTypes.STATE_READONLY in states:
                # List.
                # Translators: Speaks number of items in a list (example 
output: list with 5 items).
-               return roleText+" "+_("with %s items")%childCount
+               return roleText+" "+_("with %s items")%childControlCount
        elif fieldType=="start_addedToControlFieldStack" and 
role==controlTypes.ROLE_TABLE and tableID:
                # Table.
                return " ".join((roleText, 
getSpeechTextForProperties(_tableID=tableID, 
rowCount=attrs.get("table-rowcount"), 
columnCount=attrs.get("table-columncount")),levelText))


https://bitbucket.org/nvdaaddonteam/nvda/commits/d604742d48f4/
Changeset:   d604742d48f4
Branch:      next
User:        mdcurran
Date:        2013-09-17 01:50:42
Summary:     Merge branch 'master' into next

Affected #:  2 files

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 512f347..33f17cd 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -22,6 +22,7 @@
 - It is now possible to bind scripts to keyboard gestures containing Alt 
and/or Windows keys as modifiers. Previously, if this was done, performing the 
script would cause the Start Menu or menu bar to be activated. (#3472)
 - Selecting text in browse mode documents (e.g. using control+shift+end) no 
longer causes the keyboard layout to be switched on systems with multiple 
keyboard layouts installed. (#3472)
 - Internet Explorer should no longer crash or become unusable when closing 
NVDA. (#3397)
+- Physical movement and other events on some newer computers are no longer 
treated as inappropriate key presses. Previously, this silenced speech and 
sometimes triggered NVDA commands. (#3468)
 
 
 = 2013.2 =

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index df6f381..b440f81 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -633,7 +633,7 @@ The Voice Settings dialog box contains the following 
options:
 ==== Voice ====
 The first option that you land on in this dialog is a combo box listing all 
the voices of the current synthesizer that you have installed.
 You can use the arrow keys to listen to all the various choices.
-Left and Up arrow take you up in the list, while right and down arrow moves 
you down in the list.
+Left and Up arrow take you up in the list, while right and down arrow move you 
down in the list.
 
 ==== Variant ====
 If you are using the Espeak synthesizer that is packaged with NVDA, this is a 
combo box that lets you select the Variant the synthesizer should speak with.

Repository URL: https://bitbucket.org/nvdaaddonteam/nvda/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.

Other related posts: