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

  • From: Bhavya shah <bhavya.shah125@xxxxxxxxx>
  • To: nvda-addons@xxxxxxxxxxxxx
  • Date: Mon, 27 Oct 2014 11:23:57 +0530

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

Other related posts: