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

  • From: Noelia <nrm1977@xxxxxxxxx>
  • To: nvda-addons@xxxxxxxxxxxxx
  • Date: Mon, 27 Oct 2014 07:07:01 +0100

Hi, thanks Joseph.
I am not a NVDA commiter, that is, I can't modify the repo maintainer by NVAccess. However, I'm a member of NVDA add-on team, and can write to the NVDA repo forked at
https://bitbucket.org/nvdaaddonteam/nvda
I feel that your ticket (4354) is very interesting, and I recently started reading a book: Story of mathematics, writen by Boyer. I know that I will find symbols there (it's digitalized in Word), and I wanted to experiment with a branch for this ticket. So, if I can continue, the commits will be send to add-ons commits list, and the answers, to the add-on list.
Thanks.


El 27/10/2014 6:53, Bhavya shah escribió:
Hmm.
Interesting, I understood, thanks for the clarification.

On 10/27/14, Joseph Lee <joseph.lee22590@xxxxxxxxx> wrote:
Hi,
Here's the story:
As you pointed out, the below message would have been good for development
list. However, I sent the below notice here, seeing that Noelia forked this
branch from an older version of the master branch. You see, NV Access isn't
the only one which hosts complete NVDA repository - there exists another
repository at Bitbucket under the add-ons team account which mirrors the NV
Access repository and is meant for developers with Bitbucket account to
experiment with new features, like what Noelia is doing with ticket 4354.
Besides this branch, we have other branches at the Bitbucket repo, and NV
Access and other developers maintain NVDA repos at Bitbucket (I have one at
Bitbucket which has additional branches such as post Windows XP builds and
a
branch with missing translator comments added).
Unlike the NV Access repo, the Bitbucket NVDA add-ons team repo is updated
on a semi-regular basis. Until a few weeks ago, when Mesar integrated
various localizations into NVDA snapshots, he updated Bitbucket repo as
well
(he hasn't done that for a while). Thus after noticing that Noelia was
using
an older code, I updated the NVDA add-ons team repo to reflect latest
changes from NV Access repo so Noelia can have a more recent code from
which
she can work on her branch (this affects my post Windows XP builds as well,
as it was sort of forked from the add-ons team repo), hence the notice came
to this list.
Hope this helps (I hope I didn't confuse you; I'll answer other repo
questions after the Tek Talk event).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons-bounce@xxxxxxxxxxxxx
[mailto:nvda-addons-bounce@xxxxxxxxxxxxx] On Behalf Of Bhavya shah
Sent: Sunday, October 26, 2014 10:34 PM
To: nvda-addons@xxxxxxxxxxxxx
Subject: [nvda-addons] Re: commit/nvda: josephsl: Merge branch 'master'
into
t4354

Hi,
I am the original creator of the ticket, and have been following it.
So, was this e-mail sent to the NVDA Addons list by mistake, I think
it should have been sent to NVDA Devel.
Or is #4354 being implemented as an addon and will not be implementd
in NVDA itself?
Am I missing anything?

On 10/27/14, Joseph Lee <joseph.lee22590@xxxxxxxxx> wrote:
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','${n
vdaHelperLogLevel}'),('_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/lotusNotesRichTex
t/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_IAcc
essible2,(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.compa
re(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-c
hildStart,childLength),text,useMarkup);
+
child->getTextInRange(max(startOffset,childStart)-childStart,min(endOffset-c
hildStart,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/iaccessi
ble2
  * 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.uniqueNumb
er
+                               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=No
ne,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._ra
ngeObj.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.POSITIO
N_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_SY
STEM_FOCUSABLE:[1]}
+
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT,oleacc.ROLE_SYSTEM_COMBO
BOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessibl
e::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1],"IHTMLElement::%s"%"isContent
Editable":[1]}
                elif nodeType=="radioButton":

attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_RADIOBUTTON],"IAccessible::st
ate_%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_COMBO
BOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessibl
e2::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

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

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

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

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

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

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

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

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: