[nvda-addons] Re: commit/nvda: josephsl: Merge branch 'master' into t4354

  • From: "Joseph Lee" <joseph.lee22590@xxxxxxxxx>
  • To: <nvda-addons@xxxxxxxxxxxxx>
  • Date: Sun, 26 Oct 2014 15:29:39 -0700

Hi Noelia,
I've merged latest master branch code from NV Access server, so you can work 
from latest revisions.
Cheers,
Joseph

-----Original Message-----
From: nvda-addons-commits-bounce@xxxxxxxxxxxxx 
[mailto:nvda-addons-commits-bounce@xxxxxxxxxxxxx] On Behalf Of 
commits-noreply@xxxxxxxxxxxxx
Sent: Sunday, October 26, 2014 3:28 PM
To: nvda-addons-commits@xxxxxxxxxxxxx
Subject: commit/nvda: josephsl: Merge branch 'master' into t4354

1 new commit in nvda:

https://bitbucket.org/nvdaaddonteam/nvda/commits/ddd4982e4dfe/
Changeset:   ddd4982e4dfe
Branch:      t4354
User:        josephsl
Date:        2014-10-26 22:27:58+00:00
Summary:     Merge branch 'master' into t4354

Affected #:  34 files

diff --git a/contributors.txt b/contributors.txt
index 615b079..51d90a1 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -146,3 +146,6 @@ Dr. Mireia Ribera
 Ruben Alcaraz
 Nikos Demetriou
 Daniel Johansson
+Manish Agrawal
+Aaron Cannon
+derek riemer

diff --git a/include/liblouis b/include/liblouis
index 1e1e758..5f9c03f 160000
--- a/include/liblouis
+++ b/include/liblouis
@@ -1 +1 @@
-Subproject commit 1e1e7587cfbc263b351644e52fdaf2684103d6c8
+Subproject commit 5f9c03f2a3478561deb6ae4798175094be8a26c2

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

diff --git a/miscDeps b/miscDeps
index 6fbd449..eee6560 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit 6fbd44904c8debe4cf5a73e62a91ac8a00d1860c
+Subproject commit eee6560e4ae4de5455e94dfb99ba596f36bb21f5

diff --git a/nvdaHelper/archBuild_sconscript b/nvdaHelper/archBuild_sconscript
index 1c63dcc..fd45e07 100644
--- a/nvdaHelper/archBuild_sconscript
+++ b/nvdaHelper/archBuild_sconscript
@@ -26,6 +26,7 @@ Import(
 TARGET_ARCH=env['TARGET_ARCH']
 debug=env['nvdaHelperDebugFlags']
 release=env['release']
+signExec=env['signExec'] if env['certFile'] else None
 
 #Some defines and includes for the environment
 
env.Append(CPPDEFINES=['UNICODE','_CRT_SECURE_NO_DEPRECATE',('LOGLEVEL','${nvdaHelperLogLevel}'),('_WIN32_WINNT','_WIN32_WINNT_WINXP')])
@@ -66,6 +67,8 @@ if TARGET_ARCH=='x86':
 
 ia2RPCStubs=env.SConscript('ia2_sconscript')
 Export('ia2RPCStubs')
+if signExec:
+       env.AddPostAction(ia2RPCStubs[0],[signExec])
 env.Install(libInstallDir,ia2RPCStubs[0]) #proxy dll
 if TARGET_ARCH=='x86':
        env.Install(sourceTypelibDir,ia2RPCStubs[1]) #typelib
@@ -73,43 +76,65 @@ if TARGET_ARCH=='x86':
 if TARGET_ARCH=='x86':
        localLib=env.SConscript('local/sconscript')
        Export('localLib')
+       if signExec:
+               env.AddPostAction(localLib[0],[signExec])
        env.Install(libInstallDir,localLib)
 
 clientLib=env.SConscript('client/sconscript')
 Export('clientLib')
+if signExec:
+       env.AddPostAction(clientLib[0],[signExec])
 env.Install(clientInstallDir,clientLib)
 
 minHookLib=env.SConscript('minHook/sconscript')
 Export('minHookLib')
+if signExec:
+       env.AddPostAction(minHookLib[0],[signExec])
 env.Install(libInstallDir,minHookLib)
 
 remoteLib=env.SConscript('remote/sconscript')
 Export('remoteLib')
+if signExec:
+       env.AddPostAction(remoteLib[0],[signExec])
 env.Install(libInstallDir,remoteLib)
 
 if TARGET_ARCH=='x86_64':
        remoteLoaderProgram=env.SConscript('remoteLoader/sconscript')
+       if signExec:
+               env.AddPostAction(remoteLoaderProgram,[signExec])
        env.Install(libInstallDir,remoteLoaderProgram)
 
 vbufBaseStaticLib=env.SConscript('vbufBase/sconscript')
 Export('vbufBaseStaticLib')
 
 adobeAcrobatVBufBackend=env.SConscript('vbufBackends/adobeAcrobat/sconscript')
+if signExec:
+       env.AddPostAction(adobeAcrobatVBufBackend[0],[signExec])
 env.Install(libInstallDir,adobeAcrobatVBufBackend)
 
 adobeFlashVBufBackend=env.SConscript('vbufBackends/adobeFlash/sconscript')
+if signExec:
+       env.AddPostAction(adobeFlashVBufBackend[0],[signExec])
 env.Install(libInstallDir,adobeFlashVBufBackend)
 
 
lotusNotesRichTextVBufBackend=env.SConscript('vbufBackends/lotusNotesRichText/sconscript')
+if signExec:
+       env.AddPostAction(lotusNotesRichTextVBufBackend[0],[signExec])
 env.Install(libInstallDir,lotusNotesRichTextVBufBackend)
 
 geckoVBufBackend=env.SConscript('vbufBackends/gecko_ia2/sconscript')
+if signExec:
+       env.AddPostAction(geckoVBufBackend[0],[signExec])
 env.Install(libInstallDir,geckoVBufBackend)
 
 mshtmlVBufBackend=env.SConscript('vbufBackends/mshtml/sconscript')
+if signExec:
+       env.AddPostAction(mshtmlVBufBackend[0],[signExec])
 env.Install(libInstallDir,mshtmlVBufBackend)
 
 webKitVBufBackend=env.SConscript('vbufBackends/webKit/sconscript')
+if signExec:
+       env.AddPostAction(webKitVBufBackend[0],[signExec])
 env.Install(libInstallDir,webKitVBufBackend)
 
 if TARGET_ARCH=='x86':

diff --git a/nvdaHelper/building.txt b/nvdaHelper/building.txt
deleted file mode 100644
index 09cc81f..0000000
--- a/nvdaHelper/building.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-Build Instructions
-
-Prerequisites:
-
-NVDAHelper needs The Microsoft Windows SDK, version 6.1 or later. You can find 
it here:
-http://msdn.microsoft.com/en-us/windows/bb980924.aspx
-
- The gecko_ia2 virtual buffer backend requires the IAccessible2 IDL, version 
1.2 or later. You can obtain it here:
-http://www.linuxfoundation.org/en/Accessibility/IAccessible2
-Download the merged IDL and copy it to ..\include\ia2\ia2.idl.
-
-The adobeAcrobat virtual buffer backend requires the Adobe Acrobat 
accessibility IDL, version 9.1 or later. This can be found in the client files 
archive available from 
http://www.adobe.com/devnet/acrobat/interapplication_communication.html
-The archive is named something like Acrobat_Accessibility_9.1.zip.
-Extract the AcrobatAccess.idl file into ..\include\AcrobatAccess.
-
-The apiHook module requires MinHook 1.1.0 or later: 
http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
-       * Download the source archive. The file name is something like 
MinHook_110_src.zip depending on exact version.
-       * You will need an account on CodeProject to download from there.
-       * extract the source archive, and from it copy the libMinHook directory 
to NVDA's source/include directory.
-
-minHook (and possibly in future nvdaHelper) depends on the Boost c++ library 
1.42 or later:
-       * you can download the latest Windows installer from 
http://www.boostpro.com/download
-       * On the components page of the installer, make sure to install all the 
defaults (what ever is already checked), along with anything else you may wish 
to have for other projects.
-       * So far only boost headers are used, none of the pre-compiled 
libraries are necessary for nvda/minHook.
-
-The NVDAHelper build is managed by the SCons build system, version 1.3.0 or 
later: http://www.scons.org/
-
-Building the library:
-
-There is no need to use the MSVC environment command prompt when building, as 
scons will locate what it needs automatically in any standard environment.
-
-To build and install the library and all virtual buffer backends, open a 
command prompt, cd to the top-level directory of nvdaHelper and run the command:
-scons install
-By default a version with debugging symbols will be generated. To build a 
release version, provide release=1 on the command line when running scons:
-scons install release=1
-
-Note that now both x86 and x64 versions of the libraries are automatically 
built, there is no need to supply any target arch variables by default.
-
-However, if you specifically only want to build certain architectures, you can 
provide a comma separated list of the required architectures to the 
targetArchitectures variable on the commandline, like so:
-scons targetArchitectures=x86
-or
-scons targetArchitectures=x86_64
-or
-scons targetArchitectures=x86,x86_64
- 
\ No newline at end of file

diff --git a/nvdaHelper/contributors.txt b/nvdaHelper/contributors.txt
deleted file mode 100755
index 5c0a415..0000000
--- a/nvdaHelper/contributors.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Michael Curran <mick@xxxxxxxxxx>
-James Teh <jamie@xxxxxxxxxxx>
-Aleksey Sadovoy <lex@xxxxxx>

diff --git a/nvdaHelper/liblouis/sconscript b/nvdaHelper/liblouis/sconscript
index 72cdef4..1050407 100644
--- a/nvdaHelper/liblouis/sconscript
+++ b/nvdaHelper/liblouis/sconscript
@@ -24,7 +24,7 @@ louisRootDir = env.Dir("#include/liblouis")
 louisSourceDir = louisRootDir.Dir("liblouis")
 outDir = sourceDir.Dir("louis")
 
-RE_AC_INIT = re.compile(r"^AC_INIT\((?P<name>.*), (?P<version>.*), 
(?P<maintainer>.*)\)")
+RE_AC_INIT = re.compile(r"^AC_INIT\(\[(?P<package>.*)\], \[(?P<version>.*)\], 
\[(?P<bugReport>.*)\], \[(?P<tarName>.*)\], \[(?P<url>.*)\]\)")
 def getLouisVersion():
        # Get the version from configure.ac.
        with file(louisRootDir.File("configure.ac").abspath) as f:
@@ -50,6 +50,7 @@ sourceFiles = [
        "lou_translateString.c",
        "lou_backTranslateString.c",
        "wrappers.c",
+       "logging.c",
 ]
 objs = [env.Object("%s.obj" % f, louisSourceDir.File(f)) for f in sourceFiles]
 louisLib = env.SharedLibrary("liblouis", objs + ["liblouis.def"])

diff --git a/nvdaHelper/minHook/dllmain.cpp b/nvdaHelper/minHook/dllmain.cpp
index 25d6823..07a9e41 100644
--- a/nvdaHelper/minHook/dllmain.cpp
+++ b/nvdaHelper/minHook/dllmain.cpp
@@ -18,7 +18,7 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 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) {
+               if(MH_DisableHook(MH_ALL_HOOKS)!=MH_ERROR_NOT_INITIALIZED) {
                        //Give enough time for all hook functions to complete.
                        Sleep(250);
                        MH_Uninitialize();

diff --git a/nvdaHelper/minHook/sconscript b/nvdaHelper/minHook/sconscript
index 497a242..886b606 100644
--- a/nvdaHelper/minHook/sconscript
+++ b/nvdaHelper/minHook/sconscript
@@ -19,10 +19,11 @@ sourceFiles=[
 
 
objFiles=[env.Object('_minHook_%s.obj'%x.replace('/','_'),minhookPath.File('src/%s'%x))
 for x in sourceFiles]
 objFiles.append('dllmain.cpp')
+resFile=env.RES('_minHook',minhookPath.File('dll_resources/minHook.rc'))
 
 minHookLib=env.SharedLibrary(
        target='minHook',
-       source=objFiles+[minhookPath.File('dll_resources/minHook.def')],
+       source=objFiles+[resFile,minhookPath.File('dll_resources/minHook.def')],
 )
 
 Return('minHookLib')

diff --git a/nvdaHelper/remote/apiHook.cpp b/nvdaHelper/remote/apiHook.cpp
index 0a3430b..4c9848e 100644
--- a/nvdaHelper/remote/apiHook.cpp
+++ b/nvdaHelper/remote/apiHook.cpp
@@ -39,8 +39,6 @@ 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
 
@@ -55,8 +53,8 @@ typedef MH_STATUS(*MH_DisableAllHooks_funcType)();
 defMHFP(MH_Initialize);
 defMHFP(MH_Uninitialize);
 defMHFP(MH_CreateHook);
-defMHFP(MH_EnableAllHooks);
-defMHFP(MH_DisableAllHooks);
+defMHFP(MH_EnableHook);
+defMHFP(MH_DisableHook);
 
  bool apiHook_initialize() {
        LOG_DEBUG("calling MH_Initialize");
@@ -71,8 +69,8 @@ defMHFP(MH_DisableAllHooks);
        setMHFP(MH_Initialize);
        setMHFP(MH_Uninitialize);
        setMHFP(MH_CreateHook);
-       setMHFP(MH_EnableAllHooks);
-       setMHFP(MH_DisableAllHooks);
+       setMHFP(MH_EnableHook);
+       setMHFP(MH_DisableHook);
        if(error_setNHFP) {
                LOG_ERROR(L"Error setting minHook function pointers");
                FreeLibrary(minhookLibHandle);
@@ -124,7 +122,7 @@ bool apiHook_enableHooks() {
                LOG_ERROR(L"apiHooks not initialized");
                return false;
        }
-       res=MH_EnableAllHooks_fp();
+       res=MH_EnableHook_fp(MH_ALL_HOOKS);
        nhAssert(res==MH_OK);
        return TRUE;
 }
@@ -137,7 +135,7 @@ bool apiHook_terminate() {
                LOG_ERROR(L"apiHooks not initialized");
                return false;
        }
-       res=MH_DisableAllHooks_fp();
+       res=MH_DisableHook_fp(MH_ALL_HOOKS);
        nhAssert(res==MH_OK);
        g_hookedFunctions.clear();
        //Give enough time for all hook functions to complete.

diff --git a/nvdaHelper/remote/ia2LiveRegions.cpp 
b/nvdaHelper/remote/ia2LiveRegions.cpp
index a3c584d..df389fe 100644
--- a/nvdaHelper/remote/ia2LiveRegions.cpp
+++ b/nvdaHelper/remote/ia2LiveRegions.cpp
@@ -23,6 +23,17 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
 using namespace std;
 
+bool fetchIA2Attributes(IAccessible2* pacc2, map<wstring,wstring>& attribsMap) 
{
+       BSTR attribs=NULL;
+       pacc2->get_attributes(&attribs);
+       if(!attribs) {
+               return false;
+       }
+       IA2AttribsToMap(attribs,attribsMap);
+       SysFreeString(attribs);
+       return true;
+}
+
 IAccessible2* findAriaAtomic(IAccessible2* pacc2,map<wstring,wstring>& 
attribsMap) {
        map<wstring,wstring>::iterator i=attribsMap.find(L"atomic");
        bool atomic=(i!=attribsMap.end()&&i->second.compare(L"true")==0);
@@ -38,12 +49,8 @@ IAccessible2* findAriaAtomic(IAccessible2* 
pacc2,map<wstring,wstring>& attribsMa
                        if(pdispParent) {
                                IAccessible2* pacc2Parent=NULL;
                                
if(pdispParent->QueryInterface(IID_IAccessible2,(void**)&pacc2Parent)==S_OK&&pacc2Parent)
 {
-                                       BSTR parentAttribs=NULL;
-                                       
pacc2Parent->get_attributes(&parentAttribs);
-                                       if(parentAttribs) {
-                                               map<wstring,wstring> 
parentAttribsMap;
-                                               
IA2AttribsToMap(parentAttribs,parentAttribsMap);
-                                               SysFreeString(parentAttribs);
+                                       map<wstring,wstring> parentAttribsMap;
+                                       
if(fetchIA2Attributes(pacc2Parent,parentAttribsMap)) {
                                                
pacc2Atomic=findAriaAtomic(pacc2Parent,parentAttribsMap);
                                        }
                                        pacc2Parent->Release();
@@ -71,8 +78,13 @@ bool getTextFromIAccessible(wstring& textBuf, IAccessible2* 
pacc2, bool useNewTe
                                if(varChildren[i].vt==VT_DISPATCH) {
                                        IAccessible2* pacc2Child=NULL;
                                        
if(varChildren[i].pdispVal&&varChildren[i].pdispVal->QueryInterface(IID_IAccessible2,(void**)&pacc2Child)==S_OK)
 {
-                                               
if(getTextFromIAccessible(textBuf,pacc2Child)) {
-                                                       gotText=true;
+                                               map<wstring,wstring> 
childAttribsMap;
+                                               
fetchIA2Attributes(pacc2Child,childAttribsMap);
+                                               auto 
i=childAttribsMap.find(L"live");
+                                               
if(i==childAttribsMap.end()||i->second.compare(L"off")!=0) {
+                                                       
if(getTextFromIAccessible(textBuf,pacc2Child)) {
+                                                               gotText=true;
+                                                       }
                                                }
                                                pacc2Child->Release();
                                        }
@@ -110,8 +122,13 @@ bool getTextFromIAccessible(wstring& textBuf, 
IAccessible2* pacc2, bool useNewTe
                                                
if(paccHypertext->get_hyperlink(hyperlinkIndex,&paccHyperlink)==S_OK) {
                                                        IAccessible2* 
pacc2Child=NULL;
                                                        
if(paccHyperlink->QueryInterface(IID_IAccessible2,(void**)&pacc2Child)==S_OK) {
-                                                               
if(getTextFromIAccessible(textBuf,pacc2Child)) {
-                                                                       
gotText=true;
+                                                               
map<wstring,wstring> childAttribsMap;
+                                                               
fetchIA2Attributes(pacc2Child,childAttribsMap);
+                                                               auto 
i=childAttribsMap.find(L"live");
+                                                               
if(i==childAttribsMap.end()||i->second.compare(L"off")!=0) {
+                                                                       
if(getTextFromIAccessible(textBuf,pacc2Child)) {
+                                                                               
gotText=true;
+                                                                       }
                                                                }
                                                                charAdded=true;
                                                                
pacc2Child->Release();
@@ -217,19 +234,12 @@ void CALLBACK winEventProcHook(HWINEVENTHOOK hookID, 
DWORD eventID, HWND hwnd, l
        pserv->Release();
        if(!pacc2) return;
        //Retreave the IAccessible2 attributes, and if the object is not a live 
region then ignore the event.
-       BSTR attribs=NULL;
-       pacc2->get_attributes(&attribs);
-       if(!attribs) {
+       map<wstring,wstring> attribsMap;
+       if(!fetchIA2Attributes(pacc2,attribsMap)) {
                pacc2->Release();
                return;
        }
-       map<wstring,wstring> attribsMap;
-       IA2AttribsToMap(attribs,attribsMap);
-       SysFreeString(attribs);
-       map<wstring,wstring>::iterator i;
-       i=attribsMap.find(L"live");
-       bool isRegionRoot=(i!=attribsMap.end());
-       i=attribsMap.find(L"container-live");
+       auto i=attribsMap.find(L"container-live");
        bool 
live=(i!=attribsMap.end()&&(i->second.compare(L"polite")==0||i->second.compare(L"assertive")==0||i->second.compare(L"rude")==0));
        if(!live) {
                pacc2->Release();
@@ -251,23 +261,41 @@ void CALLBACK winEventProcHook(HWINEVENTHOOK hookID, 
DWORD eventID, HWND hwnd, l
                allowText=(i->second.find(L"text",0)!=wstring::npos);
                allowAdditions=(i->second.find(L"additions",0)!=wstring::npos);
        } 
-       //Only handle show events if additions are allowed and this is not the 
root of a region.
-       if(eventID==EVENT_OBJECT_SHOW&&(!allowAdditions||isRegionRoot)) {
+       attribsMap.clear();
+       //Only handle show events if additions are allowed
+       if(eventID==EVENT_OBJECT_SHOW&&!allowAdditions) {
                pacc2->Release();
                return;
        }
        // If this is a show event and this is not the root of the region and 
there is a text parent, 
        // We can ignore this event as there will be text events which can 
handle this better
        if(eventID==EVENT_OBJECT_SHOW) {
-       bool ignoreShowEvent=false;
+               bool ignoreShowEvent=false;
                IDispatch* pdispParent=NULL;
                pacc2->get_accParent(&pdispParent);
                if(pdispParent) {
+                       // check for text on parent
                        IAccessibleText* paccTextParent=NULL;
                        
if(pdispParent->QueryInterface(IID_IAccessibleText,(void**)&paccTextParent)==S_OK&&paccTextParent)
 {
                                ignoreShowEvent=true;
                                paccTextParent->Release();
                        }
+                       if(!ignoreShowEvent) {
+                               // Check for useful container-live on parent, 
as if missing or off, then child must be the root 
+                               // Firstly, we assume we are the root of the 
region and therefore should ignore the event
+                               ignoreShowEvent=true;
+                               IAccessible2* pacc2Parent=NULL;
+                               
if(pdispParent->QueryInterface(IID_IAccessible2,(void**)&pacc2Parent)==S_OK) {
+                                       
if(fetchIA2Attributes(pacc2Parent,attribsMap)) {
+                                               
i=attribsMap.find(L"container-live");
+                                               
if(i!=attribsMap.end()&&(i->second.compare(L"polite")==0||i->second.compare(L"assertive")==0||i->second.compare(L"rude")==0))
 {
+                                                       // There is a valid 
container-live that is not off, so therefore the child is definitly not the root
+                                                       ignoreShowEvent=false;
+                                               }
+                                       }
+                                       pacc2Parent->Release();
+                               }
+                       }
                        pdispParent->Release();
                }
                if(ignoreShowEvent) {

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp 
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index 7bd5a9a..3e42b09 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -385,9 +385,17 @@ void 
MshtmlVBufStorage_controlFieldNode_t::reportLiveText(wstring& text) {
        }
 }
 
+bool isNodeInLiveRegion(VBufStorage_fieldNode_t* node) {
+       if(!node) return false;
+       if(node->getFirstChild()) {
+               return 
((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode!=NULL;
+       }
+       return true;
+}
+
 void MshtmlVBufStorage_controlFieldNode_t::reportLiveAddition() {
        wstring text; //=(this->ariaLiveAtomicNode==this)?L"atomic: 
":L"additions: ";
-       this->getTextInRange(0,this->getLength(),text,false);
+       this->getTextInRange(0,this->getLength(),text,false,isNodeInLiveRegion);
        this->reportLiveText(text);
 }
 

diff --git a/nvdaHelper/vbufBase/storage.cpp b/nvdaHelper/vbufBase/storage.cpp
index ed7fbd3..d99dfb8 100644
--- a/nvdaHelper/vbufBase/storage.cpp
+++ b/nvdaHelper/vbufBase/storage.cpp
@@ -239,7 +239,7 @@ void 
VBufStorage_fieldNode_t::generateMarkupClosingTag(std::wstring& text) {
        text+=L">";
 }
 
-void VBufStorage_fieldNode_t::getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool useMarkup) {
+void VBufStorage_fieldNode_t::getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool useMarkup, bool(*filter)(VBufStorage_fieldNode_t*)) {
        if(this->length==0) {
                LOG_DEBUG(L"node has 0 length, not collecting text");
                return;
@@ -260,9 +260,9 @@ void VBufStorage_fieldNode_t::getTextInRange(int 
startOffset, int endOffset, std
                nhAssert(childLength>=0); //length can't be negative
                childEnd+=childLength;
                LOG_DEBUG(L"child with offsets of "<<childStart<<L" and 
"<<childEnd); 
-               if(childEnd>startOffset&&endOffset>childStart) {
+               
if(childEnd>startOffset&&endOffset>childStart&&(!filter||filter(child))) {
                        LOG_DEBUG(L"child offsets overlap requested offsets");
-                       
child->getTextInRange(max(startOffset,childStart)-childStart,min(endOffset-childStart,childLength),text,useMarkup);
+                       
child->getTextInRange(max(startOffset,childStart)-childStart,min(endOffset-childStart,childLength),text,useMarkup,filter);
                }
                childStart+=childLength;
                LOG_DEBUG(L"childStart is now "<<childStart);
@@ -358,7 +358,7 @@ void 
VBufStorage_textFieldNode_t::generateMarkupTagName(std::wstring& text) {
        text+=L"text";
 }
 
-void VBufStorage_textFieldNode_t::getTextInRange(int startOffset, int 
endOffset, std::wstring& text, bool useMarkup) {
+void VBufStorage_textFieldNode_t::getTextInRange(int startOffset, int 
endOffset, std::wstring& text, bool useMarkup, 
bool(*filter)(VBufStorage_fieldNode_t*)) {
        LOG_DEBUG(L"getting text between offsets "<<startOffset<<L" and 
"<<endOffset);
        if(useMarkup) {
                this->generateMarkupOpeningTag(text,startOffset,endOffset);

diff --git a/nvdaHelper/vbufBase/storage.h b/nvdaHelper/vbufBase/storage.h
index 3456584..795d9f4 100644
--- a/nvdaHelper/vbufBase/storage.h
+++ b/nvdaHelper/vbufBase/storage.h
@@ -286,9 +286,10 @@ class VBufStorage_fieldNode_t {
  * @param endOffset the offset to end at. Use -1 to mean node's end offset. 
  * @param text a string in whish to append the text.
  * @param useMarkup if true then markup indicating opening and closing of 
fields will be included.
+ * @param filter: a function that takes the current recursive node and returns 
true if text should be fetched and false if it should be skipped.
  * @return true if successfull, false otherwize.
  */ 
-       virtual void getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool useMarkup=false);
+       virtual void getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool 
useMarkup=false,bool(*filter)(VBufStorage_fieldNode_t*)=NULL);
 
 /**
  * @return a string providing information about this node's type, and its 
state.
@@ -359,7 +360,7 @@ class VBufStorage_textFieldNode_t : public 
VBufStorage_fieldNode_t {
 
        virtual void generateMarkupTagName(std::wstring& text);
 
-       virtual void getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool useMarkup=false);
+       virtual void getTextInRange(int startOffset, int endOffset, 
std::wstring& text, bool 
useMarkup=false,bool(*filter)(VBufStorage_fieldNode_t*)=NULL);
 
 /**
  * constructor.

diff --git a/readme.txt b/readme.txt
index e667fe3..d5b79d3 100644
--- a/readme.txt
+++ b/readme.txt
@@ -27,18 +27,19 @@ The following dependencies are included in Git submodules:
 * eSpeak, version 1.48.03: http://espeak.sourceforge.net/
 * IAccessible2, version 1.3: 
http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2
 * ConfigObj, version 4.6.0: http://www.voidspace.org.uk/python/configobj.html
-* liblouis, version 2.5.4: http://www.liblouis.org/
+* liblouis, version 2.6.0: http://www.liblouis.org/
 * NVDA images and sounds
 * System dlls not present on many systems: mfc90.dll, msvcp90.dll, 
msvcr90.dll, Microsoft.VC90.CRT.manifest
 * Adobe Acrobat accessibility interface, version XI: 
http://download.macromedia.com/pub/developer/acrobat/AcrobatAccess.zip
 * Adobe FlashAccessibility interface typelib
 * txt2tags, version 2.5: http://txt2tags.sourceforge.net/
-* MinHook, rev e21b54a: https://github.com/RaMMicHaeL/minhook
-* SCons, version 2.3.0: http://www.scons.org/
+* MinHook, tagged version 1.2.2: https://github.com/RaMMicHaeL/minhook
+* SCons, version 2.3.2: http://www.scons.org/
 * brlapi Python bindings, version 0.5.7 or later, distributed with BRLTTY for 
Windows, version 4.2-2: http://brl.thefreecat.org/brltty/
 * ALVA BC6 generic dll, version 3.0.4.1
 * lilli.dll, version 2.1.0.0
 * Handy Tech Braille SDK, version 1.4.2.0: 
ftp://ftp.handytech.de/public/Software/BrailleDriver/HTBrailleSDK_1420a.zip
+* Updated Handy Tech sbsupport.dll and dealers.dat received on 2014-09-09
 * pyserial, version 2.5: http://pypi.python.org/pypi/pyserial
 * HanSoneConnect.dll, version 2.0.0.1
 * SyncBraille.dll, version 1.0.0.1

diff --git a/sconstruct b/sconstruct
index c79a5e0..87d9934 100755
--- a/sconstruct
+++ b/sconstruct
@@ -14,6 +14,7 @@
 
 import sys
 import os
+import time
 import _winreg
 from glob import glob
 
@@ -112,12 +113,35 @@ outFilePrefix = "nvda{type}_{version}".format(type="" if 
release else "_snapshot
 outputDir=Dir(env['outputDir'])
 devDocsOutputDir=outputDir.Dir('devDocs')
 
+# An action to sign an executable with certFile.
+signExecCmd = ["signtool", "sign", "/f", certFile]
+if certPassword:
+       signExecCmd.extend(("/p", certPassword))
+if certTimestampServer:
+       signExecCmd.extend(("/t", certTimestampServer))
+def signExec(target,source,env):
+       print [str(x) for x in target]
+       #sys.exit(1)
+       # #3795: signtool can quite commonly fail with timestamping, so allow 
it to try up to 3 times with a 1 second delay between each try. 
+       res=0
+       for count in xrange(3):
+               res=env.Execute([signExecCmd+[target[0].abspath]])
+               if not res:
+                       return 0 # success
+               time.sleep(1)
+       return res # failed
+#Export via scons environment so other libraries can be signed
+env['signExec']=signExec
+
 #architecture-specific environments
 archTools=['default','windowsSdk','midl','msrpc']
 env32=env.Clone(TARGET_ARCH='x86',tools=archTools)
 env64=env.Clone(TARGET_ARCH='x86_64',tools=archTools)
-env=env32
+# Hack around odd bug where some tool [after] msvc states that static and 
shared objects are different
+env32['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+env64['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
 
+env=env32
 
 #Fill sourceDir with anything provided for it by miscDeps
 env.recursiveCopy(sourceDir,Dir('miscdeps/source'))
@@ -195,8 +219,8 @@ def NVDADistGenerator(target, source, env, for_signature):
        if env.get("uiAccess"):
                buildCmd.append("--enable-uiAccess")
        if certFile:
-               for prog in "nvda_noUIAccess", "nvda_uiAccess", "nvda_slave", 
"nvda_service":
-                       action.append(signExec[:-1] + 
[os.path.join(target[0].path, "%s.exe" % prog)])
+               for prog in "nvda_noUIAccess.exe", "nvda_uiAccess.exe", 
"nvda_slave.exe", "nvda_service.exe":
+                       action.append(lambda target,source,env, progByVal=prog: 
signExec([target[0].File(progByVal)],source,env))
 
        for ext in "", "c", "o":
                action.append(Delete(buildVersionFn + ext))
@@ -247,14 +271,6 @@ def ZipArchiveAction(target, source, env):
 
 env["BUILDERS"]["ZipArchive"] = Builder(action=ZipArchiveAction)
 
-# An action to sign an executable with certFile.
-signExec = ["signtool", "sign", "/f", certFile]
-if certPassword:
-       signExec.extend(("/p", certPassword))
-if certTimestampServer:
-       signExec.extend(("/t", certTimestampServer))
-signExec.append("$TARGET")
-
 uninstFile=File("dist/uninstall.exe")
 uninstGen = env.Command(File("uninstaller/uninstGen.exe"), 
"uninstaller/uninst.nsi",
        [[makensis, "/V2",

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py 
b/source/NVDAObjects/IAccessible/MSHTML.py
index a6bf4ee..a8e6ffb 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -386,7 +386,12 @@ class MSHTML(IAccessible):
                        if nodeName=="SELECT" and 
self.windowStyle&winUser.WS_POPUP:
                                clsList.append(PopupList)
                        elif nodeNamesToNVDARoles.get(nodeName) == 
controlTypes.ROLE_DOCUMENT:
-                               clsList.append(Body)
+                               try:
+                                       
isBodyNode=self.HTMLNodeUniqueNumber==self.HTMLNode.document.body.uniqueNumber
+                               except (COMError,NameError):
+                                       isBodyNode=False
+                               if isBodyNode:
+                                       clsList.append(Body)
                        elif nodeName == "OBJECT":
                                clsList.append(Object)
                        elif nodeName=="FIELDSET":
@@ -879,11 +884,12 @@ class Fieldset(MSHTML):
 class Body(MSHTML):
 
        def _get_parent(self):
-               # The parent of the body accessible is an irrelevant client 
object (description: MSAAHTML Registered Handler).
+               # The parent of the body accessible may be an irrelevant client 
object (description: MSAAHTML Registered Handler).
                # This object isn't returned when requesting OBJID_CLIENT, nor 
is it returned as a child of its parent.
                # Therefore, eliminate it from the ancestry completely.
+               # However it is possible that this body is a child document of 
a parent frame. In this case don't skip it.
                parent = super(Body, self).parent
-               if parent:
+               if parent and not isinstance(parent,MSHTML):
                        return parent.parent
                else:
                        return parent

diff --git a/source/NVDAObjects/IAccessible/__init__.py 
b/source/NVDAObjects/IAccessible/__init__.py
index 7214a75..4826b01 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -511,14 +511,15 @@ the NVDAObject for IAccessible
 
                clsList.append(IAccessible)
 
-
-               if self.event_objectID==winUser.OBJID_CLIENT and 
self.event_childID==0:
+               if self.event_objectID==winUser.OBJID_CLIENT and 
self.event_childID==0 and not 
isinstance(self.IAccessibleObject,IAccessibleHandler.IAccessible2):
                        # This is the main (client) area of the window, so we 
can use other classes at the window level.
+                       # #3872: However, don't do this for IAccessible2 because
+                       # IA2 supersedes window level APIs and might conflict 
with them.
                        super(IAccessible,self).findOverlayClasses(clsList)
                        #Generic client IAccessibles with no children should be 
classed as content and should use displayModel 
                        if clsList[0]==IAccessible and len(clsList)==3 and 
self.IAccessibleRole==oleacc.ROLE_SYSTEM_CLIENT and self.childCount==0:
                                clsList.insert(0,ContentGenericClient)
- 
+
        def 
__init__(self,windowHandle=None,IAccessibleObject=None,IAccessibleChildID=None,event_windowHandle=None,event_objectID=None,event_childID=None):
                """
 @param pacc: a pointer to an IAccessible object

diff --git a/source/NVDAObjects/window/__init__.py 
b/source/NVDAObjects/window/__init__.py
index 1b95c3d..e7afcee 100644
--- a/source/NVDAObjects/window/__init__.py
+++ b/source/NVDAObjects/window/__init__.py
@@ -114,7 +114,7 @@ An NVDAObject for a window
                        from .edit import Edit as newCls
                elif windowClassName=="RichEdit":
                        from .edit import RichEdit as newCls
-               elif windowClassName=="RichEdit20":
+               elif windowClassName in ("RichEdit20","REComboBox20W"):
                        from .edit import RichEdit20 as newCls
                elif windowClassName=="RICHEDIT50W":
                        from .edit import RichEdit50 as newCls

diff --git a/source/NVDAObjects/window/winword.py 
b/source/NVDAObjects/window/winword.py
index 61078f2..c66e7ef 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -477,7 +477,6 @@ class WordDocumentTextInfo(textInfos.TextInfo):
                elif which=="startToEnd":
                        self._rangeObj.Start=other._rangeObj.End
                elif which=="endToStart":
-                       print "start %s, end %s, otherStart %s, otherEnd 
%s"%(self._rangeObj.start,self._rangeObj.end,other._rangeObj.start,other._rangeObj.end)
                        self._rangeObj.End=other._rangeObj.Start
                elif which=="endToEnd":
                        self._rangeObj.End=other._rangeObj.End

diff --git a/source/addonHandler.py b/source/addonHandler.py
index 8f4fc17..0c135a3 100644
--- a/source/addonHandler.py
+++ b/source/addonHandler.py
@@ -155,7 +155,7 @@ def getAvailableAddons(refresh=False):
        return _availableAddons.itervalues()
 
 def installAddonBundle(bundle):
-       """Extracts an Addon bundle in to a unique subdirectory of the user 
addons directory, marking the addon as needing install completion on NVDA 
restart.""" 
+       """Extracts an Addon bundle in to a unique subdirectory of the user 
addons directory, marking the addon as needing install completion on NVDA 
restart."""
        addonPath = os.path.join(globalVars.appArgs.configPath, 
"addons",bundle.manifest['name']+ADDON_PENDINGINSTALL_SUFFIX)
        bundle.extract(addonPath)
        addon=Addon(addonPath)
@@ -391,7 +391,7 @@ def _translatedManifestPaths(lang=None, forBundle=False):
 
 
 class AddonBundle(object):
-       """ Represents the contents of an NVDA addon in a for suitable for 
distribution.
+       """ Represents the contents of an NVDA addon suitable for distribution.
        The bundle is compressed using the zip file format. Manifest information
        is available without the need for extraction."""
        def __init__(self, bundlePath):

diff --git a/source/api.py b/source/api.py
index c829f3b..77eb33e 100644
--- a/source/api.py
+++ b/source/api.py
@@ -218,19 +218,12 @@ def setNavigatorObject(obj,isFocus=False):
        # #3320: If in document review yet there is no document to review the 
mode should be forced to object. 
        if reviewMode=='document' and (not obj.treeInterceptor or not 
obj.treeInterceptor.isReady or obj.treeInterceptor.passThrough):
                review.setCurrentMode('object',False)
-       elif isFocus and reviewMode=='object' and obj.treeInterceptor and 
obj.treeInterceptor.isReady and not obj.treeInterceptor.passThrough:
-               review.setCurrentMode('document',False)
-       #Specifically handle when the navigator object is set due to a focus 
change in a virtualBuffer
-       #The focus change may have been becaus the caret was moved, which 
caused the focus change.
-       #If so, don't clober the review position as it will have been already 
set to a more accurate position.
-       if isFocus and oldPos and oldPos.obj is obj.treeInterceptor and 
isinstance(obj.treeInterceptor,virtualBuffers.VirtualBuffer):
-               try:
-                       objPos=obj.treeInterceptor.makeTextInfo(obj)
-               except LookupError:
-                       objPos=None
-               if objPos and objPos.isOverlapping(oldPos):
-                       globalVars.reviewPosition=oldPos
-                       globalVars.reviewPositionObj=oldPosObj
+       elif obj.treeInterceptor and obj.treeInterceptor.isReady and not 
obj.treeInterceptor.passThrough:
+               if reviewMode=='object':
+                       review.setCurrentMode('document',False)
+               if isFocus:
+                       
globalVars.reviewPosition=obj.treeInterceptor.makeTextInfo(textInfos.POSITION_CARET)
+                       globalVars.reviewPositionObj=globalVars.reviewPosition
        eventHandler.executeEvent("becomeNavigatorObject",obj)
 
 def isTypingProtected():
@@ -341,9 +334,9 @@ def getStatusBarText(obj):
        @return: The status bar text.
        @rtype: str
        """
-       text = obj.name
-       if text is None:
-               text = ""
+       text = obj.name or ""
+       if text:
+               text += " "
        return text + " ".join(chunk for child in obj.children for chunk in 
(child.name, child.value) if chunk and isinstance(chunk, basestring) and not 
chunk.isspace())
 
 def filterFileName(name):

diff --git a/source/appModules/eclipse.py b/source/appModules/eclipse.py
index fb258e7..49d02ff 100644
--- a/source/appModules/eclipse.py
+++ b/source/appModules/eclipse.py
@@ -2,10 +2,20 @@
 #A part of NonVisual Desktop Access (NVDA)
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
-#Copyright (C) 2010 James Teh <jamie@xxxxxxxxxxx>
+#Copyright (C) 2010-2014 NV Access Limited
 
 import controlTypes
 import appModuleHandler
+from NVDAObjects.IAccessible import IAccessible
+
+class EclipseTextArea(IAccessible):
+
+       def event_valueChange(self):
+               # #2314: Eclipse incorrectly fires valueChange when the 
selection changes.
+               # Unfortunately, this causes us to speak the entire selection
+               # instead of just the changed selection.
+               # Therefore, just drop this event.
+               pass
 
 class AppModule(appModuleHandler.AppModule):
 
@@ -14,3 +24,7 @@ class AppModule(appModuleHandler.AppModule):
                        # Eclipse tree views seem to fire a focus event on the 
previously focused item before firing focus on the new item (EclipseBug:315339).
                        # Try to filter this out.
                        obj.shouldAllowIAccessibleFocusEvent = False
+
+       def chooseNVDAObjectOverlayClasses(self, obj, clsList):
+               if obj.windowClassName == "SWT_Window0" and obj.role == 
controlTypes.ROLE_EDITABLETEXT:
+                       clsList.insert(0, EclipseTextArea)

diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
index f0dabc0..09f3e75 100644
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -433,6 +433,8 @@ class UIAGridRow(RowWithFakeNavigation,UIA):
                role=super(UIAGridRow,self).role
                if role==controlTypes.ROLE_TREEVIEW:
                        role=controlTypes.ROLE_TREEVIEWITEM
+               elif role==controlTypes.ROLE_DATAITEM:
+                       role=controlTypes.ROLE_LISTITEM
                return role
 
        def setFocus(self):

diff --git a/source/braille.py b/source/braille.py
index 6971d81..e845eaa 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -309,6 +309,8 @@ def _getDisplayDriver(name):
 
 def getDisplayList():
        displayList = []
+       # The display that should be placed at the end of the list.
+       lastDisplay = None
        for loader, name, isPkg in 
pkgutil.iter_modules(brailleDisplayDrivers.__path__):
                if name.startswith('_'):
                        continue
@@ -320,11 +322,17 @@ def getDisplayList():
                        continue
                try:
                        if display.check():
-                               displayList.append((display.name, 
display.description))
+                               if display.name == "noBraille":
+                                       lastDisplay = (display.name, 
display.description)
+                               else:
+                                       displayList.append((display.name, 
display.description))
                        else:
                                log.debugWarning("Braille display driver %s 
reports as unavailable, excluding" % name)
                except:
                        log.error("", exc_info=True)
+       displayList.sort(key=lambda d : d[1].lower())
+       if lastDisplay:
+               displayList.append(lastDisplay)
        return displayList
 
 class Region(object):

diff --git a/source/cursorManager.py b/source/cursorManager.py
index 492b36c..d4aae44 100644
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -13,6 +13,7 @@ import wx
 import baseObject
 import gui
 import sayAllHandler
+import review
 from scriptHandler import willSayAllResume
 import textInfos
 import api
@@ -343,4 +344,5 @@ class ReviewCursorManager(CursorManager):
 
        def _set_selection(self, info):
                self._selection = info.copy()
+               review.handleCaretMove(info)
                braille.handler.handleCaretMove(self)

diff --git a/source/gui/__init__.py b/source/gui/__init__.py
index 5929f08..fc8271b 100644
--- a/source/gui/__init__.py
+++ b/source/gui/__init__.py
@@ -458,6 +458,7 @@ class SysTrayIcon(wx.TaskBarIcon):
                item = self.menu.Append(wx.ID_EXIT, _("E&xit"),_("Exit NVDA"))
                self.Bind(wx.EVT_MENU, frame.onExitCommand, item)
 
+               self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.onActivate)
                self.Bind(wx.EVT_TASKBAR_RIGHT_DOWN, self.onActivate)
 
        def Destroy(self):

diff --git a/source/installer.py b/source/installer.py
index 47a963d..8f67787 100644
--- a/source/installer.py
+++ b/source/installer.py
@@ -144,6 +144,12 @@ def removeOldProgramFiles(destPath):
                        else:
                                os.remove(fn)
 
+       # #4235: mpr.dll is a Windows system dll accidentally included with
+       # earlier versions of NVDA. Its presence causes problems in Windows 
Vista.
+       fn = os.path.join(destPath, "mpr.dll")
+       if os.path.isfile(fn):
+               tryRemoveFile(fn)
+
 uninstallerRegInfo={
        "DisplayName":versionInfo.name,
        "DisplayVersion":versionInfo.version,

diff --git a/source/setup.py b/source/setup.py
index 752d1cb..b27e129 100755
--- a/source/setup.py
+++ b/source/setup.py
@@ -1,7 +1,7 @@
 # -*- coding: UTF-8 -*-
 #setup.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2013 NV Access Limited, Peter Vágner
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -71,7 +71,7 @@ def isSystemDLL(pathname):
        if dll in ("msvcp71.dll", "msvcp90.dll", "gdiplus.dll","mfc71.dll", 
"mfc90.dll"):
                # These dlls don't exist on many systems, so make sure they're 
included.
                return 0
-       elif dll.startswith("api-ms-win-") or dll == "powrprof.dll":
+       elif dll.startswith("api-ms-win-") or dll in ("powrprof.dll", 
"mpr.dll"):
                # These are definitely system dlls available on all systems and 
must be excluded.
                # Including them can cause serious problems when a binary build 
is run on a different version of Windows.
                return 1

diff --git a/source/speech.py b/source/speech.py
index add2bbb..a201cd4 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -536,7 +536,8 @@ def 
speakSelectionChange(oldInfo,newInfo,speakSelected=True,speakUnselected=True
 
 def speakTypedCharacters(ch):
        global curWordChars;
-       if api.isTypingProtected():
+       typingIsProtected=api.isTypingProtected()
+       if typingIsProtected:
                realChar="*"
        else:
                realChar=ch
@@ -553,7 +554,7 @@ def speakTypedCharacters(ch):
                curWordChars=[]
                if log.isEnabledFor(log.IO):
                        log.io("typed word: %s"%typedWord)
-               if config.conf["keyboard"]["speakTypedWords"]: 
+               if config.conf["keyboard"]["speakTypedWords"] and not 
typingIsProtected:
                        speakText(typedWord)
        if config.conf["keyboard"]["speakTypedCharacters"] and ord(ch)>=32:
                speakSpelling(realChar)

diff --git a/source/synthDriverHandler.py b/source/synthDriverHandler.py
index 7c2ed9d..417c114 100644
--- a/source/synthDriverHandler.py
+++ b/source/synthDriverHandler.py
@@ -39,6 +39,8 @@ def _getSynthDriver(name):
 
 def getSynthList():
        synthList=[]
+       # The synth that should be placed at the end of the list.
+       lastSynth = None
        for loader, name, isPkg in pkgutil.iter_modules(synthDrivers.__path__):
                if name.startswith('_'):
                        continue
@@ -49,11 +51,17 @@ def getSynthList():
                        continue
                try:
                        if synth.check():
-                               synthList.append((synth.name,synth.description))
+                               if synth.name == "silence":
+                                       lastSynth = 
(synth.name,synth.description)
+                               else:
+                                       
synthList.append((synth.name,synth.description))
                        else:
                                log.debugWarning("Synthesizer '%s' doesn't pass 
the check, excluding from list"%name)
                except:
                        log.error("",exc_info=True)
+       synthList.sort(key=lambda s : s[1].lower())
+       if lastSynth:
+               synthList.append(lastSynth)
        return synthList
 
 def getSynth():

diff --git a/source/versionInfo.py b/source/versionInfo.py
index de3b859..428e54a 100644
--- a/source/versionInfo.py
+++ b/source/versionInfo.py
@@ -29,7 +29,7 @@ def _updateVersionFromVCS():
 
 name="NVDA"
 longName=_("NonVisual Desktop Access")
-version="2014.3dev"
+version="2014.4dev"
 publisher="unknown"
 updateVersionType=None
 try:

diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py
index d35ff64..afd6d92 100644
--- a/source/virtualBuffers/MSHTML.py
+++ b/source/virtualBuffers/MSHTML.py
@@ -238,7 +238,7 @@ class MSHTML(VirtualBuffer):
                elif nodeType=="button":
                        
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON]}
                elif nodeType=="edit":
-                       
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
+                       
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT,oleacc.ROLE_SYSTEM_COMBOBOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1],"IHTMLElement::%s"%"isContentEditable":[1]}
                elif nodeType=="radioButton":
                        
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_RADIOBUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
                elif nodeType=="comboBox":

diff --git a/source/virtualBuffers/gecko_ia2.py 
b/source/virtualBuffers/gecko_ia2.py
index 31f8c57..f61007f 100755
--- a/source/virtualBuffers/gecko_ia2.py
+++ b/source/virtualBuffers/gecko_ia2.py
@@ -209,7 +209,7 @@ class Gecko_ia2(VirtualBuffer):
                elif nodeType=="button":
                        
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_BUTTONMENU,IAccessibleHandler.IA2_ROLE_TOGGLE_BUTTON]}
                elif nodeType=="edit":
-                       
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]}
+                       
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT,oleacc.ROLE_SYSTEM_COMBOBOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1]}
                elif nodeType=="frame":
                        
attrs={"IAccessible::role":[IAccessibleHandler.IA2_ROLE_INTERNAL_FRAME]}
                elif nodeType=="separator":

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index d07340e..a677322 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -3,6 +3,32 @@
 
 %!includeconf: ../changes.t2tconf
 
+= 2014.4 =
+
+== Changes ==
+- If an object you have moved to with object navigation is inside a browse 
mode document, but the object you were on previously was not, the review mode 
is automatically set to document. Previously this only happened if the 
navigator object was moved due to the focus changing. (#4369)
+- The Braille display and Synthesizer lists in the respective settings dialogs 
are now alphabetically sorted except for No braille/No speech, which are now at 
the bottom. (#2724)
+- Updated liblouis braille translator to 2.6.0. (#4434, #3835)
+- In browse mode, pressing e and shift+e to navigate to edit fields now 
includes editable combo boxes. This includes the search box in the latest 
versionn of Google Search. (#4436)
+- Clicking the NVDA icon in the Notification Area with the left mouse button 
now opens the NVDA menu instead of doing nothing. (#4459)
+
+
+== Bug Fixes ==
+- When moving focus back to a browse mode document (e.g. alt tabbing to an 
already opened web page) the review cursor is properly positioned at the 
virtual caret, rather than the focused control (e.g. a near by link). (#4369)
+- In Powerpoint slide shows, the review cursor correctly follows the virtual 
caret. (#4370)
+- In Mozilla Firefox and other Gecko-based browsers, new content within a live 
region will be announced even if the new content has a usable ARIA live type 
different to the parent live region. E.g. Content marked as assertive is added 
to a live region marked as polite. (#4169).
+- In Internet Explorer and other MSHTML controls, some cases where a document 
is contained within another document no longer prevent the user from accessing 
some of the content (specifically, framesets inside framesets). (#4418)
+- NVDA no longer crashes when attempting to use a Handy Tech braille display 
in some cases. (#3709)
+- In Windows Vista, a spurious "Entry Point Not Found" dialog is no longer 
displayed in several cases such as when starting NVDA from the Desktop shortcut 
or via the shortcut key. (#4235)
+- Serious problems with editable text controls in dialogs in recent versions 
of Eclipse have been fixed. (#3872)
+- In Outlook 2010, moving the caret now works as expected in the location 
field of appointments and meeting requests. (#4126)
+- Inside a live region, content which is marked as not being live (e.g. 
aria-live="off") is now correctly ignored. (#4405)
+- When reporting the text of a status bar that has a name, the name is now 
correctly separated from the first word of the status bar text. (#4430)
+- In password entry fields with speaking of typed words enabled, multiple 
asterisks are no longer pointlessly reported when beginning new words. (#4402)
+- In the Microsoft Outlook message list, items are no longer pointlessly 
announced as Data Items. (#4439)
+- When selecting text in the code editing control in the Eclipse IDE, the 
entire selection is no longer announced every time the selection changes. 
(#2314)
+
+
 = 2014.3 =
 
 == New Features ==

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 77966c9..0560398 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -84,7 +84,7 @@ Running the portable version directly from read-only media is 
not supported at t
 Using the temporary copy of NVDA is also an option (e.g. for demonstration 
purposes), though  starting NVDA in this way each time can become very time 
consuming.
 
 ++ Portable and Temporary Copy Restrictions ++
-Apart from the  inability to automatically start during and or after log-on, 
the portable and temporary copies of NVDA also have the following restrictions:
+Apart from the  inability to automatically start during and/or after log-on, 
the portable and temporary copies of NVDA also have the following restrictions:
 - The inability to interact with applications running with administrative 
privileges, unless of course NVDA itself has been run also with these 
privileges (not recommended).
 - The inability to read User Account Control (UAC) screens when trying to 
start an application with administrative privileges.
 - Windows 8: the inability to support input from a touch screen.
@@ -107,7 +107,7 @@ This also includes UAC control and other secure screens.
 
 +++ Create Desktop Shortcut (ctrl+alt+n) +++
 This option allows you to choose whether or not NVDA should create a shortcut 
on the desktop to start NVDA. 
-This shortcut if created will also be assigned a  shortcut key of 
control+alt+n allowing you to start NVDA at any time with this key stroke.
+If created, this shortcut will also be assigned a  shortcut key of 
control+alt+n, allowing you to start NVDA at any time with this key stroke.
 
 +++ Copy Portable Configuration to Current User Account +++
 This option allows you to choose whether or not NVDA should copy the user 
configuration from the currently running NVDA into the configuration for the 
currently logged on  user, for the installed copy of NVDA. 
@@ -152,22 +152,20 @@ The third lets you control if this Welcome dialog should 
appear each time NVDA s
 
 +++ The NVDA Modifier Key +++
 Most NVDA-specific keyboard commands consist of pressing a particular key 
called the NVDA modifier key in conjunction with one or more other keys.
-Notable exceptions to this are the text review commands for desktop keyboards 
which just use the numpad keys by themselves, but there are some other 
exceptions as well.
-
-NVDA can be configured so that either the numpad Insert, Extended Insert, or 
capslock key can be used as the NVDA modifier key.
+Notable exceptions to this are the text review commands for the desktop 
keyboard layout which just use the numpad keys by themselves, but there are 
some other exceptions as well.
 
+NVDA can be configured so that the numpad Insert, Extended Insert and/or 
capslock key can be used as the NVDA modifier key.
 By default, both the numpad Insert and Extended Insert keys are set as NVDA 
modifier keys.
 
-If you wish to cause one of the NVDA modifier keys to act like its original 
key (for instance you wish to turn capslock on when you have set capslock to be 
an NVDA modifier key) you can press the key twice in quick succession.
+If you wish to cause one of the NVDA modifier keys to behave as it usually 
would if NVDA were not running (e.g. you wish to turn capslock on when you have 
set capslock to be an NVDA modifier key), you can press the key twice in quick 
succession.
 
 +++ Keyboard Layouts +++
-NVDA currently comes with two sets of key commands.
-There is a layout for Desktops and a layout for Laptops.
-NVDA by default is set to use the Desktop layout, though you can switch to the 
Laptop layout in the Keyboard Settings, found under Preferences in the NVDA 
menu.
+NVDA currently comes with two sets of key commands (known as keyboard 
layouts): the desktop layout and the laptop layout.
+By default, NVDA  is set to use the Desktop layout, though you can switch to 
the Laptop layout in the Keyboard Settings, found under Preferences in the NVDA 
menu.
 
-The Desktop layout makes heavy use of the numberpad (with numlock off).
-Although most laptops do not have a physical numberpad, some laptops can 
emulate one by holding down the FN key and pressing letters and numbers on the 
right-hand side of the keyboard (7 8 9 u i o j k l etc).
-If your laptop can not do this, or does not allow you to turn numlock off, you 
may want to switch to the Laptop layout instead.
+The Desktop layout makes heavy use of the numpad (with numlock off).
+Although most laptops do not have a physical numpad, some laptops can emulate 
one by holding down the FN key and pressing letters and numbers on the 
right-hand side of the keyboard (7, 8, 9, u, i, o, j, k, l, etc.).
+If your laptop cannot do this or does not allow you to turn numlock off, you 
may want to switch to the Laptop layout instead.
 
 ++ NVDA Touch Gestures ++
 If you are running NVDA on a device with a touch screen and running Windows 8 
or higher, you can also control NVDA directly via the touch screen.
@@ -234,7 +232,7 @@ When the menu comes up, You can use the arrow keys to 
navigate the menu, and the
 || Name | Desktop key | Laptop key | Touch | Description |
 | Stop speech | Control | control | 2-finger tap | Instantly stops speaking |
 | Pause Speech | shift | shift | none | Instantly pauses speech. Pressing it 
again will continue speaking where it left off (if pausing is supported by the 
current synthesizer) |
-| NVDA Menu | NVDA+n | NVDA+n | 2-finger double tap | Pops up the NVDA menu to 
allow you to access preferences, tools and help etc |
+| NVDA Menu | NVDA+n | NVDA+n | 2-finger double tap | Pops up the NVDA menu to 
allow you to access preferences, tools, help, etc. |
 | Toggle Speech Mode | NVDA+s | NVDA+s | none | Toggles speech mode between 
speech, beeps and off. |
 | Toggle Input Help Mode | NVDA+1 | NVDA+1 | none | Pressing any key in this 
mode will report the key, and the description of any NVDA command associated 
with it |
 | Quit NVDA | NVDA+q | NVDA+q | none | Exits NVDA |
@@ -669,12 +667,13 @@ This option is a slider which goes from 0 to 100, (0 
being the lowest volume and
 This option is a slider that lets you choose how much inflection (rise and 
fall in pitch) the synthesizer should use to speak with. (The only synthesizer 
that provides this option at the present time is eSpeak).
 
 ==== Automatic Language switching ====
-This checkbox allows you to toggle whether or not NVDA should switch speech 
synthesizer languages on the fly, if language markup is available in the text 
being read.
+This checkbox allows you to toggle whether NVDA should switch speech 
synthesizer languages automatically if the text being read specifies its 
language.
 This option is enabled by default.
 Currently only the eSpeak synthesizer supports automatic language switching.
 
 ==== Automatic Dialect switching ====
-If automatic language switching is turned on, this checkbox allows you to 
toggle whether or not dialect changes should be made, rather than just actual 
language changes. E.g. If reading in an English U.S. voice but a document 
states some text is in English U.K. then if this feature is enabled the 
synthesizer will switch accents.
+This checkbox allows you to toggle whether or not dialect changes should be 
made, rather than just actual language changes.
+For example, if reading in an English U.S. voice but a document specifies that 
some text is in English U.K., then the synthesizer will switch accents if this 
option is enabled.
 This option is disabled by default.
 
 %kc:setting
@@ -880,7 +879,7 @@ Key: NVDA+6
 
 When enabled, the review cursor will automatically be moved to the position of 
the System caret each time it moves.
 
-==== Follow mouse ====
+==== Follow mouse cursor ====
 When enabled, the review cursor will follow the mouse as it moves.
 
 ==== Simple Review mode ====
@@ -1718,8 +1717,8 @@ These are (ordered from left to right):
 Currently, the right thumb key is not in use.
 The inner keys are both mapped to space.
 
-%kc:beginInclude
 || Name | Key |
+%kc:beginInclude
 | backspace key | dot 7 |
 | enter key | dot 8 |
 | escape key | space with dot 7 |
@@ -1882,6 +1881,43 @@ Please see the [BRLTTY key tables documentation 
http://mielke.cc/brltty/doc/driv
 | Route to braille cell | route (bring cursor to character) |
 %kc:endInclude
 
++ Braille control type and state abbreviations +
+In order to fit as much information as possible on a braille display, The 
folowing abbreviations have been defined to indicate control type and state.
+
+|| Abbreviation | Control type |
+| btn | button |
+| cbo | combo box |
+| chk | check box |
+| dlg | dialog |
+| edt | editable text field |
+| gra | graphic |
+| cN | table column number n, e.g. c1, c2. |
+| rN | table row number n, e.g. r1, r2. |
+| hN | heading at level n, e.g. h1, h2. |
+| lnk | link |
+| lst | list |
+| vlnk | visited link |
+| mnu | menu |
+| mnubar | menu bar |
+| rbtn | radio button |
+| tb | table |
+| tv | treeview |
+| lv N | a tree view item has a hierarchical level N|
+| ``-----`` | seperator |
+
+The following state indicators are also defined:
+|| Abbreviation | Control state |
+| ... | displayed when an object supports autocompletion |
+| ( ) | displayed when an object (e.g. a check box) is not checked |
+| (x) | displayed when an object (e.g. a check box) is checked |
+| (-) | displayed when an object (e.g. a check box) is half checked |
+| - | displayed when an object (e.g. a tree view item) is collapsible |
+| + | displayed when an object (e.g. a tree view item) is Expandable |
+| clk | displayed when an object is clickable |
+| ro | displayed when an object (e.g. an editable text field) is read-only |
+| sel | displayed when an object is selected |
+| submnu | displayed when an object has a popup (usually a sub-menu) |
+
 + Advanced Topics +
 
 ++ Advanced Customization of Symbol Pronunciation ++

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.

----------------------------------------------------------------

NVDA add-ons Central: A list for discussing NVDA add-ons

To post a message, send an email to nvda-addons@xxxxxxxxxxxxx.

To unsubscribe, send an email with the subject line of "unsubscribe" (without 
quotes) to nvda-addons-request@xxxxxxxxxxxxx.

If you have questions for list moderators, please send a message to 
nvda-addons-moderators@xxxxxxxxxxxxx.

Community addons can be found here: http://addons.nvda-project.org

Other related posts: