commit/nvda: 157 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Sat, 21 Nov 2015 17:04:50 -0000

157 new commits in nvda:

https://bitbucket.org/nvdaaddonteam/nvda/commits/912feb59a048/
Changeset: 912feb59a048
Branch: None
User: jteh
Date: 2014-09-30 06:42:37+00:00
Summary: Rename "equation" to "math".

Equation isn't accurate in many cases because math content doesn't have to
assert equality.
ROLE_EQUATION was renamed to ROLE_MATH. ROLE_EQUATION still exists for
backwards compatibility, but is now deprecated.

Affected #: 2 files

diff --git a/source/IAccessibleHandler.py b/source/IAccessibleHandler.py
index 08fcf10..a5ce5c2 100644
--- a/source/IAccessibleHandler.py
+++ b/source/IAccessibleHandler.py
@@ -196,7 +196,7 @@ IAccessibleRolesToNVDARoles={
oleacc.ROLE_SYSTEM_DIAL:controlTypes.ROLE_DIAL,
oleacc.ROLE_SYSTEM_DROPLIST:controlTypes.ROLE_DROPLIST,
oleacc.ROLE_SYSTEM_BUTTONMENU:controlTypes.ROLE_MENUBUTTON,
- oleacc.ROLE_SYSTEM_EQUATION:controlTypes.ROLE_EQUATION,
+ oleacc.ROLE_SYSTEM_EQUATION:controlTypes.ROLE_MATH,
oleacc.ROLE_SYSTEM_GRIP:controlTypes.ROLE_GRIP,
oleacc.ROLE_SYSTEM_HOTKEYFIELD:controlTypes.ROLE_HOTKEYFIELD,
oleacc.ROLE_SYSTEM_INDICATOR:controlTypes.ROLE_INDICATOR,

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 445f292..0e4788e 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -2,7 +2,7 @@
#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) 2007-2012 NV Access Limited
+#Copyright (C) 2007-2014 NV Access Limited

ROLE_UNKNOWN=0
ROLE_WINDOW=1
@@ -106,7 +106,8 @@ ROLE_DROPLIST=100
ROLE_SPLITBUTTON=101
ROLE_MENUBUTTON=102
ROLE_DROPDOWNBUTTONGRID=103
-ROLE_EQUATION=104
+ROLE_MATH=104
+ROLE_EQUATION=ROLE_MATH # Deprecated; for backwards compatibility.
ROLE_GRIP=105
ROLE_HOTKEYFIELD=106
ROLE_INDICATOR=107
@@ -400,8 +401,8 @@ roleLabels={
ROLE_MENUBUTTON:_("menu button"),
# Translators: Reported for a button which expands a grid when it is
pressed.
ROLE_DROPDOWNBUTTONGRID:_("drop down button grid"),
- # Translators: Identifies an equation.
- ROLE_EQUATION:_("equation"),
+ # Translators: Identifies mathematical content.
+ ROLE_MATH:_("math"),
# Translators: Identifies a grip control.
ROLE_GRIP:_("grip"),
# Translators: Identifies a hot key field (a field where one can enter
a hot key for something, such as assigning shortcut for icons on the desktop).


https://bitbucket.org/nvdaaddonteam/nvda/commits/818f797a7ce7/
Changeset: 818f797a7ce7
Branch: None
User: jteh
Date: 2014-09-30 06:42:51+00:00
Summary: Add skeleton framework for suppoting math presentation: the
mathPres package.

Three types of presentation are supported: speech, braille and interaction. The
framework allows plugins to provide their own implementations for any number of
these, though it is hoped that there will be bundled implementations.

Affected #: 1 file

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
new file mode 100644
index 0000000..a709700
--- /dev/null
+++ b/source/mathPres/__init__.py
@@ -0,0 +1,67 @@
+#mathPres/__init__.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2014 NV Access Limited
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+"""Framework for presentation of math.
+Three types of presentation are supported: speech, braille and interaction.
+All of these accept MathML markup.
+Plugins can register their own implementation for any or all of these
+using L{registerProvider}.
+"""
+
+class MathPresentationProvider(object):
+ """Implements presentation of math content.
+ A single provider does not need to implement all presentation types.
+ """
+
+ def getSpeechForMathMl(self, mathMl):
+ """Get speech output for specified MathML markup.
+ @param mathMl: The MathML markup.
+ @type mathMl: basestring
+ @return: A speech sequence.
+ @rtype: list of unicode and/or L{speech.SpeechCommand}
+ """
+ raise NotImplementedError
+
+ def getBrailleForMathMl(self, mathMl):
+ """Get braille output for specified MathML markup.
+ @param mathMl: The MathML markup.
+ @type mathMl: basestring
+ @return: A string of Unicode braille.
+ @rtype: unicode
+ """
+ raise NotImplementedError
+
+ def interactWithMathMl(self, mathMl):
+ """Begin interaction with specified MathML markup.
+ @param mathMl: The MathML markup.
+ """
+ raise NotImplementedError
+
+speechProvider = None
+brailleProvider = None
+interactionProvider = None
+
+def registerProvider(provider, speech=False, braille=False, interaction=False):
+ """Register a math presentation provider.
+ @param provider: The provider to register.
+ @type provider: L{MathPresentationProvider}
+ @param speech: Whether this provider supports speech output.
+ @type speech: bool
+ @param braille: Whether this provider supports braille output.
+ @type braille: bool
+ @param interaction: Whether this provider supports interaction.
+ @type interaction: bool
+ """
+ global speechProvider, brailleProvider, presentationProvider
+ if speech:
+ speechProvider = provider
+ if braille:
+ brailleProvider = provider
+ if interaction:
+ interactionProvider = provider
+
+def ensureInit():
+ pass


https://bitbucket.org/nvdaaddonteam/nvda/commits/3f1a622cb261/
Changeset: 3f1a622cb261
Branch: None
User: jteh
Date: 2014-09-30 06:43:01+00:00
Summary: Add mathMl property to NVDAObject and getMathMl method to TextInfo
to facilitate retrieval of MathML markup.

Affected #: 2 files

diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
index 6abe5b3..d61706a 100644
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -1,6 +1,7 @@
+# -*- coding: UTF-8 -*-
#NVDAObjects/__init__.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-20012 NVDA Contributors
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
Patrick Zajda
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -1040,3 +1041,11 @@ This code is executed if a gain focus event is received
by this object.
# Don't cache sleepMode, as it is derived from a property which might
change
# and we want the changed value immediately.
_cache_sleepMode = False
+
+ def _get_mathMl(self):
+ """Obtain the MathML markup for an object containing math
content.
+ This will only be called (and thus only needs to be
implemented) for
+ objects with a role of L{controlTypes.ROLE_MATH}.
+ @raise LookupError: If MathML can't be retrieved for this
object.
+ """
+ raise NotImplementedError

diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py
index 35f894c..550dc83 100755
--- a/source/textInfos/__init__.py
+++ b/source/textInfos/__init__.py
@@ -2,7 +2,7 @@
#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) 2006-2012 NV Access Limited
+#Copyright (C) 2006-2014 NV Access Limited

"""Framework for accessing text content in widgets.
The core component of this framework is the L{TextInfo} class.
@@ -451,6 +451,13 @@ class TextInfo(baseObject.AutoPropertyObject):
winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP,0,0,None,None)
winUser.setCursorPos(oldX,oldY)

+ def getMathMl(self, field):
+ """Get MathML for a math control field.
+ This will only be called for control fields with a role of
L{controlTypes.ROLE_MATH}.
+ @raise LookupError: If MathML can't be retrieved for this field.
+ """
+ raise NotImplementedError
+
RE_EOL = re.compile("\r\n|[\n\r]")
def convertToCrlf(text):
"""Convert a string so that it contains only CRLF line endings.


https://bitbucket.org/nvdaaddonteam/nvda/commits/e2efe5a08073/
Changeset: e2efe5a08073
Branch: None
User: jteh
Date: 2014-09-30 06:43:14+00:00
Summary: Add VirtualBufferTextInfo.getMathMl which just asks the relevant
NVDAObject.

Affected #: 1 file

diff --git a/source/virtualBuffers/__init__.py
b/source/virtualBuffers/__init__.py
index 860422a..7bd9b28 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -3,7 +3,7 @@
#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) 2007-2012 NV Access Limited, Peter Vágner
+#Copyright (C) 2007-2014 NV Access Limited, Peter Vágner

import time
import threading
@@ -323,6 +323,12 @@ class
VirtualBufferTextInfo(textInfos.offsets.OffsetsTextInfo):
def activate(self):
self.obj._activatePosition(self)

+ def getMathMl(self, field):
+ docHandle = int(field["controlIdentifier_docHandle"])
+ nodeId = int(field["controlIdentifier_ID"])
+ obj = self.obj.getNVDAObjectFromIdentifier(docHandle, nodeId)
+ return obj.mathMl
+
class ElementsListDialog(wx.Dialog):
ELEMENT_TYPES = (
# Translators: The label of a radio button to select the type
of element


https://bitbucket.org/nvdaaddonteam/nvda/commits/07a0292c49e7/
Changeset: 07a0292c49e7
Branch: None
User: jteh
Date: 2014-09-30 07:06:22+00:00
Summary: Speak math encountered when reading text.

Affected #: 2 files

diff --git a/source/speech.py b/source/speech.py
index add2bbb..1a4d90d 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -3,7 +3,7 @@
#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) 2006-2012 NV Access Limited, Peter Vágner, Aleksey Sadovoy
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy

"""High-level functions to speak information.
"""
@@ -587,6 +587,16 @@ class SpeakTextInfoState(object):
def copy(self):
return self.__class__(self)

+def _speakTextInfo_addMath(speechSequence, info, field):
+ import mathPres
+ mathPres.ensureInit()
+ if not mathPres.speechProvider:
+ return
+ try:
+
speechSequence.extend(mathPres.speechProvider.getSpeechForMathMl(info.getMathMl(field)))
+ except (NotImplementedError, LookupError):
+ return
+
def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlTypes.REASON_QUERY,index=None,onlyInitialFields=False,suppressBlanks=False):
if isinstance(useCache,SpeakTextInfoState):
speakTextInfoState=useCache
@@ -682,17 +692,23 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
#Get speech text for any fields that are in both controlFieldStacks, if
extra detail is not requested
if not extraDetail:
for count in xrange(commonFieldCount):
-
text=info.getControlFieldSpeech(newControlFieldStack[count],newControlFieldStack[0:count],"start_inControlFieldStack",formatConfig,extraDetail,reason=reason)
+ field=newControlFieldStack[count]
+
text=info.getControlFieldSpeech(field,newControlFieldStack[0:count],"start_inControlFieldStack",formatConfig,extraDetail,reason=reason)
if text:
speechSequence.append(text)
isTextBlank=False
+ if field.get("role")==controlTypes.ROLE_MATH:
+
_speakTextInfo_addMath(speechSequence,info,field)

#Get speech text for any fields in the new controlFieldStack that are
not in the old controlFieldStack
for count in xrange(commonFieldCount,len(newControlFieldStack)):
-
text=info.getControlFieldSpeech(newControlFieldStack[count],newControlFieldStack[0:count],"start_addedToControlFieldStack",formatConfig,extraDetail,reason=reason)
+ field=newControlFieldStack[count]
+
text=info.getControlFieldSpeech(field,newControlFieldStack[0:count],"start_addedToControlFieldStack",formatConfig,extraDetail,reason=reason)
if text:
speechSequence.append(text)
isTextBlank=False
+ if field.get("role")==controlTypes.ROLE_MATH:
+
_speakTextInfo_addMath(speechSequence,info,field)
commonFieldCount+=1

#Fetch the text for format field attributes that have changed between
what was previously cached, and this textInfo's initialFormatField.
@@ -769,6 +785,8 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT

relativeSpeechSequence.append(LangChangeCommand(None))
lastLanguage=None
relativeSpeechSequence.append(fieldText)
+ if command.command=="controlStart" and
command.field.get("role")==controlTypes.ROLE_MATH:
+
_speakTextInfo_addMath(relativeSpeechSequence,info,command.field)
if autoLanguageSwitching and
newLanguage!=lastLanguage:

relativeSpeechSequence.append(LangChangeCommand(newLanguage))
lastLanguage=newLanguage

diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py
index 550dc83..99ff8d4 100755
--- a/source/textInfos/__init__.py
+++ b/source/textInfos/__init__.py
@@ -71,7 +71,7 @@ class ControlField(Field):
return self.PRESCAT_LAYOUT

if (
- role in (controlTypes.ROLE_LINK,
controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON,
controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX,
controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB,
controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER,
controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX,
controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON,
controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW,
controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM)
+ role in (controlTypes.ROLE_LINK,
controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON,
controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX,
controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB,
controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER,
controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX,
controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON,
controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW,
controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM,
controlTypes.ROLE_MATH)
or (role == controlTypes.ROLE_EDITABLETEXT and
controlTypes.STATE_MULTILINE not in states and (controlTypes.STATE_READONLY not
in states or controlTypes.STATE_FOCUSABLE in states))
or (role == controlTypes.ROLE_LIST and
controlTypes.STATE_READONLY not in states)
):


https://bitbucket.org/nvdaaddonteam/nvda/commits/62588472995e/
Changeset: 62588472995e
Branch: None
User: jteh
Date: 2014-09-30 07:06:31+00:00
Summary: Support retrieval of MathML from MSHTML.

Affected #: 2 files

diff --git a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
index 07c2dd2..a04d1fd 100755
--- a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
@@ -1092,6 +1092,7 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf
contentString=L"\n";
} else if (nodeName.compare(L"MATH")==0) {
contentString=IAName;
+ isInteractive=true;
} else
if((!isRoot&&(IARole==ROLE_SYSTEM_APPLICATION||IARole==ROLE_SYSTEM_DIALOG))||IARole==ROLE_SYSTEM_OUTLINE)
{
contentString=L" ";
} else {

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index a8e6ffb..27d59da 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -1,6 +1,6 @@
#NVDAObjects/MSHTML.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NV Access Limited, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -81,6 +81,7 @@ nodeNamesToNVDARoles={
"FIELDSET":controlTypes.ROLE_GROUPING,
"OPTION":controlTypes.ROLE_LISTITEM,
"BLOCKQUOTE":controlTypes.ROLE_BLOCKQUOTE,
+ "MATH":controlTypes.ROLE_MATH,
}

def IAccessibleFromHTMLNode(HTMLNode):
@@ -396,6 +397,8 @@ class MSHTML(IAccessible):
clsList.append(Object)
elif nodeName=="FIELDSET":
clsList.append(Fieldset)
+ elif nodeName=="MATH":
+ clsList.append(Math)
clsList.append(MSHTML)
if not self.HTMLNodeHasAncestorIAccessible:
# The IAccessibleObject is for this node (not an
ancestor), so IAccessible overlay classes are relevant.
@@ -946,6 +949,12 @@ class RootClient(IAccessible):
class MSAATextLeaf(IAccessible):
role=controlTypes.ROLE_STATICTEXT

+class Math(MSHTML):
+ role = controlTypes.ROLE_MATH
+
+ def _get_mathMl(self):
+ return self.HTMLNode.outerHTML
+
def findExtraIAccessibleOverlayClasses(obj, clsList):
"""Determine the most appropriate class for MSHTML objects.
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses}
except that it never calls any other findOverlayClasses method.


https://bitbucket.org/nvdaaddonteam/nvda/commits/38e997a18f6e/
Changeset: 38e997a18f6e
Branch: None
User: mdcurran
Date: 2014-09-30 07:06:32+00:00
Summary: Compile ISimpleDOM tlb from idl files now added to miscDeps

Affected #: 3 files

diff --git a/miscDeps b/miscDeps
index 9683425..9423478 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit 9683425894cdb825e543ec4008413ab6c90922c7
+Subproject commit 9423478981342b887437a6af8720d6d7e9a64602

diff --git a/nvdaHelper/ISimpleDOM_sconscript b/nvdaHelper/ISimpleDOM_sconscript
new file mode 100644
index 0000000..40a2fc9
--- /dev/null
+++ b/nvdaHelper/ISimpleDOM_sconscript
@@ -0,0 +1,28 @@
+###
+#This file is a part of the NVDA project.
+#URL: http://www.nvda-project.org/
+#Copyright 2006-2010 NVDA contributers.
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License version 2.0, as
published by
+#the Free Software Foundation.
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#This license can be found at:
+#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+###
+
+Import('env')
+
+env['MIDLCOM']=env['MIDLCOM'][:-6]
+
+env.Command("ISimpleDOMText.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMText.idl",Copy("$TARGET","$SOURCE"))
+env.Command("ISimpleDOMDocument.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMDocument.idl",Copy("$TARGET","$SOURCE"))
+idlFile=env.Command("ISimpleDOMNode.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMNode.idl",Copy("$TARGET","$SOURCE"))
+
+tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
+ source=idlFile,
+ MIDLFLAGS=['/c_ext','/I',Dir('.')],
+)
+
+Return(['tlbFile','headerFile','iidSourceFile','proxySourceFile','dlldataSourceFile'])

diff --git a/nvdaHelper/archBuild_sconscript b/nvdaHelper/archBuild_sconscript
index fd45e07..624889c 100644
--- a/nvdaHelper/archBuild_sconscript
+++ b/nvdaHelper/archBuild_sconscript
@@ -73,6 +73,10 @@ env.Install(libInstallDir,ia2RPCStubs[0]) #proxy dll
if TARGET_ARCH=='x86':
env.Install(sourceTypelibDir,ia2RPCStubs[1]) #typelib

+iSimpleDomRPCStubs=env.SConscript('ISimpleDOM_sconscript')
+if TARGET_ARCH=='x86':
+ env.Install(sourceTypelibDir,iSimpleDomRPCStubs[0]) #typelib
+
if TARGET_ARCH=='x86':
localLib=env.SConscript('local/sconscript')
Export('localLib')

diff --git a/source/comInterfaces_sconscript b/source/comInterfaces_sconscript
index 1204606..6588e23 100755
--- a/source/comInterfaces_sconscript
+++ b/source/comInterfaces_sconscript
@@ -38,6 +38,7 @@
sys.modules['comtypes.gen']=comtypes.gen=__import__("comInterfaces",globals(),lo
COM_INTERFACES = {
"UIAutomationClient.py": ('{944de083-8fb8-45cf-bcb7-c477acb2f897}',1,0),
"IAccessible2Lib.py": "typelibs/ia2.tlb",
+ "ISimpleDOM.py": "typelibs/ISimpleDOMNode.tlb",
#"Accessibility.py": ('{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}',1,0),
"tom.py": ('{8CC497C9-A1DF-11CE-8098-00AA0047BE5D}',1,0),
"SpeechLib.py": ('{C866CA3A-32F7-11D2-9602-00C04F8EE628}',5,0),


https://bitbucket.org/nvdaaddonteam/nvda/commits/a40402d9d668/
Changeset: a40402d9d668
Branch: None
User: jteh
Date: 2014-09-30 07:06:32+00:00
Summary: Support retrieval of MathML from Gecko.

This includes support for MathML exposed via a data-mathml attribute on a node
with an ARIA role of math. Though non-standard, this makes it possible for
MathJax and perhaps other math rendering to be accessible with appropriate
changes.

Affected #: 2 files

diff --git a/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
b/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
index fdf2f70..c42c134 100755
--- a/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
+++ b/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
@@ -486,7 +486,7 @@ VBufStorage_fieldNode_t*
GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
// Whether this node is interactive.
// Certain objects are never interactive, even if other checks are true.
bool isNeverInteractive = parentNode->isHidden||(!isEditable && (isRoot
|| role == ROLE_SYSTEM_DOCUMENT || role == IA2_ROLE_INTERNAL_FRAME));
- bool isInteractive = !isNeverInteractive && (isEditable || inLink ||
states & STATE_SYSTEM_FOCUSABLE || states & STATE_SYSTEM_UNAVAILABLE ||
isEmbeddedApp);
+ bool isInteractive = !isNeverInteractive && (isEditable || inLink ||
states & STATE_SYSTEM_FOCUSABLE || states & STATE_SYSTEM_UNAVAILABLE ||
isEmbeddedApp || role == ROLE_SYSTEM_EQUATION);
// We aren't finished calculating isInteractive yet; actions are
handled below.
// Whether the name is the content of this node.
bool nameIsContent = isEmbeddedApp
@@ -534,6 +534,7 @@ VBufStorage_fieldNode_t*
GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
|| (role == ROLE_SYSTEM_LIST && !(states &
STATE_SYSTEM_READONLY))
|| isEmbeddedApp
|| role == ROLE_SYSTEM_OUTLINE
+ || role == ROLE_SYSTEM_EQUATION
|| (nameIsContent && (IA2AttribsMapIt =
IA2AttribsMap.find(L"explicit-name")) != IA2AttribsMap.end() &&
IA2AttribsMapIt->second == L"true")
)
renderChildren = false;

diff --git a/source/NVDAObjects/IAccessible/mozilla.py
b/source/NVDAObjects/IAccessible/mozilla.py
index a96f0c6..ded01ac 100755
--- a/source/NVDAObjects/IAccessible/mozilla.py
+++ b/source/NVDAObjects/IAccessible/mozilla.py
@@ -1,14 +1,16 @@
+# -*- coding: UTF-8 -*-
#NVDAObjects/IAccessible/mozilla.py
#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) 2006-2010 Michael Curran <mick@xxxxxxxxxx>, James Teh
<jamie@xxxxxxxxxxx>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner

from collections import namedtuple
+from ctypes import c_short
import IAccessibleHandler
import oleacc
import winUser
-from comtypes import IServiceProvider, COMError
+from comtypes import IServiceProvider, COMError, BSTR
import eventHandler
import controlTypes
from . import IAccessible, Dialog, WindowRoot
@@ -170,6 +172,18 @@ class TextLeaf(Mozilla):
class Application(Document):
shouldCreateTreeInterceptor = False

+class Math(Mozilla):
+
+ def _get_mathMl(self):
+ from comtypes.gen.ISimpleDOM import ISimpleDOMNode
+ node = self.IAccessibleObject.QueryInterface(ISimpleDOMNode)
+ # Try the data-mathml attribute.
+ attr = node.attributesForNames(1, (BSTR * 1)("data-mathml"),
(c_short * 1)(0,))
+ if attr:
+ return attr
+ # Assume the content is MathML.
+ return "<math>%s</math>" % node.innerHTML
+
def findExtraOverlayClasses(obj, clsList):
"""Determine the most appropriate class if this is a Mozilla object.
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses}
except that it never calls any other findOverlayClasses method.
@@ -246,6 +260,7 @@ _IAccessibleRolesToOverlayClasses = {
"object": EmbeddedObject,
oleacc.ROLE_SYSTEM_APPLICATION: Application,
oleacc.ROLE_SYSTEM_DIALOG: Application,
+ oleacc.ROLE_SYSTEM_EQUATION: Math,
}

#: Roles that mightn't set the focused state when they are focused.


https://bitbucket.org/nvdaaddonteam/nvda/commits/e14d7536d0d1/
Changeset: e14d7536d0d1
Branch: None
User: jteh
Date: 2014-09-30 07:06:33+00:00
Summary: Pass the TextInfo to braille.getControlFieldBraille.

Also, TextInfo.getControlFieldBraille now gets called for controlEnds instead
of calling braille.getControlFieldBraille directly. I'm pretty sure that was
just an oversight.

Affected #: 2 files

diff --git a/source/braille.py b/source/braille.py
index 6971d81..dd8447d 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -546,7 +546,7 @@ class NVDAObjectRegion(Region):
except NotImplementedError:
pass

-def getControlFieldBraille(field, ancestors, reportStart, formatConfig):
+def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
presCat = field.getPresentationCategory(ancestors, formatConfig)
if reportStart:
# If this is a container, only report it if this is the start
of the node.
@@ -719,7 +719,7 @@ class TextInfoRegion(Region):
self._addFieldText(text)
elif cmd == "controlEnd":
field = ctrlFields.pop()
- text = getControlFieldBraille(field,
ctrlFields, False, formatConfig)
+ text =
info.getControlFieldBraille(field, ctrlFields, False, formatConfig)
if not text:
continue
# Separate this field text from the
rest of the text.

diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py
index 99ff8d4..6ac580e 100755
--- a/source/textInfos/__init__.py
+++ b/source/textInfos/__init__.py
@@ -423,7 +423,7 @@ class TextInfo(baseObject.AutoPropertyObject):
def getControlFieldBraille(self, field, ancestors, reportStart,
formatConfig):
# Import late to avoid circular import.
import braille
- return braille.getControlFieldBraille(field, ancestors,
reportStart, formatConfig)
+ return braille.getControlFieldBraille(self, field, ancestors,
reportStart, formatConfig)

def getEmbeddedObject(self, offset=0):
"""Retrieve the embedded object associated with a particular
embedded object character.


https://bitbucket.org/nvdaaddonteam/nvda/commits/5bf996749b39/
Changeset: 5bf996749b39
Branch: None
User: jteh
Date: 2014-09-30 07:06:34+00:00
Summary: Braille math encountered when reading text.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index dd8447d..f3bf931 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -2,7 +2,7 @@
#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) 2008-2012 NV Access Limited
+#Copyright (C) 2008-2014 NV Access Limited

import itertools
import os
@@ -591,7 +591,17 @@ def getControlFieldBraille(info, field, ancestors,
reportStart, formatConfig):
level = field.get("level")
if level:
props["positionInfo"] = {"level": level}
- return getBrailleTextForProperties(**props)
+ text = getBrailleTextForProperties(**props)
+ if role == controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.brailleProvider:
+ try:
+ text += " " +
mathPres.brailleProvider.getBrailleForMathMl(
+ info.getMathMl(field))
+ except (NotImplementedError, LookupError):
+ pass
+ return text
else:
# Translators: Displayed in braille at the end of a control
field such as a list or table.
# %s is replaced with the control's role.


https://bitbucket.org/nvdaaddonteam/nvda/commits/f11c341d976c/
Changeset: f11c341d976c
Branch: None
User: jteh
Date: 2014-09-30 07:06:43+00:00
Summary: Support retrieval of MathML from Adobe Reader.

Affected #: 2 files

diff --git a/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
b/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
index 654a425..0fa5ad7 100644
--- a/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
+++ b/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
@@ -427,6 +427,8 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(

BSTR stdName = NULL;
int textFlags = 0;
+ // Whether to render just a space in place of the content.
+ bool renderSpace = false;
BSTR tempBstr = NULL;
if (domElement) {
// Get stdName.
@@ -440,6 +442,11 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
// This is an inline element.
parentNode->isBlock=false;
}
+ if (wcscmp(stdName, L"Formula") == 0) {
+ // We don't want the content of formulas,
+ // but we still want a space so the user can
get at them.
+ renderSpace = true;
+ }
}

// Get language.
@@ -472,7 +479,7 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
int childCount=0;
// We don't want to descend into lists and combo boxes.
// Besides, Acrobat reports the child count, but the children can't be
accessed.
- if (role != ROLE_SYSTEM_LIST && role != ROLE_SYSTEM_COMBOBOX) {
+ if (!renderSpace && role != ROLE_SYSTEM_LIST && role !=
ROLE_SYSTEM_COMBOBOX) {
LOG_DEBUG(L"get childCount with
IAccessible::get_accChildCount");
if((res=pacc->get_accChildCount((long*)(&childCount)))!=S_OK) {
LOG_DEBUG(L"pacc->get_accChildCount returned "<<res);
@@ -599,8 +606,15 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
}
}

- // Iterate through the children.
- if (childCount > 0) {
+ if (renderSpace) {
+ // Just render a space.
+ if (tempNode = buffer->addTextFieldNode(parentNode,
previousNode, L" ")) {
+ addAttrsToTextNode(tempNode);
+ previousNode=tempNode;
+ }
+
+ } else if (childCount > 0) {
+ // Iterate through the children.
LOG_DEBUG(L"Allocate memory to hold children");
VARIANT* varChildren;

if((varChildren=(VARIANT*)malloc(sizeof(VARIANT)*childCount))==NULL) {
@@ -644,8 +658,8 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
}
LOG_DEBUG(L"Freeing memory holding children");
free(varChildren);
- } else {

+ } else {
// No children, so this is a leaf node.
if (!this->isXFA && !stdName) {
// Non-XFA leaf nodes with no stdName are inline.

diff --git a/source/NVDAObjects/IAccessible/adobeAcrobat.py
b/source/NVDAObjects/IAccessible/adobeAcrobat.py
index d4d3639..13240e3 100644
--- a/source/NVDAObjects/IAccessible/adobeAcrobat.py
+++ b/source/NVDAObjects/IAccessible/adobeAcrobat.py
@@ -1,3 +1,9 @@
+#braille.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2008-2014 NV Access Limited
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
import api
import controlTypes
import eventHandler
@@ -27,7 +33,8 @@ stdNamesToRoles = {
"P": controlTypes.ROLE_PARAGRAPH,
"H": controlTypes.ROLE_HEADING,
# H1 to H6 handled separately
- # Span, Quote, Note, Reference, BibEntry, Code, Figure, Formula
+ # Span, Quote, Note, Reference, BibEntry, Code, Figure
+ "Formula": controlTypes.ROLE_MATH,
"Form": controlTypes.ROLE_FORM,
}

@@ -97,6 +104,40 @@ class AcrobatNode(IAccessible):
return self.accID == other.accID
return super(AcrobatNode, self)._isEqual(other)

+ def _getNodeMathMl(self, node):
+ tag = node.GetTagName()
+ yield "<%s" % tag
+ # Output relevant attributes.
+ if tag == "mfenced":
+ for attr in "open", "close", "separators":
+ val = node.GetAttribute(attr, "XML-1.00")
+ if val:
+ yield ' %s="%s"' % (attr, val)
+ yield ">"
+ val = node.GetValue()
+ if val:
+ yield val
+ else:
+ for childNum in xrange(node.GetChildCount()):
+ try:
+ subNode =
node.GetChild(childNum).QueryInterface(IPDDomElement)
+ except COMError:
+ continue
+ for sub in self._getNodeMathMl(subNode):
+ yield sub
+ yield "</%s>" % tag
+
+ def _get_mathMl(self):
+ # There could be other stuff before the math element. Ug.
+ for childNum in xrange(self.pdDomNode.GetChildCount()):
+ try:
+ child =
self.pdDomNode.GetChild(childNum).QueryInterface(IPDDomElement)
+ except COMError:
+ continue
+ if child.GetTagName() == "math":
+ return "".join(self._getNodeMathMl(child))
+ raise LookupError
+
class RootNode(AcrobatNode):
shouldAllowIAccessibleFocusEvent = True



https://bitbucket.org/nvdaaddonteam/nvda/commits/652f8cc555b2/
Changeset: 652f8cc555b2
Branch: None
User: jteh
Date: 2014-09-30 07:14:01+00:00
Summary: Support for retrieving math from MathType equations in Microsoft
Word.

Affected #: 3 files

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index 95d2463..a54fa9f 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -103,6 +103,7 @@ using namespace std;
#define wdDISPID_RANGE_INLINESHAPES 319
#define wdDISPID_INLINESHAPES_COUNT 1
#define wdDISPID_INLINESHAPES_ITEM 0
+#define wdDISPID_INLINESHAPE_OLEFORMAT 5
#define wdDISPID_INLINESHAPE_TYPE 6
#define wdDISPID_INLINESHAPE_ALTERNATIVETEXT 131
#define wdDISPID_INLINESHAPE_TITLE 158
@@ -128,6 +129,7 @@ using namespace std;
#define wdDISPID_PARAGRAPHFORMAT_RIGHTINDENT 106
#define wdDISPID_PARAGRAPHFORMAT_LEFTINDENT 107
#define wdDISPID_PARAGRAPHFORMAT_FIRSTLINEINDENT 108
+#define wdDISPID_OLEFORMAT_PROGID 22

#define wdCommentsStory 4

@@ -156,6 +158,9 @@ using namespace std;
#define wdNoProofing 1024 //&H400
#define wdLanguageUnknown 9999999

+#define wdInlineShapeEmbeddedOLEObject 1
+#define wdInlineShapePicture 3
+
#define formatConfig_reportFontName 1
#define formatConfig_reportFontSize 2
#define formatConfig_reportFontAttributes 4
@@ -664,7 +669,7 @@ inline int getInlineShapesCount(IDispatch* pDispatchRange) {
* Generates an opening tag for the first inline shape in this range if one
exists.
* If the function is successful, the total number of inline shapes for this
range is returned allowing the caller to then perhaps move the range forward a
character and try again.
*/
-inline int generateInlineShapeXML(IDispatch* pDispatchRange, wostringstream&
XMLStream) {
+inline int generateInlineShapeXML(IDispatch* pDispatchRange, int offset,
wostringstream& XMLStream) {
IDispatchPtr pDispatchShapes=NULL;
IDispatchPtr pDispatchShape=NULL;
int count=0;
@@ -696,7 +701,19 @@ inline int generateInlineShapeXML(IDispatch*
pDispatchRange, wostringstream& XML
}
SysFreeString(altText);
}
- XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<(shapeType==3?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\">";
+ XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<(shapeType==wdInlineShapePicture?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\"";
+ if(shapeType==wdInlineShapeEmbeddedOLEObject) {
+ XMLStream<<L" shapeoffset=\""<<offset<<L"\"";
+ IDispatchPtr pOLEFormat=NULL;
+
if(_com_dispatch_raw_propget(pDispatchShape,wdDISPID_INLINESHAPE_OLEFORMAT,VT_DISPATCH,&pOLEFormat)==S_OK)
{
+ BSTR progId=NULL;
+
if(_com_dispatch_raw_propget(pOLEFormat,wdDISPID_OLEFORMAT_PROGID,VT_BSTR,&progId)==S_OK&&progId)
{
+ XMLStream<<L" progid=\""<<progId<<"\"";
+ SysFreeString(progId);
+ }
+ }
+ }
+ XMLStream<<L">";
return count;
}

@@ -860,7 +877,7 @@ void winword_getTextInRange_helper(HWND hwnd,
winword_getTextInRange_args* args)
}
//If there are inline shapes somewhere, try getting and
generating info for the first one hear.
//We also get the over all count of shapes for this
word so we know whether we need to check for more within this word
- int
inlineShapesCount=hasInlineShapes?generateInlineShapeXML(pDispatchRange,XMLStream):0;
+ int
inlineShapesCount=hasInlineShapes?generateInlineShapeXML(pDispatchRange,chunkStartOffset,XMLStream):0;
if(inlineShapesCount>1) {

_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_COLLAPSE,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdCollapseStart);

if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdCharacter,1)!=S_OK||unitsMoved<=0)
{

diff --git a/source/NVDAObjects/window/winword.py
b/source/NVDAObjects/window/winword.py
index c66e7ef..2458b1b 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -1,6 +1,6 @@
#appModules/winword.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2012 NVDA Contributors
+#Copyright (C) 2006-2014 NV Access Limited, Manish Agrawal
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -332,7 +332,12 @@ class WordDocumentTextInfo(textInfos.TextInfo):
elif role=="graphic":
role=controlTypes.ROLE_GRAPHIC
elif role=="object":
- role=controlTypes.ROLE_EMBEDDEDOBJECT
+ progid=field.get("progid")
+ if progid and progid.startswith("Equation.DSMT"):
+ # MathType.
+ role=controlTypes.ROLE_MATH
+ else:
+ role=controlTypes.ROLE_EMBEDDEDOBJECT
else:
fieldType=int(field.pop('wdFieldType',-1))
if fieldType!=-1:
@@ -537,6 +542,19 @@ class WordDocumentTextInfo(textInfos.TextInfo):
self.obj.WinwordWindowObject.ScrollIntoView(self._rangeObj)

self.obj.WinwordSelectionObject.SetRange(self._rangeObj.Start,self._rangeObj.End)

+ def getMathMl(self, field):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ range = self._rangeObj.Duplicate
+ range.Start = int(field["shapeoffset"])
+ obj = range.InlineShapes[0].OLEFormat
+ try:
+ return mathType.getMathMl(obj)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
class WordDocument(EditableTextWithoutAutoSelectDetection, Window):

TextInfo=WordDocumentTextInfo

diff --git a/source/mathType.py b/source/mathType.py
new file mode 100644
index 0000000..0193dd8
--- /dev/null
+++ b/source/mathType.py
@@ -0,0 +1,42 @@
+#mathType.py
+#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) 2014 NV Access Limited
+
+"""Utilities for working with MathType.
+"""
+
+import _winreg as winreg
+import ctypes
+import re
+
+def _getDllPath():
+ with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Design
Science\DSMT6\Directories", 0, winreg.KEY_WOW64_32KEY | winreg.KEY_QUERY_VALUE)
as key:
+ return winreg.QueryValueEx(key, "AppSystemDir32")[0] +
"\\MT6.dll"
+
+lib = ctypes.windll[_getDllPath()]
+
+RE_STRIP_XML_PREFIX = re.compile(r"^.*?(?=<(?:\w+:)?math[ >])")
+def stripExtraneousXml(xml):
+ # Strip anything before the opening of the math tag.
+ return RE_STRIP_XML_PREFIX.sub("", xml)
+
+def getMathMl(oleFormat, runForConversion=True):
+ """Get MathML from a MathType OLEFormat object.
+ """
+ if runForConversion:
+ oleFormat.DoVerb(2) # "RunForConversion"
+ mt = oleFormat.object._comobj
+ length = ctypes.c_long()
+ # 2 is get MathML
+ try:
+ if lib.MTGetLangStrFromEqn(mt, 2, None, ctypes.byref(length))
!= 0:
+ raise RuntimeError
+ mathMl = (ctypes.c_char * length.value)()
+ if lib.MTGetLangStrFromEqn(mt, 2, ctypes.byref(mathMl),
ctypes.byref(length)) != 0:
+ raise RuntimeError
+ finally:
+ # 1 is OLECLOSE_NOSAVE
+ lib.MTCloseOleObject(1, mt)
+ return stripExtraneousXml(mathMl.value)


https://bitbucket.org/nvdaaddonteam/nvda/commits/b8a0180b0ba1/
Changeset: b8a0180b0ba1
Branch: None
User: jteh
Date: 2014-09-30 07:32:05+00:00
Summary: Support for retrieving math from MathType equations in Microsoft
PowerPoint.

Affected #: 1 file

diff --git a/source/appModules/powerpnt.py b/source/appModules/powerpnt.py
index 293933c..88bc9ae 100644
--- a/source/appModules/powerpnt.py
+++ b/source/appModules/powerpnt.py
@@ -1,6 +1,6 @@
#appModules/powerpnt.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2012-2013 NV Access Limited
+#Copyright (C) 2012-2014 NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -37,6 +37,8 @@ import scriptHandler
# These also all request to have their (incomplete) UI Automation
implementations disabled. [MS Office 2013]
objectModelWindowClasses=set(["paneClassDC","mdiClass","screenClass"])

+MATHTYPE_PROGID = "Equation.DSMT"
+
#comtypes COM interface definition for Powerpoint application object's events
class EApplication(IDispatch):
_iid_=comtypes.GUID('{914934C2-5A91-11CF-8700-00AA0060263B}')
@@ -515,6 +517,12 @@ class Shape(PpObject):

presentationType=Window.presType_content

+ def __init__(self, **kwargs):
+ super(Shape, self).__init__(**kwargs)
+ if self.role == controlTypes.ROLE_EMBEDDEDOBJECT:
+ if
self.ppObject.OLEFormat.ProgID.startswith(MATHTYPE_PROGID):
+ self.role = controlTypes.ROLE_MATH
+
def _get__overlapInfo(self):

slideWidth=self.appModule._ppApplication.activePresentation.pageSetup.slideWidth

slideHeight=self.appModule._ppApplication.activePresentation.pageSetup.slideHeight
@@ -762,6 +770,19 @@ class Shape(PpObject):
states.add(controlTypes.STATE_OFFSCREEN)
return states

+ def _get_mathMl(self):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ obj = self.ppObject.OLEFormat
+ try:
+ # Don't call RunForConversion, as this seems to make
focus bounce.
+ # We don't seem to need it for PowerPoint anyway.
+ return mathType.getMathMl(obj, runForConversion=False)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
__gestures={
"kb:leftArrow":"moveHorizontal",
"kb:rightArrow":"moveHorizontal",
@@ -929,6 +950,44 @@ class SlideShowTreeInterceptorTextInfo(NVDAObjectTextInfo):
return (0,self._getStoryLength())
raise LookupError

+ def getTextWithFields(self,formatConfig=None):
+ fields = self.obj.rootNVDAObject.basicTextFields
+ text = self.obj.rootNVDAObject.basicText
+ out = []
+ textOffset = self._startOffset
+ for fieldOffset, field in fields:
+ if fieldOffset < self._startOffset:
+ continue
+ elif fieldOffset >= self._endOffset:
+ break
+ # Output any text before the field.
+ chunk = text[textOffset:fieldOffset]
+ if chunk:
+ out.append(chunk)
+ # Output the field.
+ out.extend((
+ # Copy the field so the original isn't modified.
+ textInfos.FieldCommand("controlStart",
textInfos.ControlField(field)),
+ u" ", textInfos.FieldCommand("controlEnd",
None)))
+ textOffset = fieldOffset + 1
+ # Output any text after all fields in this range.
+ chunk = text[textOffset:self._endOffset]
+ if chunk:
+ out.append(chunk)
+ return out
+
+ def getMathMl(self, field):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ try:
+ # Don't call RunForConversion, as this seems to make
focus bounce.
+ # We don't seem to need it for PowerPoint anyway.
+ return mathType.getMathMl(field["oleFormat"],
runForConversion=False)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
class SlideShowTreeInterceptor(TreeInterceptor):
"""A TreeInterceptor for showing Slide show content. Has no caret
navigation, a CursorManager must be used on top. """

@@ -1035,6 +1094,12 @@ class SlideShowWindow(PaneClassDC):
for chunk in
self._getShapeText(cell.shape,cellShape=True):
yield chunk
return
+ if shapeType==msoEmbeddedOLEObject:
+ oleFormat=shape.OLEFormat
+ if oleFormat.ProgID.startswith(MATHTYPE_PROGID):
+ yield
textInfos.ControlField(role=controlTypes.ROLE_MATH,
+ oleFormat=oleFormat, _startOfNode=True)
+ return
label=shape.alternativeText
if not label:
try:
@@ -1055,9 +1120,20 @@ class SlideShowWindow(PaneClassDC):
ppObject=self.currentSlide.ppObject
if self.notesMode:
ppObject=ppObject.notesPage
+ # Maintain a list of fields and the offsets at which they occur.
+ # For now, these are only control fields that consume a space.
+ fields=self.basicTextFields=[]
+ # Incrementation of textLen must include line feed added by
join.
+ textLen=0
for shape in ppObject.shapes:
for chunk in self._getShapeText(shape):
- chunks.append(chunk)
+ if isinstance(chunk,textInfos.ControlField):
+ fields.append((textLen,chunk))
+ chunks.append(" ")
+ textLen+=2
+ else:
+ chunks.append(chunk)
+ textLen+=len(chunk)+1
self.basicText="\n".join(chunks)
if not self.basicText:
if self.notesMode:


https://bitbucket.org/nvdaaddonteam/nvda/commits/a0d1b1830e29/
Changeset: a0d1b1830e29
Branch: None
User: jteh
Date: 2014-09-30 11:46:38+00:00
Summary: Speak/braille math content in math NVDAObjects.

Affected #: 2 files

diff --git a/source/braille.py b/source/braille.py
index f3bf931..e6d8a9a 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -529,7 +529,8 @@ class NVDAObjectRegion(Region):
def update(self):
obj = self.obj
presConfig = config.conf["presentation"]
- text = getBrailleTextForProperties(name=obj.name, role=obj.role,
+ role = obj.role
+ text = getBrailleTextForProperties(name=obj.name, role=role,
value=obj.value if not NVDAObjectHasUsefulText(obj)
else None ,
states=obj.states,
description=obj.description if
presConfig["reportObjectDescriptions"] else None,
@@ -537,6 +538,15 @@ class NVDAObjectRegion(Region):
positionInfo=obj.positionInfo if
presConfig["reportObjectPositionInformation"] else None,
cellCoordsText=obj.cellCoordsText if
config.conf["documentFormatting"]["reportTableCellCoords"] else None,
)
+ if role == controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.brailleProvider:
+ try:
+ text += " " +
mathPres.brailleProvider.getBrailleForMathMl(
+ obj.mathMl)
+ except (NotImplementedError, LookupError):
+ pass
self.rawText = text + self.appendText
super(NVDAObjectRegion, self).update()


diff --git a/source/speech.py b/source/speech.py
index 1a4d90d..66bb3eb 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -281,7 +281,8 @@ def
speakObjectProperties(obj,reason=controlTypes.REASON_QUERY,index=None,**allo

def speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
from NVDAObjects import NVDAObjectTextInfo
- isEditable=(reason!=controlTypes.REASON_FOCUSENTERED and
obj.TextInfo!=NVDAObjectTextInfo and (obj.role in
(controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_TERMINAL) or
controlTypes.STATE_EDITABLE in obj.states))
+ role=obj.role
+ isEditable=(reason!=controlTypes.REASON_FOCUSENTERED and
obj.TextInfo!=NVDAObjectTextInfo and (role in
(controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_TERMINAL) or
controlTypes.STATE_EDITABLE in obj.states))

allowProperties={'name':True,'role':True,'states':True,'value':True,'description':True,'keyboardShortcut':True,'positionInfo_level':True,'positionInfo_indexInGroup':True,'positionInfo_similarItemsInGroup':True,"cellCoordsText":True,"rowNumber":True,"columnNumber":True,"includeTableCellCoords":True,"columnCount":True,"rowCount":True,"rowHeaderText":True,"columnHeaderText":True}

if reason==controlTypes.REASON_FOCUSENTERED:
@@ -319,7 +320,9 @@ def
speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
allowProperties['value']=False

speakObjectProperties(obj,reason=reason,index=index,**allowProperties)
- if reason!=controlTypes.REASON_ONLYCACHE and isEditable:
+ if reason==controlTypes.REASON_ONLYCACHE:
+ return
+ if isEditable:
try:
info=obj.makeTextInfo(textInfos.POSITION_SELECTION)
if not info.isCollapsed:
@@ -331,6 +334,14 @@ def
speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
except:
newInfo=obj.makeTextInfo(textInfos.POSITION_ALL)

speakTextInfo(newInfo,unit=textInfos.UNIT_PARAGRAPH,reason=controlTypes.REASON_CARET)
+ elif role==controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.speechProvider:
+ try:
+
speak(mathPres.speechProvider.getSpeechForMathMl(obj.mathMl))
+ except (NotImplementedError, LookupError):
+ pass

def
speakText(text,index=None,reason=controlTypes.REASON_MESSAGE,symbolLevel=None):
"""Speaks some text.


https://bitbucket.org/nvdaaddonteam/nvda/commits/4ab78cfe94d1/
Changeset: 4ab78cfe94d1
Branch: None
User: jteh
Date: 2014-10-01 01:13:42+00:00
Summary: Fix typo.

Affected #: 1 file

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index a709700..9451b07 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -55,7 +55,7 @@ def registerProvider(provider, speech=False, braille=False,
interaction=False):
@param interaction: Whether this provider supports interaction.
@type interaction: bool
"""
- global speechProvider, brailleProvider, presentationProvider
+ global speechProvider, brailleProvider, interactionProvider
if speech:
speechProvider = provider
if braille:


https://bitbucket.org/nvdaaddonteam/nvda/commits/48df7730846c/
Changeset: 48df7730846c
Branch: None
User: jteh
Date: 2014-10-01 01:15:22+00:00
Summary: Add command to interat with math bound to NVDA+alt+m.

Affected #: 1 file

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 4358436..4265977 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -3,7 +3,7 @@
#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) 2006-2012 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista

import time
import itertools
@@ -1371,7 +1371,42 @@ class GlobalCommands(ScriptableObject):
wx.CallAfter(gui.mainFrame.onConfigProfilesCommand, None)
# Translators: Describes the command to open the Configuration Profiles
dialog.
script_activateConfigProfilesDialog.__doc__ = _("Shows the NVDA
Configuration Profiles dialog")
-
+
+ def script_interactWithMath(self, gesture):
+ import mathPres
+ mathPres.ensureInit()
+ if not mathPres.interactionProvider:
+ # Translators: Reported when the user attempts math
interaction
+ # but math interaction is not supported.
+ ui.message(_("Math interaction not supported."))
+ return
+
+ pos = api.getReviewPosition()
+ pos.expand(textInfos.UNIT_CHARACTER)
+ for item in reversed(pos.getTextWithFields()):
+ if not isinstance(item, textInfos.FieldCommand) or
item.command != "controlStart":
+ continue
+ field = item.field
+ if field.get("role") != controlTypes.ROLE_MATH:
+ continue
+ try:
+ return
mathPres.interactionProvider.interactWithMathMl(pos.getMathMl(field))
+ except (NotImplementedError, LookupError):
+ continue
+
+ obj = api.getNavigatorObject()
+ if obj.role == controlTypes.ROLE_MATH:
+ try:
+ return
mathPres.interactionProvider.interactWithMathMl(obj.mathMl)
+ except (NotImplementedError, LookupError):
+ pass
+
+ # Translators: Reported when the user attempts math interaction
+ # with something that isn't math.
+ ui.message(_("Not math"))
+ # Translators: Describes a command.
+ script_interactWithMath.__doc__ = _("Begins interaction with math
content")
+
__gestures = {
# Basic
"kb:NVDA+n": "showGui",
@@ -1549,6 +1584,7 @@ class GlobalCommands(ScriptableObject):
"kb:NVDA+control+z": "activatePythonConsole",
"kb:NVDA+control+f3": "reloadPlugins",
"kb(desktop):NVDA+control+f2": "test_navigatorDisplayModelText",
+ "kb:NVDA+alt+m": "interactWithMath",
}

#: The single global commands instance.


https://bitbucket.org/nvdaaddonteam/nvda/commits/33e8d1e72c3b/
Changeset: 33e8d1e72c3b
Branch: None
User: jteh
Date: 2014-10-01 07:57:36+00:00
Summary: Add MathInteractionNVDAObject which can be used by math
interaction implementations to implement their own interaction model with any
commands they choose; e.g. arrow keys, etc.

Affected #: 1 file

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index 9451b07..df2319f 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -11,6 +11,12 @@ Plugins can register their own implementation for any or all
of these
using L{registerProvider}.
"""

+from NVDAObjects.window import Window
+import controlTypes
+import api
+import virtualBuffers
+import eventHandler
+
class MathPresentationProvider(object):
"""Implements presentation of math content.
A single provider does not need to implement all presentation types.
@@ -65,3 +71,40 @@ def registerProvider(provider, speech=False, braille=False,
interaction=False):

def ensureInit():
pass
+
+class MathInteractionNVDAObject(Window):
+ """Base class for a fake NVDAObject which can be focused while
interacting with math.
+ Subclasses can bind commands to itneract with the content
+ and produce speech and braille output as they wish.
+ To begin interaction, call L{setFocus}.
+ Pressing escape exits interaction.
+ """
+
+ role = controlTypes.ROLE_MATH
+ # Override the window name.
+ name = None
+ # Any tree interceptor should not apply here.
+ treeInterceptor = None
+
+ def __init__(self, provider=None, mathMl=None):
+ self.parent = parent = api.getFocusObject()
+ self.provider = provider
+ super(MathInteractionNVDAObject,
self).__init__(windowHandle=parent.windowHandle)
+
+ def setFocus(self):
+ ti = self.parent.treeInterceptor
+ if isinstance(ti, virtualBuffers.VirtualBuffer):
+ # Normally, when entering browse mode from a descendant
(e.g. dialog),
+ # we want the cursor to move to the focus (#3145).
+ # However, we don't want this for math, as math isn't
focusable.
+ ti._enteringFromOutside = True
+ eventHandler.executeEvent("gainFocus", self)
+
+ def script_exit(self, gesture):
+ eventHandler.executeEvent("gainFocus", self.parent)
+ # Translators: Describes a command.
+ script_exit.__doc__ = _("Exit math interaction")
+
+ __gestures = {
+ "kb:escape": "exit",
+ }


https://bitbucket.org/nvdaaddonteam/nvda/commits/a0bebdd734ef/
Changeset: a0bebdd734ef
Branch: None
User: jteh
Date: 2014-10-30 05:25:55+00:00
Summary: English symbols: Support usage of a decimal point without a
preceding number; e.g. .5.

Affected #: 1 file

diff --git a/source/locale/en/symbols.dic b/source/locale/en/symbols.dic
index 38cd00b..9a69d00 100644
--- a/source/locale/en/symbols.dic
+++ b/source/locale/en/symbols.dic
@@ -13,9 +13,9 @@ complexSymbols:
; phrase ending (?<=[^\s;]);(?=\s|$)
: phrase ending (?<=[^\s:]):(?=\s|$)
# Others
-decimal point (?<=\d)\.(?=\d)
+decimal point (?<![^\d -])\.(?=\d)
in-word ' (?<=[^\W_])['’]
-negative number (?<!\w)-(?=[$£€¥]?\d)
+negative number (?<!\w)-(?=[$£€¥.]?\d)

symbols:
# identifier replacement[[ level][ preserve]][ # display name]


https://bitbucket.org/nvdaaddonteam/nvda/commits/5b23b57ffecd/
Changeset: 5b23b57ffecd
Branch: None
User: jteh
Date: 2014-12-07 22:13:03+00:00
Summary: Allow NVDAObjects to override the braille regions used for them by
implementing a getBrailleRegions method.

This method takes one boolean argument, review, which is True if this is for
the review cursor.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index e6d8a9a..d63c6c5 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -1189,6 +1189,17 @@ def getFocusContextRegions(obj, oldFocusRegions=None):
_cachedFocusAncestorsEnd = ancestorsEnd

def getFocusRegions(obj, review=False):
+ # Allow objects to override normal behaviour.
+ try:
+ regions = obj.getBrailleRegions(review=review)
+ except (AttributeError, NotImplementedError):
+ pass
+ else:
+ for region in regions:
+ region.update()
+ yield region
+ return
+
# Late import to avoid circular import.
from treeInterceptorHandler import TreeInterceptor
from cursorManager import CursorManager


https://bitbucket.org/nvdaaddonteam/nvda/commits/c56f74955ddd/
Changeset: c56f74955ddd
Branch: None
User: mdcurran
Date: 2014-12-08 04:49:07+00:00
Summary: Compile mathPlayer Alpha 2014 typelib from idl files now in
miscDeps.

Affected #: 3 files

diff --git a/miscDeps b/miscDeps
index 9423478..cf40538 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit 9423478981342b887437a6af8720d6d7e9a64602
+Subproject commit cf405387f7bb383841d2eb9f6f5d180c311effab

diff --git a/nvdaHelper/archBuild_sconscript b/nvdaHelper/archBuild_sconscript
index 624889c..03141dd 100644
--- a/nvdaHelper/archBuild_sconscript
+++ b/nvdaHelper/archBuild_sconscript
@@ -77,6 +77,10 @@ iSimpleDomRPCStubs=env.SConscript('ISimpleDOM_sconscript')
if TARGET_ARCH=='x86':
env.Install(sourceTypelibDir,iSimpleDomRPCStubs[0]) #typelib

+mathPlayerRPCStubs=env.SConscript('mathPlayer_sconscript')
+if TARGET_ARCH=='x86':
+ env.Install(sourceTypelibDir,mathPlayerRPCStubs[0]) #typelib
+
if TARGET_ARCH=='x86':
localLib=env.SConscript('local/sconscript')
Export('localLib')

diff --git a/nvdaHelper/mathPlayer_sconscript b/nvdaHelper/mathPlayer_sconscript
new file mode 100644
index 0000000..592587d
--- /dev/null
+++ b/nvdaHelper/mathPlayer_sconscript
@@ -0,0 +1,25 @@
+###
+#This file is a part of the NVDA project.
+#URL: http://www.nvda-project.org/
+#Copyright 2006-2010 NVDA contributers.
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License version 2.0, as
published by
+#the Free Software Foundation.
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#This license can be found at:
+#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+###
+
+Import('env')
+
+env.Command("MathSpeechEnums.idl","#/miscDeps/include/mathPlayer/MathSpeechEnums.idl",Copy("$TARGET","$SOURCE"))
+idlFile=env.Command("mathPlayerDLL.idl","#/miscDeps/include/mathPlayer/mathPlayerDLL.idl",Copy("$TARGET","$SOURCE"))
+
+tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
+ source=idlFile,
+ MIDLFLAGS=['/I',Dir('.')],
+)
+
+Return(['tlbFile','headerFile','iidSourceFile','proxySourceFile','dlldataSourceFile'])

diff --git a/source/comInterfaces_sconscript b/source/comInterfaces_sconscript
index 6588e23..4896a4c 100755
--- a/source/comInterfaces_sconscript
+++ b/source/comInterfaces_sconscript
@@ -39,6 +39,7 @@ COM_INTERFACES = {
"UIAutomationClient.py": ('{944de083-8fb8-45cf-bcb7-c477acb2f897}',1,0),
"IAccessible2Lib.py": "typelibs/ia2.tlb",
"ISimpleDOM.py": "typelibs/ISimpleDOMNode.tlb",
+ "mathPlayer.py": "typelibs/mathPlayerDLL.tlb",
#"Accessibility.py": ('{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}',1,0),
"tom.py": ('{8CC497C9-A1DF-11CE-8098-00AA0047BE5D}',1,0),
"SpeechLib.py": ('{C866CA3A-32F7-11D2-9602-00C04F8EE628}',5,0),


https://bitbucket.org/nvdaaddonteam/nvda/commits/9b907fcd4e6a/
Changeset: 9b907fcd4e6a
Branch: None
User: jteh
Date: 2014-12-08 06:11:52+00:00
Summary: Use MathPlayer 2014 (if available) for math speech, braille and
interaction.

Affected #: 2 files

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index df2319f..173fb2d 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -16,6 +16,7 @@ import controlTypes
import api
import virtualBuffers
import eventHandler
+from logHandler import log

class MathPresentationProvider(object):
"""Implements presentation of math content.
@@ -70,7 +71,16 @@ def registerProvider(provider, speech=False, braille=False,
interaction=False):
interactionProvider = provider

def ensureInit():
- pass
+ # Register builtin providers if a plugin hasn't registered others.
+ if not speechProvider or not brailleProvider or not interactionProvider:
+ from . import mathPlayer
+ try:
+ provider = mathPlayer.MathPlayer()
+ except:
+ log.warning("MathPlayer 2014 not available")
+ else:
+ registerProvider(provider, speech=not speechProvider,
+ braille=not brailleProvider, interaction=not
interactionProvider)

class MathInteractionNVDAObject(Window):
"""Base class for a fake NVDAObject which can be focused while
interacting with math.

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
new file mode 100644
index 0000000..8288ad5
--- /dev/null
+++ b/source/mathPres/mathPlayer.py
@@ -0,0 +1,79 @@
+#mathPlayer.py
+#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) 2014 NV Access Limited
+
+"""Support for math presentation using MathPlayer 2014.
+"""
+
+import comtypes.client
+from comtypes import COMError
+from comtypes.gen.MathPlayer import MPInterface, IMathSpeech, IMathNavigation,
IMathBraille
+import speech
+from keyboardHandler import KeyboardInputGesture
+import braille
+import mathPres
+
+def _processMpSpeech(text):
+ # todo
+ return [text]
+
+class MathPlayerInteraction(mathPres.MathInteractionNVDAObject):
+
+ def __init__(self, provider=None, mathMl=None):
+ super(MathPlayerInteraction, self).__init__(provider=provider,
mathMl=mathMl)
+ provider._mpSpeech.SetMathML(mathMl)
+
+ def reportFocus(self):
+ super(MathPlayerInteraction, self).reportFocus()
+
speech.speak(_processMpSpeech(self.provider._mpSpeech.GetSpokenText()))
+
+ def getBrailleRegions(self, review=False):
+ yield braille.NVDAObjectRegion(self, appendText=" ")
+ region = braille.Region()
+ region.focusToHardLeft = True
+
self.provider._mpBraille.SetBrailleWidth(braille.handler.displaySize)
+ region.rawText = self.provider._mpBraille.GetBraille()
+ yield region
+
+ def getScript(self, gesture):
+ # Pass most keys to MathPlayer. Pretty ugly.
+ if isinstance(gesture, KeyboardInputGesture) and "NVDA" not in
gesture.modifierNames and (
+ gesture.mainKeyName in {
+ "leftArrow", "rightArrow", "upArrow",
"downArrow",
+ "home", "end",
+ "space", "backspace", "enter",
+ }
+ or len(gesture.mainKeyName) == 1
+ ):
+ return self.script_navigate
+ return super(MathPlayerInteraction, self).getScript(gesture)
+
+ def script_navigate(self, gesture):
+ modNames = gesture.modifierNames
+ try:
+ text =
self.provider._mpNavigation.DoNavigateKeyPress(gesture.vkCode,
+ "shift" in modNames, "control" in modNames,
"alt" in modNames, False)
+ except COMError:
+ return
+ speech.speak(_processMpSpeech(text))
+
+class MathPlayer(mathPres.MathPresentationProvider):
+
+ def __init__(self):
+ mpSpeech = self._mpSpeech =
comtypes.client.CreateObject(MPInterface, interface=IMathSpeech)
+ self._mpNavigation = mpSpeech.QueryInterface(IMathNavigation)
+ self._mpBraille = mpSpeech.QueryInterface(IMathBraille)
+
+ def getSpeechForMathMl(self, mathMl):
+ self._mpSpeech.SetMathML(mathMl)
+ return _processMpSpeech(self._mpSpeech.GetSpokenText())
+
+ def getBrailleForMathMl(self, mathMl):
+ self._mpSpeech.SetMathML(mathMl)
+ self._mpBraille.SetBrailleWidth(braille.handler.displaySize)
+ return self._mpBraille.GetBraille()
+
+ def interactWithMathMl(self, mathMl):
+ MathPlayerInteraction(provider=self, mathMl=mathMl).setFocus()


https://bitbucket.org/nvdaaddonteam/nvda/commits/f5166129e6cc/
Changeset: f5166129e6cc
Branch: None
User: jteh
Date: 2014-12-08 10:47:09+00:00
Summary: speech: Rename BreakCommand to SpeakWithoutPausesBreakCommand.

This is in preparation for a new BreakCommand which can be sent to a
synthesiser to insert pauses, etc.
SpeakWithoutPausesBreakCommand makes it clear that this is only related to the
speakWithoutPauses function. Update the docstring to make this clear also.
It now also correctly subclasses SpeechCommand instead of object.

Affected #: 1 file

diff --git a/source/speech.py b/source/speech.py
index 66bb3eb..7be5f53 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -692,7 +692,7 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
if not endingBlock and reason==controlTypes.REASON_SAYALL:

endingBlock=bool(int(controlFieldStackCache[count].get('isBlock',0)))
if endingBlock:
- speechSequence.append(BreakCommand())
+ speechSequence.append(SpeakWithoutPausesBreakCommand())
# The TextInfo should be considered blank if we are only exiting fields
(i.e. we aren't entering any new fields and there is no text).
isTextBlank=True

@@ -1365,7 +1365,7 @@ def speakWithoutPauses(speechSequence,detectBreaks=True):
if detectBreaks and speechSequence:
sequenceLen=len(speechSequence)
for index in xrange(sequenceLen):
- if isinstance(speechSequence[index],BreakCommand):
+ if
isinstance(speechSequence[index],SpeakWithoutPausesBreakCommand):
if index>0 and lastStartIndex<index:

speakWithoutPauses(speechSequence[lastStartIndex:index],detectBreaks=False)
speakWithoutPauses(None)
@@ -1469,5 +1469,8 @@ class LangChangeCommand(SpeechCommand):
def __repr__(self):
return "LangChangeCommand (%r)"%self.lang

-class BreakCommand(object):
- """Forces speakWithoutPauses to flush its buffer and therefore break
the sentence at this point."""
+class SpeakWithoutPausesBreakCommand(SpeechCommand):
+ """Forces speakWithoutPauses to flush its buffer and therefore break
the sentence at this point.
+ This should only be used with the L{speakWithoutPauses} function.
+ This will be removed during processing.
+ """


https://bitbucket.org/nvdaaddonteam/nvda/commits/bcbf789f90b1/
Changeset: bcbf789f90b1
Branch: None
User: jteh
Date: 2014-12-08 11:19:26+00:00
Summary: Add speech.BreakCommand to insert a pause of specified length.
This includes support for eSpeak and SAPI 5.

Affected #: 3 files

diff --git a/source/speech.py b/source/speech.py
index 7be5f53..266f404 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -1474,3 +1474,17 @@ class SpeakWithoutPausesBreakCommand(SpeechCommand):
This should only be used with the L{speakWithoutPauses} function.
This will be removed during processing.
"""
+
+class BreakCommand(SpeechCommand):
+ """Insert a break between words.
+ """
+
+ def __init__(self, time=0):
+ """
+ @param time: The duration of the pause to be inserted in
milliseconds.
+ @param time: int
+ """
+ self.time = time
+
+ def __repr__(self):
+ return "BreakCommand(time=%d)" % self.time

diff --git a/source/synthDrivers/espeak.py b/source/synthDrivers/espeak.py
index f58a68f..55c42b9 100644
--- a/source/synthDrivers/espeak.py
+++ b/source/synthDrivers/espeak.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#synthDrivers/espeak.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2007-2013 NV Access Limited, Peter Vágner
+#Copyright (C) 2007-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -70,6 +70,8 @@ class SynthDriver(SynthDriver):
textList.append("</voice>")
textList.append("<voice
xml:lang=\"%s\">"%(item.lang if item.lang else
defaultLanguage).replace('_','-'))
langChanged=True
+ elif isinstance(item,speech.BreakCommand):
+ textList.append('<break time="%dms" />' %
item.time)
elif isinstance(item,speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s"%item)
else:

diff --git a/source/synthDrivers/sapi5.py b/source/synthDrivers/sapi5.py
index 1c866de..e51a252 100644
--- a/source/synthDrivers/sapi5.py
+++ b/source/synthDrivers/sapi5.py
@@ -1,6 +1,7 @@
+# -*- coding: UTF-8 -*-
#synthDrivers/sapi5.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -136,6 +137,8 @@ class SynthDriver(SynthDriver):
textList.append("<Bookmark Mark=\"%d\"
/>"%item.index)
elif isinstance(item,speech.CharacterModeCommand):
textList.append("<spell>" if item.state else
"</spell>")
+ elif isinstance(item,speech.BreakCommand):
+ textList.append('<silence msec="%d" />' %
item.time)
elif isinstance(item,speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s"%item)
else:


https://bitbucket.org/nvdaaddonteam/nvda/commits/5eac19a7035d/
Changeset: 5eac19a7035d
Branch: None
User: jteh
Date: 2014-12-08 11:34:08+00:00
Summary: MathPlayer: Handle pauses and correct pronunciation of the
character "a".

The pauses will probably need scaling for rates.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 8288ad5..87575ce 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -7,17 +7,35 @@
"""Support for math presentation using MathPlayer 2014.
"""

+import re
import comtypes.client
from comtypes import COMError
-from comtypes.gen.MathPlayer import MPInterface, IMathSpeech, IMathNavigation,
IMathBraille
+from comtypes.gen.MathPlayer import MPInterface, IMathSpeech,
IMathSpeechSettings, IMathNavigation, IMathBraille
import speech
from keyboardHandler import KeyboardInputGesture
import braille
import mathPres

+RE_MP_SPEECH = re.compile(
+ # Break.
+ r"<break time='(?P<break>\d+)ms'/> ?"
+ # Pronunciation for the character "a".
+ "|(?P<charA><phoneme alphabet='ipa' ph='\xe6'> eh</phoneme>)"
+ # Other tags, which we don't care about.
+ r"|<[^>]+> ?"
+ # Actual content.
+ r"|(?P<content>[^<]+)")
def _processMpSpeech(text):
- # todo
- return [text]
+ out = []
+ for m in RE_MP_SPEECH.finditer(text):
+ if m.lastgroup == "break":
+
out.append(speech.BreakCommand(time=int(m.group("break"))))
+ elif m.lastgroup == "charA":
+ out.extend((speech.CharacterModeCommand(True),
+ "a", speech.CharacterModeCommand(False)))
+ elif m.lastgroup == "content":
+ out.append(m.group(0))
+ return out

class MathPlayerInteraction(mathPres.MathInteractionNVDAObject):

@@ -63,6 +81,8 @@ class MathPlayer(mathPres.MathPresentationProvider):

def __init__(self):
mpSpeech = self._mpSpeech =
comtypes.client.CreateObject(MPInterface, interface=IMathSpeech)
+ mpSpeechSettings = mpSpeech.QueryInterface(IMathSpeechSettings)
+ mpSpeechSettings.SetSpeechTags("SSML")
self._mpNavigation = mpSpeech.QueryInterface(IMathNavigation)
self._mpBraille = mpSpeech.QueryInterface(IMathBraille)



https://bitbucket.org/nvdaaddonteam/nvda/commits/78ddd7afeeb0/
Changeset: 78ddd7afeeb0
Branch: None
User: jteh
Date: 2014-12-09 00:55:20+00:00
Summary: MathPlayer: Convert commas in navigation messages to BreakCommands.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 87575ce..55e2db0 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -23,8 +23,10 @@ RE_MP_SPEECH = re.compile(
"|(?P<charA><phoneme alphabet='ipa' ph='\xe6'> eh</phoneme>)"
# Other tags, which we don't care about.
r"|<[^>]+> ?"
+ # Commas indicating pauses in navigation messages.
+ r"| ?(?P<comma>,) ?"
# Actual content.
- r"|(?P<content>[^<]+)")
+ r"|(?P<content>[^<,]+)")
def _processMpSpeech(text):
out = []
for m in RE_MP_SPEECH.finditer(text):
@@ -33,6 +35,8 @@ def _processMpSpeech(text):
elif m.lastgroup == "charA":
out.extend((speech.CharacterModeCommand(True),
"a", speech.CharacterModeCommand(False)))
+ elif m.lastgroup == "comma":
+ out.append(speech.BreakCommand(time=100))
elif m.lastgroup == "content":
out.append(m.group(0))
return out


https://bitbucket.org/nvdaaddonteam/nvda/commits/92dc9b52cce6/
Changeset: 92dc9b52cce6
Branch: None
User: jteh
Date: 2014-12-09 11:35:34+00:00
Summary: The upcoming MathPlayer release will be called MathPlayer 4, so
tweak accordingly.

Affected #: 2 files

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index 173fb2d..f6f79a0 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -77,7 +77,7 @@ def ensureInit():
try:
provider = mathPlayer.MathPlayer()
except:
- log.warning("MathPlayer 2014 not available")
+ log.warning("MathPlayer 4 not available")
else:
registerProvider(provider, speech=not speechProvider,
braille=not brailleProvider, interaction=not
interactionProvider)

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 55e2db0..ab15a82 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -4,7 +4,7 @@
#See the file COPYING for more details.
#Copyright (C) 2014 NV Access Limited

-"""Support for math presentation using MathPlayer 2014.
+"""Support for math presentation using MathPlayer 4.
"""

import re


https://bitbucket.org/nvdaaddonteam/nvda/commits/0130b4fe342d/
Changeset: 0130b4fe342d
Branch: None
User: jteh
Date: 2014-12-09 11:40:54+00:00
Summary: User Guide: Document math support.

Affected #: 1 file

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index c438837..aea28d5 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -522,6 +522,35 @@ A key command is provided to return to the original page
containing the embedded
| Move to containing browse mode document | NVDA+control+space | Moves the
focus out of the current embedded object and into the document that contains it
|
%kc:endInclude

++ Reading Mathematical Content +
+Using MathPlayer 4 from Design Science, NVDA can read and interactively
navigate supported mathematical content.
+This requires that MathPlayer 4 is installed on the computer.
+NVDA supports the following types of mathematical content:
+- MathML in Mozilla Firefox and Microsoft Internet Explorer.
+- Design Science MathType in Microsoft Word and PowerPoint.
+- MathML in Adobe Reader. Note that this is not an official standard yet, so
there is currently no publicly available software that can produce this content.
+-
+
+When reading a document, NVDA will speak any supported mathematical content
where it occurs.
+If you are using a braille display, it will also be displayed in braille.
+
+++ Interactive Navigation ++
+If you are working primarily with speech, in most cases, you will probably
wish to examine the expression in smaller segments, rather than hearing the
entire expression at once.
+To do this, first move the review cursor to the mathematical content.
+By default, the review cursor follows the system caret, so you can usually use
the system caret to move to the desired content.
+Then, activate the following command:
+
+%kc:beginInclude
+|| Name | Key | Description |
+| Interact with math content | NVDA+alt+m | Begins interaction with math
content. |
+%kc:endInclude
+
+At this point, you can use MathPlayer commands such as the arrow keys to
explore the expression.
+For example, you can move through the expression with the left and right arrow
keys and zoom into a portion of the expression such as a fraction using the
down arrow key.
+Please see the MathPlayer documentation for further information.
+
+When you wish to return to the document, simply press the escape key.
+
+ Application Specific NVDA Commands +
NVDA provides its own extra commands for some applications to make certain
tasks easier or to provide access to functionality which is not otherwise
accessible to screen reader users.



https://bitbucket.org/nvdaaddonteam/nvda/commits/fc33dfde98c9/
Changeset: fc33dfde98c9
Branch: None
User: jteh
Date: 2014-12-10 06:02:49+00:00
Summary: cosmetic: Use actual Unicode character instead of escape for
readability.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index ab15a82..20af545 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -1,3 +1,4 @@
+# -*- coding: UTF-8 -*-
#mathPlayer.py
#A part of NonVisual Desktop Access (NVDA)
#This file is covered by the GNU General Public License.
@@ -20,7 +21,7 @@ RE_MP_SPEECH = re.compile(
# Break.
r"<break time='(?P<break>\d+)ms'/> ?"
# Pronunciation for the character "a".
- "|(?P<charA><phoneme alphabet='ipa' ph='\xe6'> eh</phoneme>)"
+ ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>)"
# Other tags, which we don't care about.
r"|<[^>]+> ?"
# Commas indicating pauses in navigation messages.


https://bitbucket.org/nvdaaddonteam/nvda/commits/b57d2dd2daae/
Changeset: b57d2dd2daae
Branch: None
User: jteh
Date: 2014-12-11 02:08:09+00:00
Summary: speech: Add PitchCommand, VolumeCommand and RateCommand to adjust
these parameters during speech. Includes support for eSpeak and SAPI 5.

Affected #: 3 files

diff --git a/source/speech.py b/source/speech.py
index 266f404..31893df 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -1488,3 +1488,48 @@ class BreakCommand(SpeechCommand):

def __repr__(self):
return "BreakCommand(time=%d)" % self.time
+
+class PitchCommand(SpeechCommand):
+ """Change the pitch of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
pitch setting;
+ e.g. 0.5 is half, 1 returns to the current pitch
setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "PitchCommand(multiplier=%g)" % self.multiplier
+
+class VolumeCommand(SpeechCommand):
+ """Change the volume of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
volume setting;
+ e.g. 0.5 is half, 1 returns to the current volume
setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "VolumeCommand(multiplier=%g)" % self.multiplier
+
+class RateCommand(SpeechCommand):
+ """Change the rate of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
rate setting;
+ e.g. 0.5 is half, 1 returns to the current rate setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "RateCommand(multiplier=%g)" % self.multiplier

diff --git a/source/synthDrivers/espeak.py b/source/synthDrivers/espeak.py
index 55c42b9..bc708cc 100644
--- a/source/synthDrivers/espeak.py
+++ b/source/synthDrivers/espeak.py
@@ -50,10 +50,20 @@ class SynthDriver(SynthDriver):
def _get_language(self):
return self._language

+ PROSODY_ATTRS = {
+ speech.PitchCommand: "pitch",
+ speech.VolumeCommand: "volume",
+ speech.RateCommand: "rate",
+ }
+
def speak(self,speechSequence):
defaultLanguage=self._language
textList=[]
langChanged=False
+ prosody={}
+ # We output malformed XML, as we might close an outer tag after
opening an inner one; e.g.
+ # <voice><prosody></voice></prosody>.
+ # However, eSpeak doesn't seem to mind.
for item in speechSequence:
if isinstance(item,basestring):
s=unicode(item)
@@ -72,12 +82,34 @@ class SynthDriver(SynthDriver):
langChanged=True
elif isinstance(item,speech.BreakCommand):
textList.append('<break time="%dms" />' %
item.time)
+ elif type(item) in self.PROSODY_ATTRS:
+ if prosody:
+ # Close previous prosody tag.
+ textList.append("</prosody>")
+ attr=self.PROSODY_ATTRS[type(item)]
+ if item.multiplier==1:
+ # Returning to normal.
+ try:
+ del prosody[attr]
+ except KeyError:
+ pass
+ else:
+ prosody[attr]=int(item.multiplier* 100)
+ if not prosody:
+ continue
+ textList.append("<prosody")
+ for attr,val in prosody.iteritems():
+ textList.append(' %s="%d%%"'%(attr,val))
+ textList.append(">")
elif isinstance(item,speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s"%item)
else:
log.error("Unknown speech: %s"%item)
+ # Close any open tags.
if langChanged:
textList.append("</voice>")
+ if prosody:
+ textList.append("</prosody>")
text=u"".join(textList)
_espeak.speak(text)


diff --git a/source/synthDrivers/sapi5.py b/source/synthDrivers/sapi5.py
index e51a252..9ced0d5 100644
--- a/source/synthDrivers/sapi5.py
+++ b/source/synthDrivers/sapi5.py
@@ -93,8 +93,11 @@ class SynthDriver(SynthDriver):
else:
return None

+ def _percentToRate(self, percent):
+ return (percent - 50) / 5
+
def _set_rate(self,rate):
- self.tts.Rate = (rate-50)/5
+ self.tts.Rate = self._percentToRate(rate)

def _set_pitch(self,value):
#pitch is really controled with xml around speak commands
@@ -128,27 +131,85 @@ class SynthDriver(SynthDriver):
return
self._initTts(voice=voice)

- def speak(self,speechSequence):
- textList=[]
+ def _percentToPitch(self, percent):
+ return percent / 2 - 25
+
+ def speak(self, speechSequence):
+ textList = []
+
+ # NVDA SpeechCommands are linear, but XML is hierarchical.
+ # Therefore, we track values for non-empty tags.
+ # When a tag changes, we close all previously opened tags and
open new ones.
+ tags = {}
+ # We have to use something mutable here because it needs to be
changed by the inner function.
+ tagsChanged = [True]
+ openedTags = []
+ def outputTags():
+ if not tagsChanged[0]:
+ return
+ for tag in reversed(openedTags):
+ textList.append("</%s>" % tag)
+ del openedTags[:]
+ for tag, attrs in tags.iteritems():
+ textList.append("<%s" % tag)
+ for attr, val in attrs.iteritems():
+ textList.append(' %s="%s"' % (attr,
val))
+ textList.append(">")
+ openedTags.append(tag)
+ tagsChanged[0] = False
+
+ pitch = self._pitch
+ # Pitch must always be specified in the markup.
+ tags["pitch"] = {"absmiddle": self._percentToPitch(pitch)}
+ rate = self.rate
+ volume = self.volume
+
for item in speechSequence:
- if isinstance(item,basestring):
- textList.append(item.replace("<","&lt;"))
- elif isinstance(item,speech.IndexCommand):
- textList.append("<Bookmark Mark=\"%d\"
/>"%item.index)
- elif isinstance(item,speech.CharacterModeCommand):
- textList.append("<spell>" if item.state else
"</spell>")
- elif isinstance(item,speech.BreakCommand):
+ if isinstance(item, basestring):
+ outputTags()
+ textList.append(item.replace("<", "&lt;"))
+ elif isinstance(item, speech.IndexCommand):
+ textList.append('<Bookmark Mark="%d" />' %
item.index)
+ elif isinstance(item, speech.CharacterModeCommand):
+ if item.state:
+ tags["spell"] = {}
+ else:
+ try:
+ del tags["spell"]
+ except KeyError:
+ pass
+ tagsChanged[0] = True
+ elif isinstance(item, speech.BreakCommand):
textList.append('<silence msec="%d" />' %
item.time)
- elif isinstance(item,speech.SpeechCommand):
- log.debugWarning("Unsupported speech command:
%s"%item)
+ elif isinstance(item, speech.PitchCommand):
+ tags["pitch"] = {"absmiddle":
self._percentToPitch(int(pitch * item.multiplier))}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.VolumeCommand):
+ if item.multiplier == 1:
+ try:
+ del tags["volume"]
+ except KeyError:
+ pass
+ else:
+ tags["volume"] = {"level": int(volume *
item.multiplier)}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.RateCommand):
+ if item.multiplier == 1:
+ try:
+ del tags["rate"]
+ except KeyError:
+ pass
+ else:
+ tags["rate"] = {"absspeed":
self._percentToRate(int(rate * item.multiplier))}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.SpeechCommand):
+ log.debugWarning("Unsupported speech command:
%s" % item)
else:
- log.error("Unknown speech: %s"%item)
- text="".join(textList)
- #Pitch must always be hardcoded
- pitch=(self._pitch/2)-25
- text="<pitch absmiddle=\"%s\">%s</pitch>"%(pitch,text)
- flags=constants.SVSFIsXML|constants.SVSFlagsAsync
- self.tts.Speak(text,flags)
+ log.error("Unknown speech: %s" % item)
+
+ text = "".join(textList)
+ flags = constants.SVSFIsXML | constants.SVSFlagsAsync
+ self.tts.Speak(text, flags)

def cancel(self):
#if self.tts.Status.RunningState == 2:


https://bitbucket.org/nvdaaddonteam/nvda/commits/d2a4f252f749/
Changeset: d2a4f252f749
Branch: None
User: jteh
Date: 2014-12-11 02:29:30+00:00
Summary: MathPlayer: Support pitch, volume and rate changes.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 20af545..8784f41 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -22,14 +22,23 @@ RE_MP_SPEECH = re.compile(
r"<break time='(?P<break>\d+)ms'/> ?"
# Pronunciation for the character "a".
ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>)"
+ # Prosody.
+ r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
+ r"|(?P<prosodyReset></prosidy>) ?"
# Other tags, which we don't care about.
r"|<[^>]+> ?"
# Commas indicating pauses in navigation messages.
r"| ?(?P<comma>,) ?"
# Actual content.
r"|(?P<content>[^<,]+)")
+PROSODY_COMMANDS = {
+ "pitch": speech.PitchCommand,
+ "volume": speech.VolumeCommand,
+ "rate": speech.RateCommand,
+}
def _processMpSpeech(text):
out = []
+ resetProsody = set()
for m in RE_MP_SPEECH.finditer(text):
if m.lastgroup == "break":

out.append(speech.BreakCommand(time=int(m.group("break"))))
@@ -38,6 +47,14 @@ def _processMpSpeech(text):
"a", speech.CharacterModeCommand(False)))
elif m.lastgroup == "comma":
out.append(speech.BreakCommand(time=100))
+ elif m.lastgroup in PROSODY_COMMANDS:
+ command = PROSODY_COMMANDS[m.lastgroup]
+ out.append(command(multiplier=int(m.group(m.lastgroup))
/ 100.0))
+ resetProsody.add(command)
+ elif m.lastgroup == "prosodyReset":
+ for command in resetProsody:
+ out.append(command(multiplier=1))
+ resetProsody.clear()
elif m.lastgroup == "content":
out.append(m.group(0))
return out


https://bitbucket.org/nvdaaddonteam/nvda/commits/e40942040114/
Changeset: e40942040114
Branch: None
User: jteh
Date: 2014-12-11 02:30:50+00:00
Summary: MathPlayer: Eliminate pointless space in speech sequence after
CharacterModeCommand for "a".

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 8784f41..9576aab 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -21,7 +21,7 @@ RE_MP_SPEECH = re.compile(
# Break.
r"<break time='(?P<break>\d+)ms'/> ?"
# Pronunciation for the character "a".
- ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>)"
+ ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>) ?"
# Prosody.
r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
r"|(?P<prosodyReset></prosidy>) ?"


https://bitbucket.org/nvdaaddonteam/nvda/commits/48ccb728c2c4/
Changeset: 48ccb728c2c4
Branch: None
User: jteh
Date: 2014-12-11 07:09:30+00:00
Summary: Add speech.PhonemeCommand to insert specific IPA pronunciation.
Includes a couple of phonemes in eSpeak and SAPI 5.

These maps can be extended, but we only currently need very specific phonemes,
so I've only mapped those for now.

Affected #: 4 files

diff --git a/source/speech.py b/source/speech.py
index 31893df..79bbf51 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -1533,3 +1533,27 @@ class RateCommand(SpeechCommand):

def __repr__(self):
return "RateCommand(multiplier=%g)" % self.multiplier
+
+class PhonemeCommand(SpeechCommand):
+ """Insert a specific pronunciation.
+ This command accepts Unicode International Phonetic Alphabet (IPA)
characters.
+ Note that this is not well supported by synthesizers.
+ """
+
+ def __init__(self, ipa, text=None):
+ """
+ @param ipa: Unicode IPA characters.
+ @type ipa: unicode
+ @param text: Text to speak if the synthesizer does not support
+ some or all of the specified IPA characters,
+ C{None} to ignore this command instead.
+ @type text: unicode
+ """
+ self.ipa = ipa
+ self.text = text
+
+ def __repr__(self):
+ out = "PhonemeCommand(%r" % self.ipa
+ if self.text:
+ out += ", text=%r" % self.text
+ return out + ")"

diff --git a/source/synthDrivers/_espeak.py b/source/synthDrivers/_espeak.py
index d309d81..128fc01 100755
--- a/source/synthDrivers/_espeak.py
+++ b/source/synthDrivers/_espeak.py
@@ -173,7 +173,7 @@ def _speak(text):
global isSpeaking
uniqueID=c_int()
isSpeaking = True
- flags = espeakCHARS_WCHAR | espeakSSML
+ flags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES
return espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)

def speak(text):

diff --git a/source/synthDrivers/espeak.py b/source/synthDrivers/espeak.py
index bc708cc..3f4e5f1 100644
--- a/source/synthDrivers/espeak.py
+++ b/source/synthDrivers/espeak.py
@@ -56,6 +56,22 @@ class SynthDriver(SynthDriver):
speech.RateCommand: "rate",
}

+ IPA_TO_ESPEAK = {
+ u"θ": u"T",
+ u"s": u"s",
+ u"ˈ": u"'",
+ }
+
+ def _processText(self, text):
+ text = unicode(text)
+ # We need to make several replacements.
+ return text.translate({
+ 0x1: None, # used for embedded commands
+ 0x3C: u"&lt;", # <: because of XML
+ 0x3E: u"&gt;", # >: because of XML
+ 0x5B: u" [", # [: [[ indicates phonemes
+ })
+
def speak(self,speechSequence):
defaultLanguage=self._language
textList=[]
@@ -66,11 +82,7 @@ class SynthDriver(SynthDriver):
# However, eSpeak doesn't seem to mind.
for item in speechSequence:
if isinstance(item,basestring):
- s=unicode(item)
- # Replace \01, as this is used for embedded
commands.
- #Also replace < and > as espeak handles xml
-
s=s.translate({ord(u'\01'):None,ord(u'<'):u'&lt;',ord(u'>'):u'&gt;'})
- textList.append(s)
+ textList.append(self._processText(item))
elif isinstance(item,speech.IndexCommand):
textList.append("<mark name=\"%d\"
/>"%item.index)
elif isinstance(item,speech.CharacterModeCommand):
@@ -101,6 +113,15 @@ class SynthDriver(SynthDriver):
for attr,val in prosody.iteritems():
textList.append(' %s="%d%%"'%(attr,val))
textList.append(">")
+ elif isinstance(item,speech.PhonemeCommand):
+ # We can't use unicode.translate because we
want to reject unknown characters.
+ try:
+
phonemes="".join([self.IPA_TO_ESPEAK[char] for char in item.ipa])
+ textList.append(u"[[%s]]"%phonemes)
+ except KeyError:
+ log.debugWarning("Unknown character in
IPA string: %s"%item.ipa)
+ if item.text:
+
textList.append(self._processText(item.text))
elif isinstance(item,speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s"%item)
else:

diff --git a/source/synthDrivers/sapi5.py b/source/synthDrivers/sapi5.py
index 9ced0d5..12a5b26 100644
--- a/source/synthDrivers/sapi5.py
+++ b/source/synthDrivers/sapi5.py
@@ -134,6 +134,30 @@ class SynthDriver(SynthDriver):
def _percentToPitch(self, percent):
return percent / 2 - 25

+ IPA_TO_SAPI = {
+ u"θ": u"th",
+ u"s": u"s",
+ }
+ def _convertPhoneme(self, ipa):
+ # We only know about US English phonemes.
+ # Rather than just ignoring unknown phonemes, SAPI throws an
exception.
+ # Therefore, don't bother with any other language.
+ if self.tts.voice.GetAttribute("language") != "409":
+ raise LookupError("No data for this language")
+ out = []
+ outAfter = None
+ for ipaChar in ipa:
+ if ipaChar == u"ˈ":
+ outAfter = u"1"
+ continue
+ out.append(self.IPA_TO_SAPI[ipaChar])
+ if outAfter:
+ out.append(outAfter)
+ outAfter = None
+ if outAfter:
+ out.append(outAfter)
+ return u" ".join(out)
+
def speak(self, speechSequence):
textList = []

@@ -202,6 +226,14 @@ class SynthDriver(SynthDriver):
else:
tags["rate"] = {"absspeed":
self._percentToRate(int(rate * item.multiplier))}
tagsChanged[0] = True
+ elif isinstance(item, speech.PhonemeCommand):
+ try:
+ textList.append(u'<pron
sym="%s">%s</pron>'
+ %
(self._convertPhoneme(item.ipa), item.text or u""))
+ except LookupError:
+ log.debugWarning("Couldn't convert
character in IPA string: %s" % item.ipa)
+ if item.text:
+ textList.append(item.text)
elif isinstance(item, speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s" % item)
else:


https://bitbucket.org/nvdaaddonteam/nvda/commits/18a10fd6147b/
Changeset: 18a10fd6147b
Branch: None
User: jteh
Date: 2014-12-11 07:11:27+00:00
Summary: MathPlayer: Support specific pronunciation. Practically, this is
currently only used for the "th" and "ths" at the end of certain ordinal
numbers.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 9576aab..c0d85d8 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -22,6 +22,8 @@ RE_MP_SPEECH = re.compile(
r"<break time='(?P<break>\d+)ms'/> ?"
# Pronunciation for the character "a".
ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>) ?"
+ # Specific pronunciation.
+ ur"|<phoneme alphabet='ipa' ph='(?P<ipa>[^']+)'> (?P<phonemeText>[^
<]+)</phoneme> ?"
# Prosody.
r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
r"|(?P<prosodyReset></prosidy>) ?"
@@ -55,6 +57,9 @@ def _processMpSpeech(text):
for command in resetProsody:
out.append(command(multiplier=1))
resetProsody.clear()
+ elif m.lastgroup == "phonemeText":
+ out.append(speech.PhonemeCommand(m.group("ipa"),
+ text=m.group("phonemeText")))
elif m.lastgroup == "content":
out.append(m.group(0))
return out


https://bitbucket.org/nvdaaddonteam/nvda/commits/f9cc4820c022/
Changeset: f9cc4820c022
Branch: None
User: jteh
Date: 2014-12-12 00:43:30+00:00
Summary: MathPlayer seems to put the % sign outside of the quotes for the
rate and volume attributes. Tweak our code accordingly.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index c0d85d8..b346e8a 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -25,7 +25,7 @@ RE_MP_SPEECH = re.compile(
# Specific pronunciation.
ur"|<phoneme alphabet='ipa' ph='(?P<ipa>[^']+)'> (?P<phonemeText>[^
<]+)</phoneme> ?"
# Prosody.
- r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
+ r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)'%)?(?: rate='(?P<rate>\d+)'%)?> ?"
r"|(?P<prosodyReset></prosidy>) ?"
# Other tags, which we don't care about.
r"|<[^>]+> ?"


https://bitbucket.org/nvdaaddonteam/nvda/commits/a4f909557583/
Changeset: a4f909557583
Branch: None
User: jteh
Date: 2014-12-12 00:48:16+00:00
Summary: sapi5: Close any tags that are still open after all commands are
processed.

Affected #: 1 file

diff --git a/source/synthDrivers/sapi5.py b/source/synthDrivers/sapi5.py
index 12a5b26..2117b03 100644
--- a/source/synthDrivers/sapi5.py
+++ b/source/synthDrivers/sapi5.py
@@ -238,6 +238,10 @@ class SynthDriver(SynthDriver):
log.debugWarning("Unsupported speech command:
%s" % item)
else:
log.error("Unknown speech: %s" % item)
+ # Close any tags that are still open.
+ tags.clear()
+ tagsChanged[0] = True
+ outputTags()

text = "".join(textList)
flags = constants.SVSFIsXML | constants.SVSFlagsAsync


https://bitbucket.org/nvdaaddonteam/nvda/commits/b5e1fc7affa6/
Changeset: b5e1fc7affa6
Branch: None
User: jteh
Date: 2014-12-12 00:56:37+00:00
Summary: Fix speaking of "space space" by some synthesisers (such as Ivona)
when handling CharacterModeCommand.

This occurred because speech.speak appends CHUNK_SEPARATOR (" ") to all text.
It no longer does this if in character mode.

Affected #: 1 file

diff --git a/source/speech.py b/source/speech.py
index 79bbf51..35cfff0 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -455,12 +455,17 @@ def speak(speechSequence,symbolLevel=None):
if symbolLevel is None:
symbolLevel=config.conf["speech"]["symbolLevel"]
curLanguage=defaultLanguage
+ inCharacterMode=False
for index in xrange(len(speechSequence)):
item=speechSequence[index]
+ if isinstance(item,CharacterModeCommand):
+ inCharacterMode=item.state
if autoLanguageSwitching and isinstance(item,LangChangeCommand):
curLanguage=item.lang
if isinstance(item,basestring):
-
speechSequence[index]=processText(curLanguage,item,symbolLevel)+CHUNK_SEPARATOR
+
speechSequence[index]=processText(curLanguage,item,symbolLevel)
+ if not inCharacterMode:
+ speechSequence[index]+=CHUNK_SEPARATOR
getSynth().speak(speechSequence)

def speakSelectionMessage(message,text):


https://bitbucket.org/nvdaaddonteam/nvda/commits/a5332ba2c64b/
Changeset: a5332ba2c64b
Branch: None
User: jteh
Date: 2014-12-12 01:56:59+00:00
Summary: Move stripExtraneousXml from mathType to mathPres, as it is needed
elsewhere too.

Affected #: 2 files

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index f6f79a0..6a221c0 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -11,6 +11,7 @@ Plugins can register their own implementation for any or all
of these
using L{registerProvider}.
"""

+import re
from NVDAObjects.window import Window
import controlTypes
import api
@@ -118,3 +119,11 @@ class MathInteractionNVDAObject(Window):
__gestures = {
"kb:escape": "exit",
}
+
+RE_STRIP_XML_PREFIX = re.compile(r"^.*?(?=<(?:\w+:)?math[ >])")
+def stripExtraneousXml(xml):
+ """Strip extraneous XML from MathML.
+ This is needed where retrieving MathML produces more than just the math
tag.
+ Currently, this strips anything before the opening of the math tag.
+ """
+ return RE_STRIP_XML_PREFIX.sub("", xml)

diff --git a/source/mathType.py b/source/mathType.py
index 0193dd8..e3930e5 100644
--- a/source/mathType.py
+++ b/source/mathType.py
@@ -9,7 +9,7 @@

import _winreg as winreg
import ctypes
-import re
+import mathPres

def _getDllPath():
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Design
Science\DSMT6\Directories", 0, winreg.KEY_WOW64_32KEY | winreg.KEY_QUERY_VALUE)
as key:
@@ -17,11 +17,6 @@ def _getDllPath():

lib = ctypes.windll[_getDllPath()]

-RE_STRIP_XML_PREFIX = re.compile(r"^.*?(?=<(?:\w+:)?math[ >])")
-def stripExtraneousXml(xml):
- # Strip anything before the opening of the math tag.
- return RE_STRIP_XML_PREFIX.sub("", xml)
-
def getMathMl(oleFormat, runForConversion=True):
"""Get MathML from a MathType OLEFormat object.
"""
@@ -39,4 +34,4 @@ def getMathMl(oleFormat, runForConversion=True):
finally:
# 1 is OLECLOSE_NOSAVE
lib.MTCloseOleObject(1, mt)
- return stripExtraneousXml(mathMl.value)
+ return mathPres.stripExtraneousXml(mathMl.value)


https://bitbucket.org/nvdaaddonteam/nvda/commits/473d4e082a59/
Changeset: 473d4e082a59
Branch: None
User: jteh
Date: 2014-12-12 01:58:53+00:00
Summary: Fix math in Internet Explorer 8.

IE 8 seems to include an XML declaration before the math tag. We need to strip
this in order for MathPlayer (and probably other implementations) to handle it
correctly.

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 27d59da..d6cbe53 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -953,7 +953,8 @@ class Math(MSHTML):
role = controlTypes.ROLE_MATH

def _get_mathMl(self):
- return self.HTMLNode.outerHTML
+ import mathPres
+ return mathPres.stripExtraneousXml(self.HTMLNode.outerHTML)

def findExtraIAccessibleOverlayClasses(obj, clsList):
"""Determine the most appropriate class for MSHTML objects.


https://bitbucket.org/nvdaaddonteam/nvda/commits/8cfd1d0653f4/
Changeset: 8cfd1d0653f4
Branch: None
User: jteh
Date: 2014-12-15 07:37:41+00:00
Summary: Merge branch 'master' into t4673

Affected #: 170 files

diff --git a/contributors.txt b/contributors.txt
index f094044..4655c1e 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -144,6 +144,20 @@ Noelia Ruiz Martínez
Bhavya Shah
Dr. Mireia Ribera
Ruben Alcaraz
+Marina Salse Rovira
+Santi Moese
Nikos Demetriou
Daniel Johansson
Manish Agrawal
+Aaron Cannon
+derek riemer
+Irene Nakas
+Mahmood Taghavi
+Mohammadreza Rashad
+Jorge Zarache
+Dinesh Mittal
+Maheshinder Singh Khosla
+Nikola Jovic
+Niklas Johansson
+Dinesh Mittal
+Maheshinder Singh Khosla

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/miscDeps b/miscDeps
index cf40538..c198735 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit cf405387f7bb383841d2eb9f6f5d180c311effab
+Subproject commit c198735dcf0c966c0550a7c2142dfb02513150ef

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/remote/ia2LiveRegions.cpp
b/nvdaHelper/remote/ia2LiveRegions.cpp
index 773f94b..df389fe 100644
--- a/nvdaHelper/remote/ia2LiveRegions.cpp
+++ b/nvdaHelper/remote/ia2LiveRegions.cpp
@@ -23,6 +23,17 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

using namespace std;

+bool fetchIA2Attributes(IAccessible2* pacc2, map<wstring,wstring>& attribsMap)
{
+ BSTR attribs=NULL;
+ pacc2->get_attributes(&attribs);
+ if(!attribs) {
+ return false;
+ }
+ IA2AttribsToMap(attribs,attribsMap);
+ SysFreeString(attribs);
+ return true;
+}
+
IAccessible2* findAriaAtomic(IAccessible2* pacc2,map<wstring,wstring>&
attribsMap) {
map<wstring,wstring>::iterator i=attribsMap.find(L"atomic");
bool atomic=(i!=attribsMap.end()&&i->second.compare(L"true")==0);
@@ -38,12 +49,8 @@ IAccessible2* findAriaAtomic(IAccessible2*
pacc2,map<wstring,wstring>& attribsMa
if(pdispParent) {
IAccessible2* pacc2Parent=NULL;

if(pdispParent->QueryInterface(IID_IAccessible2,(void**)&pacc2Parent)==S_OK&&pacc2Parent)
{
- BSTR parentAttribs=NULL;
-
pacc2Parent->get_attributes(&parentAttribs);
- if(parentAttribs) {
- map<wstring,wstring>
parentAttribsMap;
-
IA2AttribsToMap(parentAttribs,parentAttribsMap);
- SysFreeString(parentAttribs);
+ map<wstring,wstring> parentAttribsMap;
+
if(fetchIA2Attributes(pacc2Parent,parentAttribsMap)) {

pacc2Atomic=findAriaAtomic(pacc2Parent,parentAttribsMap);
}
pacc2Parent->Release();
@@ -71,8 +78,13 @@ bool getTextFromIAccessible(wstring& textBuf, IAccessible2*
pacc2, bool useNewTe
if(varChildren[i].vt==VT_DISPATCH) {
IAccessible2* pacc2Child=NULL;

if(varChildren[i].pdispVal&&varChildren[i].pdispVal->QueryInterface(IID_IAccessible2,(void**)&pacc2Child)==S_OK)
{
-
if(getTextFromIAccessible(textBuf,pacc2Child)) {
- gotText=true;
+ map<wstring,wstring>
childAttribsMap;
+
fetchIA2Attributes(pacc2Child,childAttribsMap);
+ auto
i=childAttribsMap.find(L"live");
+
if(i==childAttribsMap.end()||i->second.compare(L"off")!=0) {
+
if(getTextFromIAccessible(textBuf,pacc2Child)) {
+ gotText=true;
+ }
}
pacc2Child->Release();
}
@@ -110,8 +122,13 @@ bool getTextFromIAccessible(wstring& textBuf,
IAccessible2* pacc2, bool useNewTe

if(paccHypertext->get_hyperlink(hyperlinkIndex,&paccHyperlink)==S_OK) {
IAccessible2*
pacc2Child=NULL;

if(paccHyperlink->QueryInterface(IID_IAccessible2,(void**)&pacc2Child)==S_OK) {
-
if(getTextFromIAccessible(textBuf,pacc2Child)) {
-
gotText=true;
+
map<wstring,wstring> childAttribsMap;
+
fetchIA2Attributes(pacc2Child,childAttribsMap);
+ auto
i=childAttribsMap.find(L"live");
+
if(i==childAttribsMap.end()||i->second.compare(L"off")!=0) {
+
if(getTextFromIAccessible(textBuf,pacc2Child)) {
+
gotText=true;
+ }
}
charAdded=true;

pacc2Child->Release();
@@ -217,18 +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);
- attribs=NULL;
- map<wstring,wstring>::iterator i;
- i=attribsMap.find(L"container-live");
+ auto i=attribsMap.find(L"container-live");
bool
live=(i!=attribsMap.end()&&(i->second.compare(L"polite")==0||i->second.compare(L"assertive")==0||i->second.compare(L"rude")==0));
if(!live) {
pacc2->Release();
@@ -275,9 +286,7 @@ void CALLBACK winEventProcHook(HWINEVENTHOOK hookID, DWORD
eventID, HWND hwnd, l
ignoreShowEvent=true;
IAccessible2* pacc2Parent=NULL;

if(pdispParent->QueryInterface(IID_IAccessible2,(void**)&pacc2Parent)==S_OK) {
-
if(pacc2Parent->get_attributes(&attribs)==S_OK&&attribs) {
-
IA2AttribsToMap(attribs,attribsMap);
- SysFreeString(attribs);
+
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

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index 7bd5a9a..3e42b09 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -385,9 +385,17 @@ void
MshtmlVBufStorage_controlFieldNode_t::reportLiveText(wstring& text) {
}
}

+bool isNodeInLiveRegion(VBufStorage_fieldNode_t* node) {
+ if(!node) return false;
+ if(node->getFirstChild()) {
+ return
((MshtmlVBufStorage_controlFieldNode_t*)node)->ariaLiveNode!=NULL;
+ }
+ return true;
+}
+
void MshtmlVBufStorage_controlFieldNode_t::reportLiveAddition() {
wstring text; //=(this->ariaLiveAtomicNode==this)?L"atomic:
":L"additions: ";
- this->getTextInRange(0,this->getLength(),text,false);
+ this->getTextInRange(0,this->getLength(),text,false,isNodeInLiveRegion);
this->reportLiveText(text);
}


diff --git a/nvdaHelper/vbufBase/storage.cpp b/nvdaHelper/vbufBase/storage.cpp
index ed7fbd3..d99dfb8 100644
--- a/nvdaHelper/vbufBase/storage.cpp
+++ b/nvdaHelper/vbufBase/storage.cpp
@@ -239,7 +239,7 @@ void
VBufStorage_fieldNode_t::generateMarkupClosingTag(std::wstring& text) {
text+=L">";
}

-void VBufStorage_fieldNode_t::getTextInRange(int startOffset, int endOffset,
std::wstring& text, bool useMarkup) {
+void VBufStorage_fieldNode_t::getTextInRange(int startOffset, int endOffset,
std::wstring& text, bool useMarkup, bool(*filter)(VBufStorage_fieldNode_t*)) {
if(this->length==0) {
LOG_DEBUG(L"node has 0 length, not collecting text");
return;
@@ -260,9 +260,9 @@ void VBufStorage_fieldNode_t::getTextInRange(int
startOffset, int endOffset, std
nhAssert(childLength>=0); //length can't be negative
childEnd+=childLength;
LOG_DEBUG(L"child with offsets of "<<childStart<<L" and
"<<childEnd);
- if(childEnd>startOffset&&endOffset>childStart) {
+
if(childEnd>startOffset&&endOffset>childStart&&(!filter||filter(child))) {
LOG_DEBUG(L"child offsets overlap requested offsets");
-
child->getTextInRange(max(startOffset,childStart)-childStart,min(endOffset-childStart,childLength),text,useMarkup);
+
child->getTextInRange(max(startOffset,childStart)-childStart,min(endOffset-childStart,childLength),text,useMarkup,filter);
}
childStart+=childLength;
LOG_DEBUG(L"childStart is now "<<childStart);
@@ -358,7 +358,7 @@ void
VBufStorage_textFieldNode_t::generateMarkupTagName(std::wstring& text) {
text+=L"text";
}

-void VBufStorage_textFieldNode_t::getTextInRange(int startOffset, int
endOffset, std::wstring& text, bool useMarkup) {
+void VBufStorage_textFieldNode_t::getTextInRange(int startOffset, int
endOffset, std::wstring& text, bool useMarkup,
bool(*filter)(VBufStorage_fieldNode_t*)) {
LOG_DEBUG(L"getting text between offsets "<<startOffset<<L" and
"<<endOffset);
if(useMarkup) {
this->generateMarkupOpeningTag(text,startOffset,endOffset);

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

/**
* @return a string providing information about this node's type, and its
state.
@@ -359,7 +360,7 @@ class VBufStorage_textFieldNode_t : public
VBufStorage_fieldNode_t {

virtual void generateMarkupTagName(std::wstring& text);

- virtual void getTextInRange(int startOffset, int endOffset,
std::wstring& text, bool useMarkup=false);
+ virtual void getTextInRange(int startOffset, int endOffset,
std::wstring& text, bool
useMarkup=false,bool(*filter)(VBufStorage_fieldNode_t*)=NULL);

/**
* constructor.

diff --git a/readme.txt b/readme.txt
index 81df6a6..d5b79d3 100644
--- a/readme.txt
+++ b/readme.txt
@@ -27,7 +27,7 @@ The following dependencies are included in Git submodules:
* eSpeak, version 1.48.03: http://espeak.sourceforge.net/
* IAccessible2, version 1.3:
http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2
* ConfigObj, version 4.6.0: http://www.voidspace.org.uk/python/configobj.html
-* liblouis, version 2.5.4: http://www.liblouis.org/
+* liblouis, version 2.6.0: http://www.liblouis.org/
* NVDA images and sounds
* System dlls not present on many systems: mfc90.dll, msvcp90.dll,
msvcr90.dll, Microsoft.VC90.CRT.manifest
* Adobe Acrobat accessibility interface, version XI:
http://download.macromedia.com/pub/developer/acrobat/AcrobatAccess.zip
@@ -39,6 +39,7 @@ The following dependencies are included in Git submodules:
* 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/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index d6cbe53..da8ea94 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -84,6 +84,22 @@ nodeNamesToNVDARoles={
"MATH":controlTypes.ROLE_MATH,
}

+def getZoomFactorsFromHTMLDocument(HTMLDocument):
+ try:
+ scr=HTMLDocument.parentWindow.screen
+ except (COMError,NameError,AttributeError):
+ log.debugWarning("no screen object for MSHTML document")
+ return (1,1)
+ try:
+ devX=float(scr.deviceXDPI)
+ devY=float(scr.deviceYDPI)
+ logX=float(scr.logicalXDPI)
+ logY=float(scr.logicalYDPI)
+ except (COMError,NameError,AttributeError,TypeError):
+ log.debugWarning("unable to fetch DPI factors")
+ return (1,1)
+ return (devX/logX,devY/logY)
+
def IAccessibleFromHTMLNode(HTMLNode):
try:
s=HTMLNode.QueryInterface(IServiceProvider)
@@ -367,8 +383,10 @@ class MSHTML(IAccessible):
windowHandle=kwargs.get('windowHandle')
p=ctypes.wintypes.POINT(x=relation[0],y=relation[1])

ctypes.windll.user32.ScreenToClient(windowHandle,ctypes.byref(p))
+ # #3494: MSHTML's internal coordinates are always at a
hardcoded DPI (usually 96) no matter the system DPI or zoom level.
+
xFactor,yFactor=getZoomFactorsFromHTMLDocument(HTMLNode.document)
try:
-
HTMLNode=HTMLNode.document.elementFromPoint(p.x,p.y)
+
HTMLNode=HTMLNode.document.elementFromPoint(p.x/xFactor,p.y/yFactor)
except:
HTMLNode=None
if not HTMLNode:
@@ -451,15 +469,24 @@ class MSHTML(IAccessible):
if self.HTMLNodeName in ("OBJECT","EMBED"):
self.HTMLNodeHasAncestorIAccessible=True

+ def _get_zoomFactors(self):
+ return getZoomFactorsFromHTMLDocument(self.HTMLNode.document)
+
def _get_location(self):
if self.HTMLNodeName and not self.HTMLNodeName.startswith('#'):
try:
r=self.HTMLNode.getBoundingClientRect()
except COMError:
return None
- width=r.right-r.left
- height=r.bottom-r.top
- p=ctypes.wintypes.POINT(x=r.left,y=r.top)
+ # #3494: MSHTML's internal coordinates are always at a
hardcoded DPI (usually 96) no matter the system DPI or zoom level.
+ xFactor,yFactor=self.zoomFactors
+ left=int(r.left*xFactor)
+ top=int(r.top*yFactor)
+ right=int(r.right*xFactor)
+ bottom=int(r.bottom*yFactor)
+ width=right-left
+ height=bottom-top
+ p=ctypes.wintypes.POINT(x=left,y=top)

ctypes.windll.user32.ClientToScreen(self.windowHandle,ctypes.byref(p))
return (p.x,p.y,width,height)
return None
@@ -582,7 +609,7 @@ class MSHTML(IAccessible):
except (COMError, AttributeError, NameError):
pass
try:
- return self.HTMLNode.innerText or ""
+ return self.HTMLNode.innerText or
super(MSHTML,self).basicText
except (COMError, AttributeError, NameError):
pass
return super(MSHTML,self).basicText

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 7214a75..4826b01 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -511,14 +511,15 @@ the NVDAObject for IAccessible

clsList.append(IAccessible)

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

diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
index d61706a..aefa6bf 100644
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -78,7 +78,9 @@ class
DynamicNVDAObjectType(baseObject.ScriptableObject.__class__):
clsList.append(APIClass)
# Allow app modules to choose overlay classes.
appModule=obj.appModule
- if appModule and "chooseNVDAObjectOverlayClasses" in
appModule.__class__.__dict__:
+ # optimisation: The base implementation of
chooseNVDAObjectOverlayClasses does nothing,
+ # so only call this method if it's been overridden.
+ if appModule and not
hasattr(appModule.chooseNVDAObjectOverlayClasses, "_isBase"):
appModule.chooseNVDAObjectOverlayClasses(obj, clsList)
# Allow global plugins to choose overlay classes.
for plugin in globalPluginHandler.runningPlugins:

diff --git a/source/NVDAObjects/window/__init__.py
b/source/NVDAObjects/window/__init__.py
index 1b95c3d..aab9b6f 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
@@ -445,4 +445,5 @@ windowClassMap={
"ScintillaWindowImpl":"Scintilla",
"RICHEDIT60W_WLXPRIVATE":"RICHEDIT50W",
"TNumEdit":"Edit",
+ "TAccessibleRichEdit":"RichEdit20",
}

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index c92845a..6704708 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -251,10 +251,22 @@ class ExcelWorksheet(ExcelBase):
if columnHeader:
for headerRowNumber in
xrange(info.rowNumber,info.rowNumber+info.rowSpan):

headerCell=self.excelWorksheetObject.cells(headerRowNumber,cell.columnNumber)
+ # The header could be merged cells.
+ # if so, fetch text from the first in
the merge as that always contains the content
+ try:
+
headerCell=headerCell.mergeArea.item(1)
+ except
(COMError,NameError,AttributeError):
+ pass
textList.append(headerCell.text)
else:
for headerColumnNumber in
xrange(info.columnNumber,info.columnNumber+info.colSpan):

headerCell=self.excelWorksheetObject.cells(cell.rowNumber,headerColumnNumber)
+ # The header could be merged cells.
+ # if so, fetch text from the first in
the merge as that always contains the content
+ try:
+
headerCell=headerCell.mergeArea.item(1)
+ except
(COMError,NameError,AttributeError):
+ pass
textList.append(headerCell.text)
text=" ".join(textList)
if text:

diff --git a/source/api.py b/source/api.py
index a03cf15..77eb33e 100644
--- a/source/api.py
+++ b/source/api.py
@@ -334,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/appModuleHandler.py b/source/appModuleHandler.py
index 7879c61..847db71 100644
--- a/source/appModuleHandler.py
+++ b/source/appModuleHandler.py
@@ -1,6 +1,7 @@
+# -*- coding: UTF-8 -*-
#appModuleHandler.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
Patrick Zajda
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -18,6 +19,7 @@ import sys
import pkgutil
import threading
import tempfile
+import comtypes.client
import baseObject
import globalVars
from logHandler import log
@@ -76,6 +78,18 @@ def getAppNameFromProcessID(processID,includeExt=False):
winKernel.kernel32.CloseHandle(FSnapshotHandle)
if not includeExt:
appName=os.path.splitext(appName)[0].lower()
+ if not appName:
+ return appName
+
+ # This might be an executable which hosts multiple apps.
+ # Try querying the app module for the name of the app being hosted.
+ try:
+ # Python 2.x can't properly handle unicode module names, so
convert them.
+ mod = __import__("appModules.%s" % appName.encode("mbcs"),
+ globals(), locals(), ("appModules",))
+ return mod.getAppNameFromHost(processID)
+ except (ImportError, AttributeError, LookupError):
+ pass
return appName

def getAppModuleForNVDAObject(obj):
@@ -260,6 +274,15 @@ class AppModule(baseObject.ScriptableObject):
where C{eventName} is the name of the event; e.g. C{event_gainFocus}.
These event methods take two arguments: the NVDAObject on which the
event was fired
and a callable taking no arguments which calls the next event handler.
+
+ Some executables host many different applications; e.g. javaw.exe.
+ In this case, it is desirable that a specific app module be loaded for
each
+ actual application, rather than the one for the hosting executable.
+ To support this, the module for the hosting executable
+ (not the C{AppModule} class within it) can implement the function
+ C{getAppNameFromHost(processId)}, where C{processId} is the id of the
host process.
+ It should return a unicode string specifying the name that should be
used.
+ Alternatively, it can raise C{LookupError} if a name couldn't be
determined.
"""

#: Whether NVDA should sleep while in this application (e.g. the
application is self-voicing).
@@ -369,6 +392,8 @@ class AppModule(baseObject.ScriptableObject):
@param clsList: The list of classes, which will be modified by
this method if appropriate.
@type clsList: list of L{NVDAObjects.NVDAObject}
"""
+ # optimisation: Make it easy to detect that this hasn't been overridden.
+ chooseNVDAObjectOverlayClasses._isBase = True

def _get_is64BitProcess(self):
"""Whether the underlying process is a 64 bit process.
@@ -408,3 +433,22 @@ class AppProfileTrigger(config.ProfileTrigger):

def __init__(self, appName):
self.spec = "app:%s" % appName
+
+def getWmiProcessInfo(processId):
+ """Retrieve the WMI Win32_Process class instance for a given process.
+ For details about the available properties, see
+ http://msdn.microsoft.com/en-us/library/aa394372%28v=vs.85%29.aspx
+ @param processId: The id of the process in question.
+ @type processId: int
+ @return: The WMI Win32_Process class instance.
+ @raise LookupError: If there was an error retrieving the instance.
+ """
+ try:
+ wmi = comtypes.client.CoGetObject(r"winmgmts:root\cimv2",
dynamic=True)
+ results = wmi.ExecQuery("select * from Win32_Process "
+ "where ProcessId = %d" % processId)
+ for result in results:
+ return result
+ except:
+ raise LookupError("Couldn't get process information using WMI")
+ raise LookupError("No such process")

diff --git a/source/appModules/eclipse.py b/source/appModules/eclipse.py
index fb258e7..66c4880 100644
--- a/source/appModules/eclipse.py
+++ b/source/appModules/eclipse.py
@@ -2,15 +2,29 @@
#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):

def event_NVDAObject_init(self, obj):
- if obj.windowClassName == "SysTreeView32" and obj.role ==
controlTypes.ROLE_TREEVIEWITEM and controlTypes.STATE_FOCUSED not in obj.states:
+ if obj.windowClassName == "SysTreeView32" and obj.role in
(controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_CHECKBOX) and
controlTypes.STATE_FOCUSED not in obj.states:
# 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/javaw.py b/source/appModules/javaw.py
new file mode 100644
index 0000000..3d1a2b8
--- /dev/null
+++ b/source/appModules/javaw.py
@@ -0,0 +1,53 @@
+#appModules/javaw.py
+#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) 2014 NV Access Limited
+
+"""Support for app specific modules for Java apps hosted by javaw.exe.
+"""
+
+import os
+import shlex
+import appModuleHandler
+from appModuleHandler import AppModule
+
+def _getEntryPoint(cmd):
+ cmd = iter(shlex.split(cmd))
+ # First argument is the executable.
+ next(cmd)
+ for arg in cmd:
+ if arg in ("-cp", "-classpath"):
+ # This option consuems the next argument.
+ next(cmd)
+ continue
+ if arg.startswith("-jar"):
+ # Next argument is the jar. Remove the extension.
+ return os.path.splitext(next(cmd))[0]
+ if arg.startswith("-"):
+ continue
+ if not arg:
+ continue
+ # Class.
+ return arg
+ raise LookupError
+
+def getAppNameFromHost(processId):
+ # Some apps have launcher executables which launch javaw.exe to run the
app.
+ # In this case, the parent process will usually be the launcher.
+ proc = appModuleHandler.getWmiProcessInfo(processId)
+ parent = proc.parentProcessId
+ if parent:
+ name = appModuleHandler.getAppNameFromProcessID(parent)
+ if name and name not in ("explorer", "cmd"):
+ # The parent isn't a shell, so it's probably a launcher.
+ return name
+
+ # Try getting the class/jar from the command line.
+ cmd = proc.CommandLine
+ if not cmd:
+ raise LookupError
+ try:
+ return "javaw_" + _getEntryPoint(cmd).replace(".", "_")
+ except:
+ raise LookupError

diff --git a/source/appModules/mintty.py b/source/appModules/mintty.py
new file mode 100644
index 0000000..9759b4e
--- /dev/null
+++ b/source/appModules/mintty.py
@@ -0,0 +1,7 @@
+"""App module for mintty
+"""
+
+from . import putty
+
+class AppModule(putty.AppModule):
+ TERMINAL_WINDOW_CLASS = "mintty"

diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
index f0dabc0..a98bfb9 100644
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -69,6 +69,7 @@ class AppModule(appModuleHandler.AppModule):
import gui
# Translators: The title for the dialog shown while Microsoft
Outlook initializes.
d=wx.Dialog(None,title=_("Waiting for Outlook..."))
+ d.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
gui.mainFrame.prePopup()
d.Show()
self._hasTriedoutlookAppSwitch=True
@@ -433,6 +434,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/appModules/powerpnt.py b/source/appModules/powerpnt.py
index 88bc9ae..c75a1f8 100644
--- a/source/appModules/powerpnt.py
+++ b/source/appModules/powerpnt.py
@@ -808,7 +808,11 @@ class TextFrameTextInfo(textInfos.offsets.OffsetsTextInfo):
return start,end

def _getTextRange(self,start,end):
-
text=self.obj.ppObject.textRange.text[start:end].replace('\x0b','\n')
+ # #4619: First let's "normalise" the text, i.e. get rid of the
CR/LF mess
+ text=self.obj.ppObject.textRange.text
+ text=text.replace('\r\n','\n')
+ #Now string slicing will be okay
+ text=text[start:end].replace('\x0b','\n')
text=text.replace('\r','\n')
return text

@@ -1179,6 +1183,7 @@ class AppModule(appModuleHandler.AppModule):
import gui
# Translators: A title for a dialog shown while Microsoft
PowerPoint initializes
d=wx.Dialog(None,title=_("Waiting for Powerpoint..."))
+ d.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
gui.mainFrame.prePopup()
d.Show()
self.hasTriedPpAppSwitch=True

diff --git a/source/appModules/putty.py b/source/appModules/putty.py
index e980984..b84ccee 100644
--- a/source/appModules/putty.py
+++ b/source/appModules/putty.py
@@ -2,7 +2,7 @@
#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

"""App module for PuTTY
"""
@@ -14,9 +14,11 @@ import appModuleHandler
from NVDAObjects.IAccessible import IAccessible

class AppModule(appModuleHandler.AppModule):
+ # Allow this to be overridden for derived applications.
+ TERMINAL_WINDOW_CLASS = "PuTTY"

def chooseNVDAObjectOverlayClasses(self, obj, clsList):
- if obj.windowClassName == "PuTTY" and
isinstance(obj,IAccessible) and obj.IAccessibleRole ==
oleacc.ROLE_SYSTEM_CLIENT:
+ if obj.windowClassName == self.TERMINAL_WINDOW_CLASS and
isinstance(obj,IAccessible) and obj.IAccessibleRole ==
oleacc.ROLE_SYSTEM_CLIENT:
try:
clsList.remove(DisplayModelEditableText)
except ValueError:

diff --git a/source/appModules/sts.py b/source/appModules/sts.py
new file mode 100644
index 0000000..8ff39f9
--- /dev/null
+++ b/source/appModules/sts.py
@@ -0,0 +1,5 @@
+"""App module for Spring Tool Suite
+This simply uses the app module for Eclipse.
+"""
+
+from eclipse import *

diff --git a/source/braille.py b/source/braille.py
index d63c6c5..ea05d58 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/brailleDisplayDrivers/papenmeier.py
b/source/brailleDisplayDrivers/papenmeier.py
index 73ce726..ce5e1c8 100644
--- a/source/brailleDisplayDrivers/papenmeier.py
+++ b/source/brailleDisplayDrivers/papenmeier.py
@@ -511,7 +511,7 @@ class InputGesture(braille.BrailleDisplayGesture,
brailleInput.BrailleInputGestu

self.id=brl_join_keys(brl_decode_key_names_repeat(driver))
return

- if keys[0] == 'L' and driver._baud!=1:
+ if driver._baud!=1 and keys[0] == 'L':
#get dots
z = ord('0')
b = ord(keys[4])-z

diff --git a/source/characterProcessing.py b/source/characterProcessing.py
index 8235890..d31bba1 100644
--- a/source/characterProcessing.py
+++ b/source/characterProcessing.py
@@ -374,6 +374,7 @@ class SpeechSymbolProcessor(object):
# We need to merge symbol data from several sources.
sources = self.sources = []
builtin, user =
self.localeSymbols.fetchLocaleData(locale,fallback=False)
+ self.builtinSources = [builtin]
self.userSymbols = user
sources.append(user)
sources.append(builtin)
@@ -381,7 +382,9 @@ class SpeechSymbolProcessor(object):
# Always use English as a base.
if locale != "en":
# Only the builtin data.
-
sources.append(self.localeSymbols.fetchLocaleData("en")[0])
+ enBaseSymbols =
self.localeSymbols.fetchLocaleData("en")[0]
+ sources.append(enBaseSymbols)
+ self.builtinSources.append(enBaseSymbols)

# The computed symbol information from all sources.
symbols = self.computedSymbols = collections.OrderedDict()
@@ -524,7 +527,10 @@ class SpeechSymbolProcessor(object):
@rtype: bool
"""
identifier = newSymbol.identifier
- oldSymbol = self.computedSymbols[identifier]
+ try:
+ oldSymbol = self.computedSymbols[identifier]
+ except KeyError:
+ oldSymbol = None
if oldSymbol is newSymbol:
return False
try:
@@ -533,19 +539,19 @@ class SpeechSymbolProcessor(object):
userSymbol = SpeechSymbol(identifier)

changed = False
- if newSymbol.pattern != oldSymbol.pattern:
+ if oldSymbol and newSymbol.pattern != oldSymbol.pattern:
userSymbol.pattern = newSymbol.pattern
changed = True
- if newSymbol.replacement != oldSymbol.replacement:
+ if not oldSymbol or newSymbol.replacement !=
oldSymbol.replacement:
userSymbol.replacement = newSymbol.replacement
changed = True
- if newSymbol.level != oldSymbol.level:
+ if not oldSymbol or newSymbol.level != oldSymbol.level:
userSymbol.level = newSymbol.level
changed = True
- if newSymbol.preserve != oldSymbol.preserve:
+ if not oldSymbol or newSymbol.preserve != oldSymbol.preserve:
userSymbol.preserve = newSymbol.preserve
changed = True
- if newSymbol.displayName != oldSymbol.displayName:
+ if not oldSymbol or newSymbol.displayName !=
oldSymbol.displayName:
userSymbol.displayName = newSymbol.displayName
changed = True

@@ -556,6 +562,28 @@ class SpeechSymbolProcessor(object):
self.userSymbols.symbols[identifier] = userSymbol
return True

+ def deleteSymbol(self, symbol):
+ """Delete a user defined symbol.
+ If the symbol does not exist, this method simply does nothing.
+ These changes do not take effect until the symbol processor is
reinitialised.
+ @param symbol: The symbol to delete.
+ @type symbol: L{SpeechSymbol}
+ """
+ try:
+ del self.userSymbols.symbols[symbol.identifier]
+ except KeyError:
+ pass
+
+ def isBuiltin(self, symbolIdentifier):
+ """Determine whether a symbol is built in.
+ @param symbolIdentifier: The identifier of the symbol in
question.
+ @type symbolIdentifier: unicode
+ @return: C{True} if the symbol is built in,
+ C{False} if it was added by the user.
+ @rtype: bool
+ """
+ return any(symbolIdentifier in source.symbols for source in
self.builtinSources)
+
_localeSpeechSymbolProcessors = LocaleDataMap(SpeechSymbolProcessor)

def processSpeechSymbols(locale, text, level):

diff --git a/source/colors.py b/source/colors.py
index 1df103f..2fe4db3 100644
--- a/source/colors.py
+++ b/source/colors.py
@@ -88,13 +88,12 @@ RGBToNames={
#Standard 16 HTML 4 colors
# Translators: The color black.
RGB(0x00,0x00,0x00):_('black'),
- # Translators: The color green.
- RGB(0x00,0x80,0x00):_('green'),
+ # Translators: The color dark green.
+ RGB(0x00,0x80,0x00):_('dark green'),
# Translators: The light gray color.
RGB(0xc0,0xc0,0xc0):_('light grey'),
- # Translators: The color lime.
- # For more info see: http://en.wikipedia.org/wiki/Lime_%28color%29
- RGB(0x00,0xff,0x00):_('lime'),
+ # Translators: The color green (full brightness)
+ RGB(0x00,0xff,0x00):_('green'),
# Translators: The color gray (halfway between white and black).
RGB(0x80,0x80,0x80):_('grey'),
# Translators: the color olive.

diff --git a/source/config/__init__.py b/source/config/__init__.py
index c02396d..26a2934 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -418,6 +418,8 @@ def addConfigDirsToPythonPackagePath(module, subdir=None):
@param subdir: The subdirectory to be used, C{None} for the name of
C{module}.
@type subdir: str
"""
+ if globalVars.appArgs.disableAddons:
+ return
if not subdir:
subdir = module.__name__
# Python 2.x doesn't properly handle unicode import paths, so convert
them.

diff --git a/source/core.py b/source/core.py
index ad7be89..8f5a5f7 100644
--- a/source/core.py
+++ b/source/core.py
@@ -62,7 +62,7 @@ def doStartupDialogs():
from gui import upgradeAlerts
upgradeAlerts.NewLaptopKeyboardLayout.run()

-def restart():
+def restart(disableAddons=False):
"""Restarts NVDA by starting a new copy with -r."""
if globalVars.appArgs.launcher:
import wx
@@ -71,9 +71,20 @@ def restart():
return
import subprocess
import shellapi
+ options=[]
+ try:
+ sys.argv.index('-r')
+ except:
+ options.append("-r")
+ try:
+ sys.argv.pop(sys.argv.index('--disable-addons'))
+ except:
+ pass
+ if disableAddons:
+ options.append('--disable-addons')
shellapi.ShellExecute(None, None,
sys.executable.decode("mbcs"),
- subprocess.list2cmdline(sys.argv + ["-r"]).decode("mbcs"),
+ subprocess.list2cmdline(sys.argv + options).decode("mbcs"),
None, 0)

def resetConfiguration(factoryDefaults=False):

diff --git a/source/cursorManager.py b/source/cursorManager.py
index d4aae44..87fb5b2 100644
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -1,6 +1,6 @@
#cursorManager.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2012 NVDA Contributors
+#Copyright (C) 2006-2014 NVDA Contributors
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -23,6 +23,47 @@ import braille
import controlTypes
from inputCore import SCRCAT_BROWSEMODE

+class FindDialog(wx.Dialog):
+ """A dialog used to specify text to find in a cursor manager.
+ """
+
+ def __init__(self, parent, cursorManager, text):
+ # Translators: Title of a dialog to find text.
+ super(FindDialog, self).__init__(parent, wx.ID_ANY, _("Find"))
+ # Have a copy of the active cursor manager, as this is needed
later for finding text.
+ self.activeCursorManager = cursorManager
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ findSizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: Dialog text for NvDA's find command.
+ textToFind = wx.StaticText(self, wx.ID_ANY, label=_("Type the
text you wish to find"))
+ findSizer.Add(textToFind)
+ self.findTextField = wx.TextCtrl(self, wx.ID_ANY)
+ self.findTextField.SetValue(text)
+ findSizer.Add(self.findTextField)
+ mainSizer.Add(findSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+ # Translators: An option in find dialog to perform
case-sensitive search.
+
self.caseSensitiveCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Case
&sensitive"))
+ self.caseSensitiveCheckBox.SetValue(False)
+
mainSizer.Add(self.caseSensitiveCheckBox,border=10,flag=wx.BOTTOM)
+
+ mainSizer.AddSizer(self.CreateButtonSizer(wx.OK|wx.CANCEL))
+ self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK)
+ self.Bind(wx.EVT_BUTTON,self.onCancel,id=wx.ID_CANCEL)
+ mainSizer.Fit(self)
+ self.SetSizer(mainSizer)
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+ self.findTextField.SetFocus()
+
+ def onOk(self, evt):
+ text = self.findTextField.GetValue()
+ caseSensitive = self.caseSensitiveCheckBox.GetValue()
+ wx.CallLater(100, self.activeCursorManager.doFindText, text,
caseSensitive=caseSensitive)
+ self.Destroy()
+
+ def onCancel(self, evt):
+ self.Destroy()
+
class CursorManager(baseObject.ScriptableObject):
"""
A mix-in providing caret navigation and selection commands for the
object's virtual text range.
@@ -84,24 +125,11 @@ class CursorManager(baseObject.ScriptableObject):
if not oldInfo.isCollapsed:
speech.speakSelectionChange(oldInfo,self.selection)

- def doFindTextDialog(self):
- d = wx.TextEntryDialog(gui.mainFrame,
- # Translators: Dialog text for NvDA's find command.
- _("Type the text you wish to find"),
- # Translators: Title of a dialog to find text.
- _("Find"),
- defaultValue=self._lastFindText)
- def callback(result):
- if result == wx.ID_OK:
- # Make sure this happens after focus returns to
the document.
- wx.CallLater(100, self.doFindText, d.GetValue())
- gui.runScriptModalDialog(d, callback)
-
- def doFindText(self,text,reverse=False):
+ def doFindText(self,text,reverse=False,caseSensitive=False):
if not text:
return
info=self.makeTextInfo(textInfos.POSITION_CARET)
- res=info.find(text,reverse=reverse)
+ res=info.find(text,reverse=reverse,caseSensitive=caseSensitive)
if res:
self.selection=info
speech.cancelSpeech()
@@ -111,14 +139,17 @@ class CursorManager(baseObject.ScriptableObject):
wx.CallAfter(gui.messageBox,_('text "%s" not
found')%text,_("Find Error"),wx.OK|wx.ICON_ERROR)
CursorManager._lastFindText=text

- def script_find(self,gesture):
- self.doFindTextDialog()
+ def script_find(self,gesture):
+ d = FindDialog(gui.mainFrame, self, self._lastFindText)
+ gui.mainFrame.prePopup()
+ d.Show()
+ gui.mainFrame.postPopup()
# Translators: Input help message for NVDA's find command.
script_find.__doc__ = _("find a text string from the current cursor
position")

def script_findNext(self,gesture):
if not self._lastFindText:
- self.doFindTextDialog()
+ self.script_find(gesture)
return
self.doFindText(self._lastFindText)
# Translators: Input help message for find next command.
@@ -126,7 +157,7 @@ class CursorManager(baseObject.ScriptableObject):

def script_findPrevious(self,gesture):
if not self._lastFindText:
- self.doFindTextDialog()
+ self.script_find(gesture)
return
self.doFindText(self._lastFindText,reverse=True)
# Translators: Input help message for find previous command.

diff --git a/source/gui/__init__.py b/source/gui/__init__.py
index 5929f08..0007701 100644
--- a/source/gui/__init__.py
+++ b/source/gui/__init__.py
@@ -11,6 +11,7 @@ import sys
import threading
import codecs
import ctypes
+import weakref
import wx
import globalVars
import tones
@@ -192,16 +193,13 @@ class MainFrame(wx.Frame):
self._popupSettingsDialog(DictionaryDialog,_("Temporary
dictionary"),speechDictHandler.dictionaries["temp"])

def onExitCommand(self, evt):
- canExit=False
if config.conf["general"]["askToExit"]:
- if isInMessageBox:
- return
- # Translators: Message shown to ask if user really
wishes to quit NVDA.
- if messageBox(_("Are you sure you want to quit NVDA?"),
_("Exit NVDA"), wx.YES_NO|wx.ICON_WARNING) == wx.YES:
- canExit=True
+ self.prePopup()
+ d = ExitDialog(self)
+ d.Raise()
+ d.Show()
+ self.postPopup()
else:
- canExit=True
- if canExit:
wx.GetApp().ExitMainLoop()

def onGeneralSettingsCommand(self,evt):
@@ -458,6 +456,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):
@@ -581,6 +580,7 @@ class WelcomeDialog(wx.Dialog):
self.SetSizer(mainSizer)
mainSizer.Fit(self)
self.capsAsNVDAModifierCheckBox.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onOk(self, evt):
config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"] =
self.capsAsNVDAModifierCheckBox.IsChecked()
@@ -651,6 +651,7 @@ class LauncherDialog(wx.Dialog):

self.Sizer = mainSizer
mainSizer.Fit(self)
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onLicenseAgree(self, evt):
for ctrl in self.actionButtons:
@@ -677,6 +678,69 @@ class LauncherDialog(wx.Dialog):
d.Show()
mainFrame.postPopup()

+class ExitDialog(wx.Dialog):
+ _instance = None
+
+ def __new__(cls, parent):
+ # Make this a singleton.
+ inst = cls._instance() if cls._instance else None
+ if not inst:
+ return super(cls, cls).__new__(cls, parent)
+ return inst
+
+ def __init__(self, parent):
+ inst = ExitDialog._instance() if ExitDialog._instance else None
+ if inst:
+ return
+ # Use a weakref so the instance can die.
+ ExitDialog._instance = weakref.ref(self)
+ # Translators: The title of the dialog to exit NVDA
+ super(ExitDialog, self).__init__(parent, title=_("Exit NVDA"))
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ if globalVars.appArgs.disableAddons:
+ # Translators: A message in the exit Dialog shown when
all add-ons are disabled.
+ addonsDisabledLabel=wx.StaticText(self,-1,label=_("All
add-ons are now disabled. They will be re-enabled on the next restart unless
you choose to disable them again."))
+ mainSizer.Add(addonsDisabledLabel)
+
+ actionSizer=wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: The label for actions list in the Exit dialog.
+ actionsLabel=wx.StaticText(self,-1,label=_("What would you like
to &do?"))
+ actionSizer.Add(actionsLabel)
+ actionsListID=wx.NewId()
+ self.actions = [
+ # Translators: An option in the combo box to choose exit action.
+ _("Exit"),
+ # Translators: An option in the combo box to choose exit action.
+ _("Restart"),
+ # Translators: An option in the combo box to choose exit action.
+ _("Restart with add-ons disabled")]
+
self.actionsList=wx.Choice(self,actionsListID,choices=self.actions)
+ self.actionsList.SetSelection(0)
+ actionSizer.Add(self.actionsList)
+ mainSizer.Add(actionSizer,border=10,flag=wx.CENTER)
+
+ mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
+ self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
+ self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)
+ mainSizer.Fit(self)
+ self.Sizer = mainSizer
+ self.actionsList.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
+ def onOk(self, evt):
+ action=self.actionsList.GetSelection()
+ if action == 0:
+ wx.GetApp().ExitMainLoop()
+ elif action == 1:
+
queueHandler.queueFunction(queueHandler.eventQueue,core.restart)
+ elif action == 2:
+
queueHandler.queueFunction(queueHandler.eventQueue,core.restart,True)
+ self.Destroy()
+
+ def onCancel(self, evt):
+ self.Destroy()
+
class ExecAndPump(threading.Thread):
"""Executes the given function with given args and kwargs in a
background thread while blocking and pumping in the current thread."""

@@ -713,6 +777,7 @@ class IndeterminateProgressDialog(wx.ProgressDialog):
self.timer = wx.PyTimer(self.Pulse)
self.timer.Start(1000)
self.Raise()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def Pulse(self):
super(IndeterminateProgressDialog, self).Pulse()

diff --git a/source/gui/addonGui.py b/source/gui/addonGui.py
index 76a1bd6..2c687ba 100644
--- a/source/gui/addonGui.py
+++ b/source/gui/addonGui.py
@@ -11,6 +11,7 @@ import languageHandler
import gui
from logHandler import log
import addonHandler
+import globalVars

class AddonsDialog(wx.Dialog):
_instance = None
@@ -29,6 +30,10 @@ class AddonsDialog(wx.Dialog):
mainSizer=wx.BoxSizer(wx.VERTICAL)
settingsSizer=wx.BoxSizer(wx.VERTICAL)
entriesSizer=wx.BoxSizer(wx.VERTICAL)
+ if globalVars.appArgs.disableAddons:
+ # Translators: A message in the add-ons manager shown
when all add-ons are disabled.
+ addonsDisabledLabel=wx.StaticText(self,-1,label=_("All
add-ons are now disabled. To enable add-ons you must restart NVDA."))
+ mainSizer.Add(addonsDisabledLabel)
# Translators: the label for the installed addons list in the
addons manager.
entriesLabel=wx.StaticText(self,-1,label=_("Installed Add-ons"))
entriesSizer.Add(entriesLabel)
@@ -82,6 +87,7 @@ class AddonsDialog(wx.Dialog):
self.SetSizer(mainSizer)
self.refreshAddonsList()
self.addonsList.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def OnAddClick(self,evt):
# Translators: The message displayed in the dialog that allows
you to choose an add-on package for installation.
@@ -170,6 +176,9 @@ class AddonsDialog(wx.Dialog):
elif addon.isPendingRemove:
# Translators: The status shown for an addon that has
been marked as removed, before NVDA has been restarted.
return _("remove")
+ elif globalVars.appArgs.disableAddons:
+ # Translators: The status shown for an addon when its
currently suspended do to addons been disabled.
+ return _("suspended")
else:
# Translators: The status shown for an addon when its
currently running in NVDA.
return _("running")

diff --git a/source/gui/configProfiles.py b/source/gui/configProfiles.py
index 4be9f10..04d79c3 100644
--- a/source/gui/configProfiles.py
+++ b/source/gui/configProfiles.py
@@ -92,6 +92,7 @@ class ProfilesDialog(wx.Dialog):
mainSizer.Fit(self)
self.Sizer = mainSizer
self.profileList.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def __del__(self):
ProfilesDialog._instance = None
@@ -326,6 +327,7 @@ class TriggersDialog(wx.Dialog):
self.onTriggerListChoice(None)
mainSizer.Fit(self)
self.Sizer = mainSizer
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onTriggerListChoice(self, evt):
trig = self.triggers[self.triggerList.Selection]
@@ -387,6 +389,7 @@ class NewProfileDialog(wx.Dialog):
mainSizer.Fit(self)
self.Sizer = mainSizer
self.profileName.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onOk(self, evt):
confTrigs = config.conf.triggersToProfiles

diff --git a/source/gui/installerGui.py b/source/gui/installerGui.py
index dd51adf..dc192c6 100644
--- a/source/gui/installerGui.py
+++ b/source/gui/installerGui.py
@@ -128,6 +128,7 @@ class InstallerDialog(wx.Dialog):

self.Sizer = mainSizer
mainSizer.Fit(self)
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onInstall(self, evt):
self.Hide()
@@ -177,6 +178,7 @@ class PortableCreaterDialog(wx.Dialog):

self.Sizer = mainSizer
mainSizer.Fit(self)
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onBrowseForPortableDirectory(self, evt):
# Translators: The title of the dialog presented when browsing
for the

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index c833bf0..8171f9c 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -1,12 +1,14 @@
+# -*- coding: UTF-8 -*-
#settingsDialogs.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

import glob
import os
import copy
+import re
import wx
import winUser
import logHandler
@@ -78,6 +80,7 @@ class SettingsDialog(wx.Dialog):
self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK)
self.Bind(wx.EVT_BUTTON,self.onCancel,id=wx.ID_CANCEL)
self.postInit()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def __del__(self):
SettingsDialog._hasInstance=False
@@ -150,8 +153,8 @@ class GeneralSettingsDialog(SettingsDialog):
if globalVars.appArgs.secure:
self.saveOnExitCheckBox.Disable()

settingsSizer.Add(self.saveOnExitCheckBox,border=10,flag=wx.BOTTOM)
- # Translators: The label for a setting in general settings to
ask before quitting NVDA (if not checked, NVDA will exit without asking the
user for confirmation).
-
self.askToExitCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Warn before
exiting NVDA"))
+ # Translators: The label for a setting in general settings to
ask before quitting NVDA (if not checked, NVDA will exit without asking the
user for action).
+
self.askToExitCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Sho&w exit options
when exiting NVDA"))

self.askToExitCheckBox.SetValue(config.conf["general"]["askToExit"])

settingsSizer.Add(self.askToExitCheckBox,border=10,flag=wx.BOTTOM)
# Translators: The label for a setting in general settings to
play sounds when NVDA starts or exits.
@@ -1048,7 +1051,7 @@ class DocumentFormattingDialog(SettingsDialog):
settingsSizer.Add(self.styleCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
# document formatting settings dialog.
-
self.spellingErrorsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report
spelling errors"))
+
self.spellingErrorsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report
spelling e&rrors"))

self.spellingErrorsCheckBox.SetValue(config.conf["documentFormatting"]["reportSpellingErrors"])

settingsSizer.Add(self.spellingErrorsCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
@@ -1153,6 +1156,15 @@ class DocumentFormattingDialog(SettingsDialog):
super(DocumentFormattingDialog, self).onOk(evt)

class DictionaryEntryDialog(wx.Dialog):
+ TYPE_LABELS = {
+ # Translators: This is a label for an Entry Type radio button
in add dictionary entry dialog.
+ speechDictHandler.ENTRY_TYPE_ANYWHERE: _("&Anywhere"),
+ # Translators: This is a label for an Entry Type radio button
in add dictionary entry dialog.
+ speechDictHandler.ENTRY_TYPE_WORD: _("Whole &word"),
+ # Translators: This is a label for an Entry Type radio button
in add dictionary entry dialog.
+ speechDictHandler.ENTRY_TYPE_REGEXP: _("&Regular expression")
+ }
+ TYPE_LABELS_ORDERING = (speechDictHandler.ENTRY_TYPE_ANYWHERE,
speechDictHandler.ENTRY_TYPE_WORD, speechDictHandler.ENTRY_TYPE_REGEXP)

# Translators: This is the label for the edit dictionary entry dialog.
def __init__(self, parent, title=_("Edit Dictionary Entry")):
@@ -1174,17 +1186,29 @@ class DictionaryEntryDialog(wx.Dialog):
# Translators: This is a label for a checkbox in add dictionary
entry dialog.

self.caseSensitiveCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Case
&sensitive"))
settingsSizer.Add(self.caseSensitiveCheckBox)
- # Translators: This is a label for a checkbox in add dictionary
entry dialog.
-
self.regexpCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Regular &expression"))
- settingsSizer.Add(self.regexpCheckBox)
+
+ # Translators: This is a label for a set of radio buttons in
add dictionary entry dialog.
+ self.typeRadioBox=wx.RadioBox(self,wx.NewId(),label=_("&Type"),
choices=[DictionaryEntryDialog.TYPE_LABELS[i] for i in
DictionaryEntryDialog.TYPE_LABELS_ORDERING])
+ settingsSizer.Add(self.typeRadioBox)

mainSizer.Add(settingsSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
buttonSizer=self.CreateButtonSizer(wx.OK|wx.CANCEL)

mainSizer.Add(buttonSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.BOTTOM)
mainSizer.Fit(self)
self.SetSizer(mainSizer)
+ self.setType(speechDictHandler.ENTRY_TYPE_ANYWHERE)
self.patternTextCtrl.SetFocus()

+ def getType(self):
+ typeRadioValue = self.typeRadioBox.GetSelection()
+ if typeRadioValue == wx.NOT_FOUND:
+ return speechDictHandler.ENTRY_TYPE_ANYWHERE
+ return
DictionaryEntryDialog.TYPE_LABELS_ORDERING[typeRadioValue]
+
+ def setType(self, type):
+
self.typeRadioBox.SetSelection(DictionaryEntryDialog.TYPE_LABELS_ORDERING.index(type))
+
class DictionaryDialog(SettingsDialog):
+ TYPE_LABELS = {t: l.replace("&", "") for t, l in
DictionaryEntryDialog.TYPE_LABELS.iteritems()}

def __init__(self,parent,title,speechDict):
self.title = title
@@ -1209,11 +1233,11 @@ class DictionaryDialog(SettingsDialog):
self.dictList.InsertColumn(2,_("Replacement"),width=150)
# Translators: The label for a column in dictionary entries
list used to identify whether the entry is case sensitive or not.
self.dictList.InsertColumn(3,_("case"),width=50)
- # Translators: The label for a column in dictionary entries
list used to identify whether the entry is a regular expression or not.
- self.dictList.InsertColumn(4,_("Regexp"),width=50)
+ # Translators: The label for a column in dictionary entries
list used to identify whether the entry is a regular expression, matches whole
words, or matches anywhere.
+ self.dictList.InsertColumn(4,_("Type"),width=50)
self.offOn = (_("off"),_("on"))
for entry in self.tempSpeechDict:
-
self.dictList.Append((entry.comment,entry.pattern,entry.replacement,self.offOn[int(entry.caseSensitive)],self.offOn[int(entry.regexp)]))
+
self.dictList.Append((entry.comment,entry.pattern,entry.replacement,self.offOn[int(entry.caseSensitive)],DictionaryDialog.TYPE_LABELS[entry.type]))
self.editingIndex=-1
entriesSizer.Add(self.dictList,proportion=8)
settingsSizer.Add(entriesSizer)
@@ -1253,8 +1277,8 @@ class DictionaryDialog(SettingsDialog):
# Translators: This is the label for the add dictionary entry
dialog.
entryDialog=DictionaryEntryDialog(self,title=_("Add Dictionary
Entry"))
if entryDialog.ShowModal()==wx.ID_OK:
-
self.tempSpeechDict.append(speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),bool(entryDialog.regexpCheckBox.GetValue())))
-
self.dictList.Append((entryDialog.commentTextCtrl.GetValue(),entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())],self.offOn[int(entryDialog.regexpCheckBox.GetValue())]))
+
self.tempSpeechDict.append(speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),entryDialog.getType()))
+
self.dictList.Append((entryDialog.commentTextCtrl.GetValue(),entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())],DictionaryDialog.TYPE_LABELS[entryDialog.getType()]))
index=self.dictList.GetFirstSelected()
while index>=0:
self.dictList.Select(index,on=0)
@@ -1276,14 +1300,14 @@ class DictionaryDialog(SettingsDialog):

entryDialog.replacementTextCtrl.SetValue(self.tempSpeechDict[editIndex].replacement)

entryDialog.commentTextCtrl.SetValue(self.tempSpeechDict[editIndex].comment)

entryDialog.caseSensitiveCheckBox.SetValue(self.tempSpeechDict[editIndex].caseSensitive)
-
entryDialog.regexpCheckBox.SetValue(self.tempSpeechDict[editIndex].regexp)
+ entryDialog.setType(self.tempSpeechDict[editIndex].type)
if entryDialog.ShowModal()==wx.ID_OK:
-
self.tempSpeechDict[editIndex]=speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),bool(entryDialog.regexpCheckBox.GetValue()))
+
self.tempSpeechDict[editIndex]=speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),entryDialog.getType())

self.dictList.SetStringItem(editIndex,0,entryDialog.commentTextCtrl.GetValue())

self.dictList.SetStringItem(editIndex,1,entryDialog.patternTextCtrl.GetValue())

self.dictList.SetStringItem(editIndex,2,entryDialog.replacementTextCtrl.GetValue())

self.dictList.SetStringItem(editIndex,3,self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())])
-
self.dictList.SetStringItem(editIndex,4,self.offOn[int(entryDialog.regexpCheckBox.GetValue())])
+
self.dictList.SetStringItem(editIndex,4,DictionaryDialog.TYPE_LABELS[entryDialog.getType()])
self.dictList.SetFocus()
entryDialog.Destroy()

@@ -1459,6 +1483,25 @@ class BrailleSettingsDialog(SettingsDialog):
enable = len(self.possiblePorts) > 0 and not
(len(self.possiblePorts) == 1 and self.possiblePorts[0][0] == "auto")
self.portsList.Enable(enable)

+class AddSymbolDialog(wx.Dialog):
+
+ def __init__(self, parent):
+ # Translators: This is the label for the add symbol dialog.
+ super(AddSymbolDialog,self).__init__(parent, title=_("Add
Symbol"))
+ mainSizer=wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: This is the label for the edit field in the add
symbol dialog.
+ sizer.Add(wx.StaticText(self, label=_("Symbol:")))
+ self.identifierTextCtrl = wx.TextCtrl(self)
+ sizer.Add(self.identifierTextCtrl)
+ mainSizer.Add(sizer, border=20, flag=wx.LEFT | wx.RIGHT |
wx.TOP)
+ buttonSizer=self.CreateButtonSizer(wx.OK | wx.CANCEL)
+ mainSizer.Add(buttonSizer, border=20, flag=wx.LEFT | wx.RIGHT |
wx.BOTTOM)
+ mainSizer.Fit(self)
+ self.SetSizer(mainSizer)
+ self.identifierTextCtrl.SetFocus()
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
class SpeechSymbolsDialog(SettingsDialog):
# Translators: This is the label for the symbol pronunciation dialog.
title = _("Symbol Pronunciation")
@@ -1470,6 +1513,7 @@ class SpeechSymbolsDialog(SettingsDialog):
symbolProcessor =
characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData("en")
self.symbolProcessor = symbolProcessor
symbols = self.symbols = [copy.copy(symbol) for symbol in
self.symbolProcessor.computedSymbols.itervalues()]
+ self.pendingRemovals = {}

sizer = wx.BoxSizer(wx.HORIZONTAL)
# Translators: The label for symbols list in symbol
pronunciation dialog.
@@ -1506,6 +1550,17 @@ class SpeechSymbolsDialog(SettingsDialog):
sizer.Add(self.levelList)
changeSizer.Add(sizer)
settingsSizer.Add(changeSizer)
+ entryButtonsSizer=wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: The label for a button in the Symbol
Pronunciation dialog to add a new symbol.
+ addButton = wx.Button(self, label=_("&Add"))
+ entryButtonsSizer.Add(addButton)
+ # Translators: The label for a button in the Symbol
Pronunciation dialog to remove a symbol.
+ self.removeButton = wx.Button(self, label=_("Re&move"))
+ self.removeButton.Disable()
+ entryButtonsSizer.Add(self.removeButton)
+ addButton.Bind(wx.EVT_BUTTON, self.OnAddClick)
+ self.removeButton.Bind(wx.EVT_BUTTON, self.OnRemoveClick)
+ settingsSizer.Add(entryButtonsSizer)

self.editingItem = None

@@ -1533,6 +1588,7 @@ class SpeechSymbolsDialog(SettingsDialog):
self.editingItem = item
self.replacementEdit.Value = symbol.replacement
self.levelList.Selection =
characterProcessing.SPEECH_SYMBOL_LEVELS.index(symbol.level)
+ self.removeButton.Enabled = not
self.symbolProcessor.isBuiltin(symbol.identifier)

def onListChar(self, evt):
if evt.KeyCode == wx.WXK_RETURN:
@@ -1545,10 +1601,60 @@ class SpeechSymbolsDialog(SettingsDialog):
else:
evt.Skip()

+ def OnAddClick(self, evt):
+ with AddSymbolDialog(self) as entryDialog:
+ if entryDialog.ShowModal() != wx.ID_OK:
+ return
+ identifier = entryDialog.identifierTextCtrl.GetValue()
+ if not identifier:
+ return
+ for index, symbol in enumerate(self.symbols):
+ if identifier == symbol.identifier:
+ # Translators: An error reported in the Symbol
Pronunciation dialog when adding a symbol that is already present.
+ gui.messageBox(_('Symbol "%s" is already
present.') % identifier,
+ _("Error"), wx.OK | wx.ICON_ERROR)
+ self.symbolsList.Select(index)
+ self.symbolsList.Focus(index)
+ self.symbolsList.SetFocus()
+ return
+ addedSymbol = characterProcessing.SpeechSymbol(identifier)
+ try:
+ del self.pendingRemovals[identifier]
+ except KeyError:
+ pass
+ addedSymbol.displayName = identifier
+ addedSymbol.replacement = ""
+ addedSymbol.level = characterProcessing.SYMLVL_ALL
+ self.symbols.append(addedSymbol)
+ item = self.symbolsList.Append((addedSymbol.displayName,))
+ self.updateListItem(item, addedSymbol)
+ self.symbolsList.Select(item)
+ self.symbolsList.Focus(item)
+ self.symbolsList.SetFocus()
+
+ def OnRemoveClick(self, evt):
+ index = self.symbolsList.GetFirstSelected()
+ symbol = self.symbols[index]
+ self.pendingRemovals[symbol.identifier] = symbol
+ # Deleting from self.symbolsList focuses the next item before
deleting,
+ # so it must be done *before* we delete from self.symbols.
+ self.symbolsList.DeleteItem(index)
+ del self.symbols[index]
+ index = min(index, self.symbolsList.ItemCount - 1)
+ self.symbolsList.Select(index)
+ self.symbolsList.Focus(index)
+ # We don't get a new focus event with the new index, so set
editingItem.
+ self.editingItem = index
+ self.symbolsList.SetFocus()
+
def onOk(self, evt):
self.onSymbolEdited(None)
self.editingItem = None
+ for symbol in self.pendingRemovals.itervalues():
+ self.symbolProcessor.deleteSymbol(symbol)
for symbol in self.symbols:
+ if not symbol.replacement:
+ continue
self.symbolProcessor.updateSymbol(symbol)
try:
self.symbolProcessor.userSymbols.save()
@@ -1562,22 +1668,18 @@ class InputGesturesDialog(SettingsDialog):
title = _("Input Gestures")

def makeSettings(self, settingsSizer):
+ # Translators: The label of a text field to search for gestures
in the Input Gestures dialog.
+ settingsSizer.Add(wx.StaticText(self,
label=pgettext("inputGestures", "&Filter by:")))
+ filter = wx.TextCtrl(self)
+ filter.Bind(wx.EVT_TEXT, self.onFilterChange, filter)
+ settingsSizer.Add(filter)
tree = self.tree = wx.TreeCtrl(self, style=wx.TR_HAS_BUTTONS |
wx.TR_HIDE_ROOT | wx.TR_SINGLE)
self.treeRoot = tree.AddRoot("root")
tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.onTreeSelect)
settingsSizer.Add(tree, proportion=7, flag=wx.EXPAND)

- gestures =
inputCore.manager.getAllGestureMappings(obj=gui.mainFrame.prevFocus,
ancestors=gui.mainFrame.prevFocusAncestors)
- for category in sorted(gestures):
- treeCat = tree.AppendItem(self.treeRoot, category)
- commands = gestures[category]
- for command in sorted(commands):
- treeCom = tree.AppendItem(treeCat, command)
- commandInfo = commands[command]
- tree.SetItemPyData(treeCom, commandInfo)
- for gesture in commandInfo.gestures:
- treeGes = tree.AppendItem(treeCom,
self._formatGesture(gesture))
- tree.SetItemPyData(treeGes, gesture)
+ self.gestures =
inputCore.manager.getAllGestureMappings(obj=gui.mainFrame.prevFocus,
ancestors=gui.mainFrame.prevFocusAncestors)
+ self.populateTree()

sizer = wx.BoxSizer(wx.HORIZONTAL)
# Translators: The label of a button to add a gesture in the
Input Gestures dialog.
@@ -1597,6 +1699,32 @@ class InputGesturesDialog(SettingsDialog):
def postInit(self):
self.tree.SetFocus()

+ def populateTree(self, filter=''):
+ if filter:
+ #This regexp uses a positive lookahead (?=...) for
every word in the filter, which just makes sure the word is present in the
string to be tested without matching position or order.
+ filterReg = re.compile(r'(?=.*?' +
r')(?=.*?'.join(filter.split(' ')) + r')', re.U|re.IGNORECASE)
+ for category in sorted(self.gestures):
+ treeCat = self.tree.AppendItem(self.treeRoot, category)
+ commands = self.gestures[category]
+ for command in sorted(commands):
+ if filter and not filterReg.match(command):
+ continue
+ treeCom = self.tree.AppendItem(treeCat, command)
+ commandInfo = commands[command]
+ self.tree.SetItemPyData(treeCom, commandInfo)
+ for gesture in commandInfo.gestures:
+ treeGes = self.tree.AppendItem(treeCom,
self._formatGesture(gesture))
+ self.tree.SetItemPyData(treeGes,
gesture)
+ if not self.tree.ItemHasChildren(treeCat):
+ self.tree.Delete(treeCat)
+ elif filter:
+ self.tree.Expand(treeCat)
+
+ def onFilterChange(self, evt):
+ filter=evt.GetEventObject().GetValue()
+ self.tree.DeleteChildren(self.treeRoot)
+ self.populateTree(filter)
+
def _formatGesture(self, identifier):
try:
source, main =
inputCore.getDisplayTextForGestureIdentifier(identifier)
@@ -1667,6 +1795,7 @@ class InputGesturesDialog(SettingsDialog):
self.pendingAdds.add(entry)
self.tree.SetItemText(treeGes, disp)
self.tree.SetItemPyData(treeGes, gid)
+ scriptInfo.gestures.append(gid)
self.onTreeSelect(None)

def onRemove(self, evt):
@@ -1681,6 +1810,7 @@ class InputGesturesDialog(SettingsDialog):
except KeyError:
self.pendingRemoves.add(entry)
self.tree.Delete(treeGes)
+ scriptInfo.gestures.remove(gesture)
self.tree.SetFocus()

def onOk(self, evt):

diff --git a/source/gui/upgradeAlerts.py b/source/gui/upgradeAlerts.py
index 354104d..04364da 100644
--- a/source/gui/upgradeAlerts.py
+++ b/source/gui/upgradeAlerts.py
@@ -39,6 +39,7 @@ class NewLaptopKeyboardLayout(wx.Dialog):
whatsNewButton.SetFocus()
self.Sizer = mainSizer
mainSizer.Fit(self)
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

def onClose(self, evt):
config.conf["upgrade"]["newLaptopKeyboardLayout"] = True

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,

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/9f48eb4763a1/
Changeset: 9f48eb4763a1
Branch: None
User: josephsl
Date: 2014-12-16 00:52:42+00:00
Summary: Global Commands: look up touch labels map for the new touch mode
before resorting to presenting the label from the touch modes list. re #4699.

Affected #: 1 file

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 4358436..b63d468 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -1340,8 +1340,12 @@ class GlobalCommands(ScriptableObject):
index=(index+1)%len(touchHandler.availableTouchModes)
newMode=touchHandler.availableTouchModes[index]
touchHandler.handler._curTouchMode=newMode
- # Translators: Cycles through available touch modes (a group of
related touch gestures; example output: "object mode"; see the user guide for
more information on touch modes).
- ui.message(_("%s mode")%newMode)
+ try:
+ newModeLabel=touchHandler.touchModeLabels[newMode]
+ except KeyError:
+ # Translators: Cycles through available touch modes (a
group of related touch gestures; example output: "object mode"; see the user
guide for more information on touch modes).
+ newModeLabel=_("%s mode")%newMode
+ ui.message(newModeLabel)
# Translators: Input help mode message for a touchscreen gesture.
script_touch_changeMode.__doc__=_("cycles between available touch
modes")
script_touch_changeMode.category=SCRCAT_TOUCH


https://bitbucket.org/nvdaaddonteam/nvda/commits/a3193ab4471e/
Changeset: a3193ab4471e
Branch: None
User: josephsl
Date: 2014-12-29 22:25:00+00:00
Summary: Target Windows 10 using its GUID. re #4760
Starting with Windows 8.1, Microsoft recommends developers to use ap manifests
to specify OS compatibility instead of relying on version info tuple (which
Python returns via Windows API). This was used for fixing ticket 3793
(targeting Windows 8.).
This also applies to Windows 10 in that it has its oww GUID. Without this
Windows 10 tells NVDA that it is Windows 8.1 (NT6.3, not NT6.4/10.0). Thus the
new GUID for Windows 10 was added to declare that NVDA supports Windows 10.

Affected #: 1 file

diff --git a/source/setup.py b/source/setup.py
index b27e129..5b4a1d8 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-2014 NV Access Limited, Peter Vágner
+#Copyright (C) 2006-2015 NV Access Limited, Peter Vágner, Joseph Lee
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -54,6 +54,8 @@ MAIN_MANIFEST_EXTRA = r"""
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><!--
Windows 8.1 --><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 10 -->
+ <supportedOS
Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility>
"""


https://bitbucket.org/nvdaaddonteam/nvda/commits/88678f48b793/
Changeset: 88678f48b793
Branch: None
User: jteh
Date: 2015-01-14 05:54:25+00:00
Summary: MathPlayer: Adjust parsing to reflect recent SSML fixes in
MathPlayer.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index b346e8a..a4e759d 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -20,13 +20,13 @@ import mathPres
RE_MP_SPEECH = re.compile(
# Break.
r"<break time='(?P<break>\d+)ms'/> ?"
- # Pronunciation for the character "a".
- ur"|(?P<charA><phoneme alphabet='ipa' ph='æ'> eh</phoneme>) ?"
+ # Pronunciation of characters.
+ ur"|<say-as interpret-as='characters'>(?P<char>[^<])</say-as> ?"
# Specific pronunciation.
ur"|<phoneme alphabet='ipa' ph='(?P<ipa>[^']+)'> (?P<phonemeText>[^
<]+)</phoneme> ?"
# Prosody.
- r"|<prosidy(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)'%)?(?: rate='(?P<rate>\d+)'%)?> ?"
- r"|(?P<prosodyReset></prosidy>) ?"
+ r"|<prosody(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
+ r"|(?P<prosodyReset></prosody>) ?"
# Other tags, which we don't care about.
r"|<[^>]+> ?"
# Commas indicating pauses in navigation messages.
@@ -44,9 +44,9 @@ def _processMpSpeech(text):
for m in RE_MP_SPEECH.finditer(text):
if m.lastgroup == "break":

out.append(speech.BreakCommand(time=int(m.group("break"))))
- elif m.lastgroup == "charA":
+ elif m.lastgroup == "char":
out.extend((speech.CharacterModeCommand(True),
- "a", speech.CharacterModeCommand(False)))
+ m.group("char"),
speech.CharacterModeCommand(False)))
elif m.lastgroup == "comma":
out.append(speech.BreakCommand(time=100))
elif m.lastgroup in PROSODY_COMMANDS:


https://bitbucket.org/nvdaaddonteam/nvda/commits/c163eacde5c8/
Changeset: c163eacde5c8
Branch: None
User: jteh
Date: 2015-01-14 07:33:26+00:00
Summary: MathPlayer: Scale pauses assuming that rate 0% is 80 wpm and 100%
is 450 wpm.

This obviously isn't going to be the same for all synths, but it's probably the
best we can do given that not all synths support wpm.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index a4e759d..a6b7c79 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -39,11 +39,16 @@ PROSODY_COMMANDS = {
"rate": speech.RateCommand,
}
def _processMpSpeech(text):
+ # MathPlayer's default rate is 180 wpm.
+ # Assume that 0% is 80 wpm and 100% is 450 wpm and scale accordingly.
+ synth = speech.getSynth()
+ wpm = synth._percentToParam(synth.rate, 80, 450)
+ breakMulti = 180.0 / wpm
out = []
resetProsody = set()
for m in RE_MP_SPEECH.finditer(text):
if m.lastgroup == "break":
-
out.append(speech.BreakCommand(time=int(m.group("break"))))
+
out.append(speech.BreakCommand(time=int(m.group("break")) * breakMulti))
elif m.lastgroup == "char":
out.extend((speech.CharacterModeCommand(True),
m.group("char"),
speech.CharacterModeCommand(False)))


https://bitbucket.org/nvdaaddonteam/nvda/commits/b98940140670/
Changeset: b98940140670
Branch: None
User: jteh
Date: 2015-01-19 05:54:34+00:00
Summary: mshtml vbuf backend: Drop support for MathPlayer <= 3, as it
interferes with support for MathPlayer 4. It's far less useful anyway.

Affected #: 1 file

diff --git a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
index a04d1fd..db1dd94 100755
--- a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
@@ -1090,10 +1090,10 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf
} else if(nodeName.compare(L"BR")==0) {
LOG_DEBUG(L"node is a br tag, adding a line feed as its text.");
contentString=L"\n";
- } else if (nodeName.compare(L"MATH")==0) {
- contentString=IAName;
- isInteractive=true;
- } else
if((!isRoot&&(IARole==ROLE_SYSTEM_APPLICATION||IARole==ROLE_SYSTEM_DIALOG))||IARole==ROLE_SYSTEM_OUTLINE)
{
+ } else
if((!isRoot&&(IARole==ROLE_SYSTEM_APPLICATION||IARole==ROLE_SYSTEM_DIALOG))
+ ||IARole==ROLE_SYSTEM_OUTLINE
+ ||nodeName.compare(L"MATH")==0
+ ) {
contentString=L" ";
} else {
renderChildren=true;


https://bitbucket.org/nvdaaddonteam/nvda/commits/93d962bbad72/
Changeset: 93d962bbad72
Branch: None
User: jteh
Date: 2015-01-19 07:09:50+00:00
Summary: In browse mode, make it possible to interact with math under the
browse mode cursor by simply pressing enter.

Affected #: 2 files

diff --git a/source/virtualBuffers/__init__.py
b/source/virtualBuffers/__init__.py
index f413884..96cd5a4 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -866,6 +866,19 @@ class VirtualBuffer(cursorManager.CursorManager,
treeInterceptorHandler.TreeInte
obj = info.NVDAObjectAtStart
if not obj:
return
+ if obj.role == controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if not mathPres.interactionProvider:
+ # Translators: Reported when the user attempts
math interaction
+ # but math interaction is not supported.
+ ui.message(_("Math interaction not supported."))
+ return
+ try:
+ return
mathPres.interactionProvider.interactWithMathMl(obj.mathMl)
+ except (NotImplementedError, LookupError):
+ pass
+ return
if self.shouldPassThrough(obj):
obj.setFocus()
self.passThrough = True

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index e55c7d9..69f3013 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -535,9 +535,14 @@ If you are using a braille display, it will also be
displayed in braille.

++ Interactive Navigation ++
If you are working primarily with speech, in most cases, you will probably
wish to examine the expression in smaller segments, rather than hearing the
entire expression at once.
-To do this, first move the review cursor to the mathematical content.
+
+If you are in browse mode, you can do this by moving the cursor to the
mathematical content and pressing enter.
+
+If you are not in browse mode:
++ move the review cursor to the mathematical content.
By default, the review cursor follows the system caret, so you can usually use
the system caret to move to the desired content.
-Then, activate the following command:
++ Then, activate the following command:
++

%kc:beginInclude
|| Name | Key | Description |


https://bitbucket.org/nvdaaddonteam/nvda/commits/cc54976c1ea8/
Changeset: cc54976c1ea8
Branch: None
User: jteh
Date: 2015-01-20 02:01:30+00:00
Summary: Merge branch 'master' into t4673

Affected #: 38 files

diff --git a/contributors.txt b/contributors.txt
index 4655c1e..6b1212a 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -161,3 +161,4 @@ Nikola Jovic
Niklas Johansson
Dinesh Mittal
Maheshinder Singh Khosla
+Zvonimir Stanecic

diff --git a/miscDeps b/miscDeps
index c198735..6ae89fa 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit c198735dcf0c966c0550a7c2142dfb02513150ef
+Subproject commit 6ae89fa504b1cad4d15d74f64dc8b7cae200e5b2

diff --git a/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf
b/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf
index 0d5c07e..6539166 100644
--- a/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf
+++ b/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.acf
@@ -18,6 +18,7 @@ interface NvdaInProcUtils {
[fault_status,comm_status] unregisterNVDAProcess();
[fault_status,comm_status] winword_expandToLine();
[fault_status,comm_status] winword_getTextInRange();
+ [fault_status,comm_status] winword_moveByLine();
[fault_status,comm_status] sysListView32_getGroupInfo();
[fault_status,comm_status] getActiveObject();
[fault_status,comm_status] dumpOnCrash();

diff --git a/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl
b/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl
index f5d3fd4..b2841c8 100644
--- a/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl
+++ b/nvdaHelper/interfaces/nvdaInProcUtils/nvdaInProcUtils.idl
@@ -47,6 +47,8 @@ interface NvdaInProcUtils {

error_status_t winword_getTextInRange([in] const long windowHandle,
[in] const int startOffset, [in] const int endOffset, [in] const long
formatConfig, [out] BSTR* text);

+ error_status_t winword_moveByLine([in] const long windowHandle, [in]
const int offset, [in] const int moveBack, [out] int* newOffset);
+
error_status_t sysListView32_getGroupInfo([in] long windowHandle, [in]
int groupIndex, [out,string] BSTR* header, [out,string] BSTR* footer, [out]
int* state);

error_status_t getActiveObject([in] handle_t bindingHandle, [in,string]
const wchar_t* progid, [out] IUnknown** ppUnknown);

diff --git a/nvdaHelper/local/nvdaHelperLocal.def
b/nvdaHelper/local/nvdaHelperLocal.def
index 340fa6e..e44cfb8 100644
--- a/nvdaHelper/local/nvdaHelperLocal.def
+++ b/nvdaHelper/local/nvdaHelperLocal.def
@@ -13,6 +13,7 @@ EXPORTS
nvdaInProcUtils_getActiveObject
nvdaInProcUtils_winword_expandToLine
nvdaInProcUtils_winword_getTextInRange
+ nvdaInProcUtils_winword_moveByLine
VBuf_createBuffer
VBuf_destroyBuffer
VBuf_findNodeByAttributes

diff --git a/nvdaHelper/remote/displayModel.cpp
b/nvdaHelper/remote/displayModel.cpp
index 48644c4..5a3f92f 100644
--- a/nvdaHelper/remote/displayModel.cpp
+++ b/nvdaHelper/remote/displayModel.cpp
@@ -260,6 +260,14 @@ void displayModel_t::copyRectangle(const RECT& srcRect,
BOOL removeFromSource, B
//Insert the chunk in to the temporary list
copiedChunks.insert(copiedChunks.end(),chunk);
}
+ //Save the old source focus rectangle
+ RECT* srcFocusRect=NULL;
+ if(focusRect) {
+ srcFocusRect=new RECT;
+ *srcFocusRect=*focusRect;
+ }
+ //Clear the source rectangle if requested to do so (move rather than
copy)
+ if(removeFromSource) this->clearRectangle(srcRect);
//Clear the entire destination rectangle if requested to do so
if(opaqueCopy) destModel->clearRectangle(clippedDestRect);
//insert the copied chunks in to the destination model
@@ -268,23 +276,19 @@ void displayModel_t::copyRectangle(const RECT& srcRect,
BOOL removeFromSource, B
destModel->insertChunk(*i);
}
// If a focus rectangle was also contained in the source area, copy the
focus rectangle as well
- if(false) {
//focusRect&&IntersectRect(&tempRect,&srcRect,focusRect)&&EqualRect(&tempRect,focusRect))
{
- RECT newFocusRect=*focusRect;
-
transposAndScaleCoordinate(srcRect.left,destRect.left,scaleX,newFocusRect.left);
-
transposAndScaleCoordinate(srcRect.left,destRect.left,scaleX,newFocusRect.right);
-
transposAndScaleCoordinate(srcRect.top,destRect.top,scaleY,newFocusRect.top);
-
transposAndScaleCoordinate(srcRect.top,destRect.top,scaleY,newFocusRect.bottom);
-
if(IntersectRect(&tempRect,&clippedDestRect,&newFocusRect)&&EqualRect(&tempRect,&newFocusRect))
{
- RECT oldDestFocusRect;
-
if(!opaqueCopy&&destModel->getFocusRect(&oldDestFocusRect)&&EqualRect(&oldDestFocusRect,&newFocusRect))
{
- destModel->setFocusRect(NULL);
- } else {
+ if(srcFocusRect) {
+
if(IntersectRect(&tempRect,&srcRect,srcFocusRect)&&EqualRect(&tempRect,srcFocusRect))
{
+ RECT newFocusRect=*srcFocusRect;
+
transposAndScaleCoordinate(srcRect.left,destRect.left,scaleX,newFocusRect.left);
+
transposAndScaleCoordinate(srcRect.left,destRect.left,scaleX,newFocusRect.right);
+
transposAndScaleCoordinate(srcRect.top,destRect.top,scaleY,newFocusRect.top);
+
transposAndScaleCoordinate(srcRect.top,destRect.top,scaleY,newFocusRect.bottom);
+
if(IntersectRect(&tempRect,&clippedDestRect,&newFocusRect)&&EqualRect(&tempRect,&newFocusRect))
{
destModel->setFocusRect(&newFocusRect);
}
}
+ free(srcFocusRect);
}
- //Clear the source rectangle if requested to do so (move rather than
copy)
- if(removeFromSource) this->clearRectangle(srcRect);
}

void displayModel_t::generateWhitespaceXML(HWND hwnd, long baseline, wstring&
text) {

diff --git a/nvdaHelper/remote/gdiHooks.cpp b/nvdaHelper/remote/gdiHooks.cpp
index 14492e0..a175fed 100644
--- a/nvdaHelper/remote/gdiHooks.cpp
+++ b/nvdaHelper/remote/gdiHooks.cpp
@@ -1145,6 +1145,7 @@ void gdiHooks_inProcess_initialize() {

real_CreateCompatibleDC=apiHook_hookFunction_safe("GDI32.dll",CreateCompatibleDC,fake_CreateCompatibleDC);

real_SelectObject=apiHook_hookFunction_safe("GDI32.dll",SelectObject,fake_SelectObject);

real_DeleteDC=apiHook_hookFunction_safe("GDI32.dll",DeleteDC,fake_DeleteDC);
+
real_FillRect=apiHook_hookFunction_safe("USER32.dll",FillRect,fake_FillRect);

real_DrawFocusRect=apiHook_hookFunction_safe("USER32.dll",DrawFocusRect,fake_DrawFocusRect);

real_BeginPaint=apiHook_hookFunction_safe("USER32.dll",BeginPaint,fake_BeginPaint);
real_BitBlt=apiHook_hookFunction_safe("GDI32.dll",BitBlt,fake_BitBlt);

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index a54fa9f..41ba2bc 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -44,6 +44,7 @@ using namespace std;
#define wdDISPID_REVISIONS_ITEM 0
#define wdDISPID_REVISION_TYPE 4
#define wdDISPID_RANGE_STORYTYPE 7
+#define wdDISPID_RANGE_MOVE 109
#define wdDISPID_RANGE_MOVEEND 111
#define wdDISPID_RANGE_COLLAPSE 101
#define wdDISPID_RANGE_TEXT 0
@@ -117,6 +118,8 @@ using namespace std;
#define wdDISPID_TABLES_ITEM 0
#define wdDISPID_TABLE_NESTINGLEVEL 108
#define wdDISPID_TABLE_RANGE 0
+#define wdDISPID_TABLE_BORDERS 1100
+#define wdDISPID_BORDERS_ENABLE 2
#define wdDISPID_RANGE_CELLS 57
#define wdDISPID_CELLS_ITEM 0
#define wdDISPID_CELL_RANGE 0
@@ -160,6 +163,7 @@ using namespace std;

#define wdInlineShapeEmbeddedOLEObject 1
#define wdInlineShapePicture 3
+#define wdInlineShapeLinkedPicture 4

#define formatConfig_reportFontName 1
#define formatConfig_reportFontSize 2
@@ -178,9 +182,10 @@ using namespace std;
#define formatConfig_reportLanguage 16384
#define formatConfig_reportRevisions 32768
#define formatConfig_reportParagraphIndentation 65536
-
+#define formatConfig_includeLayoutTables 131072
+
#define formatConfig_fontFlags
(formatConfig_reportFontName|formatConfig_reportFontSize|formatConfig_reportFontAttributes|formatConfig_reportColor)
-#define formatConfig_initialFormatFlags
(formatConfig_reportPage|formatConfig_reportLineNumber|formatConfig_reportTables|formatConfig_reportHeadings)
+#define formatConfig_initialFormatFlags
(formatConfig_reportPage|formatConfig_reportLineNumber|formatConfig_reportTables|formatConfig_reportHeadings|formatConfig_includeLayoutTables)

UINT wm_winword_expandToLine=0;
typedef struct {
@@ -432,9 +437,16 @@ bool collectCommentOffsets(IDispatchPtr pDispatchRange,
vector<pair<long,long>>&
return !commentVector.empty();
}

-bool fetchTableInfo(IDispatch* pDispatchTable, int* rowCount, int*
columnCount, int* nestingLevel) {
+bool fetchTableInfo(IDispatch* pDispatchTable, bool includeLayoutTables, int*
rowCount, int* columnCount, int* nestingLevel) {
IDispatchPtr pDispatchRows=NULL;
IDispatchPtr pDispatchColumns=NULL;
+ IDispatchPtr pDispatchBorders=NULL;
+
if(!includeLayoutTables&&_com_dispatch_raw_propget(pDispatchTable,wdDISPID_TABLE_BORDERS,VT_DISPATCH,&pDispatchBorders)==S_OK&&pDispatchBorders)
{
+ BOOL isEnabled=true;
+
if(_com_dispatch_raw_propget(pDispatchBorders,wdDISPID_BORDERS_ENABLE,VT_BOOL,&isEnabled)==S_OK&&!isEnabled)
{
+ return false;
+ }
+ }

if(_com_dispatch_raw_propget(pDispatchTable,wdDISPID_TABLE_ROWS,VT_DISPATCH,&pDispatchRows)==S_OK&&pDispatchRows)
{

_com_dispatch_raw_propget(pDispatchRows,wdDISPID_ROWS_COUNT,VT_I4,rowCount);
}
@@ -445,7 +457,7 @@ bool fetchTableInfo(IDispatch* pDispatchTable, int*
rowCount, int* columnCount,
return true;
}

-int generateTableXML(IDispatch* pDispatchRange, int startOffset, int
endOffset, wostringstream& XMLStream) {
+int generateTableXML(IDispatch* pDispatchRange, bool includeLayoutTables, int
startOffset, int endOffset, wostringstream& XMLStream) {
int numTags=0;
int iVal=0;
IDispatchPtr pDispatchTables=NULL;
@@ -461,7 +473,7 @@ int generateTableXML(IDispatch* pDispatchRange, int
startOffset, int endOffset,
if(

_com_dispatch_raw_propget(pDispatchRange,wdDISPID_RANGE_TABLES,VT_DISPATCH,&pDispatchTables)!=S_OK||!pDispatchTables\

||_com_dispatch_raw_method(pDispatchTables,wdDISPID_TABLES_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchTable,L"\x0003",1)!=S_OK||!pDispatchTable\
-
||!fetchTableInfo(pDispatchTable,&rowCount,&columnCount,&nestingLevel)\
+
||!fetchTableInfo(pDispatchTable,includeLayoutTables,&rowCount,&columnCount,&nestingLevel)\
) {
return 0;
}
@@ -701,7 +713,7 @@ inline int generateInlineShapeXML(IDispatch*
pDispatchRange, int offset, wostrin
}
SysFreeString(altText);
}
- XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<(shapeType==wdInlineShapePicture?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\"";
+ XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<((shapeType==wdInlineShapePicture||shapeType==wdInlineShapeLinkedPicture)?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\"";
if(shapeType==wdInlineShapeEmbeddedOLEObject) {
XMLStream<<L" shapeoffset=\""<<offset<<L"\"";
IDispatchPtr pOLEFormat=NULL;
@@ -797,7 +809,7 @@ void winword_getTextInRange_helper(HWND hwnd,
winword_getTextInRange_args* args)
int unitsMoved=0;
BSTR text=NULL;
if(initialFormatConfig&formatConfig_reportTables) {
-
neededClosingControlTagCount+=generateTableXML(pDispatchRange,args->startOffset,args->endOffset,XMLStream);
+
neededClosingControlTagCount+=generateTableXML(pDispatchRange,(initialFormatConfig&formatConfig_includeLayoutTables)!=0,args->startOffset,args->endOffset,XMLStream);
}
IDispatchPtr pDispatchParagraphs=NULL;
IDispatchPtr pDispatchParagraph=NULL;
@@ -928,12 +940,62 @@ void winword_getTextInRange_helper(HWND hwnd,
winword_getTextInRange_args* args)
args->text=SysAllocString(XMLStream.str().c_str());
}

+UINT wm_winword_moveByLine=0;
+typedef struct {
+ int offset;
+ int moveBack;
+ int newOffset;
+} winword_moveByLine_args;
+void winword_moveByLine_helper(HWND hwnd, winword_moveByLine_args* args) {
+ //Fetch all needed objects
+ IDispatchPtr pDispatchWindow=NULL;
+
if(AccessibleObjectFromWindow(hwnd,OBJID_NATIVEOM,IID_IDispatch,(void**)&pDispatchWindow)!=S_OK||!pDispatchWindow)
{
+ LOG_DEBUGWARNING(L"AccessibleObjectFromWindow failed");
+ return;
+ }
+ IDispatchPtr pDispatchApplication=NULL;
+
if(_com_dispatch_raw_propget(pDispatchWindow,wdDISPID_WINDOW_APPLICATION,VT_DISPATCH,&pDispatchApplication)!=S_OK||!pDispatchApplication)
{
+ LOG_DEBUGWARNING(L"window.application failed");
+ return;
+ }
+ IDispatchPtr pDispatchSelection=NULL;
+
if(_com_dispatch_raw_propget(pDispatchWindow,wdDISPID_WINDOW_SELECTION,VT_DISPATCH,&pDispatchSelection)!=S_OK||!pDispatchSelection)
{
+ LOG_DEBUGWARNING(L"application.selection failed");
+ return;
+ }
+ BOOL startWasActive=false;
+
if(_com_dispatch_raw_propget(pDispatchSelection,wdDISPID_SELECTION_STARTISACTIVE,VT_BOOL,&startWasActive)!=S_OK)
{
+ LOG_DEBUGWARNING(L"selection.StartIsActive failed");
+ }
+ IDispatch* pDispatchOldSelRange=NULL;
+
if(_com_dispatch_raw_propget(pDispatchSelection,wdDISPID_SELECTION_RANGE,VT_DISPATCH,&pDispatchOldSelRange)!=S_OK||!pDispatchOldSelRange)
{
+ LOG_DEBUGWARNING(L"selection.range failed");
+ return;
+ }
+ //Disable screen updating as we will be moving the selection temporarily
+
_com_dispatch_raw_propput(pDispatchApplication,wdDISPID_APPLICATION_SCREENUPDATING,VT_BOOL,false);
+ //Move the selection to the given range
+
_com_dispatch_raw_method(pDispatchSelection,wdDISPID_SELECTION_SETRANGE,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003\x0003",args->offset,args->offset);
+// Move the selection by 1 line
+ int unitsMoved=0;
+
_com_dispatch_raw_method(pDispatchSelection,wdDISPID_RANGE_MOVE,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdLine,((args->moveBack)?-1:1));
+
_com_dispatch_raw_propget(pDispatchSelection,wdDISPID_RANGE_START,VT_I4,&(args->newOffset));
+ //Move the selection back to its original location
+
_com_dispatch_raw_method(pDispatchOldSelRange,wdDISPID_RANGE_SELECT,DISPATCH_METHOD,VT_EMPTY,NULL,NULL);
+ //Restore the old selection direction
+
_com_dispatch_raw_propput(pDispatchSelection,wdDISPID_SELECTION_STARTISACTIVE,VT_BOOL,startWasActive);
+ //Reenable screen updating
+
_com_dispatch_raw_propput(pDispatchApplication,wdDISPID_APPLICATION_SCREENUPDATING,VT_BOOL,true);
+}
+
LRESULT CALLBACK winword_callWndProcHook(int code, WPARAM wParam, LPARAM
lParam) {
CWPSTRUCT* pcwp=(CWPSTRUCT*)lParam;
if(pcwp->message==wm_winword_expandToLine) {

winword_expandToLine_helper(pcwp->hwnd,reinterpret_cast<winword_expandToLine_args*>(pcwp->wParam));
} else if(pcwp->message==wm_winword_getTextInRange) {

winword_getTextInRange_helper(pcwp->hwnd,reinterpret_cast<winword_getTextInRange_args*>(pcwp->wParam));
+ } else if(pcwp->message==wm_winword_moveByLine) {
+
winword_moveByLine_helper(pcwp->hwnd,reinterpret_cast<winword_moveByLine_args*>(pcwp->wParam));
}
return 0;
}
@@ -954,9 +1016,17 @@ error_status_t
nvdaInProcUtils_winword_getTextInRange(handle_t bindingHandle, co
return RPC_S_OK;
}

+error_status_t nvdaInProcUtils_winword_moveByLine(handle_t bindingHandle,
const long windowHandle, const int offset, const int moveBack, int* newOffset) {
+ winword_moveByLine_args args={offset,moveBack,NULL};
+ SendMessage((HWND)windowHandle,wm_winword_moveByLine,(WPARAM)&args,0);
+ *newOffset=args.newOffset;
+ return RPC_S_OK;
+}
+
void winword_inProcess_initialize() {

wm_winword_expandToLine=RegisterWindowMessage(L"wm_winword_expandToLine");

wm_winword_getTextInRange=RegisterWindowMessage(L"wm_winword_getTextInRange");
+ wm_winword_moveByLine=RegisterWindowMessage(L"wm_winword_moveByLine");
registerWindowsHook(WH_CALLWNDPROC,winword_callWndProcHook);
}


diff --git a/readme.txt b/readme.txt
index d5b79d3..b69fc0b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -8,7 +8,7 @@ The NVDA source depends on several other packages to run
correctly.

=== Installed Dependencies ===
The following dependencies need to be installed on your system:
-* Python, version 2.7.8, 32 bit: http://www.python.org/
+* Python, version 2.7.9, 32 bit: http://www.python.org/
* Microsoft Visual Studio 2012 Update 1 or later (Express for Windows Desktop,
or Professional)
* Download for Visual Studio Express 2012 (Windows Desktop):
http://www.microsoft.com/en-au/download/details.aspx?id=34673
* Download for Visual Studio 2012 latest update package:
http://go.microsoft.com/fwlink/?LinkId=301713
@@ -22,7 +22,7 @@ If you aren't sure, run git submodule update after every git
pull, merge or chec

The following dependencies are included in Git submodules:
* comtypes, version 0.6.2: http://sourceforge.net/projects/comtypes/
-* wxPython, version 2.8.12.1 unicode: http://www.wxpython.org/
+* wxPython, version 3.0.2.0: http://www.wxpython.org/
* Python Windows Extensions, build 218:
http://sourceforge.net/projects/pywin32/
* eSpeak, version 1.48.03: http://espeak.sourceforge.net/
* IAccessible2, version 1.3:
http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index da8ea94..57195a6 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -152,20 +152,24 @@ def locateHTMLElementByID(document,ID):
if not frames: #frames can be None in IE 10
return None
for frame in frames:
- try:
- pacc=IAccessibleFromHTMLNode(frame)
- except NotImplementedError:
- # #1569: It's not possible to get an IAccessible from
frames marked with an ARIA role of presentation.
- # In this case, just skip this frame.
+ childElement=getChildHTMLNodeFromFrame(frame)
+ if not childElement:
continue
- res=IAccessibleHandler.accChild(pacc,1)
- if not res: continue
- childElement=HTMLNodeFromIAccessible(res[0])
- if not childElement: continue
childElement=locateHTMLElementByID(childElement.document,ID)
if not childElement: continue
return childElement

+def getChildHTMLNodeFromFrame(frame):
+ try:
+ pacc=IAccessibleFromHTMLNode(frame)
+ except NotImplementedError:
+ # #1569: It's not possible to get an IAccessible from frames
marked with an ARIA role of presentation.
+ # In this case, just skip this frame.
+ return
+ res=IAccessibleHandler.accChild(pacc,1)
+ if not res: return
+ return HTMLNodeFromIAccessible(res[0])
+
class MSHTMLTextInfo(textInfos.TextInfo):

def _expandToLine(self,textRange):
@@ -373,12 +377,23 @@ class MSHTML(IAccessible):
return False

if relation=="focus":
- try:
- HTMLNode=HTMLNode.document.activeElement
- # The IAccessibleObject may be incorrect now,
so let the constructor recalculate it.
- del kwargs['IAccessibleObject']
- except:
- log.exception("Error getting activeElement")
+ # #4045: we must recurse into frames ourselves when
fetching the active element of a document.
+ while True:
+ try:
+ HTMLNode=HTMLNode.document.activeElement
+ except:
+ log.exception("Error getting
activeElement")
+ break
+ nodeName=HTMLNode.nodeName or ""
+ if nodeName.lower() not in ("frame","iframe"):
+ # The IAccessibleObject may be
incorrect now, so let the constructor recalculate it.
+ del kwargs['IAccessibleObject']
+ break
+ childElement=getChildHTMLNodeFromFrame(HTMLNode)
+ if not childElement:
+ break
+ HTMLNode=childElement
+
elif isinstance(relation,tuple):
windowHandle=kwargs.get('windowHandle')
p=ctypes.wintypes.POINT(x=relation[0],y=relation[1])

diff --git a/source/NVDAObjects/IAccessible/winword.py
b/source/NVDAObjects/IAccessible/winword.py
index 613bffb..04bc989 100644
--- a/source/NVDAObjects/IAccessible/winword.py
+++ b/source/NVDAObjects/IAccessible/winword.py
@@ -58,6 +58,10 @@ class SpellCheckErrorField(IAccessible,WordDocument_WwN):
speech.speakText(errorText)
speech.speakSpelling(errorText)

+ def isDuplicateIAccessibleEvent(self,obj):
+ """ We return false here because the spell checker window
raises the focus event every time the value changes instead of the value
changed event
+ regardless of the fact that this window already has the
focus."""
+ return False

class ProtectedDocumentPane(IAccessible):
"""The pane that gets focus in case a document opens in protected mode
in word

diff --git a/source/NVDAObjects/window/winword.py
b/source/NVDAObjects/window/winword.py
index 2458b1b..0e99769 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -12,6 +12,7 @@ import comtypes.automation
import uuid
import operator
import locale
+import collections
import sayAllHandler
import eventHandler
import braille
@@ -30,6 +31,9 @@ import textInfos
import textInfos.offsets
import colors
import controlTypes
+import browseMode
+import review
+from cursorManager import CursorManager, ReviewCursorManager
from tableUtils import HeaderCellInfo, HeaderCellTracker
from . import Window
from ..behaviors import EditableTextWithoutAutoSelectDetection
@@ -81,8 +85,23 @@ wdGoToRelative=2
wdGoToNext=2
wdGoToPrevious=3
#GoTo - units
+wdGoToBookmark=-1
+wdGoToSection=0
wdGoToPage=1
+wdGoToTable=2
wdGoToLine=3
+wdGoToFootnote=4
+wdGoToEndnote=5
+wdGoToComment=6
+wdGoToField=7
+wdGoToGraphic=8
+wdGoToObject=9
+wdGoToEquation=10
+wdGoToHeading=11
+wdGoToPercent=12
+wdGoToSpellingError=13
+wdGoToGrammaticalError=14
+wdGoToProofreadingError=15

wdCommentsStory=4
wdEndnotesStory=3
@@ -235,9 +254,170 @@ formatConfigFlagsMap={
"reportRevisions":32768,
"reportParagraphIndentation":65536,
}
+formatConfigFlag_includeLayoutTables=131072
+
+class WordDocumentHeadingQuickNavItem(browseMode.TextInfoQuickNavItem):
+
+ def __init__(self,nodeType,document,textInfo,level):
+ self.level=level
+
super(WordDocumentHeadingQuickNavItem,self).__init__(nodeType,document,textInfo)
+
+ def isChild(self,parent):
+ if not isinstance(parent,WordDocumentHeadingQuickNavItem):
+ return False
+ return self.level>parent.level
+
+class WordDocumentCollectionQuickNavItem(browseMode.TextInfoQuickNavItem):
+ """
+ A QuickNavItem representing an item that MS Word stores as a collection
(e.g. link, table etc).
+ """
+
+ def rangeFromCollectionItem(self,item):
+ """
+ Fetches a Microsoft Word range object from a Microsoft Word
item in a collection. E.g. a HyperLink object.
+ @param item: an item from a collection (E.g. a HyperLink
object).
+ """
+ return item.range
+
+ def __init__(self,itemType,document,collectionItem):
+ """
+ See L{TextInfoQuickNavItem} for itemType and document argument
definitions.
+ @param collectionItem: an item from an MS Word collection e.g.
HyperLink object.
+ """
+ self.collectionItem=collectionItem
+ self.rangeObj=self.rangeFromCollectionItem(collectionItem)
+
textInfo=BrowseModeWordDocumentTextInfo(document,None,_rangeObj=self.rangeObj)
+
super(WordDocumentCollectionQuickNavItem,self).__init__(itemType,document,textInfo)
+
+class WordDocumentCommentQuickNavItem(WordDocumentCollectionQuickNavItem):
+ @property
+ def label(self):
+ author=self.collectionItem.author
+ date=self.collectionItem.date
+ text=self.collectionItem.range.text
+ return _(u"comment: {text} by {author} on
{date}").format(author=author,text=text,date=date)
+
+ def rangeFromCollectionItem(self,item):
+ return item.scope
+
+class WordDocumentRevisionQuickNavItem(WordDocumentCollectionQuickNavItem):
+ @property
+ def label(self):
+ revisionType=wdRevisionTypeLabels.get(self.collectionItem.type)
+ author=self.collectionItem.author or ""
+ date=self.collectionItem.date
+ text=(self.collectionItem.range.text or "")[:100]
+ return _(u"{revisionType}: {text} by {author} on
{date}").format(revisionType=revisionType,author=author,text=text,date=date)
+
+class WinWordCollectionQuicknavIterator(object):
+ """
+ Allows iterating over an MS Word collection (e.g. HyperLinks) emitting
L{QuickNavItem} objects.
+ """
+
+ quickNavItemClass=WordDocumentCollectionQuickNavItem #: the
QuickNavItem class that should be instanciated and emitted.
+
+ def __init__(self,itemType,document,direction,rangeObj,includeCurrent):
+ """
+ See L{QuickNavItemIterator} for itemType, document and
direction definitions.
+ @param rangeObj: a Microsoft Word range object where the
collection should be fetched from.
+ @ param includeCurrent: if true then any item at the initial
position will be also emitted rather than just further ones.
+ """
+ self.document=document
+ self.itemType=itemType
+ self.direction=direction if direction else "next"
+ self.rangeObj=rangeObj
+ self.includeCurrent=includeCurrent
+
+ def collectionFromRange(self,rangeObj):
+ """
+ Fetches a Microsoft Word collection object from a Microsoft
Word range object. E.g. HyperLinks from a range.
+ @param rangeObj: a Microsoft Word range object.
+ @return: a Microsoft Word collection object.
+ """
+ raise NotImplementedError
+
+ def filter(self,item):
+ """
+ Only allows certain items fom a collection to be emitted. E.g.
a table who's borders are enabled.
+ @param item: an item from a Microsoft Word collection (e.g.
HyperLink object).
+ @return True if this item should be allowd, false otherwise.
+ @rtype: bool
+ """
+ return True
+
+ def iterate(self):
+ """
+ returns a generator that emits L{QuickNavItem} objects for this
collection.
+ """
+ if self.direction=="next":
+ self.rangeObj.moveEnd(wdStory,1)
+ elif self.direction=="previous":
+ self.rangeObj.collapse(wdCollapseStart)
+ self.rangeObj.moveStart(wdStory,-1)
+ items=self.collectionFromRange(self.rangeObj)
+ itemCount=items.count
+ isFirst=True
+ for index in xrange(1,itemCount+1):
+ if self.direction=="previous":
+ index=itemCount-(index-1)
+ collectionItem=items[index]
+
item=self.quickNavItemClass(self.itemType,self.document,collectionItem)
+ itemRange=item.rangeObj
+ # Skip over the item we're already on.
+ if not self.includeCurrent and isFirst and
((self.direction=="next" and itemRange.start<=self.rangeObj.start) or
(self.direction=="previous" and itemRange.end>self.rangeObj.end)):
+ continue
+ if not self.filter(collectionItem):
+ continue
+ yield item
+ isFirst=False
+
+class LinkWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):
+ def collectionFromRange(self,rangeObj):
+ return rangeObj.hyperlinks
+
+class
CommentWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):
+ quickNavItemClass=WordDocumentCommentQuickNavItem
+ def collectionFromRange(self,rangeObj):
+ return rangeObj.comments
+
+class
RevisionWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):
+ quickNavItemClass=WordDocumentRevisionQuickNavItem
+ def collectionFromRange(self,rangeObj):
+ return rangeObj.revisions
+
+class
GraphicWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):
+ def collectionFromRange(self,rangeObj):
+ return rangeObj.inlineShapes
+ def filter(self,item):
+ return 2<item.type<5
+
+class
TableWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):
+ def collectionFromRange(self,rangeObj):
+ return rangeObj.tables
+ def filter(self,item):
+ return item.borders.enable

class WordDocumentTextInfo(textInfos.TextInfo):

+ def find(self,text,caseSensitive=False,reverse=False):
+ f=self._rangeObj.find
+ f.text=text
+ f.matchCase=caseSensitive
+ f.forward=not reverse
+ return f.execute()
+
+ shouldIncludeLayoutTables=True #: layout tables should always be
included (no matter the user's browse mode setting).
+
+ def activate(self):
+ # Handle activating links.
+ # It is necessary to expand to word to get a link as the link's
first character is never actually in the link!
+ tempRange=self._rangeObj.duplicate
+ tempRange.expand(wdWord)
+ links=tempRange.hyperlinks
+ if links.count>0:
+ links[1].follow()
+ return
+
def _expandToLineAtCaret(self):
lineStart=ctypes.c_int()
lineEnd=ctypes.c_int()
@@ -271,7 +451,7 @@ class WordDocumentTextInfo(textInfos.TextInfo):
self._rangeObj.SetRange(0,0)
elif position==textInfos.POSITION_LAST:
self._rangeObj=self.obj.WinwordSelectionObject.range
- self._rangeObj.moveEnd(wdStory,1)
+ self._rangeObj.endOf(wdStory)
self._rangeObj.move(wdCharacter,-1)
elif isinstance(position,textInfos.offsets.Offsets):
self._rangeObj=self.obj.WinwordSelectionObject.range
@@ -291,6 +471,8 @@ class WordDocumentTextInfo(textInfos.TextInfo):
endOffset=self._rangeObj.end
text=BSTR()
formatConfigFlags=sum(y for x,y in
formatConfigFlagsMap.iteritems() if formatConfig.get(x,False))
+ if self.shouldIncludeLayoutTables:
+ formatConfigFlags+=formatConfigFlag_includeLayoutTables

res=NVDAHelper.localLib.nvdaInProcUtils_winword_getTextInRange(self.obj.appModule.helperLocalBindingHandle,self.obj.documentWindowHandle,startOffset,endOffset,formatConfigFlags,ctypes.byref(text))
if res or not text:
log.debugWarning("winword_getTextInRange failed with
%d"%res)
@@ -446,10 +628,14 @@ class WordDocumentTextInfo(textInfos.TextInfo):
lang = locale.windows_locale[lcid]
if lang:
return languageHandler.normalizeLanguage(lang)
-
+
def expand(self,unit):
- if unit==textInfos.UNIT_LINE and self.basePosition not in
(textInfos.POSITION_CARET,textInfos.POSITION_SELECTION):
- unit=textInfos.UNIT_SENTENCE
+ if unit==textInfos.UNIT_LINE:
+ try:
+ if self._rangeObj.tables.count>0 and
self._rangeObj.cells.count==0:
+ unit=textInfos.UNIT_CHARACTER
+ except COMError:
+ pass
if unit==textInfos.UNIT_LINE:
self._expandToLineAtCaret()
elif unit==textInfos.UNIT_CHARACTER:
@@ -510,27 +696,63 @@ class WordDocumentTextInfo(textInfos.TextInfo):
text=""
return text

- def move(self,unit,direction,endPoint=None):
- if unit==textInfos.UNIT_LINE:
- unit=textInfos.UNIT_SENTENCE
+ def _move(self,unit,direction,endPoint=None,_rangeObj=None):
+ if not _rangeObj:
+ _rangeObj=self._rangeObj
if unit in NVDAUnitsToWordUnits:
unit=NVDAUnitsToWordUnits[unit]
else:
raise NotImplementedError("unit: %s"%unit)
if endPoint=="start":
- moveFunc=self._rangeObj.MoveStart
+ moveFunc=_rangeObj.MoveStart
elif endPoint=="end":
- moveFunc=self._rangeObj.MoveEnd
+ moveFunc=_rangeObj.MoveEnd
else:
- moveFunc=self._rangeObj.Move
+ moveFunc=_rangeObj.Move
res=moveFunc(unit,direction)
#units higher than character and word expand to contain the
last text plus the insertion point offset in the document
#However move from a character before will incorrectly move to
this offset which makes move/expand contridictory to each other
#Make sure that move fails if it lands on the final offset but
the unit is bigger than character/word
- if direction>0 and endPoint!="end" and unit not in
(wdCharacter,wdWord) and
(self._rangeObj.start+1)==self.obj.WinwordDocumentObject.characters.count:
+ if direction>0 and endPoint!="end" and unit not in
(wdCharacter,wdWord) and
(_rangeObj.start+1)==self.obj.WinwordDocumentObject.characters.count:
return 0
return res

+ def move(self,unit,direction,endPoint=None):
+ if unit!=textInfos.UNIT_LINE:
+ return self._move(unit,direction,endPoint)
+ if direction==0 or direction>1 or direction<-1:
+ raise NotImplementedError("moving by line is only
supported collapsed and with a count of 1 or -1")
+ oldOffset=self._rangeObj.end if endPoint=="end" else
self._rangeObj.start
+ newOffset=ctypes.c_long()
+ # Try moving by line making use of the selection temporarily
+
res=NVDAHelper.localLib.nvdaInProcUtils_winword_moveByLine(self.obj.appModule.helperLocalBindingHandle,self.obj.documentWindowHandle,oldOffset,1
if direction<0 else 0,ctypes.byref(newOffset))
+ if res==0:
+ res=direction
+ newOffset=newOffset.value
+ if direction<0 and not endPoint and newOffset==oldOffset:
+ # Moving backwards by line seemed to not move.
+ # Therefore fallback to moving back a character,
expanding to line and collapsing to start instead.
+ self.move(textInfos.UNIT_CHARACTER,-1)
+ self.expand(unit)
+ self.collapse()
+ elif direction>0 and not endPoint and newOffset<oldOffset:
+ # Moving forward by line seems to have wrapped back
before the original position
+ # This can happen in some tables with merged rows.
+ # Try moving forward by cell, but if that fails, jump
past the entire table.
+ res=self.move(textInfos.UNIT_CELL,direction,endPoint)
+ if res==0:
+ self.expand(textInfos.UNIT_TABLE)
+ self.collapse(end=True)
+ else:
+ # the move by line using the selection succeeded.
Therefore update this TextInfo's position.
+ if not endPoint:
+ self._rangeObj.setRange(newOffset,newOffset)
+ elif endPoint=="start":
+ self._rangeObj.start=newOffset
+ elif endPoint=="end":
+ self._rangeObj.end=newOffset
+ return res
+
def _get_bookmark(self):
return
textInfos.offsets.Offsets(self._rangeObj.Start,self._rangeObj.End)

@@ -555,8 +777,162 @@ class WordDocumentTextInfo(textInfos.TextInfo):
except:
raise LookupError("Couldn't get MathML from MathType")

+class
BrowseModeTreeInterceptorWithMakeTextInfo(browseMode.BrowseModeTreeInterceptor):
+ def makeTextInfo(self,position):
+ return self.TextInfo(self,position)
+
+class WordDocumentTextInfoForTreeInterceptor(WordDocumentTextInfo):
+
+ def _get_shouldIncludeLayoutTables(self):
+ return config.conf['documentFormatting']['includeLayoutTables']
+
+class BrowseModeWordDocumentTextInfo(textInfos.TextInfo):
+
+ def __init__(self,obj,position,_rangeObj=None):
+ if isinstance(position,WordDocument):
+ position=textInfos.POSITION_CARET
+
super(BrowseModeWordDocumentTextInfo,self).__init__(obj,position)
+
self.innerTextInfo=WordDocumentTextInfoForTreeInterceptor(obj.rootNVDAObject,position,_rangeObj=_rangeObj)
+
+ def find(self,text,caseSensitive=False,reverse=False):
+ return self.innerTextInfo.find(text,caseSensitive,reverse)
+
+ def copy(self):
+ return
BrowseModeWordDocumentTextInfo(self.obj,None,_rangeObj=self.innerTextInfo._rangeObj)
+
+ def activate(self):
+ return self.innerTextInfo.activate()
+
+ def compareEndPoints(self,other,which):
+ return
self.innerTextInfo.compareEndPoints(other.innerTextInfo,which)
+
+ def setEndPoint(self,other,which):
+ return self.innerTextInfo.setEndPoint(other.innerTextInfo,which)
+
+ def _get_isCollapsed(self):
+ return self.innerTextInfo.isCollapsed
+
+ def collapse(self,end=False):
+ return self.innerTextInfo.collapse(end=end)
+
+ def move(self,unit,direction,endPoint=None):
+ return self.innerTextInfo.move(unit,direction,endPoint=endPoint)
+
+ def _get_bookmark(self):
+ return self.innerTextInfo.bookmark
+
+ def updateCaret(self):
+ return self.innerTextInfo.updateCaret()
+
+ def updateSelection(self):
+ return self.innerTextInfo.updateSelection()
+
+ def _get_text(self):
+ return self.innerTextInfo.text
+
+ def getTextWithFields(self,formatConfig=None):
+ return
self.innerTextInfo.getTextWithFields(formatConfig=formatConfig)
+
+ def expand(self,unit):
+ return self.innerTextInfo.expand(unit)
+
+class
WordDocumentTreeInterceptor(CursorManager,BrowseModeTreeInterceptorWithMakeTextInfo):
+
+ TextInfo=BrowseModeWordDocumentTextInfo
+ needsReviewCursorTextInfoWrapper=False
+
+ def _get_isAlive(self):
+ return winUser.isWindow(self.rootNVDAObject.windowHandle)
+
+ def __contains__(self,obj):
+ return obj==self.rootNVDAObject
+
+ def _set_selection(self,info):
+ super(WordDocumentTreeInterceptor,self)._set_selection(info)
+ review.handleCaretMove(info)
+
+ def _get_ElementsListDialog(self):
+ return ElementsListDialog
+
+ def _iterHeadings(self,nodeType,direction,rangeObj,includeCurrent):
+ neededLevel=int(nodeType[7:]) if len(nodeType)>7 else 0
+ isFirst=True
+ while True:
+ if not isFirst or includeCurrent:
+ level=rangeObj.paragraphs[1].outlineLevel
+ if level and 0<level<10 and (not neededLevel or
neededLevel==level):
+ rangeObj.expand(wdParagraph)
+ yield
WordDocumentHeadingQuickNavItem(nodeType,self,BrowseModeWordDocumentTextInfo(self,None,_rangeObj=rangeObj),level)
+ isFirst=False
+ if direction=="next":
+ newRangeObj=rangeObj.gotoNext(wdGoToHeading)
+ if not newRangeObj or
newRangeObj.start<=rangeObj.start:
+ break
+ elif direction=="previous":
+ newRangeObj=rangeObj.gotoPrevious(wdGoToHeading)
+ if not newRangeObj or
newRangeObj.start>=rangeObj.start:
+ break
+ rangeObj=newRangeObj
+
+ def _iterNodesByType(self,nodeType,direction="next",pos=None):
+ if pos:
+ rangeObj=pos.innerTextInfo._rangeObj
+ else:
+
rangeObj=self.rootNVDAObject.WinwordDocumentObject.range(0,0)
+ includeCurrent=False if pos else True
+ if nodeType=="link":
+ return
LinkWinWordCollectionQuicknavIterator(nodeType,self,direction,rangeObj,includeCurrent).iterate()
+ elif nodeType=="annotation":
+
comments=CommentWinWordCollectionQuicknavIterator(nodeType,self,direction,rangeObj,includeCurrent).iterate()
+
revisions=RevisionWinWordCollectionQuicknavIterator(nodeType,self,direction,rangeObj,includeCurrent).iterate()
+ return
browseMode.mergeQuickNavItemIterators([comments,revisions],direction)
+ elif nodeType=="table":
+ return
TableWinWordCollectionQuicknavIterator(nodeType,self,direction,rangeObj,includeCurrent).iterate()
+ elif nodeType=="graphic":
+ return
GraphicWinWordCollectionQuicknavIterator(nodeType,self,direction,rangeObj,includeCurrent).iterate()
+ elif nodeType.startswith('heading'):
+ return
self._iterHeadings(nodeType,direction,rangeObj,includeCurrent)
+ else:
+ raise NotImplementedError
+
+ def event_gainFocus(self,obj,nextHandler):
+ obj.reportFocus()
+ braille.handler.handleGainFocus(self)
+
+ def script_nextRow(self,gesture):
+ self.rootNVDAObject._moveInTable(row=True,forward=True)
+ braille.handler.handleCaretMove(self)
+
+ def script_previousRow(self,gesture):
+ self.rootNVDAObject._moveInTable(row=True,forward=False)
+ braille.handler.handleCaretMove(self)
+
+ def script_nextColumn(self,gesture):
+ self.rootNVDAObject._moveInTable(row=False,forward=True)
+ braille.handler.handleCaretMove(self)
+
+ def script_previousColumn(self,gesture):
+ self.rootNVDAObject._moveInTable(row=False,forward=False)
+ braille.handler.handleCaretMove(self)
+
+ __gestures={
+ "kb:tab":"trapNonCommandGesture",
+ "kb:shift+tab":"trapNonCommandGesture",
+ "kb:control+alt+upArrow": "previousRow",
+ "kb:control+alt+downArrow": "nextRow",
+ "kb:control+alt+leftArrow": "previousColumn",
+ "kb:control+alt+rightArrow": "nextColumn",
+ # We want to fall back to MS Word's real page up and page down,
rather than browseMode's faked 25 lines
+ "kb:pageUp":None,
+ "kb:pageDown":None,
+ "kb:shift+pageUp":None,
+ "kb:shift+pageDown":None,
+ }
+
class WordDocument(EditableTextWithoutAutoSelectDetection, Window):

+ treeInterceptorClass=WordDocumentTreeInterceptor
+ shouldCreateTreeInterceptor=False
TextInfo=WordDocumentTextInfo

#: True if formatting should be ignored (text only) such as for
spellCheck error field
@@ -868,7 +1244,7 @@ class WordDocument(EditableTextWithoutAutoSelectDetection,
Window):
isCollapsed=False
if not isCollapsed:

speech.speakTextInfo(info,reason=controlTypes.REASON_FOCUS)
- braille.handler.handleCaretMove(info)
+ braille.handler.handleCaretMove(self)
if isCollapsed:

offset=info._rangeObj.information(wdHorizontalPositionRelativeToPage)
msg=self.getLocalizedMeasurementTextForPointSize(offset)
@@ -1066,3 +1442,10 @@ class WordDocument_WwN(WordDocument):
"kb:shift+tab":None,
}

+class ElementsListDialog(browseMode.ElementsListDialog):
+
+
ELEMENT_TYPES=(browseMode.ElementsListDialog.ELEMENT_TYPES[0],browseMode.ElementsListDialog.ELEMENT_TYPES[1],
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("annotation", _("&Annotations")),
+ )

diff --git a/source/addonHandler.py b/source/addonHandler.py
index 0c135a3..4f4ab85 100644
--- a/source/addonHandler.py
+++ b/source/addonHandler.py
@@ -235,8 +235,8 @@ class Addon(object):
os.rename(self.path,tempPath)
except (WindowsError,IOError):
raise RuntimeError("Cannot rename add-on path for
deletion")
- shutil.rmtree(self.path,ignore_errors=True)
- if os.path.exists(self.path):
+ shutil.rmtree(tempPath,ignore_errors=True)
+ if os.path.exists(tempPath):
log.error("Error removing addon directory %s, deferring
until next NVDA restart"%self.path)

@property

diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
index a98bfb9..2ef07d3 100644
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -22,6 +22,7 @@ import speech
import ui
from NVDAObjects.IAccessible import IAccessible
from NVDAObjects.window import Window
+from NVDAObjects.window.winword import WordDocument
from NVDAObjects.IAccessible.MSHTML import MSHTML
from NVDAObjects.behaviors import RowWithFakeNavigation
from NVDAObjects.UIA import UIA
@@ -129,6 +130,8 @@ class AppModule(appModuleHandler.AppModule):
clsList.insert(0,UIAGridRow)
if not isinstance(obj,IAccessible):
return
+ if WordDocument in clsList:
+ clsList.insert(0,OutlookWordDocument)
role=obj.role
windowClassName=obj.windowClassName
states=obj.states
@@ -441,3 +444,15 @@ class UIAGridRow(RowWithFakeNavigation,UIA):
def setFocus(self):
super(UIAGridRow,self).setFocus()
eventHandler.queueEvent("gainFocus",self)
+
+class OutlookWordDocument(WordDocument):
+
+ def _get_shouldCreateTreeInterceptor(self):
+ # #2975: If this WordDocument is displaying a sent message,
then it should be read with browse mode.
+ try:
+ return
self.appModule.nativeOm.activeInspector().currentItem.sent
+ except (COMError,NameError,AttributeError):
+ return False
+
+ def _get_role(self):
+ return controlTypes.ROLE_DOCUMENT if
self.shouldCreateTreeInterceptor else super(OutlookWordDocument,self).role

diff --git a/source/browseMode.py b/source/browseMode.py
new file mode 100644
index 0000000..7ac02b2
--- /dev/null
+++ b/source/browseMode.py
@@ -0,0 +1,764 @@
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2006-2014 NVDA Contributors
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+import itertools
+import collections
+import winsound
+import wx
+import nvwave
+import queueHandler
+import gui
+import ui
+from scriptHandler import isScriptWaiting, willSayAllResume
+import controlTypes
+import config
+import textInfos
+import speech
+import sayAllHandler
+import treeInterceptorHandler
+
+REASON_QUICKNAV = "quickNav"
+
+def reportPassThrough(treeInterceptor,onlyIfChanged=True):
+ """Reports the virtual buffer pass through mode if it has changed.
+ @param treeInterceptor: The current Browse Mode treeInterceptor.
+ @type treeInterceptor: L{BrowseModeTreeInterceptor}
+ @param onlyIfChanged: if true reporting will not happen if the last
reportPassThrough reported the same thing.
+ @type onlyIfChanged: bool
+ """
+ if not onlyIfChanged or treeInterceptor.passThrough !=
reportPassThrough.last:
+ if config.conf["virtualBuffers"]["passThroughAudioIndication"]:
+ sound = r"waves\focusMode.wav" if
treeInterceptor.passThrough else r"waves\browseMode.wav"
+ nvwave.playWaveFile(sound)
+ else:
+ if treeInterceptor.passThrough:
+ speech.speakMessage(_("focus mode"))
+ else:
+ speech.speakMessage(_("browse mode"))
+ reportPassThrough.last = treeInterceptor.passThrough
+reportPassThrough.last = False
+
+def mergeQuickNavItemIterators(iterators,direction="next"):
+ """
+ Merges multiple iterators that emit L{QuickNavItem} objects, yielding
them from first to last.
+ They are sorted using min or max (__lt__ should be implemented on the
L{QuickNavItem} objects).
+ @param iters: the iterators you want to merge.
+ @type iters: sequence of iterators that emit L{QuicknavItem} objects.
+ @param direction: the direction these iterators are searching (e.g.
next, previuos)
+ @type direction: string
+ """
+ finder=min if direction=="next" else max
+ curValues=[]
+ # Populate a list with all iterators and their corisponding first value
+ for it in iterators:
+ try:
+ val=next(it)
+ except StopIteration:
+ continue
+ curValues.append((it,val))
+ # Until all iterators have been used up,
+ # Find the first (minimum or maximum) of all the values,
+ # emit that, and update the list with the next available value for the
iterator who's value was emitted.
+ while len(curValues)>0:
+ first=finder(curValues,key=lambda x: x[1])
+ curValues.remove(first)
+ it,val=first
+ yield val
+ try:
+ newVal=next(it)
+ except StopIteration:
+ continue
+ curValues.append((it,newVal))
+
+class QuickNavItem(object):
+ """ Emitted by L{BrowseModeTreeInterceptor._iterNodesByType}, this
represents one of many positions in a browse mode document, based on the type
of item being searched for (e.g. link, heading, table etc)."""
+
+ itemType=None #: The type of items searched for (e.g. link, heading,
table etc)
+ label=None #: The label that should represent this item in the Elements
list.
+ isAfterSelection=False #: Is this item positioned after the caret in
the document? Used by the elements list to plae its own selection.
+
+ def __init__(self,itemType,document):
+ """
+ @param itemType: the type that was searched for (e.g. link,
heading, table etc)
+ @ type itemType: string
+ @ param document: the browse mode document this item is a part
of.
+ @type document: L{BrowseModeTreeInterceptor}
+ """
+ self.itemType=itemType
+ self.document=document
+
+ def isChild(self,parent):
+ """
+ Is this item a child of the given parent?
+ This is used when representing items in a hierarchical tree
structure, such as the Elements List.
+ @param parent: the item of whom this item may be a child of.
+ @type parent: L{QuickNavItem}
+ @return: True if this item is a child, false otherwise.
+ @rtype: bool
+ """
+ raise NotImplementedError
+
+ def report(self,readUnit=None):
+ """
+ Reports the contents of this item.
+ @param readUnit: the optional unit (e.g. line, paragraph) that
should be used to announce the item position when moved to. If not given, then
the full sise of the item is used.
+ @type readUnit: a L{textInfos}.UNIT_* constant.
+ """
+ raise NotImplementedError
+
+ def moveTo(self):
+ """
+ Moves the browse mode caret or focus to this item.
+ """
+ raise NotImplementedError
+
+ def activate(self):
+ """
+ Activates this item's position. E.g. follows a link, presses a
button etc.
+ """
+ raise NotImplementedError
+
+class TextInfoQuickNavItem(QuickNavItem):
+ """ Represents a quick nav item in a browse mode document who's
positions are represented by a L{textInfos.TextInfo}. """
+
+ def __init__(self,itemType,document,textInfo):
+ """
+ See L{QuickNavItem.__init__} for itemType and document argument
definitions.
+ @param textInfo: the textInfo position this item represents.
+ @type textInfo: L{textInfos.TextInfo}
+ """
+ self.textInfo=textInfo
+ super(TextInfoQuickNavItem,self).__init__(itemType,document)
+
+ def __lt__(self,other):
+ return
self.textInfo.compareEndPoints(other.textInfo,"startToStart")<0
+
+ @property
+ def label(self):
+ return self.textInfo.text.strip()
+
+ def activate(self):
+ self.textInfo.activate()
+
+ def isChild(self,parent):
+ if parent.textInfo.isOverlapping(self.textInfo):
+ return True
+ return False
+
+ def report(self,readUnit=None):
+ info=self.textInfo
+ if readUnit:
+ fieldInfo = info.copy()
+ info.collapse()
+ info.move(readUnit, 1, endPoint="end")
+ if info.compareEndPoints(fieldInfo, "endToEnd") > 0:
+ # We've expanded past the end of the field, so
limit to the end of the field.
+ info.setEndPoint(fieldInfo, "endToEnd")
+ speech.speakTextInfo(info, reason=controlTypes.REASON_FOCUS)
+
+ def moveTo(self):
+ self.textInfo.updateCaret()
+
+ @property
+ def isAfterSelection(self):
+ caret=self.document.makeTextInfo(textInfos.POSITION_CARET)
+ return self.textInfo.compareEndPoints(caret, "startToStart") <= 0
+
+class BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
+
+ def _get_shouldTrapNonCommandGestures(self):
+ return config.conf['virtualBuffers']['trapNonCommandGestures']
+
+ def script_trapNonCommandGesture(self,gesture):
+ winsound.PlaySound("default",1)
+
+ def _get_ElementsListDialog(self):
+ return ElementsListDialog
+
+ def _iterNodesByType(self,itemType,direction="next",pos=None):
+ """
+ Yields L{QuickNavItem} objects representing the ordered
positions in this document according to the type being searched for (e.g. link,
heading, table etc).
+ @param itemType: the type being searched for (e.g. link,
heading, table etc)
+ @type itemType: string
+ @param direction: the direction in which to search (next,
previous, up)
+ @ type direction: string
+ @param pos: the position in the document from where to seart
the search.
+ @type pos: Usually an L{textInfos.TextInfo}
+ """
+ return iter(())
+
+ def _quickNavScript(self,gesture, itemType, direction, errorMessage,
readUnit):
+ info=self.selection
+ try:
+ item = next(self._iterNodesByType(itemType, direction,
info))
+ except NotImplementedError:
+ # Translators: a message when a particular quick nav
command is not supported in the current document.
+ ui.message(_("Not supported in this document"))
+ return
+ except StopIteration:
+ ui.message(errorMessage)
+ return
+ item.moveTo()
+ if not gesture or not willSayAllResume(gesture):
+ item.report(readUnit=readUnit)
+
+ @classmethod
+ def addQuickNav(cls, itemType, key, nextDoc, nextError, prevDoc,
prevError, readUnit=None):
+ scriptSuffix = itemType[0].upper() + itemType[1:]
+ scriptName = "next%s" % scriptSuffix
+ funcName = "script_%s" % scriptName
+ script = lambda self,gesture: self._quickNavScript(gesture,
itemType, "next", nextError, readUnit)
+ script.__doc__ = nextDoc
+ script.__name__ = funcName
+ script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+ setattr(cls, funcName, script)
+ cls.__gestures["kb:%s" % key] = scriptName
+ scriptName = "previous%s" % scriptSuffix
+ funcName = "script_%s" % scriptName
+ script = lambda self,gesture: self._quickNavScript(gesture,
itemType, "previous", prevError, readUnit)
+ script.__doc__ = prevDoc
+ script.__name__ = funcName
+ script.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+ setattr(cls, funcName, script)
+ cls.__gestures["kb:shift+%s" % key] = scriptName
+
+ def script_elementsList(self,gesture):
+ # We need this to be a modal dialog, but it mustn't block this
script.
+ def run():
+ gui.mainFrame.prePopup()
+ d = self.ElementsListDialog(self)
+ d.ShowModal()
+ d.Destroy()
+ gui.mainFrame.postPopup()
+ wx.CallAfter(run)
+ # Translators: the description for the elements list dialog script on
virtualBuffers.
+ script_elementsList.__doc__ = _("Presents a list of links, headings or
landmarks")
+
+ def _activatePosition(self,info):
+ info.activate()
+
+ def script_activatePosition(self,gesture):
+ info=self.makeTextInfo(textInfos.POSITION_CARET)
+ self._activatePosition(info)
+ # Translators: the description for the activatePosition script on
virtualBuffers.
+ script_activatePosition.__doc__ = _("activates the current object in
the document")
+
+ __gestures={
+ "kb:NVDA+f7": "elementsList",
+ "kb:enter": "activatePosition",
+ "kb:space": "activatePosition",
+ }
+
+# Add quick navigation scripts.
+qn = BrowseModeTreeInterceptor.addQuickNav
+qn("heading", key="h",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading"))
+qn("heading1", key="1",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 1"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 1"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 1"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 1"))
+qn("heading2", key="2",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 2"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 2"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 2"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 2"))
+qn("heading3", key="3",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 3"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 3"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 3"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 3"))
+qn("heading4", key="4",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 4"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 4"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 4"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 4"))
+qn("heading5", key="5",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 5"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 5"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 5"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 5"))
+qn("heading6", key="6",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next heading at level 6"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next heading at level 6"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous heading at level 6"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous heading at level 6"))
+qn("table", key="t",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next table"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next table"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous table"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous table"),
+ readUnit=textInfos.UNIT_LINE)
+qn("link", key="k",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next link"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous link"))
+qn("visitedLink", key="v",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next visited link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next visited link"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous visited link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous visited link"))
+qn("unvisitedLink", key="u",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next unvisited link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next unvisited link"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous unvisited link"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous unvisited link"))
+qn("formField", key="f",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next form field"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next form field"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous form field"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous form field"),
+ readUnit=textInfos.UNIT_LINE)
+qn("list", key="l",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next list"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next list"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous list"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous list"),
+ readUnit=textInfos.UNIT_LINE)
+qn("listItem", key="i",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next list item"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next list item"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous list item"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous list item"))
+qn("button", key="b",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next button"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next button"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous button"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous button"))
+qn("edit", key="e",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next edit field"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next edit field"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous edit field"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous edit field"),
+ readUnit=textInfos.UNIT_LINE)
+qn("frame", key="m",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next frame"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next frame"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous frame"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous frame"),
+ readUnit=textInfos.UNIT_LINE)
+qn("separator", key="s",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next separator"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next separator"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous separator"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous separator"))
+qn("radioButton", key="r",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next radio button"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next radio button"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous radio button"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous radio button"))
+qn("comboBox", key="c",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next combo box"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next combo box"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous combo box"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous combo box"))
+qn("checkBox", key="x",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next check box"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next check box"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous check box"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous check box"))
+qn("graphic", key="g",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next graphic"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next graphic"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous graphic"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous graphic"))
+qn("blockQuote", key="q",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next block quote"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next block quote"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous block quote"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous block quote"))
+qn("notLinkBlock", key="n",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("skips forward past a block of links"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no more text after a block of links"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("skips backward past a block of links"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no more text before a block of links"),
+ readUnit=textInfos.UNIT_LINE)
+qn("landmark", key="d",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next landmark"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next landmark"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous landmark"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous landmark"),
+ readUnit=textInfos.UNIT_LINE)
+qn("embeddedObject", key="o",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next embedded object"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next embedded object"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous embedded object"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous embedded object"))
+qn("annotation", key="a",
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ nextDoc=_("moves to the next annotation"),
+ # Translators: Message presented when the browse mode element is not
found.
+ nextError=_("no next annotation"),
+ # Translators: Input help message for a quick navigation command in
browse mode.
+ prevDoc=_("moves to the previous annotation"),
+ # Translators: Message presented when the browse mode element is not
found.
+ prevError=_("no previous annotation"))
+del qn
+
+class ElementsListDialog(wx.Dialog):
+ ELEMENT_TYPES = (
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("link", _("Lin&ks")),
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("heading", _("&Headings")),
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("landmark", _("Lan&dmarks")),
+ )
+
+ Element = collections.namedtuple("Element", ("item", "parent"))
+
+ lastSelectedElementType=0
+
+ def __init__(self, document):
+ self.document = document
+ # Translators: The title of the browse mode Elements List
dialog.
+ super(ElementsListDialog, self).__init__(gui.mainFrame,
wx.ID_ANY, _("Elements List"))
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ # Translators: The label of a group of radio buttons to select
the type of element
+ # in the browse mode Elements List dialog.
+ child = wx.RadioBox(self, wx.ID_ANY, label=_("Type:"),
choices=tuple(et[1] for et in self.ELEMENT_TYPES))
+ child.SetSelection(self.lastSelectedElementType)
+ child.Bind(wx.EVT_RADIOBOX, self.onElementTypeChange)
+ mainSizer.Add(child,proportion=1)
+
+ self.tree = wx.TreeCtrl(self, wx.ID_ANY,
style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_SINGLE)
+ self.tree.Bind(wx.EVT_SET_FOCUS, self.onTreeSetFocus)
+ self.tree.Bind(wx.EVT_CHAR, self.onTreeChar)
+ self.treeRoot = self.tree.AddRoot("root")
+ mainSizer.Add(self.tree,proportion=7,flag=wx.EXPAND)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: The label of an editable text field to filter
the elements
+ # in the browse mode Elements List dialog.
+ label = wx.StaticText(self, wx.ID_ANY, _("&Filter by:"))
+ sizer.Add(label)
+ self.filterEdit = wx.TextCtrl(self, wx.ID_ANY)
+ self.filterEdit.Bind(wx.EVT_TEXT, self.onFilterEditTextChange)
+ sizer.Add(self.filterEdit)
+ mainSizer.Add(sizer,proportion=1)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ # Translators: The label of a button to activate an element
+ # in the browse mode Elements List dialog.
+ self.activateButton = wx.Button(self, wx.ID_ANY, _("&Activate"))
+ self.activateButton.Bind(wx.EVT_BUTTON, lambda evt:
self.onAction(True))
+ sizer.Add(self.activateButton)
+ # Translators: The label of a button to move to an element
+ # in the browse mode Elements List dialog.
+ self.moveButton = wx.Button(self, wx.ID_ANY, _("&Move to"))
+ self.moveButton.Bind(wx.EVT_BUTTON, lambda evt:
self.onAction(False))
+ sizer.Add(self.moveButton)
+ sizer.Add(wx.Button(self, wx.ID_CANCEL))
+ mainSizer.Add(sizer,proportion=1)
+
+ mainSizer.Fit(self)
+ self.SetSizer(mainSizer)
+
+ self.tree.SetFocus()
+
self.initElementType(self.ELEMENT_TYPES[self.lastSelectedElementType][0])
+ self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
+ def onElementTypeChange(self, evt):
+ elementType=evt.GetInt()
+ # We need to make sure this gets executed after the focus event.
+ # Otherwise, NVDA doesn't seem to get the event.
+ queueHandler.queueFunction(queueHandler.eventQueue,
self.initElementType, self.ELEMENT_TYPES[elementType][0])
+ self.lastSelectedElementType=elementType
+
+ def initElementType(self, elType):
+ if elType == "link":
+ # Links can be activated.
+ self.activateButton.Enable()
+ self.SetAffirmativeId(self.activateButton.GetId())
+ else:
+ # No other element type can be activated.
+ self.activateButton.Disable()
+ self.SetAffirmativeId(self.moveButton.GetId())
+
+ # Gather the elements of this type.
+ self._elements = []
+ self._initialElement = None
+
+ parentElements = []
+ for item in self.document._iterNodesByType(elType):
+ # Find the parent element, if any.
+ for parent in reversed(parentElements):
+ if item.isChild(parent.item):
+ break
+ else:
+ # We're not a child of this parent, so
this parent has no more children and can be removed from the stack.
+ parentElements.pop()
+ else:
+ # No parent found, so we're at the root.
+ # Note that parentElements will be empty at
this point, as all parents are no longer relevant and have thus been removed
from the stack.
+ parent = None
+
+ element=self.Element(item,parent)
+ self._elements.append(element)
+
+ if item.isAfterSelection:
+ # The element immediately preceding or
overlapping the caret should be the initially selected element.
+ # This element immediately follows the caret,
so we want the previous element.
+ try:
+ self._initialElement =
self._elements[-1]
+ except IndexError:
+ # No previous element.
+ pass
+
+ # This could be the parent of a subsequent element, so
add it to the parents stack.
+ parentElements.append(element)
+
+ # Start with no filtering.
+ self.filter("", newElementType=True)
+
+ def filter(self, filterText, newElementType=False):
+ # If this is a new element type, use the element nearest the
cursor.
+ # Otherwise, use the currently selected element.
+ defaultElement = self._initialElement if newElementType else
self.tree.GetItemPyData(self.tree.GetSelection())
+ # Clear the tree.
+ self.tree.DeleteChildren(self.treeRoot)
+
+ # Populate the tree with elements matching the filter text.
+ elementsToTreeItems = {}
+ item = None
+ defaultItem = None
+ matched = False
+ #Do case-insensitive matching by lowering both filterText and
each element's text.
+ filterText=filterText.lower()
+ for element in self._elements:
+ if filterText not in element.item.label.lower():
+ item = None
+ continue
+ matched = True
+ parent = element.parent
+ if parent:
+ parent = elementsToTreeItems.get(parent)
+ item = self.tree.AppendItem(parent or self.treeRoot,
element.item.label)
+ self.tree.SetItemPyData(item, element)
+ elementsToTreeItems[element] = item
+ if element == defaultElement:
+ defaultItem = item
+
+ self.tree.ExpandAll()
+
+ if not matched:
+ # No items, so disable the buttons.
+ self.activateButton.Disable()
+ self.moveButton.Disable()
+ return
+
+ # If there's no default item, use the first item in the tree.
+ self.tree.SelectItem(defaultItem or
self.tree.GetFirstChild(self.treeRoot)[0])
+ # Enable the button(s).
+ # If the activate button isn't the default button, it is
disabled for this element type and shouldn't be enabled here.
+ if self.AffirmativeId == self.activateButton.Id:
+ self.activateButton.Enable()
+ self.moveButton.Enable()
+
+ def onTreeSetFocus(self, evt):
+ # Start with no search.
+ self._searchText = ""
+ self._searchCallLater = None
+ evt.Skip()
+
+ def onTreeChar(self, evt):
+ key = evt.KeyCode
+
+ if key == wx.WXK_RETURN:
+ # The enter key should be propagated to the dialog and
thus activate the default button,
+ # but this is broken (wx ticket #3725).
+ # Therefore, we must catch the enter key here.
+ # Activate the current default button.
+ evt = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED,
wx.ID_ANY)
+ button = self.FindWindowById(self.AffirmativeId)
+ if button.Enabled:
+ button.ProcessEvent(evt)
+ else:
+ wx.Bell()
+
+ elif key >= wx.WXK_START or key == wx.WXK_BACK:
+ # Non-printable character.
+ self._searchText = ""
+ evt.Skip()
+
+ else:
+ # Search the list.
+ # We have to implement this ourselves, as tree views
don't accept space as a search character.
+ char = unichr(evt.UnicodeKey).lower()
+ # IF the same character is typed twice, do the same
search.
+ if self._searchText != char:
+ self._searchText += char
+ if self._searchCallLater:
+ self._searchCallLater.Restart()
+ else:
+ self._searchCallLater = wx.CallLater(1000,
self._clearSearchText)
+ self.search(self._searchText)
+
+ def _clearSearchText(self):
+ self._searchText = ""
+
+ def search(self, searchText):
+ item = self.tree.GetSelection()
+ if not item:
+ # No items.
+ return
+
+ # First try searching from the current item.
+ # Failing that, search from the first item.
+ items =
itertools.chain(self._iterReachableTreeItemsFromItem(item),
self._iterReachableTreeItemsFromItem(self.tree.GetFirstChild(self.treeRoot)[0]))
+ if len(searchText) == 1:
+ # If only a single character has been entered, skip
(search after) the current item.
+ next(items)
+
+ for item in items:
+ if
self.tree.GetItemText(item).lower().startswith(searchText):
+ self.tree.SelectItem(item)
+ return
+
+ # Not found.
+ wx.Bell()
+
+ def _iterReachableTreeItemsFromItem(self, item):
+ while item:
+ yield item
+
+ childItem = self.tree.GetFirstChild(item)[0]
+ if childItem and self.tree.IsExpanded(item):
+ # Has children and is reachable, so recurse.
+ for childItem in
self._iterReachableTreeItemsFromItem(childItem):
+ yield childItem
+
+ item = self.tree.GetNextSibling(item)
+
+ def onFilterEditTextChange(self, evt):
+ self.filter(self.filterEdit.GetValue())
+ evt.Skip()
+
+ def onAction(self, activate):
+ self.Close()
+ # Save off the last selected element type on to the class so
its used in initialization next time.
+
self.__class__.lastSelectedElementType=self.lastSelectedElementType
+ item = self.tree.GetSelection()
+ item = self.tree.GetItemPyData(item).item
+ if activate:
+ item.activate()
+ else:
+ def move():
+ speech.cancelSpeech()
+ item.moveTo()
+ item.report()
+ wx.CallLater(100, move)

diff --git a/source/config/__init__.py b/source/config/__init__.py
index 26a2934..1f28f8b 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -69,6 +69,7 @@ confspec = ConfigObj(StringIO(
# The synthesiser to use
synth = string(default=auto)
symbolLevel = integer(default=100)
+ trustVoiceLanguage = boolean(default=true)
beepSpeechModePitch = integer(default=10000,min=50,max=11025)
outputDevice = string(default=default)
autoLanguageSwitching = boolean(default=true)
@@ -149,6 +150,7 @@ confspec = ConfigObj(StringIO(
autoPassThroughOnCaretMove = boolean(default=false)
passThroughAudioIndication = boolean(default=true)
autoSayAllOnPageLoad = boolean(default=true)
+ trapNonCommandGestures = boolean(default=true)

#Settings for document reading (such as MS Word and wordpad)
[documentFormatting]

diff --git a/source/core.py b/source/core.py
index 8f5a5f7..f6b999b 100644
--- a/source/core.py
+++ b/source/core.py
@@ -70,6 +70,7 @@ def restart(disableAddons=False):
wx.GetApp().ExitMainLoop()
return
import subprocess
+ import winUser
import shellapi
options=[]
try:
@@ -85,7 +86,9 @@ def restart(disableAddons=False):
shellapi.ShellExecute(None, None,
sys.executable.decode("mbcs"),
subprocess.list2cmdline(sys.argv + options).decode("mbcs"),
- None, 0)
+ None,
+ # #4475: ensure that the first window of the new process is not
hidden by providing SW_SHOWNORMAL
+ winUser.SW_SHOWNORMAL)

def resetConfiguration(factoryDefaults=False):
"""Loads the configuration, installs the correct language support and
initialises audio so that it will use the configured synth and speech settings.
@@ -228,19 +231,32 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.debug("Initializing GUI")
import gui
gui.initialize()
+
+ # #3763: In wxPython 3, the class name of frame windows changed from
wxWindowClassNR to wxWindowNR.
+ # NVDA uses the main frame to check for and quit another instance of
NVDA.
+ # To remain compatible with older versions of NVDA, create our own
wxWindowClassNR.
+ # We don't need to do anything else because wx handles WM_QUIT for all
windows.
+ import windowUtils
+ class MessageWindow(windowUtils.CustomWindow):
+ className = u"wxWindowClassNR"
+ messageWindow = MessageWindow(unicode(versionInfo.name))
+
# initialize wxpython localization support
locale = wx.Locale()
lang=languageHandler.getLanguage()
- if '_' in lang:
- wxLang=lang.split('_')[0]
- else:
- wxLang=lang
+ wxLang=locale.FindLanguageInfo(lang)
+ if not wxLang and '_' in lang:
+ wxLang=locale.FindLanguageInfo(lang.split('_')[0])
if hasattr(sys,'frozen'):

locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale"))
- try:
- locale.Init(lang,wxLang)
- except:
- pass
+ if wxLang:
+ try:
+ locale.Init(wxLang.Language)
+ except:
+ log.error("Failed to initialize wx
locale",exc_info=True)
+ else:
+ log.debugWarning("wx does not support language %s" % lang)
+
import api
import winUser
import NVDAObjects.window
@@ -357,6 +373,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
app.MainLoop()

log.info("Exiting")
+ messageWindow.destroy()
if updateCheck:
_terminate(updateCheck)


diff --git a/source/globalCommands.py b/source/globalCommands.py
index 4265977..3c63d2e 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -29,6 +29,7 @@ import winUser
import appModuleHandler
import winKernel
import treeInterceptorHandler
+import browseMode
import scriptHandler
import ui
import braille
@@ -812,16 +813,22 @@ class GlobalCommands(ScriptableObject):
if focus in ti:
# Update the focus, as it will have cached that
there is no tree interceptor.
focus.treeInterceptor = ti
+ # If we just happened to create a browse mode
TreeInterceptor
+ # Then ensure that browse mode is reported
here. From the users point of view, browse mode was turned on.
+ if
isinstance(ti,browseMode.BrowseModeTreeInterceptor) and not ti.passThrough:
+ browseMode.reportPassThrough(ti,False)
+ braille.handler.handleGainFocus(ti)
return

- if not isinstance(vbuf, virtualBuffers.VirtualBuffer):
+ if not isinstance(vbuf, browseMode.BrowseModeTreeInterceptor):
return
- # Toggle virtual buffer pass-through.
+ # Toggle browse mode pass-through.
vbuf.passThrough = not vbuf.passThrough
- # If we are enabling pass-through, the user has explicitly
chosen to do so, so disable auto-pass-through.
- # If we're disabling pass-through, re-enable auto-pass-through.
- vbuf.disableAutoPassThrough = vbuf.passThrough
- virtualBuffers.reportPassThrough(vbuf)
+ if isinstance(vbuf,virtualBuffers.VirtualBuffer):
+ # If we are enabling pass-through, the user has
explicitly chosen to do so, so disable auto-pass-through.
+ # If we're disabling pass-through, re-enable
auto-pass-through.
+ vbuf.disableAutoPassThrough = vbuf.passThrough
+ browseMode.reportPassThrough(vbuf)
# Translators: Input help mode message for toggle focus and browse mode
command in web browsing and other situations.
script_toggleVirtualBufferPassThrough.__doc__=_("Toggles between browse
mode and focus mode. When in focus mode, keys will pass straight through to the
application, allowing you to interact directly with a control. When in browse
mode, you can navigate the document with the cursor, quick navigation keys,
etc.")

script_toggleVirtualBufferPassThrough.category=inputCore.SCRCAT_BROWSEMODE

diff --git a/source/gui/__init__.py b/source/gui/__init__.py
index 0007701..61d0c58 100644
--- a/source/gui/__init__.py
+++ b/source/gui/__init__.py
@@ -478,12 +478,24 @@ class SysTrayIcon(wx.TaskBarIcon):

def initialize():
global mainFrame
+ if mainFrame:
+ raise RuntimeError("GUI already initialized")
mainFrame = MainFrame()
wx.GetApp().SetTopWindow(mainFrame)

def terminate():
global mainFrame
- mainFrame.Destroy()
+ # This is called after the main loop exits because WM_QUIT exits the
main loop
+ # without destroying all objects correctly and we need to support
WM_QUIT.
+ # Therefore, any request to exit should exit the main loop.
+ wx.CallAfter(mainFrame.Destroy)
+ # #4460: We need another iteration of the main loop
+ # so that everything (especially the TaskBarIcon) is cleaned up
properly.
+ # ProcessPendingEvents doesn't seem to work, but MainLoop does.
+ # Because the top window gets destroyed,
+ # MainLoop thankfully returns pretty quickly.
+ wx.GetApp().MainLoop()
+ mainFrame = None

def showGui():
wx.CallAfter(mainFrame.showGui)
@@ -590,8 +602,8 @@ class WelcomeDialog(wx.Dialog):
try:
config.conf.save()
except:
- pass
- self.Close()
+ log.debugWarning("could not save",exc_info=True)
+ self.EndModal(wx.ID_OK)

@classmethod
def run(cls):
@@ -795,6 +807,10 @@ class IndeterminateProgressDialog(wx.ProgressDialog):
# Translators: Announced periodically to indicate
progress for an indeterminate progress bar.
speech.speakMessage(_("Please wait"))

+ def IsActive(self):
+ #4714: In wxPython 3, ProgressDialog.IsActive always seems to
return False.
+ return
winUser.isDescendantWindow(winUser.getForegroundWindow(), self.Handle)
+
def done(self):
self.timer.Stop()
if self.IsActive():

diff --git a/source/gui/addonGui.py b/source/gui/addonGui.py
index 2c687ba..63cbf32 100644
--- a/source/gui/addonGui.py
+++ b/source/gui/addonGui.py
@@ -157,7 +157,10 @@ class AddonsDialog(wx.Dialog):
del progressDialog
finally:
if closeAfter:
- self.onClose(None)
+ # #4460: If we do this immediately, wx seems to
drop the WM_QUIT sent if the user chooses to restart.
+ # This seems to have something to do with the
wx.ProgressDialog.
+ # The CallLater seems to work around this.
+ wx.CallLater(1, self.Close)

def OnRemoveClick(self,evt):
index=self.addonsList.GetFirstSelected()

diff --git a/source/gui/installerGui.py b/source/gui/installerGui.py
index dc192c6..5982e24 100644
--- a/source/gui/installerGui.py
+++ b/source/gui/installerGui.py
@@ -65,10 +65,11 @@ def
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,sil
gui.messageBox(msg+_("Please press OK to start the installed
copy."),
# Translators: The title of a dialog presented to
indicate a successful operation.
_("Success"))
+ # #4475: ensure that the first window of the new process is not hidden
by providing SW_SHOWNORMAL
shellapi.ShellExecute(None, None,
os.path.join(installer.defaultInstallPath,'nvda.exe'),
u"-r",
- None, 0)
+ None, winUser.SW_SHOWNORMAL)

def doSilentInstall():
prevInstall=installer.isPreviousInstall()

diff --git a/source/gui/logViewer.py b/source/gui/logViewer.py
index d25b65a..81093db 100755
--- a/source/gui/logViewer.py
+++ b/source/gui/logViewer.py
@@ -20,7 +20,7 @@ class LogViewer(wx.Frame):
self.Bind(wx.EVT_CLOSE, self.onClose)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.outputCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(500, 500),
style=wx.TE_MULTILINE | wx.TE_READONLY|wx.TE_RICH)
- self.outputCtrl.Bind(wx.EVT_CHAR, self.onOutputChar)
+ self.outputCtrl.Bind(wx.EVT_KEY_DOWN, self.onOutputKeyDown)
mainSizer.Add(self.outputCtrl, proportion=1, flag=wx.EXPAND)
self.SetSizer(mainSizer)
mainSizer.Fit(self)
@@ -78,10 +78,12 @@ class LogViewer(wx.Frame):
# Translators: Dialog text presented when NVDA cannot
save a log file.
gui.messageBox(_("Error saving log: %s") % e.strerror,
_("Error"), style=wx.OK | wx.ICON_ERROR, parent=self)

- def onOutputChar(self, evt):
+ def onOutputKeyDown(self, evt):
key = evt.GetKeyCode()
+ # #3763: WX 3 no longer passes escape via evt_char in richEdit
controls. Therefore evt_key_down must be used.
if key == wx.WXK_ESCAPE:
self.Close()
+ return
evt.Skip()

def activate():

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/55b50a6556e0/
Changeset: 55b50a6556e0
Branch: None
User: jteh
Date: 2015-01-20 02:46:31+00:00
Summary: Move UI code for math interaction and code for retrieving math
from a TextInfo into mathPres to eliminate some code duplication.

Affected #: 3 files

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 3c63d2e..4b8ebe8 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -1381,36 +1381,20 @@ class GlobalCommands(ScriptableObject):

def script_interactWithMath(self, gesture):
import mathPres
- mathPres.ensureInit()
- if not mathPres.interactionProvider:
+ mathMl = mathPres.getMathMlFromTextInfo(api.getReviewPosition())
+ if not mathMl:
+ obj = api.getNavigatorObject()
+ if obj.role == controlTypes.ROLE_MATH:
+ try:
+ mathMl = obj.mathMl
+ except (NotImplementedError, LookupError):
+ mathMl = None
+ if not mathMl:
# Translators: Reported when the user attempts math
interaction
- # but math interaction is not supported.
- ui.message(_("Math interaction not supported."))
+ # with something that isn't math.
+ ui.message(_("Not math"))
return
-
- pos = api.getReviewPosition()
- pos.expand(textInfos.UNIT_CHARACTER)
- for item in reversed(pos.getTextWithFields()):
- if not isinstance(item, textInfos.FieldCommand) or
item.command != "controlStart":
- continue
- field = item.field
- if field.get("role") != controlTypes.ROLE_MATH:
- continue
- try:
- return
mathPres.interactionProvider.interactWithMathMl(pos.getMathMl(field))
- except (NotImplementedError, LookupError):
- continue
-
- obj = api.getNavigatorObject()
- if obj.role == controlTypes.ROLE_MATH:
- try:
- return
mathPres.interactionProvider.interactWithMathMl(obj.mathMl)
- except (NotImplementedError, LookupError):
- pass
-
- # Translators: Reported when the user attempts math interaction
- # with something that isn't math.
- ui.message(_("Not math"))
+ mathPres.interactWithMathMl(mathMl)
# Translators: Describes a command.
script_interactWithMath.__doc__ = _("Begins interaction with math
content")


diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index 6a221c0..463f696 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -18,6 +18,8 @@ import api
import virtualBuffers
import eventHandler
from logHandler import log
+import ui
+import textInfos

class MathPresentationProvider(object):
"""Implements presentation of math content.
@@ -127,3 +129,41 @@ def stripExtraneousXml(xml):
Currently, this strips anything before the opening of the math tag.
"""
return RE_STRIP_XML_PREFIX.sub("", xml)
+
+def getMathMlFromTextInfo(pos):
+ """Get MathML (if any) at the start of a TextInfo.
+ The caller need not call L{ensureInit} before calling this function.
+ @param pos: The TextInfo in question.
+ @type pos: L{textInfos.TextInfo}
+ @return: The MathML or C{None} if there is no math.
+ @rtype: basestring
+ """
+ pos = pos.copy()
+ pos.expand(textInfos.UNIT_CHARACTER)
+ for item in reversed(pos.getTextWithFields()):
+ if not isinstance(item, textInfos.FieldCommand) or item.command
!= "controlStart":
+ continue
+ field = item.field
+ if field.get("role") != controlTypes.ROLE_MATH:
+ continue
+ try:
+ return pos.getMathMl(field)
+ except (NotImplementedError, LookupError):
+ continue
+ return None
+
+def interactWithMathMl(mathMl):
+ """Begin interaction with specified MathML markup, reporting any errors
to the user.
+ This is intended to be called from scripts.
+ If interaction isn't supported, this will be reported to the user.
+ The script should return after calling this function.
+ The caller need not call L{ensureInit} before calling this function.
+ @param mathMl: The MathML markup.
+ """
+ ensureInit()
+ if not interactionProvider:
+ # Translators: Reported when the user attempts math interaction
+ # but math interaction is not supported.
+ ui.message(_("Math interaction not supported."))
+ return
+ return interactionProvider.interactWithMathMl(mathMl)

diff --git a/source/virtualBuffers/__init__.py
b/source/virtualBuffers/__init__.py
index 95197e4..e50adee 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -3,7 +3,7 @@
#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) 2007-2014 NV Access Limited, Peter Vágner
+#Copyright (C) 2007-2015 NV Access Limited, Peter Vágner

import time
import threading
@@ -608,14 +608,8 @@ class VirtualBuffer(cursorManager.CursorManager,
browseMode.BrowseModeTreeInterc
return
if obj.role == controlTypes.ROLE_MATH:
import mathPres
- mathPres.ensureInit()
- if not mathPres.interactionProvider:
- # Translators: Reported when the user attempts
math interaction
- # but math interaction is not supported.
- ui.message(_("Math interaction not supported."))
- return
try:
- return
mathPres.interactionProvider.interactWithMathMl(obj.mathMl)
+ return mathPres.interactWithMathMl(obj.mathMl)
except (NotImplementedError, LookupError):
pass
return


https://bitbucket.org/nvdaaddonteam/nvda/commits/efb1ba478e30/
Changeset: efb1ba478e30
Branch: None
User: jteh
Date: 2015-01-20 02:53:15+00:00
Summary: Ms Word browse mode: Support math.

Affected #: 1 file

diff --git a/source/NVDAObjects/window/winword.py
b/source/NVDAObjects/window/winword.py
index 0e99769..bcd66a8 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -1,6 +1,6 @@
#appModules/winword.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NV Access Limited, Manish Agrawal
+#Copyright (C) 2006-2015 NV Access Limited, Manish Agrawal
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -409,6 +409,10 @@ class WordDocumentTextInfo(textInfos.TextInfo):
shouldIncludeLayoutTables=True #: layout tables should always be
included (no matter the user's browse mode setting).

def activate(self):
+ import mathPres
+ mathMl=mathPres.getMathMlFromTextInfo(self)
+ if mathMl:
+ return mathPres.interactWithMathMl(mathMl)
# Handle activating links.
# It is necessary to expand to word to get a link as the link's
first character is never actually in the link!
tempRange=self._rangeObj.duplicate
@@ -836,6 +840,9 @@ class BrowseModeWordDocumentTextInfo(textInfos.TextInfo):
def expand(self,unit):
return self.innerTextInfo.expand(unit)

+ def getMathMl(self, field):
+ return self.innerTextInfo.getMathMl(field)
+
class
WordDocumentTreeInterceptor(CursorManager,BrowseModeTreeInterceptorWithMakeTextInfo):

TextInfo=BrowseModeWordDocumentTextInfo


https://bitbucket.org/nvdaaddonteam/nvda/commits/937a7afda880/
Changeset: 937a7afda880
Branch: None
User: jteh
Date: 2015-01-20 07:02:12+00:00
Summary: Split table cells into a new TextInfo presentation category
(PRESCAT_CELL), as they are quite different to other PRESCAT_MARKERs.

For the other markers, the control field text is generally more interesting
than the content itself (which is usually just a space). This is not the case
for table cells, which are the same as containers except we don't want to
report when they end.
Also, math is now PRESCAT_MARKER, not PRESCAT_SINGLELINE.

Affected #: 2 files

diff --git a/source/speech.py b/source/speech.py
index 7c56047..856c708 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -1010,7 +1010,7 @@ def
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
speakEntry=True
speakWithinForLine=True
speakExitForOther=True
- elif presCat == attrs.PRESCAT_MARKER:
+ elif presCat in (attrs.PRESCAT_MARKER, attrs.PRESCAT_CELL):
speakEntry=True
elif presCat == attrs.PRESCAT_CONTAINER:
speakEntry=True

diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py
index 6ac580e..32e1476 100755
--- a/source/textInfos/__init__.py
+++ b/source/textInfos/__init__.py
@@ -31,10 +31,13 @@ class ControlField(Field):

#: This field is usually a single line item; e.g. a link or heading.
PRESCAT_SINGLELINE = "singleLine"
- #: This field is a marker; e.g. a separator or table cell.
+ #: This field is a marker; e.g. a separator or footnote.
PRESCAT_MARKER = "marker"
#: This field is a container, usually multi-line.
PRESCAT_CONTAINER = "container"
+ #: This field is a section of a larger container which is adjacent to
another similar section;
+ #: e.g. a table cell.
+ PRESCAT_CELL = "cell"
#: This field is just for layout.
PRESCAT_LAYOUT = None

@@ -71,13 +74,15 @@ class ControlField(Field):
return self.PRESCAT_LAYOUT

if (
- role in (controlTypes.ROLE_LINK,
controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON,
controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX,
controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB,
controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER,
controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX,
controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON,
controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW,
controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM,
controlTypes.ROLE_MATH)
+ role in (controlTypes.ROLE_LINK,
controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON,
controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX,
controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB,
controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER,
controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX,
controlTypes.ROLE_PROGRESSBAR, controlTypes.ROLE_TOGGLEBUTTON,
controlTypes.ROLE_MENUBUTTON, controlTypes.ROLE_TREEVIEW,
controlTypes.ROLE_CHECKMENUITEM, controlTypes.ROLE_RADIOMENUITEM)
or (role == controlTypes.ROLE_EDITABLETEXT and
controlTypes.STATE_MULTILINE not in states and (controlTypes.STATE_READONLY not
in states or controlTypes.STATE_FOCUSABLE in states))
or (role == controlTypes.ROLE_LIST and
controlTypes.STATE_READONLY not in states)
):
return self.PRESCAT_SINGLELINE
- elif role in (controlTypes.ROLE_SEPARATOR,
controlTypes.ROLE_FOOTNOTE, controlTypes.ROLE_ENDNOTE,
controlTypes.ROLE_EMBEDDEDOBJECT, controlTypes.ROLE_TABLECELL,
controlTypes.ROLE_TABLECOLUMNHEADER, controlTypes.ROLE_TABLEROWHEADER,
controlTypes.ROLE_APPLICATION, controlTypes.ROLE_DIALOG):
+ elif role in (controlTypes.ROLE_SEPARATOR,
controlTypes.ROLE_FOOTNOTE, controlTypes.ROLE_ENDNOTE,
controlTypes.ROLE_EMBEDDEDOBJECT, controlTypes.ROLE_APPLICATION,
controlTypes.ROLE_DIALOG, controlTypes.ROLE_MATH):
return self.PRESCAT_MARKER
+ elif role in (controlTypes.ROLE_TABLECELL,
controlTypes.ROLE_TABLECOLUMNHEADER, controlTypes.ROLE_TABLEROWHEADER):
+ return self.PRESCAT_CELL
elif (
role in (controlTypes.ROLE_BLOCKQUOTE,
controlTypes.ROLE_FRAME, controlTypes.ROLE_INTERNALFRAME,
controlTypes.ROLE_TOOLBAR, controlTypes.ROLE_MENUBAR,
controlTypes.ROLE_POPUPMENU, controlTypes.ROLE_TABLE)
or (role == controlTypes.ROLE_EDITABLETEXT and
(controlTypes.STATE_READONLY not in states or controlTypes.STATE_FOCUSABLE in
states) and controlTypes.STATE_MULTILINE in states)


https://bitbucket.org/nvdaaddonteam/nvda/commits/6b9e3ca85a2f/
Changeset: 6b9e3ca85a2f
Branch: None
User: jteh
Date: 2015-01-20 07:07:55+00:00
Summary: When the cursor is positioned over long math content, stop braille
from scrolling to the end of the content.

To achieve this, for PRESCAT_MARKER, the cursor/selection start is now placed
at the start of the field info (e.g. the math), not the actual (usually
useless) content.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index ea05d58..92aec0f 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -566,6 +566,8 @@ class NVDAObjectRegion(Region):

def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
presCat = field.getPresentationCategory(ancestors, formatConfig)
+ # Cache this for later use.
+ field._presCat = presCat
if reportStart:
# If this is a container, only report it if this is the start
of the node.
if presCat == field.PRESCAT_CONTAINER and not
field.get("_startOfNode"):
@@ -744,6 +746,18 @@ class TextInfoRegion(Region):
ctrlFields.append(field)
if not text:
continue
+ if getattr(field, "_presCat") ==
field.PRESCAT_MARKER:
+ # In this case, the field text
is what the user cares about,
+ # not the actual content.
+ fieldStart = len(self.rawText)
+ if fieldStart > 0:
+ # There'll be a space
before the field text.
+ fieldStart += 1
+ if
shouldMoveCursorToFirstContent:
+
shouldMoveCursorToFirstContent = False
+ self.cursorPos =
fieldStart
+ elif isSelection and
self._selectionStart is None:
+ self._selectionStart =
fieldStart
self._addFieldText(text)
elif cmd == "controlEnd":
field = ctrlFields.pop()


https://bitbucket.org/nvdaaddonteam/nvda/commits/7398611c9b10/
Changeset: 7398611c9b10
Branch: None
User: jteh
Date: 2015-02-04 00:11:54+00:00
Summary: Add eventHandler.requestEvents to request particular events that
are blocked by default; e.g. show events from a specific control or certain
events even when in the background.

Affected #: 1 file

diff --git a/source/eventHandler.py b/source/eventHandler.py
index 34946e9..832e108 100755
--- a/source/eventHandler.py
+++ b/source/eventHandler.py
@@ -181,6 +181,24 @@ def doPreDocumentLoadComplete(obj):

focusObject.treeInterceptor=treeInterceptorHandler.getTreeInterceptor(focusObject)
return True

+#: set of (eventName, processId, windowClassName) of events to accept.
+_acceptEvents = set()
+
+def requestEvents(eventName=None, processId=None, windowClassName=None):
+ """Request that particular events be accepted from a platform API.
+ Normally, L{shouldAcceptEvent} rejects certain events, including
+ most show events, events indicating changes in background processes,
etc.
+ This function allows plugins to override this for specific cases;
+ e.g. to receive show events from a specific control or
+ to receive certain events even when in the background.
+ Note that NVDA may block some events at a lower level and doesn't
listen for some event types at all.
+ In these cases, you will not be able to override this.
+ All arguments must be provided.
+ """
+ if not eventName or not processId or not windowClassName:
+ raise ValueError("eventName, processId or windowClassName not
specified")
+ _acceptEvents.add((eventName, processId, windowClassName))
+
def shouldAcceptEvent(eventName, windowHandle=None):
"""Check whether an event should be accepted from a platform API.
Creating NVDAObjects and executing events can be expensive
@@ -191,6 +209,11 @@ def shouldAcceptEvent(eventName, windowHandle=None):
if not windowHandle:
# We can't filter without a window handle.
return True
+ key = (eventName,
+ winUser.getWindowThreadProcessID(windowHandle)[0],
+ winUser.getClassName(windowHandle))
+ if key in _acceptEvents:
+ return True
if eventName == "valueChange" and
config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]:
return True
if eventName == "show":


https://bitbucket.org/nvdaaddonteam/nvda/commits/577a53ca25f9/
Changeset: 577a53ca25f9
Branch: None
User: jteh
Date: 2015-02-12 05:26:39+00:00
Summary: eSpeak: Fix problem where SSML tags were being pronounced if a
PhonemeCommand was immediately followed by some other command.

It seems eSpeak doesn't handle tags immediately following a phoneme block, so
always put a space after a phoneme block. This doesn't seem to have any adverse
consequences.

Affected #: 1 file

diff --git a/source/synthDrivers/espeak.py b/source/synthDrivers/espeak.py
index 3f4e5f1..72a46d7 100644
--- a/source/synthDrivers/espeak.py
+++ b/source/synthDrivers/espeak.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#synthDrivers/espeak.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2007-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy
+#Copyright (C) 2007-2015 NV Access Limited, Peter Vágner, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -117,7 +117,9 @@ class SynthDriver(SynthDriver):
# We can't use unicode.translate because we
want to reject unknown characters.
try:

phonemes="".join([self.IPA_TO_ESPEAK[char] for char in item.ipa])
- textList.append(u"[[%s]]"%phonemes)
+ # There needs to be a space after the
phoneme command.
+ # Otherwise, eSpeak will announce a
subsequent SSML tag instead of processing it.
+ textList.append(u"[[%s]] "%phonemes)
except KeyError:
log.debugWarning("Unknown character in
IPA string: %s"%item.ipa)
if item.text:


https://bitbucket.org/nvdaaddonteam/nvda/commits/712a3aee01d5/
Changeset: 712a3aee01d5
Branch: None
User: siddhartha_iitd
Date: 2015-02-12 07:07:27+00:00
Summary: Character descriptions are now handled correctly for conjunct
characters in certain Indian languages.

Affected #: 1 file

diff --git a/source/speech.py b/source/speech.py
index 105b784..1814435 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -37,6 +37,8 @@ beenCanceled=True
isPaused=False
curWordChars=[]

+#Set containing locale codes for languages supporting conjunct characters
+LANGS_WITH_CONJUNCT_CHARS = {'hi', 'as', 'bn', 'gu', 'kn', 'kok', 'ml', 'mni',
'mr', 'pa', 'te', 'ur'}
# The REASON_* constants in this module are deprecated and will be removed in
a future release.
# Use controlTypes.REASON_* instead.
from controlTypes import REASON_FOCUS, REASON_FOCUSENTERED, REASON_MOUSE,
REASON_QUERY, REASON_CHANGE, REASON_MESSAGE, REASON_SAYALL, REASON_CARET,
REASON_ONLYCACHE
@@ -179,18 +181,45 @@ def
speakSpelling(text,locale=None,useCharacterDescriptions=False):
return
queueHandler.registerGeneratorObject(_speakSpellingGenerator)

+def getCharDescListFromText(text,locale):
+ """This method prepares a list, which contains character and its
description for all characters the text is made up of, by checking the presence
of character descriptions in characterDescriptions.dic of that locale for all
possible combination of consecutive characters in the text.
+ This is done to take care of conjunct characters present in several
languages such as Hindi, Urdu, etc.
+ """
+ charDescList = []
+ charDesc=None
+ i = len(text)
+ while i:
+ subText = text[:i]
+ charDesc =
characterProcessing.getCharacterDescription(locale,subText)
+ if charDesc or i==1:
+ charDescList.append((subText,charDesc))
+ text = text[i:]
+ i = len(text)
+ else:
+ i = i - 1
+ return charDescList
+
def _speakSpellingGen(text,locale,useCharacterDescriptions):
synth=getSynth()
synthConfig=config.conf["speech"][synth.name]
buf=[(text,locale,useCharacterDescriptions)]
for text,locale,useCharacterDescriptions in buf:
textLength=len(text)
- for count,char in enumerate(text):
+ count = 0
+ localeHasConjuncts = True if locale.split('_',1)[0] in
LANGS_WITH_CONJUNCT_CHARS else False
+ charDescList = getCharDescListFromText(text,locale) if
localeHasConjuncts else text
+ for item in charDescList:
+ if localeHasConjuncts:
+ # item is a tuple containing character and its
description
+ char = item[0]
+ charDesc = item[1]
+ else:
+ # item is just a character.
+ char = item
+ if useCharacterDescriptions:
+
charDesc=characterProcessing.getCharacterDescription(locale,char.lower())
uppercase=char.isupper()
- charDesc=None
- if useCharacterDescriptions:
-
charDesc=characterProcessing.getCharacterDescription(locale,char.lower())
- if charDesc:
+ if useCharacterDescriptions and charDesc:
#Consider changing to multiple synth speech
calls
char=charDesc[0] if textLength>1 else
u"\u3001".join(charDesc)
else:
@@ -201,6 +230,7 @@ def _speakSpellingGen(text,locale,useCharacterDescriptions):
if uppercase and synth.isSupported("pitch") and
synthConfig["capPitchChange"]:
oldPitch=synthConfig["pitch"]

synth.pitch=max(0,min(oldPitch+synthConfig["capPitchChange"],100))
+ count = len(char)
index=count+1
log.io("Speaking character %r"%char)
speechSequence=[LangChangeCommand(locale)] if
config.conf['speech']['autoLanguageSwitching'] else []


https://bitbucket.org/nvdaaddonteam/nvda/commits/f5b75d2384f1/
Changeset: f5b75d2384f1
Branch: None
User: jteh
Date: 2015-02-12 07:08:13+00:00
Summary: Merge branch 't4582' into next

Incubates #4582.

Affected #: 35 files

diff --git a/source/locale/ca/LC_MESSAGES/nvda.po
b/source/locale/ca/LC_MESSAGES/nvda.po
index 0b34d57..6c189b4 100644
--- a/source/locale/ca/LC_MESSAGES/nvda.po
+++ b/source/locale/ca/LC_MESSAGES/nvda.po
@@ -2086,11 +2086,11 @@ msgstr "Entrada"

#. Translators: This will be presented when the input help is toggled.
msgid "input help on"
-msgstr "Ajuda a l’entrada activada"
+msgstr "Ajuda a l'entrada activada"

#. Translators: This will be presented when the input help is toggled.
msgid "input help off"
-msgstr "Ajuda a l’entrada desactivada"
+msgstr "Ajuda a l'entrada desactivada"

#. Translators: Input help mode message for toggle input help command.
msgid ""
@@ -4412,10 +4412,9 @@ msgstr "S'està esperant al Powerpoint..."
msgid "Skype"
msgstr "Skype"

-#, fuzzy
msgid "Reports and moves the review cursor to a recent message"
msgstr ""
-"Commuta entre si el cursor de revisió segueix o no el cursor del sistema."
+"Mou el cursor de revisió a un missatge recent i n'informa del contingut"

#. Translators: Indicates that a contact stopped typing.
msgid "Typing stopped"
@@ -5913,7 +5912,7 @@ msgstr "Indicació audible del mode de focus i de
navegació"
#. browse mode settings dialog.
msgid "&Trap all non-command gestures from reaching the document"
msgstr ""
-"&Impedeix que tots els gestos que no corresponen a instruccions arribin al "
+"Impedeix que tots els gestos que no corresponen a instruccions arribin al "
"document"

#. Translators: This is the label for the document formatting dialog.

diff --git a/source/locale/de/LC_MESSAGES/nvda.po
b/source/locale/de/LC_MESSAGES/nvda.po
index 68efb6d..bb8b936 100644
--- a/source/locale/de/LC_MESSAGES/nvda.po
+++ b/source/locale/de/LC_MESSAGES/nvda.po
@@ -11,7 +11,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.7.1\n"
+"X-Generator: Poedit 1.7.4\n"
"X-Poedit-Bookmarks: 999,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"

#. Translators: Message to indicate User Account Control (UAC) or other secure
desktop screen is active.
@@ -4957,7 +4957,7 @@ msgstr "&Installieren..."
#. Remove a speech dictionary entry.
#. Translators: The label of a button to remove a gesture in the Input
Gestures dialog.
msgid "&Remove"
-msgstr "&Entfernen"
+msgstr "Ent&fernen"

#. Translators: The label of a button in Add-ons Manager to open the Add-ons
website and get more add-ons.
msgid "&Get add-ons..."
@@ -5514,7 +5514,7 @@ msgid ""
"Use currently saved settings on the logon and other secure screens (requires "
"administrator privileges)"
msgstr ""
-"A&ktuell gespeicherte Einstellungen im Anmeldebildschirm und bei "
+"Aktuell &gespeicherte Einstellungen im Anmeldebildschirm und bei "
"Sicherheitsmeldungen verwenden (erfordert Administrationsberechtigungen)"

#. Translators: The label of a checkbox in general settings to toggle
automatic checking for updated versions of NVDA (if not checked, user must
check for updates manually).
@@ -6117,7 +6117,7 @@ msgstr "Ersetzen durch"

#. Translators: The label for a column in dictionary entries list used to
identify whether the entry is case sensitive or not.
msgid "case"
-msgstr "Schreibweise ignorieren"
+msgstr "Schreibweise beachten"

#. Translators: The label for a column in dictionary entries list used to
identify whether the entry is a regular expression, matches whole words, or
matches anywhere.
msgid "Type"

diff --git a/source/locale/fi/LC_MESSAGES/nvda.po
b/source/locale/fi/LC_MESSAGES/nvda.po
index 71c6b19..7bfa509 100644
--- a/source/locale/fi/LC_MESSAGES/nvda.po
+++ b/source/locale/fi/LC_MESSAGES/nvda.po
@@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: NVDA bzr main:5884\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-03 19:12+1000\n"
-"PO-Revision-Date: 2015-02-04 13:52+0200\n"
+"PO-Revision-Date: 2015-02-06 09:05+0200\n"
"Last-Translator: Jani Kinnunen <jani.kinnunen@xxxxxxxxxx>\n"
"Language-Team: fi <jani.kinnunen@xxxxxxxxxx>\n"
"Language: fi\n"
@@ -934,19 +934,19 @@ msgstr "ei edellisiä erottimia"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the next radio button"
-msgstr "siirtää seuraavan valintapainikkeen kohdalle"
+msgstr "siirtää seuraavan vaihtoehtopainikkeen kohdalle"

#. Translators: Message presented when the browse mode element is not found.
msgid "no next radio button"
-msgstr "ei enempää valintapainikkeita"
+msgstr "ei enempää vaihtoehtopainikkeita"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the previous radio button"
-msgstr "siirtää edellisen valintapainikkeen kohdalle"
+msgstr "siirtää edellisen vaihtoehtopainikkeen kohdalle"

#. Translators: Message presented when the browse mode element is not found.
msgid "no previous radio button"
-msgstr "ei edellisiä valintapainikkeita"
+msgstr "ei edellisiä vaihtoehtopainikkeita"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the next combo box"
@@ -1248,7 +1248,7 @@ msgstr "valintaruutu"

#. Translators: The text used to identify radio buttons such as yes or no
radio button.
msgid "radio button"
-msgstr "valintapainike"
+msgstr "vaihtoehtopainike"

#. Translators: The word used to identify a static text such as dialog text.
msgid "text"
@@ -1525,7 +1525,7 @@ msgstr "sivu"

#. Translators: Identifies a radio menu item.
msgid "radio menu item"
-msgstr "valintapainike valikon kohteena"
+msgstr "vaihtoehtopainike valikon kohteena"

#. Translators: Identifies a layered pane.
msgid "layered pane"
@@ -2330,7 +2330,7 @@ msgid ""
"position of the caret inside it, if possible."
msgstr ""
"Siirtää navigointiobjektin nykyiseen kohdistukseen ja "
-"tarkastelukohdistimensiinä olevan kohdistimen kohdalle, mikäli mahdollista."
+"tarkastelukohdistimensiinä olevan kohdistimen kohdalle, jos mahdollista."

#. Translators: Reported when:
#. 1. There is no focusable object e.g. cannot use tab and shift tab to move
to controls.
@@ -5555,12 +5555,12 @@ msgstr "Puheäänen asetukset"
#. Translators: This is the label for a checkbox in the
#. voice settings dialog (if checked, text will be read using the voice for
the language of the text).
msgid "Automatic language switching (when supported)"
-msgstr "Vaihda kieltä automaattisesti (mikäli mahdollista)"
+msgstr "Vaihda kieltä automaattisesti (jos mahdollista)"

#. Translators: This is the label for a checkbox in the
#. voice settings dialog (if checked, different voices for dialects will be
used to read text in that dialect).
msgid "Automatic dialect switching (when supported)"
-msgstr "Vaihda murretta automaattisesti (mikäli mahdollista)"
+msgstr "Vaihda murretta automaattisesti (jos mahdollista)"

#. Translators: This is the label for a combobox in the
#. voice settings dialog (possible choices are none, some, most and all).

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/e0510d38549f/
Changeset: e0510d38549f
Branch: None
User: dineshkaushal
Date: 2015-02-12 07:26:27+00:00
Summary: New braille translation tables for several Indian languages.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index e845eaa..5d8d78f 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -33,6 +33,12 @@ TABLES = (
("ar-fa.utb", _("Farsi grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("as-in-g1.utb", _("Assamese grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("be-in-g1.utb", _("Bengali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("bg.ctb", _("Bulgarian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -114,6 +120,9 @@ TABLES = (
("fr-bfu-g2.ctb", _("French (unified) Grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("gu-in-g1.utb", _("Gujarati grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("gr-gr-g1.utb", _("Greek (Greece) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -141,15 +150,30 @@ TABLES = (
("it-it-comp8.utb", _("Italian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ka-in-g1.utb", _("Kannada grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ko-g1.ctb", _("Korean grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ko-g2.ctb", _("Korean grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ks-in-g1.utb", _("Kashmiri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Lv-Lv-g1.utb", _("Latvian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ml-in-g1.utb", _("Malayalam grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mn-in-g1.utb", _("Manipuri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mr-in-g1.utb", _("Marathi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("nl-be-g1.utb", _("Dutch (Belgium) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -171,6 +195,12 @@ TABLES = (
("No-No-g3.ctb", _("Norwegian grade 3"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("np-in-g1.utb", _("Nepali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("or-in-g1.utb", _("Oriya grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Pl-Pl-g1.utb", _("Polish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -183,12 +213,18 @@ TABLES = (
("Pt-Pt-g2.ctb", _("Portuguese grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("pu-in-g1.utb", _("Punjabi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ru-compbrl.ctb", _("Russian braille for computer code"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ru-ru-g1.utb", _("Russian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("sa-in-g1.utb", _("Sanskrit grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Se-Se-g1.utb", _("Swedish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -204,6 +240,9 @@ TABLES = (
("ta-ta-g1.ctb", _("Tamil grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("te-in-g1.utb", _("Telegu grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("tr.ctb", _("Turkish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.


https://bitbucket.org/nvdaaddonteam/nvda/commits/29fdc711cefe/
Changeset: 29fdc711cefe
Branch: None
User: jteh
Date: 2015-02-12 07:27:00+00:00
Summary: Merge branch 't4778' into next

Incubates #4778.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index af803f0..a4ac5ae 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -33,6 +33,12 @@ TABLES = (
("ar-fa.utb", _("Farsi grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("as-in-g1.utb", _("Assamese grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("be-in-g1.utb", _("Bengali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("bg.ctb", _("Bulgarian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -114,6 +120,9 @@ TABLES = (
("fr-bfu-g2.ctb", _("French (unified) Grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("gu-in-g1.utb", _("Gujarati grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("gr-gr-g1.utb", _("Greek (Greece) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -141,15 +150,30 @@ TABLES = (
("it-it-comp8.utb", _("Italian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ka-in-g1.utb", _("Kannada grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ko-g1.ctb", _("Korean grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ko-g2.ctb", _("Korean grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ks-in-g1.utb", _("Kashmiri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Lv-Lv-g1.utb", _("Latvian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ml-in-g1.utb", _("Malayalam grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mn-in-g1.utb", _("Manipuri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mr-in-g1.utb", _("Marathi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("nl-be-g1.utb", _("Dutch (Belgium) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -171,6 +195,12 @@ TABLES = (
("No-No-g3.ctb", _("Norwegian grade 3"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("np-in-g1.utb", _("Nepali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("or-in-g1.utb", _("Oriya grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Pl-Pl-g1.utb", _("Polish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -183,12 +213,18 @@ TABLES = (
("Pt-Pt-g2.ctb", _("Portuguese grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("pu-in-g1.utb", _("Punjabi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ru-compbrl.ctb", _("Russian braille for computer code"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ru-ru-g1.utb", _("Russian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("sa-in-g1.utb", _("Sanskrit grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Se-Se-g1.utb", _("Swedish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -204,6 +240,9 @@ TABLES = (
("ta-ta-g1.ctb", _("Tamil grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("te-in-g1.utb", _("Telegu grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("tr.ctb", _("Turkish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.


https://bitbucket.org/nvdaaddonteam/nvda/commits/f372f6ef6f97/
Changeset: f372f6ef6f97
Branch: None
User: mdcurran
Date: 2015-02-13 10:14:22+00:00
Summary: Merge branch 't1987' into next. Incubates #1987

Affected #: 3 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 884dd94..da2db7d 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -1,6 +1,6 @@
#NVDAObjects/excel.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NVDA Contributors <http://www.nvaccess.org/>
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -28,6 +28,8 @@ from . import Window
from .. import NVDAObjectTextInfo
import scriptHandler
import ctypes
+import browseMode
+

xlCenter=-4108
xlJustify=-4130
@@ -52,8 +54,255 @@ xlA1 = 1
xlRC = 2
xlUnderlineStyleNone=-4142

+#Excel cell types
+xlCellTypeAllFormatConditions =-4172 # from enum XlCellType
+xlCellTypeAllValidation =-4174 # from enum XlCellType
+xlCellTypeBlanks =4 # from enum XlCellType
+xlCellTypeComments =-4144 # from enum XlCellType
+xlCellTypeConstants =2 # from enum XlCellType
+xlCellTypeFormulas =-4123 # from enum XlCellType
+xlCellTypeLastCell =11 # from enum XlCellType
+xlCellTypeSameFormatConditions=-4173 # from enum XlCellType
+xlCellTypeSameValidation =-4175 # from enum XlCellType
+xlCellTypeVisible =12 # from enum XlCellType
+
+re_RC=re.compile(r'R(?:\[(\d+)\])?C(?:\[(\d+)\])?')
re_absRC=re.compile(r'^R(\d+)C(\d+)(?::R(\d+)C(\d+))?$')

+class ExcelQuickNavItem(browseMode.QuickNavItem):
+
+ def __init__( self , nodeType , document , itemObject , itemCollection
):
+ self.excelItemObject = itemObject
+ self.excelItemCollection = itemCollection
+ super( ExcelQuickNavItem ,self).__init__( nodeType , document )
+
+ def activate(self):
+ pass
+
+ def isChild(self,parent):
+ return False
+
+ def report(self,readUnit=None):
+ pass
+
+class ExcelChartQuickNavItem(ExcelQuickNavItem):
+
+ def __init__( self , nodeType , document , chartObject ,
chartCollection ):
+ self.chartIndex = chartObject.Index
+ if chartObject.Chart.HasTitle:
+
+ self.label = chartObject.Chart.ChartTitle.Text + " " +
chartObject.TopLeftCell.address(False,False,1,False) + "-" +
chartObject.BottomRightCell.address(False,False,1,False)
+
+ else:
+
+ self.label = chartObject.Name + " " +
chartObject.TopLeftCell.address(False,False,1,False) + "-" +
chartObject.BottomRightCell.address(False,False,1,False)
+
+ super( ExcelChartQuickNavItem ,self).__init__( nodeType ,
document , chartObject , chartCollection )
+
+ def __lt__(self,other):
+ return self.chartIndex < other.chartIndex
+
+ def moveTo(self):
+ try:
+ self.excelItemObject.Activate()
+
+ # After activate(), though the chart object is
selected,
+
+ # pressing arrow keys moves the object, rather than
+
+ # let use go inside for sub-objects. Somehow
+ # calling an COM function on a different object fixes that !
+
+ log.debugWarning( self.excelItemCollection.Count )
+
+ except(COMError):
+
+ pass
+ focus=api.getDesktopObject().objectWithFocus()
+ if not focus or not isinstance(focus,ExcelBase):
+ return
+ # Charts are not yet automatically detected with
objectFromFocus, so therefore use selection
+ sel=focus._getSelection()
+ if not sel:
+ return
+ eventHandler.queueEvent("gainFocus",sel)
+
+
+ @property
+ def isAfterSelection(self):
+ activeCell = self.document.Application.ActiveCell
+ #log.debugWarning("active row: {} active column: {} current
row: {} current column: {}".format ( activeCell.row , activeCell.column ,
self.excelCommentObject.row , self.excelCommentObject.column ) )
+
+ if self.excelItemObject.TopLeftCell.row == activeCell.row:
+ if self.excelItemObject.TopLeftCell.column >
activeCell.column:
+ return False
+ elif self.excelItemObject.TopLeftCell.row > activeCell.row:
+ return False
+ return True
+
+class ExcelRangeBasedQuickNavItem(ExcelQuickNavItem):
+
+ def __lt__(self,other):
+ if self.excelItemObject.row == other.excelItemObject.row:
+ return self.excelItemObject.column <
other.excelItemObject.column
+ else:
+ return self.excelItemObject.row <
other.excelItemObject.row
+
+ def moveTo(self):
+ self.excelItemObject.Activate()
+
eventHandler.queueEvent("gainFocus",api.getDesktopObject().objectWithFocus())
+
+ @property
+ def isAfterSelection(self):
+ activeCell = self.document.Application.ActiveCell
+ log.debugWarning("active row: {} active column: {} current row:
{} current column: {}".format ( activeCell.row , activeCell.column ,
self.excelItemObject.row , self.excelItemObject.column ) )
+
+ if self.excelItemObject.row == activeCell.row:
+ if self.excelItemObject.column > activeCell.column:
+ return False
+ elif self.excelItemObject.row > activeCell.row:
+ return False
+ return True
+
+class ExcelCommentQuickNavItem(ExcelRangeBasedQuickNavItem):
+
+ def __init__( self , nodeType , document , commentObject ,
commentCollection ):
+ self.label = commentObject.address(False,False,1,False) + " " +
commentObject.Comment.Text()
+ super( ExcelCommentQuickNavItem , self).__init__( nodeType ,
document , commentObject , commentCollection )
+
+class ExcelFormulaQuickNavItem(ExcelRangeBasedQuickNavItem):
+
+ def __init__( self , nodeType , document , formulaObject ,
formulaCollection ):
+ self.label = formulaObject.address(False,False,1,False) + " " +
formulaObject.Formula
+ super( ExcelFormulaQuickNavItem , self).__init__( nodeType ,
document , formulaObject , formulaCollection )
+
+class ExcelQuicknavIterator(object):
+ """
+ Allows iterating over an MS excel collection (e.g. Comments, Formulas
or charts) emitting L{QuickNavItem} objects.
+ """
+
+ def __init__(self, itemType , document , direction , includeCurrent):
+ """
+ See L{QuickNavItemIterator} for itemType, document and
direction definitions.
+ @ param includeCurrent: if true then any item at the initial
position will be also emitted rather than just further ones.
+ """
+ self.document=document
+ self.itemType=itemType
+ self.direction=direction if direction else "next"
+ self.includeCurrent=includeCurrent
+
+ def collectionFromWorksheet(self,worksheetObject):
+ """
+ Fetches a Microsoft Excel collection object from a Microsoft
excel worksheet object. E.g. charts, comments, or formula.
+ @param worksheetObject: a Microsoft excel worksheet object.
+ @return: a Microsoft excel collection object.
+ """
+ raise NotImplementedError
+
+ def filter(self,item):
+ """
+ Only allows certain items fom a collection to be emitted. E.g.
a chart .
+ @param item: an item from a Microsoft excel collection (e.g.
chart object).
+ @return True if this item should be allowd, false otherwise.
+ @rtype: bool
+ """
+ return True
+
+ def iterate(self):
+ """
+ returns a generator that emits L{QuickNavItem} objects for this
collection.
+ """
+ items=self.collectionFromWorksheet(self.document)
+ if not items:
+ return
+ if self.direction=="previous":
+ items=reversed(items)
+ for collectionItem in items:
+
item=self.quickNavItemClass(self.itemType,self.document,collectionItem , items )
+ if not self.filter(collectionItem):
+ continue
+ yield item
+
+class ChartExcelCollectionQuicknavIterator(ExcelQuicknavIterator):
+ quickNavItemClass=ExcelChartQuickNavItem#: the QuickNavItem class that
should be instanciated and emitted.
+ def collectionFromWorksheet( self , worksheetObject ):
+ return worksheetObject.ChartObjects()
+
+class CommentExcelCollectionQuicknavIterator(ExcelQuicknavIterator):
+ quickNavItemClass=ExcelCommentQuickNavItem#: the QuickNavItem class
that should be instanciated and emitted.
+ def collectionFromWorksheet( self , worksheetObject ):
+ try:
+ return worksheetObject.cells.SpecialCells(
xlCellTypeComments )
+ except(COMError):
+
+ return None
+
+class FormulaExcelCollectionQuicknavIterator(ExcelQuicknavIterator):
+ quickNavItemClass=ExcelFormulaQuickNavItem#: the QuickNavItem class
that should be instanciated and emitted.
+ def collectionFromWorksheet( self , worksheetObject ):
+ try:
+ return worksheetObject.cells.SpecialCells(
xlCellTypeFormulas )
+ except(COMError):
+
+ return None
+
+class ExcelBrowseModeTreeInterceptor(browseMode.BrowseModeTreeInterceptor):
+
+ needsReviewCursorTextInfoWrapper=False
+ passThrough=True
+
+ def _get_isAlive(self):
+ if not winUser.isWindow(self.rootNVDAObject.windowHandle):
+ return False
+ try:
+ return
self.rootNVDAObject.excelWorksheetObject.name==self.rootNVDAObject.excelApplicationObject.activeSheet.name
+ except (COMError,AttributeError,NameError):
+ log.debugWarning("could not compair sheet
names",exc_info=True)
+ return False
+
+
+ def __contains__(self,obj):
+ return
winUser.isDescendantWindow(self.rootNVDAObject.windowHandle,obj.windowHandle)
+
+
+
+ def _set_selection(self,info):
+ super(ExcelBrowseModeTreeInterceptor,self)._set_selection(info)
+ #review.handleCaretMove(info)
+
+ def _get_ElementsListDialog(self):
+ return ElementsListDialog
+
+ def _iterNodesByType(self,nodeType,direction="next",pos=None):
+ if nodeType=="chart":
+ return ChartExcelCollectionQuicknavIterator( nodeType ,
self.rootNVDAObject.excelWorksheetObject , direction , None ).iterate()
+ elif nodeType=="comment":
+ return CommentExcelCollectionQuicknavIterator( nodeType
, self.rootNVDAObject.excelWorksheetObject , direction , None ).iterate()
+ elif nodeType=="formula":
+ return FormulaExcelCollectionQuicknavIterator( nodeType
, self.rootNVDAObject.excelWorksheetObject , direction , None ).iterate()
+ else:
+ raise NotImplementedError
+
+ def script_elementsList(self,gesture):
+
super(ExcelBrowseModeTreeInterceptor,self).script_elementsList(gesture)
+ # Translators: the description for the elements list dialog script on
virtualBuffers.
+ script_elementsList.__doc__ = _("Presents a list of links, headings or
landmarks")
+ script_elementsList.ignoreTreeInterceptorPassThrough=True
+
+class ElementsListDialog(browseMode.ElementsListDialog):
+
+ ELEMENT_TYPES=(
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("chart", _("&Chart")),
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("comment", _("&Comment")),
+ # Translators: The label of a radio button to select the type
of element
+ # in the browse mode Elements List dialog.
+ ("formula", _("&Formula")),
+ )
+
class ExcelBase(Window):
"""A base that all Excel NVDAObjects inherit from, which contains some
useful methods."""

@@ -99,14 +348,27 @@ class ExcelBase(Window):
isMerged=selection.mergeCells
except (COMError,NameError):
isMerged=False
+
+ try:
+ numCells=selection.count
+ except (COMError,NameError):
+ numCells=0
+
+ isChartActive = True if self.excelWindowObject.ActiveChart else
False
+ obj=None
if isMerged:

obj=ExcelMergedCell(windowHandle=self.windowHandle,excelWindowObject=self.excelWindowObject,excelCellObject=selection.item(1))
- elif selection.Count>1:
+ elif numCells>1:

obj=ExcelSelection(windowHandle=self.windowHandle,excelWindowObject=self.excelWindowObject,excelRangeObject=selection)
- else:
+ elif numCells==1:

obj=ExcelCell(windowHandle=self.windowHandle,excelWindowObject=self.excelWindowObject,excelCellObject=selection)
+ elif isChartActive:
+ selection = self.excelWindowObject.ActiveChart
+ import excelChart
+
obj=excelChart.ExcelChart(windowHandle=self.windowHandle,excelWindowObject=self.excelWindowObject,excelChartObject=selection)
return obj

+
class Excel7Window(ExcelBase):
"""An overlay class for Window for the EXCEL7 window class, which
simply bounces focus to the active excel cell."""

@@ -126,6 +388,9 @@ class Excel7Window(ExcelBase):

class ExcelWorksheet(ExcelBase):

+
+ treeInterceptorClass=ExcelBrowseModeTreeInterceptor
+
role=controlTypes.ROLE_TABLE

def _get_excelApplicationObject(self):
@@ -877,9 +1142,10 @@ class ExcelMergedCell(ExcelCell):

def _get_cellCoordsText(self):
return self.getCellAddress(self.excelCellObject.mergeArea)
-
+
def _get_rowSpan(self):
return self.excelCellObject.mergeArea.rows.count

def _get_colSpan(self):
return self.excelCellObject.mergeArea.columns.count
+

diff --git a/source/NVDAObjects/window/excelChart.py
b/source/NVDAObjects/window/excelChart.py
new file mode 100644
index 0000000..2cbead2
--- /dev/null
+++ b/source/NVDAObjects/window/excelChart.py
@@ -0,0 +1,919 @@
+#NVDAObjects/excel.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+# adding support for excel charts ticket 1987
+
+import time
+import ui
+import eventHandler
+import controlTypes
+import excel
+from logHandler import log
+from . import Window
+import scriptHandler
+import colors
+
+from comtypes.client import *
+import comtypes
+from comtypes.automation import IDispatch
+import ctypes
+import comtypes.GUID
+
+import math
+from NVDAObjects import NVDAObject
+import string
+import weakref
+
+
+#ChartEvents definition
+class ChartEvents(IDispatch):
+ _case_insensitive_ = True
+ _iid_ = comtypes.GUID('{0002440F-0000-0000-C000-000000000046}')
+ _idlflags_ = ['hidden']
+ _methods_ = []
+ _disp_methods_=[
+ comtypes.DISPMETHOD([comtypes.dispid(235)], None, 'Select',
+ ( ['in'], ctypes.c_int, 'ElementID' ),
+ ( ['in'], ctypes.c_int, 'Arg1' ),
+ ( ['in'], ctypes.c_int, 'Arg2' )),
+ ]
+
+# Chart types in Microsoft Excel.
+xl3DArea = -4098
+xl3DAreaStacked = 78
+xl3DAreaStacked100 = 79
+xl3DBarClustered = 60
+xl3DBarStacked = 61
+xl3DBarStacked100 = 62
+xl3DColumn = -4100
+xl3DColumnClustered = 54
+xl3DColumnStacked = 55
+xl3DColumnStacked100 = 56
+xl3DLine = -4101
+xl3DPie = -4102
+xl3DPieExploded = 70
+xlArea = 1
+xlAreaStacked = 76
+xlAreaStacked100 = 77
+xlBarClustered = 57
+xlBarOfPie = 71
+xlBarStacked = 58
+xlBarStacked100 = 59
+xlBubble = 15
+xlBubble3DEffect = 87
+xlColumnClustered = 51
+xlColumnStacked = 52
+xlColumnStacked100 = 53
+xlConeBarClustered = 102
+xlConeBarStacked = 103
+xlConeBarStacked100 = 104
+xlConeCol = 105
+xlConeColClustered = 99
+xlConeColStacked = 100
+xlConeColStacked100 = 101
+xlCylinderBarClustered = 95
+xlCylinderBarStacked = 96
+xlCylinderBarStacked100 = 97
+xlCylinderCol = 98
+xlCylinderColClustered = 92
+xlCylinderColStacked = 93
+xlCylinderColStacked100 = 94
+xlDoughnut = -4120
+xlDoughnutExploded = 80
+xlLine = 4
+xlLineMarkers = 65
+xlLineMarkersStacked = 66
+xlLineMarkersStacked100 = 67
+xlLineStacked = 63
+xlLineStacked100 = 64
+xlPie = 5
+xlPieExploded = 69
+xlPieOfPie = 68
+xlPyramidBarClustered = 109
+xlPyramidBarStacked = 110
+xlPyramidBarStacked100 = 111
+xlPyramidCol = 112
+xlPyramidColClustered = 106
+xlPyramidColStacked = 107
+xlPyramidColStacked100 = 108
+xlRadar = -4151
+xlRadarFilled = 82
+xlRadarMarkers = 81
+xlStockHLC = 88
+xlStockOHLC = 89
+xlStockVHLC = 90
+xlStockVOHLC = 91
+xlSurface = 83
+xlSurfaceTopView = 85
+xlSurfaceTopViewWireframe = 86
+xlSurfaceWireframe = 84
+xlXYScatter = -4169
+xlXYScatterLines = 74
+xlXYScatterLinesNoMarkers = 75
+xlXYScatterSmooth = 72
+xlXYScatterSmoothNoMarkers = 73
+
+# Dictionary for the Description of chart types.
+chartTypeDict = {
+ # Translators: Chart type
+ xl3DArea : _( "3D Area" ),
+ # Translators: Chart type
+ xl3DAreaStacked : _( "3D Stacked Area" ),
+ # Translators: Chart type
+ xl3DAreaStacked100 : _( "100 percent Stacked Area" ) ,
+ # Translators: Chart type
+ xl3DBarClustered : _( "3D Clustered Bar" ) ,
+ # Translators: Chart type
+ xl3DBarStacked : _( "3D Stacked Bar" ) ,
+ # Translators: Chart type
+ xl3DBarStacked100 : _( "3D 100 percent Stacked Bar" ) ,
+ # Translators: Chart type
+ xl3DColumn : _( "3D Column" ) ,
+ # Translators: Chart type
+ xl3DColumnClustered : _( "3D Clustered Column" ),
+ # Translators: Chart type
+ xl3DColumnStacked : _( "3D Stacked Column" ) ,
+ # Translators: Chart type
+ xl3DColumnStacked100 : _( "3D 100 percent Stacked Column" ) ,
+ # Translators: Chart type
+ xl3DLine : _( "3D Line" ) ,
+ # Translators: Chart type
+ xl3DPie : _( "3D Pie" ) ,
+ # Translators: Chart type
+ xl3DPieExploded : _( "Exploded 3D Pie" ) ,
+ # Translators: Chart type
+ xlArea : _( "Area" ) ,
+ # Translators: Chart type
+ xlAreaStacked : _( "Stacked Area" ) ,
+ # Translators: Chart type
+ xlAreaStacked100 : _( "100 percent Stacked Area" ) ,
+ # Translators: Chart type
+ xlBarClustered : _( "Clustered Bar" ) ,
+ # Translators: Chart type
+ xlBarOfPie : _( "Bar of Pie" ) ,
+ # Translators: Chart type
+ xlBarStacked : _( "Stacked Bar" ) ,
+ # Translators: Chart type
+ xlBarStacked100 : _( "100 percent Stacked Bar" ) ,
+ # Translators: Chart type
+ xlBubble : _( "Bubble" ) ,
+ # Translators: Chart type
+ xlBubble3DEffect : _( "Bubble with 3D effects" ) ,
+ # Translators: Chart type
+ xlColumnClustered : _( "Clustered Column" ) ,
+ # Translators: Chart type
+ xlColumnStacked : _( "Stacked Column" ) ,
+ # Translators: Chart type
+ xlColumnStacked100 : _( "100 percent Stacked Column" ) ,
+ # Translators: Chart type
+ xlConeBarClustered : _( "Clustered Cone Bar" ) ,
+ # Translators: Chart type
+ xlConeBarStacked : _( "Stacked Cone Bar" ) ,
+ # Translators: Chart type
+ xlConeBarStacked100 : _( "100 percent Stacked Cone Bar" ) ,
+ # Translators: Chart type
+ xlConeCol : _( "3D Cone Column" ) ,
+ # Translators: Chart type
+ xlConeColClustered : _( "Clustered Cone Column" ) ,
+ # Translators: Chart type
+ xlConeColStacked : _( "Stacked Cone Column" ),
+ # Translators: Chart type
+ xlConeColStacked100 : _( "100 percent Stacked Cone Column" ) ,
+ # Translators: Chart type
+ xlCylinderBarClustered : _( "Clustered Cylinder Bar" ) ,
+ # Translators: Chart type
+ xlCylinderBarStacked : _( "Stacked Cylinder Bar" ) ,
+ # Translators: Chart type
+ xlCylinderBarStacked100 : _( "100 percent Stacked Cylinder Bar" ) ,
+ # Translators: Chart type
+ xlCylinderCol : _( "3D Cylinder Column" ) ,
+ # Translators: Chart type
+ xlCylinderColClustered : _( "Clustered Cone Column" ) ,
+ # Translators: Chart type
+ xlCylinderColStacked : _( "Stacked Cone Column" ) ,
+ # Translators: Chart type
+ xlCylinderColStacked100 : _( "100 percent Stacked Cylinder Column" ) ,
+ # Translators: Chart type
+ xlDoughnut : _( "Doughnut" ) ,
+ # Translators: Chart type
+ xlDoughnutExploded : _( "Exploded Doughnut" ) ,
+ # Translators: Chart type
+ xlLine : _( "Line" ) ,
+ # Translators: Chart type
+ xlLineMarkers : _( "Line with Markers" ) ,
+ # Translators: Chart type
+ xlLineMarkersStacked : _( "Stacked Line with Markers" ) ,
+ # Translators: Chart type
+ xlLineMarkersStacked100 : _( "100 percent Stacked Line with Markers" ) ,
+ # Translators: Chart type
+ xlLineStacked : _( "Stacked Line" ) ,
+ # Translators: Chart type
+ xlLineStacked100 : _( "100 percent Stacked Line" ) ,
+ # Translators: Chart type
+ xlPie : _( "Pie" ) ,
+ # Translators: Chart type
+ xlPieExploded : _( "Exploded Pie" ) ,
+ # Translators: Chart type
+ xlPieOfPie : _( "Pie of Pie" ) ,
+ # Translators: Chart type
+ xlPyramidBarClustered : _( "Clustered Pyramid Bar" ) ,
+ # Translators: Chart type
+ xlPyramidBarStacked : _( "Stacked Pyramid Bar" ) ,
+ # Translators: Chart type
+ xlPyramidBarStacked100 : _( "100 percent Stacked Pyramid Bar" ) ,
+ # Translators: Chart type
+ xlPyramidCol : _( "3D Pyramid Column" ) ,
+ # Translators: Chart type
+ xlPyramidColClustered : _( "Clustered Pyramid Column" ) ,
+ # Translators: Chart type
+ xlPyramidColStacked : _( "Stacked Pyramid Column" ) ,
+ # Translators: Chart type
+ xlPyramidColStacked100 : _( "100 percent Stacked Pyramid Column" ) ,
+ # Translators: Chart type
+ xlRadar : _( "Radar" ) ,
+ # Translators: Chart type
+ xlRadarFilled : _( "Filled Radar" ) ,
+ # Translators: Chart type
+ xlRadarMarkers : _( "Radar with Data Markers" ) ,
+ # Translators: Chart type
+ xlStockHLC : _( "High-Low-Close" ) ,
+ # Translators: Chart type
+ xlStockOHLC : _( "Open-High-Low-Close" ) ,
+ # Translators: Chart type
+ xlStockVHLC : _( "Volume-High-Low-Close" ) ,
+ # Translators: Chart type
+ xlStockVOHLC : _( "Volume-Open-High-Low-Close" ) ,
+ # Translators: Chart type
+ xlSurface : _( "3D Surface" ) ,
+ # Translators: Chart type
+ xlSurfaceTopView : _( "Surface (Top View)" ) ,
+ # Translators: Chart type
+ xlSurfaceTopViewWireframe : _( "Surface (Top View wireframe)" ) ,
+ # Translators: Chart type
+ xlSurfaceWireframe : _( "3D Surface (wireframe)" ) ,
+ # Translators: Chart type
+ xlXYScatter : _( "Scatter" ) ,
+ # Translators: Chart type
+ xlXYScatterLines : _( "Scatter with Lines" ) ,
+ # Translators: Chart type
+ xlXYScatterLinesNoMarkers : _( "Scatter with Lines and No Data Markers"
) ,
+ # Translators: Chart type
+ xlXYScatterSmooth : _( "Scatter with Smoothed Lines" ) ,
+ # Translators: Chart type
+ xlXYScatterSmoothNoMarkers : _( "Scatter with Smoothed Lines and No
Data Markers")
+}
+
+# Dictionary for the segments of different chart types.
+chartSegmentDict = {
+ xl3DArea : "3D Area",
+ xl3DAreaStacked : "3D Stacked Area",
+ xl3DAreaStacked100 : "100 percent Stacked Area",
+ xl3DBarClustered : "3D Clustered Bar",
+ xl3DBarStacked : "3D Stacked Bar",
+ xl3DBarStacked100 : "3D 100 percent Stacked Bar",
+ xl3DColumn : "Column",
+ xl3DColumnClustered : "Column",
+ xl3DColumnStacked : "Column",
+ xl3DColumnStacked100 : "Column",
+ xl3DLine : "Line",
+ xl3DPie : "Slice",
+ xl3DPieExploded : "Slice",
+ xlArea : "Area",
+ xlAreaStacked : "Stacked Area",
+ xlAreaStacked100 : "100 percent Stacked Area",
+ xlBarClustered : "Clustered Bar",
+ xlBarOfPie : "Bar of Pie",
+ xlBarStacked : "Stacked Bar",
+ xlBarStacked100 : "100 percent Stacked Bar",
+ xlBubble : "Bubble",
+ xlBubble3DEffect : "Bubble with 3D effects",
+ xlColumnClustered : "Column",
+ xlColumnStacked : "Column",
+ xlColumnStacked100 : "Column",
+ xlConeBarClustered : "Clustered Cone Bar",
+ xlConeBarStacked : "Stacked Cone Bar",
+ xlConeBarStacked100 : "100 percent Stacked Cone Bar",
+ xlConeCol : "3D Cone Column",
+ xlConeColClustered : "Clustered Cone Column",
+ xlConeColStacked : "Stacked Cone Column",
+ xlConeColStacked100 : "100 percent Stacked Cone Column",
+ xlCylinderBarClustered : "Clustered Cylinder Bar",
+ xlCylinderBarStacked : "Stacked Cylinder Bar",
+ xlCylinderBarStacked100 : "100 percent Stacked Cylinder Bar",
+ xlCylinderCol : "3D Cylinder Column",
+ xlCylinderColClustered : "Clustered Cone Column",
+ xlCylinderColStacked : "Stacked Cone Column",
+ xlCylinderColStacked100 : "100 percent Stacked Cylinder Column",
+ xlDoughnut : "Doughnut",
+ xlDoughnutExploded : "Exploded Doughnut",
+ xlLine : "Line",
+ xlLineMarkers : "Line",
+ xlLineMarkersStacked : "Line",
+ xlLineMarkersStacked100 : "Line",
+ xlLineStacked : "Line",
+ xlLineStacked100 : "Line",
+ xlPie : "slice",
+ xlPieExploded : "Exploded Pie",
+ xlPieOfPie : "Pie of Pie",
+ xlPyramidBarClustered : "Clustered Pyramid Bar",
+ xlPyramidBarStacked : "Stacked Pyramid Bar",
+ xlPyramidBarStacked100 : "100 percent Stacked Pyramid Bar",
+ xlPyramidCol : "3D Pyramid Column",
+ xlPyramidColClustered : "Clustered Pyramid Column",
+ xlPyramidColStacked : "Stacked Pyramid Column",
+ xlPyramidColStacked100 : "100 percent Stacked Pyramid Column",
+ xlRadar : "Radar",
+ xlRadarFilled : "Filled Radar",
+ xlRadarMarkers : "Radar with Data Markers",
+ xlStockHLC : "High-Low-Close",
+ xlStockOHLC : "Open-High-Low-Close",
+ xlStockVHLC : "Volume-High-Low-Close",
+ xlStockVOHLC : "Volume-Open-High-Low-Close",
+ xlSurface : "3D Surface",
+ xlSurfaceTopView : "Surface (Top View)",
+ xlSurfaceTopViewWireframe : "Surface (Top View wireframe)",
+ xlSurfaceWireframe : "3D Surface (wireframe)",
+ xlXYScatter : "Scatter",
+ xlXYScatterLines : "Scatter with Lines",
+ xlXYScatterLinesNoMarkers : "Scatter with Lines and No Data Markers",
+ xlXYScatterSmooth : "Scatter with Smoothed Lines",
+ xlXYScatterSmoothNoMarkers : "Scatter with Smoothed Lines and No Data
Markers"
+}
+
+
+
+# Axis types in chart
+xlCategory = 1
+xlValue = 2
+xlSeriesAxis = 3 # Valid only for 3-D charts
+
+# Axis Groups in chart
+xlPrimary = 1
+xlSecondary = 2
+
+
+
+# values for enumeration 'XlChartItem'
+xlDataLabel = 0
+xlChartArea = 2
+xlSeries = 3
+xlChartTitle = 4
+xlWalls = 5
+xlCorners = 6
+xlDataTable = 7
+xlTrendline = 8
+xlErrorBars = 9
+xlXErrorBars = 10
+xlYErrorBars = 11
+xlLegendEntry = 12
+xlLegendKey = 13
+xlShape = 14
+xlMajorGridlines = 15
+xlMinorGridlines = 16
+xlAxisTitle = 17
+xlUpBars = 18
+xlPlotArea = 19
+xlDownBars = 20
+xlAxis = 21
+xlSeriesLines = 22
+xlFloor = 23
+xlLegend = 24
+xlHiLoLines = 25
+xlDropLines = 26
+xlRadarAxisLabels = 27
+xlNothing = 28
+xlLeaderLines = 29
+xlDisplayUnitLabel = 30
+xlPivotChartFieldButton = 31
+xlPivotChartDropZone = 32
+XlChartItem = ctypes.c_int # enum
+
+
+
+class ExcelChart(excel.ExcelBase):
+ def
__init__(self,windowHandle=None,excelWindowObject=None,excelChartObject=None):
+ self.windowHandle = windowHandle
+ self.excelWindowObject = excelWindowObject
+ self.excelChartObject = excelChartObject
+ self.excelChartEventHandlerObject = ExcelChartEventHandler(
self )
+ self.excelChartEventConnection = GetEvents(
self.excelChartObject , self.excelChartEventHandlerObject , ChartEvents)
+ log.debugWarning("ExcelChart init")
+ super(ExcelChart,self).__init__(windowHandle=windowHandle)
+ for gesture in self.__changeSelectionGestures:
+ self.bindGesture(gesture, "changeSelection")
+
+ def _isEqual(self, other):
+ if not super(ExcelChart, self)._isEqual(other):
+ return False
+ return self.excelChartObject.Parent.Index ==
other.excelChartObject.Parent.Index
+
+ def _get_name(self):
+ if self.excelChartObject.HasTitle:
+ name=self.excelChartObject.ChartTitle.Text
+ else:
+ name=self.excelChartObject.Name
+#find the type of the chart
+ chartType = self.excelChartObject.ChartType
+ if chartType in chartTypeDict.keys():
+ chartTypeText = "%s" %(chartTypeDict[chartType])
+ else:
+ # Translators: chart type to be reported when the type
is not available
+ chartTypeText=_("unknown")
+ # Translators: prompt for chart title and chart type to be
reported
+ return _("Chart title equals %s type equals %s" %(name,
chartTypeText))
+
+ def _get_title(self):
+ try:
+ title=self.excelChartObject.ChartTitle
+ except COMError:
+ title=None
+ return title
+
+ def _get_role(self):
+ return controlTypes.ROLE_CHART
+
+ def script_switchToCell(self,gesture):
+ cell=self.excelWindowObject.ActiveCell
+ cell.Activate()
+ cellObj=self._getSelection()
+ eventHandler.queueEvent("gainFocus",cellObj)
+ script_switchToCell.canPropagate=True
+
+ def event_gainFocus(self):
+ if self.excelChartObject.HasTitle:
+ name=self.excelChartObject.ChartTitle.Text
+ else:
+ name=self.excelChartObject.Name
+#find the type of the chart
+ chartType = self.excelChartObject.ChartType
+ if chartType in chartTypeDict.keys():
+ chartTypeText=_("%s" %(chartTypeDict[chartType]))
+ else:
+ # Translators: chart type to be reported when the type
is not available
+ chartTypeText=_("unknown")
+ # Translators: prompt for chart title and chart type to be
reported
+ ui.message( _("Chart title equals %s type equals %s" %(name,
chartTypeText)) )
+ self.reportSeriesSummary()
+
+ def script_reportTitle(self,gesture):
+ ui.message (self._get_name())
+ script_reportTitle.canPropagate=True
+
+ def reportAxisTitle(self, axisType):
+ axis=None
+ if self.excelChartObject.HasAxis(axisType, xlPrimary):
+ axis = self.excelChartObject.Axes(axisType, xlPrimary)
+ else:
+ pass
+ # Translators: Axis title to be reported when the title is not
available
+ axisTitle = axis.AxisTitle.Text if axis and axis.HasTitle else
_("Not defined")
+ # Translators: Chart Axis types
+ axisName = _( "Category" ) if axisType==xlCategory else _(
"Value" ) if axisType==xlValue else _( "Series" )
+ # Translators: Prompt for axis title and axis type to be
reported
+ text=_("%s Axis is %s" %(axisName, axisTitle))
+ ui.message(text)
+
+ def script_reportCategoryAxis(self, gesture):
+ self.reportAxisTitle(xlCategory)
+ script_reportCategoryAxis.canPropagate=True
+
+ def script_reportValueAxis(self, gesture):
+ self.reportAxisTitle(xlValue)
+ script_reportValueAxis.canPropagate=True
+
+ def script_reportSeriesAxis(self, gesture):
+ self.reportAxisTitle(xlSeriesAxis)
+ script_reportSeriesAxis.canPropagate=True
+
+ def reportSeriesSummary(self ):
+ count = self.excelChartObject.SeriesCollection().count
+ if count>0:
+ if count == 1:
+ # Translators: Number of series when there is
only one series
+ seriesValueString = _( "There is %d series in
this chart" ) %(count)
+ else:
+ # Translators: Number of series when there are
multiple series
+ seriesValueString = _( "There are total %d
series in this chart" ) %(count)
+
+ for i in xrange(1, count+1):
+ # Translators: prompt for series number and
name to be reported
+ seriesValueString += ", Series %d %s" %(i,
self.excelChartObject.SeriesCollection(i).Name)
+ text = seriesValueString
+ else:
+ # Translators: prompt to be reported when there is no
series
+ text=_("No Series defined.")
+ ui.message(text)
+
+ def script_reportSeriesSummary(self, gesture):
+ self.reportSeriesSummary()
+ script_reportSeriesSummary.canPropagate=True
+
+ __gestures = {
+ "kb:escape": "switchToCell",
+ "kb:NVDA+t" : "reportTitle",
+ "kb:NVDA+shift+1" : "reportCategoryAxis",
+ "kb:NVDA+shift+2" : "reportValueAxis",
+ "kb:NVDA+shift+3" : "reportSeriesAxis",
+ "kb:NVDA+shift+4" : "reportSeriesSummary",
+ }
+
+ def script_changeSelection(self,gesture):
+ oldSelection=self._getSelection()
+ gesture.send()
+ newSelection=None
+ curTime=startTime=time.time()
+ while (curTime-startTime)<=0.15:
+ if scriptHandler.isScriptWaiting():
+ # Prevent lag if keys are pressed rapidly
+ return
+ if eventHandler.isPendingEvents('gainFocus'):
+ return
+ newSelection=self._getSelection()
+ if newSelection and newSelection!=oldSelection:
+ break
+ api.processPendingEvents(processEventQueue=False)
+ time.sleep(0.015)
+ curTime=time.time()
+ if newSelection:
+ eventHandler.executeEvent('gainFocus',newSelection)
+ script_changeSelection.canPropagate=True
+
+ __changeSelectionGestures = {
+ "kb:control+pageUp",
+ "kb:control+pageDown",
+ "kb:tab",
+ "kb:shift+tab",
+ }
+
+ def elementChanged( self , ElementID ,arg1,arg2):
+ selectedChartElement = None
+ if ElementID == xlAxis:
+ selectedChartElement = ExcelChartElementAxis(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlAxisTitle:
+ selectedChartElement = ExcelChartElementAxisTitle(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlSeries:
+ selectedChartElement = ExcelChartElementSeries(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlTrendline:
+ selectedChartElement = ExcelChartElementTrendline(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlChartTitle:
+ selectedChartElement = ExcelChartElementChartTitle(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlChartArea:
+ selectedChartElement = ExcelChartElementChartArea(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlPlotArea:
+ selectedChartElement = ExcelChartElementPlotArea(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlLegend:
+ selectedChartElement = ExcelChartElementLegend(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlLegendEntry:
+ selectedChartElement = ExcelChartElementLegendEntry(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ elif ElementID == xlLegendKey:
+ selectedChartElement = ExcelChartElementLegendKey(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+ else:
+ selectedChartElement = ExcelChartElementBase(
windowHandle= self.windowHandle , excelChartObject= self.excelChartObject ,
elementID=ElementID , arg1=arg1 , arg2=arg2 )
+
+ if selectedChartElement :
+ selectedChartElement.parent = self
+ selectedChartElement.previous = None
+ selectedChartElement.next = None
+ eventHandler.queueEvent("gainFocus",
selectedChartElement )
+
+class ExcelChartEventHandler(comtypes.COMObject):
+ _com_interfaces_=[ChartEvents,IDispatch]
+
+ def __init__(self, owner ):
+ self.owner = weakref.proxy( owner )
+ super(ExcelChartEventHandler ,self).__init__()
+
+ def ChartEvents_Select(self, this, ElementID ,arg1,arg2):
+ self.owner.elementChanged( ElementID ,arg1,arg2)
+
+class ExcelChartElementBase(Window):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ self.excelChartObject = excelChartObject
+ self.elementID = elementID
+ self.arg1 = arg1
+ self.arg2 = arg2
+ super(ExcelChartElementBase
,self).__init__(windowHandle=windowHandle)
+
+ def GetChartSegment(self):
+ chartType = self.excelChartObject.ChartType
+ if chartType in chartSegmentDict.keys():
+ text= chartSegmentDict[chartType]
+ else:
+ # Translators: Chart segment such as slice for pie
chart etc this is reported when there is no segment available.
+ text=_("item")
+ return text
+
+ def _get_role(self):
+ return controlTypes.ROLE_UNKNOWN
+
+ def _get_name(self):
+ return self._getChartElementText(self.elementID , self.arg1 ,
self.arg2)
+
+ def script_reportCurrentChartElementWithExtraInfo(self,gesture):
+ ui.message( self._getChartElementText(self.elementID ,
self.arg1 , self.arg2 , True ) )
+
+ def script_reportCurrentChartElementColor(self,gesture):
+ if self.elementID == xlSeries:
+ if self.arg2 == -1:
+ ui.message ( _( "Series color: {}
").format(colors.RGB.fromCOLORREF(int( self.excelChartObject.SeriesCollection(
self.arg1 ).Interior.Color ) ).name ) )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlDisplayUnitLabel:
+ # Translators: prompt for xlDisplayUnitLabel
+ return _( "Display Unit Label")
+
+ elif ElementID == xlMajorGridlines:
+ # Translators: prompt for xlMajorGridlines
+ return _( "Major Gridlines" )
+
+ elif ElementID == xlMinorGridlines:
+ # Translators: prompt for xlMinorGridlines
+ return _( "Minor Gridlines" )
+
+ elif ElementID == xlPivotChartDropZone:
+ # Translators: prompt for xlPivotChartDropZone
+ return _( "Pivot Chart Drop Zone" )
+
+ elif ElementID == xlPivotChartFieldButton:
+ # Translators: prompt for xlPivotChartFieldButton
+ return _( "Pivot Chart Field Button" )
+
+ elif ElementID == xlDownBars:
+ # Translators: prompt for xlDownBars
+ return _( "Down Bars" )
+
+ elif ElementID == xlDropLines:
+ # Translators: prompt for xlDropLines
+ return _( "Drop Lines" )
+
+ elif ElementID == xlHiLoLines:
+ # Translators: prompt for xlHiLoLines
+ return _( "Hi Lo Lines" )
+
+ elif ElementID == xlRadarAxisLabels:
+ # Translators: prompt for xlRadarAxisLabels
+ return _( "Radar Axis Labels" )
+
+ elif ElementID == xlSeriesLines:
+ # Translators: prompt for xlSeriesLines
+ return _( "Series Lines" )
+
+ elif ElementID == xlUpBars:
+ # Translators: prompt for xlUpBars
+ return _( "Up Bars" )
+
+ elif ElementID == xlCorners:
+ # Translators: prompt for xlCorners
+ return _( "Corners" )
+
+ elif ElementID == xlDataTable:
+ # Translators: prompt for xlDataTable
+ return _( "Data Table" )
+
+ elif ElementID == xlFloor:
+ # Translators: prompt for xlFloor
+ return _( "Floor" )
+
+ elif ElementID == xlNothing:
+ # Translators: prompt for xlNothing
+ return _( "xlNothing" )
+
+ elif ElementID == xlWalls:
+ # Translators: prompt for xlWalls
+ return _( "Walls" )
+
+ elif ElementID == xlDataLabel:
+ # Translators: prompt for xlDataLabel
+ return _( "Data Label" )
+
+ elif ElementID == xlErrorBars:
+ # Translators: prompt for xlErrorBars
+ return _( "Error Bars" )
+
+ elif ElementID == xlXErrorBars:
+ # Translators: prompt for xlXErrorBars
+ return _( "X Error Bars" )
+
+ elif ElementID == xlYErrorBars:
+ # Translators: prompt for xlYErrorBars
+ return _( "Y Error Bars" )
+
+ elif ElementID == xlShape:
+ # Translators: prompt for xlShape
+ return _( "Shape" )
+
+ #end def _Select
+
+ __gestures = {
+ "kb:NVDA+d" : "reportCurrentChartElementWithExtraInfo",
+ "kb:NVDA+f" : "reportCurrentChartElementColor",
+ }
+
+
+
+
+# end class ExcelChartEventHandler
+
+class ExcelChartElementSeries(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super(ExcelChartElementSeries,self).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlSeries:
+ if arg2 == -1:
+ # Translators: Prompt for series details in the
format: Name series index of count
+ return _( "{} Series {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
+ else:
+# if XValue is a float, change it to int, else dates are shown with points.
hope this does not introduce another bug
+ if isinstance(
self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1] , float):
+ excelSeriesXValue =
int(self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1] )
+ else:
+ excelSeriesXValue =
self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1]
+
+ output=""
+ if self.excelChartObject.ChartType == xlLine or
self.excelChartObject.ChartType == xlLineMarkers or
self.excelChartObject.ChartType == xlLineMarkersStacked or
self.excelChartObject.ChartType == xlLineMarkersStacked100 or
self.excelChartObject.ChartType == xlLineStacked or
self.excelChartObject.ChartType == xlLineStacked100:
+ if arg2 > 1:
+
+ if
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] ==
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2]:
+ # Translators: for line
charts, no change from the previous element
+ output += _( "no change
from point {}, ").format( arg2 - 1 )
+ elif
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] >
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2]:
+ # Translators: for line
charts, increase from the previous element
+ output += _( "Increased
by {} from point {}, ").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] , arg2 - 1 )
+ else:
+ # Translators: for line
charts, decrease from the previous element
+ output += _( "decreased
by {} from point {}, ").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] , arg2 - 1 )
+
+ if self.excelChartObject.HasAxis(xlCategory)
and self.excelChartObject.Axes(xlCategory).HasTitle:
+ # Translators: report category axis
title if available in the format title value
+ output += _( "{} {}: ").format(
self.excelChartObject.Axes(xlCategory).AxisTitle.Text , excelSeriesXValue )
+ else:
+ # Translators: report category axis
title as Category if axis title is not available in the format "category" value
+ output += _( "Category {}: ").format(
excelSeriesXValue )
+
+ if self.excelChartObject.HasAxis(xlValue) and
self.excelChartObject.Axes(xlValue).HasTitle:
+ # Translators: report value axis title
if available in the format title value
+ output += _( "{} {}").format(
self.excelChartObject.Axes(xlValue).AxisTitle.Text ,
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])
+ else:
+ # Translators: report value axis title
as value if axis title is not available in the format "Value" value
+ output += _( "value {}").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])
+
+ if self.excelChartObject.ChartType == xlPie or
self.excelChartObject.ChartType == xlPieExploded or
self.excelChartObject.ChartType == xlPieOfPie:
+ total = math.fsum(
self.excelChartObject.SeriesCollection(arg1).Values )
+ # Translators: Prompt for pie chart in
the format: fraction nn percent slice index of count
+ output += _( " fraction {:.2f} Percent
{} {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1] / total *100.00 ,
self.GetChartSegment() , arg2 , len(
self.excelChartObject.SeriesCollection(arg1).Values ) )
+ else:
+ # Translators: Prompt for other charts
in the format: segment type index of count
+ output += _( " {} {} of {}").format(
self.GetChartSegment() , arg2 , len(
self.excelChartObject.SeriesCollection(arg1).Values ) )
+
+ return output
+
+class ExcelChartElementAxis(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementAxis , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlAxis:
+ if arg1 == xlPrimary:
+ # Translators: axis group
+ axisGroup = _("Primary")
+ elif arg1 == xlSecondary :
+ # Translators: axis group
+ axisGroup = _("Secondary")
+
+ if arg2 == xlCategory:
+ # Translators: axis type
+ axisType= _("Category")
+ elif arg2 == xlValue:
+ # Translators: axis type
+ axisType= _("Value")
+ elif arg2 == xlSeriesAxis:
+ # Translators: axis type
+ axisType= _("Series")
+
+ axisDescription =""
+ if self.excelChartObject.HasAxis( arg2 ) and
self.excelChartObject.Axes( arg2 ).HasTitle:
+ # Translators: Prompt for axis details such as:
type, group, and title
+ axisDescription += _("Chart Axis, type equals
{}, group equals {}, Title equals {}").format( axisType , axisGroup ,
self.excelChartObject.Axes( arg2 , arg1 ).AxisTitle.Text )
+ elif self.excelChartObject.HasAxis( arg2 ) and not
self.excelChartObject.Axes( arg2 ).HasTitle:
+ # Translators: Prompt for axis details such as:
type, group, and title when there is no title
+ axisDescription += _("Chart Axis, type equals
{}, group equals {}, Title equals {}").format( axisType , axisGroup , _("none")
)
+
+ return axisDescription
+
+class ExcelChartElementAxisTitle(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementAxisTitle , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlAxisTitle:
+ axisTitle=""
+ if self.excelChartObject.HasAxis( arg2 ) and
self.excelChartObject.Axes( arg2 ).HasTitle:
+ # Translators: Prompt for axis title if axis
has title
+ axisTitle += _("Chart Axis Title equals {}
").format( self.excelChartObject.Axes( arg2 , arg1 ).AxisTitle.Text )
+ elif self.excelChartObject.HasAxis( arg2 ) and not
self.excelChartObject.Axes( arg2 ).HasTitle:
+ # Translators: Prompt for axis title without
title
+ axisTitle += _("Chart Axis Title equals {}
").format( _("none") )
+
+ return axisTitle
+
+class ExcelChartElementTrendline(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementTrendline , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlTrendline:
+ if
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DisplayEquation
or
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DisplayRSquared:
+ trendlineText = unicode(
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DataLabel.Text
).encode("utf-8").replace("\xc2\xb2" , _( " square " ) )
+ # Translators: Prompt for trendline with
equation or r square
+ return _( " trendline {} ").format(
trendlineText )
+ else:
+ # Translators: Prompt for trendline without
equation or r square
+ return _( "Trendline" )
+
+class ExcelChartElementChartTitle(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementChartTitle , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlChartTitle:
+ if self.excelChartObject.HasTitle:
+ # Translators: Prompt for chart title
+ return _( "Chart Title equals {}").format (
self.excelChartObject.ChartTitle.Text )
+ else:
+ # Translators: Prompt for chart title when the
title is not available
+ return _( "Untitled chart" )
+
+class ExcelChartElementChartArea(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementChartArea , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlChartArea:
+ if reportExtraInfo:
+ # Translators: Prompt for chart area with
dimentions
+ return _( "Chart area height equals {}, width
equals {}, top equals {}, left equals {}").format (
self.excelChartObject.ChartArea.Height , self.excelChartObject.ChartArea.Width
, self.excelChartObject.ChartArea.Top , self.excelChartObject.ChartArea.Left)
+ else:
+ # Translators: Prompt for chart area
+ return _( "Chart area ")
+
+class ExcelChartElementPlotArea(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementPlotArea , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlPlotArea:
+ if reportExtraInfo:
+ # useing {:.0f} to remove fractions
+ # Translators: Prompt for plot area with inner
dimentions
+ return _( "Plot Area inside height equals
{:.0f}, inside width equals {:.0f}, inside top equals {:.0f}, inside left
equals {:.0f}").format ( self.excelChartObject.PlotArea.InsideHeight ,
self.excelChartObject.PlotArea.InsideWidth ,
self.excelChartObject.PlotArea.InsideTop ,
self.excelChartObject.PlotArea.InsideLeft )
+ else:
+ # Translators: Prompt for plot area
+ return _( "Plot Area " )
+
+class ExcelChartElementLegend(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementLegend , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlLegend:
+ if self.excelChartObject.HasLegend:
+ # Translators: Prompt for Legend
+ return _( "Legend" )
+ else:
+ # Translators: Prompt for Legend when no legend is
present
+ return _( "No legend" )
+
+class ExcelChartElementLegendEntry(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementLegendEntry , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlLegendEntry:
+ # Translators: Prompt for Legend entry for series name
index of count
+ return _( "Legend entry for Series {}, {} of
{}").format( self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
+
+class ExcelChartElementLegendKey(ExcelChartElementBase):
+
+ def __init__(self, windowHandle=None , excelChartObject=None ,
elementID=None , arg1=None , arg2=None ):
+ super( ExcelChartElementLegendKey , self ).__init__(
windowHandle=windowHandle , excelChartObject=excelChartObject ,
elementID=elementID , arg1=arg1 , arg2=arg2 )
+
+ def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
+ if ElementID == xlLegendKey:
+ # Translators: Prompt for Legend key for series name
index of count
+ return _( "Legend key for Series {} {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
+
+

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 7029663..32398b1 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -542,6 +542,7 @@ NVDA provides its own extra commands for some applications
to make certain tasks
| Set column headers | NVDA+shift+c | Pressing this once tells NVDA this is
the first header cell in the row that contains column headers, which should be
automatically announced when moving between columns below this row. Pressing
twice will clear the setting. |
| Set row headers | NVDA+shift+r | Pressing this once tells NVDA this is the
first header cell in the column that contains row headers, which should be
automatically announced when moving between rows after this column. Pressing
twice will clear the setting. |
| Report comment | NVDA+alt+c | Reports the comment on the current cell if
any. |
+| Cell List dialog | NVDA+f7 | opens the Cell List dialog showing cells with
comments or formulas. Cells can be also grouped by region. |
%kc:endInclude

++ Microsoft PowerPoint ++


https://bitbucket.org/nvdaaddonteam/nvda/commits/b26149bb8693/
Changeset: b26149bb8693
Branch: None
User: Leonard de Ruijter
Date: 2015-02-13 21:17:39+00:00
Summary: Added keyboard accelerators for "Play audio coordinates when mouse
moves" and "Brightness controls audio coordinates volume". Also capitalized
those first letters as they weren't before, which was inconsistent with the
other options in this window.

Affected #: 1 file

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index be054cb..3ae1bea 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -740,12 +740,12 @@ class MouseSettingsDialog(SettingsDialog):

settingsSizer.Add(self.reportObjectRoleCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
# mouse settings dialog.
- self.audioCheckBox=wx.CheckBox(self,wx.NewId(),label=_("play
audio coordinates when mouse moves"))
+ self.audioCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Play
audio coordinates when mouse moves"))

self.audioCheckBox.SetValue(config.conf["mouse"]["audioCoordinatesOnMouseMove"])
settingsSizer.Add(self.audioCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
# mouse settings dialog.
-
self.audioDetectBrightnessCheckBox=wx.CheckBox(self,wx.NewId(),label=_("brightness
controls audio coordinates volume"))
+
self.audioDetectBrightnessCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Brightness
controls audio coordinates volume"))

self.audioDetectBrightnessCheckBox.SetValue(config.conf["mouse"]["audioCoordinates_detectBrightness"])

settingsSizer.Add(self.audioDetectBrightnessCheckBox,border=10,flag=wx.BOTTOM)



https://bitbucket.org/nvdaaddonteam/nvda/commits/99683fbd296a/
Changeset: 99683fbd296a
Branch: None
User: mdcurran
Date: 2015-02-14 13:18:45+00:00
Summary: Merge branch 't1987' into next. Incubates #1987

Affected #: 1 file

diff --git a/source/NVDAObjects/window/excelChart.py
b/source/NVDAObjects/window/excelChart.py
index 2cbead2..bd9ab23 100644
--- a/source/NVDAObjects/window/excelChart.py
+++ b/source/NVDAObjects/window/excelChart.py
@@ -1,3 +1,4 @@
+# -*- coding: UTF-8 -*-
#NVDAObjects/excel.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
@@ -423,7 +424,7 @@ class ExcelChart(excel.ExcelBase):
# Translators: chart type to be reported when the type
is not available
chartTypeText=_("unknown")
# Translators: prompt for chart title and chart type to be
reported
- return _("Chart title equals %s type equals %s" %(name,
chartTypeText))
+ return _("Chart title equals {chartTitle} type equals
{chartType}").format(chartTitle=name, chartType=chartTypeText)

def _get_title(self):
try:
@@ -455,7 +456,7 @@ class ExcelChart(excel.ExcelBase):
# Translators: chart type to be reported when the type
is not available
chartTypeText=_("unknown")
# Translators: prompt for chart title and chart type to be
reported
- ui.message( _("Chart title equals %s type equals %s" %(name,
chartTypeText)) )
+ ui.message( _("Chart title equals {chartTitle} type equals
{chartType}").format(chartTitle=name, chartType=chartTypeText))
self.reportSeriesSummary()

def script_reportTitle(self,gesture):
@@ -473,7 +474,7 @@ class ExcelChart(excel.ExcelBase):
# Translators: Chart Axis types
axisName = _( "Category" ) if axisType==xlCategory else _(
"Value" ) if axisType==xlValue else _( "Series" )
# Translators: Prompt for axis title and axis type to be
reported
- text=_("%s Axis is %s" %(axisName, axisTitle))
+ text=_("{axisName} Axis is
{axisTitle}").format(axisName=axisName, axisTitle=axisTitle)
ui.message(text)

def script_reportCategoryAxis(self, gesture):


https://bitbucket.org/nvdaaddonteam/nvda/commits/9a39a4ce2c46/
Changeset: 9a39a4ce2c46
Branch: None
User: jteh
Date: 2015-02-19 03:46:15+00:00
Summary: Set MathPlayer's speech language to NVDA's speech language.

Note that this doesn't account for language markup in the document or math.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index a6b7c79..0eec26d 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -3,7 +3,7 @@
#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) 2014 NV Access Limited
+#Copyright (C) 2014-2015 NV Access Limited

"""Support for math presentation using MathPlayer 4.
"""
@@ -73,6 +73,7 @@ class
MathPlayerInteraction(mathPres.MathInteractionNVDAObject):

def __init__(self, provider=None, mathMl=None):
super(MathPlayerInteraction, self).__init__(provider=provider,
mathMl=mathMl)
+ provider._setSpeechLanguage(mathMl)
provider._mpSpeech.SetMathML(mathMl)

def reportFocus(self):
@@ -113,12 +114,17 @@ class MathPlayer(mathPres.MathPresentationProvider):

def __init__(self):
mpSpeech = self._mpSpeech =
comtypes.client.CreateObject(MPInterface, interface=IMathSpeech)
- mpSpeechSettings = mpSpeech.QueryInterface(IMathSpeechSettings)
+ mpSpeechSettings = self._mpSpeechSettings =
mpSpeech.QueryInterface(IMathSpeechSettings)
mpSpeechSettings.SetSpeechTags("SSML")
self._mpNavigation = mpSpeech.QueryInterface(IMathNavigation)
self._mpBraille = mpSpeech.QueryInterface(IMathBraille)

+ def _setSpeechLanguage(self, mathMl):
+ lang = speech.getCurrentLanguage()
+ self._mpSpeechSettings.SetLanguage(lang.replace("_", "-"))
+
def getSpeechForMathMl(self, mathMl):
+ self._setSpeechLanguage(mathMl)
self._mpSpeech.SetMathML(mathMl)
return _processMpSpeech(self._mpSpeech.GetSpokenText())



https://bitbucket.org/nvdaaddonteam/nvda/commits/27b5b4f0caa1/
Changeset: 27b5b4f0caa1
Branch: None
User: jteh
Date: 2015-02-19 05:41:46+00:00
Summary: NVDAObject: Add language attribute. Implement this for IAccessible
and MSHTML.

Affected #: 6 files

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index 3e42b09..d368f59 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -435,3 +435,10 @@ void
MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_con
this->reportLiveText(newChildrenText);
}
}
+
+void
MshtmlVBufStorage_controlFieldNode_t::generateAttributesForMarkupOpeningTag(wstring&
text, int startOffset, int endOffset) {
+
VBufStorage_controlFieldNode_t::generateAttributesForMarkupOpeningTag(text,
startOffset, endOffset);
+ wostringstream s;
+ s << L"language=\"" << language << L"\" ";
+ text += s.str();
+}

diff --git a/nvdaHelper/vbufBackends/mshtml/node.h
b/nvdaHelper/vbufBackends/mshtml/node.h
index 1fe53dd..63e5527 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.h
+++ b/nvdaHelper/vbufBackends/mshtml/node.h
@@ -40,6 +40,7 @@ class MshtmlVBufStorage_controlFieldNode_t : public
VBufStorage_controlFieldNode
void reportLiveAddition();
void preProcessLiveRegion(const MshtmlVBufStorage_controlFieldNode_t*
parent, const std::map<std::wstring,std::wstring>& attribsMap);
void postProcessLiveRegion(VBufStorage_controlFieldNode_t* oldNode,
std::set<VBufStorage_controlFieldNode_t*>& atomicNodes);
+ virtual void generateAttributesForMarkupOpeningTag(std::wstring& text,
int startOffset, int endOffset);
MshtmlVBufStorage_controlFieldNode_t(int docHandle, int ID, bool
isBlock, MshtmlVBufBackend_t* backend, IHTMLDOMNode* pHTMLDOMNode, const
std::wstring& lang);
~MshtmlVBufStorage_controlFieldNode_t();


diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 57195a6..1dfa0a8 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -1,6 +1,6 @@
#NVDAObjects/MSHTML.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NV Access Limited, Aleksey Sadovoy
+#Copyright (C) 2006-2015 NV Access Limited, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -890,6 +890,17 @@ class MSHTML(IAccessible):
info.append("MSHTML nodeName: %s" % ret)
return info

+ def _get_language(self):
+ ti = self.treeInterceptor
+ if not ti:
+ # This is too slow to calculate without a buffer.
+ # This case should be pretty rare anyway.
+ return None
+ try:
+ return ti.getControlFieldForNVDAObject(self)["language"]
+ except LookupError:
+ return None
+
class V6ComboBox(IAccessible):
"""The object which receives value change events for combo boxes in
MSHTML/IE 6.
"""

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 4826b01..6d804dc 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1,5 +1,5 @@
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2012 NVDA Contributors
+#Copyright (C) 2006-2015 NVDA Contributors
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -1433,6 +1433,17 @@ the NVDAObject for IAccessible
info.append("IAccessible2 attributes: %s" % ret)
return info

+ def _get_language(self):
+ try:
+ ia2Locale = self.IAccessibleObject.locale
+ except (AttributeError, COMError):
+ return None
+ if ia2Locale.language and ia2Locale.country:
+ return "%s_%s" % (ia2Locale.language, ia2Locale.country)
+ elif ia2Locale.language:
+ return ia2Locale.language
+ return None
+
class ContentGenericClient(IAccessible):

TextInfo=displayModel.DisplayModelTextInfo

diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
index aefa6bf..0a46dc0 100644
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -1051,3 +1051,7 @@ This code is executed if a gain focus event is received
by this object.
@raise LookupError: If MathML can't be retrieved for this
object.
"""
raise NotImplementedError
+
+ #: The language/locale of this object.
+ #: @type: basestring
+ language = None

diff --git a/source/virtualBuffers/__init__.py
b/source/virtualBuffers/__init__.py
index e50adee..b0dac15 100644
--- a/source/virtualBuffers/__init__.py
+++ b/source/virtualBuffers/__init__.py
@@ -500,9 +500,6 @@ class VirtualBuffer(cursorManager.CursorManager,
browseMode.BrowseModeTreeInterc
break
return tableLayout

-
-
-
def getNVDAObjectFromIdentifier(self, docHandle, ID):
"""Retrieve an NVDAObject for a given node identifier.
Subclasses must override this method.
@@ -1277,6 +1274,20 @@ class VirtualBuffer(cursorManager.CursorManager,
browseMode.BrowseModeTreeInterc
"""
braille.handler.handleUpdate(self)

+ def getControlFieldForNVDAObject(self, obj):
+ docHandle, objId = self.getIdentifierFromNVDAObject(obj)
+ objId = unicode(objId)
+ info = self.makeTextInfo(obj)
+ info.collapse()
+ info.expand(textInfos.UNIT_CHARACTER)
+ for item in info.getTextWithFields():
+ if not isinstance(item, textInfos.FieldCommand) or not
item.field:
+ continue
+ fieldId = item.field.get("controlIdentifier_ID")
+ if fieldId == objId:
+ return item.field
+ raise LookupError
+
__gestures = {
"kb:NVDA+d": "activateLongDesc",
"kb:NVDA+f5": "refreshBuffer",


https://bitbucket.org/nvdaaddonteam/nvda/commits/e367b62211d2/
Changeset: e367b62211d2
Branch: None
User: jteh
Date: 2015-02-19 05:48:26+00:00
Summary: For Gecko and MSHTML, when returning MathML, provide the inherited
language (if any) in the xml:lang attribute of the math tag.

Affected #: 3 files

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 1dfa0a8..aed0dba 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -1007,7 +1007,10 @@ class Math(MSHTML):

def _get_mathMl(self):
import mathPres
- return mathPres.stripExtraneousXml(self.HTMLNode.outerHTML)
+ mathMl = mathPres.stripExtraneousXml(self.HTMLNode.outerHTML)
+ if not mathPres.getLanguageFromMath(mathMl) and self.language:
+ mathMl = mathPres.insertLanguageIntoMath(mathMl,
self.language)
+ return mathMl

def findExtraIAccessibleOverlayClasses(obj, clsList):
"""Determine the most appropriate class for MSHTML objects.

diff --git a/source/NVDAObjects/IAccessible/mozilla.py
b/source/NVDAObjects/IAccessible/mozilla.py
index ded01ac..4a79e12 100755
--- a/source/NVDAObjects/IAccessible/mozilla.py
+++ b/source/NVDAObjects/IAccessible/mozilla.py
@@ -180,9 +180,16 @@ class Math(Mozilla):
# Try the data-mathml attribute.
attr = node.attributesForNames(1, (BSTR * 1)("data-mathml"),
(c_short * 1)(0,))
if attr:
+ import mathPres
+ if not mathPres.getLanguageFromMath(attr) and
self.language:
+ attr = mathPres.insertLanguageIntoMath(attr,
self.language)
return attr
# Assume the content is MathML.
- return "<math>%s</math>" % node.innerHTML
+ if self.language:
+ attrs = ' xml:lang="%s"' % self.language
+ else:
+ attrs = ""
+ return "<math%s>%s</math>" % (attrs, node.innerHTML)

def findExtraOverlayClasses(obj, clsList):
"""Determine the most appropriate class if this is a Mozilla object.

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
index 463f696..cf0cb52 100644
--- a/source/mathPres/__init__.py
+++ b/source/mathPres/__init__.py
@@ -167,3 +167,20 @@ def interactWithMathMl(mathMl):
ui.message(_("Math interaction not supported."))
return
return interactionProvider.interactWithMathMl(mathMl)
+
+RE_MATH_LANG = re.compile(r"""<math.*? xml:lang=["']([^"']+)["'].*?>""")
+def getLanguageFromMath(mathMl):
+ """Get the language specified in a math tag.
+ @return: The language or C{None} if unspeicifed.
+ @rtype: basestring
+ """
+ m = RE_MATH_LANG.search(mathMl)
+ if m:
+ return m.group(1)
+ return None
+
+RE_MATH_APPEND = re.compile(r"(<math[^>]*)>")
+def insertLanguageIntoMath(mathMl, language):
+ """Insert the specified language into a math tag.
+ """
+ return RE_MATH_APPEND.sub(r'\1 xml:lang="%s">' % language, mathMl,
count=1)


https://bitbucket.org/nvdaaddonteam/nvda/commits/5202e978d75c/
Changeset: 5202e978d75c
Branch: None
User: jteh
Date: 2015-02-19 05:49:47+00:00
Summary: MathPlayer: Set the language based on the xml:lang attribute of
the math tag, if any.

Affected #: 1 file

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
index 0eec26d..e21627a 100644
--- a/source/mathPres/mathPlayer.py
+++ b/source/mathPres/mathPlayer.py
@@ -38,13 +38,15 @@ PROSODY_COMMANDS = {
"volume": speech.VolumeCommand,
"rate": speech.RateCommand,
}
-def _processMpSpeech(text):
+def _processMpSpeech(text, language):
# MathPlayer's default rate is 180 wpm.
# Assume that 0% is 80 wpm and 100% is 450 wpm and scale accordingly.
synth = speech.getSynth()
wpm = synth._percentToParam(synth.rate, 80, 450)
breakMulti = 180.0 / wpm
out = []
+ if language:
+ out.append(speech.LangChangeCommand(language))
resetProsody = set()
for m in RE_MP_SPEECH.finditer(text):
if m.lastgroup == "break":
@@ -67,6 +69,8 @@ def _processMpSpeech(text):
text=m.group("phonemeText")))
elif m.lastgroup == "content":
out.append(m.group(0))
+ if language:
+ out.append(speech.LangChangeCommand(None))
return out

class MathPlayerInteraction(mathPres.MathInteractionNVDAObject):
@@ -78,7 +82,8 @@ class
MathPlayerInteraction(mathPres.MathInteractionNVDAObject):

def reportFocus(self):
super(MathPlayerInteraction, self).reportFocus()
-
speech.speak(_processMpSpeech(self.provider._mpSpeech.GetSpokenText()))
+
speech.speak(_processMpSpeech(self.provider._mpSpeech.GetSpokenText(),
+ self.provider._language))

def getBrailleRegions(self, review=False):
yield braille.NVDAObjectRegion(self, appendText=" ")
@@ -108,7 +113,7 @@ class
MathPlayerInteraction(mathPres.MathInteractionNVDAObject):
"shift" in modNames, "control" in modNames,
"alt" in modNames, False)
except COMError:
return
- speech.speak(_processMpSpeech(text))
+ speech.speak(_processMpSpeech(text, self.provider._language))

class MathPlayer(mathPres.MathPresentationProvider):

@@ -120,13 +125,16 @@ class MathPlayer(mathPres.MathPresentationProvider):
self._mpBraille = mpSpeech.QueryInterface(IMathBraille)

def _setSpeechLanguage(self, mathMl):
- lang = speech.getCurrentLanguage()
+ lang = mathPres.getLanguageFromMath(mathMl)
+ if not lang:
+ lang = speech.getCurrentLanguage()
self._mpSpeechSettings.SetLanguage(lang.replace("_", "-"))
+ self._language = lang

def getSpeechForMathMl(self, mathMl):
self._setSpeechLanguage(mathMl)
self._mpSpeech.SetMathML(mathMl)
- return _processMpSpeech(self._mpSpeech.GetSpokenText())
+ return _processMpSpeech(self._mpSpeech.GetSpokenText(),
self._language)

def getBrailleForMathMl(self, mathMl):
self._mpSpeech.SetMathML(mathMl)


https://bitbucket.org/nvdaaddonteam/nvda/commits/887b3bf8ffa9/
Changeset: 887b3bf8ffa9
Branch: None
User: jteh
Date: 2015-02-19 06:01:16+00:00
Summary: Merge branch 'master' into next

Affected #: 60 files

diff --git a/contributors.txt b/contributors.txt
index c1717e5..c2256f0 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -165,3 +165,4 @@ Zvonimir Stanecic
Tyler Spivey
Siddhartha Gupta
Siddharth
+Aleksandr Lin'kov

diff --git a/source/locale/ca/symbols.dic b/source/locale/ca/symbols.dic
index 5f5447d..70c334a 100644
--- a/source/locale/ca/symbols.dic
+++ b/source/locale/ca/symbols.dic
@@ -103,6 +103,9 @@ _ guió baix most
‎ marca d'esquerra a dreta char
‏ marca de dreta a esquerra char
■ quadrat negre some
+▪ quadrat negre some
+◾ quadrat negre some
+◦ pic blanc some
➔ fletxa dreta some
§ secció most
° grau some

diff --git a/source/locale/de/symbols.dic b/source/locale/de/symbols.dic
index 9bff0b8..ffbdd59 100644
--- a/source/locale/de/symbols.dic
+++ b/source/locale/de/symbols.dic
@@ -30,6 +30,7 @@ symbols:
decimal point none always
in-word ' Apostroph all norep
negative number Minus none norep
+date separator none always

# Whitespace
\0 Leer char # null

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/a3260c12511a/
Changeset: a3260c12511a
Branch: None
User: jteh
Date: 2015-02-20 04:07:38+00:00
Summary: Merge branch 't4930' into next

Incubates #4930.

Affected #: 1 file

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index a9bffc5..1218f01 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#settingsDialogs.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov
+#Copyright (C) 2006-2015 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov, Leonard de Ruijter
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -1515,15 +1515,19 @@ class AddSymbolDialog(wx.Dialog):
self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)

class SpeechSymbolsDialog(SettingsDialog):
- # Translators: This is the label for the symbol pronunciation dialog.
- title = _("Symbol Pronunciation")

- def makeSettings(self, settingsSizer):
+ def __init__(self,parent):
try:
- symbolProcessor =
characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData(languageHandler.getLanguage())
+ symbolProcessor =
characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData(speech.getCurrentLanguage())
except LookupError:
symbolProcessor =
characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData("en")
self.symbolProcessor = symbolProcessor
+ # Translators: This is the label for the symbol pronunciation
dialog.
+ # %s is replaced by the language for which symbol pronunciation
is being edited.
+ self.title = _("Symbol Pronunciation
(%s)")%languageHandler.getLanguageDescription(self.symbolProcessor.locale)
+ super(SpeechSymbolsDialog, self).__init__(parent)
+
+ def makeSettings(self, settingsSizer):
symbols = self.symbols = [copy.copy(symbol) for symbol in
self.symbolProcessor.computedSymbols.itervalues()]
self.pendingRemovals = {}



https://bitbucket.org/nvdaaddonteam/nvda/commits/8b85f9ce540a/
Changeset: 8b85f9ce540a
Branch: None
User: jteh
Date: 2015-02-20 06:08:55+00:00
Summary: Merge branch 't4916' into next

Incubates #4916.

Affected #: 1 file

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index 1218f01..edc5ce2 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -740,12 +740,12 @@ class MouseSettingsDialog(SettingsDialog):

settingsSizer.Add(self.reportObjectRoleCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
# mouse settings dialog.
- self.audioCheckBox=wx.CheckBox(self,wx.NewId(),label=_("play
audio coordinates when mouse moves"))
+ self.audioCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Play
audio coordinates when mouse moves"))

self.audioCheckBox.SetValue(config.conf["mouse"]["audioCoordinatesOnMouseMove"])
settingsSizer.Add(self.audioCheckBox,border=10,flag=wx.BOTTOM)
# Translators: This is the label for a checkbox in the
# mouse settings dialog.
-
self.audioDetectBrightnessCheckBox=wx.CheckBox(self,wx.NewId(),label=_("brightness
controls audio coordinates volume"))
+
self.audioDetectBrightnessCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Brightness
controls audio coordinates volume"))

self.audioDetectBrightnessCheckBox.SetValue(config.conf["mouse"]["audioCoordinates_detectBrightness"])

settingsSizer.Add(self.audioDetectBrightnessCheckBox,border=10,flag=wx.BOTTOM)



https://bitbucket.org/nvdaaddonteam/nvda/commits/b9e6bc17cc19/
Changeset: b9e6bc17cc19
Branch: None
User: jteh
Date: 2015-02-20 06:14:29+00:00
Summary: Merge branch 't4760' into next

Incubates #4760.

Affected #: 1 file

diff --git a/source/setup.py b/source/setup.py
index 4281085..5899696 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-2014 NV Access Limited, Peter Vágner
+#Copyright (C) 2006-2015 NV Access Limited, Peter Vágner, Joseph Lee
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -54,6 +54,8 @@ MAIN_MANIFEST_EXTRA = r"""
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><!--
Windows 8.1 --><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 10 -->
+ <supportedOS
Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility>
"""


https://bitbucket.org/nvdaaddonteam/nvda/commits/92af37e94d8e/
Changeset: 92af37e94d8e
Branch: None
User: siddhartha_iitd
Date: 2015-02-25 12:19:47+00:00
Summary: Set default font size to 11; changed obscured to cropped in and
obscuring to overflowing

Affected #: 2 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 884dd94..5784035 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -582,7 +582,7 @@ class ExcelCell(ExcelBase):
deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(tempDC, 88)
#Fetching Font Size and Weight information
iFontSize = self.excelCellObject.Font.Size
- iFontSize = int(iFontSize)
+ iFontSize = 11 if iFontSize is None else int(iFontSize)
iFontSize = ctypes.c_int(iFontSize)
iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize,
deviceCaps, 72)
#Font Weight for Bold FOnt is 700 and for normal font it's 400

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 223a75d..45c4ad2 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -549,9 +549,9 @@ stateLabels={
# Translators: a state that denotes the existance of a comment.
STATE_HASCOMMENT:_("has comment"),
# Translators: a state that denotes that the object is covered
partially or fully by another object
- STATE_OBSCURED:_("obscured"),
+ STATE_OBSCURED:_("cropped in"),
# Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
- STATE_OBSCURING:_("obscuring"),
+ STATE_OBSCURING:_("overflowing"),
}

negativeStateLabels={


https://bitbucket.org/nvdaaddonteam/nvda/commits/0986bab6750a/
Changeset: 0986bab6750a
Branch: None
User: siddhartha_iitd
Date: 2015-02-27 09:34:02+00:00
Summary: Added STATE_CROPPED and STATE_OVERFLOWING states and corresponding
text mappings. Now using these states instead of STATE_OBSCURED and
STATE_OBSCURING

Affected #: 2 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 5784035..07fb33d 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -564,9 +564,9 @@ class ExcelCell(ExcelBase):
states.add(controlTypes.STATE_HASCOMMENT)
if self._overlapInfo is not None:
if self._overlapInfo['obscuredFromRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURED)
+ states.add(controlTypes.STATE_CROPPED)
if self._overlapInfo['obscuringRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURING)
+ states.add(controlTypes.STATE_OVERFLOWING)
return states

def getCellWidthAndTextWidth(self):
@@ -635,8 +635,10 @@ class ExcelCell(ExcelBase):
#Release & Delete the device context
ctypes.windll.gdi32.DeleteDC(tempDC)
#Retrieve the text width
- textWidth = StructText.width+5
+ textWidth = StructText.width
cellWidth = self.excelCellObject.ColumnWidth *
xlCellWidthUnitToPixels #Conversion factor to convert the cellwidth to pixels
+ log.io("\nTextWidth:\t"+str(textWidth)+"\n")
+ log.io("\nCellWidth:\t"+str(cellWidth)+"\n")
return (cellWidth,textWidth)

def _get__overlapInfo(self):

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 45c4ad2..1740780 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -188,6 +188,8 @@ STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
STATE_OBSCURING=0x8000000000
+STATE_CROPPED=0x10000000000
+STATE_OVERFLOWING=0X20000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -549,9 +551,13 @@ stateLabels={
# Translators: a state that denotes the existance of a comment.
STATE_HASCOMMENT:_("has comment"),
# Translators: a state that denotes that the object is covered
partially or fully by another object
- STATE_OBSCURED:_("cropped in"),
+ STATE_OBSCURED:_("obscured"),
# Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
- STATE_OBSCURING:_("overflowing"),
+ STATE_OBSCURING:_("obscuring"),
+ # Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
+ STATE_CROPPED:_("cropped"),
+ # Translators: a state that denotes that the object(text) is
overflowing into the adjacent space
+ STATE_OVERFLOWING:_("overflowing"),
}

negativeStateLabels={


https://bitbucket.org/nvdaaddonteam/nvda/commits/0527e2d358cb/
Changeset: 0527e2d358cb
Branch: None
User: mdcurran
Date: 2015-03-16 05:20:10+00:00
Summary: Merge branch 'master' into next

Affected #: 2 files

diff --git a/source/versionInfo.py b/source/versionInfo.py
index 7ff28bf..966022c 100644
--- a/source/versionInfo.py
+++ b/source/versionInfo.py
@@ -1,6 +1,6 @@
#versionInfo.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NV Access Limited
+#Copyright (C) 2006-2015 NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -31,7 +31,7 @@ def _updateVersionFromVCS():
# Otherwise, py2exe will break.
name="NVDA"
longName=_("NonVisual Desktop Access")
-version="2015.1dev"
+version="2015.2dev"
publisher="unknown"
updateVersionType=None
try:

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 387ef2f..aa95ea9 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -3,6 +3,12 @@

%!includeconf: ../changes.t2tconf

+= 2015.2 =
+
+== New Features ==
+- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
+
+
= 2015.1 =
Highlights of this release include browse mode for documents in Microsoft Word
and Outlook; major enhancements to support for Skype for Desktop; and
significant fixes for Microsoft Internet Explorer.



https://bitbucket.org/nvdaaddonteam/nvda/commits/98fc313e3889/
Changeset: 98fc313e3889
Branch: None
User: mdcurran
Date: 2015-03-16 05:44:28+00:00
Summary: Merge branch 'master' into next

Affected #: 1 file

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index aa95ea9..a7432ec 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -9,6 +9,10 @@
- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)


+== Changes for Developers ==
+- brailleInput.handler.sendChars(mychar) will no longer filter out a character
if it is equal to the previous character, by ensuring that the key sent is
correctly released.
+
+
= 2015.1 =
Highlights of this release include browse mode for documents in Microsoft Word
and Outlook; major enhancements to support for Skype for Desktop; and
significant fixes for Microsoft Internet Explorer.



https://bitbucket.org/nvdaaddonteam/nvda/commits/6e6e831bb3c0/
Changeset: 6e6e831bb3c0
Branch: None
User: mdcurran
Date: 2015-03-16 05:48:12+00:00
Summary: Merge branch 'master' into next

Affected #: 0 files



https://bitbucket.org/nvdaaddonteam/nvda/commits/52db824ebbcb/
Changeset: 52db824ebbcb
Branch: None
User: mdcurran
Date: 2015-03-16 06:02:14+00:00
Summary: MSHTML NVDAObject's value property: don't return anything for
editable combo boxes. Stops inappropriate announcement when typing in new
Google search field.

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 9541e9b..36b58ae 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -602,7 +602,8 @@ class MSHTML(IAccessible):
value=""
return value
IARole=self.IAccessibleRole
- if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT):
+ # value is not useful on certain nodes that just expose a URL,
or they have other ways of getting their content (#4976 - editble combos).
+ if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT)
or (IARole==oleacc.ROLE_SYSTEM_COMBOBOX and controlTypes.STATE_EDITABLE in
self.states):
return ""
else:
return super(MSHTML,self).value


https://bitbucket.org/nvdaaddonteam/nvda/commits/b9951fccf744/
Changeset: b9951fccf744
Branch: None
User: mdcurran
Date: 2015-03-16 06:02:32+00:00
Summary: Merge branch 't4976' into next. Incubates #4976

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 7c2f5bd..709e39f 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -655,7 +655,8 @@ class MSHTML(IAccessible):
value=""
return value
IARole=self.IAccessibleRole
- if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT):
+ # value is not useful on certain nodes that just expose a URL,
or they have other ways of getting their content (#4976 - editble combos).
+ if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT)
or (IARole==oleacc.ROLE_SYSTEM_COMBOBOX and controlTypes.STATE_EDITABLE in
self.states):
return ""
else:
return super(MSHTML,self).value


https://bitbucket.org/nvdaaddonteam/nvda/commits/fa0978333b33/
Changeset: fa0978333b33
Branch: None
User: siddhartha_iitd
Date: 2015-03-16 08:29:28+00:00
Summary: Removed the log statements

Affected #: 1 file

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 07fb33d..4ecfefc 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -635,10 +635,8 @@ class ExcelCell(ExcelBase):
#Release & Delete the device context
ctypes.windll.gdi32.DeleteDC(tempDC)
#Retrieve the text width
- textWidth = StructText.width
+ textWidth = StructText.width+5
cellWidth = self.excelCellObject.ColumnWidth *
xlCellWidthUnitToPixels #Conversion factor to convert the cellwidth to pixels
- log.io("\nTextWidth:\t"+str(textWidth)+"\n")
- log.io("\nCellWidth:\t"+str(cellWidth)+"\n")
return (cellWidth,textWidth)

def _get__overlapInfo(self):


https://bitbucket.org/nvdaaddonteam/nvda/commits/0d800c21756d/
Changeset: 0d800c21756d
Branch: None
User: mdcurran
Date: 2015-03-18 03:41:41+00:00
Summary: Merge branch 't4699' into next. Incubates #4699

Affected #: 1 file

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 5c376dd..b30b832 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -1347,8 +1347,12 @@ class GlobalCommands(ScriptableObject):
index=(index+1)%len(touchHandler.availableTouchModes)
newMode=touchHandler.availableTouchModes[index]
touchHandler.handler._curTouchMode=newMode
- # Translators: Cycles through available touch modes (a group of
related touch gestures; example output: "object mode"; see the user guide for
more information on touch modes).
- ui.message(_("%s mode")%newMode)
+ try:
+ newModeLabel=touchHandler.touchModeLabels[newMode]
+ except KeyError:
+ # Translators: Cycles through available touch modes (a
group of related touch gestures; example output: "object mode"; see the user
guide for more information on touch modes).
+ newModeLabel=_("%s mode")%newMode
+ ui.message(newModeLabel)
# Translators: Input help mode message for a touchscreen gesture.
script_touch_changeMode.__doc__=_("cycles between available touch
modes")
script_touch_changeMode.category=SCRCAT_TOUCH


https://bitbucket.org/nvdaaddonteam/nvda/commits/13e79955a9bb/
Changeset: 13e79955a9bb
Branch: None
User: mdcurran
Date: 2015-03-19 23:27:34+00:00
Summary: Increase list of known colors to include all CSS 3 colors. Also
improve the closest color algorithm to use a weighted hsv (with hue 4 times
more important) instead of rgb.

Affected #: 1 file

diff --git a/source/colors.py b/source/colors.py
index 2fe4db3..f067b9d 100644
--- a/source/colors.py
+++ b/source/colors.py
@@ -6,6 +6,7 @@

from collections import namedtuple
import math
+import colorsys
from ctypes.wintypes import COLORREF
import re

@@ -74,8 +75,15 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
longestDistance=255.0
# Translators: Reported when text is written in unknown color.
closestName=_("unknown color")
+
selfHSV=colorsys.rgb_to_hsv(self.red/255.0,self.green/255.0,self.blue/255.0)
for possibleRGB,possibleName in RGBToNames.iteritems():
-
distance=math.sqrt(abs(self.red-possibleRGB.red)**2+abs(self.green-possibleRGB.green)**2+abs(self.blue-possibleRGB.blue)**2)
+
possibleHSV=colorsys.rgb_to_hsv(possibleRGB.red/255.0,possibleRGB.green/255.0,possibleRGB.blue/255.0)
+ dh=abs(selfHSV[0]-possibleHSV[0])
+ if dh>0.5:
+ dh=1-dh
+ ds=abs(selfHSV[1]-possibleHSV[1])
+ dv=abs(selfHSV[2]-possibleHSV[2])
+ distance=math.sqrt(0.4*(dh**2)+0.1*(ds**2)+0.1*(dv**2))
if distance<longestDistance:
longestDistance=distance
closestName=possibleName
@@ -85,48 +93,284 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
RGBToNamesCache={}

RGBToNames={
- #Standard 16 HTML 4 colors
- # Translators: The color black.
- RGB(0x00,0x00,0x00):_('black'),
- # Translators: The color dark green.
- RGB(0x00,0x80,0x00):_('dark green'),
- # Translators: The light gray color.
- RGB(0xc0,0xc0,0xc0):_('light grey'),
- # Translators: The color green (full brightness)
- RGB(0x00,0xff,0x00):_('green'),
- # Translators: The color gray (halfway between white and black).
- RGB(0x80,0x80,0x80):_('grey'),
- # Translators: the color olive.
- # For more info see:
http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
- RGB(0x80,0x80,0x00):_('olive'),
- # Translators: The color white.
- RGB(0xff,0xff,0xff):_('white'),
- # Translators: The color yellow.
- RGB(0xff,0xff,0x00):_('yellow'),
- # Translators: The dark red color.
- RGB(0x80,0x00,0x00):_('dark red'),
- # Translators: The color navy blue (dark blue).
- # For more info see http://en.wikipedia.org/wiki/Navy_blue
- RGB(0x00,0x00,0xa0):_('navy blue'),
- # Translators: The color red.
- RGB(0xff,0x00,0x00):_('red'),
- # Translators: The color blue.
- RGB(0x00,0x00,0xff):_('blue'),
- # Translators: The color purple.
- RGB(0x80,0x00,0x80):_('purple'),
- # Translators: The color teal, which is a mix of green and blue, mostly
green.
- # For more info see http://en.wikipedia.org/wiki/Teal
- RGB(0x00,0x80,0x80):_('teal'),
- # Translators: The color fuchsia is a mix of blue and red.
- # For more info see: http://en.wikipedia.org/wiki/Magenta
- RGB(0xff,0x00,0xff):_('fuchsia'),
- # Translators: The aqua color is an equal amount of blue and green.
- # For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
- RGB(0x00,0xff,0xff):_('aqua'),
-
- #Extra CSS 2.1 color
-
- # Translators: This is the color orange.
- RGB(0xff,0xa5,0x00):_('orange'),
+# Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,248,255):pgettext('color name','Alice Blue'),
+# Translators: the color Antique White (RGB 250, 235, 215) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,235,215):pgettext('color name','Antique White'),
+# Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Aqua'),
+# Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,212):pgettext('color name','Aquamarine'),
+# Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,255):pgettext('color name','Azure'),
+# Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,220):pgettext('color name','Beige'),
+# Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,196):pgettext('color name','Bisque'),
+# Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,0):pgettext('color name','Black'),
+# Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,235,205):pgettext('color name','Blanched Almond'),
+# Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,255):pgettext('color name','Blue'),
+# Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(138,43,226):pgettext('color name','Blue Violet'),
+# Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(165,42,42):pgettext('color name','Brown'),
+# Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(222,184,135):pgettext('color name','Burly Wood'),
+# Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(95,158,160):pgettext('color name','Cadet Blue'),
+# Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,0):pgettext('color name','Chartreuse'),
+# Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,105,30):pgettext('color name','Chocolate'),
+# Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,127,80):pgettext('color name','Coral'),
+# Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(100,149,237):pgettext('color name','Cornflower Blue'),
+# Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,248,220):pgettext('color name','Cornsilk'),
+# Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,20,60):pgettext('color name','Crimson'),
+# Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Cyan'),
+# Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,139):pgettext('color name','Dark Blue'),
+# Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,139,139):pgettext('color name','Dark Cyan'),
+# Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(184,134,11):pgettext('color name','Dark Goldenrod'),
+# Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(169,169,169):pgettext('color name','Dark Gray'),
+# Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,100,0):pgettext('color name','Dark Green'),
+# Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(189,183,107):pgettext('color name','Dark Khaki'),
+# Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,139):pgettext('color name','Dark Magenta'),
+# Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(85,107,47):pgettext('color name','Dark Olive Green'),
+# Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,140,0):pgettext('color name','Dark Orange'),
+# Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(153,50,204):pgettext('color name','Dark Orchid'),
+# Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,0):pgettext('color name','Dark Red'),
+# Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(233,150,122):pgettext('color name','Dark Salmon'),
+# Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(143,188,143):pgettext('color name','Dark Sea Green'),
+# Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,61,139):pgettext('color name','Dark Slate Blue'),
+# Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(47,79,79):pgettext('color name','Dark Slate Gray'),
+# Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,206,209):pgettext('color name','Dark Turquoise'),
+# Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(148,0,211):pgettext('color name','Dark Violet'),
+# Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,20,147):pgettext('color name','Deep Pink'),
+# Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,191,255):pgettext('color name','Deep Sky Blue'),
+# Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(105,105,105):pgettext('color name','Dim Gray'),
+# Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(30,144,255):pgettext('color name','Dodger Blue'),
+# Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(178,34,34):pgettext('color name','Fire Brick'),
+# Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,240):pgettext('color name','Floral White'),
+# Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(34,139,34):pgettext('color name','Forest Green'),
+# Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Fuchsia'),
+# Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,220,220):pgettext('color name','Gainsboro'),
+# Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(248,248,255):pgettext('color name','Ghost White'),
+# Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,215,0):pgettext('color name','Gold'),
+# Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,165,32):pgettext('color name','Goldenrod'),
+# Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,128):pgettext('color name','Gray'),
+# Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,0):pgettext('color name','Green'),
+# Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,255,47):pgettext('color name','Green Yellow'),
+# Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,240):pgettext('color name','Honeydew'),
+# Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,105,180):pgettext('color name','Hot Pink'),
+# Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,92,92):pgettext('color name','Indian Red'),
+# Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(75,0,130):pgettext('color name','Indigo'),
+# Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,240):pgettext('color name','Ivory'),
+# Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,230,140):pgettext('color name','Khaki'),
+# Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(230,230,250):pgettext('color name','Lavender'),
+# Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,240,245):pgettext('color name','Lavender Blush'),
+# Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(124,252,0):pgettext('color name','Lawn Green'),
+# Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,205):pgettext('color name','Lemon Chiffon'),
+# Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,216,230):pgettext('color name','Light Blue'),
+# Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,128,128):pgettext('color name','Light Coral'),
+# Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(224,255,255):pgettext('color name','Light Cyan'),
+# Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,250,210):pgettext('color name','Light Goldenrod Yellow'),
+# Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(144,238,144):pgettext('color name','Light Green'),
+# Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(211,211,211):pgettext('color name','Light Grey'),
+# Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,182,193):pgettext('color name','Light Pink'),
+# Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,160,122):pgettext('color name','Light Salmon'),
+# Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(32,178,170):pgettext('color name','Light Sea Green'),
+# Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,250):pgettext('color name','Light Sky Blue'),
+# Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(119,136,153):pgettext('color name','Light Slate Gray'),
+# Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,196,222):pgettext('color name','Light Steel Blue'),
+# Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,224):pgettext('color name','Light Yellow'),
+# Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,0):pgettext('color name','Lime'),
+# Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(50,205,50):pgettext('color name','Lime Green'),
+# Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,240,230):pgettext('color name','Linen'),
+# Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Magenta'),
+# Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,0):pgettext('color name','Maroon'),
+# Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(102,205,170):pgettext('color name','Medium Aquamarine'),
+# Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,205):pgettext('color name','Medium Blue'),
+# Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(186,85,211):pgettext('color name','Medium Orchid'),
+# Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(147,112,219):pgettext('color name','Medium Purple'),
+# Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(60,179,113):pgettext('color name','Medium Sea Green'),
+# Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(123,104,238):pgettext('color name','Medium Slate Blue'),
+# Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,250,154):pgettext('color name','Medium Spring Green'),
+# Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,209,204):pgettext('color name','Medium Turquoise'),
+# Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(199,21,133):pgettext('color name','Medium Violet Red'),
+# Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(25,25,112):pgettext('color name','Midnight Blue'),
+# Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,255,250):pgettext('color name','Mint Cream'),
+# Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,225):pgettext('color name','Misty Rose'),
+# Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,181):pgettext('color name','Moccasin'),
+# Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,222,173):pgettext('color name','Navajo White'),
+# Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,128):pgettext('color name','Navy'),
+# Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(253,245,230):pgettext('color name','Old Lace'),
+# Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,0):pgettext('color name','Olive'),
+# Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(107,142,35):pgettext('color name','Olive Drab'),
+# Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,165,0):pgettext('color name','Orange'),
+# Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,69,0):pgettext('color name','Orange Red'),
+# Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,112,214):pgettext('color name','Orchid'),
+# Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,232,170):pgettext('color name','Pale Goldenrod'),
+# Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(152,251,152):pgettext('color name','Pale Green'),
+# Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(175,238,238):pgettext('color name','Pale Turquoise'),
+# Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(219,112,147):pgettext('color name','Pale Violet Red'),
+# Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,239,213):pgettext('color name','Papaya Whip'),
+# Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,218,185):pgettext('color name','Peach Puff'),
+# Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,133,63):pgettext('color name','Peru'),
+# Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,192,203):pgettext('color name','Pink'),
+# Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(221,160,221):pgettext('color name','Plum'),
+# Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,224,230):pgettext('color name','Powder Blue'),
+# Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,128):pgettext('color name','Purple'),
+# Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,0):pgettext('color name','Red'),
+# Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(188,143,143):pgettext('color name','Rosy Brown'),
+# Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(65,105,225):pgettext('color name','Royal Blue'),
+# Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,69,19):pgettext('color name','Saddle Brown'),
+# Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,128,114):pgettext('color name','Salmon'),
+# Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(244,164,96):pgettext('color name','Sandy Brown'),
+# Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(46,139,87):pgettext('color name','Sea Green'),
+# Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,245,238):pgettext('color name','Seashell'),
+# Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(160,82,45):pgettext('color name','Sienna'),
+# Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(192,192,192):pgettext('color name','Silver'),
+# Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,235):pgettext('color name','Sky Blue'),
+# Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(106,90,205):pgettext('color name','Slate Blue'),
+# Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(112,128,144):pgettext('color name','Slate Gray'),
+# Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,250):pgettext('color name','Snow'),
+# Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,127):pgettext('color name','Spring Green'),
+# Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(70,130,180):pgettext('color name','Steel Blue'),
+# Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,180,140):pgettext('color name','Tan'),
+# Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,128):pgettext('color name','Teal'),
+# Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(216,191,216):pgettext('color name','Thistle'),
+# Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,99,71):pgettext('color name','Tomato'),
+# Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(64,224,208):pgettext('color name','Turquoise'),
+# Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,130,238):pgettext('color name','Violet'),
+# Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,222,179):pgettext('color name','Wheat'),
+# Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,255):pgettext('color name','White'),
+# Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,245):pgettext('color name','White Smoke'),
+# Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,0):pgettext('color name','Yellow'),
+# Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(154,205,50):pgettext('color name','Yellow Green'),
}
-


https://bitbucket.org/nvdaaddonteam/nvda/commits/18bc3c3e31d2/
Changeset: 18bc3c3e31d2
Branch: None
User: mdcurran
Date: 2015-03-19 23:28:35+00:00
Summary: Merge branch 't4984' into next. Incubates #4984

Affected #: 1 file

diff --git a/source/colors.py b/source/colors.py
index 2fe4db3..f067b9d 100644
--- a/source/colors.py
+++ b/source/colors.py
@@ -6,6 +6,7 @@

from collections import namedtuple
import math
+import colorsys
from ctypes.wintypes import COLORREF
import re

@@ -74,8 +75,15 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
longestDistance=255.0
# Translators: Reported when text is written in unknown color.
closestName=_("unknown color")
+
selfHSV=colorsys.rgb_to_hsv(self.red/255.0,self.green/255.0,self.blue/255.0)
for possibleRGB,possibleName in RGBToNames.iteritems():
-
distance=math.sqrt(abs(self.red-possibleRGB.red)**2+abs(self.green-possibleRGB.green)**2+abs(self.blue-possibleRGB.blue)**2)
+
possibleHSV=colorsys.rgb_to_hsv(possibleRGB.red/255.0,possibleRGB.green/255.0,possibleRGB.blue/255.0)
+ dh=abs(selfHSV[0]-possibleHSV[0])
+ if dh>0.5:
+ dh=1-dh
+ ds=abs(selfHSV[1]-possibleHSV[1])
+ dv=abs(selfHSV[2]-possibleHSV[2])
+ distance=math.sqrt(0.4*(dh**2)+0.1*(ds**2)+0.1*(dv**2))
if distance<longestDistance:
longestDistance=distance
closestName=possibleName
@@ -85,48 +93,284 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
RGBToNamesCache={}

RGBToNames={
- #Standard 16 HTML 4 colors
- # Translators: The color black.
- RGB(0x00,0x00,0x00):_('black'),
- # Translators: The color dark green.
- RGB(0x00,0x80,0x00):_('dark green'),
- # Translators: The light gray color.
- RGB(0xc0,0xc0,0xc0):_('light grey'),
- # Translators: The color green (full brightness)
- RGB(0x00,0xff,0x00):_('green'),
- # Translators: The color gray (halfway between white and black).
- RGB(0x80,0x80,0x80):_('grey'),
- # Translators: the color olive.
- # For more info see:
http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
- RGB(0x80,0x80,0x00):_('olive'),
- # Translators: The color white.
- RGB(0xff,0xff,0xff):_('white'),
- # Translators: The color yellow.
- RGB(0xff,0xff,0x00):_('yellow'),
- # Translators: The dark red color.
- RGB(0x80,0x00,0x00):_('dark red'),
- # Translators: The color navy blue (dark blue).
- # For more info see http://en.wikipedia.org/wiki/Navy_blue
- RGB(0x00,0x00,0xa0):_('navy blue'),
- # Translators: The color red.
- RGB(0xff,0x00,0x00):_('red'),
- # Translators: The color blue.
- RGB(0x00,0x00,0xff):_('blue'),
- # Translators: The color purple.
- RGB(0x80,0x00,0x80):_('purple'),
- # Translators: The color teal, which is a mix of green and blue, mostly
green.
- # For more info see http://en.wikipedia.org/wiki/Teal
- RGB(0x00,0x80,0x80):_('teal'),
- # Translators: The color fuchsia is a mix of blue and red.
- # For more info see: http://en.wikipedia.org/wiki/Magenta
- RGB(0xff,0x00,0xff):_('fuchsia'),
- # Translators: The aqua color is an equal amount of blue and green.
- # For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
- RGB(0x00,0xff,0xff):_('aqua'),
-
- #Extra CSS 2.1 color
-
- # Translators: This is the color orange.
- RGB(0xff,0xa5,0x00):_('orange'),
+# Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,248,255):pgettext('color name','Alice Blue'),
+# Translators: the color Antique White (RGB 250, 235, 215) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,235,215):pgettext('color name','Antique White'),
+# Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Aqua'),
+# Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,212):pgettext('color name','Aquamarine'),
+# Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,255):pgettext('color name','Azure'),
+# Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,220):pgettext('color name','Beige'),
+# Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,196):pgettext('color name','Bisque'),
+# Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,0):pgettext('color name','Black'),
+# Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,235,205):pgettext('color name','Blanched Almond'),
+# Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,255):pgettext('color name','Blue'),
+# Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(138,43,226):pgettext('color name','Blue Violet'),
+# Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(165,42,42):pgettext('color name','Brown'),
+# Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(222,184,135):pgettext('color name','Burly Wood'),
+# Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(95,158,160):pgettext('color name','Cadet Blue'),
+# Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,0):pgettext('color name','Chartreuse'),
+# Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,105,30):pgettext('color name','Chocolate'),
+# Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,127,80):pgettext('color name','Coral'),
+# Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(100,149,237):pgettext('color name','Cornflower Blue'),
+# Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,248,220):pgettext('color name','Cornsilk'),
+# Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,20,60):pgettext('color name','Crimson'),
+# Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Cyan'),
+# Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,139):pgettext('color name','Dark Blue'),
+# Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,139,139):pgettext('color name','Dark Cyan'),
+# Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(184,134,11):pgettext('color name','Dark Goldenrod'),
+# Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(169,169,169):pgettext('color name','Dark Gray'),
+# Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,100,0):pgettext('color name','Dark Green'),
+# Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(189,183,107):pgettext('color name','Dark Khaki'),
+# Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,139):pgettext('color name','Dark Magenta'),
+# Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(85,107,47):pgettext('color name','Dark Olive Green'),
+# Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,140,0):pgettext('color name','Dark Orange'),
+# Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(153,50,204):pgettext('color name','Dark Orchid'),
+# Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,0):pgettext('color name','Dark Red'),
+# Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(233,150,122):pgettext('color name','Dark Salmon'),
+# Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(143,188,143):pgettext('color name','Dark Sea Green'),
+# Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,61,139):pgettext('color name','Dark Slate Blue'),
+# Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(47,79,79):pgettext('color name','Dark Slate Gray'),
+# Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,206,209):pgettext('color name','Dark Turquoise'),
+# Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(148,0,211):pgettext('color name','Dark Violet'),
+# Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,20,147):pgettext('color name','Deep Pink'),
+# Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,191,255):pgettext('color name','Deep Sky Blue'),
+# Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(105,105,105):pgettext('color name','Dim Gray'),
+# Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(30,144,255):pgettext('color name','Dodger Blue'),
+# Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(178,34,34):pgettext('color name','Fire Brick'),
+# Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,240):pgettext('color name','Floral White'),
+# Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(34,139,34):pgettext('color name','Forest Green'),
+# Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Fuchsia'),
+# Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,220,220):pgettext('color name','Gainsboro'),
+# Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(248,248,255):pgettext('color name','Ghost White'),
+# Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,215,0):pgettext('color name','Gold'),
+# Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,165,32):pgettext('color name','Goldenrod'),
+# Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,128):pgettext('color name','Gray'),
+# Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,0):pgettext('color name','Green'),
+# Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,255,47):pgettext('color name','Green Yellow'),
+# Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,240):pgettext('color name','Honeydew'),
+# Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,105,180):pgettext('color name','Hot Pink'),
+# Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,92,92):pgettext('color name','Indian Red'),
+# Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(75,0,130):pgettext('color name','Indigo'),
+# Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,240):pgettext('color name','Ivory'),
+# Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,230,140):pgettext('color name','Khaki'),
+# Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(230,230,250):pgettext('color name','Lavender'),
+# Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,240,245):pgettext('color name','Lavender Blush'),
+# Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(124,252,0):pgettext('color name','Lawn Green'),
+# Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,205):pgettext('color name','Lemon Chiffon'),
+# Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,216,230):pgettext('color name','Light Blue'),
+# Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,128,128):pgettext('color name','Light Coral'),
+# Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(224,255,255):pgettext('color name','Light Cyan'),
+# Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,250,210):pgettext('color name','Light Goldenrod Yellow'),
+# Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(144,238,144):pgettext('color name','Light Green'),
+# Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(211,211,211):pgettext('color name','Light Grey'),
+# Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,182,193):pgettext('color name','Light Pink'),
+# Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,160,122):pgettext('color name','Light Salmon'),
+# Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(32,178,170):pgettext('color name','Light Sea Green'),
+# Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,250):pgettext('color name','Light Sky Blue'),
+# Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(119,136,153):pgettext('color name','Light Slate Gray'),
+# Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,196,222):pgettext('color name','Light Steel Blue'),
+# Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,224):pgettext('color name','Light Yellow'),
+# Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,0):pgettext('color name','Lime'),
+# Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(50,205,50):pgettext('color name','Lime Green'),
+# Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,240,230):pgettext('color name','Linen'),
+# Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Magenta'),
+# Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,0):pgettext('color name','Maroon'),
+# Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(102,205,170):pgettext('color name','Medium Aquamarine'),
+# Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,205):pgettext('color name','Medium Blue'),
+# Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(186,85,211):pgettext('color name','Medium Orchid'),
+# Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(147,112,219):pgettext('color name','Medium Purple'),
+# Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(60,179,113):pgettext('color name','Medium Sea Green'),
+# Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(123,104,238):pgettext('color name','Medium Slate Blue'),
+# Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,250,154):pgettext('color name','Medium Spring Green'),
+# Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,209,204):pgettext('color name','Medium Turquoise'),
+# Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(199,21,133):pgettext('color name','Medium Violet Red'),
+# Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(25,25,112):pgettext('color name','Midnight Blue'),
+# Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,255,250):pgettext('color name','Mint Cream'),
+# Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,225):pgettext('color name','Misty Rose'),
+# Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,181):pgettext('color name','Moccasin'),
+# Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,222,173):pgettext('color name','Navajo White'),
+# Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,128):pgettext('color name','Navy'),
+# Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(253,245,230):pgettext('color name','Old Lace'),
+# Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,0):pgettext('color name','Olive'),
+# Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(107,142,35):pgettext('color name','Olive Drab'),
+# Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,165,0):pgettext('color name','Orange'),
+# Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,69,0):pgettext('color name','Orange Red'),
+# Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,112,214):pgettext('color name','Orchid'),
+# Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,232,170):pgettext('color name','Pale Goldenrod'),
+# Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(152,251,152):pgettext('color name','Pale Green'),
+# Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(175,238,238):pgettext('color name','Pale Turquoise'),
+# Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(219,112,147):pgettext('color name','Pale Violet Red'),
+# Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,239,213):pgettext('color name','Papaya Whip'),
+# Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,218,185):pgettext('color name','Peach Puff'),
+# Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,133,63):pgettext('color name','Peru'),
+# Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,192,203):pgettext('color name','Pink'),
+# Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(221,160,221):pgettext('color name','Plum'),
+# Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,224,230):pgettext('color name','Powder Blue'),
+# Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,128):pgettext('color name','Purple'),
+# Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,0):pgettext('color name','Red'),
+# Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(188,143,143):pgettext('color name','Rosy Brown'),
+# Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(65,105,225):pgettext('color name','Royal Blue'),
+# Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,69,19):pgettext('color name','Saddle Brown'),
+# Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,128,114):pgettext('color name','Salmon'),
+# Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(244,164,96):pgettext('color name','Sandy Brown'),
+# Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(46,139,87):pgettext('color name','Sea Green'),
+# Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,245,238):pgettext('color name','Seashell'),
+# Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(160,82,45):pgettext('color name','Sienna'),
+# Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(192,192,192):pgettext('color name','Silver'),
+# Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,235):pgettext('color name','Sky Blue'),
+# Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(106,90,205):pgettext('color name','Slate Blue'),
+# Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(112,128,144):pgettext('color name','Slate Gray'),
+# Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,250):pgettext('color name','Snow'),
+# Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,127):pgettext('color name','Spring Green'),
+# Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(70,130,180):pgettext('color name','Steel Blue'),
+# Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,180,140):pgettext('color name','Tan'),
+# Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,128):pgettext('color name','Teal'),
+# Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(216,191,216):pgettext('color name','Thistle'),
+# Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,99,71):pgettext('color name','Tomato'),
+# Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(64,224,208):pgettext('color name','Turquoise'),
+# Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,130,238):pgettext('color name','Violet'),
+# Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,222,179):pgettext('color name','Wheat'),
+# Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,255):pgettext('color name','White'),
+# Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,245):pgettext('color name','White Smoke'),
+# Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,0):pgettext('color name','Yellow'),
+# Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(154,205,50):pgettext('color name','Yellow Green'),
}
-


https://bitbucket.org/nvdaaddonteam/nvda/commits/f7c5528fbae3/
Changeset: f7c5528fbae3
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:14+00:00
Summary: The windows version is now reported as major.minor.build
service_pack_major.service_pack_minor product_type in both logging and update
check queries.

Re #3724

Affected #: 2 files

diff --git a/source/core.py b/source/core.py
index 79aa249..137d6bf 100644
--- a/source/core.py
+++ b/source/core.py
@@ -172,7 +172,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.warning("Could not set language to %s"%lang)
import versionInfo
log.info("NVDA version %s" % versionInfo.version)
- log.info("Using Windows version %r" % (sys.getwindowsversion(),))
+ log.info("Using Windows version %s" % "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=sys.getwindowsversion()))
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
# Set a reasonable timeout for any socket connections NVDA makes.

diff --git a/source/updateCheck.py b/source/updateCheck.py
index 2a88500..78ea8b2 100644
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -64,7 +64,7 @@ def checkForUpdate(auto=False):
"autoCheck": auto,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
- "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack}".format(v=winVer),
+ "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVer),
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
"language": languageHandler.getLanguage(),
"installed": config.isInstalledCopy(),


https://bitbucket.org/nvdaaddonteam/nvda/commits/574a890008aa/
Changeset: 574a890008aa
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:14+00:00
Summary: sys.getwindowsversion() calls replaced with variable in winVersion
module, re #3724

Affected #: 4 files

diff --git a/source/UIAHandler.py b/source/UIAHandler.py
index 0978374..e4c7cb9 100644
--- a/source/UIAHandler.py
+++ b/source/UIAHandler.py
@@ -1,4 +1,4 @@
-import sys
+import winVersion
import comtypes
import config
from logHandler import log
@@ -7,8 +7,7 @@ handler=None
isUIAAvailable=False

if config.conf and config.conf["UIA"]["enabled"]:
- winver=sys.getwindowsversion()
- winver=winver.major+(winver.minor/10.0)
+ winver=winVersion.winVersion.major+(winVersion.winVersion.minor/10.0)
if winver>=config.conf["UIA"]["minWindowsVersion"]:
try:
from _UIAHandler import *

diff --git a/source/core.py b/source/core.py
index 137d6bf..3dfcd10 100644
--- a/source/core.py
+++ b/source/core.py
@@ -18,6 +18,7 @@ comtypes.gen.__path__.append(comInterfaces.__path__[0])
import comtypesMonkeyPatches

import sys
+import winVersion
import thread
import nvwave
import os
@@ -172,7 +173,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.warning("Could not set language to %s"%lang)
import versionInfo
log.info("NVDA version %s" % versionInfo.version)
- log.info("Using Windows version %s" % "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=sys.getwindowsversion()))
+ log.info("Using Windows version %s" % "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVersion.winVersion))
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
# Set a reasonable timeout for any socket connections NVDA makes.

diff --git a/source/updateCheck.py b/source/updateCheck.py
index 78ea8b2..5bc9552 100644
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -15,7 +15,7 @@ import versionInfo
if not versionInfo.updateVersionType:
raise RuntimeError("No update version type, update checking not
supported")

-import sys
+import winVersion
import os
import threading
import time
@@ -59,12 +59,11 @@ def checkForUpdate(auto=False):
@rtype: dict
@raise RuntimeError: If there is an error checking for an update.
"""
- winVer = sys.getwindowsversion()
params = {
"autoCheck": auto,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
- "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVer),
+ "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVersion.winVersion),
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
"language": languageHandler.getLanguage(),
"installed": config.isInstalledCopy(),

diff --git a/source/winVersion.py b/source/winVersion.py
index 69a6b27..7359a7b 100644
--- a/source/winVersion.py
+++ b/source/winVersion.py
@@ -7,18 +7,19 @@
import sys
import winUser

+winVersion=sys.getwindowsversion()
+
def canRunVc2010Builds():
- OSVersion=sys.getwindowsversion()
- if (OSVersion.major, OSVersion.minor) < (5, 1):
+ if (winVersion.major, winVersion.minor) < (5, 1):
# Earlier than Windows XP.
return False
- if OSVersion.major == 5:
- if OSVersion.minor == 1:
+ if winVersion.major == 5:
+ if winVersion.minor == 1:
# Windows XP for x86.
- return OSVersion.service_pack_major >= 2
- if OSVersion.minor == 2 and OSVersion.product_type!=1:
+ return winVersion.service_pack_major >= 2
+ if winVersion.minor == 2 and winVersion.product_type!=1:
# Windows Server 2003.
# (5.2 x64 is Windows XP x64. Its RTM is based on
Server 2003 sp1,
# so all versions should be fine.)
- return OSVersion.service_pack_major >= 1
+ return winVersion.service_pack_major >= 1
return True


https://bitbucket.org/nvdaaddonteam/nvda/commits/29fc3f82cc11/
Changeset: 29fc3f82cc11
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:15+00:00
Summary: Added winVersion.longWinVersion which is a more readable string
containing windows version, build, service pack (if any) and product type
(workstation, domain controller or server)
Re #3724

Affected #: 3 files

diff --git a/source/core.py b/source/core.py
index 3dfcd10..850e1c7 100644
--- a/source/core.py
+++ b/source/core.py
@@ -173,7 +173,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.warning("Could not set language to %s"%lang)
import versionInfo
log.info("NVDA version %s" % versionInfo.version)
- log.info("Using Windows version %s" % "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVersion.winVersion))
+ log.info("Using Windows version %s" % winVersion.longWinVersion)
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
# Set a reasonable timeout for any socket connections NVDA makes.

diff --git a/source/updateCheck.py b/source/updateCheck.py
index 5bc9552..ada7704 100644
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -63,7 +63,7 @@ def checkForUpdate(auto=False):
"autoCheck": auto,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
- "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack_major}.{v.service_pack_minor}
{v.product_type}".format(v=winVersion.winVersion),
+ "osVersion": winVersion.longWinVersion,
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
"language": languageHandler.getLanguage(),
"installed": config.isInstalledCopy(),

diff --git a/source/winVersion.py b/source/winVersion.py
index 7359a7b..5f49326 100644
--- a/source/winVersion.py
+++ b/source/winVersion.py
@@ -8,6 +8,10 @@ import sys
import winUser

winVersion=sys.getwindowsversion()
+longWinVersion="{v.major}.{v.minor}.{v.build}".format(v=winVersion)
+if (winVersion.service_pack_major != 0):
+ longWinVersion+=" service pack %d.%d" %
(winVersion.service_pack_major,winVersion.service_pack_minor)
+longWinVersion+=" %s" % ["workstation","domain
controller","server"][winVersion.product_type-1]

def canRunVc2010Builds():
if (winVersion.major, winVersion.minor) < (5, 1):


https://bitbucket.org/nvdaaddonteam/nvda/commits/95b0985cae65/
Changeset: 95b0985cae65
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:15+00:00
Summary: Replace more sys.getwindowsversion calls with winVersion.winVersion

Affected #: 4 files

diff --git a/source/NVDAObjects/window/edit.py
b/source/NVDAObjects/window/edit.py
index 92bbc67..a6b9fbf 100644
--- a/source/NVDAObjects/window/edit.py
+++ b/source/NVDAObjects/window/edit.py
@@ -5,6 +5,7 @@

import locale
import sys
+import winVersion
import comtypes.client
import struct
import ctypes
@@ -378,7 +379,7 @@ class EditTextInfo(textInfos.offsets.OffsetsTextInfo):
start=end

end=watchdog.cancellableSendMessage(self.obj.windowHandle,EM_FINDWORDBREAK,WB_MOVEWORDRIGHT,offset)
return (start,end)
- elif sys.getwindowsversion().major<6: #Implementation of
standard edit field wordbreak behaviour (only breaks on space)
+ elif sys.winVersion.winVersion.major<6: #Implementation of
standard edit field wordbreak behaviour (only breaks on space)
lineStart,lineEnd=self._getLineOffsets(offset)
if offset>=lineEnd:
return offset,offset+1

diff --git a/source/appModuleHandler.py b/source/appModuleHandler.py
index 847db71..209ac9e 100644
--- a/source/appModuleHandler.py
+++ b/source/appModuleHandler.py
@@ -16,6 +16,7 @@ import ctypes
import ctypes.wintypes
import os
import sys
+import winVersion
import pkgutil
import threading
import tempfile
@@ -300,7 +301,7 @@ class AppModule(baseObject.ScriptableObject):
#: The application name.
#: @type: str
self.appName=appName
- if sys.getwindowsversion().major > 5:
+ if winVersion.winVersion.major > 5:

self.processHandle=winKernel.openProcess(winKernel.SYNCHRONIZE|winKernel.PROCESS_QUERY_INFORMATION,False,processID)
else:

self.processHandle=winKernel.openProcess(winKernel.SYNCHRONIZE|winKernel.PROCESS_QUERY_INFORMATION|winKernel.PROCESS_VM_READ,False,processID)
@@ -314,7 +315,7 @@ class AppModule(baseObject.ScriptableObject):
if not self.processHandle:
raise RuntimeError("processHandle is 0")
# Choose the right function to use to get the executable file
name
- if sys.getwindowsversion().major > 5:
+ if winVersion.winVersion.major > 5:
# For Windows Vista and higher, use
QueryFullProcessImageName function
GetModuleFileName =
ctypes.windll.Kernel32.QueryFullProcessImageNameW
else:

diff --git a/source/nvda_service.py b/source/nvda_service.py
index 4f75a2c..8907b60 100644
--- a/source/nvda_service.py
+++ b/source/nvda_service.py
@@ -14,6 +14,7 @@ import os
import time
import subprocess
import _winreg
+import winVersion

CREATE_UNICODE_ENVIRONMENT=1024
INFINITE = 0xffffffff
@@ -314,7 +315,7 @@ class NVDAService(win32serviceutil.ServiceFramework):
def SvcDoRun(self):
initDebug()
debug("service starting")
- self.isWindowsXP = sys.getwindowsversion()[0:2] == (5, 1)
+ self.isWindowsXP = winVersion.winVersion[0:2] == (5, 1)
self.exitEvent = threading.Event()
self.initSession(windll.kernel32.WTSGetActiveConsoleSessionId())
self.exitEvent.wait()

diff --git a/source/touchHandler.py b/source/touchHandler.py
index 0abd66e..49a88a9 100644
--- a/source/touchHandler.py
+++ b/source/touchHandler.py
@@ -10,6 +10,7 @@ from ctypes import *
from ctypes.wintypes import *
import re
import sys
+import winVersion
import globalPluginHandler
import config
import winUser
@@ -275,8 +276,7 @@ def initialize():
if not config.isInstalledCopy():
log.debugWarning("Touch only supported on installed copies")
raise NotImplementedError
- version=sys.getwindowsversion()
- if (version.major*10+version.minor)<62:
+ if (winVersion.winVersion.major*10+winVersion.winVersion.minor)<62:
log.debugWarning("Touch only supported on Windows 8 and higher")
raise NotImplementedError
maxTouches=windll.user32.GetSystemMetrics(95) #maximum touches


https://bitbucket.org/nvdaaddonteam/nvda/commits/6168c50e4904/
Changeset: 6168c50e4904
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:16+00:00
Summary: Small fixes and clean ups for #3724

Affected #: 2 files

diff --git a/source/NVDAObjects/window/edit.py
b/source/NVDAObjects/window/edit.py
index a6b9fbf..477830f 100644
--- a/source/NVDAObjects/window/edit.py
+++ b/source/NVDAObjects/window/edit.py
@@ -4,7 +4,6 @@
#See the file COPYING for more details.

import locale
-import sys
import winVersion
import comtypes.client
import struct
@@ -379,7 +378,7 @@ class EditTextInfo(textInfos.offsets.OffsetsTextInfo):
start=end

end=watchdog.cancellableSendMessage(self.obj.windowHandle,EM_FINDWORDBREAK,WB_MOVEWORDRIGHT,offset)
return (start,end)
- elif sys.winVersion.winVersion.major<6: #Implementation of
standard edit field wordbreak behaviour (only breaks on space)
+ elif winVersion.winVersion.major<6: #Implementation of standard
edit field wordbreak behaviour (only breaks on space)
lineStart,lineEnd=self._getLineOffsets(offset)
if offset>=lineEnd:
return offset,offset+1

diff --git a/source/touchHandler.py b/source/touchHandler.py
index 49a88a9..5cf3c79 100644
--- a/source/touchHandler.py
+++ b/source/touchHandler.py
@@ -9,7 +9,6 @@ import threading
from ctypes import *
from ctypes.wintypes import *
import re
-import sys
import winVersion
import globalPluginHandler
import config


https://bitbucket.org/nvdaaddonteam/nvda/commits/1e96ffd9e5a3/
Changeset: 1e96ffd9e5a3
Branch: None
User: Leonard de Ruijter
Date: 2015-03-20 11:15:16+00:00
Summary: Applied changes as requested in comment:10, #3724
* Changed the name longWinVersion to winVersionText
* Excluded service pack minor from winVersionText if it is 0

Affected #: 3 files

diff --git a/source/core.py b/source/core.py
index 850e1c7..c74f5b4 100644
--- a/source/core.py
+++ b/source/core.py
@@ -173,7 +173,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.warning("Could not set language to %s"%lang)
import versionInfo
log.info("NVDA version %s" % versionInfo.version)
- log.info("Using Windows version %s" % winVersion.longWinVersion)
+ log.info("Using Windows version %s" % winVersion.winVersionText)
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
# Set a reasonable timeout for any socket connections NVDA makes.

diff --git a/source/updateCheck.py b/source/updateCheck.py
index ada7704..80acdd3 100644
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -63,7 +63,7 @@ def checkForUpdate(auto=False):
"autoCheck": auto,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
- "osVersion": winVersion.longWinVersion,
+ "osVersion": winVersion.winVersionText,
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
"language": languageHandler.getLanguage(),
"installed": config.isInstalledCopy(),

diff --git a/source/winVersion.py b/source/winVersion.py
index 5f49326..f61fb0e 100644
--- a/source/winVersion.py
+++ b/source/winVersion.py
@@ -8,10 +8,9 @@ import sys
import winUser

winVersion=sys.getwindowsversion()
-longWinVersion="{v.major}.{v.minor}.{v.build}".format(v=winVersion)
-if (winVersion.service_pack_major != 0):
- longWinVersion+=" service pack %d.%d" %
(winVersion.service_pack_major,winVersion.service_pack_minor)
-longWinVersion+=" %s" % ["workstation","domain
controller","server"][winVersion.product_type-1]
+winVersionText="{v.major}.{v.minor}.{v.build}".format(v=winVersion)
+winVersionText+="" if winVersion.service_pack_major == 0 else (" service pack
%d"%winVersion.service_pack_major)+(".%d"%winVersion.service_pack_minor if
winVersion.service_pack_minor!=0 else "")
+winVersionText+=" %s" % ["workstation","domain
controller","server"][winVersion.product_type-1]

def canRunVc2010Builds():
if (winVersion.major, winVersion.minor) < (5, 1):


https://bitbucket.org/nvdaaddonteam/nvda/commits/a64f0ebefdcb/
Changeset: a64f0ebefdcb
Branch: None
User: jteh
Date: 2015-03-26 05:29:15+00:00
Summary: Merge branch 'master' into next

Affected #: 1 file

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index a7432ec..be1ab25 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -7,6 +7,16 @@

== New Features ==
- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
+- New braille translation tables for several Indian languages. (#4778)
+
+
+== Changes ==
+- In NVDA's Document Formatting dialog, the keyboard shortcuts for Report
lists, Report links, Report line numbers and Report font name have been
changed. (#4650)
+- In NVDA's Mouse Settings dialog, keyboard shortcuts have been added for play
audio coordinates when mouse moves and brightness controls audio coordinates
volume. (#4916)
+
+
+== Bug Fixes ==
+- Character descriptions are now handled correctly for conjunct characters in
certain Indian languages. (#4582)


== Changes for Developers ==


https://bitbucket.org/nvdaaddonteam/nvda/commits/f466b7c50c53/
Changeset: f466b7c50c53
Branch: None
User: siddhartha_iitd
Date: 2015-03-30 23:55:13+00:00
Summary: Color label calculation for the color palet in MS Office
applications.

Affected #: 2 files

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 083ad9e..17a3bdd 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1795,4 +1795,5 @@ _staticMap={
("listview",oleacc.ROLE_SYSTEM_CLIENT):"ListviewPane",
("NUIDialog",oleacc.ROLE_SYSTEM_CLIENT):"NUIDialogClient",
("_WwB",oleacc.ROLE_SYSTEM_CLIENT):"winword.ProtectedDocumentPane",
+
("MsoCommandBar",oleacc.ROLE_SYSTEM_LISTITEM):"msOffice.CommandBarListItem",
}

diff --git a/source/NVDAObjects/IAccessible/msOffice.py
b/source/NVDAObjects/IAccessible/msOffice.py
index 5cd6dae..f541936 100755
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -11,6 +11,7 @@ import winUser
import api
from . import IAccessible, getNVDAObjectFromEvent
import eventHandler
+import re

"""Miscellaneous support for Microsoft Office applications.
"""
@@ -105,6 +106,34 @@ class BrokenMsoCommandBar(IAccessible):
return None
return name

+class CommandBarListItem(IAccessible):
+ """A list item in an MSO commandbar, that may be part of a color
palet."""
+
+ COMPILED_RE = re.compile(r'RGB\(\d+, \d+, \d+\)',re.I)
+ def _get_rgbNameAndMatch(self):
+ name = super(CommandBarListItem,self).name
+ if self.COMPILED_RE.match(name):
+ matchRGB = True
+ else:
+ matchRGB = False
+ return name, matchRGB
+
+ def _get_name(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ return colors.RGB.fromString(name).name
+ else:
+ return name
+
+ def _get_description(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ return (', red '+ str(colors.RGB.fromString(name).red)
+ ', green ' + str(colors.RGB.fromString(name).green) + ', blue ' +
str(colors.RGB.fromString(name).blue))
+ else:
+ return super(CommandBarListItem,self).description
+
class SDMSymbols(SDM):

def _get_value(self):


https://bitbucket.org/nvdaaddonteam/nvda/commits/5393cb0ad2b6/
Changeset: 5393cb0ad2b6
Branch: None
User: mdcurran
Date: 2015-03-30 23:57:30+00:00
Summary: Merge branch 't4984' into t3045

Affected #: 1 file

diff --git a/source/colors.py b/source/colors.py
index 2fe4db3..f067b9d 100644
--- a/source/colors.py
+++ b/source/colors.py
@@ -6,6 +6,7 @@

from collections import namedtuple
import math
+import colorsys
from ctypes.wintypes import COLORREF
import re

@@ -74,8 +75,15 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
longestDistance=255.0
# Translators: Reported when text is written in unknown color.
closestName=_("unknown color")
+
selfHSV=colorsys.rgb_to_hsv(self.red/255.0,self.green/255.0,self.blue/255.0)
for possibleRGB,possibleName in RGBToNames.iteritems():
-
distance=math.sqrt(abs(self.red-possibleRGB.red)**2+abs(self.green-possibleRGB.green)**2+abs(self.blue-possibleRGB.blue)**2)
+
possibleHSV=colorsys.rgb_to_hsv(possibleRGB.red/255.0,possibleRGB.green/255.0,possibleRGB.blue/255.0)
+ dh=abs(selfHSV[0]-possibleHSV[0])
+ if dh>0.5:
+ dh=1-dh
+ ds=abs(selfHSV[1]-possibleHSV[1])
+ dv=abs(selfHSV[2]-possibleHSV[2])
+ distance=math.sqrt(0.4*(dh**2)+0.1*(ds**2)+0.1*(dv**2))
if distance<longestDistance:
longestDistance=distance
closestName=possibleName
@@ -85,48 +93,284 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
RGBToNamesCache={}

RGBToNames={
- #Standard 16 HTML 4 colors
- # Translators: The color black.
- RGB(0x00,0x00,0x00):_('black'),
- # Translators: The color dark green.
- RGB(0x00,0x80,0x00):_('dark green'),
- # Translators: The light gray color.
- RGB(0xc0,0xc0,0xc0):_('light grey'),
- # Translators: The color green (full brightness)
- RGB(0x00,0xff,0x00):_('green'),
- # Translators: The color gray (halfway between white and black).
- RGB(0x80,0x80,0x80):_('grey'),
- # Translators: the color olive.
- # For more info see:
http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
- RGB(0x80,0x80,0x00):_('olive'),
- # Translators: The color white.
- RGB(0xff,0xff,0xff):_('white'),
- # Translators: The color yellow.
- RGB(0xff,0xff,0x00):_('yellow'),
- # Translators: The dark red color.
- RGB(0x80,0x00,0x00):_('dark red'),
- # Translators: The color navy blue (dark blue).
- # For more info see http://en.wikipedia.org/wiki/Navy_blue
- RGB(0x00,0x00,0xa0):_('navy blue'),
- # Translators: The color red.
- RGB(0xff,0x00,0x00):_('red'),
- # Translators: The color blue.
- RGB(0x00,0x00,0xff):_('blue'),
- # Translators: The color purple.
- RGB(0x80,0x00,0x80):_('purple'),
- # Translators: The color teal, which is a mix of green and blue, mostly
green.
- # For more info see http://en.wikipedia.org/wiki/Teal
- RGB(0x00,0x80,0x80):_('teal'),
- # Translators: The color fuchsia is a mix of blue and red.
- # For more info see: http://en.wikipedia.org/wiki/Magenta
- RGB(0xff,0x00,0xff):_('fuchsia'),
- # Translators: The aqua color is an equal amount of blue and green.
- # For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
- RGB(0x00,0xff,0xff):_('aqua'),
-
- #Extra CSS 2.1 color
-
- # Translators: This is the color orange.
- RGB(0xff,0xa5,0x00):_('orange'),
+# Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,248,255):pgettext('color name','Alice Blue'),
+# Translators: the color Antique White (RGB 250, 235, 215) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,235,215):pgettext('color name','Antique White'),
+# Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Aqua'),
+# Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,212):pgettext('color name','Aquamarine'),
+# Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,255):pgettext('color name','Azure'),
+# Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,220):pgettext('color name','Beige'),
+# Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,196):pgettext('color name','Bisque'),
+# Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,0):pgettext('color name','Black'),
+# Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,235,205):pgettext('color name','Blanched Almond'),
+# Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,255):pgettext('color name','Blue'),
+# Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(138,43,226):pgettext('color name','Blue Violet'),
+# Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(165,42,42):pgettext('color name','Brown'),
+# Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(222,184,135):pgettext('color name','Burly Wood'),
+# Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(95,158,160):pgettext('color name','Cadet Blue'),
+# Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,0):pgettext('color name','Chartreuse'),
+# Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,105,30):pgettext('color name','Chocolate'),
+# Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,127,80):pgettext('color name','Coral'),
+# Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(100,149,237):pgettext('color name','Cornflower Blue'),
+# Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,248,220):pgettext('color name','Cornsilk'),
+# Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,20,60):pgettext('color name','Crimson'),
+# Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Cyan'),
+# Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,139):pgettext('color name','Dark Blue'),
+# Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,139,139):pgettext('color name','Dark Cyan'),
+# Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(184,134,11):pgettext('color name','Dark Goldenrod'),
+# Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(169,169,169):pgettext('color name','Dark Gray'),
+# Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,100,0):pgettext('color name','Dark Green'),
+# Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(189,183,107):pgettext('color name','Dark Khaki'),
+# Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,139):pgettext('color name','Dark Magenta'),
+# Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(85,107,47):pgettext('color name','Dark Olive Green'),
+# Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,140,0):pgettext('color name','Dark Orange'),
+# Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(153,50,204):pgettext('color name','Dark Orchid'),
+# Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,0):pgettext('color name','Dark Red'),
+# Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(233,150,122):pgettext('color name','Dark Salmon'),
+# Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(143,188,143):pgettext('color name','Dark Sea Green'),
+# Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,61,139):pgettext('color name','Dark Slate Blue'),
+# Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(47,79,79):pgettext('color name','Dark Slate Gray'),
+# Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,206,209):pgettext('color name','Dark Turquoise'),
+# Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(148,0,211):pgettext('color name','Dark Violet'),
+# Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,20,147):pgettext('color name','Deep Pink'),
+# Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,191,255):pgettext('color name','Deep Sky Blue'),
+# Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(105,105,105):pgettext('color name','Dim Gray'),
+# Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(30,144,255):pgettext('color name','Dodger Blue'),
+# Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(178,34,34):pgettext('color name','Fire Brick'),
+# Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,240):pgettext('color name','Floral White'),
+# Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(34,139,34):pgettext('color name','Forest Green'),
+# Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Fuchsia'),
+# Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,220,220):pgettext('color name','Gainsboro'),
+# Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(248,248,255):pgettext('color name','Ghost White'),
+# Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,215,0):pgettext('color name','Gold'),
+# Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,165,32):pgettext('color name','Goldenrod'),
+# Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,128):pgettext('color name','Gray'),
+# Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,0):pgettext('color name','Green'),
+# Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,255,47):pgettext('color name','Green Yellow'),
+# Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,240):pgettext('color name','Honeydew'),
+# Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,105,180):pgettext('color name','Hot Pink'),
+# Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,92,92):pgettext('color name','Indian Red'),
+# Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(75,0,130):pgettext('color name','Indigo'),
+# Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,240):pgettext('color name','Ivory'),
+# Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,230,140):pgettext('color name','Khaki'),
+# Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(230,230,250):pgettext('color name','Lavender'),
+# Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,240,245):pgettext('color name','Lavender Blush'),
+# Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(124,252,0):pgettext('color name','Lawn Green'),
+# Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,205):pgettext('color name','Lemon Chiffon'),
+# Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,216,230):pgettext('color name','Light Blue'),
+# Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,128,128):pgettext('color name','Light Coral'),
+# Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(224,255,255):pgettext('color name','Light Cyan'),
+# Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,250,210):pgettext('color name','Light Goldenrod Yellow'),
+# Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(144,238,144):pgettext('color name','Light Green'),
+# Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(211,211,211):pgettext('color name','Light Grey'),
+# Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,182,193):pgettext('color name','Light Pink'),
+# Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,160,122):pgettext('color name','Light Salmon'),
+# Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(32,178,170):pgettext('color name','Light Sea Green'),
+# Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,250):pgettext('color name','Light Sky Blue'),
+# Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(119,136,153):pgettext('color name','Light Slate Gray'),
+# Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,196,222):pgettext('color name','Light Steel Blue'),
+# Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,224):pgettext('color name','Light Yellow'),
+# Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,0):pgettext('color name','Lime'),
+# Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(50,205,50):pgettext('color name','Lime Green'),
+# Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,240,230):pgettext('color name','Linen'),
+# Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Magenta'),
+# Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,0):pgettext('color name','Maroon'),
+# Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(102,205,170):pgettext('color name','Medium Aquamarine'),
+# Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,205):pgettext('color name','Medium Blue'),
+# Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(186,85,211):pgettext('color name','Medium Orchid'),
+# Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(147,112,219):pgettext('color name','Medium Purple'),
+# Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(60,179,113):pgettext('color name','Medium Sea Green'),
+# Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(123,104,238):pgettext('color name','Medium Slate Blue'),
+# Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,250,154):pgettext('color name','Medium Spring Green'),
+# Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,209,204):pgettext('color name','Medium Turquoise'),
+# Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(199,21,133):pgettext('color name','Medium Violet Red'),
+# Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(25,25,112):pgettext('color name','Midnight Blue'),
+# Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,255,250):pgettext('color name','Mint Cream'),
+# Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,225):pgettext('color name','Misty Rose'),
+# Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,181):pgettext('color name','Moccasin'),
+# Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,222,173):pgettext('color name','Navajo White'),
+# Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,128):pgettext('color name','Navy'),
+# Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(253,245,230):pgettext('color name','Old Lace'),
+# Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,0):pgettext('color name','Olive'),
+# Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(107,142,35):pgettext('color name','Olive Drab'),
+# Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,165,0):pgettext('color name','Orange'),
+# Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,69,0):pgettext('color name','Orange Red'),
+# Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,112,214):pgettext('color name','Orchid'),
+# Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,232,170):pgettext('color name','Pale Goldenrod'),
+# Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(152,251,152):pgettext('color name','Pale Green'),
+# Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(175,238,238):pgettext('color name','Pale Turquoise'),
+# Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(219,112,147):pgettext('color name','Pale Violet Red'),
+# Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,239,213):pgettext('color name','Papaya Whip'),
+# Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,218,185):pgettext('color name','Peach Puff'),
+# Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,133,63):pgettext('color name','Peru'),
+# Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,192,203):pgettext('color name','Pink'),
+# Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(221,160,221):pgettext('color name','Plum'),
+# Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,224,230):pgettext('color name','Powder Blue'),
+# Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,128):pgettext('color name','Purple'),
+# Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,0):pgettext('color name','Red'),
+# Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(188,143,143):pgettext('color name','Rosy Brown'),
+# Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(65,105,225):pgettext('color name','Royal Blue'),
+# Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,69,19):pgettext('color name','Saddle Brown'),
+# Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,128,114):pgettext('color name','Salmon'),
+# Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(244,164,96):pgettext('color name','Sandy Brown'),
+# Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(46,139,87):pgettext('color name','Sea Green'),
+# Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,245,238):pgettext('color name','Seashell'),
+# Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(160,82,45):pgettext('color name','Sienna'),
+# Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(192,192,192):pgettext('color name','Silver'),
+# Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,235):pgettext('color name','Sky Blue'),
+# Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(106,90,205):pgettext('color name','Slate Blue'),
+# Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(112,128,144):pgettext('color name','Slate Gray'),
+# Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,250):pgettext('color name','Snow'),
+# Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,127):pgettext('color name','Spring Green'),
+# Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(70,130,180):pgettext('color name','Steel Blue'),
+# Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,180,140):pgettext('color name','Tan'),
+# Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,128):pgettext('color name','Teal'),
+# Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(216,191,216):pgettext('color name','Thistle'),
+# Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,99,71):pgettext('color name','Tomato'),
+# Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(64,224,208):pgettext('color name','Turquoise'),
+# Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,130,238):pgettext('color name','Violet'),
+# Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,222,179):pgettext('color name','Wheat'),
+# Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,255):pgettext('color name','White'),
+# Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,245):pgettext('color name','White Smoke'),
+# Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,0):pgettext('color name','Yellow'),
+# Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(154,205,50):pgettext('color name','Yellow Green'),
}
-


https://bitbucket.org/nvdaaddonteam/nvda/commits/7d01e14de4fd/
Changeset: 7d01e14de4fd
Branch: None
User: mdcurran
Date: 2015-03-31 00:05:14+00:00
Summary: CommandBarListItem color palet item: allow the RGB description to
be translatable.

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/msOffice.py
b/source/NVDAObjects/IAccessible/msOffice.py
index f541936..f08061d 100755
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -130,7 +130,9 @@ class CommandBarListItem(IAccessible):
name, matchRGB = self.rgbNameAndMatch
if matchRGB:
import colors
- return (', red '+ str(colors.RGB.fromString(name).red)
+ ', green ' + str(colors.RGB.fromString(name).green) + ', blue ' +
str(colors.RGB.fromString(name).blue))
+ rgb=colors.RGB.fromString(name)
+ # Translators: a color, broken down into its RGB red,
green, blue parts.
+ return _("RGB red {rgb.red}, green {rgb.green} and blue
{rgb.blue}").format(rgb=colors.RGB.fromString(name))
else:
return super(CommandBarListItem,self).description



https://bitbucket.org/nvdaaddonteam/nvda/commits/c409fd11564c/
Changeset: c409fd11564c
Branch: None
User: mdcurran
Date: 2015-03-31 00:05:36+00:00
Summary: Merge branch 't3045' into next. Incubates #3045

Affected #: 2 files

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 083ad9e..17a3bdd 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1795,4 +1795,5 @@ _staticMap={
("listview",oleacc.ROLE_SYSTEM_CLIENT):"ListviewPane",
("NUIDialog",oleacc.ROLE_SYSTEM_CLIENT):"NUIDialogClient",
("_WwB",oleacc.ROLE_SYSTEM_CLIENT):"winword.ProtectedDocumentPane",
+
("MsoCommandBar",oleacc.ROLE_SYSTEM_LISTITEM):"msOffice.CommandBarListItem",
}

diff --git a/source/NVDAObjects/IAccessible/msOffice.py
b/source/NVDAObjects/IAccessible/msOffice.py
index 5cd6dae..f08061d 100755
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -11,6 +11,7 @@ import winUser
import api
from . import IAccessible, getNVDAObjectFromEvent
import eventHandler
+import re

"""Miscellaneous support for Microsoft Office applications.
"""
@@ -105,6 +106,36 @@ class BrokenMsoCommandBar(IAccessible):
return None
return name

+class CommandBarListItem(IAccessible):
+ """A list item in an MSO commandbar, that may be part of a color
palet."""
+
+ COMPILED_RE = re.compile(r'RGB\(\d+, \d+, \d+\)',re.I)
+ def _get_rgbNameAndMatch(self):
+ name = super(CommandBarListItem,self).name
+ if self.COMPILED_RE.match(name):
+ matchRGB = True
+ else:
+ matchRGB = False
+ return name, matchRGB
+
+ def _get_name(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ return colors.RGB.fromString(name).name
+ else:
+ return name
+
+ def _get_description(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ rgb=colors.RGB.fromString(name)
+ # Translators: a color, broken down into its RGB red,
green, blue parts.
+ return _("RGB red {rgb.red}, green {rgb.green} and blue
{rgb.blue}").format(rgb=colors.RGB.fromString(name))
+ else:
+ return super(CommandBarListItem,self).description
+
class SDMSymbols(SDM):

def _get_value(self):


https://bitbucket.org/nvdaaddonteam/nvda/commits/1ac99db91d8c/
Changeset: 1ac99db91d8c
Branch: None
User: mdcurran
Date: 2015-03-31 00:15:28+00:00
Summary: Merge branch 'in_t3040_new' into t3040

Affected #: 2 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 884dd94..4ecfefc 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -564,9 +564,9 @@ class ExcelCell(ExcelBase):
states.add(controlTypes.STATE_HASCOMMENT)
if self._overlapInfo is not None:
if self._overlapInfo['obscuredFromRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURED)
+ states.add(controlTypes.STATE_CROPPED)
if self._overlapInfo['obscuringRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURING)
+ states.add(controlTypes.STATE_OVERFLOWING)
return states

def getCellWidthAndTextWidth(self):
@@ -582,7 +582,7 @@ class ExcelCell(ExcelBase):
deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(tempDC, 88)
#Fetching Font Size and Weight information
iFontSize = self.excelCellObject.Font.Size
- iFontSize = int(iFontSize)
+ iFontSize = 11 if iFontSize is None else int(iFontSize)
iFontSize = ctypes.c_int(iFontSize)
iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize,
deviceCaps, 72)
#Font Weight for Bold FOnt is 700 and for normal font it's 400

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 223a75d..1740780 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -188,6 +188,8 @@ STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
STATE_OBSCURING=0x8000000000
+STATE_CROPPED=0x10000000000
+STATE_OVERFLOWING=0X20000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -552,6 +554,10 @@ stateLabels={
STATE_OBSCURED:_("obscured"),
# Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
STATE_OBSCURING:_("obscuring"),
+ # Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
+ STATE_CROPPED:_("cropped"),
+ # Translators: a state that denotes that the object(text) is
overflowing into the adjacent space
+ STATE_OVERFLOWING:_("overflowing"),
}

negativeStateLabels={


https://bitbucket.org/nvdaaddonteam/nvda/commits/2e2b33d2b034/
Changeset: 2e2b33d2b034
Branch: None
User: mdcurran
Date: 2015-03-31 00:19:44+00:00
Summary: Merge branch 't3040' into next. Incubates #3040

Affected #: 2 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index da2db7d..d5ba5df 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -829,9 +829,9 @@ class ExcelCell(ExcelBase):
states.add(controlTypes.STATE_HASCOMMENT)
if self._overlapInfo is not None:
if self._overlapInfo['obscuredFromRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURED)
+ states.add(controlTypes.STATE_CROPPED)
if self._overlapInfo['obscuringRightBy'] > 0:
- states.add(controlTypes.STATE_OBSCURING)
+ states.add(controlTypes.STATE_OVERFLOWING)
return states

def getCellWidthAndTextWidth(self):
@@ -847,7 +847,7 @@ class ExcelCell(ExcelBase):
deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(tempDC, 88)
#Fetching Font Size and Weight information
iFontSize = self.excelCellObject.Font.Size
- iFontSize = int(iFontSize)
+ iFontSize = 11 if iFontSize is None else int(iFontSize)
iFontSize = ctypes.c_int(iFontSize)
iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize,
deviceCaps, 72)
#Font Weight for Bold FOnt is 700 and for normal font it's 400

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 223a75d..1740780 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -188,6 +188,8 @@ STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
STATE_OBSCURING=0x8000000000
+STATE_CROPPED=0x10000000000
+STATE_OVERFLOWING=0X20000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -552,6 +554,10 @@ stateLabels={
STATE_OBSCURED:_("obscured"),
# Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
STATE_OBSCURING:_("obscuring"),
+ # Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
+ STATE_CROPPED:_("cropped"),
+ # Translators: a state that denotes that the object(text) is
overflowing into the adjacent space
+ STATE_OVERFLOWING:_("overflowing"),
}

negativeStateLabels={


https://bitbucket.org/nvdaaddonteam/nvda/commits/cdcc20c86ccf/
Changeset: cdcc20c86ccf
Branch: None
User: mdcurran
Date: 2015-03-31 05:54:39+00:00
Summary: Merge branch 't4699'. Fixes #4699

Affected #: 2 files

diff --git a/source/globalCommands.py b/source/globalCommands.py
index f94c95d..a99412e 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -1347,8 +1347,12 @@ class GlobalCommands(ScriptableObject):
index=(index+1)%len(touchHandler.availableTouchModes)
newMode=touchHandler.availableTouchModes[index]
touchHandler.handler._curTouchMode=newMode
- # Translators: Cycles through available touch modes (a group of
related touch gestures; example output: "object mode"; see the user guide for
more information on touch modes).
- ui.message(_("%s mode")%newMode)
+ try:
+ newModeLabel=touchHandler.touchModeLabels[newMode]
+ except KeyError:
+ # Translators: Cycles through available touch modes (a
group of related touch gestures; example output: "object mode"; see the user
guide for more information on touch modes).
+ newModeLabel=_("%s mode")%newMode
+ ui.message(newModeLabel)
# Translators: Input help mode message for a touchscreen gesture.
script_touch_changeMode.__doc__=_("cycles between available touch
modes")
script_touch_changeMode.category=SCRCAT_TOUCH

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index be1ab25..630b4e3 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -21,6 +21,7 @@

== Changes for Developers ==
- brailleInput.handler.sendChars(mychar) will no longer filter out a character
if it is equal to the previous character, by ensuring that the key sent is
correctly released.
+- scripts for changing touch modes will now honor new labeles added to
touchHandler.touchModeLabels. (#4699)


= 2015.1 =


https://bitbucket.org/nvdaaddonteam/nvda/commits/8f4c5111324f/
Changeset: 8f4c5111324f
Branch: None
User: mdcurran
Date: 2015-03-31 06:05:04+00:00
Summary: Merge branch 't4976'. Fixes #4976

Affected #: 2 files

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 9541e9b..36b58ae 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -602,7 +602,8 @@ class MSHTML(IAccessible):
value=""
return value
IARole=self.IAccessibleRole
- if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT):
+ # value is not useful on certain nodes that just expose a URL,
or they have other ways of getting their content (#4976 - editble combos).
+ if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT)
or (IARole==oleacc.ROLE_SYSTEM_COMBOBOX and controlTypes.STATE_EDITABLE in
self.states):
return ""
else:
return super(MSHTML,self).value

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 630b4e3..b1e247e 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -17,6 +17,7 @@

== Bug Fixes ==
- Character descriptions are now handled correctly for conjunct characters in
certain Indian languages. (#4582)
+-In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)


== Changes for Developers ==


https://bitbucket.org/nvdaaddonteam/nvda/commits/434c0a5d6f7c/
Changeset: 434c0a5d6f7c
Branch: None
User: mdcurran
Date: 2015-03-31 06:05:48+00:00
Summary: Merge branch 'master' into next

Affected #: 1 file

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index be1ab25..b1e247e 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -17,10 +17,12 @@

== Bug Fixes ==
- Character descriptions are now handled correctly for conjunct characters in
certain Indian languages. (#4582)
+-In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)


== Changes for Developers ==
- brailleInput.handler.sendChars(mychar) will no longer filter out a character
if it is equal to the previous character, by ensuring that the key sent is
correctly released.
+- scripts for changing touch modes will now honor new labeles added to
touchHandler.touchModeLabels. (#4699)


= 2015.1 =


https://bitbucket.org/nvdaaddonteam/nvda/commits/da5042c91d79/
Changeset: da5042c91d79
Branch: None
User: mdcurran
Date: 2015-03-31 06:07:58+00:00
Summary: Merge branch 'master' into next

Affected #: 60 files

diff --git a/source/locale/an/symbols.dic b/source/locale/an/symbols.dic
index b539f0c..a02cd93 100644
--- a/source/locale/an/symbols.dic
+++ b/source/locale/an/symbols.dic
@@ -122,6 +122,9 @@ _ guión baixo most
‎ marca de cucha a dreita char
‏ marca de dreita a cucha char
■ Barra vertical tallada some
+▪ vinyeta negra some
+◾ quadro negro some
+◦ vinyeta blanca some
← flecha enta la cucha some
➔ flecha enta la dreita some
§ Sección most

diff --git a/source/locale/fa/characterDescriptions.dic
b/source/locale/fa/characterDescriptions.dic
index 3fb66c9..cafb22e 100644
--- a/source/locale/fa/characterDescriptions.dic
+++ b/source/locale/fa/characterDescriptions.dic
@@ -52,7 +52,7 @@ z Zulu
خ خروس
د دختر
ذ ذکر
-ر روزنامه
+ر روزنامه
ز زنبور
ژ ژاله
س سیب

diff --git a/source/locale/fa/symbols.dic b/source/locale/fa/symbols.dic
index ce58007..4228a6d 100644
--- a/source/locale/fa/symbols.dic
+++ b/source/locale/fa/symbols.dic
@@ -1,8 +1,15 @@
#locale/fa/symbols.dic
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (c) 2014 NVDA Farsi contributors
+#Copyright (c) 2015 NVDA Persian (Farsi) contributors
#This file is covered by the GNU General Public License.

+complexSymbols:
+# identifier regexp
+# Sentence endings.
+؟ sentence ending (?<=[^\s؟])\؟(?=[\"'”’)\s]|$)
+# Phrase endings.
+؛ phrase ending (?<=[^\s؛])؛(?=\s|$)
+
symbols:
# identifier replacement[[ level][ preserve]][ # display name]

@@ -10,11 +17,11 @@ symbols:
. sentence ending نقطه
! sentence ending علامتِ تعجب
? sentence ending Question
-؟ sentence ending علامتِ سؤال
-؛ phrase ending نقطه ویرگول
+؟ sentence ending علامتِ سؤال all always
+؛ phrase ending نقطه ویرگول all always
; phrase ending semicolon
: phrase ending دو‌نقطه
-decimal point نقطه - norep
+decimal point نقطه none never
in-word ' tick
negative number منفی

@@ -33,7 +40,7 @@ negative number منفی
\# شماره
$ دلار
£ پوند
-€ يورو
+€ یورو
% درصد
& And
' tick
@@ -74,9 +81,10 @@ _ زیرخط
— em dash
● دایره
¨ diaeresis
-■ مربعِ سیاه char
-➔ فِلِشِ راست‌نمای سر‌پهن char
-→ ‌فِلِشِ راست‌نما char
+■ مربعِ سیاه
+➔ فِلِشِ راست‌نمای سر‌پهن
+→ ‌فِلِشِ راست‌نما
+← ‌فِلِشِ چپ‌نما
§ بخش
° درجه
¹ ۱ بالانویس
@@ -87,20 +95,21 @@ _ زیرخط
÷ تقسیم‌بر
✓ تیک
✔ تیکِ ضخیم
-٬ هزار‌گان
-٫ ممیز none
-٪ درصد some

# Persian symbols
، ویرگول all always
؟ علامتِ سؤال all always
؛ نقطه‌ویرگول all always
-ـ کشیده char always
« گیومه باز most always
» گیومه بسته most always
-ٔ همزه‌ی بالا char always
+ـ کشیده char norep
+ٔ همزه‌ی بالا char norep
+٬ هزار‌گان char never
+٫ ممیز none never
+٪ درصد none never
+﷼ ریال none never

-# Unicode Formating symbols
+# Unicode formatting symbols
‎ نشانه چپ به راست char never
‏ نشانه راست به چپ char never
‍ نیم‌اتصال char never

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/daf65862f53f/
Changeset: daf65862f53f
Branch: None
User: mdcurran
Date: 2015-04-02 04:35:55+00:00
Summary: Windows command consoles: support wm_char for announcing typed
characters if it is available, and disable our older character handling code in
win7 and above (wm_char is better). Also don't allow announcing of characters
if the console's input echo mode is not on (e.g. password entry).

Affected #: 4 files

diff --git a/source/NVDAHelper.py b/source/NVDAHelper.py
index 90474fd..aa31895 100755
--- a/source/NVDAHelper.py
+++ b/source/NVDAHelper.py
@@ -354,8 +354,7 @@ def
nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString):
@WINFUNCTYPE(c_long,c_long,c_wchar)
def nvdaControllerInternal_typedCharacterNotify(threadID,ch):
focus=api.getFocusObject()
- if focus.windowClassName!="ConsoleWindowClass":
- eventHandler.queueEvent("typedCharacter",focus,ch=ch)
+ eventHandler.queueEvent("typedCharacter",focus,ch=ch)
return 0

@WINFUNCTYPE(c_long, c_int, c_int)

diff --git a/source/NVDAObjects/window/winConsole.py
b/source/NVDAObjects/window/winConsole.py
index 86f9de8..a2ef11c 100644
--- a/source/NVDAObjects/window/winConsole.py
+++ b/source/NVDAObjects/window/winConsole.py
@@ -47,6 +47,11 @@ class WinConsole(Terminal,
EditableTextWithoutAutoSelectDetection, Window):
def _getTextLines(self):
return winConsoleHandler.getConsoleVisibleLines()

+ def event_typedCharacter(self,ch):
+ if winConsoleHandler.isInputEchoEnabled():
+ super(WinConsole,self).event_typedCharacter(ch)
+
+
def script_caret_backspaceCharacter(self, gesture):
super(WinConsole, self).script_caret_backspaceCharacter(gesture)
# #2586: We use console update events for typed characters,

diff --git a/source/winConsoleHandler.py b/source/winConsoleHandler.py
index 764da03..10b2bb6 100755
--- a/source/winConsoleHandler.py
+++ b/source/winConsoleHandler.py
@@ -4,6 +4,7 @@
#See the file COPYING for more details.
#Copyright (C) 2009-2010 Michael Curran <mick@xxxxxxxxxx>, James Teh
<jamie@xxxxxxxxxxx>

+import sys
import wx
import winUser
import winKernel
@@ -21,6 +22,7 @@ CHECK_DEAD_INTERVAL = 100

consoleObject=None #:The console window that is currently in the foreground.
consoleWinEventHookHandles=[] #:a list of currently registered console win
events.
+consoleInputHandle=None
consoleOutputHandle=None
checkDeadTimer=None

@@ -54,7 +56,7 @@ def _consoleCtrlHandler(event):
return False

def connectConsole(obj):
- global consoleObject, consoleOutputHandle, checkDeadTimer
+ global consoleObject, consoleOutputHandle, consoleInputHandle,
checkDeadTimer
#Get the process ID of the console this NVDAObject is fore
processID,threadID=winUser.getWindowThreadProcessID(obj.windowHandle)
#Attach NVDA to this console so we can access its text etc
@@ -65,6 +67,7 @@ def connectConsole(obj):
return False
wincon.SetConsoleCtrlHandler(_consoleCtrlHandler,True)

consoleOutputHandle=winKernel.CreateFile(u"CONOUT$",winKernel.GENERIC_READ|winKernel.GENERIC_WRITE,winKernel.FILE_SHARE_READ|winKernel.FILE_SHARE_WRITE,None,winKernel.OPEN_EXISTING,0,None)

+
consoleInputHandle=winKernel.CreateFile(u"CONIN$",winKernel.GENERIC_READ|winKernel.GENERIC_WRITE,winKernel.FILE_SHARE_READ|winKernel.FILE_SHARE_WRITE,None,winKernel.OPEN_EXISTING,0,None)

#Register this callback with all the win events we need, storing the
given handles for removal later
for eventID in
(winUser.EVENT_CONSOLE_CARET,winUser.EVENT_CONSOLE_UPDATE_REGION,winUser.EVENT_CONSOLE_UPDATE_SIMPLE,winUser.EVENT_CONSOLE_UPDATE_SCROLL,winUser.EVENT_CONSOLE_LAYOUT):

handle=winUser.setWinEventHook(eventID,eventID,0,consoleWinEventHook,0,0,0)
@@ -77,7 +80,7 @@ def connectConsole(obj):
return True

def disconnectConsole():
- global consoleObject, consoleOutputHandle, consoleWinEventHookHandles,
checkDeadTimer
+ global consoleObject, consoleOutputHandle, consoleInputHandle,
consoleWinEventHookHandles, checkDeadTimer
if not consoleObject:
log.debugWarning("console was not connected")
return False
@@ -90,6 +93,8 @@ def disconnectConsole():
consoleObject.stopMonitoring()
winKernel.closeHandle(consoleOutputHandle)
consoleOutputHandle=None
+ winKernel.closeHandle(consoleInputHandle)
+ consoleInputHandle=None
consoleObject=None
try:
wincon.SetConsoleCtrlHandler(_consoleCtrlHandler,False)
@@ -137,6 +142,9 @@ def
consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestam
# This avoids an extra core cycle.
consoleObject.event_textChange()
if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE:
+ ver=sys.getwindowsversion()
+ if ver.major>6 or (ver.major==6 and ver.minor>1):
+ return # #513: Win 7 and above receive wm_char for
characters.
x=winUser.LOWORD(objectID)
y=winUser.HIWORD(objectID)

consoleScreenBufferInfo=wincon.GetConsoleScreenBufferInfo(consoleOutputHandle)
@@ -150,6 +158,9 @@ def terminate():
if consoleObject:
disconnectConsole()

+def isInputEchoEnabled():
+ return
wincon.getConsoleMode(consoleInputHandle)&wincon.ENABLE_ECHO_INPUT
+
class WinConsoleTextInfo(textInfos.offsets.OffsetsTextInfo):

_cache_consoleScreenBufferInfo=True

diff --git a/source/wincon.py b/source/wincon.py
index 3eaa94a..b7aff4f 100755
--- a/source/wincon.py
+++ b/source/wincon.py
@@ -43,6 +43,8 @@ CONSOLE_SELECTION_NOT_EMPTY=0x2
CONSOLE_MOUSE_SELECTION=0X4
CONSOLE_MOUSE_DOWN=0x8

+ENABLE_ECHO_INPUT=0x4
+
def GetConsoleSelectionInfo():
info=CONSOLE_SELECTION_INFO()
if windll.kernel32.GetConsoleSelectionInfo(byref(info))==0:
@@ -89,3 +91,10 @@ def GetConsoleProcessList(maxProcessCount):
def SetConsoleCtrlHandler(handler,add):
if windll.kernel32.SetConsoleCtrlHandler(handler,add)==0:
raise WinError()
+
+def getConsoleMode(handle):
+ val=DWORD()
+ windll.kernel32.GetConsoleMode(handle,byref(val))
+ return val.value
+
+
\ No newline at end of file


https://bitbucket.org/nvdaaddonteam/nvda/commits/a0d15ab7f1d1/
Changeset: a0d15ab7f1d1
Branch: None
User: mdcurran
Date: 2015-04-02 04:38:48+00:00
Summary: Merge branch 't513' into next. Incubates #513

Affected #: 4 files

diff --git a/source/NVDAHelper.py b/source/NVDAHelper.py
index 90474fd..aa31895 100755
--- a/source/NVDAHelper.py
+++ b/source/NVDAHelper.py
@@ -354,8 +354,7 @@ def
nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString):
@WINFUNCTYPE(c_long,c_long,c_wchar)
def nvdaControllerInternal_typedCharacterNotify(threadID,ch):
focus=api.getFocusObject()
- if focus.windowClassName!="ConsoleWindowClass":
- eventHandler.queueEvent("typedCharacter",focus,ch=ch)
+ eventHandler.queueEvent("typedCharacter",focus,ch=ch)
return 0

@WINFUNCTYPE(c_long, c_int, c_int)

diff --git a/source/NVDAObjects/window/winConsole.py
b/source/NVDAObjects/window/winConsole.py
index 86f9de8..a2ef11c 100644
--- a/source/NVDAObjects/window/winConsole.py
+++ b/source/NVDAObjects/window/winConsole.py
@@ -47,6 +47,11 @@ class WinConsole(Terminal,
EditableTextWithoutAutoSelectDetection, Window):
def _getTextLines(self):
return winConsoleHandler.getConsoleVisibleLines()

+ def event_typedCharacter(self,ch):
+ if winConsoleHandler.isInputEchoEnabled():
+ super(WinConsole,self).event_typedCharacter(ch)
+
+
def script_caret_backspaceCharacter(self, gesture):
super(WinConsole, self).script_caret_backspaceCharacter(gesture)
# #2586: We use console update events for typed characters,

diff --git a/source/winConsoleHandler.py b/source/winConsoleHandler.py
index 764da03..10b2bb6 100755
--- a/source/winConsoleHandler.py
+++ b/source/winConsoleHandler.py
@@ -4,6 +4,7 @@
#See the file COPYING for more details.
#Copyright (C) 2009-2010 Michael Curran <mick@xxxxxxxxxx>, James Teh
<jamie@xxxxxxxxxxx>

+import sys
import wx
import winUser
import winKernel
@@ -21,6 +22,7 @@ CHECK_DEAD_INTERVAL = 100

consoleObject=None #:The console window that is currently in the foreground.
consoleWinEventHookHandles=[] #:a list of currently registered console win
events.
+consoleInputHandle=None
consoleOutputHandle=None
checkDeadTimer=None

@@ -54,7 +56,7 @@ def _consoleCtrlHandler(event):
return False

def connectConsole(obj):
- global consoleObject, consoleOutputHandle, checkDeadTimer
+ global consoleObject, consoleOutputHandle, consoleInputHandle,
checkDeadTimer
#Get the process ID of the console this NVDAObject is fore
processID,threadID=winUser.getWindowThreadProcessID(obj.windowHandle)
#Attach NVDA to this console so we can access its text etc
@@ -65,6 +67,7 @@ def connectConsole(obj):
return False
wincon.SetConsoleCtrlHandler(_consoleCtrlHandler,True)

consoleOutputHandle=winKernel.CreateFile(u"CONOUT$",winKernel.GENERIC_READ|winKernel.GENERIC_WRITE,winKernel.FILE_SHARE_READ|winKernel.FILE_SHARE_WRITE,None,winKernel.OPEN_EXISTING,0,None)

+
consoleInputHandle=winKernel.CreateFile(u"CONIN$",winKernel.GENERIC_READ|winKernel.GENERIC_WRITE,winKernel.FILE_SHARE_READ|winKernel.FILE_SHARE_WRITE,None,winKernel.OPEN_EXISTING,0,None)

#Register this callback with all the win events we need, storing the
given handles for removal later
for eventID in
(winUser.EVENT_CONSOLE_CARET,winUser.EVENT_CONSOLE_UPDATE_REGION,winUser.EVENT_CONSOLE_UPDATE_SIMPLE,winUser.EVENT_CONSOLE_UPDATE_SCROLL,winUser.EVENT_CONSOLE_LAYOUT):

handle=winUser.setWinEventHook(eventID,eventID,0,consoleWinEventHook,0,0,0)
@@ -77,7 +80,7 @@ def connectConsole(obj):
return True

def disconnectConsole():
- global consoleObject, consoleOutputHandle, consoleWinEventHookHandles,
checkDeadTimer
+ global consoleObject, consoleOutputHandle, consoleInputHandle,
consoleWinEventHookHandles, checkDeadTimer
if not consoleObject:
log.debugWarning("console was not connected")
return False
@@ -90,6 +93,8 @@ def disconnectConsole():
consoleObject.stopMonitoring()
winKernel.closeHandle(consoleOutputHandle)
consoleOutputHandle=None
+ winKernel.closeHandle(consoleInputHandle)
+ consoleInputHandle=None
consoleObject=None
try:
wincon.SetConsoleCtrlHandler(_consoleCtrlHandler,False)
@@ -137,6 +142,9 @@ def
consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestam
# This avoids an extra core cycle.
consoleObject.event_textChange()
if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE:
+ ver=sys.getwindowsversion()
+ if ver.major>6 or (ver.major==6 and ver.minor>1):
+ return # #513: Win 7 and above receive wm_char for
characters.
x=winUser.LOWORD(objectID)
y=winUser.HIWORD(objectID)

consoleScreenBufferInfo=wincon.GetConsoleScreenBufferInfo(consoleOutputHandle)
@@ -150,6 +158,9 @@ def terminate():
if consoleObject:
disconnectConsole()

+def isInputEchoEnabled():
+ return
wincon.getConsoleMode(consoleInputHandle)&wincon.ENABLE_ECHO_INPUT
+
class WinConsoleTextInfo(textInfos.offsets.OffsetsTextInfo):

_cache_consoleScreenBufferInfo=True

diff --git a/source/wincon.py b/source/wincon.py
index 3eaa94a..b7aff4f 100755
--- a/source/wincon.py
+++ b/source/wincon.py
@@ -43,6 +43,8 @@ CONSOLE_SELECTION_NOT_EMPTY=0x2
CONSOLE_MOUSE_SELECTION=0X4
CONSOLE_MOUSE_DOWN=0x8

+ENABLE_ECHO_INPUT=0x4
+
def GetConsoleSelectionInfo():
info=CONSOLE_SELECTION_INFO()
if windll.kernel32.GetConsoleSelectionInfo(byref(info))==0:
@@ -89,3 +91,10 @@ def GetConsoleProcessList(maxProcessCount):
def SetConsoleCtrlHandler(handler,add):
if windll.kernel32.SetConsoleCtrlHandler(handler,add)==0:
raise WinError()
+
+def getConsoleMode(handle):
+ val=DWORD()
+ windll.kernel32.GetConsoleMode(handle,byref(val))
+ return val.value
+
+
\ No newline at end of file


https://bitbucket.org/nvdaaddonteam/nvda/commits/115be898d170/
Changeset: 115be898d170
Branch: None
User: mdcurran
Date: 2015-04-06 03:23:37+00:00
Summary: winConsoleHandler: disable the older typed character announcement
code ror Windows consoles in Windows 7 and above. Previously it was
accidentially only disabling for Win 8 and above.

Affected #: 1 file

diff --git a/source/winConsoleHandler.py b/source/winConsoleHandler.py
index 10b2bb6..88ee4b6 100755
--- a/source/winConsoleHandler.py
+++ b/source/winConsoleHandler.py
@@ -143,7 +143,7 @@ def
consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestam
consoleObject.event_textChange()
if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE:
ver=sys.getwindowsversion()
- if ver.major>6 or (ver.major==6 and ver.minor>1):
+ if ver.major>6 or (ver.major==6 and ver.minor>=1):
return # #513: Win 7 and above receive wm_char for
characters.
x=winUser.LOWORD(objectID)
y=winUser.HIWORD(objectID)


https://bitbucket.org/nvdaaddonteam/nvda/commits/091a0e4457b1/
Changeset: 091a0e4457b1
Branch: None
User: mdcurran
Date: 2015-04-06 03:24:05+00:00
Summary: Merge branch 't513' into next. Incubates #513

Affected #: 1 file

diff --git a/source/winConsoleHandler.py b/source/winConsoleHandler.py
index 10b2bb6..88ee4b6 100755
--- a/source/winConsoleHandler.py
+++ b/source/winConsoleHandler.py
@@ -143,7 +143,7 @@ def
consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestam
consoleObject.event_textChange()
if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE:
ver=sys.getwindowsversion()
- if ver.major>6 or (ver.major==6 and ver.minor>1):
+ if ver.major>6 or (ver.major==6 and ver.minor>=1):
return # #513: Win 7 and above receive wm_char for
characters.
x=winUser.LOWORD(objectID)
y=winUser.HIWORD(objectID)


https://bitbucket.org/nvdaaddonteam/nvda/commits/de9ec0c11442/
Changeset: de9ec0c11442
Branch: None
User: dkager
Date: 2015-04-08 05:56:16+00:00
Summary: Update Danish braille table references to point to the new tables
in liblouis 2.6.0.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index e845eaa..fb24150 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -45,10 +45,16 @@ TABLES = (
("cz-cz-g1.utb", _("Czech grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("da-dk-g1.utb", _("Danish grade 1"), False),
+ ("da-dk-g16.utb", _("Danish 6 dot grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("da-dk-g2.ctb", _("Danish grade 2"), False),
+ ("da-dk-g18.utb", _("Danish 8 dot grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("da-dk-g26.ctb", _("Danish 6 dot grade 2"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("da-dk-g28.ctb", _("Danish 8 dot grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("de-de-comp8.ctb", _("German 8 dot computer braille"), True),


https://bitbucket.org/nvdaaddonteam/nvda/commits/52aa9eeb9372/
Changeset: 52aa9eeb9372
Branch: None
User: jteh
Date: 2015-04-08 05:59:16+00:00
Summary: Merge branch 't4986' into next

Incubates #4986.

Affected #: 1 file

diff --git a/source/braille.py b/source/braille.py
index a4ac5ae..928e77a 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -51,10 +51,16 @@ TABLES = (
("cz-cz-g1.utb", _("Czech grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("da-dk-g1.utb", _("Danish grade 1"), False),
+ ("da-dk-g16.utb", _("Danish 6 dot grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("da-dk-g2.ctb", _("Danish grade 2"), False),
+ ("da-dk-g18.utb", _("Danish 8 dot grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("da-dk-g26.ctb", _("Danish 6 dot grade 2"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("da-dk-g28.ctb", _("Danish 8 dot grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("de-de-comp8.ctb", _("German 8 dot computer braille"), True),


https://bitbucket.org/nvdaaddonteam/nvda/commits/ab6e311a32ef/
Changeset: ab6e311a32ef
Branch: None
User: jteh
Date: 2015-04-08 07:19:53+00:00
Summary: Merge branch 't4777' into next

Incubates #4777.

Affected #: 17 files

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

diff --git a/readme.txt b/readme.txt
index f05e408..078688f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -27,7 +27,7 @@ The following dependencies are included in Git submodules:
* eSpeak, version 1.48.04: http://espeak.sourceforge.net/
* IAccessible2, version 1.3:
http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2
* ConfigObj, version 4.6.0: http://www.voidspace.org.uk/python/configobj.html
-* liblouis, version 2.6.0: http://www.liblouis.org/
+* liblouis, version 2.6.2: 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

diff --git a/source/braille.py b/source/braille.py
index 928e77a..d49b588 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -111,19 +111,19 @@ TABLES = (
("fi-fi-8dot.ctb", _("Finnish 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("fr-ca-g1.utb", _("French (Canada) grade 1"), False),
+ ("fr-bfu-comp6.utb", _("French (unified) 6 dot computer braille"),
False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("Fr-Ca-g2.ctb", _("French (Canada) grade 2"), False),
+ ("fr-bfu-comp8.utb", _("French (unified) 8 dot computer braille"),
True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("fr-bfu-comp6.utb", _("French (unified) 6 dot computer braille"),
False),
+ ("fr-bfu-g2.ctb", _("French (unified) Grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("fr-bfu-comp8.utb", _("French (unified) 8 dot computer braille"),
True),
+ ("fr-ca-g1.utb", _("French (Canada) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("fr-bfu-g2.ctb", _("French (unified) Grade 2"), False),
+ ("Fr-Ca-g2.ctb", _("French (Canada) grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("gu-in-g1.utb", _("Gujarati grade 1"), False),
@@ -180,10 +180,10 @@ TABLES = (
("mr-in-g1.utb", _("Marathi grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("nl-be-g1.utb", _("Dutch (Belgium) grade 1"), False),
+ ("nl-BE-g1.ctb", _("Dutch (Belgium) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("Nl-Nl-g1.utb", _("Dutch (netherlands) grade 1"), False),
+ ("nl-NL-g1.ctb", _("Dutch (Netherlands) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("no-no.ctb", _("Norwegian 8 dot computer braille"), True),
@@ -234,7 +234,7 @@ TABLES = (
("Se-Se-g1.utb", _("Swedish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
- ("sk-sk-g1.utb", _("Slovak"), False),
+ ("sk-sk-g1.utb", _("Slovak grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("sl-si-g1.utb", _("Slovene grade 1"), False),

diff --git a/source/locale/ar/LC_MESSAGES/nvda.po
b/source/locale/ar/LC_MESSAGES/nvda.po
index 8d24e88..733e98a 100644
--- a/source/locale/ar/LC_MESSAGES/nvda.po
+++ b/source/locale/ar/LC_MESSAGES/nvda.po
@@ -4,15 +4,15 @@ msgid ""
msgstr ""
"Project-Id-Version: master-10703,53a09c4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-03 19:12+1000\n"
-"PO-Revision-Date: 2015-01-29 18:43+0200\n"
+"POT-Creation-Date: 2015-03-26 19:04-0700\n"
+"PO-Revision-Date: 2015-03-31 12:28+0200\n"
"Last-Translator: \n"
"Language-Team: AR <arabictranslationteam@xxxxxxxxxxxxxxxx>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.7.4\n"
+"X-Generator: Poedit 1.7.5\n"

#. Translators: Message to indicate User Account Control (UAC) or other secure
desktop screen is active.
msgid "Secure Desktop"
@@ -136,6 +136,16 @@ msgstr "فارسي بدون اختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Assamese grade 1"
+msgstr "إسامية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Bengali grade 1"
+msgstr "بنغالية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Bulgarian 8 dot computer braille"
msgstr "بلغاري برايل الحاسوب 8 نقاط"

@@ -270,6 +280,11 @@ msgstr "فرنسي موحد باختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Gujarati grade 1"
+msgstr "غوجراتية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Greek (Greece) grade 1"
msgstr "يوناني بدون اختصارات"

@@ -315,6 +330,11 @@ msgstr "إيطالي حاسوب برايل 8 نقاط"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kannada grade 1"
+msgstr "كانادا بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Korean grade 1"
msgstr "كوري بدون اختصارات"

@@ -325,11 +345,31 @@ msgstr "كوري باختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kashmiri grade 1"
+msgstr "كاشميرية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Latvian grade 1"
msgstr "لاتفي بدون اختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Malayalam grade 1"
+msgstr "مالايالامية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Manipuri grade 1"
+msgstr "مانيبرى بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Marathi grade 1"
+msgstr "مهاراتية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Dutch (Belgium) grade 1"
msgstr "هولاندي بلجيكي بدون اختصارات"

@@ -365,6 +405,16 @@ msgstr "نرويجي المستوى الثالث"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Nepali grade 1"
+msgstr "نيبالية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Oriya grade 1"
+msgstr "إوريا بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Polish grade 1"
msgstr "بولاندي بدون اختصارات"

@@ -385,6 +435,11 @@ msgstr "برتغالي بدون اختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Punjabi grade 1"
+msgstr "بنجابية بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Russian braille for computer code"
msgstr "برايل روسي لشفرة الحاسوب"

@@ -395,6 +450,11 @@ msgstr "روسي بدون اختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Sanskrit grade 1"
+msgstr "سنسكريتي بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Swedish grade 1"
msgstr "سويدي بدون اختصارات"

@@ -420,6 +480,11 @@ msgstr "تاميل بدون اختصارات"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Telegu grade 1"
+msgstr "تيلوجو بدون اختصارات"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Turkish grade 1"
msgstr "تركي بدون اختصارات"

@@ -1948,8 +2013,8 @@ msgstr "غير محدد"

#. Translators: A message informing the user that there are errors in the
configuration file.
msgid ""
-"Your configuration file contains errors. Your configuration has been reset "
-"to factory defaults.\n"
+"Your configuration file contains errors. Your configuration has been reset to
"
+"factory defaults.\n"
"More details about the errors can be found in the log file."
msgstr ""
"يوجد خلل بملف الإعدادات الخاص بك. لقد تم العودة بالبرنامج إلى الإعدادات "
@@ -2004,8 +2069,8 @@ msgstr "البحث عن نص بدأً من الموضع الحالي للمؤش

#. Translators: Input help message for find next command.
msgid ""
-"find the next occurrence of the previously entered text string from the "
-"current cursor's position"
+"find the next occurrence of the previously entered text string from the
current "
+"cursor's position"
msgstr "البحث عن الموضع التالي للنص المُدخل سلفا بدأً من الموضع الراهن للمؤشر"

#. Translators: Input help message for find previous command.
@@ -2085,8 +2150,8 @@ msgid ""
"Turns input help on or off. When on, any input such as pressing a key on the "
"keyboard will tell you what script is associated with that input, if any."
msgstr ""
-"تشغيل وتعطيل المساعدة التفاعليةففي وضع التشغيل ستخبرك بوظيفة أي مدخل كالضغط "
-"على أحد أزرار لوحة المفاتيح"
+"تشغيل وتعطيل المساعدة التفاعليةففي وضع التشغيل ستخبرك بوظيفة أي مدخل كالضغط
على "
+"أحد أزرار لوحة المفاتيح"

#. Translators: This is presented when sleep mode is deactivated, NVDA will
continue working as expected.
msgid "Sleep mode off"
@@ -2102,11 +2167,10 @@ msgstr "الانتقال بين تشغيل وتعطيل وضع الصمت للت

#. Translators: Input help mode message for report current line command.
msgid ""
-"Reports the current line under the application cursor. Pressing this key "
-"twice will spell the current line"
+"Reports the current line under the application cursor. Pressing this key
twice "
+"will spell the current line"
msgstr ""
-"قراءة السطر الواقع تحت مؤشر التطبيق. بالضغط على هذا المفتاح مرتين يقوم "
-"بتهجئته"
+"قراءة السطر الواقع تحت مؤشر التطبيق. بالضغط على هذا المفتاح مرتين يقوم
بتهجئته"

#. Translators: Reported when left mouse button is clicked.
msgid "left click"
@@ -2150,14 +2214,14 @@ msgstr "تثبيت أو تحرير زر الفأرة الأيمن"

#. Translators: Input help mode message for report current selection command.
msgid ""
-"Announces the current selection in edit controls and documents. If there is "
-"no selection it says so."
+"Announces the current selection in edit controls and documents. If there is
no "
+"selection it says so."
msgstr "قراءة النص المحدد بكائنات التحرير والمستندات."

#. Translators: Input help mode message for report date and time command.
msgid ""
-"If pressed once, reports the current time. If pressed twice, reports the "
-"current date"
+"If pressed once, reports the current time. If pressed twice, reports the
current "
+"date"
msgstr "بالنقر عليه مرة واحدة, يُعْلِمُك بالوقت. ومرتين, يُعْلِمُك بالتاريخ"

#. Translators: Reported when there are no settings to configure in synth
settings ring (example: when there is no setting for language).
@@ -2214,8 +2278,7 @@ msgstr "نُطْق مفاتيح التحكم تشغيل"

#. Translators: Input help mode message for toggle speak command keys command.
msgid ""
-"Toggles on and off the speaking of typed keys, that are not specifically "
-"characters"
+"Toggles on and off the speaking of typed keys, that are not specifically
characters"
msgstr "تشغيل وتعطيل نُطْق كافة مفاتيح التحكم باستثناء الحروف"

#. Translators: Reported when the user cycles through speech symbol levels
@@ -2226,11 +2289,9 @@ msgid "symbol level %s"
msgstr "مستوى قراءة الرموز %s"

#. Translators: Input help mode message for cycle speech symbol level command.
-msgid ""
-"Cycles through speech symbol levels which determine what symbols are spoken"
+msgid "Cycles through speech symbol levels which determine what symbols are
spoken"
msgstr ""
-"التنقل بين مستويات نطق الرموز لتحديد كمية الرموز أو علامات الترقيم التي سيتم "
-"نطقها"
+"التنقل بين مستويات نطق الرموز لتحديد كمية الرموز أو علامات الترقيم التي سيتم
نطقها"

#. Translators: Reported when the object has no location for the mouse to move
to it.
msgid "object has no location"
@@ -2246,8 +2307,8 @@ msgstr "تحريك مؤشر NVDA إلى مؤشر الفأرة"

#. Translators: Input help mode message for move navigator object to mouse
command.
msgid ""
-"Sets the navigator object to the current object under the mouse pointer and "
-"speaks it"
+"Sets the navigator object to the current object under the mouse pointer and
speaks "
+"it"
msgstr "نقل مؤشر NVDA إلى الكائن الواقع تحت مؤشر الفأرة وقراءته"

#. Translators: reported when there are no other available review modes for
this object
@@ -2256,11 +2317,11 @@ msgstr "لا يوجد نمط استعراض تالي"

#. Translators: Script help message for next review mode command.
msgid ""
-"Switches to the next review mode (e.g. object, document or screen) and "
-"positions the review position at the point of the navigator object"
+"Switches to the next review mode (e.g. object, document or screen) and
positions "
+"the review position at the point of the navigator object"
msgstr ""
-"ينتقل إلى نمط الاستعراض التالي (على سبيل المثال نمط استعراض الكائن أو "
-"المستند أو الشاشة) ويضع مؤشر الاستعراض عند مؤشر NVDA"
+"ينتقل إلى نمط الاستعراض التالي (على سبيل المثال نمط استعراض الكائن أو المستند
أو "
+"الشاشة) ويضع مؤشر الاستعراض عند مؤشر NVDA"

#. Translators: reported when there are no other available review modes for
this object
msgid "No previous review mode"
@@ -2271,8 +2332,8 @@ msgid ""
"Switches to the previous review mode (e.g. object, document or screen) and "
"positions the review position at the point of the navigator object"
msgstr ""
-"ينتقل إلى نمط الاستعراض السابق (على سبيل المثال نمط استعراض الكائن أو "
-"المستند أو الشاشة) ويضع مؤشر الاستعراض عند مؤشر NVDA"
+"ينتقل إلى نمط الاستعراض السابق (على سبيل المثال نمط استعراض الكائن أو المستند
أو "
+"الشاشة) ويضع مؤشر الاستعراض عند مؤشر NVDA"

#. Translators: Reported when the user tries to perform a command related to
the navigator object
#. but there is no current navigator object.
@@ -2286,12 +2347,11 @@ msgstr "نَسخ %s إلى الحافظة"

#. Translators: Input help mode message for report current navigator object
command.
msgid ""
-"Reports the current navigator object. Pressing twice spells this information,"
-"and pressing three times Copies name and value of this object to the "
-"clipboard"
+"Reports the current navigator object. Pressing twice spells this
information,and "
+"pressing three times Copies name and value of this object to the clipboard"
msgstr ""
-"الإعلان عن الكائن الحالي. بالضغط عليه مرتين سيقوم بتهجئته وبالضغط عليه ثلاث "
-"مرات سيقوم بنسخ اسم وقيمة الكائن إلى الحافظة"
+"الإعلان عن الكائن الحالي. بالضغط عليه مرتين سيقوم بتهجئته وبالضغط عليه ثلاث
مرات "
+"سيقوم بنسخ اسم وقيمة الكائن إلى الحافظة"

#. Translators: message when there is no location information for the review
cursor
msgid "No location information"
@@ -2299,11 +2359,11 @@ msgstr "لا توجد معلومات عن موقع الكائن"

#. Translators: Description for report review cursor location command.
msgid ""
-"Reports information about the location of the text or object at the review "
-"cursor. Pressing twice may provide further detail."
+"Reports information about the location of the text or object at the review
cursor. "
+"Pressing twice may provide further detail."
msgstr ""
-"يعلن عن موقع النص أو الكائن الواقع تحت مؤشر الاستعراض. بالضغط عليه مرتين "
-"ربما يزودك بمزيد من المعلومات."
+"يعلن عن موقع النص أو الكائن الواقع تحت مؤشر الاستعراض. بالضغط عليه مرتين ربما
"
+"يزودك بمزيد من المعلومات."

#. Translators: Reported when attempting to move the navigator object to focus.
msgid "move to focus"
@@ -2314,8 +2374,8 @@ msgid ""
"Sets the navigator object to the current focus, and the review cursor to the "
"position of the caret inside it, if possible."
msgstr ""
-"وضع مؤشر NVDA عند مؤشر النظام ووضع مؤشر الاستعراض عند مؤشر التحرير بداخله "
-"إذا كان ذلك ممكن"
+"وضع مؤشر NVDA عند مؤشر النظام ووضع مؤشر الاستعراض عند مؤشر التحرير بداخله إذا
كان "
+"ذلك ممكن"

#. Translators: Reported when:
#. 1. There is no focusable object e.g. cannot use tab and shift tab to move
to controls.
@@ -2333,11 +2393,11 @@ msgstr "لا يوجد مؤشر تحرير"

#. Translators: Input help mode message for move focus to current navigator
object command.
msgid ""
-"Pressed once Sets the keyboard focus to the navigator object, pressed twice "
-"sets the system caret to the position of the review cursor"
+"Pressed once Sets the keyboard focus to the navigator object, pressed twice
sets "
+"the system caret to the position of the review cursor"
msgstr ""
-"بالضغط عليه مرة واحدة يقوم بتحريك مؤشر النظام إلى مؤشر NVDA وبالضغط عليه "
-"مرتين يضع مؤشر التحرير في موقع مؤشر الاستعراض"
+"بالضغط عليه مرة واحدة يقوم بتحريك مؤشر النظام إلى مؤشر NVDA وبالضغط عليه
مرتين يضع "
+"مؤشر التحرير في موقع مؤشر الاستعراض"

#. Translators: Reported when there is no containing (parent) object such as
when focused on desktop.
msgid "No containing object"
@@ -2381,8 +2441,8 @@ msgstr "لا يوجد فعل افتراضي"

#. Translators: Input help mode message for activate current object command.
msgid ""
-"Performs the default action on the current navigator object (example: "
-"presses it if it is a button)."
+"Performs the default action on the current navigator object (example: presses
it "
+"if it is a button)."
msgstr ""
"تنفيذ الفعل الافتراضي على مؤشر NVDA (على سبيل المثال: الضغط عليه إذا كان زر)."

@@ -2392,24 +2452,24 @@ msgstr "بداية"

#. Translators: Input help mode message for move review cursor to top line
command.
msgid ""
-"Moves the review cursor to the top line of the current navigator object and "
-"speaks it"
+"Moves the review cursor to the top line of the current navigator object and
speaks "
+"it"
msgstr "استعراض السطر الأول من الكائن الحالي وقراءته"

#. Translators: Input help mode message for move review cursor to previous
line command.
msgid ""
-"Moves the review cursor to the previous line of the current navigator object "
-"and speaks it"
+"Moves the review cursor to the previous line of the current navigator object
and "
+"speaks it"
msgstr "استعراض السطر السابق للكائن الحالي وقراءته"

#. Translators: Input help mode message for read current line under review
cursor command.
msgid ""
"Reports the line of the current navigator object where the review cursor is "
-"situated. If this key is pressed twice, the current line will be spelled. "
-"Pressing three times will spell the line using character descriptions."
+"situated. If this key is pressed twice, the current line will be spelled.
Pressing "
+"three times will spell the line using character descriptions."
msgstr ""
-"استعراض السطر الحالي. بالضغط على هذا المفتاح مرتين متعاقبتين يقوم بتهجئته "
-"وبالضغط عليه ثلاث مرات يقوم بتهجئة السطر تهجئة صوتية"
+"استعراض السطر الحالي. بالضغط على هذا المفتاح مرتين متعاقبتين يقوم بتهجئته
وبالضغط "
+"عليه ثلاث مرات يقوم بتهجئة السطر تهجئة صوتية"

#. Translators: a message reported when:
#. Review cursor is at the bottom line of the current navigator object.
@@ -2425,21 +2485,21 @@ msgstr "استعراض السطر التالي"

#. Translators: Input help mode message for move review cursor to bottom line
command.
msgid ""
-"Moves the review cursor to the bottom line of the current navigator object "
-"and speaks it"
+"Moves the review cursor to the bottom line of the current navigator object
and "
+"speaks it"
msgstr "استعراض السطر الأخير"

#. Translators: Input help mode message for move review cursor to previous
word command.
msgid ""
-"Moves the review cursor to the previous word of the current navigator object "
-"and speaks it"
+"Moves the review cursor to the previous word of the current navigator object
and "
+"speaks it"
msgstr "استعراض الكلمة السابقة"

#. Translators: Input help mode message for report current word under review
cursor command.
msgid ""
"Speaks the word of the current navigator object where the review cursor is "
-"situated. Pressing twice spells the word. Pressing three times spells the "
-"word using character descriptions"
+"situated. Pressing twice spells the word. Pressing three times spells the
word "
+"using character descriptions"
msgstr ""
"نطق الكلمة الحالية الواقعة تحت مؤشر الاستعراض. بالضغط على هذا المفتاح مرتين "
"متعاقبتين يقوم بتهجأتها وبالضغط عليه ثلاث مرات يقوم بتهجئة الكلمة تهجئة صوتية"
@@ -2455,39 +2515,39 @@ msgstr "يسار"

#. Translators: Input help mode message for move review cursor to start of
current line command.
msgid ""
-"Moves the review cursor to the first character of the line where it is "
-"situated in the current navigator object and speaks it"
+"Moves the review cursor to the first character of the line where it is
situated in "
+"the current navigator object and speaks it"
msgstr "استعراض أول حرف من السطر الحالي"

#. Translators: Input help mode message for move review cursor to previous
character command.
msgid ""
-"Moves the review cursor to the previous character of the current navigator "
-"object and speaks it"
+"Moves the review cursor to the previous character of the current navigator
object "
+"and speaks it"
msgstr "استعراض الحرف السابق"

#. Translators: Input help mode message for report current character under
review cursor command.
msgid ""
-"Reports the character of the current navigator object where the review "
-"cursor is situated. Pressing twice reports a description or example of that "
-"character. Pressing three times reports the numeric value of the character "
-"in decimal and hexadecimal"
+"Reports the character of the current navigator object where the review cursor
is "
+"situated. Pressing twice reports a description or example of that character. "
+"Pressing three times reports the numeric value of the character in decimal
and "
+"hexadecimal"
msgstr ""
-"نطق الحرف الحالي الواقع تحت مؤشر الاستعراض. بالضغط على هذا المفتاح مرتين "
-"يعطي مثال صوتي للحرف. وبالضغط عليه ثلاث مرات ينطق القيمة الرقمية له"
+"نطق الحرف الحالي الواقع تحت مؤشر الاستعراض. بالضغط على هذا المفتاح مرتين يعطي
مثال "
+"صوتي للحرف. وبالضغط عليه ثلاث مرات ينطق القيمة الرقمية له"

msgid "right"
msgstr "يمين"

#. Translators: Input help mode message for move review cursor to next
character command.
msgid ""
-"Moves the review cursor to the next character of the current navigator "
-"object and speaks it"
+"Moves the review cursor to the next character of the current navigator object
and "
+"speaks it"
msgstr "استعراض الحرف التالي"

#. Translators: Input help mode message for move review cursor to end of
current line command.
msgid ""
-"Moves the review cursor to the last character of the line where it is "
-"situated in the current navigator object and speaks it"
+"Moves the review cursor to the last character of the line where it is
situated in "
+"the current navigator object and speaks it"
msgstr "استعراض آخر حرف بالسطر"

#. Translators: A speech mode which disables speech output.
@@ -2504,9 +2564,9 @@ msgstr "نمط النطق كلام"

#. Translators: Input help mode message for toggle speech mode command.
msgid ""
-"Toggles between the speech modes of off, beep and talk. When set to off NVDA "
-"will not speak anything. If beeps then NVDA will simply beep each time it "
-"its supposed to speak something. If talk then NVDA wil just speak normally."
+"Toggles between the speech modes of off, beep and talk. When set to off NVDA
will "
+"not speak anything. If beeps then NVDA will simply beep each time it its
supposed "
+"to speak something. If talk then NVDA wil just speak normally."
msgstr "الانتقال بين أنظمة النطق من صفير, وكلام, وصَمْت"

#. Translators: Input help mode message for move to next document with focus
command, mostly used in web browsing to move from embedded object to the
webpage document.
@@ -2515,10 +2575,10 @@ msgstr "الرجوع إلى المستند الذي يحتوي على الكائ

#. Translators: Input help mode message for toggle focus and browse mode
command in web browsing and other situations.
msgid ""
-"Toggles between browse mode and focus mode. When in focus mode, keys will "
-"pass straight through to the application, allowing you to interact directly "
-"with a control. When in browse mode, you can navigate the document with the "
-"cursor, quick navigation keys, etc."
+"Toggles between browse mode and focus mode. When in focus mode, keys will
pass "
+"straight through to the application, allowing you to interact directly with a
"
+"control. When in browse mode, you can navigate the document with the cursor,
quick "
+"navigation keys, etc."
msgstr "الانتقال بين النمط التفاعلي ونمط التصفح "

#. Translators: Input help mode message for quit NVDA command.
@@ -2531,14 +2591,13 @@ msgstr "تفعيل واجهة البرنامج"

#. Translators: Input help mode message for say all in review cursor command.
msgid ""
-"reads from the review cursor up to end of current text, moving the review "
-"cursor as it goes"
+"reads from the review cursor up to end of current text, moving the review
cursor "
+"as it goes"
msgstr "بدأ القراءة من عند مؤشر الاستعراض, حتى نهاية النص"

#. Translators: Input help mode message for say all with system caret command.
msgid ""
-"reads from the system caret up to the end of the text, moving the caret as "
-"it goes"
+"reads from the system caret up to the end of the text, moving the caret as it
goes"
msgstr "بدأ القراءة من عند مؤشر التحرير, حتى نهاية النص"

#. Translators: Reported when trying to obtain formatting information (such as
font name, indentation and so on) but there is no formatting information for
the text under cursor.
@@ -2547,8 +2606,7 @@ msgstr "لا توجد تنسيقات"

#. Translators: Input help mode message for report formatting command.
msgid ""
-"Reports formatting info for the current review cursor position within a "
-"document"
+"Reports formatting info for the current review cursor position within a
document"
msgstr "الإعلان عن التنسيق بالموضع الحالي لمؤشر الاستعراض داخل المستند"

#. Translators: Input help mode message for report current focus command.
@@ -2581,9 +2639,8 @@ msgstr "لا يوجد عنوان"

#. Translators: Input help mode message for report title bar command.
msgid ""
-"Reports the title of the current application or foreground window. If "
-"pressed twice, spells the title. If pressed three times, copies the title to "
-"the clipboard"
+"Reports the title of the current application or foreground window. If pressed
"
+"twice, spells the title. If pressed three times, copies the title to the
clipboard"
msgstr ""
"الإعلان عن عنوان التطبيق الحالي أو النافذة المرئية. بالضغط عليه مرتين, يقوم "
"بتهجئته, وبالضغط عليه ثلاث مرات ينسخ العنوان إلى حافظة الوندوز"
@@ -2594,13 +2651,13 @@ msgstr "قراءة الكائن الحالي"

#. Translators: Input help mode message for developer info for current
navigator object command, used by developers to examine technical info on
navigator object. This command also serves as a shortcut to open NVDA log
viewer.
msgid ""
-"Logs information about the current navigator object which is useful to "
-"developers and activates the log viewer so the information can be examined."
+"Logs information about the current navigator object which is useful to
developers "
+"and activates the log viewer so the information can be examined."
msgstr ""
-"يسجل المعلومات حول الكائن الحالي ويقوم بتنشيط عارض تقارير البرنامج كي يمكن "
-"فحص المعلومات الواردة بها وهو أمر مفيد للمطورين.Logs information about the "
-"current navigator object which is useful to developers and activates the log "
-"viewer so the information can be examined\t."
+"يسجل المعلومات حول الكائن الحالي ويقوم بتنشيط عارض تقارير البرنامج كي يمكن
فحص "
+"المعلومات الواردة بها وهو أمر مفيد للمطورين.Logs information about the
current "
+"navigator object which is useful to developers and activates the log viewer
so the "
+"information can be examined\t."

#. Translators: A mode where no progress bar updates are given.
msgid "no progress bar updates"
@@ -2620,8 +2677,8 @@ msgstr "إصدار صوت الصفير بالإضافة إلى نُطْق الن

#. Translators: Input help mode message for toggle progress bar output command.
msgid ""
-"Toggles between beeps, speech, beeps and speech, and off, for reporting "
-"progress bar updates"
+"Toggles between beeps, speech, beeps and speech, and off, for reporting
progress "
+"bar updates"
msgstr ""
"يَتَنَقَّل بالإعلام عن التغييرات في شريط التقدم بين صوت الصفير فقط, أو نطق
النسبة "
"المئوية فقط, أو عن طريق الاثنين معا, أو عن طريق التعطيل"
@@ -2636,8 +2693,8 @@ msgstr "الإعلان عن التغييرات التلقائية تشغيل"

#. Translators: Input help mode message for toggle dynamic content changes
command.
msgid ""
-"Toggles on and off the reporting of dynamic content changes, such as new "
-"text in dos console windows"
+"Toggles on and off the reporting of dynamic content changes, such as new text
in "
+"dos console windows"
msgstr "تشغيل وتعطيل الإعلام عن تغيير المحتوى التلقائي للسطر الإلكتروني"

#. Translators: presented when toggled.
@@ -2649,8 +2706,7 @@ msgid "caret moves review cursor on"
msgstr "تغيير مؤشر الاستعراض وفقا لحركة مؤشر التحرير تشغيل"

#. Translators: Input help mode message for toggle caret moves review cursor
command.
-msgid ""
-"Toggles on and off the movement of the review cursor due to the caret moving."
+msgid "Toggles on and off the movement of the review cursor due to the caret
moving."
msgstr "تشغيل وتعطيل تحريك مؤشر الاستعراض وفقا لمؤشر التحرير."

#. Translators: presented when toggled.
@@ -2662,8 +2718,7 @@ msgid "focus moves navigator object on"
msgstr "تغيير الكائن بتغيير التحديد الحالي تشغيل"

#. Translators: Input help mode message for toggle focus moves navigator
object command.
-msgid ""
-"Toggles on and off the movement of the navigator object due to focus changes"
+msgid "Toggles on and off the movement of the navigator object due to focus
changes"
msgstr "تشغيل وتعطيل حركة الكائن تبعا لحركة التحديد الحالي"

#. Translators: This is presented when there is no battery such as desktop
computers and laptops with battery pack removed.
@@ -2685,8 +2740,7 @@ msgstr "{hours:d} ساعات و {minutes:d} دقائق متبقية"

#. Translators: Input help mode message for report battery status command.
msgid "reports battery status and time remaining if AC is not plugged in"
-msgstr ""
-"الإعلان عن حالة البطارية والزمن المتبقي في حالة فصل مصدر الطاقة الكهرابائية"
+msgstr "الإعلان عن حالة البطارية والزمن المتبقي في حالة فصل مصدر الطاقة
الكهرابائية"

#. Translators: Spoken to indicate that the next key press will be sent
straight to the current program as though NVDA is not running.
msgid "Pass next key through"
@@ -2694,8 +2748,8 @@ msgstr "تمرير المفتاح التالي عبر"

#. Translators: Input help mode message for pass next key through command.
msgid ""
-"The next key that is pressed will not be handled at all by NVDA, it will be "
-"passed directly through to Windows."
+"The next key that is pressed will not be handled at all by NVDA, it will be
passed "
+"directly through to Windows."
msgstr "تنفيذ مفتاح الاختصار التالي في النوندوز"

#. Translators: Indicates the name of the current program (example output:
Currently running application is explorer.exe).
@@ -2714,8 +2768,8 @@ msgstr " والوحدة البرمجية العاملة الحالية هي %s"

#. Translators: Input help mode message for report current program name and
app module name command.
msgid ""
-"Speaks the filename of the active application along with the name of the "
-"currently loaded appModule"
+"Speaks the filename of the active application along with the name of the
currently "
+"loaded appModule"
msgstr "قراءة اسم الملف في التطبيق الحالي بالتزامن مع الوحدة البرمجية العاملة"

#. Translators: Input help mode message for go to general settings dialog
command.
@@ -2756,11 +2810,11 @@ msgstr "حفظ الإعدادات الحالية للبرنامج"

#. Translators: Input help mode message for apply last saved or default
settings command.
msgid ""
-"Pressing once reverts the current configuration to the most recently saved "
-"state. Pressing three times reverts to factory defaults."
+"Pressing once reverts the current configuration to the most recently saved
state. "
+"Pressing three times reverts to factory defaults."
msgstr ""
-"بالضغط عليه مرة واحدة سيقوم باسترجاع الإعدادات السابقة. بالضغط عليه ثلاث "
-"مرات سيعود بالبرنامج إلى الإعدادات الافتراضية."
+"بالضغط عليه مرة واحدة سيقوم باسترجاع الإعدادات السابقة. بالضغط عليه ثلاث مرات
"
+"سيعود بالبرنامج إلى الإعدادات الافتراضية."

#. Translators: Input help mode message for activate python console command.
msgid "Activates the NVDA Python Console, primarily useful for development"
@@ -2790,8 +2844,7 @@ msgstr "لا يوجد نص بالحافظة"
#. Translators: If the number of characters on the clipboard is greater than
about 1000, it reports this message and gives number of characters on the
clipboard.
#. Example output: The clipboard contains a large portion of text. It is 2300
characters long.
#, python-format
-msgid ""
-"The clipboard contains a large portion of text. It is %s characters long"
+msgid "The clipboard contains a large portion of text. It is %s characters
long"
msgstr "الحافظة تحتوي على جزء كبير من نص. يبلغ طوله %s حرف"

#. Translators: Input help mode message for report clipboard text command.
@@ -2804,8 +2857,7 @@ msgstr "بداية التحديد"

#. Translators: Input help mode message for mark review cursor position for
copy command (that is, marks the current review cursor position as the starting
point for text to be copied).
msgid ""
-"Marks the current position of the review cursor as the start of text to be "
-"copied"
+"Marks the current position of the review cursor as the start of text to be
copied"
msgstr "بدأ التحديد من نقطة وجود المؤشر للنسخ"

#. Translators: Presented when attempting to copy some review cursor text but
there is no start marker.
@@ -2826,8 +2878,8 @@ msgstr "لا يوجد نص للنسخ"

#. Translators: Input help mode message for copy selected review cursor text
to clipboard command.
msgid ""
-"Retrieves the text from the previously set start marker up to and including "
-"the current position of the review cursor and copies it to the clipboard"
+"Retrieves the text from the previously set start marker up to and including
the "
+"current position of the review cursor and copies it to the clipboard"
msgstr ""
"استرجاع النص بداية من علامة التحديد السابقة حتى موضع المؤشر ونسخه إلى الحافظة"

@@ -2864,8 +2916,8 @@ msgid ""
"Reloads app modules and global plugins without restarting NVDA, which can be "
"Useful for developers"
msgstr ""
-"إعادة تحميل الوحدات البرمجية والملحقات العالمية دون إعادة تشغيل NVDA مما "
-"يفيد المطورين"
+"إعادة تحميل الوحدات البرمجية والملحقات العالمية دون إعادة تشغيل NVDA مما يفيد
"
+"المطورين"

#. Translators: a message when there is no next object when navigating
msgid "no next"
@@ -2873,14 +2925,12 @@ msgstr "لا يوجد المزيد من الكائنات"

#. Translators: Input help mode message for a touchscreen gesture.
msgid ""
-"Moves to the next object in a flattened view of the object navigation "
-"hierarchy"
+"Moves to the next object in a flattened view of the object navigation
hierarchy"
msgstr "يتحرك للكائن التالي وفقا للترتيب الشجري للكائنات"

#. Translators: Input help mode message for a touchscreen gesture.
msgid ""
-"Moves to the previous object in a flattened view of the object navigation "
-"hierarchy"
+"Moves to the previous object in a flattened view of the object navigation
hierarchy"
msgstr "يتحرك للكائن السابق وفقا للترتيب الشجري للكائنات"

#. Translators: Cycles through available touch modes (a group of related touch
gestures; example output: "object mode"; see the user guide for more
information on touch modes).
@@ -2898,11 +2948,11 @@ msgstr "الإعلان عن الكائن أو المحتوى الذي يقع ت

#. Translators: Input help mode message for a touchscreen gesture.
msgid ""
-"Reports the new object or content under your finger if different to where "
-"your finger was last"
+"Reports the new object or content under your finger if different to where
your "
+"finger was last"
msgstr ""
-"الإعلان عن الكائن أو المحتوى الجديد الذي يقع تحت أصبعك إذا اختلف عن الكائن "
-"الذي كنت لمسته آخر مرة"
+"الإعلان عن الكائن أو المحتوى الجديد الذي يقع تحت أصبعك إذا اختلف عن الكائن
الذي "
+"كنت لمسته آخر مرة"

#. Translators: Describes the command to open the Configuration Profiles
dialog.
msgid "Shows the NVDA Configuration Profiles dialog"
@@ -3286,8 +3336,8 @@ msgid ""
"Allows NVDA to run on the Windows Logon screen, UAC screen and other secure "
"screens."
msgstr ""
-"السماح ل NVDA بالعمل عند شاشة الدخول لويندوز, وشاشة حسابات المستخدم, "
-"والشاشات المأمنة الأخرى."
+"السماح ل NVDA بالعمل عند شاشة الدخول لويندوز, وشاشة حسابات المستخدم, والشاشات
"
+"المأمنة الأخرى."

msgid "Type help(object) to get help about object."
msgstr "اكتب help(واسم الكائن) للحصول على معلومات عنه"
@@ -3772,19 +3822,17 @@ msgid ""
"We need your help in order to continue to improve NVDA.\n"
"This project relies primarily on donations and grants. By donating, you are "
"helping to fund full time development.\n"
-"If even $10 is donated for every download, we will be able to cover all of "
-"the ongoing costs of the project.\n"
+"If even $10 is donated for every download, we will be able to cover all of
the "
+"ongoing costs of the project.\n"
"All donations are received by NV Access, the non-profit organisation which "
"develops NVDA.\n"
"Thank you for your support."
msgstr ""
"نريد منك المساعدة من أجل الاستمرار في تطوير nvda.\n"
-"يعتمد هذا المشروع بشكل أساسي على التبرعات والمنح. فمن خلال قيامك بالتبرع, "
-"فإنك تساهم في تمويل تطوير NVDA بأجر كامل.\n"
-"إذا قمت بالتبرع ب$10 لكل مرة تحميل, سنكون قادرون على تغطية كل تكلفة هذا "
-"المشروع.\n"
-"تستقبل التبرعات منظمة NV Access, المنظمة الغير ربحية المسؤولة عن تطوير "
-"NVDA.\n"
+"يعتمد هذا المشروع بشكل أساسي على التبرعات والمنح. فمن خلال قيامك بالتبرع,
فإنك "
+"تساهم في تمويل تطوير NVDA بأجر كامل.\n"
+"إذا قمت بالتبرع ب$10 لكل مرة تحميل, سنكون قادرون على تغطية كل تكلفة هذا
المشروع.\n"
+"تستقبل التبرعات منظمة NV Access, المنظمة الغير ربحية المسؤولة عن تطوير
NVDA.\n"
"نشكرك على الدعم."

#. Translators: The title of the dialog requesting donations from users.
@@ -3821,21 +3869,20 @@ msgid ""
"URL: {url}\n"
"{copyright}\n"
"\n"
-"{name} is covered by the GNU General Public License (Version 2). You are "
-"free to share or change this software in any way you like as long as it is "
-"accompanied by the license and you make all source code available to anyone "
-"who wants it. This applies to both original and modified copies of this "
-"software, plus any derivative works.\n"
+"{name} is covered by the GNU General Public License (Version 2). You are free
to "
+"share or change this software in any way you like as long as it is
accompanied by "
+"the license and you make all source code available to anyone who wants it.
This "
+"applies to both original and modified copies of this software, plus any
derivative "
+"works.\n"
"For further details, you can view the license from the Help menu.\n"
-"It can also be viewed online at: http://www.gnu.org/licenses/old-licenses/";
-"gpl-2.0.html\n"
+"It can also be viewed online at:
http://www.gnu.org/licenses/old-licenses/gpl-2.0.";
+"html\n"
"\n"
-"{name} is developed by NV Access, a non-profit organisation committed to "
-"helping and promoting free and open source solutions for blind and vision "
-"impaired people.\n"
+"{name} is developed by NV Access, a non-profit organisation committed to
helping "
+"and promoting free and open source solutions for blind and vision impaired "
+"people.\n"
"If you find NVDA useful and want it to continue to improve, please consider "
-"donating to NV Access. You can do this by selecting Donate from the NVDA "
-"menu."
+"donating to NV Access. You can do this by selecting Donate from the NVDA
menu."
msgstr ""
"{longName} ({name})\n"
"إصدار: {version}\n"
@@ -3843,22 +3890,21 @@ msgstr ""
"URL: http://www.arabic-nvda.org\n";
"{copyright}\n"
"\n"
-"يخضع برنامج {name} للإصدار الثاني من رخصة جي أن يو العمومية GNU General "
-"Public License. وهي تقضي للمستخدم بكامل الحرية بتوزيع البرنامج أو تعديل "
-"مكوّناته البرمجية بأي طريقة شاء ما دام يُرفِق الرخصة مع البرنامج ويجعل مصدر "
-"الشفرة متاحًا لكل من يطلبه. وينطبق ذلك على كل من النسخة الأصلية والنسخة "
-"المعدَّلة من البرنامج بالإضافة إلى أية برامج تستعمل شفرة برمجية مأخوذة من هذا
"
-"البرنامج.\n"
+"يخضع برنامج {name} للإصدار الثاني من رخصة جي أن يو العمومية GNU General
Public "
+"License. وهي تقضي للمستخدم بكامل الحرية بتوزيع البرنامج أو تعديل مكوّناته
البرمجية "
+"بأي طريقة شاء ما دام يُرفِق الرخصة مع البرنامج ويجعل مصدر الشفرة متاحًا لكل
من يطلبه. "
+"وينطبق ذلك على كل من النسخة الأصلية والنسخة المعدَّلة من البرنامج بالإضافة
إلى أية "
+"برامج تستعمل شفرة برمجية مأخوذة من هذا البرنامج.\n"
"ولمزيد من المعلومات يمكنكم الاطلاع على الرخصة من خلال قائمة المساعدة\n"
"كما يمكنكم الاطلاع عليها عبر الإنترنت فللترجمة باللغة العربية (لنصّ رخصة جينو
"
-"العمومية http://www.linuxfuture.org/download/Arabic_GPL_2.0.htm) وللاطلاع "
-"على الرخصة باللغة الانكليزية (GNU General Public License Version 2 http://";
-"www.gnu.org/licenses/old-licenses/gpl-2.0.html\n"
+"العمومية http://www.linuxfuture.org/download/Arabic_GPL_2.0.htm) وللاطلاع
على "
+"الرخصة باللغة الانكليزية (GNU General Public License Version 2
http://www.gnu.org/";
+"licenses/old-licenses/gpl-2.0.html\n"
"\n"
-"والمؤسسة التي تقوم بتطوير {name} هي مؤسسة NV Access وهي مؤسسة غير ربحية تهدف "
-"إلى العمل على تطوير حلول مفتوحة المصدر للمكفوفين وضعاف البصر.\n"
-"إذا كنت ممن يهمهم أمر البرنامج وتطويره برجاء التبرع لمؤسسة NV Access وذلك "
-"باختيار العنصر تبرع من قائمة NVDA الرئيسية.\n"
+"والمؤسسة التي تقوم بتطوير {name} هي مؤسسة NV Access وهي مؤسسة غير ربحية تهدف
إلى "
+"العمل على تطوير حلول مفتوحة المصدر للمكفوفين وضعاف البصر.\n"
+"إذا كنت ممن يهمهم أمر البرنامج وتطويره برجاء التبرع لمؤسسة NV Access وذلك
باختيار "
+"العنصر تبرع من قائمة NVDA الرئيسية.\n"
"وللتبرع ل NVDA العربي يرجى زيارة موقعنا http://www.arabic-nvda.org";

#. Translators: the message that is shown when the user tries to install an
add-on from windows explorer and NVDA is not running.
@@ -3871,13 +3917,13 @@ msgstr ""

#. Translators: Reports navigator object's dimensions (example output: object
edges positioned 20 per cent from left edge of screen, 10 per cent from top
edge of screen, width is 40 per cent of screen, height is 50 per cent of
screen).
msgid ""
-"Object edges positioned {left:.1f} per cent from left edge of screen, "
-"{top:.1f} per cent from top edge of screen, width is {width:.1f} per cent of "
-"screen, height is {height:.1f} per cent of screen"
+"Object edges positioned {left:.1f} per cent from left edge of screen,
{top:.1f} "
+"per cent from top edge of screen, width is {width:.1f} per cent of screen,
height "
+"is {height:.1f} per cent of screen"
msgstr ""
-"موقع الكائن على الشاشة {left:.1f} بالمائة من الحد الأيسر للشاشة, {top:.1f} "
-"بالمائة من الحد الأيمن للشاشة, العرض {width:.1f} بالمائة من الشاشة, "
-"والطول{height:.1f} بالمائة من الشاشة"
+"موقع الكائن على الشاشة {left:.1f} بالمائة من الحد الأيسر للشاشة, {top:.1f}
بالمائة "
+"من الحد الأيمن للشاشة, العرض {width:.1f} بالمائة من الشاشة,
والطول{height:.1f} "
+"بالمائة من الشاشة"

#. Translators: a message announcing a candidate's character and description.
msgid "{symbol} as in {description}"
@@ -4280,13 +4326,12 @@ msgstr "يبعد عن الحافة السفلى للشريحة بمقدار {dis

#. Translators: The description for a script
msgid ""
-"Toggles between reporting the speaker notes or the actual slide content. "
-"This does not change what is visible on-screen, but only what the user can "
-"read with NVDA"
+"Toggles between reporting the speaker notes or the actual slide content. This
does "
+"not change what is visible on-screen, but only what the user can read with
NVDA"
msgstr ""
-"الانتقال بين تشغيل وتعطيل الإعلان عن ملاحظات المعلق أو المحتوى الفعلي "
-"للشريحة. هذا لم يغير شيء مما يظهر على الشاشة, بل سيتم الإعلان عما يمكن "
-"للمستخدم قراءته باستخدام NVDA"
+"الانتقال بين تشغيل وتعطيل الإعلان عن ملاحظات المعلق أو المحتوى الفعلي
للشريحة. هذا "
+"لم يغير شيء مما يظهر على الشاشة, بل سيتم الإعلان عما يمكن للمستخدم قراءته
باستخدام "
+"NVDA"

#. Translators: The title of the current slide (with notes) in a running Slide
Show in Microsoft PowerPoint.
msgid "Slide show notes - {slideName}"
@@ -4498,8 +4543,7 @@ msgid "&Keyboard settings..."
msgstr "إعدادات &لوحة المفاتيح..."

msgid ""
-"Configure keyboard layout, speaking of typed characters, words or command "
-"keys"
+"Configure keyboard layout, speaking of typed characters, words or command
keys"
msgstr "تعديل نمط لوحة المفاتيح، بنطق الأحرف, أو الكلمات أو مفاتيح الاختصار"

#. Translators: The label for the menu item to open Mouse Settings dialog.
@@ -4521,8 +4565,8 @@ msgid "&Input composition settings..."
msgstr "إ&عدادات كتابة الأحرف الآسيوية"

msgid ""
-"Configure how NVDA reports input composition and candidate selection for "
-"certain languages"
+"Configure how NVDA reports input composition and candidate selection for
certain "
+"languages"
msgstr "إعداداد كيفية إعلان NVDA عن قائمة المدخلات المقترحة والأحرف المكتوبة"

#. Translators: The label for the menu item to open Object Presentation dialog.
@@ -4551,8 +4595,8 @@ msgid "&Default dictionary..."
msgstr "ال&معجم التلقائي..."

msgid ""
-"A dialog where you can set default dictionary by adding dictionary entries "
-"to the list"
+"A dialog where you can set default dictionary by adding dictionary entries to
the "
+"list"
msgstr "مُحاوَرَة تُمَكّنك من وضع معجم صوتي تلقائي عن طريق إضافة قواعد نطقية
للقائمة"

#. Translators: The label for the menu item to open Voice specific speech
dictionary dialog.
@@ -4560,21 +4604,19 @@ msgid "&Voice dictionary..."
msgstr "معجم الصوت ال&حالي..."

msgid ""
-"A dialog where you can set voice-specific dictionary by adding dictionary "
-"entries to the list"
+"A dialog where you can set voice-specific dictionary by adding dictionary
entries "
+"to the list"
msgstr ""
-"مُحاوَرَة تُمَكّنك من وضع معجم صوتي خاص بالصوت الحالي عن طريق إضافة قواعد
نطقية "
-"للقائمة"
+"مُحاوَرَة تُمَكّنك من وضع معجم صوتي خاص بالصوت الحالي عن طريق إضافة قواعد
نطقية للقائمة"

#. Translators: The label for the menu item to open Temporary speech
dictionary dialog.
msgid "&Temporary dictionary..."
msgstr "معجم صوتي &مؤقت..."

msgid ""
-"A dialog where you can set temporary dictionary by adding dictionary entries "
-"to the edit box"
-msgstr ""
-"مُحاوَرَة تُمَكّنك من وضع معجم صوتي مؤقت عن طريق إضافة قواعد نطقية لمربع
تحرير"
+"A dialog where you can set temporary dictionary by adding dictionary entries
to "
+"the edit box"
+msgstr "مُحاوَرَة تُمَكّنك من وضع معجم صوتي مؤقت عن طريق إضافة قواعد نطقية
لمربع تحرير"

#. Translators: The label for a submenu under NvDA Preferences menu to select
speech dictionaries.
msgid "Speech &dictionaries"
@@ -4694,24 +4736,22 @@ msgstr "الخروج من البرنامج"

msgid ""
"Welcome to NVDA!\n"
-"Most commands for controlling NVDA require you to hold down the NVDA key "
-"while pressing other keys.\n"
-"By default, the numpad insert and main insert keys may both be used as the "
-"NVDA key.\n"
+"Most commands for controlling NVDA require you to hold down the NVDA key
while "
+"pressing other keys.\n"
+"By default, the numpad insert and main insert keys may both be used as the
NVDA "
+"key.\n"
"You can also configure NVDA to use the CapsLock as the NVDA key.\n"
"Press NVDA+n at any time to activate the NVDA menu.\n"
-"From this menu, you can configure NVDA, get help and access other NVDA "
-"functions.\n"
+"From this menu, you can configure NVDA, get help and access other NVDA
functions.\n"
msgstr ""
"أهلا وسهلا بكم في برنامج NVDA\n"
-". تتطلب معظم أوامر البرنامج الضغط على مفتاح NVDA قبيل الضغط على مفاتيح "
-"الاختصار الأخرى.\n"
-" ويقوم مفتاحي الإدراج سواء الواقع في اللوحة الرقمية أو الممتد بالعمل كمفتاح "
-"NVDA.\n"
+". تتطلب معظم أوامر البرنامج الضغط على مفتاح NVDA قبيل الضغط على مفاتيح
الاختصار "
+"الأخرى.\n"
+" ويقوم مفتاحي الإدراج سواء الواقع في اللوحة الرقمية أو الممتد بالعمل كمفتاح
NVDA.\n"
" وكذلك بإمكانك ضبط البرنامج بحيث يستخدم مفتاح تكبير الحروف كمفتاح للبرنامج.\n"
-"وفي أي وقت يمكنك الضغط على مفتاح NVDA زائد حرف (N) لفتح قائمة البرنامج ومن "
-"ثم إجراء اية تعديلات تفضيلية أو الحصول على التعليمات الخاصة به أو الوصول "
-"لأية وظائف أخرى في البرنامج.\n"
+"وفي أي وقت يمكنك الضغط على مفتاح NVDA زائد حرف (N) لفتح قائمة البرنامج ومن ثم
"
+"إجراء اية تعديلات تفضيلية أو الحصول على التعليمات الخاصة به أو الوصول لأية
وظائف "
+"أخرى في البرنامج.\n"

#. Translators: The title of the Welcome dialog when user starts NVDA for the
first time.
msgid "Welcome to NVDA"
@@ -4756,11 +4796,11 @@ msgstr "استم&رار التشغيل"

#. Translators: A message in the exit Dialog shown when all add-ons are
disabled.
msgid ""
-"All add-ons are now disabled. They will be re-enabled on the next restart "
-"unless you choose to disable them again."
+"All add-ons are now disabled. They will be re-enabled on the next restart
unless "
+"you choose to disable them again."
msgstr ""
-"كل الإضافات معطلة الآن. سيتم تفعيلها في المرة التالية من إعادة تشغيل NVDA "
-"إلا إذا اخترت تعطيلها مرة أخرى."
+"كل الإضافات معطلة الآن. سيتم تفعيلها في المرة التالية من إعادة تشغيل NVDA إلا
إذا "
+"اخترت تعطيلها مرة أخرى."

#. Translators: The label for actions list in the Exit dialog.
msgid "What would you like to &do?"
@@ -4844,16 +4884,15 @@ msgstr "حزمة الإضافة البرمجية (*.{ext})"
#. Translators: The message displayed when an error occurs when opening an
add-on package for adding.
#, python-format
msgid ""
-"Failed to open add-on package file at %s - missing file or invalid file "
-"format"
+"Failed to open add-on package file at %s - missing file or invalid file
format"
msgstr ""
-"فشل في فتح الحزمة التي تحتوي على الإضافة البرمجية ب %s - ربما لفقدان أحد "
-"الملفات أو لخطأ في تنسيق الملف."
+"فشل في فتح الحزمة التي تحتوي على الإضافة البرمجية ب %s - ربما لفقدان أحد
الملفات "
+"أو لخطأ في تنسيق الملف."

#. Translators: A message asking the user if they really wish to install an
addon.
msgid ""
-"Are you sure you want to install this add-on? Only install add-ons from "
-"trusted sources.\n"
+"Are you sure you want to install this add-on? Only install add-ons from
trusted "
+"sources.\n"
"Addon: {summary} {version}\n"
"Author: {author}"
msgstr ""
@@ -4867,11 +4906,9 @@ msgid "Add-on Installation"
msgstr "تثبيت الإضافة البرمجية"

#. Translators: A message asking if the user wishes to update a previously
installed add-on with this one.
-msgid ""
-"A version of this add-on is already installed. Would you like to update it?"
+msgid "A version of this add-on is already installed. Would you like to update
it?"
msgstr ""
-"نفس الإصدارأو إصدار آخر مثبت بالفعل من تلك الإضافة. هل تريد حذف الإضافة "
-"القديمة"
+"نفس الإصدارأو إصدار آخر مثبت بالفعل من تلك الإضافة. هل تريد حذف الإضافة
القديمة"

#. Translators: The title of the dialog presented while an Addon is being
installed.
msgid "Installing Add-on"
@@ -4910,11 +4947,11 @@ msgstr "تعمل"

#. Translators: A message asking the user if they wish to restart NVDA as
addons have been added or removed.
msgid ""
-"Add-ons have been added or removed. You must restart NVDA for these changes "
-"to take effect. Would you like to restart now?"
+"Add-ons have been added or removed. You must restart NVDA for these changes
to "
+"take effect. Would you like to restart now?"
msgstr ""
-"لقد تم إضافة أو حذف إضافات برمجية. يجب عليك إعادة تشغيل NVDA لتفعيل "
-"التغييرات. هل تود إعادة التشغيل الآن؟"
+"لقد تم إضافة أو حذف إضافات برمجية. يجب عليك إعادة تشغيل NVDA لتفعيل
التغييرات. هل "
+"تود إعادة التشغيل الآن؟"

#. Translators: Title for message asking if the user wishes to restart NVDA as
addons have been added or removed.
msgid "Restart NVDA"
@@ -5044,11 +5081,9 @@ msgid "Say all"
msgstr "القراءة المتصلة"

#. Translators: An error displayed when saving configuration profile triggers
fails.
-msgid ""
-"Error saving configuration profile triggers - probably read only file system."
+msgid "Error saving configuration profile triggers - probably read only file
system."
msgstr ""
-"خطأ بحفظ الأوضاع المرتبطة بمحرك - أغلب الظن أن النظام الذي تستخدمه للقراءة "
-"فقط."
+"خطأ بحفظ الأوضاع المرتبطة بمحرك - أغلب الظن أن النظام الذي تستخدمه للقراءة
فقط."

#. Translators: The title of the configuration profile triggers dialog.
msgid "Profile Triggers"
@@ -5087,12 +5122,12 @@ msgstr "استخدم هذا الوضع في:"
#. Translators: The confirmation prompt presented when creating a new
configuration profile
#. and the selected trigger is already associated.
msgid ""
-"This trigger is already associated with another profile. If you continue, it "
-"will be removed from that profile and associated with this one.\n"
+"This trigger is already associated with another profile. If you continue, it
will "
+"be removed from that profile and associated with this one.\n"
"Are you sure you want to continue?"
msgstr ""
-"هذا المُشَّغِلْ يستخدم مع وضع آخر. إذا أردت الاستمرار, سيتم حذف المحرك من هذا
"
-"الوضع وربطه بالوضع الحالي.\n"
+"هذا المُشَّغِلْ يستخدم مع وضع آخر. إذا أردت الاستمرار, سيتم حذف المحرك من هذا
الوضع "
+"وربطه بالوضع الحالي.\n"
"هل تريد الاستمرار؟"

#. Translators: The title of the warning dialog displayed when trying to copy
settings for use in secure screens.
@@ -5107,12 +5142,11 @@ msgstr "خطأ في إنشاء الوضع - أغلب الظن أن ملف الن
#. manually activate a configuration profile that has just been created.
msgid ""
"To edit this profile, you will need to manually activate it. Once you have "
-"finished editing, you will need to manually deactivate it to resume normal "
-"usage.\n"
+"finished editing, you will need to manually deactivate it to resume normal
usage.\n"
"Do you wish to manually activate it now?"
msgstr ""
-"لتعديل هذا الوضع, ينبغي عليك تنشيطه يدويا. بمجرد الانتهاء من التعديل, ستحتاج "
-"إلى تعطيله يدويا كي تستأنف الاستخدام الطبيعي.\n"
+"لتعديل هذا الوضع, ينبغي عليك تنشيطه يدويا. بمجرد الانتهاء من التعديل, ستحتاج
إلى "
+"تعطيله يدويا كي تستأنف الاستخدام الطبيعي.\n"
"هل تريد تنشيط الملف يدويا الآن؟"

#. Translators: The title of the confirmation dialog for manual activation of
a created profile.
@@ -5137,12 +5171,12 @@ msgstr "يرجى الانتظار حتى تثبيت NVDA."

#. Translators: a message dialog asking to retry or cancel when NVDA install
fails
msgid ""
-"The installation is unable to remove or overwrite a file. Another copy of "
-"NVDA may be running on another logged-on user account. Please make sure all "
-"installed copies of NVDA are shut down and try the installation again."
+"The installation is unable to remove or overwrite a file. Another copy of
NVDA may "
+"be running on another logged-on user account. Please make sure all installed "
+"copies of NVDA are shut down and try the installation again."
msgstr ""
-"تعذر حذف أو استبدال أحد الملفات. ربما تعمل نسخة أخرى من NVDA على حساب مستخدم "
-"آخر. يرجى التأكد من تعطيل جميع نسخ NVDA العاملة وقم بإعادة التثبيت مرة أخرى."
+"تعذر حذف أو استبدال أحد الملفات. ربما تعمل نسخة أخرى من NVDA على حساب مستخدم
آخر. "
+"يرجى التأكد من تعطيل جميع نسخ NVDA العاملة وقم بإعادة التثبيت مرة أخرى."

#. Translators: the title of a retry cancel dialog when NVDA installation fails
#. Translators: the title of a retry cancel dialog when NVDA portable copy
creation fails
@@ -5151,10 +5185,8 @@ msgstr "الملف قيد الاستخدام"

#. Translators: The message displayed when an error occurs during installation
of NVDA.
msgid ""
-"The installation of NVDA failed. Please check the Log Viewer for more "
-"information."
-msgstr ""
-"فشل تثبيت NVDA. يرجى الاطلاع على ملف تقارير البرنامج لمزيد من المعلومات."
+"The installation of NVDA failed. Please check the Log Viewer for more
information."
+msgstr "فشل تثبيت NVDA. يرجى الاطلاع على ملف تقارير البرنامج لمزيد من
المعلومات."

#. Translators: The message displayed when NVDA has been successfully
installed.
msgid "Successfully installed NVDA. "
@@ -5183,15 +5215,12 @@ msgstr "لتثبيت NVDA على القرص الصلب, يرجى الضغط عل

#. Translators: An informational message in the Install NVDA dialog.
msgid ""
-"A previous copy of NVDA has been found on your system. This copy will be "
-"updated."
-msgstr ""
-"تم العثور على نسخة من البرنامج على نظام التشغيل الخاص بك. سيتم تحديثها."
+"A previous copy of NVDA has been found on your system. This copy will be
updated."
+msgstr "تم العثور على نسخة من البرنامج على نظام التشغيل الخاص بك. سيتم
تحديثها."

#. Translators: a message in the installer telling the user NVDA is now
located in a different place.
msgid ""
-"The installation path for NVDA has changed. it will now be installed in "
-"{path}"
+"The installation path for NVDA has changed. it will now be installed in
{path}"
msgstr "لقد تم تغيير مسار تثبيت NVDA. سيتم تثبيته بالمسار {path}"

#. Translators: The label of a checkbox option in the Install NVDA dialog.
@@ -5222,11 +5251,10 @@ msgstr "عمل نسخة محمولة من NVDA"

#. Translators: An informational message displayed in the Create Portable NVDA
dialog.
msgid ""
-"To create a portable copy of NVDA, please select the path and other options "
-"and then press Continue"
+"To create a portable copy of NVDA, please select the path and other options
and "
+"then press Continue"
msgstr ""
-"لإنشاء نسخة محمولة من NVDA, رجاء اختر المسار والخيارات الأخرى ثم اضغط زر "
-"استمرار"
+"لإنشاء نسخة محمولة من NVDA, رجاء اختر المسار والخيارات الأخرى ثم اضغط زر
استمرار"

#. Translators: The label of a grouping containing controls to select the
destination directory
#. in the Create Portable NVDA dialog.
@@ -5351,8 +5379,7 @@ msgid "Log level"
msgstr "مستوى التقرير"

#. Translators: The label for a setting in general settings to allow NVDA to
come up in Windows login screen (useful if user needs to enter passwords or if
multiple user accounts are present to allow user to choose the correct account).
-msgid ""
-"Use NVDA on the Windows logon screen (requires administrator privileges)"
+msgid "Use NVDA on the Windows logon screen (requires administrator
privileges)"
msgstr "تشغيل البرنامج عند شاشة الدخول إلى ويندوز (يحتاج لصلاحيات إدارية)"

#. Translators: The label for a button in general settings to copy current
user settings to system settings (to allow current settings to be used in
secure screens such as User Account Control (UAC) dialog).
@@ -5360,8 +5387,8 @@ msgid ""
"Use currently saved settings on the logon and other secure screens (requires "
"administrator privileges)"
msgstr ""
-"استخدام الإعدادات المحفوظة حاليا في شاشة الدخول لويندوز وفي الشاشات الآمنة "
-"الأخرى (يتطلب صلاحيات إدارية)"
+"استخدام الإعدادات المحفوظة حاليا في شاشة الدخول لويندوز وفي الشاشات الآمنة
الأخرى "
+"(يتطلب صلاحيات إدارية)"

#. Translators: The label of a checkbox in general settings to toggle
automatic checking for updated versions of NVDA (if not checked, user must
check for updates manually).
msgid "Automatically check for &updates to NVDA"
@@ -5369,13 +5396,12 @@ msgstr "&تحديث nvda آليا"

#. Translators: A message to warn the user when attempting to copy current
settings to system settings.
msgid ""
-"Custom plugins were detected in your user settings directory. Copying these "
-"to the system profile could be a security risk. Do you still wish to copy "
-"your settings?"
+"Custom plugins were detected in your user settings directory. Copying these
to the "
+"system profile could be a security risk. Do you still wish to copy your
settings?"
msgstr ""
-"لقد تم اكتشاف احتواء مجلد الإعدادات الخاص بك على ملحقات برمجية إضافية. نسخ "
-"تلك الإعدادات إلى شاشات الدخول ربما يعرضك لخطورة أمنية. هل تريد الاستمرار في "
-"نسخ إعداداتك؟"
+"لقد تم اكتشاف احتواء مجلد الإعدادات الخاص بك على ملحقات برمجية إضافية. نسخ
تلك "
+"الإعدادات إلى شاشات الدخول ربما يعرضك لخطورة أمنية. هل تريد الاستمرار في نسخ "
+"إعداداتك؟"

#. Translators: The title of the dialog presented while settings are being
copied
msgid "Copying Settings"
@@ -5387,11 +5413,11 @@ msgstr "يرجى الانتظار حتى الانتهاء من نسخ الإعد

#. Translators: a message dialog asking to retry or cancel when copying
settings fails
msgid ""
-"Unable to copy a file. Perhaps it is currently being used by another process "
-"or you have run out of disc space on the drive you are copying to."
+"Unable to copy a file. Perhaps it is currently being used by another process
or "
+"you have run out of disc space on the drive you are copying to."
msgstr ""
-"تعذر نسخ أحد الملفات. ربما حدث هذا لأن هذا الملف مستخدم من قبل تطبيق آخر أو "
-"أن مساحة محرك الأقراص الذي تنسخ به غير كافية."
+"تعذر نسخ أحد الملفات. ربما حدث هذا لأن هذا الملف مستخدم من قبل تطبيق آخر أو
أن "
+"مساحة محرك الأقراص الذي تنسخ به غير كافية."

#. Translators: the title of a retry cancel dialog when copying settings fails
msgid "Error Copying"
@@ -5420,13 +5446,13 @@ msgstr "صلاحيات غير كافية"

#. Translators: The message displayed after NVDA interface language has been
changed.
msgid ""
-"For the new language to take effect, the configuration must be saved and "
-"NVDA must be restarted. Press enter to save and restart NVDA, or cancel to "
-"manually save and exit at a later time."
+"For the new language to take effect, the configuration must be saved and NVDA
must "
+"be restarted. Press enter to save and restart NVDA, or cancel to manually
save and "
+"exit at a later time."
msgstr ""
-"لتفعيل اللغة الجديدة, يجب حفظ الإعدادات وإعادة تشغيل البرنامج. قم بالضغط على "
-"مفتاح الإدخال لحفظ الإعدادات وإعادة تشغيل البرنامج، أو مفتاح الهروب لإلغاء "
-"الأمر وحفظ التعديلات, وإعادة تشغيل البرنامج في وقت لاحق."
+"لتفعيل اللغة الجديدة, يجب حفظ الإعدادات وإعادة تشغيل البرنامج. قم بالضغط على
مفتاح "
+"الإدخال لحفظ الإعدادات وإعادة تشغيل البرنامج، أو مفتاح الهروب لإلغاء الأمر
وحفظ "
+"التعديلات, وإعادة تشغيل البرنامج في وقت لاحق."

#. Translators: The title of the dialog which appears when the user changed
NVDA's interface language.
msgid "Language Configuration Change"
@@ -5552,8 +5578,7 @@ msgstr "ا&ستأناف القراءة المتصلة مع مفاتيح الحر
#. Translators: This is the label for a checkbox in the
#. keyboard settings dialog.
msgid "Beep if typing lowercase letters when caps lock is on"
-msgstr ""
-"إصدار تنبيه عند كتابة الأحرف مع مفتاح التبديل أثناء تشغيل مفتاح تكبير الحروف"
+msgstr "إصدار تنبيه عند كتابة الأحرف مع مفتاح التبديل أثناء تشغيل مفتاح تكبير
الحروف"

#. Translators: This is the label for a checkbox in the
#. keyboard settings dialog.
@@ -5599,13 +5624,13 @@ msgstr "الإعلان عن &نوع الكائن عند وقوع مؤشر الف

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "play audio coordinates when mouse moves"
-msgstr "إصدار صفارة عند تنقل مؤشر الفأرة"
+msgid "&Play audio coordinates when mouse moves"
+msgstr "إ&صدار صفارة عند تنقل مؤشر الفأرة"

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "brightness controls audio coordinates volume"
-msgstr "التحكم في مستوى صوت صفارة أبعاد الشاشة حسب نقائها"
+msgid "&Brightness controls audio coordinates volume"
+msgstr "ال&تحكم في مستوى صوت صفارة أبعاد الشاشة حسب نقائها"

#. Translators: This is the label for the review cursor settings dialog.
msgid "Review Cursor Settings"
@@ -5793,7 +5818,7 @@ msgstr ""

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report font &name"
+msgid "Report &font name"
msgstr "الإعلان عن &نوع الخط"

#. Translators: This is the label for a checkbox in the
@@ -5838,7 +5863,7 @@ msgstr "الإعلان عن ال&صفحات"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &line numbers"
+msgid "Report line &numbers"
msgstr "الإعلان عن ر&قم السطر"

#. Translators: This message is presented in the document formatting settings
dialogue
@@ -5869,7 +5894,7 @@ msgstr "الإعلان عن مرا&جع الخلايا بالجدول"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &links"
+msgid "Report lin&ks"
msgstr "الإعلان عن ال&روابط"

#. Translators: This is the label for a checkbox in the
@@ -5879,7 +5904,7 @@ msgstr "الإعلان عن رؤوس الموضو&عات"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report l&ists"
+msgid "Report &lists"
msgstr "الإعلان عن القوائم ال&سردية"

#. Translators: This is the label for a checkbox in the
@@ -6087,8 +6112,7 @@ msgstr "ادخل اختصار:"
#. Translators: An error displayed when saving user defined input gestures
fails.
msgid "Error saving user defined gestures - probably read only file system."
msgstr ""
-"لا يمكن حفظ الاختصارات التي قمت بتخصيصها - أغلب الظن أن ملف النظام معد "
-"للقراءة فقط"
+"لا يمكن حفظ الاختصارات التي قمت بتخصيصها - أغلب الظن أن ملف النظام معد
للقراءة فقط"

#. Translators: name of the default espeak varient.
msgctxt "espeakVarient"
@@ -6150,8 +6174,8 @@ msgstr "استخدام عرض تنسيق الشاشة تعطيل"

#. Translators: the description for the toggleScreenLayout script on
virtualBuffers.
msgid ""
-"Toggles on and off if the screen layout is preserved while rendering the "
-"document content"
+"Toggles on and off if the screen layout is preserved while rendering the
document "
+"content"
msgstr "تشغيل وتعطيل الاحتفاظ بعرض تنسيق الشاشة أثناء معالجة محتوى الصفحة"

#. Translators: The message reported when a user attempts to use a table
movement command
@@ -6217,8 +6241,8 @@ msgid ""
"Cannot set headers. Please enable reporting of table headers in Document "
"Formatting Settings"
msgstr ""
-"لا يمكن ضبط رؤوس الصفوف أو الأعمدة. يرجى تفعيل إعداد الإعلان عن رؤوس الصفوف "
-"أو الأعمدة بالجدول بمحاورة تنسيق المستندات"
+"لا يمكن ضبط رؤوس الصفوف أو الأعمدة. يرجى تفعيل إعداد الإعلان عن رؤوس الصفوف
أو "
+"الأعمدة بالجدول بمحاورة تنسيق المستندات"

#. Translators: a message reported in the SetColumnHeader script for Excel.
msgid "Set {address} as start of column headers"
@@ -6237,12 +6261,12 @@ msgid "Cannot find {address} in column headers"
msgstr "تعذر وجود {address} في رؤوس الأعمدة"

msgid ""
-"Pressing once will set this cell as the first column header for any cells "
-"lower and to the right of it within this region. Pressing twice will forget "
-"the current column header for this cell."
+"Pressing once will set this cell as the first column header for any cells
lower "
+"and to the right of it within this region. Pressing twice will forget the
current "
+"column header for this cell."
msgstr ""
-"الضغط مرة واحدة سيجعل هذه الخلية رأس للعمود الأول للخلايا الأسفل منها أو "
-"التي يمينها في هذا النطاق. والضغط مرتين سيلغي رأس العمود لهذه الخلية. "
+"الضغط مرة واحدة سيجعل هذه الخلية رأس للعمود الأول للخلايا الأسفل منها أو التي
"
+"يمينها في هذا النطاق. والضغط مرتين سيلغي رأس العمود لهذه الخلية. "

#. Translators: a message reported in the SetRowHeader script for Excel.
msgid "Set {address} as start of row headers"
@@ -6261,12 +6285,12 @@ msgid "Cannot find {address} in row headers"
msgstr "تعذر وجود {address} في رؤوس الأعمدة"

msgid ""
-"Pressing once will set this cell as the first row header for any cells lower "
-"and to the right of it within this region. Pressing twice will forget the "
-"current row header for this cell."
+"Pressing once will set this cell as the first row header for any cells lower
and "
+"to the right of it within this region. Pressing twice will forget the current
row "
+"header for this cell."
msgstr ""
-"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس صف للخلايا الأسفل "
-"منها والتي على يمينها في هذه المنطقة. بالضغط عليه مرتين سيلغي هذا الإعداد."
+"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس صف للخلايا الأسفل
منها "
+"والتي على يمينها في هذه المنطقة. بالضغط عليه مرتين سيلغي هذا الإعداد."

#. Translators: A message in Excel when there is no comment
msgid "Not on a comment"
@@ -6411,10 +6435,8 @@ msgid "Set row {rowNumber} column {columnNumber} as
start of column headers"
msgstr "تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس الأعمدة"

#. Translators: a message reported in the SetColumnHeader script for Microsoft
Word.
-msgid ""
-"Already set row {rowNumber} column {columnNumber} as start of column headers"
-msgstr ""
-"تم بالفعل تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس الأعمدة"
+msgid "Already set row {rowNumber} column {columnNumber} as start of column
headers"
+msgstr "تم بالفعل تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس
الأعمدة"

#. Translators: a message reported in the SetColumnHeader script for Microsoft
Word.
msgid "Removed row {rowNumber} column {columnNumber} from column headers"
@@ -6425,22 +6447,20 @@ msgid "Cannot find row {rowNumber} column
{columnNumber} in column headers"
msgstr "تعذر الوصول إلى الصف {rowNumber} العمود {columnNumber} في رؤوس الأعمدة"

msgid ""
-"Pressing once will set this cell as the first column header for any cells "
-"lower and to the right of it within this table. Pressing twice will forget "
-"the current column header for this cell."
+"Pressing once will set this cell as the first column header for any cells
lower "
+"and to the right of it within this table. Pressing twice will forget the
current "
+"column header for this cell."
msgstr ""
-"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس عمود للخلايا "
-"الأسفل منها والتي على يمينها في هذا الجدول. بالضغط عليه مرتين سيلغي الإعداد"
+"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس عمود للخلايا
الأسفل "
+"منها والتي على يمينها في هذا الجدول. بالضغط عليه مرتين سيلغي الإعداد"

#. Translators: a message reported in the SetRowHeader script for Microsoft
Word.
msgid "Set row {rowNumber} column {columnNumber} as start of row headers"
msgstr "تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس الصفوف"

#. Translators: a message reported in the SetRowHeader script for Microsoft
Word.
-msgid ""
-"Already set row {rowNumber} column {columnNumber} as start of row headers"
-msgstr ""
-"تم بالفعل تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس الأعمدة"
+msgid "Already set row {rowNumber} column {columnNumber} as start of row
headers"
+msgstr "تم بالفعل تعيين الصف {rowNumber} العمود {columnNumber} كبداية لرؤوس
الأعمدة"

#. Translators: a message reported in the SetRowHeader script for Microsoft
Word.
msgid "Removed row {rowNumber} column {columnNumber} from row headers"
@@ -6451,12 +6471,12 @@ msgid "Cannot find row {rowNumber} column
{columnNumber} in row headers"
msgstr "تمت إزالة الصف {rowNumber} العمود {columnNumber} من رؤوس الصفوف"

msgid ""
-"Pressing once will set this cell as the first row header for any cells lower "
-"and to the right of it within this table. Pressing twice will forget the "
-"current row header for this cell."
+"Pressing once will set this cell as the first row header for any cells lower
and "
+"to the right of it within this table. Pressing twice will forget the current
row "
+"header for this cell."
msgstr ""
-"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس صف للخلايا الأسفل "
-"منها والتي على يمينها في هذا الجدول. بالضغط عليه مرتين سيلغي هذا الإعداد."
+"بالضغط عليه مرة واحدة سيقوم بتعيين الخلية المحددة كأول رأس صف للخلايا الأسفل
منها "
+"والتي على يمينها في هذا الجدول. بالضغط عليه مرتين سيلغي هذا الإعداد."

#. Translators: a message when toggling formatting in Microsoft word
msgid "Bold on"
@@ -6561,15 +6581,15 @@ msgid "HIMS SyncBraille"
msgstr "HIMS SyncBraille"

#~ msgid ""
-#~ "In NVDA 2013.1, the laptop keyboard layout has been completely redesigned "
-#~ "in order to make it more intuitive and consistent.\n"
+#~ "In NVDA 2013.1, the laptop keyboard layout has been completely redesigned
in "
+#~ "order to make it more intuitive and consistent.\n"
#~ "If you use the laptop layout, please see the What's New document for more "
#~ "information."
#~ msgstr ""
-#~ "في الإصدار 2013.1, قام المطورون بإعادة تصميم نمط الحواسب المحمولة تماما "
-#~ "كي يكون أسرع وأكثر توافقا.\n"
-#~ "فإذا كنت من مستخدمي نمط الحواسب المحمولة, يرجى قراءة ملف المستجدات لمزيد "
-#~ "من المعلومات."
+#~ "في الإصدار 2013.1, قام المطورون بإعادة تصميم نمط الحواسب المحمولة تماما كي
يكون "
+#~ "أسرع وأكثر توافقا.\n"
+#~ "فإذا كنت من مستخدمي نمط الحواسب المحمولة, يرجى قراءة ملف المستجدات لمزيد
من "
+#~ "المعلومات."

#~ msgid "New Laptop Keyboard layout"
#~ msgstr "نمط جديد للحواسب المحمولة"

diff --git a/source/locale/bg/LC_MESSAGES/nvda.po
b/source/locale/bg/LC_MESSAGES/nvda.po
index b854de8..7fbf264 100644
--- a/source/locale/bg/LC_MESSAGES/nvda.po
+++ b/source/locale/bg/LC_MESSAGES/nvda.po
@@ -4,15 +4,15 @@ msgid ""
msgstr ""
"Project-Id-Version: NVDA bzr main:5822\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-03 19:12+1000\n"
-"PO-Revision-Date: 2015-01-31 07:01+0200\n"
-"Last-Translator: Zahari Yurukov <zahari.yurukov@xxxxxxxxx>\n"
+"POT-Creation-Date: 2015-03-26 19:04-0700\n"
+"PO-Revision-Date: 2015-03-28 10:14+0200\n"
+"Last-Translator: Kostadin Kolev <k_kolev1985@xxxxxxx>\n"
"Language-Team: Български <>\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.5.4\n"
+"X-Generator: Poedit 1.6.10\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"

#. Translators: Message to indicate User Account Control (UAC) or other secure
desktop screen is active.
@@ -137,6 +137,16 @@ msgstr "Фарси от първи вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Assamese grade 1"
+msgstr "Асамски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Bengali grade 1"
+msgstr "Бенгалски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Bulgarian 8 dot computer braille"
msgstr "Български 8-точков компютърен брайл "

@@ -271,6 +281,11 @@ msgstr "Френски универсален от втори вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Gujarati grade 1"
+msgstr "Гуджарати от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Greek (Greece) grade 1"
msgstr "Гръцки от първи вид"

@@ -316,6 +331,11 @@ msgstr "Италиански 8-точков компютърен брайл"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kannada grade 1"
+msgstr "Каннада от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Korean grade 1"
msgstr "Корейски от първи вид"

@@ -326,11 +346,31 @@ msgstr "Корейски от втори вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kashmiri grade 1"
+msgstr "Кашмирски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Latvian grade 1"
msgstr "Латвийски от първи вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Malayalam grade 1"
+msgstr "Малаялам от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Manipuri grade 1"
+msgstr "Манипури от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Marathi grade 1"
+msgstr "Маратхи от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Dutch (Belgium) grade 1"
msgstr "Холандски белгийски от първи вид"

@@ -366,6 +406,16 @@ msgstr "Норвежки от трети вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Nepali grade 1"
+msgstr "Непалски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Oriya grade 1"
+msgstr "Ория от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Polish grade 1"
msgstr "Полски от първи вид"

@@ -386,6 +436,11 @@ msgstr "Португалски от втори вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Punjabi grade 1"
+msgstr "Пенджабски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Russian braille for computer code"
msgstr "Руски компютърен брайл"

@@ -396,6 +451,11 @@ msgstr "Руски от първи вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Sanskrit grade 1"
+msgstr "Санскритски от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Swedish grade 1"
msgstr "Шведски от първи вид"

@@ -421,6 +481,11 @@ msgstr "Тамил от първи вид"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Telegu grade 1"
+msgstr "Телугу от първи вид"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Turkish grade 1"
msgstr "Турски от първи вид"

@@ -5691,14 +5756,15 @@ msgstr "Докладвай &вида на обекта при досег с ми

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "play audio coordinates when mouse moves"
-msgstr "Просвирвай звуково координатите на мишката"
+msgid "&Play audio coordinates when mouse moves"
+msgstr "&Просвирвай звуково координатите на мишката"

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "brightness controls audio coordinates volume"
+msgid "&Brightness controls audio coordinates volume"
msgstr ""
-"Силата на звука на аудиокоординатите на мишката зависи от яркостта на екрана"
+"Силата на звука на аудиокоординатите на мишката зависи от &яркостта на "
+"екрана"

#. Translators: This is the label for the review cursor settings dialog.
msgid "Review Cursor Settings"
@@ -5889,7 +5955,7 @@ msgstr ""

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report font &name"
+msgid "Report &font name"
msgstr "Докладвай &името на шрифта"

#. Translators: This is the label for a checkbox in the
@@ -5934,7 +6000,7 @@ msgstr "Докладвай &страниците"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &line numbers"
+msgid "Report line &numbers"
msgstr "Докладвай &номерата на редовете"

#. Translators: This message is presented in the document formatting settings
dialogue
@@ -5965,7 +6031,7 @@ msgstr "Докладвай к&оординатите на клетките в т

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &links"
+msgid "Report lin&ks"
msgstr "Докладвай &връзките"

#. Translators: This is the label for a checkbox in the
@@ -5975,8 +6041,8 @@ msgstr "Докладвай заглавията"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report l&ists"
-msgstr "Докладвай списъците"
+msgid "Report &lists"
+msgstr "Докладвай спис&ъците"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/aa63df38f14a/
Changeset: aa63df38f14a
Branch: None
User: jteh
Date: 2015-04-09 03:44:25+00:00
Summary: eventHandler.requestEvents: Clean up entries for processes soon
after they exit.

This is done by using a WeakValueDictionary and mapping event entries to
AppModules.

Affected #: 1 file

diff --git a/source/eventHandler.py b/source/eventHandler.py
index 832e108..b1c6f30 100755
--- a/source/eventHandler.py
+++ b/source/eventHandler.py
@@ -5,6 +5,7 @@
#Copyright (C) 2007-2014 NV Access Limited

import threading
+import weakref
import queueHandler
import api
import speech
@@ -181,8 +182,10 @@ def doPreDocumentLoadComplete(obj):

focusObject.treeInterceptor=treeInterceptorHandler.getTreeInterceptor(focusObject)
return True

-#: set of (eventName, processId, windowClassName) of events to accept.
-_acceptEvents = set()
+#: Collection of (eventName, processId, windowClassName) of events to accept.
+#: We use a WeakValueDictionary mapping events to AppModules so that
+#: entries get cleaned up automatically soon after their process dies.
+_acceptEvents = weakref.WeakValueDictionary()

def requestEvents(eventName=None, processId=None, windowClassName=None):
"""Request that particular events be accepted from a platform API.
@@ -197,7 +200,8 @@ def requestEvents(eventName=None, processId=None,
windowClassName=None):
"""
if not eventName or not processId or not windowClassName:
raise ValueError("eventName, processId or windowClassName not
specified")
- _acceptEvents.add((eventName, processId, windowClassName))
+ app = appModuleHandler.getAppModuleFromProcessID(processId)
+ _acceptEvents[(eventName, processId, windowClassName)] = app

def shouldAcceptEvent(eventName, windowHandle=None):
"""Check whether an event should be accepted from a platform API.


https://bitbucket.org/nvdaaddonteam/nvda/commits/7a90d3108a5e/
Changeset: 7a90d3108a5e
Branch: None
User: jteh
Date: 2015-04-09 03:46:21+00:00
Summary: Document that eventHandler.requestEvents should generally be
called during plugin instantiation.

Affected #: 1 file

diff --git a/source/eventHandler.py b/source/eventHandler.py
index b1c6f30..8d6c909 100755
--- a/source/eventHandler.py
+++ b/source/eventHandler.py
@@ -196,6 +196,7 @@ def requestEvents(eventName=None, processId=None,
windowClassName=None):
to receive certain events even when in the background.
Note that NVDA may block some events at a lower level and doesn't
listen for some event types at all.
In these cases, you will not be able to override this.
+ This should generally be called when a plugin is instantiated.
All arguments must be provided.
"""
if not eventName or not processId or not windowClassName:


https://bitbucket.org/nvdaaddonteam/nvda/commits/f8c568ea7044/
Changeset: f8c568ea7044
Branch: None
User: jteh
Date: 2015-04-09 03:51:23+00:00
Summary: Merge branch 't3831' (early part) into next

This doesn't actually change anything, but is necessary to avoid merge
conflicts due to an ammended commit in t3831.

Affected #: 0 files



https://bitbucket.org/nvdaaddonteam/nvda/commits/0edc1a9c7e8e/
Changeset: 0edc1a9c7e8e
Branch: None
User: jteh
Date: 2015-04-09 03:52:08+00:00
Summary: Merge branch 't3831' into next

Incubates #3831.

Affected #: 1 file

diff --git a/source/eventHandler.py b/source/eventHandler.py
index 88be1a8..7f432b7 100755
--- a/source/eventHandler.py
+++ b/source/eventHandler.py
@@ -5,6 +5,7 @@
#Copyright (C) 2007-2014 NV Access Limited

import threading
+import weakref
import queueHandler
import api
import speech
@@ -181,8 +182,10 @@ def doPreDocumentLoadComplete(obj):

focusObject.treeInterceptor=treeInterceptorHandler.getTreeInterceptor(focusObject)
return True

-#: set of (eventName, processId, windowClassName) of events to accept.
-_acceptEvents = set()
+#: Collection of (eventName, processId, windowClassName) of events to accept.
+#: We use a WeakValueDictionary mapping events to AppModules so that
+#: entries get cleaned up automatically soon after their process dies.
+_acceptEvents = weakref.WeakValueDictionary()

def requestEvents(eventName=None, processId=None, windowClassName=None):
"""Request that particular events be accepted from a platform API.
@@ -193,11 +196,13 @@ def requestEvents(eventName=None, processId=None,
windowClassName=None):
to receive certain events even when in the background.
Note that NVDA may block some events at a lower level and doesn't
listen for some event types at all.
In these cases, you will not be able to override this.
+ This should generally be called when a plugin is instantiated.
All arguments must be provided.
"""
if not eventName or not processId or not windowClassName:
raise ValueError("eventName, processId or windowClassName not
specified")
- _acceptEvents.add((eventName, processId, windowClassName))
+ app = appModuleHandler.getAppModuleFromProcessID(processId)
+ _acceptEvents[(eventName, processId, windowClassName)] = app

def shouldAcceptEvent(eventName, windowHandle=None):
"""Check whether an event should be accepted from a platform API.


https://bitbucket.org/nvdaaddonteam/nvda/commits/83d70e4ce78e/
Changeset: 83d70e4ce78e
Branch: None
User: jteh
Date: 2015-04-09 07:21:55+00:00
Summary: winVersion: Make service pack code more readable. Use a tuple
instead of a list for product types.

Affected #: 1 file

diff --git a/source/winVersion.py b/source/winVersion.py
index f61fb0e..94e14bc 100644
--- a/source/winVersion.py
+++ b/source/winVersion.py
@@ -9,8 +9,11 @@ import winUser

winVersion=sys.getwindowsversion()
winVersionText="{v.major}.{v.minor}.{v.build}".format(v=winVersion)
-winVersionText+="" if winVersion.service_pack_major == 0 else (" service pack
%d"%winVersion.service_pack_major)+(".%d"%winVersion.service_pack_minor if
winVersion.service_pack_minor!=0 else "")
-winVersionText+=" %s" % ["workstation","domain
controller","server"][winVersion.product_type-1]
+if winVersion.service_pack_major!=0:
+ winVersionText+=" service pack %d"%winVersion.service_pack_major
+ if winVersion.service_pack_minor!=0:
+ winVersionText+=".%d"%winVersion.service_pack_minor
+winVersionText+=" %s" % ("workstation","domain
controller","server")[winVersion.product_type-1]

def canRunVc2010Builds():
if (winVersion.major, winVersion.minor) < (5, 1):


https://bitbucket.org/nvdaaddonteam/nvda/commits/4b9a9264a106/
Changeset: 4b9a9264a106
Branch: None
User: jteh
Date: 2015-04-09 07:22:33+00:00
Summary: Merge branch 't3724' into next

Incubates #3724.

Affected #: 8 files

diff --git a/source/NVDAObjects/window/edit.py
b/source/NVDAObjects/window/edit.py
index 92bbc67..477830f 100644
--- a/source/NVDAObjects/window/edit.py
+++ b/source/NVDAObjects/window/edit.py
@@ -4,7 +4,7 @@
#See the file COPYING for more details.

import locale
-import sys
+import winVersion
import comtypes.client
import struct
import ctypes
@@ -378,7 +378,7 @@ class EditTextInfo(textInfos.offsets.OffsetsTextInfo):
start=end

end=watchdog.cancellableSendMessage(self.obj.windowHandle,EM_FINDWORDBREAK,WB_MOVEWORDRIGHT,offset)
return (start,end)
- elif sys.getwindowsversion().major<6: #Implementation of
standard edit field wordbreak behaviour (only breaks on space)
+ elif winVersion.winVersion.major<6: #Implementation of standard
edit field wordbreak behaviour (only breaks on space)
lineStart,lineEnd=self._getLineOffsets(offset)
if offset>=lineEnd:
return offset,offset+1

diff --git a/source/UIAHandler.py b/source/UIAHandler.py
index 0978374..e4c7cb9 100644
--- a/source/UIAHandler.py
+++ b/source/UIAHandler.py
@@ -1,4 +1,4 @@
-import sys
+import winVersion
import comtypes
import config
from logHandler import log
@@ -7,8 +7,7 @@ handler=None
isUIAAvailable=False

if config.conf and config.conf["UIA"]["enabled"]:
- winver=sys.getwindowsversion()
- winver=winver.major+(winver.minor/10.0)
+ winver=winVersion.winVersion.major+(winVersion.winVersion.minor/10.0)
if winver>=config.conf["UIA"]["minWindowsVersion"]:
try:
from _UIAHandler import *

diff --git a/source/appModuleHandler.py b/source/appModuleHandler.py
index 847db71..209ac9e 100644
--- a/source/appModuleHandler.py
+++ b/source/appModuleHandler.py
@@ -16,6 +16,7 @@ import ctypes
import ctypes.wintypes
import os
import sys
+import winVersion
import pkgutil
import threading
import tempfile
@@ -300,7 +301,7 @@ class AppModule(baseObject.ScriptableObject):
#: The application name.
#: @type: str
self.appName=appName
- if sys.getwindowsversion().major > 5:
+ if winVersion.winVersion.major > 5:

self.processHandle=winKernel.openProcess(winKernel.SYNCHRONIZE|winKernel.PROCESS_QUERY_INFORMATION,False,processID)
else:

self.processHandle=winKernel.openProcess(winKernel.SYNCHRONIZE|winKernel.PROCESS_QUERY_INFORMATION|winKernel.PROCESS_VM_READ,False,processID)
@@ -314,7 +315,7 @@ class AppModule(baseObject.ScriptableObject):
if not self.processHandle:
raise RuntimeError("processHandle is 0")
# Choose the right function to use to get the executable file
name
- if sys.getwindowsversion().major > 5:
+ if winVersion.winVersion.major > 5:
# For Windows Vista and higher, use
QueryFullProcessImageName function
GetModuleFileName =
ctypes.windll.Kernel32.QueryFullProcessImageNameW
else:

diff --git a/source/core.py b/source/core.py
index 79aa249..c74f5b4 100644
--- a/source/core.py
+++ b/source/core.py
@@ -18,6 +18,7 @@ comtypes.gen.__path__.append(comInterfaces.__path__[0])
import comtypesMonkeyPatches

import sys
+import winVersion
import thread
import nvwave
import os
@@ -172,7 +173,7 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
log.warning("Could not set language to %s"%lang)
import versionInfo
log.info("NVDA version %s" % versionInfo.version)
- log.info("Using Windows version %r" % (sys.getwindowsversion(),))
+ log.info("Using Windows version %s" % winVersion.winVersionText)
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
# Set a reasonable timeout for any socket connections NVDA makes.

diff --git a/source/nvda_service.py b/source/nvda_service.py
index f9bad25..f670256 100644
--- a/source/nvda_service.py
+++ b/source/nvda_service.py
@@ -14,6 +14,7 @@ import os
import time
import subprocess
import _winreg
+import winVersion

CREATE_UNICODE_ENVIRONMENT=1024
INFINITE = 0xffffffff
@@ -311,7 +312,7 @@ class NVDAService(win32serviceutil.ServiceFramework):
def SvcDoRun(self):
initDebug()
debug("service starting")
- self.isWindowsXP = sys.getwindowsversion()[0:2] == (5, 1)
+ self.isWindowsXP = winVersion.winVersion[0:2] == (5, 1)
self.exitEvent = threading.Event()
self.initSession(windll.kernel32.WTSGetActiveConsoleSessionId())
self.exitEvent.wait()

diff --git a/source/touchHandler.py b/source/touchHandler.py
index 0abd66e..5cf3c79 100644
--- a/source/touchHandler.py
+++ b/source/touchHandler.py
@@ -9,7 +9,7 @@ import threading
from ctypes import *
from ctypes.wintypes import *
import re
-import sys
+import winVersion
import globalPluginHandler
import config
import winUser
@@ -275,8 +275,7 @@ def initialize():
if not config.isInstalledCopy():
log.debugWarning("Touch only supported on installed copies")
raise NotImplementedError
- version=sys.getwindowsversion()
- if (version.major*10+version.minor)<62:
+ if (winVersion.winVersion.major*10+winVersion.winVersion.minor)<62:
log.debugWarning("Touch only supported on Windows 8 and higher")
raise NotImplementedError
maxTouches=windll.user32.GetSystemMetrics(95) #maximum touches

diff --git a/source/updateCheck.py b/source/updateCheck.py
index 2a88500..80acdd3 100644
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -15,7 +15,7 @@ import versionInfo
if not versionInfo.updateVersionType:
raise RuntimeError("No update version type, update checking not
supported")

-import sys
+import winVersion
import os
import threading
import time
@@ -59,12 +59,11 @@ def checkForUpdate(auto=False):
@rtype: dict
@raise RuntimeError: If there is an error checking for an update.
"""
- winVer = sys.getwindowsversion()
params = {
"autoCheck": auto,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
- "osVersion": "{v.major}.{v.minor}.{v.build}
{v.service_pack}".format(v=winVer),
+ "osVersion": winVersion.winVersionText,
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
"language": languageHandler.getLanguage(),
"installed": config.isInstalledCopy(),

diff --git a/source/winVersion.py b/source/winVersion.py
index 69a6b27..94e14bc 100644
--- a/source/winVersion.py
+++ b/source/winVersion.py
@@ -7,18 +7,25 @@
import sys
import winUser

+winVersion=sys.getwindowsversion()
+winVersionText="{v.major}.{v.minor}.{v.build}".format(v=winVersion)
+if winVersion.service_pack_major!=0:
+ winVersionText+=" service pack %d"%winVersion.service_pack_major
+ if winVersion.service_pack_minor!=0:
+ winVersionText+=".%d"%winVersion.service_pack_minor
+winVersionText+=" %s" % ("workstation","domain
controller","server")[winVersion.product_type-1]
+
def canRunVc2010Builds():
- OSVersion=sys.getwindowsversion()
- if (OSVersion.major, OSVersion.minor) < (5, 1):
+ if (winVersion.major, winVersion.minor) < (5, 1):
# Earlier than Windows XP.
return False
- if OSVersion.major == 5:
- if OSVersion.minor == 1:
+ if winVersion.major == 5:
+ if winVersion.minor == 1:
# Windows XP for x86.
- return OSVersion.service_pack_major >= 2
- if OSVersion.minor == 2 and OSVersion.product_type!=1:
+ return winVersion.service_pack_major >= 2
+ if winVersion.minor == 2 and winVersion.product_type!=1:
# Windows Server 2003.
# (5.2 x64 is Windows XP x64. Its RTM is based on
Server 2003 sp1,
# so all versions should be fine.)
- return OSVersion.service_pack_major >= 1
+ return winVersion.service_pack_major >= 1
return True


https://bitbucket.org/nvdaaddonteam/nvda/commits/3c7b96817a8c/
Changeset: 3c7b96817a8c
Branch: None
User: jteh
Date: 2015-04-13 05:12:15+00:00
Summary: In Skype for Desktop 7.2 and later, typing notifications are now
reported and problems immediately after moving focus out of a conversation have
been fixed.

Skype 7.2 changed the typing notification control. Aside from the obvious, this
also caused an exception whenever a conversation lost focus.
Also, since Skype seem intent on changing things every couple of versions, if
the output list and/or typing indicator can't be found, log a warning and try
to handle this more gracefully.

Affected #: 1 file

diff --git a/source/appModules/skype.py b/source/appModules/skype.py
index 8573969..2c9ccbc 100644
--- a/source/appModules/skype.py
+++ b/source/appModules/skype.py
@@ -20,10 +20,16 @@ import queueHandler
import config
import NVDAObjects.behaviors
import api
+from logHandler import log

# Translators: The name of the NVDA command category for Skype specific
commands.
SCRCAT_SKYPE = _("Skype")

+TYPING_INDICATOR_MATCH = {
+ ("TTypingIndicatorPanel", controlTypes.ROLE_STATICTEXT),
+ ("TWidgetControl", controlTypes.ROLE_LISTITEM), # Skype <= 7.2
+}
+
class Conversation(NVDAObjects.IAccessible.IAccessible):
scriptCategory = SCRCAT_SKYPE

@@ -50,17 +56,22 @@ class Conversation(NVDAObjects.IAccessible.IAccessible):

windowUtils.findDescendantWindow(self.windowHandle,
className="TChatContentControl"),
winUser.OBJID_CLIENT, 0).lastChild
except LookupError:
- pass
+ log.debugWarning("Couldn't find output list")
+ self.outputList = None
else:
self.outputList.startMonitoring()
- try:
- self.typingIndicator =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
-
windowUtils.findDescendantWindow(self.windowHandle, className="TWidgetControl"),
- winUser.OBJID_CLIENT, 1)
- except LookupError:
- pass
- else:
+ for wClass, role in TYPING_INDICATOR_MATCH:
+ try:
+ self.typingIndicator =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
+
windowUtils.findDescendantWindow(self.windowHandle, className=wClass),
+ winUser.OBJID_CLIENT, 1)
+ except LookupError:
+ continue
self.typingIndicator.startMonitoring()
+ break
+ else:
+ log.debugWarning("Couldn't find typing indicator")
+ self.typingIndicator = None

def event_focusEntered(self):
self._gainedFocus()
@@ -74,10 +85,12 @@ class Conversation(NVDAObjects.IAccessible.IAccessible):

def lostFocus(self):
self.appModule.conversation = None
- self.outputList.stopMonitoring()
- self.outputList = None
- self.typingIndicator.stopMonitoring()
- self.typingIndicator = None
+ if self.outputList:
+ self.outputList.stopMonitoring()
+ self.outputList = None
+ if self.typingIndicator:
+ self.typingIndicator.stopMonitoring()
+ self.typingIndicator = None

def script_reviewRecentMessage(self, gesture):
try:
@@ -217,7 +230,7 @@ class AppModule(appModuleHandler.AppModule):
clsList.insert(0, ChatOutputList)
elif wClass == "TTrayAlert" and role ==
controlTypes.ROLE_WINDOW:
clsList.insert(0, Notification)
- elif wClass == "TWidgetControl" and role ==
controlTypes.ROLE_LISTITEM:
+ elif (wClass, role) in TYPING_INDICATOR_MATCH:
clsList.insert(0, TypingIndicator)

def event_gainFocus(self, obj, nextHandler):


https://bitbucket.org/nvdaaddonteam/nvda/commits/90583c7267d6/
Changeset: 90583c7267d6
Branch: None
User: jteh
Date: 2015-04-13 06:50:49+00:00
Summary: Merge branch 't4972' into next

Incubates #4972.

Affected #: 1 file

diff --git a/source/appModules/skype.py b/source/appModules/skype.py
index 8573969..2c9ccbc 100644
--- a/source/appModules/skype.py
+++ b/source/appModules/skype.py
@@ -20,10 +20,16 @@ import queueHandler
import config
import NVDAObjects.behaviors
import api
+from logHandler import log

# Translators: The name of the NVDA command category for Skype specific
commands.
SCRCAT_SKYPE = _("Skype")

+TYPING_INDICATOR_MATCH = {
+ ("TTypingIndicatorPanel", controlTypes.ROLE_STATICTEXT),
+ ("TWidgetControl", controlTypes.ROLE_LISTITEM), # Skype <= 7.2
+}
+
class Conversation(NVDAObjects.IAccessible.IAccessible):
scriptCategory = SCRCAT_SKYPE

@@ -50,17 +56,22 @@ class Conversation(NVDAObjects.IAccessible.IAccessible):

windowUtils.findDescendantWindow(self.windowHandle,
className="TChatContentControl"),
winUser.OBJID_CLIENT, 0).lastChild
except LookupError:
- pass
+ log.debugWarning("Couldn't find output list")
+ self.outputList = None
else:
self.outputList.startMonitoring()
- try:
- self.typingIndicator =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
-
windowUtils.findDescendantWindow(self.windowHandle, className="TWidgetControl"),
- winUser.OBJID_CLIENT, 1)
- except LookupError:
- pass
- else:
+ for wClass, role in TYPING_INDICATOR_MATCH:
+ try:
+ self.typingIndicator =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
+
windowUtils.findDescendantWindow(self.windowHandle, className=wClass),
+ winUser.OBJID_CLIENT, 1)
+ except LookupError:
+ continue
self.typingIndicator.startMonitoring()
+ break
+ else:
+ log.debugWarning("Couldn't find typing indicator")
+ self.typingIndicator = None

def event_focusEntered(self):
self._gainedFocus()
@@ -74,10 +85,12 @@ class Conversation(NVDAObjects.IAccessible.IAccessible):

def lostFocus(self):
self.appModule.conversation = None
- self.outputList.stopMonitoring()
- self.outputList = None
- self.typingIndicator.stopMonitoring()
- self.typingIndicator = None
+ if self.outputList:
+ self.outputList.stopMonitoring()
+ self.outputList = None
+ if self.typingIndicator:
+ self.typingIndicator.stopMonitoring()
+ self.typingIndicator = None

def script_reviewRecentMessage(self, gesture):
try:
@@ -217,7 +230,7 @@ class AppModule(appModuleHandler.AppModule):
clsList.insert(0, ChatOutputList)
elif wClass == "TTrayAlert" and role ==
controlTypes.ROLE_WINDOW:
clsList.insert(0, Notification)
- elif wClass == "TWidgetControl" and role ==
controlTypes.ROLE_LISTITEM:
+ elif (wClass, role) in TYPING_INDICATOR_MATCH:
clsList.insert(0, TypingIndicator)

def event_gainFocus(self, obj, nextHandler):


https://bitbucket.org/nvdaaddonteam/nvda/commits/dc92f310f686/
Changeset: dc92f310f686
Branch: None
User: mdcurran
Date: 2015-04-14 00:24:18+00:00
Summary: Merge branch 't1987' into next. Incubates #1987

Affected #: 1 file

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index d5ba5df..6c8da2c 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -297,7 +297,7 @@ class ElementsListDialog(browseMode.ElementsListDialog):
("chart", _("&Chart")),
# Translators: The label of a radio button to select the type
of element
# in the browse mode Elements List dialog.
- ("comment", _("&Comment")),
+ ("comment", _("C&omment")),
# Translators: The label of a radio button to select the type
of element
# in the browse mode Elements List dialog.
("formula", _("&Formula")),


https://bitbucket.org/nvdaaddonteam/nvda/commits/ffc160a7cb97/
Changeset: ffc160a7cb97
Branch: None
User: jteh
Date: 2015-04-14 06:10:16+00:00
Summary: Remove STATE_OBSCURING, which is no longer needed.

Affected #: 1 file

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 1740780..e543fa3 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -187,9 +187,8 @@ STATE_PINNED=0x800000000
STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
-STATE_OBSCURING=0x8000000000
-STATE_CROPPED=0x10000000000
-STATE_OVERFLOWING=0X20000000000
+STATE_CROPPED=0x8000000000
+STATE_OVERFLOWING=0x10000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -552,8 +551,6 @@ stateLabels={
STATE_HASCOMMENT:_("has comment"),
# Translators: a state that denotes that the object is covered
partially or fully by another object
STATE_OBSCURED:_("obscured"),
- # Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
- STATE_OBSCURING:_("obscuring"),
# Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
STATE_CROPPED:_("cropped"),
# Translators: a state that denotes that the object(text) is
overflowing into the adjacent space


https://bitbucket.org/nvdaaddonteam/nvda/commits/ebc37ebf7c77/
Changeset: ebc37ebf7c77
Branch: None
User: jteh
Date: 2015-04-14 06:10:34+00:00
Summary: Merge branch 't3040' into next

Affected #: 1 file

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 1740780..e543fa3 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -187,9 +187,8 @@ STATE_PINNED=0x800000000
STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
-STATE_OBSCURING=0x8000000000
-STATE_CROPPED=0x10000000000
-STATE_OVERFLOWING=0X20000000000
+STATE_CROPPED=0x8000000000
+STATE_OVERFLOWING=0x10000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -552,8 +551,6 @@ stateLabels={
STATE_HASCOMMENT:_("has comment"),
# Translators: a state that denotes that the object is covered
partially or fully by another object
STATE_OBSCURED:_("obscured"),
- # Translators: a state that denotes that the object is overlapping onto
adjacent object(s)
- STATE_OBSCURING:_("obscuring"),
# Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
STATE_CROPPED:_("cropped"),
# Translators: a state that denotes that the object(text) is
overflowing into the adjacent space


https://bitbucket.org/nvdaaddonteam/nvda/commits/a6522e61e0e9/
Changeset: a6522e61e0e9
Branch: None
User: jteh
Date: 2015-04-14 06:37:41+00:00
Summary: Merge branch 'master' into next

Affected #: 4 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 6c8da2c..7fab72d 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -29,7 +29,6 @@ from .. import NVDAObjectTextInfo
import scriptHandler
import ctypes
import browseMode
-

xlCenter=-4108
xlJustify=-4130

diff --git a/source/browseMode.py b/source/browseMode.py
index 8f5e09d..a071c1e 100644
--- a/source/browseMode.py
+++ b/source/browseMode.py
@@ -235,8 +235,8 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
d.Destroy()
gui.mainFrame.postPopup()
wx.CallAfter(run)
- # Translators: the description for the elements list dialog script on
virtualBuffers.
- script_elementsList.__doc__ = _("Presents a list of links, headings or
landmarks")
+ # Translators: the description for the Elements List command in browse
mode.
+ script_elementsList.__doc__ = _("Lists various types of elements in
this document")

def _activatePosition(self,info):
info.activate()

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 099f5a5..a760c6e 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -8,11 +8,13 @@
== New Features ==
- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
- New braille translation tables for several Indian languages. (#4778)
+- In Microsoft Excel, NVDA now reports when a cell has overflowing or cropped
content. (#3040)


== Changes ==
- In NVDA's Document Formatting dialog, the keyboard shortcuts for Report
lists, Report links, Report line numbers and Report font name have been
changed. (#4650)
- In NVDA's Mouse Settings dialog, keyboard shortcuts have been added for play
audio coordinates when mouse moves and brightness controls audio coordinates
volume. (#4916)
+- Significantly improved reporting of color names. (#4984)


== Bug Fixes ==

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 426f460..64ccc2b 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -442,7 +442,7 @@ Although a physical mouse or trackpad should be used to
navigate with the mouse,

+ Browse Mode +
Complex read-only documents such as web pages are browsed in NVDA using browse
mode.
-This includes documents in Mozilla Firefox, Microsoft Internet Explorer, HTML
messages in Microsoft Outlook, Google Chrome, Adobe Reader and Adobe Flash.
+This includes documents in Mozilla Firefox, Microsoft Internet Explorer,
Mozilla Thunderbird, HTML messages in Microsoft Outlook, Google Chrome, Adobe
Reader and Adobe Flash.
Browse mode is also optionally available for Microsoft Word documents.

In browse mode, the content of the document is made available in a flat
representation that can be navigated with the cursor keys as if it were a
normal text document.
@@ -497,6 +497,7 @@ The following keys by themselves jump to the next available
element, while addin
- d: landmark
- o: embedded object
- 1 to 6: headings at levels 1 to 6 respectively
+- a: annotation (comment, editor revision, etc.)
-
To move to the beginning or end of containing elements such as lists and
tables:
|| Name | Key | Description |
@@ -505,13 +506,14 @@ To move to the beginning or end of containing elements
such as lists and tables:
%kc:endInclude

++ The Elements List ++
-The elements list provides access to a list of either links, headings or
landmarks in the document.
-Radio buttons allow you to switch between these three types of information.
+The elements list provides access to a list of various types of elements in
the document as appropriate for the application.
+For example, in web browsers, the elements list can list links, headings or
landmarks.
+Radio buttons allow you to switch between the different types of elements.
An edit field is also provided in the dialog which allows you to filter the
list to help you search for a particular item on the page.
Once you have chosen an item, you can use the provided buttons in the dialog
to move to or activate that item.
%kc:beginInclude
|| Name | Key | Description |
-| Browse mode elements list | NVDA+f7 | Brings up the Elements list which
contains links, headings and landmarks from the current document |
+| Browse mode elements list | NVDA+f7 | Lists various types of elements in the
current document |
%kc:endInclude

++ Embedded Objects ++


https://bitbucket.org/nvdaaddonteam/nvda/commits/32e4b8fed066/
Changeset: 32e4b8fed066
Branch: None
User: jteh
Date: 2015-04-14 06:40:24+00:00
Summary: Merge branch 'master' into next

Affected #: 2 files

diff --git a/source/NVDAObjects/IAccessible/msOffice.py
b/source/NVDAObjects/IAccessible/msOffice.py
index f08061d..a96fac3 100755
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -132,7 +132,7 @@ class CommandBarListItem(IAccessible):
import colors
rgb=colors.RGB.fromString(name)
# Translators: a color, broken down into its RGB red,
green, blue parts.
- return _("RGB red {rgb.red}, green {rgb.green} and blue
{rgb.blue}").format(rgb=colors.RGB.fromString(name))
+ return _("RGB red {rgb.red}, green {rgb.green}, blue
{rgb.blue}").format(rgb=colors.RGB.fromString(name))
else:
return super(CommandBarListItem,self).description


diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index a760c6e..ac778e3 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -21,6 +21,7 @@
- Character descriptions are now handled correctly for conjunct characters in
certain Indian languages. (#4582)
- If the "Trust voice's language when processing characters and symbols"
option is enabled, the Punctuation/Symbol pronunciation dialog now correctly
uses the voice language. Also, the language for which pronunciation is being
edited is shown in the dialog's title. (#4930)
-In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)
+- When selecting colors in Microsoft Office applications, color names are now
reported. (#3045)


== Changes for Developers ==


https://bitbucket.org/nvdaaddonteam/nvda/commits/f380a32da833/
Changeset: f380a32da833
Branch: None
User: jteh
Date: 2015-04-15 04:43:37+00:00
Summary: User Guide: Provide link to download MathPlayer.

Affected #: 1 file

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index d5173b2..b42a691 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -525,6 +525,8 @@ A key command is provided to return to the original page
containing the embedded
+ Reading Mathematical Content +
Using MathPlayer 4 from Design Science, NVDA can read and interactively
navigate supported mathematical content.
This requires that MathPlayer 4 is installed on the computer.
+MathPlayer is available as a free download from:
http://www.dessci.com/en/products/mathplayer/
+
NVDA supports the following types of mathematical content:
- MathML in Mozilla Firefox and Microsoft Internet Explorer.
- Design Science MathType in Microsoft Word and PowerPoint.


https://bitbucket.org/nvdaaddonteam/nvda/commits/aaf3e7117e2a/
Changeset: aaf3e7117e2a
Branch: None
User: jteh
Date: 2015-04-15 06:17:38+00:00
Summary: Mozilla MathML support: Don't return invalid MathML markup if an
element has no data-mathml attribute, is not a math tag but has ARIA
role="math"; e.g. MathJax output.

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/mozilla.py
b/source/NVDAObjects/IAccessible/mozilla.py
index 4a79e12..8676ab5 100755
--- a/source/NVDAObjects/IAccessible/mozilla.py
+++ b/source/NVDAObjects/IAccessible/mozilla.py
@@ -184,7 +184,9 @@ class Math(Mozilla):
if not mathPres.getLanguageFromMath(attr) and
self.language:
attr = mathPres.insertLanguageIntoMath(attr,
self.language)
return attr
- # Assume the content is MathML.
+ if self.IA2Attributes.get("tag") != "math":
+ # This isn't MathML.
+ raise LookupError
if self.language:
attrs = ' xml:lang="%s"' % self.language
else:


https://bitbucket.org/nvdaaddonteam/nvda/commits/ae15aac8f27e/
Changeset: ae15aac8f27e
Branch: None
User: jteh
Date: 2015-04-17 03:47:16+00:00
Summary: Don't prefix math with "math" when it is encountered in text, as
this is often redundant and is overly verbose for short, inline math.

This is controversial, as you can't be certain whether something is real math
or not, but this is probably usually obvious from context. There have been
several requests for this, so let's see how it goes; it can always be reverted.

Affected #: 2 files

diff --git a/source/braille.py b/source/braille.py
index 92aec0f..0e33898 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -603,7 +603,11 @@ def getControlFieldBraille(info, field, ancestors,
reportStart, formatConfig):
return getBrailleTextForProperties(**props)

elif reportStart:
- props = {"role": role, "states": states,"value":value}
+ props = {
+ # Don't report the role for math here.
+ # However, we still need to pass it (hence "_role").
+ "_role" if role == controlTypes.ROLE_MATH else "role":
role,
+ "states": states,"value":value}
if config.conf["presentation"]["reportKeyboardShortcuts"]:
kbShortcut = field.get("keyboardShortcut")
if kbShortcut:
@@ -617,7 +621,9 @@ def getControlFieldBraille(info, field, ancestors,
reportStart, formatConfig):
mathPres.ensureInit()
if mathPres.brailleProvider:
try:
- text += " " +
mathPres.brailleProvider.getBrailleForMathMl(
+ if text:
+ text += " "
+ text +=
mathPres.brailleProvider.getBrailleForMathMl(
info.getMathMl(field))
except (NotImplementedError, LookupError):
pass

diff --git a/source/speech.py b/source/speech.py
index 856c708..80dd8b9 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -714,8 +714,9 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
if text:
speechSequence.append(text)
isTextBlank=False
- if field.get("role")==controlTypes.ROLE_MATH:
-
_speakTextInfo_addMath(speechSequence,info,field)
+ if field.get("role")==controlTypes.ROLE_MATH:
+ isTextBlank=False
+
_speakTextInfo_addMath(speechSequence,info,field)

#Get speech text for any fields in the new controlFieldStack that are
not in the old controlFieldStack
for count in xrange(commonFieldCount,len(newControlFieldStack)):
@@ -724,8 +725,9 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
if text:
speechSequence.append(text)
isTextBlank=False
- if field.get("role")==controlTypes.ROLE_MATH:
-
_speakTextInfo_addMath(speechSequence,info,field)
+ if field.get("role")==controlTypes.ROLE_MATH:
+ isTextBlank=False
+ _speakTextInfo_addMath(speechSequence,info,field)
commonFieldCount+=1

#Fetch the text for format field attributes that have changed between
what was previously cached, and this textInfo's initialFormatField.
@@ -802,8 +804,8 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT

relativeSpeechSequence.append(LangChangeCommand(None))
lastLanguage=None
relativeSpeechSequence.append(fieldText)
- if command.command=="controlStart" and
command.field.get("role")==controlTypes.ROLE_MATH:
-
_speakTextInfo_addMath(relativeSpeechSequence,info,command.field)
+ if command.command=="controlStart" and
command.field.get("role")==controlTypes.ROLE_MATH:
+
_speakTextInfo_addMath(relativeSpeechSequence,info,command.field)
if autoLanguageSwitching and
newLanguage!=lastLanguage:

relativeSpeechSequence.append(LangChangeCommand(newLanguage))
lastLanguage=newLanguage
@@ -876,7 +878,7 @@ def
getSpeechTextForProperties(reason=controlTypes.REASON_QUERY,**propertyValues
rowNumber=propertyValues.get('rowNumber')
columnNumber=propertyValues.get('columnNumber')
includeTableCellCoords=propertyValues.get('includeTableCellCoords',True)
- if speakRole and (reason not in
(controlTypes.REASON_SAYALL,controlTypes.REASON_CARET,controlTypes.REASON_FOCUS)
or not (name or value or cellCoordsText or rowNumber or columnNumber) or role
not in controlTypes.silentRolesOnFocus):
+ if speakRole and (reason not in
(controlTypes.REASON_SAYALL,controlTypes.REASON_CARET,controlTypes.REASON_FOCUS)
or not (name or value or cellCoordsText or rowNumber or columnNumber) or role
not in controlTypes.silentRolesOnFocus) and (role!=controlTypes.ROLE_MATH or
reason not in (controlTypes.REASON_CARET,controlTypes.REASON_SAYALL)):
textList.append(controlTypes.roleLabels[role])
if value:
textList.append(value)


https://bitbucket.org/nvdaaddonteam/nvda/commits/fdf3abc1664c/
Changeset: fdf3abc1664c
Branch: None
User: jteh
Date: 2015-04-17 03:58:04+00:00
Summary: Merge branch 'master' into t4673

Affected #: 188 files

diff --git a/contributors.txt b/contributors.txt
index 6b1212a..c2256f0 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -162,3 +162,7 @@ Niklas Johansson
Dinesh Mittal
Maheshinder Singh Khosla
Zvonimir Stanecic
+Tyler Spivey
+Siddhartha Gupta
+Siddharth
+Aleksandr Lin'kov

diff --git a/include/espeak b/include/espeak
index 0511bfb..2145b25 160000
--- a/include/espeak
+++ b/include/espeak
@@ -1 +1 @@
-Subproject commit 0511bfb820ba6726b4baee1b32e3a2b2577a3247
+Subproject commit 2145b258f483ba3b3665356f24a7b6b7bb96a9df

diff --git a/nvdaHelper/remote/ia2LiveRegions.cpp
b/nvdaHelper/remote/ia2LiveRegions.cpp
index df389fe..970c8ef 100644
--- a/nvdaHelper/remote/ia2LiveRegions.cpp
+++ b/nvdaHelper/remote/ia2LiveRegions.cpp
@@ -261,7 +261,11 @@ 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);
}
- attribsMap.clear();
+ // We only support additions or text
+ if(!allowAdditions&&!allowText) {
+ pacc2->Release();
+ return;
+ }
//Only handle show events if additions are allowed
if(eventID==EVENT_OBJECT_SHOW&&!allowAdditions) {
pacc2->Release();
@@ -286,9 +290,10 @@ void CALLBACK winEventProcHook(HWINEVENTHOOK hookID, DWORD
eventID, HWND hwnd, l
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))
{
+ map<wstring,wstring> parentAttribsMap;
+
if(fetchIA2Attributes(pacc2Parent,parentAttribsMap)) {
+
i=parentAttribsMap.find(L"container-live");
+
if(i!=parentAttribsMap.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;
}

diff --git a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
index db1dd94..3db4129 100755
--- a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
@@ -473,8 +473,8 @@ inline void getAttributesFromHTMLDOMNode(IHTMLDOMNode*
pHTMLDOMNode,wstring& nod

macro_addHTMLAttributeToMap(L"role",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);

macro_addHTMLAttributeToMap(L"aria-valuenow",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);

macro_addHTMLAttributeToMap(L"aria-sort",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
-
macro_addHTMLAttributeToMap(L"aria-labelledBy",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
-
macro_addHTMLAttributeToMap(L"aria-describedBy",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
+
macro_addHTMLAttributeToMap(L"aria-labelledby",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
+
macro_addHTMLAttributeToMap(L"aria-describedby",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);

macro_addHTMLAttributeToMap(L"aria-expanded",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);

macro_addHTMLAttributeToMap(L"aria-selected",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);

macro_addHTMLAttributeToMap(L"aria-level",false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
@@ -862,7 +862,8 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf

language=static_cast<MshtmlVBufStorage_controlFieldNode_t*>(parentNode)->language;
}

- VBufStorage_controlFieldNode_t* node=new
MshtmlVBufStorage_controlFieldNode_t(docHandle,ID,isBlock,this,pHTMLDOMNode,language);
+ bool isDocRoot=!parentNode&&(!oldNode||!oldNode->getParent());
+ VBufStorage_controlFieldNode_t* node=new
MshtmlVBufStorage_controlFieldNode_t(docHandle,ID,isBlock,this,isDocRoot,pHTMLDOMNode,language);

((MshtmlVBufStorage_controlFieldNode_t*)node)->preProcessLiveRegion((MshtmlVBufStorage_controlFieldNode_t*)(oldNode?oldNode->getParent():parentNode),attribsMap);
bool wasInNewSubtree=inNewSubtree;
if(!wasInNewSubtree&&!oldNode) {
@@ -1066,12 +1067,6 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf
if(contentString.empty()) {
contentString=L" ";
}
- } else if(nodeName.compare(L"BUTTON")==0) {
- if(!IAName.empty()) {
- contentString=IAName;
- } else {
- contentString=L" ";
- }
} else if(nodeName.compare(L"SELECT")==0) {
if(!IAValue.empty()) {
contentString=IAValue;
@@ -1183,7 +1178,7 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf
}

//A node who's rendered children produces no content, or only a
small amount of whitespace should render its title or URL
- if(!nodeHasUsefulContent(parentNode)) {
+ if(!hidden&&!nodeHasUsefulContent(parentNode)) {
contentString=L"";
if(!IAName.empty()) {
contentString=IAName;

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index d368f59..e8a3adc 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -272,10 +272,11 @@ class CHTMLChangeSink : public IHTMLChangeSink {

};

-MshtmlVBufStorage_controlFieldNode_t::MshtmlVBufStorage_controlFieldNode_t(int
docHandle, int ID, bool isBlock, MshtmlVBufBackend_t* backend, IHTMLDOMNode*
pHTMLDOMNode,const wstring& lang):
VBufStorage_controlFieldNode_t(docHandle,ID,isBlock), language(lang) {
+MshtmlVBufStorage_controlFieldNode_t::MshtmlVBufStorage_controlFieldNode_t(int
docHandle, int ID, bool isBlock, MshtmlVBufBackend_t* backend, bool isRootNode,
IHTMLDOMNode* pHTMLDOMNode,const wstring& lang):
VBufStorage_controlFieldNode_t(docHandle,ID,isBlock), language(lang) {
nhAssert(backend);
nhAssert(pHTMLDOMNode);
this->backend=backend;
+ this->isRootNode=isRootNode;
pHTMLDOMNode->AddRef();
this->pHTMLDOMNode=pHTMLDOMNode;
this->propChangeSink=NULL;
@@ -290,7 +291,7 @@
MshtmlVBufStorage_controlFieldNode_t::MshtmlVBufStorage_controlFieldNode_t(int d
} else {
propChangeSink->Release();
}
-
if(nodeName!=NULL&&(_wcsicmp(nodeName,L"body")==0||_wcsicmp(nodeName,L"frameset")==0))
{
+
if(this->isRootNode||(nodeName!=NULL&&(_wcsicmp(nodeName,L"body")==0||_wcsicmp(nodeName,L"frameset")==0)))
{
IHTMLDOMNode2* pHTMLDOMNode2=NULL;

pHTMLDOMNode->QueryInterface(IID_IHTMLDOMNode2,(void**)&pHTMLDOMNode2);
if(pHTMLDOMNode2) {
@@ -355,8 +356,13 @@ void
MshtmlVBufStorage_controlFieldNode_t::preProcessLiveRegion(const MshtmlVBuf
}
i=attribsMap.find(L"HTMLAttrib::aria-relevant");
if(i!=attribsMap.end()&&!i->second.empty()) {
-
this->ariaLiveIsTextRelevant=i->second.find(L"text")!=wstring::npos;
-
this->ariaLiveIsAdditionsRelevant=i->second.find(L"additions")!=wstring::npos;
+ if(i->second.compare(L"all")==0) {
+ this->ariaLiveIsTextRelevant=true;
+ this->ariaLiveIsAdditionsRelevant=true;
+ } else {
+
this->ariaLiveIsTextRelevant=i->second.find(L"text")!=wstring::npos;
+
this->ariaLiveIsAdditionsRelevant=i->second.find(L"additions")!=wstring::npos;
+ }
} else {

this->ariaLiveIsTextRelevant=parent?parent->ariaLiveIsTextRelevant:true;

this->ariaLiveIsAdditionsRelevant=parent?parent->ariaLiveIsAdditionsRelevant:true;
@@ -405,26 +411,52 @@ void
MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_con
bool
reportNode=!oldNode&&this->ariaLiveIsAdditionsRelevant&&this->ariaLiveNode!=this;
wstring newChildrenText;
if(!reportNode&&oldNode&&ariaLiveIsTextRelevant) {
- wstring oldChildrenText;
- for(VBufStorage_fieldNode_t*
tempNode=oldNode->getFirstChild();tempNode;tempNode=tempNode->getNext()) {
- int length=tempNode->getLength();
- if(!tempNode->getFirstChild()&&length>0) {
-
tempNode->getTextInRange(0,length,oldChildrenText,false);
- oldChildrenText+=L' ';
+ // Find the first new text child
+ VBufStorage_fieldNode_t* newStart=this->getFirstChild();
+ VBufStorage_fieldNode_t* oldStart=oldNode->getFirstChild();
+ while(newStart&&oldStart) {
+ if(newStart->getLength()==0||newStart->getFirstChild())
{
+ newStart=newStart->getNext();
+ continue;
+ }
+ if(oldStart->getLength()==0||oldStart->getFirstChild())
{
+ oldStart=oldStart->getNext();
+ continue;
+ }
+
if(((VBufStorage_textFieldNode_t*)oldStart)->text.compare(((VBufStorage_textFieldNode_t*)newStart)->text)!=0)
{
+ break;
}
+ oldStart=oldStart->getNext();
+ newStart=newStart->getNext();
}
- for(VBufStorage_fieldNode_t*
tempNode=this->getFirstChild();tempNode;tempNode=tempNode->getNext()) {
- int length=tempNode->getLength();
- if(!tempNode->getFirstChild()&&length>0) {
-
tempNode->getTextInRange(0,length,newChildrenText,false);
- newChildrenText+=L' ';
+ // Find the last new text child
+ VBufStorage_fieldNode_t* newEnd=this->getLastChild();
+ VBufStorage_fieldNode_t* oldEnd=oldNode->getLastChild();
+ while(newEnd&&oldEnd) {
+ if(newEnd->getLength()==0||newEnd->getLastChild()) {
+ newEnd=newEnd->getPrevious();
+ continue;
}
+ if(oldEnd->getLength()==0||oldEnd->getLastChild()) {
+ oldEnd=oldEnd->getPrevious();
+ continue;
+ }
+
if(((VBufStorage_textFieldNode_t*)oldEnd)->text.compare(((VBufStorage_textFieldNode_t*)newEnd)->text)!=0)
{
+ break;
+ }
+ oldEnd=oldEnd->getPrevious();
+ newEnd=newEnd->getPrevious();
}
- if(newChildrenText.compare(oldChildrenText)==0) {
- newChildrenText=L"";
+ // Collect all the text between the first and last new text
children.
+ while(newStart) {
+ if(newStart->getLength()>0&&!newStart->getFirstChild())
{
+
newStart->getTextInRange(0,newStart->getLength(),newChildrenText,false);
+ }
+ if(newStart==newEnd) break;
+ newStart=newStart->getNext();
}
}
- if(!reportNode&&newChildrenText.empty()) return;
+ if(!reportNode&&newChildrenText.empty()) return;
if(this->ariaLiveAtomicNode) {
atomicNodes.insert(this->ariaLiveAtomicNode);
newChildrenText=L"";

diff --git a/nvdaHelper/vbufBackends/mshtml/node.h
b/nvdaHelper/vbufBackends/mshtml/node.h
index 63e5527..0d9a8e3 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.h
+++ b/nvdaHelper/vbufBackends/mshtml/node.h
@@ -41,7 +41,8 @@ class MshtmlVBufStorage_controlFieldNode_t : public
VBufStorage_controlFieldNode
void preProcessLiveRegion(const MshtmlVBufStorage_controlFieldNode_t*
parent, const std::map<std::wstring,std::wstring>& attribsMap);
void postProcessLiveRegion(VBufStorage_controlFieldNode_t* oldNode,
std::set<VBufStorage_controlFieldNode_t*>& atomicNodes);
virtual void generateAttributesForMarkupOpeningTag(std::wstring& text,
int startOffset, int endOffset);
- MshtmlVBufStorage_controlFieldNode_t(int docHandle, int ID, bool
isBlock, MshtmlVBufBackend_t* backend, IHTMLDOMNode* pHTMLDOMNode, const
std::wstring& lang);
+ bool isRootNode;
+ MshtmlVBufStorage_controlFieldNode_t(int docHandle, int ID, bool
isBlock, MshtmlVBufBackend_t* backend, bool isRootNode, IHTMLDOMNode*
pHTMLDOMNode, const std::wstring& lang);
~MshtmlVBufStorage_controlFieldNode_t();

};

diff --git a/nvdaHelper/vbufBase/storage.h b/nvdaHelper/vbufBase/storage.h
index 795d9f4..99431e9 100644
--- a/nvdaHelper/vbufBase/storage.h
+++ b/nvdaHelper/vbufBase/storage.h
@@ -351,11 +351,6 @@ class VBufStorage_controlFieldNode_t : public
VBufStorage_fieldNode_t {
class VBufStorage_textFieldNode_t : public VBufStorage_fieldNode_t {
protected:

-/**
- * The text this field contains.
- */
- std::wstring text;
-
virtual VBufStorage_textFieldNode_t*locateTextFieldNodeAtOffset(int
offset, int *relativeOffset);

virtual void generateMarkupTagName(std::wstring& text);
@@ -372,6 +367,11 @@ class VBufStorage_textFieldNode_t : public
VBufStorage_fieldNode_t {

public:

+ /**
+ * The text this field contains.
+ */
+ const std::wstring text;
+
virtual std::wstring getDebugInfo() const;

};

diff --git a/nvdaHelper/vbufBase/utils.cpp b/nvdaHelper/vbufBase/utils.cpp
index 25a1bce..6ceaa63 100644
--- a/nvdaHelper/vbufBase/utils.cpp
+++ b/nvdaHelper/vbufBase/utils.cpp
@@ -27,6 +27,10 @@ wstring getNameForURL(const wstring &url) {
wstring::size_type colonPos = url.find(L':');
if (colonPos != wstring::npos && url.compare(colonPos, 3, L"://") != 0)
{
// This URL specifies a protocol, but it is not a path-based
protocol; e.g. it is a javascript: or mailto: URL.
+ wstring imgCheck = url.substr(0, 11);
+ transform(imgCheck.begin(), imgCheck.end(), imgCheck.begin(),
tolower);
+ if (imgCheck.compare(0, 11, L"data:image/") == 0)
+ return L""; // This URL is not useful.
// Return the URL as is with the protocol stripped.
return url.substr(colonPos + 1);
}

diff --git a/readme.txt b/readme.txt
index b69fc0b..f05e408 100644
--- a/readme.txt
+++ b/readme.txt
@@ -24,7 +24,7 @@ The following dependencies are included in Git submodules:
* comtypes, version 0.6.2: http://sourceforge.net/projects/comtypes/
* wxPython, version 3.0.2.0: http://www.wxpython.org/
* Python Windows Extensions, build 218:
http://sourceforge.net/projects/pywin32/
-* eSpeak, version 1.48.03: http://espeak.sourceforge.net/
+* eSpeak, version 1.48.04: http://espeak.sourceforge.net/
* IAccessible2, version 1.3:
http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2
* ConfigObj, version 4.6.0: http://www.voidspace.org.uk/python/configobj.html
* liblouis, version 2.6.0: http://www.liblouis.org/

diff --git a/source/IAccessibleHandler.py b/source/IAccessibleHandler.py
index a5ce5c2..92d88e9 100644
--- a/source/IAccessibleHandler.py
+++ b/source/IAccessibleHandler.py
@@ -752,8 +752,9 @@ def processForegroundWinEvent(window,objectID,childID):

def processShowWinEvent(window,objectID,childID):
className=winUser.getClassName(window)
- #For now we only support 'show' event for tooltips, IMM candidates and
notification bars as otherwize we get flooded
- if className in ("Frame Notification
Bar","tooltips_class32","mscandui21.candidate","mscandui40.candidate","MSCandUIWindow_Candidate")
and objectID==winUser.OBJID_CLIENT:
+ #For now we only support 'show' event for tooltips, IMM candidates,
notification bars and other specific notification area alerts as otherwize we
get flooded
+ # #4741: TTrayAlert is for Skype.
+ if className in ("Frame Notification
Bar","tooltips_class32","mscandui21.candidate","mscandui40.candidate","MSCandUIWindow_Candidate","TTrayAlert")
and objectID==winUser.OBJID_CLIENT:

NVDAEvent=winEventToNVDAEvent(winUser.EVENT_OBJECT_SHOW,window,objectID,childID)
if NVDAEvent:
eventHandler.queueEvent(*NVDAEvent)

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index aed0dba..fe2c8cc 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -550,12 +550,18 @@ class MSHTML(IAccessible):
ariaRole=self.HTMLAttributes['aria-role']
if ariaRole=="gridcell":
return True
- return super(MSHTML,self).shouldAllowIAccessibleFocusEvent
+ res=super(MSHTML,self).shouldAllowIAccessibleFocusEvent
+ if not res:
+ # #4667: Internet Explorer 11 correctly fires focus
events for aria-activeDescendant, but fails to set the focused state.
+ # Therefore check aria-activeDescendant manually and
let the focus events through in this case.
+ activeElement=self.HTMLNode.document.activeElement
+ if activeElement:
+
activeID=activeElement.getAttribute('aria-activedescendant')
+ if activeID and activeID==self.HTMLNode.ID:
+ res=True
+ return res

def _get_name(self):
- ariaLabel=self.HTMLAttributes['aria-label']
- if ariaLabel:
- return ariaLabel
ariaLabelledBy=self.HTMLAttributes['aria-labelledBy']
if ariaLabelledBy:
try:
@@ -567,24 +573,27 @@ class MSHTML(IAccessible):
return labelNode.innerText
except (COMError,NameError):
pass
- title=self.HTMLAttributes['title']
- # #2121: MSHTML sometimes returns a node for the title
attribute.
- # This doesn't make any sense, so ignore it.
- if title and isinstance(title,basestring):
- return title
+ ariaLabel=self.HTMLAttributes['aria-label']
+ if ariaLabel:
+ return ariaLabel
if self.IAccessibleRole==oleacc.ROLE_SYSTEM_TABLE:
summary=self.HTMLAttributes['summary']
if summary:
return summary
- if self.HTMLNodeHasAncestorIAccessible:
- return ""
- #IE inappropriately generates the name from descendants on some
controls
- if self.IAccessibleRole in
(oleacc.ROLE_SYSTEM_MENUBAR,oleacc.ROLE_SYSTEM_TOOLBAR,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_TABLE,oleacc.ROLE_SYSTEM_DOCUMENT):
- return ""
- #Adding an ARIA landmark or unknown role to a DIV node makes an
IAccessible with role_system_grouping and a name calculated from descendants.
- # This name should also be ignored, but check NVDA's role, not
accRole as its possible that NVDA chose a better role
- # E.g. row (#2780)
- if self.HTMLNodeName=="DIV" and
self.role==controlTypes.ROLE_GROUPING:
+ if (
+ self.HTMLNodeHasAncestorIAccessible or
+ #IE inappropriately generates the name from descendants
on some controls
+ self.IAccessibleRole in
(oleacc.ROLE_SYSTEM_MENUBAR,oleacc.ROLE_SYSTEM_TOOLBAR,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_TABLE,oleacc.ROLE_SYSTEM_DOCUMENT)
or
+ #Adding an ARIA landmark or unknown role to a DIV or
NAV node makes an IAccessible with role_system_grouping and a name calculated
from descendants.
+ # This name should also be ignored, but check NVDA's
role, not accRole as its possible that NVDA chose a better role
+ # E.g. row (#2780)
+ (self.HTMLNodeName in ("DIV","NAV") and
self.role==controlTypes.ROLE_GROUPING)
+ ):
+ title=self.HTMLAttributes['title']
+ # #2121: MSHTML sometimes returns a node for the title
attribute.
+ # This doesn't make any sense, so ignore it.
+ if title and isinstance(title,basestring):
+ return title
return ""
return super(MSHTML,self).name

@@ -596,7 +605,8 @@ class MSHTML(IAccessible):
value=""
return value
IARole=self.IAccessibleRole
- if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT):
+ # value is not useful on certain nodes that just expose a URL,
or they have other ways of getting their content (#4976 - editble combos).
+ if IARole in (oleacc.ROLE_SYSTEM_PANE,oleacc.ROLE_SYSTEM_TEXT)
or (IARole==oleacc.ROLE_SYSTEM_COMBOBOX and controlTypes.STATE_EDITABLE in
self.states):
return ""
else:
return super(MSHTML,self).value

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 6d804dc..d34aecb 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -30,7 +30,7 @@ from NVDAObjects.window import Window
from NVDAObjects import NVDAObject, NVDAObjectTextInfo, InvalidNVDAObject
import NVDAObjects.JAB
import eventHandler
-from NVDAObjects.behaviors import ProgressBar, Dialog,
EditableTextWithAutoSelectDetection, FocusableUnfocusableContainer
+from NVDAObjects.behaviors import ProgressBar, Dialog,
EditableTextWithAutoSelectDetection, FocusableUnfocusableContainer, ToolTip,
Notification

def getNVDAObjectFromEvent(hwnd,objectID,childID):
try:
@@ -1582,15 +1582,6 @@ class OutlineItem(IAccessible):
except (ValueError, TypeError):
return val

-class Tooltip(IAccessible):
-
- def event_show(self):
- # TODO: Abstract this somehow.
- if (config.conf["presentation"]["reportTooltips"] and
(self.IAccessibleRole==oleacc.ROLE_SYSTEM_TOOLTIP)) or
(config.conf["presentation"]["reportHelpBalloons"] and
(self.IAccessibleRole==oleacc.ROLE_SYSTEM_HELPBALLOON)):
-
speech.speakObject(self,reason=controlTypes.REASON_FOCUS)
- # TODO: Don't use getBrailleTextForProperties directly.
-
braille.handler.message(braille.getBrailleTextForProperties(name=self.name,
role=self.role))
-
class List(IAccessible):

def _get_role(self):
@@ -1752,8 +1743,8 @@ _staticMap={
("Static",oleacc.ROLE_SYSTEM_STATICTEXT):"StaticText",
("msctls_statusbar32",oleacc.ROLE_SYSTEM_STATICTEXT):"StaticText",
(None,oleacc.ROLE_SYSTEM_PUSHBUTTON):"Button",
- ("tooltips_class32",oleacc.ROLE_SYSTEM_TOOLTIP):"Tooltip",
- ("tooltips_class32",oleacc.ROLE_SYSTEM_HELPBALLOON):"Tooltip",
+ ("tooltips_class32",oleacc.ROLE_SYSTEM_TOOLTIP):"ToolTip",
+ ("tooltips_class32",oleacc.ROLE_SYSTEM_HELPBALLOON):"Notification",
(None,oleacc.ROLE_SYSTEM_DIALOG):"Dialog",
(None,oleacc.ROLE_SYSTEM_ALERT):"Dialog",
(None,oleacc.ROLE_SYSTEM_PROPERTYPAGE):"Dialog",
@@ -1815,4 +1806,5 @@ _staticMap={
("listview",oleacc.ROLE_SYSTEM_CLIENT):"ListviewPane",
("NUIDialog",oleacc.ROLE_SYSTEM_CLIENT):"NUIDialogClient",
("_WwB",oleacc.ROLE_SYSTEM_CLIENT):"winword.ProtectedDocumentPane",
+
("MsoCommandBar",oleacc.ROLE_SYSTEM_LISTITEM):"msOffice.CommandBarListItem",
}

diff --git a/source/NVDAObjects/IAccessible/msOffice.py
b/source/NVDAObjects/IAccessible/msOffice.py
index 5cd6dae..a96fac3 100755
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -11,6 +11,7 @@ import winUser
import api
from . import IAccessible, getNVDAObjectFromEvent
import eventHandler
+import re

"""Miscellaneous support for Microsoft Office applications.
"""
@@ -105,6 +106,36 @@ class BrokenMsoCommandBar(IAccessible):
return None
return name

+class CommandBarListItem(IAccessible):
+ """A list item in an MSO commandbar, that may be part of a color
palet."""
+
+ COMPILED_RE = re.compile(r'RGB\(\d+, \d+, \d+\)',re.I)
+ def _get_rgbNameAndMatch(self):
+ name = super(CommandBarListItem,self).name
+ if self.COMPILED_RE.match(name):
+ matchRGB = True
+ else:
+ matchRGB = False
+ return name, matchRGB
+
+ def _get_name(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ return colors.RGB.fromString(name).name
+ else:
+ return name
+
+ def _get_description(self):
+ name, matchRGB = self.rgbNameAndMatch
+ if matchRGB:
+ import colors
+ rgb=colors.RGB.fromString(name)
+ # Translators: a color, broken down into its RGB red,
green, blue parts.
+ return _("RGB red {rgb.red}, green {rgb.green}, blue
{rgb.blue}").format(rgb=colors.RGB.fromString(name))
+ else:
+ return super(CommandBarListItem,self).description
+
class SDMSymbols(SDM):

def _get_value(self):

diff --git a/source/NVDAObjects/behaviors.py b/source/NVDAObjects/behaviors.py
index 7d341a3..9b3cb99 100755
--- a/source/NVDAObjects/behaviors.py
+++ b/source/NVDAObjects/behaviors.py
@@ -603,3 +603,31 @@ class FocusableUnfocusableContainer(NVDAObject):
if obj.isFocusable:
obj.setFocus()
break
+
+class ToolTip(NVDAObject):
+ """Provides information about an item over which the user is hovering a
cursor.
+ The object should fire a show event when it appears.
+ """
+ role = controlTypes.ROLE_TOOLTIP
+
+ def event_show(self):
+ if not config.conf["presentation"]["reportTooltips"]:
+ return
+ speech.speakObject(self, reason=controlTypes.REASON_FOCUS)
+ # Ideally, we wouldn't use getBrailleTextForProperties directly.
+
braille.handler.message(braille.getBrailleTextForProperties(name=self.name,
role=self.role))
+
+class Notification(NVDAObject):
+ """Informs the user of non-critical information that does not require
immediate action.
+ This is primarily for notifications displayed in the system
notification area.
+ The object should fire a alert or show event when the user should be
notified.
+ """
+
+ def event_alert(self):
+ if not config.conf["presentation"]["reportHelpBalloons"]:
+ return
+ speech.speakObject(self, reason=controlTypes.REASON_FOCUS)
+ # Ideally, we wouldn't use getBrailleTextForProperties directly.
+
braille.handler.message(braille.getBrailleTextForProperties(name=self.name,
role=self.role))
+
+ event_show = event_alert

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 6704708..4ecfefc 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -27,6 +27,7 @@ import controlTypes
from . import Window
from .. import NVDAObjectTextInfo
import scriptHandler
+import ctypes

xlCenter=-4108
xlJustify=-4130
@@ -35,7 +36,7 @@ xlRight=-4152
xlDistributed=-4117
xlBottom=-4107
xlTop=-4160
-
+xlCellWidthUnitToPixels = 7.5919335705812574139976275207592
alignmentLabels={
xlCenter:"center",
xlJustify:"justify",
@@ -561,8 +562,115 @@ class ExcelCell(ExcelBase):
comment=None
if comment:
states.add(controlTypes.STATE_HASCOMMENT)
+ if self._overlapInfo is not None:
+ if self._overlapInfo['obscuredFromRightBy'] > 0:
+ states.add(controlTypes.STATE_CROPPED)
+ if self._overlapInfo['obscuringRightBy'] > 0:
+ states.add(controlTypes.STATE_OVERFLOWING)
return states

+ def getCellWidthAndTextWidth(self):
+ #handle to Device Context
+ hDC = ctypes.windll.user32.GetDC(self.windowHandle)
+ tempDC = ctypes.windll.gdi32.CreateCompatibleDC(hDC)
+ ctypes.windll.user32.ReleaseDC(self.windowHandle, hDC)
+ #Compatible Bitmap for current Device Context
+ hBMP = ctypes.windll.gdi32.CreateCompatibleBitmap(tempDC, 1, 1)
+ #handle to the bitmap object
+ hOldBMP = ctypes.windll.gdi32.SelectObject(tempDC, hBMP)
+ #Pass Device Context and LOGPIXELSX, the horizontal resolution
in pixels per unit inch
+ deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(tempDC, 88)
+ #Fetching Font Size and Weight information
+ iFontSize = self.excelCellObject.Font.Size
+ iFontSize = 11 if iFontSize is None else int(iFontSize)
+ iFontSize = ctypes.c_int(iFontSize)
+ iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize,
deviceCaps, 72)
+ #Font Weight for Bold FOnt is 700 and for normal font it's 400
+ iFontWeight = 700 if self.excelCellObject.Font.Bold else 400
+ #Fetching Font Name and style information
+ sFontName = self.excelCellObject.Font.Name
+ sFontItalic = self.excelCellObject.Font.Italic
+ sFontUnderline = True if self.excelCellObject.Font.Underline
else False
+ sFontStrikeThrough = self.excelCellObject.Font.Strikethrough
+ #If FontSize is <0: The font mapper transforms this value into
device units
+ #and matches its absolute value against the character height of
the available fonts.
+ iFontHeight = iFontSize * -1
+ #If Font Width is 0, the font mapper chooses a closest match
value.
+ iFontWidth = 0
+ iEscapement = 0
+ iOrientation = 0
+ #Default CharSet based on System Locale is chosen
+ iCharSet = 0
+ #Default font mapper behavior
+ iOutputPrecision = 0
+ #Default clipping behavior
+ iClipPrecision = 0
+ #Default Quality
+ iOutputQuality = 0
+ #Default Pitch and default font family
+ iPitchAndFamily = 0
+ #Create a font object with the correct size, weight and style
+ hFont = ctypes.windll.gdi32.CreateFontW(iFontHeight,
iFontWidth, iEscapement, iOrientation, iFontWeight, sFontItalic,
sFontUnderline, sFontStrikeThrough, iCharSet, iOutputPrecision, iClipPrecision,
iOutputQuality, iPitchAndFamily, sFontName)
+ #Load the font into the device context, storing the original
font object
+ hOldFont = ctypes.windll.gdi32.SelectObject(tempDC, hFont)
+ sText = self.excelCellObject.Text
+ textLength = len(sText)
+ class structText(ctypes.Structure):
+ _fields_ = [("width", ctypes.c_int),
("height",ctypes.c_int)]
+ StructText = structText()
+ getTextExtentPoint = ctypes.windll.gdi32.GetTextExtentPoint32W
+ getTextExtentPoint.argtypes = [ctypes.c_void_p,
ctypes.c_wchar_p, ctypes.c_int, ctypes.POINTER(structText)]
+ getTextExtentPoint.restype = ctypes.c_int
+ sText = unicode(sText)
+ #Get the text dimensions
+ ctypes.windll.gdi32.GetTextExtentPoint32W(tempDC, sText,
textLength,ctypes.byref(StructText))
+ #Restore the old Font Object
+ ctypes.windll.gdi32.SelectObject(tempDC, hOldFont)
+ #Delete the font object we created
+ ctypes.windll.gdi32.DeleteObject(hFont)
+ #Restore the old Bitmap Object
+ ctypes.windll.gdi32.SelectObject(tempDC, hOldBMP)
+ #Delete the temporary BitMap Object
+ ctypes.windll.gdi32.DeleteObject(hBMP)
+ #Release & Delete the device context
+ ctypes.windll.gdi32.DeleteDC(tempDC)
+ #Retrieve the text width
+ textWidth = StructText.width+5
+ cellWidth = self.excelCellObject.ColumnWidth *
xlCellWidthUnitToPixels #Conversion factor to convert the cellwidth to pixels
+ return (cellWidth,textWidth)
+
+ def _get__overlapInfo(self):
+ (cellWidth, textWidth) = self.getCellWidthAndTextWidth()
+ isWrapText = self.excelCellObject.WrapText
+ isShrinkToFit = self.excelCellObject.ShrinkToFit
+ isMerged = self.excelWindowObject.Selection.MergeCells
+ adjacentCell = self.excelCellObject.Offset(0,1)
+ if adjacentCell.Text:
+ isAdjacentCellEmpty = False
+ else:
+ isAdjacentCellEmpty = True
+ info = {}
+ if isMerged:
+ columnCountInMergeArea =
self.excelCellObject.MergeArea.Columns.Count
+ curCol = self.excelCellObject.Column
+ curRow = self.excelCellObject.Row
+ cellWidth = 0
+ for x in xrange(columnCountInMergeArea):
+ cellWidth += self.excelCellObject.Cells(curRow,
curCol).ColumnWidth
+ curCol += 1
+ cellWidth = cellWidth * xlCellWidthUnitToPixels
#Conversion factor to convert the cellwidth to pixels
+ if isWrapText or isShrinkToFit or textWidth <= cellWidth:
+ info = None
+ else:
+ if isAdjacentCellEmpty:
+ info['obscuringRightBy']= textWidth - cellWidth
+ info['obscuredFromRightBy'] = 0
+ else:
+ info['obscuredFromRightBy']= textWidth -
cellWidth
+ info['obscuringRightBy'] = 0
+ self._overlapInfo = info
+ return self._overlapInfo
+
def _get_parent(self):
worksheet=self.excelCellObject.Worksheet

self.parent=ExcelWorksheet(windowHandle=self.windowHandle,excelWindowObject=self.excelWindowObject,excelWorksheetObject=worksheet)

diff --git a/source/NVDAObjects/window/winword.py
b/source/NVDAObjects/window/winword.py
index bcd66a8..7106e95 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -399,6 +399,15 @@ class
TableWinWordCollectionQuicknavIterator(WinWordCollectionQuicknavIterator):

class WordDocumentTextInfo(textInfos.TextInfo):

+ # #4852: temporary fix.
+ # force mouse reading chunk to sentense to make it what it used to be
in 2014.4.
+ # We need to however fix line so it does not accidentially scroll.
+ def _get_unit_mouseChunk(self):
+ unit=super(WordDocumentTextInfo,self).unit_mouseChunk
+ if unit==textInfos.UNIT_LINE:
+ unit=textInfos.UNIT_SENTENCE
+ return unit
+
def find(self,text,caseSensitive=False,reverse=False):
f=self._rangeObj.find
f.text=text
@@ -798,6 +807,9 @@ class BrowseModeWordDocumentTextInfo(textInfos.TextInfo):

super(BrowseModeWordDocumentTextInfo,self).__init__(obj,position)

self.innerTextInfo=WordDocumentTextInfoForTreeInterceptor(obj.rootNVDAObject,position,_rangeObj=_rangeObj)

+ def _get__rangeObj(self):
+ return self.innerTextInfo._rangeObj
+
def find(self,text,caseSensitive=False,reverse=False):
return self.innerTextInfo.find(text,caseSensitive,reverse)

@@ -965,6 +977,20 @@ class WordDocument(EditableTextWithoutAutoSelectDetection,
Window):
states.add(controlTypes.STATE_MULTILINE)
return states

+ def
populateHeaderCellTrackerFromHeaderRows(self,headerCellTracker,table):
+ rows=table.rows
+ for rowIndex in xrange(rows.count):
+ try:
+ row=rows.item(rowIndex+1)
+ except COMError:
+ break
+ try:
+ headingFormat=row.headingFormat
+ except (COMError,AttributeError,NameError):
+ headingFormat=0
+ if headingFormat==-1: # is a header row
+
headerCellTracker.addHeaderCellInfo(rowNumber=row.index,columnNumber=1,isColumnHeader=True,isRowHeader=False)
+
def
populateHeaderCellTrackerFromBookmarks(self,headerCellTracker,bookmarks):
for x in bookmarks:
name=x.name
@@ -991,6 +1017,7 @@ class WordDocument(EditableTextWithoutAutoSelectDetection,
Window):
if not self._curHeaderCellTrackerTable or not
tableRange.isEqual(self._curHeaderCellTrackerTable.range):
self._curHeaderCellTracker=HeaderCellTracker()

self.populateHeaderCellTrackerFromBookmarks(self._curHeaderCellTracker,tableRange.bookmarks)
+
self.populateHeaderCellTrackerFromHeaderRows(self._curHeaderCellTracker,table)
self._curHeaderCellTrackerTable=table
return self._curHeaderCellTracker

@@ -1032,7 +1059,7 @@ class
WordDocument(EditableTextWithoutAutoSelectDetection, Window):
return False

headerCellTracker=self.getHeaderCellTrackerForTable(cell.range.tables[1])

info=headerCellTracker.getHeaderCellInfoAt(rowNumber,columnNumber)
- if not info:
+ if not info or not hasattr(info,'name'):
return False
if isColumnHeader and info.isColumnHeader:
info.isColumnHeader=False

diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py
index 7cdc55b..08fc6a1 100644
--- a/source/_UIAHandler.py
+++ b/source/_UIAHandler.py
@@ -39,6 +39,7 @@ badUIAWindowClassNames=[
"RICHEDIT50W",
"SysListView32",
"_WwG",
+ '_WwN',
"EXCEL7",
"Button",
]

diff --git a/source/appModules/outlook.py b/source/appModules/outlook.py
index 2ef07d3..9ac8f5f 100644
--- a/source/appModules/outlook.py
+++ b/source/appModules/outlook.py
@@ -12,6 +12,8 @@ import winKernel
import comHelper
import winUser
from logHandler import log
+import textInfos
+import braille
import appModuleHandler
import eventHandler
import UIAHandler
@@ -22,7 +24,7 @@ import speech
import ui
from NVDAObjects.IAccessible import IAccessible
from NVDAObjects.window import Window
-from NVDAObjects.window.winword import WordDocument
+from NVDAObjects.window.winword import WordDocument,
WordDocumentTreeInterceptor
from NVDAObjects.IAccessible.MSHTML import MSHTML
from NVDAObjects.behaviors import RowWithFakeNavigation
from NVDAObjects.UIA import UIA
@@ -445,14 +447,46 @@ class UIAGridRow(RowWithFakeNavigation,UIA):
super(UIAGridRow,self).setFocus()
eventHandler.queueEvent("gainFocus",self)

+class MailViewerTreeInterceptor(WordDocumentTreeInterceptor):
+ """A BrowseMode treeInterceptor specifically for readonly emails, where
tab and shift+tab are safe and we know will not edit the document."""
+
+ def script_tab(self,gesture):
+
bookmark=self.rootNVDAObject.makeTextInfo(textInfos.POSITION_SELECTION).bookmark
+ gesture.send()
+ info,caretMoved=self.rootNVDAObject._hasCaretMoved(bookmark)
+ if not caretMoved:
+ return
+ info=self.makeTextInfo(textInfos.POSITION_SELECTION)
+ inTable=info._rangeObj.tables.count>0
+ isCollapsed=info.isCollapsed
+ if inTable and isCollapsed:
+ info.expand(textInfos.UNIT_CELL)
+ isCollapsed=False
+ if not isCollapsed:
+
speech.speakTextInfo(info,reason=controlTypes.REASON_FOCUS)
+ braille.handler.handleCaretMove(self)
+
+ __gestures={
+ "kb:tab":"tab",
+ "kb:shift+tab":"tab",
+ }
+
class OutlookWordDocument(WordDocument):

- def _get_shouldCreateTreeInterceptor(self):
- # #2975: If this WordDocument is displaying a sent message,
then it should be read with browse mode.
+ def _get_isReadonlyViewer(self):
+ # #2975: The only way we know an email is read-only is if the
underlying email has been sent.
try:
return
self.appModule.nativeOm.activeInspector().currentItem.sent
except (COMError,NameError,AttributeError):
return False

+ def _get_treeInterceptorClass(self):
+ if self.isReadonlyViewer:
+ return MailViewerTreeInterceptor
+ return super(OutlookWordDocument,self).treeInterceptorClass
+
+ def _get_shouldCreateTreeInterceptor(self):
+ return self.isReadonlyViewer
+
def _get_role(self):
- return controlTypes.ROLE_DOCUMENT if
self.shouldCreateTreeInterceptor else super(OutlookWordDocument,self).role
+ return controlTypes.ROLE_DOCUMENT if self.isReadonlyViewer else
super(OutlookWordDocument,self).role

diff --git a/source/appModules/skype.py b/source/appModules/skype.py
index 75ac77c..8573969 100644
--- a/source/appModules/skype.py
+++ b/source/appModules/skype.py
@@ -1,11 +1,13 @@
# -*- coding: UTF-8 -*-
#appModules/skype.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2007-2013 Peter Vágner, NV Access Limited
+#Copyright (C) 2007-2015 Peter Vágner, NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

+import re
from comtypes import COMError
+import wx
import appModuleHandler
import controlTypes
import winUser
@@ -16,35 +18,100 @@ import windowUtils
import displayModel
import queueHandler
import config
+import NVDAObjects.behaviors
+import api
+
+# Translators: The name of the NVDA command category for Skype specific
commands.
+SCRCAT_SKYPE = _("Skype")
+
+class Conversation(NVDAObjects.IAccessible.IAccessible):
+ scriptCategory = SCRCAT_SKYPE
+
+ def initOverlayClass(self):
+ for n in xrange(0, 10):
+ self.bindGesture("kb:NVDA+control+%d" % n,
"reviewRecentMessage")
+
+ def _isEqual(self, other):
+ # Sometimes, we get this object as an unproxied IAccessible,
+ # which means the location is different, so
IAccessible._isEqual return False.
+ # This can cause us to get a gainFocus and a focusEntered on
two different instances.
+ # We don't care about the location here.
+ return self.windowHandle == other.windowHandle
+
+ def _gainedFocus(self):
+ # The user has entered this Skype conversation.
+ if self.appModule.conversation:
+ # Another conversation was previously focused. Clean it
up.
+ self.appModule.conversation.lostFocus()
+
+ self.appModule.conversation = self
+ try:
+ self.outputList =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
+
windowUtils.findDescendantWindow(self.windowHandle,
className="TChatContentControl"),
+ winUser.OBJID_CLIENT, 0).lastChild
+ except LookupError:
+ pass
+ else:
+ self.outputList.startMonitoring()
+ try:
+ self.typingIndicator =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
+
windowUtils.findDescendantWindow(self.windowHandle, className="TWidgetControl"),
+ winUser.OBJID_CLIENT, 1)
+ except LookupError:
+ pass
+ else:
+ self.typingIndicator.startMonitoring()
+
+ def event_focusEntered(self):
+ self._gainedFocus()
+ super(Conversation, self).event_focusEntered()
+
+ def event_gainFocus(self):
+ # A conversation might have its own top level window,
+ # but foreground changes often trigger gainFocus instead of
focusEntered.
+ self._gainedFocus()
+ super(Conversation, self).event_gainFocus()
+
+ def lostFocus(self):
+ self.appModule.conversation = None
+ self.outputList.stopMonitoring()
+ self.outputList = None
+ self.typingIndicator.stopMonitoring()
+ self.typingIndicator = None
+
+ def script_reviewRecentMessage(self, gesture):
+ try:
+ index = int(gesture.mainKeyName[-1])
+ except (AttributeError, ValueError):
+ return
+ if index == 0:
+ index = 10
+ self.outputList.reviewRecentMessage(index)
+ # Describes the NVDA command to review messages in Skype.
+ script_reviewRecentMessage.__doc__ = _("Reports and moves the review
cursor to a recent message")
+ script_reviewRecentMessage.canPropagate = True

class ChatOutputList(NVDAObjects.IAccessible.IAccessible):

def startMonitoring(self):
- self.oldLastMessageText = None
- self.oldSecondLastMessageText = None
+ self.oldMessageCount = None
self.update(initial=True)
displayModel.requestTextChangeNotifications(self, True)

def stopMonitoring(self):
displayModel.requestTextChangeNotifications(self, False)

+ RE_MESSAGE = re.compile(r"^From (?P<from>.*), (?P<body>.*), sent on
(?P<time>.*?)(?: Edited by .* at .*?)?(?: Not delivered|New)?$")
def reportMessage(self, text):
- if text.startswith("["):
- # Remove the timestamp.
- text = text.split("] ", 1)[1]
+ # Messages are ridiculously verbose.
+ # Strip the time and other metadata if possible.
+ m = self.RE_MESSAGE.match(text)
+ if m:
+ text = "%s, %s" % (m.group("from"), m.group("body"))
ui.message(text)

- def update(self, initial=False):
- reportNew = not initial and
config.conf["presentation"]["reportDynamicContentChanges"]
-
- # Ideally, we'd determine new messages based just on the change
in child count,
- # but children can be inserted in the middle when messages are
expanded.
- # Therefore, we have to use message text.
+ def _getMessageCount(self):
ia = self.IAccessibleObject
- newMessages = []
- lastWasEdited = False
- # The list is chronological and we're looking for new messages,
- # so scan the list in reverse.
for c in xrange(self.childCount, -1, -1):
try:
if ia.accRole(c) != oleacc.ROLE_SYSTEM_LISTITEM
or ia.accState(c) & oleacc.STATE_SYSTEM_UNAVAILABLE:
@@ -53,58 +120,78 @@ class ChatOutputList(NVDAObjects.IAccessible.IAccessible):
except COMError:
# The child probably disappeared after we
fetched childCount.
continue
- text = ia.accName(c)
- if not text:
- continue
- if text.startswith("[] "):
- # When timestamps are disabled,
- # Skype initially prefixes outgoing messages
with "[] ".
- # However, the prefix silently disappears
shortly afterwards.
- # Remove it so we aren't affected by it.
- text = text[3:]
- if text == self.oldLastMessageText:
- # No more new messages.
- break
- if text == self.oldSecondLastMessageText and
len(newMessages) == 1:
- # We didn't match the last message, but this is
the second last message.
- # This means the last message must have been
edited, so stop here.
- lastWasEdited = True
- break
- newMessages.append(text)
- if not reportNew and (self.oldLastMessageText or
len(newMessages) > 1):
- # If we're not reporting new messages, we only
need to go
- # far enough so that we have the second last
message.
- break
-
- if not newMessages:
- return
+ return c
+ return 0

- oldLast = self.oldLastMessageText
- self.oldLastMessageText = newMessages[0]
- if not lastWasEdited:
- try:
- self.oldSecondLastMessageText = newMessages[1]
- except IndexError:
- # There was only one new message,
- # so the second last is the old last.
- self.oldSecondLastMessageText = oldLast
+ def update(self, initial=False):
+ newCount = self._getMessageCount()
+ if (not initial and
config.conf["presentation"]["reportDynamicContentChanges"]
+ #4644: Don't report a flood of messages.
+ and newCount - self.oldMessageCount < 5):
+ ia = self.IAccessibleObject
+ for c in xrange(self.oldMessageCount + 1, newCount + 1):
+ text = ia.accName(c)
+ if not text:
+ continue
+ self.reportMessage(text)
+ self.oldMessageCount = newCount
+
+ def event_textChange(self):
+ # This event is called from another thread, but this needs to
run in the main thread.
+ queueHandler.queueFunction(queueHandler.eventQueue, self.update)

- if not reportNew:
+ def reviewRecentMessage(self, index):
+ count = self._getMessageCount()
+ if index > count:
+ # Translators: This is presented to inform the user
that no instant message has been received.
+ ui.message(_("No message yet"))
return
+ message = self.getChild(count - index)
+ api.setNavigatorObject(message)
+ self.reportMessage(message.name)
+
+class Notification(NVDAObjects.behaviors.Notification):
+ role = controlTypes.ROLE_ALERT
+
+ def _get_name(self):
+ return " ".join(child.name for child in self.children)
+
+ def event_show(self):
+ # There is a delay before the content of the notification is
ready.
+ wx.CallLater(500, self.event_alert)
+
+class TypingIndicator(NVDAObjects.IAccessible.IAccessible):
+
+ def initOverlayClass(self):
+ self._oldName = None

- for text in reversed(newMessages):
- self.reportMessage(text)
+ def startMonitoring(self):
+ displayModel.requestTextChangeNotifications(self, True)
+
+ def stopMonitoring(self):
+ displayModel.requestTextChangeNotifications(self, False)
+
+ def _maybeReport(self):
+ name = self.name
+ if name == self._oldName:
+ # There was no real change; just a redraw.
+ return
+ self._oldName = name
+ if name:
+ ui.message(name)
+ else:
+ # Translators: Indicates that a contact stopped typing.
+ ui.message(_("Typing stopped"))

def event_textChange(self):
# This event is called from another thread, but this needs to
run in the main thread.
- queueHandler.queueFunction(queueHandler.eventQueue, self.update)
+ queueHandler.queueFunction(queueHandler.eventQueue,
self._maybeReport)

class AppModule(appModuleHandler.AppModule):

def __init__(self, *args, **kwargs):
super(AppModule, self).__init__(*args, **kwargs)
- self.chatWindow = None
- self.chatOutputList = None
+ self.conversation = None

def event_NVDAObject_init(self,obj):
if isinstance(obj, NVDAObjects.IAccessible.IAccessible) and
obj.event_objectID is None and controlTypes.STATE_FOCUSED in obj.states and
obj.role not in
(controlTypes.ROLE_POPUPMENU,controlTypes.ROLE_MENUITEM,controlTypes.ROLE_MENUBAR):
@@ -122,47 +209,22 @@ class AppModule(appModuleHandler.AppModule):
obj.shouldAllowIAccessibleFocusEvent = False

def chooseNVDAObjectOverlayClasses(self, obj, clsList):
- if obj.windowClassName == "TChatContentControl" and obj.role ==
controlTypes.ROLE_LIST:
+ wClass = obj.windowClassName
+ role = obj.role
+ if isinstance(obj, NVDAObjects.IAccessible.IAccessible) and
obj.windowClassName == "TConversationForm" and obj.IAccessibleRole ==
oleacc.ROLE_SYSTEM_CLIENT:
+ clsList.insert(0, Conversation)
+ elif wClass == "TChatContentControl" and role ==
controlTypes.ROLE_LIST:
clsList.insert(0, ChatOutputList)
-
- def conversationMaybeFocused(self, obj):
- if not isinstance(obj, NVDAObjects.IAccessible.IAccessible) or
obj.windowClassName != "TConversationForm" or obj.IAccessibleRole !=
oleacc.ROLE_SYSTEM_CLIENT:
- # This isn't a Skype conversation.
- return
- # The user has entered a Skype conversation.
-
- if self.chatWindow:
- # Another conversation was already focused and hasn't
been cleaned up yet.
- self.conversationLostFocus()
-
- window = obj.windowHandle
- self.chatWindow = window
- try:
- self.chatOutputList =
NVDAObjects.IAccessible.getNVDAObjectFromEvent(
- windowUtils.findDescendantWindow(window,
className="TChatContentControl"),
- winUser.OBJID_CLIENT, 1)
- except LookupError:
- pass
- else:
- self.chatOutputList.startMonitoring()
-
- def event_focusEntered(self, obj, nextHandler):
- self.conversationMaybeFocused(obj)
- nextHandler()
-
- def conversationLostFocus(self):
- self.chatWindow = None
- self.chatOutputList.stopMonitoring()
- self.chatOutputList = None
+ elif wClass == "TTrayAlert" and role ==
controlTypes.ROLE_WINDOW:
+ clsList.insert(0, Notification)
+ elif wClass == "TWidgetControl" and role ==
controlTypes.ROLE_LISTITEM:
+ clsList.insert(0, TypingIndicator)

def event_gainFocus(self, obj, nextHandler):
- if self.chatWindow and not
winUser.isDescendantWindow(self.chatWindow, obj.windowHandle):
- self.conversationLostFocus()
- # A conversation might have its own top level window,
- # but foreground changes often trigger gainFocus instead of
focusEntered.
- self.conversationMaybeFocused(obj)
+ if self.conversation and not
winUser.isDescendantWindow(self.conversation.windowHandle, obj.windowHandle):
+ self.conversation.lostFocus()
nextHandler()

def event_appModule_loseFocus(self):
- if self.chatWindow:
- self.conversationLostFocus()
+ if self.conversation:
+ self.conversation.lostFocus()

diff --git a/source/braille.py b/source/braille.py
index 0e33898..ea8b46e 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -33,6 +33,12 @@ TABLES = (
("ar-fa.utb", _("Farsi grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("as-in-g1.utb", _("Assamese grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("be-in-g1.utb", _("Bengali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("bg.ctb", _("Bulgarian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -114,6 +120,9 @@ TABLES = (
("fr-bfu-g2.ctb", _("French (unified) Grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("gu-in-g1.utb", _("Gujarati grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("gr-gr-g1.utb", _("Greek (Greece) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -141,15 +150,30 @@ TABLES = (
("it-it-comp8.utb", _("Italian 8 dot computer braille"), True),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ka-in-g1.utb", _("Kannada grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ko-g1.ctb", _("Korean grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ko-g2.ctb", _("Korean grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ks-in-g1.utb", _("Kashmiri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Lv-Lv-g1.utb", _("Latvian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("ml-in-g1.utb", _("Malayalam grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mn-in-g1.utb", _("Manipuri grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("mr-in-g1.utb", _("Marathi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("nl-be-g1.utb", _("Dutch (Belgium) grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -171,6 +195,12 @@ TABLES = (
("No-No-g3.ctb", _("Norwegian grade 3"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("np-in-g1.utb", _("Nepali grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
+ ("or-in-g1.utb", _("Oriya grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Pl-Pl-g1.utb", _("Polish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -183,12 +213,18 @@ TABLES = (
("Pt-Pt-g2.ctb", _("Portuguese grade 2"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("pu-in-g1.utb", _("Punjabi grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("ru-compbrl.ctb", _("Russian braille for computer code"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
("ru-ru-g1.utb", _("Russian grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("sa-in-g1.utb", _("Sanskrit grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("Se-Se-g1.utb", _("Swedish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
@@ -204,6 +240,9 @@ TABLES = (
("ta-ta-g1.ctb", _("Tamil grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.
+ ("te-in-g1.utb", _("Telegu grade 1"), False),
+ # Translators: The name of a braille table displayed in the
+ # braille settings dialog.
("tr.ctb", _("Turkish grade 1"), False),
# Translators: The name of a braille table displayed in the
# braille settings dialog.

diff --git a/source/brailleDisplayDrivers/papenmeier.py
b/source/brailleDisplayDrivers/papenmeier.py
index ce5e1c8..8227eb6 100644
--- a/source/brailleDisplayDrivers/papenmeier.py
+++ b/source/brailleDisplayDrivers/papenmeier.py
@@ -2,7 +2,7 @@
#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) 2012 Tobias Platen, Halim Sahin, Ali-Riza Ciftcioglu, NV Access
Limited
+#Copyright (C) 2012-2015 Tobias Platen, Halim Sahin, Ali-Riza Ciftcioglu, NV
Access Limited
#Author: Tobias Platen (nvda@xxxxxxxxxxxx)
#minor changes by Halim Sahin (nvda@xxxxxxxxxxxx), Ali-Riza Ciftcioglu
<aliminator83@xxxxxxxxxxxxxx> and James Teh

@@ -104,7 +104,7 @@ def brl_poll(dev):

def brl_decode_trio(keys):
"""decode routing keys on Trio"""
- if(keys[0:3]=='KP_' ): #KEYSTATE CHANGED EVENT on Trio, not Braille keys
+ if(keys[0]=='K' ): #KEYSTATE CHANGED EVENT on Trio, not Braille keys
keys = keys[3:]
i = 0
j = []
@@ -227,12 +227,9 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver,
ScriptableObject):
port = portInfo["port"]
hwID = portInfo["hardwareID"]
if "bluetoothName" in portInfo:
- if(portInfo["bluetoothName"] ==
"braillex trio "):
+ if portInfo["bluetoothName"][0:14] ==
"braillex trio " or portInfo["bluetoothName"][0:13] == "braillex live":
try:
self._dev =
serial.Serial(port, baudrate = 57600,timeout = BLUETOOTH_TIMEOUT, writeTimeout
= BLUETOOTH_TIMEOUT)
- self.numCells = 40
- self._proto = 'B'
- self._voffset = 0

log.info("connectBluetooth success")
except:

log.debugWarning("connectBluetooth failed")
@@ -271,8 +268,7 @@ connection could not be established"""
elif ftdi2:
self._baud = 57600
self.connectUSB(devlist)
- if(self._dev is None):
- return None
+ if(self._dev is not None):
try:
#request type of braille display
self._dev.write(brl_auto_id())
@@ -284,13 +280,14 @@ connection could not be established"""
self._dev.set_baud_rate(self._baud)
self._dev.purge()
self._dev.read(self._dev.inWaiting())
- self.numCells = 40
- self._proto = 'B'
- self._voffset = 0
- #we don't use autoid here, because the
trio might be switched off and other braille displays using the same baud rate
do not exist
+ #request type of braille display twice
because of baudrate change
+ self._dev.write(brl_auto_id())
+ self._dev.write(brl_auto_id())
+ time.sleep(0.05)# wait 50 ms in order
to get response for further actions
+ autoid=brl_poll(self._dev)
+ if(len(autoid) != 8):
+ return None
else:
- if(len(autoid) != 8):
- return None
autoid =
struct.unpack('BBBBBBBB',autoid)
if(autoid[3] == 0x35 and autoid[4] ==
0x38):#EL80s
self.numCells = 80
@@ -355,6 +352,26 @@ connection could not be established"""
self._proto = 'A'
self._voffset = 20
log.info("Found EL2D80s")
+ elif(autoid[3] == 0x35 and autoid[4] ==
0x39):#trio
+ self.numCells = 40
+ self._proto = 'B'
+ self._voffset = 0
+ log.info("Found trio")
+ elif(autoid[3] == 0x36 and autoid[4] ==
0x34):#live20
+ self.numCells = 20
+ self._proto = 'B'
+ self._voffset = 0
+ log.info("Found live 20")
+ elif(autoid[3] == 0x36 and autoid[4] ==
0x33):#live+
+ self.numCells = 40
+ self._proto = 'B'
+ self._voffset = 0
+ log.info("Found live+")
+ elif(autoid[3] == 0x36 and autoid[4] ==
0x32):#live
+ self.numCells = 40
+ self._proto = 'B'
+ self._voffset = 0
+ log.info("Found live")
else:
log.debugWarning('UNKNOWN
BRAILLE')

@@ -511,7 +528,7 @@ class InputGesture(braille.BrailleDisplayGesture,
brailleInput.BrailleInputGestu

self.id=brl_join_keys(brl_decode_key_names_repeat(driver))
return

- if driver._baud!=1 and keys[0] == 'L':
+ if driver._baud != 1 and keys[0] == 'L' and not
((ord(keys[3])-48) >>3):
#get dots
z = ord('0')
b = ord(keys[4])-z

diff --git a/source/brailleInput.py b/source/brailleInput.py
index b012330..ffd0838 100644
--- a/source/brailleInput.py
+++ b/source/brailleInput.py
@@ -51,12 +51,13 @@ class BrailleInputHandler(object):
def sendChars(self, chars):
inputs = []
for ch in chars:
- input = winUser.Input()
- input.type = winUser.INPUT_KEYBOARD
- input.ii.ki = winUser.KeyBdInput()
- input.ii.ki.wScan = ord(ch)
- input.ii.ki.dwFlags = winUser.KEYEVENTF_UNICODE
- inputs.append(input)
+ for direction in (0,winUser.KEYEVENTF_KEYUP):
+ input = winUser.Input()
+ input.type = winUser.INPUT_KEYBOARD
+ input.ii.ki = winUser.KeyBdInput()
+ input.ii.ki.wScan = ord(ch)
+ input.ii.ki.dwFlags =
winUser.KEYEVENTF_UNICODE|direction
+ inputs.append(input)
winUser.SendInput(inputs)

class BrailleInputGesture(inputCore.InputGesture):

diff --git a/source/browseMode.py b/source/browseMode.py
index 7ac02b2..a071c1e 100644
--- a/source/browseMode.py
+++ b/source/browseMode.py
@@ -1,5 +1,5 @@
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NVDA Contributors
+#Copyright (C) 2015 NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -18,6 +18,7 @@ import textInfos
import speech
import sayAllHandler
import treeInterceptorHandler
+import inputCore

REASON_QUICKNAV = "quickNav"

@@ -167,6 +168,7 @@ class TextInfoQuickNavItem(QuickNavItem):
return self.textInfo.compareEndPoints(caret, "startToStart") <= 0

class BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
+ scriptCategory = inputCore.SCRCAT_BROWSEMODE

def _get_shouldTrapNonCommandGestures(self):
return config.conf['virtualBuffers']['trapNonCommandGestures']
@@ -233,8 +235,8 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
d.Destroy()
gui.mainFrame.postPopup()
wx.CallAfter(run)
- # Translators: the description for the elements list dialog script on
virtualBuffers.
- script_elementsList.__doc__ = _("Presents a list of links, headings or
landmarks")
+ # Translators: the description for the Elements List command in browse
mode.
+ script_elementsList.__doc__ = _("Lists various types of elements in
this document")

def _activatePosition(self,info):
info.activate()

diff --git a/source/colors.py b/source/colors.py
index 2fe4db3..f067b9d 100644
--- a/source/colors.py
+++ b/source/colors.py
@@ -6,6 +6,7 @@

from collections import namedtuple
import math
+import colorsys
from ctypes.wintypes import COLORREF
import re

@@ -74,8 +75,15 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
longestDistance=255.0
# Translators: Reported when text is written in unknown color.
closestName=_("unknown color")
+
selfHSV=colorsys.rgb_to_hsv(self.red/255.0,self.green/255.0,self.blue/255.0)
for possibleRGB,possibleName in RGBToNames.iteritems():
-
distance=math.sqrt(abs(self.red-possibleRGB.red)**2+abs(self.green-possibleRGB.green)**2+abs(self.blue-possibleRGB.blue)**2)
+
possibleHSV=colorsys.rgb_to_hsv(possibleRGB.red/255.0,possibleRGB.green/255.0,possibleRGB.blue/255.0)
+ dh=abs(selfHSV[0]-possibleHSV[0])
+ if dh>0.5:
+ dh=1-dh
+ ds=abs(selfHSV[1]-possibleHSV[1])
+ dv=abs(selfHSV[2]-possibleHSV[2])
+ distance=math.sqrt(0.4*(dh**2)+0.1*(ds**2)+0.1*(dv**2))
if distance<longestDistance:
longestDistance=distance
closestName=possibleName
@@ -85,48 +93,284 @@ class RGB(namedtuple('RGB',('red','green','blue'))):
RGBToNamesCache={}

RGBToNames={
- #Standard 16 HTML 4 colors
- # Translators: The color black.
- RGB(0x00,0x00,0x00):_('black'),
- # Translators: The color dark green.
- RGB(0x00,0x80,0x00):_('dark green'),
- # Translators: The light gray color.
- RGB(0xc0,0xc0,0xc0):_('light grey'),
- # Translators: The color green (full brightness)
- RGB(0x00,0xff,0x00):_('green'),
- # Translators: The color gray (halfway between white and black).
- RGB(0x80,0x80,0x80):_('grey'),
- # Translators: the color olive.
- # For more info see:
http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
- RGB(0x80,0x80,0x00):_('olive'),
- # Translators: The color white.
- RGB(0xff,0xff,0xff):_('white'),
- # Translators: The color yellow.
- RGB(0xff,0xff,0x00):_('yellow'),
- # Translators: The dark red color.
- RGB(0x80,0x00,0x00):_('dark red'),
- # Translators: The color navy blue (dark blue).
- # For more info see http://en.wikipedia.org/wiki/Navy_blue
- RGB(0x00,0x00,0xa0):_('navy blue'),
- # Translators: The color red.
- RGB(0xff,0x00,0x00):_('red'),
- # Translators: The color blue.
- RGB(0x00,0x00,0xff):_('blue'),
- # Translators: The color purple.
- RGB(0x80,0x00,0x80):_('purple'),
- # Translators: The color teal, which is a mix of green and blue, mostly
green.
- # For more info see http://en.wikipedia.org/wiki/Teal
- RGB(0x00,0x80,0x80):_('teal'),
- # Translators: The color fuchsia is a mix of blue and red.
- # For more info see: http://en.wikipedia.org/wiki/Magenta
- RGB(0xff,0x00,0xff):_('fuchsia'),
- # Translators: The aqua color is an equal amount of blue and green.
- # For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
- RGB(0x00,0xff,0xff):_('aqua'),
-
- #Extra CSS 2.1 color
-
- # Translators: This is the color orange.
- RGB(0xff,0xa5,0x00):_('orange'),
+# Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,248,255):pgettext('color name','Alice Blue'),
+# Translators: the color Antique White (RGB 250, 235, 215) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,235,215):pgettext('color name','Antique White'),
+# Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Aqua'),
+# Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,212):pgettext('color name','Aquamarine'),
+# Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,255):pgettext('color name','Azure'),
+# Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,220):pgettext('color name','Beige'),
+# Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,196):pgettext('color name','Bisque'),
+# Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,0):pgettext('color name','Black'),
+# Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,235,205):pgettext('color name','Blanched Almond'),
+# Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,255):pgettext('color name','Blue'),
+# Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(138,43,226):pgettext('color name','Blue Violet'),
+# Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(165,42,42):pgettext('color name','Brown'),
+# Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(222,184,135):pgettext('color name','Burly Wood'),
+# Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(95,158,160):pgettext('color name','Cadet Blue'),
+# Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(127,255,0):pgettext('color name','Chartreuse'),
+# Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,105,30):pgettext('color name','Chocolate'),
+# Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,127,80):pgettext('color name','Coral'),
+# Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(100,149,237):pgettext('color name','Cornflower Blue'),
+# Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,248,220):pgettext('color name','Cornsilk'),
+# Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,20,60):pgettext('color name','Crimson'),
+# Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,255):pgettext('color name','Cyan'),
+# Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,139):pgettext('color name','Dark Blue'),
+# Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,139,139):pgettext('color name','Dark Cyan'),
+# Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(184,134,11):pgettext('color name','Dark Goldenrod'),
+# Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(169,169,169):pgettext('color name','Dark Gray'),
+# Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,100,0):pgettext('color name','Dark Green'),
+# Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(189,183,107):pgettext('color name','Dark Khaki'),
+# Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,139):pgettext('color name','Dark Magenta'),
+# Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(85,107,47):pgettext('color name','Dark Olive Green'),
+# Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,140,0):pgettext('color name','Dark Orange'),
+# Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(153,50,204):pgettext('color name','Dark Orchid'),
+# Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,0,0):pgettext('color name','Dark Red'),
+# Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(233,150,122):pgettext('color name','Dark Salmon'),
+# Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(143,188,143):pgettext('color name','Dark Sea Green'),
+# Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,61,139):pgettext('color name','Dark Slate Blue'),
+# Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(47,79,79):pgettext('color name','Dark Slate Gray'),
+# Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,206,209):pgettext('color name','Dark Turquoise'),
+# Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(148,0,211):pgettext('color name','Dark Violet'),
+# Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,20,147):pgettext('color name','Deep Pink'),
+# Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,191,255):pgettext('color name','Deep Sky Blue'),
+# Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(105,105,105):pgettext('color name','Dim Gray'),
+# Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(30,144,255):pgettext('color name','Dodger Blue'),
+# Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(178,34,34):pgettext('color name','Fire Brick'),
+# Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,240):pgettext('color name','Floral White'),
+# Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(34,139,34):pgettext('color name','Forest Green'),
+# Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Fuchsia'),
+# Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(220,220,220):pgettext('color name','Gainsboro'),
+# Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(248,248,255):pgettext('color name','Ghost White'),
+# Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,215,0):pgettext('color name','Gold'),
+# Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,165,32):pgettext('color name','Goldenrod'),
+# Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,128):pgettext('color name','Gray'),
+# Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,0):pgettext('color name','Green'),
+# Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,255,47):pgettext('color name','Green Yellow'),
+# Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,255,240):pgettext('color name','Honeydew'),
+# Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,105,180):pgettext('color name','Hot Pink'),
+# Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,92,92):pgettext('color name','Indian Red'),
+# Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(75,0,130):pgettext('color name','Indigo'),
+# Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,240):pgettext('color name','Ivory'),
+# Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,230,140):pgettext('color name','Khaki'),
+# Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(230,230,250):pgettext('color name','Lavender'),
+# Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,240,245):pgettext('color name','Lavender Blush'),
+# Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(124,252,0):pgettext('color name','Lawn Green'),
+# Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,205):pgettext('color name','Lemon Chiffon'),
+# Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(173,216,230):pgettext('color name','Light Blue'),
+# Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(240,128,128):pgettext('color name','Light Coral'),
+# Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(224,255,255):pgettext('color name','Light Cyan'),
+# Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,250,210):pgettext('color name','Light Goldenrod Yellow'),
+# Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(144,238,144):pgettext('color name','Light Green'),
+# Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(211,211,211):pgettext('color name','Light Grey'),
+# Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,182,193):pgettext('color name','Light Pink'),
+# Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,160,122):pgettext('color name','Light Salmon'),
+# Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(32,178,170):pgettext('color name','Light Sea Green'),
+# Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,250):pgettext('color name','Light Sky Blue'),
+# Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(119,136,153):pgettext('color name','Light Slate Gray'),
+# Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,196,222):pgettext('color name','Light Steel Blue'),
+# Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,224):pgettext('color name','Light Yellow'),
+# Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,0):pgettext('color name','Lime'),
+# Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(50,205,50):pgettext('color name','Lime Green'),
+# Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,240,230):pgettext('color name','Linen'),
+# Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,255):pgettext('color name','Magenta'),
+# Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,0):pgettext('color name','Maroon'),
+# Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(102,205,170):pgettext('color name','Medium Aquamarine'),
+# Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,205):pgettext('color name','Medium Blue'),
+# Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(186,85,211):pgettext('color name','Medium Orchid'),
+# Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(147,112,219):pgettext('color name','Medium Purple'),
+# Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(60,179,113):pgettext('color name','Medium Sea Green'),
+# Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(123,104,238):pgettext('color name','Medium Slate Blue'),
+# Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,250,154):pgettext('color name','Medium Spring Green'),
+# Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(72,209,204):pgettext('color name','Medium Turquoise'),
+# Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(199,21,133):pgettext('color name','Medium Violet Red'),
+# Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(25,25,112):pgettext('color name','Midnight Blue'),
+# Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,255,250):pgettext('color name','Mint Cream'),
+# Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,225):pgettext('color name','Misty Rose'),
+# Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,228,181):pgettext('color name','Moccasin'),
+# Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,222,173):pgettext('color name','Navajo White'),
+# Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,0,128):pgettext('color name','Navy'),
+# Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(253,245,230):pgettext('color name','Old Lace'),
+# Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,128,0):pgettext('color name','Olive'),
+# Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(107,142,35):pgettext('color name','Olive Drab'),
+# Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,165,0):pgettext('color name','Orange'),
+# Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,69,0):pgettext('color name','Orange Red'),
+# Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(218,112,214):pgettext('color name','Orchid'),
+# Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,232,170):pgettext('color name','Pale Goldenrod'),
+# Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(152,251,152):pgettext('color name','Pale Green'),
+# Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(175,238,238):pgettext('color name','Pale Turquoise'),
+# Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(219,112,147):pgettext('color name','Pale Violet Red'),
+# Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,239,213):pgettext('color name','Papaya Whip'),
+# Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,218,185):pgettext('color name','Peach Puff'),
+# Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(205,133,63):pgettext('color name','Peru'),
+# Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,192,203):pgettext('color name','Pink'),
+# Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(221,160,221):pgettext('color name','Plum'),
+# Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(176,224,230):pgettext('color name','Powder Blue'),
+# Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(128,0,128):pgettext('color name','Purple'),
+# Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,0,0):pgettext('color name','Red'),
+# Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(188,143,143):pgettext('color name','Rosy Brown'),
+# Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(65,105,225):pgettext('color name','Royal Blue'),
+# Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(139,69,19):pgettext('color name','Saddle Brown'),
+# Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(250,128,114):pgettext('color name','Salmon'),
+# Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(244,164,96):pgettext('color name','Sandy Brown'),
+# Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(46,139,87):pgettext('color name','Sea Green'),
+# Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,245,238):pgettext('color name','Seashell'),
+# Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(160,82,45):pgettext('color name','Sienna'),
+# Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(192,192,192):pgettext('color name','Silver'),
+# Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(135,206,235):pgettext('color name','Sky Blue'),
+# Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(106,90,205):pgettext('color name','Slate Blue'),
+# Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(112,128,144):pgettext('color name','Slate Gray'),
+# Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,250,250):pgettext('color name','Snow'),
+# Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,255,127):pgettext('color name','Spring Green'),
+# Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(70,130,180):pgettext('color name','Steel Blue'),
+# Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(210,180,140):pgettext('color name','Tan'),
+# Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(0,128,128):pgettext('color name','Teal'),
+# Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(216,191,216):pgettext('color name','Thistle'),
+# Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,99,71):pgettext('color name','Tomato'),
+# Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(64,224,208):pgettext('color name','Turquoise'),
+# Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(238,130,238):pgettext('color name','Violet'),
+# Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,222,179):pgettext('color name','Wheat'),
+# Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,255):pgettext('color name','White'),
+# Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(245,245,245):pgettext('color name','White Smoke'),
+# Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(255,255,0):pgettext('color name','Yellow'),
+# Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+ RGB(154,205,50):pgettext('color name','Yellow Green'),
}
-

diff --git a/source/comtypesMonkeyPatches.py b/source/comtypesMonkeyPatches.py
index 1ba21e4..980ac2e 100644
--- a/source/comtypesMonkeyPatches.py
+++ b/source/comtypesMonkeyPatches.py
@@ -5,8 +5,11 @@

from logHandler import log

+from comtypes import COMError
+from comtypes.hresult import *
+
#Monkey patch comtypes to support byref in variants
-from comtypes.automation import VARIANT, VT_BYREF
+from comtypes.automation import VARIANT, VT_BYREF, IDispatch
from ctypes import cast, c_void_p
from _ctypes import _Pointer
oldVARIANT_value_fset=VARIANT.value.fset
@@ -60,3 +63,12 @@ oldVARIANT_value_fget=VARIANT.value.fget
def newVARIANT_value_fget(self):
return self._get_value(dynamic=True)

VARIANT.value=property(newVARIANT_value_fget,VARIANT.value.fset,VARIANT.value.fdel)
+
+# #4258: monkeypatch to better handle error where IDispatch's GetTypeInfo can
return a NULL pointer. Affects QT5
+oldGetTypeInfo=IDispatch._GetTypeInfo
+def newGetTypeInfo(self,index,lcid=0):
+ res=oldGetTypeInfo(self,index,lcid)
+ if not res:
+ raise COMError(E_NOTIMPL,None,None)
+ return res
+IDispatch._GetTypeInfo=newGetTypeInfo

diff --git a/source/controlTypes.py b/source/controlTypes.py
index 0e4788e..b3ab20e 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -188,6 +188,8 @@ STATE_PINNED=0x800000000
STATE_HASFORMULA=0x1000000000 #Mostly for spreadsheets
STATE_HASCOMMENT=0X2000000000
STATE_OBSCURED=0x4000000000
+STATE_CROPPED=0x8000000000
+STATE_OVERFLOWING=0x10000000000

roleLabels={
# Translators: The word for an unknown control type.
@@ -550,6 +552,10 @@ stateLabels={
STATE_HASCOMMENT:_("has comment"),
# Translators: a state that denotes that the object is covered
partially or fully by another object
STATE_OBSCURED:_("obscured"),
+ # Translators: a state that denotes that the object(text) is cropped as
it couldn't be accommodated in the allocated/available space
+ STATE_CROPPED:_("cropped"),
+ # Translators: a state that denotes that the object(text) is
overflowing into the adjacent space
+ STATE_OVERFLOWING:_("overflowing"),
}

negativeStateLabels={

diff --git a/source/core.py b/source/core.py
index f6b999b..79aa249 100644
--- a/source/core.py
+++ b/source/core.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#core.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NV Access Limited, Aleksey Sadovoy, Christopher Toth,
Joseph Lee, Peter Vágner
+#Copyright (C) 2006-2015 NV Access Limited, Aleksey Sadovoy, Christopher Toth,
Joseph Lee, Peter Vágner
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -58,9 +58,6 @@ def doStartupDialogs():
gui.messageBox(_("Your gesture map file contains errors.\n"
"More details about the errors can be found in
the log file."),
_("gesture map File Error"), wx.OK|wx.ICON_EXCLAMATION)
- if not config.conf["upgrade"]["newLaptopKeyboardLayout"]:
- from gui import upgradeAlerts
- upgradeAlerts.NewLaptopKeyboardLayout.run()

def restart(disableAddons=False):
"""Restarts NVDA by starting a new copy with -r."""
@@ -305,10 +302,10 @@ This initializes all modules such as audio, IAccessible,
keyboard, mouse, and GU
import globalPluginHandler
log.debug("Initializing global plugin handler")
globalPluginHandler.initialize()
- if globalVars.appArgs.install:
+ if globalVars.appArgs.install or globalVars.appArgs.installSilent:
import wx
import gui.installerGui
- wx.CallAfter(gui.installerGui.doSilentInstall)
+
wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not
globalVars.appArgs.installSilent)
elif not globalVars.appArgs.minimal:
try:
# Translators: This is shown on a braille display (if
one is connected) when NVDA starts.

diff --git a/source/cursorManager.py b/source/cursorManager.py
index 87fb5b2..8d681e3 100644
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -191,6 +191,14 @@ class CursorManager(baseObject.ScriptableObject):
self._caretMovementScriptHelper(gesture,textInfos.UNIT_LINE,1)
script_moveByLine_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET

+ def script_moveBySentence_back(self,gesture):
+
self._caretMovementScriptHelper(gesture,textInfos.UNIT_SENTENCE,-1)
+ script_moveBySentence_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+
+ def script_moveBySentence_forward(self,gesture):
+
self._caretMovementScriptHelper(gesture,textInfos.UNIT_SENTENCE,1)
+
script_moveBySentence_forward.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+
def script_moveByParagraph_back(self,gesture):

self._caretMovementScriptHelper(gesture,textInfos.UNIT_PARAGRAPH,-1)
script_moveByParagraph_back.resumeSayAllMode=sayAllHandler.CURSOR_CARET
@@ -335,6 +343,8 @@ class CursorManager(baseObject.ScriptableObject):
"kb:NVDA+Control+f": "find",
"kb:NVDA+f3": "findNext",
"kb:NVDA+shift+f3": "findPrevious",
+ "kb:alt+upArrow":"moveBySentence_back",
+ "kb:alt+downArrow":"moveBySentence_forward",
}

class _ReviewCursorManagerTextInfo(textInfos.TextInfo):

diff --git a/source/editableText.py b/source/editableText.py
index 0f05a71..a2de56a 100755
--- a/source/editableText.py
+++ b/source/editableText.py
@@ -127,6 +127,18 @@ class EditableText(ScriptableObject):
onlyInitial=False

speech.speakTextInfo(lineInfo,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET,onlyInitialFields=onlyInitial,suppressBlanks=True)

+ def _caretMoveBySentenceHelper(self, gesture, direction):
+ if isScriptWaiting():
+ return
+ try:
+ info=self.makeTextInfo(textInfos.POSITION_CARET)
+ info.move(textInfos.UNIT_SENTENCE, direction)
+ info.updateCaret()
+
self._caretScriptPostMovedHelper(textInfos.UNIT_SENTENCE,gesture,info)
+ except:
+ gesture.send()
+ return
+
def script_caret_moveByLine(self,gesture):
self._caretMovementScriptHelper(gesture, textInfos.UNIT_LINE)
script_caret_moveByLine.resumeSayAllMode=sayAllHandler.CURSOR_CARET
@@ -141,6 +153,13 @@ class EditableText(ScriptableObject):
self._caretMovementScriptHelper(gesture,
textInfos.UNIT_PARAGRAPH)
script_caret_moveByParagraph.resumeSayAllMode=sayAllHandler.CURSOR_CARET

+ def script_caret_previousSentence(self,gesture):
+ self._caretMoveBySentenceHelper(gesture, -1)
+
script_caret_previousSentence.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+
+ def script_caret_nextSentence(self,gesture):
+ self._caretMoveBySentenceHelper(gesture, 1)
+ script_caret_nextSentence.resumeSayAllMode=sayAllHandler.CURSOR_CARET

def _backspaceScriptHelper(self,unit,gesture):
try:
@@ -196,6 +215,8 @@ class EditableText(ScriptableObject):
"kb:control+rightArrow": "caret_moveByWord",
"kb:control+upArrow": "caret_moveByParagraph",
"kb:control+downArrow": "caret_moveByParagraph",
+ "kb:alt+upArrow": "caret_previousSentence",
+ "kb:alt+downArrow": "caret_nextSentence",
"kb:home": "caret_moveByCharacter",
"kb:end": "caret_moveByCharacter",
"kb:control+home": "caret_moveByLine",

diff --git a/source/globalCommands.py b/source/globalCommands.py
index 4b8ebe8..b35f2bc 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -1347,8 +1347,12 @@ class GlobalCommands(ScriptableObject):
index=(index+1)%len(touchHandler.availableTouchModes)
newMode=touchHandler.availableTouchModes[index]
touchHandler.handler._curTouchMode=newMode
- # Translators: Cycles through available touch modes (a group of
related touch gestures; example output: "object mode"; see the user guide for
more information on touch modes).
- ui.message(_("%s mode")%newMode)
+ try:
+ newModeLabel=touchHandler.touchModeLabels[newMode]
+ except KeyError:
+ # Translators: Cycles through available touch modes (a
group of related touch gestures; example output: "object mode"; see the user
guide for more information on touch modes).
+ newModeLabel=_("%s mode")%newMode
+ ui.message(newModeLabel)
# Translators: Input help mode message for a touchscreen gesture.
script_touch_changeMode.__doc__=_("cycles between available touch
modes")
script_touch_changeMode.category=SCRCAT_TOUCH

diff --git a/source/gui/installerGui.py b/source/gui/installerGui.py
index 5982e24..9701aca 100644
--- a/source/gui/installerGui.py
+++ b/source/gui/installerGui.py
@@ -17,7 +17,7 @@ from logHandler import log
import gui
import tones

-def
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,silent=False):
+def
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,silent=False,startAfterInstall=True):
progressDialog = gui.IndeterminateProgressDialog(gui.mainFrame,
# Translators: The title of the dialog presented while NVDA is
being updated.
_("Updating NVDA") if isUpdate
@@ -45,7 +45,7 @@ def
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,sil
# Translators: the title of a retry cancel dialog when NVDA
installation fails
title=_("File in Use")
if
winUser.MessageBox(None,message,title,winUser.MB_RETRYCANCEL)==winUser.IDRETRY:
- return
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,silent)
+ return
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,silent,startAfterInstall)
if res!=0:
log.error("Installation failed: %s"%res)
# Translators: The message displayed when an error occurs
during installation of NVDA.
@@ -65,15 +65,18 @@ def
doInstall(createDesktopShortcut,startOnLogon,copyPortableConfig,isUpdate,sil
gui.messageBox(msg+_("Please press OK to start the installed
copy."),
# Translators: The title of a dialog presented to
indicate a successful operation.
_("Success"))
- # #4475: ensure that the first window of the new process is not hidden
by providing SW_SHOWNORMAL
- shellapi.ShellExecute(None, None,
- os.path.join(installer.defaultInstallPath,'nvda.exe'),
- u"-r",
- None, winUser.SW_SHOWNORMAL)
-
-def doSilentInstall():
+ if startAfterInstall:
+ # #4475: ensure that the first window of the new process is not
hidden by providing SW_SHOWNORMAL
+ shellapi.ShellExecute(None, None,
+ os.path.join(installer.defaultInstallPath,'nvda.exe'),
+ u"-r",
+ None, winUser.SW_SHOWNORMAL)
+ else:
+ wx.GetApp().ExitMainLoop()
+
+def doSilentInstall(startAfterInstall=True):
prevInstall=installer.isPreviousInstall()
- doInstall(installer.isDesktopShortcutInstalled() if prevInstall else
True,config.getStartOnLogonScreen() if prevInstall else
True,False,prevInstall,True)
+ doInstall(installer.isDesktopShortcutInstalled() if prevInstall else
True,config.getStartOnLogonScreen() if prevInstall else
True,False,prevInstall,silent=True,startAfterInstall=startAfterInstall)

class InstallerDialog(wx.Dialog):


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

https://bitbucket.org/nvdaaddonteam/nvda/commits/e4c7b9a459a9/
Changeset: e4c7b9a459a9
Branch: None
User: jteh
Date: 2015-04-17 04:06:58+00:00
Summary: Merge branch 't4673' into next

Incubates #4673.

Affected #: 32 files

diff --git a/miscDeps b/miscDeps
index 703676b..6ae89fa 160000
--- a/miscDeps
+++ b/miscDeps
@@ -1 +1 @@
-Subproject commit 703676b5edf1a7883bbc5b8f0d3863d0245bf542
+Subproject commit 6ae89fa504b1cad4d15d74f64dc8b7cae200e5b2

diff --git a/nvdaHelper/ISimpleDOM_sconscript b/nvdaHelper/ISimpleDOM_sconscript
new file mode 100644
index 0000000..40a2fc9
--- /dev/null
+++ b/nvdaHelper/ISimpleDOM_sconscript
@@ -0,0 +1,28 @@
+###
+#This file is a part of the NVDA project.
+#URL: http://www.nvda-project.org/
+#Copyright 2006-2010 NVDA contributers.
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License version 2.0, as
published by
+#the Free Software Foundation.
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#This license can be found at:
+#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+###
+
+Import('env')
+
+env['MIDLCOM']=env['MIDLCOM'][:-6]
+
+env.Command("ISimpleDOMText.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMText.idl",Copy("$TARGET","$SOURCE"))
+env.Command("ISimpleDOMDocument.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMDocument.idl",Copy("$TARGET","$SOURCE"))
+idlFile=env.Command("ISimpleDOMNode.idl","#/miscDeps/include/ISimpleDOM/ISimpleDOMNode.idl",Copy("$TARGET","$SOURCE"))
+
+tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
+ source=idlFile,
+ MIDLFLAGS=['/c_ext','/I',Dir('.')],
+)
+
+Return(['tlbFile','headerFile','iidSourceFile','proxySourceFile','dlldataSourceFile'])

diff --git a/nvdaHelper/archBuild_sconscript b/nvdaHelper/archBuild_sconscript
index fd45e07..03141dd 100644
--- a/nvdaHelper/archBuild_sconscript
+++ b/nvdaHelper/archBuild_sconscript
@@ -73,6 +73,14 @@ env.Install(libInstallDir,ia2RPCStubs[0]) #proxy dll
if TARGET_ARCH=='x86':
env.Install(sourceTypelibDir,ia2RPCStubs[1]) #typelib

+iSimpleDomRPCStubs=env.SConscript('ISimpleDOM_sconscript')
+if TARGET_ARCH=='x86':
+ env.Install(sourceTypelibDir,iSimpleDomRPCStubs[0]) #typelib
+
+mathPlayerRPCStubs=env.SConscript('mathPlayer_sconscript')
+if TARGET_ARCH=='x86':
+ env.Install(sourceTypelibDir,mathPlayerRPCStubs[0]) #typelib
+
if TARGET_ARCH=='x86':
localLib=env.SConscript('local/sconscript')
Export('localLib')

diff --git a/nvdaHelper/mathPlayer_sconscript b/nvdaHelper/mathPlayer_sconscript
new file mode 100644
index 0000000..592587d
--- /dev/null
+++ b/nvdaHelper/mathPlayer_sconscript
@@ -0,0 +1,25 @@
+###
+#This file is a part of the NVDA project.
+#URL: http://www.nvda-project.org/
+#Copyright 2006-2010 NVDA contributers.
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License version 2.0, as
published by
+#the Free Software Foundation.
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#This license can be found at:
+#http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+###
+
+Import('env')
+
+env.Command("MathSpeechEnums.idl","#/miscDeps/include/mathPlayer/MathSpeechEnums.idl",Copy("$TARGET","$SOURCE"))
+idlFile=env.Command("mathPlayerDLL.idl","#/miscDeps/include/mathPlayer/mathPlayerDLL.idl",Copy("$TARGET","$SOURCE"))
+
+tlbFile,headerFile,iidSourceFile,proxySourceFile,dlldataSourceFile=env.TypeLibrary(
+ source=idlFile,
+ MIDLFLAGS=['/I',Dir('.')],
+)
+
+Return(['tlbFile','headerFile','iidSourceFile','proxySourceFile','dlldataSourceFile'])

diff --git a/nvdaHelper/remote/winword.cpp b/nvdaHelper/remote/winword.cpp
index 1139d73..41ba2bc 100644
--- a/nvdaHelper/remote/winword.cpp
+++ b/nvdaHelper/remote/winword.cpp
@@ -104,6 +104,7 @@ using namespace std;
#define wdDISPID_RANGE_INLINESHAPES 319
#define wdDISPID_INLINESHAPES_COUNT 1
#define wdDISPID_INLINESHAPES_ITEM 0
+#define wdDISPID_INLINESHAPE_OLEFORMAT 5
#define wdDISPID_INLINESHAPE_TYPE 6
#define wdDISPID_INLINESHAPE_ALTERNATIVETEXT 131
#define wdDISPID_INLINESHAPE_TITLE 158
@@ -131,6 +132,7 @@ using namespace std;
#define wdDISPID_PARAGRAPHFORMAT_RIGHTINDENT 106
#define wdDISPID_PARAGRAPHFORMAT_LEFTINDENT 107
#define wdDISPID_PARAGRAPHFORMAT_FIRSTLINEINDENT 108
+#define wdDISPID_OLEFORMAT_PROGID 22

#define wdCommentsStory 4

@@ -159,6 +161,10 @@ using namespace std;
#define wdNoProofing 1024 //&H400
#define wdLanguageUnknown 9999999

+#define wdInlineShapeEmbeddedOLEObject 1
+#define wdInlineShapePicture 3
+#define wdInlineShapeLinkedPicture 4
+
#define formatConfig_reportFontName 1
#define formatConfig_reportFontSize 2
#define formatConfig_reportFontAttributes 4
@@ -675,7 +681,7 @@ inline int getInlineShapesCount(IDispatch* pDispatchRange) {
* Generates an opening tag for the first inline shape in this range if one
exists.
* If the function is successful, the total number of inline shapes for this
range is returned allowing the caller to then perhaps move the range forward a
character and try again.
*/
-inline int generateInlineShapeXML(IDispatch* pDispatchRange, wostringstream&
XMLStream) {
+inline int generateInlineShapeXML(IDispatch* pDispatchRange, int offset,
wostringstream& XMLStream) {
IDispatchPtr pDispatchShapes=NULL;
IDispatchPtr pDispatchShape=NULL;
int count=0;
@@ -707,7 +713,19 @@ inline int generateInlineShapeXML(IDispatch*
pDispatchRange, wostringstream& XML
}
SysFreeString(altText);
}
- XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<((shapeType==3||shapeType==4)?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\">";
+ XMLStream<<L"<control _startOfNode=\"1\"
role=\""<<((shapeType==wdInlineShapePicture||shapeType==wdInlineShapeLinkedPicture)?L"graphic":L"object")<<L"\"
value=\""<<altTextStr<<L"\"";
+ if(shapeType==wdInlineShapeEmbeddedOLEObject) {
+ XMLStream<<L" shapeoffset=\""<<offset<<L"\"";
+ IDispatchPtr pOLEFormat=NULL;
+
if(_com_dispatch_raw_propget(pDispatchShape,wdDISPID_INLINESHAPE_OLEFORMAT,VT_DISPATCH,&pOLEFormat)==S_OK)
{
+ BSTR progId=NULL;
+
if(_com_dispatch_raw_propget(pOLEFormat,wdDISPID_OLEFORMAT_PROGID,VT_BSTR,&progId)==S_OK&&progId)
{
+ XMLStream<<L" progid=\""<<progId<<"\"";
+ SysFreeString(progId);
+ }
+ }
+ }
+ XMLStream<<L">";
return count;
}

@@ -871,7 +889,7 @@ void winword_getTextInRange_helper(HWND hwnd,
winword_getTextInRange_args* args)
}
//If there are inline shapes somewhere, try getting and
generating info for the first one hear.
//We also get the over all count of shapes for this
word so we know whether we need to check for more within this word
- int
inlineShapesCount=hasInlineShapes?generateInlineShapeXML(pDispatchRange,XMLStream):0;
+ int
inlineShapesCount=hasInlineShapes?generateInlineShapeXML(pDispatchRange,chunkStartOffset,XMLStream):0;
if(inlineShapesCount>1) {

_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_COLLAPSE,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdCollapseStart);

if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_MOVEEND,DISPATCH_METHOD,VT_I4,&unitsMoved,L"\x0003\x0003",wdCharacter,1)!=S_OK||unitsMoved<=0)
{

diff --git a/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
b/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
index 654a425..0fa5ad7 100644
--- a/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
+++ b/nvdaHelper/vbufBackends/adobeAcrobat/adobeAcrobat.cpp
@@ -427,6 +427,8 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(

BSTR stdName = NULL;
int textFlags = 0;
+ // Whether to render just a space in place of the content.
+ bool renderSpace = false;
BSTR tempBstr = NULL;
if (domElement) {
// Get stdName.
@@ -440,6 +442,11 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
// This is an inline element.
parentNode->isBlock=false;
}
+ if (wcscmp(stdName, L"Formula") == 0) {
+ // We don't want the content of formulas,
+ // but we still want a space so the user can
get at them.
+ renderSpace = true;
+ }
}

// Get language.
@@ -472,7 +479,7 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
int childCount=0;
// We don't want to descend into lists and combo boxes.
// Besides, Acrobat reports the child count, but the children can't be
accessed.
- if (role != ROLE_SYSTEM_LIST && role != ROLE_SYSTEM_COMBOBOX) {
+ if (!renderSpace && role != ROLE_SYSTEM_LIST && role !=
ROLE_SYSTEM_COMBOBOX) {
LOG_DEBUG(L"get childCount with
IAccessible::get_accChildCount");
if((res=pacc->get_accChildCount((long*)(&childCount)))!=S_OK) {
LOG_DEBUG(L"pacc->get_accChildCount returned "<<res);
@@ -599,8 +606,15 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
}
}

- // Iterate through the children.
- if (childCount > 0) {
+ if (renderSpace) {
+ // Just render a space.
+ if (tempNode = buffer->addTextFieldNode(parentNode,
previousNode, L" ")) {
+ addAttrsToTextNode(tempNode);
+ previousNode=tempNode;
+ }
+
+ } else if (childCount > 0) {
+ // Iterate through the children.
LOG_DEBUG(L"Allocate memory to hold children");
VARIANT* varChildren;

if((varChildren=(VARIANT*)malloc(sizeof(VARIANT)*childCount))==NULL) {
@@ -644,8 +658,8 @@ AdobeAcrobatVBufStorage_controlFieldNode_t*
AdobeAcrobatVBufBackend_t::fillVBuf(
}
LOG_DEBUG(L"Freeing memory holding children");
free(varChildren);
- } else {

+ } else {
// No children, so this is a leaf node.
if (!this->isXFA && !stdName) {
// Non-XFA leaf nodes with no stdName are inline.

diff --git a/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
b/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
index fdf2f70..c42c134 100755
--- a/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
+++ b/nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
@@ -486,7 +486,7 @@ VBufStorage_fieldNode_t*
GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
// Whether this node is interactive.
// Certain objects are never interactive, even if other checks are true.
bool isNeverInteractive = parentNode->isHidden||(!isEditable && (isRoot
|| role == ROLE_SYSTEM_DOCUMENT || role == IA2_ROLE_INTERNAL_FRAME));
- bool isInteractive = !isNeverInteractive && (isEditable || inLink ||
states & STATE_SYSTEM_FOCUSABLE || states & STATE_SYSTEM_UNAVAILABLE ||
isEmbeddedApp);
+ bool isInteractive = !isNeverInteractive && (isEditable || inLink ||
states & STATE_SYSTEM_FOCUSABLE || states & STATE_SYSTEM_UNAVAILABLE ||
isEmbeddedApp || role == ROLE_SYSTEM_EQUATION);
// We aren't finished calculating isInteractive yet; actions are
handled below.
// Whether the name is the content of this node.
bool nameIsContent = isEmbeddedApp
@@ -534,6 +534,7 @@ VBufStorage_fieldNode_t*
GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc,
|| (role == ROLE_SYSTEM_LIST && !(states &
STATE_SYSTEM_READONLY))
|| isEmbeddedApp
|| role == ROLE_SYSTEM_OUTLINE
+ || role == ROLE_SYSTEM_EQUATION
|| (nameIsContent && (IA2AttribsMapIt =
IA2AttribsMap.find(L"explicit-name")) != IA2AttribsMap.end() &&
IA2AttribsMapIt->second == L"true")
)
renderChildren = false;

diff --git a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
index f191f99..3db4129 100755
--- a/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/mshtml.cpp
@@ -1085,9 +1085,10 @@ VBufStorage_fieldNode_t*
MshtmlVBufBackend_t::fillVBuf(VBufStorage_buffer_t* buf
} else if(nodeName.compare(L"BR")==0) {
LOG_DEBUG(L"node is a br tag, adding a line feed as its text.");
contentString=L"\n";
- } else if (nodeName.compare(L"MATH")==0) {
- contentString=IAName;
- } else
if((!isRoot&&(IARole==ROLE_SYSTEM_APPLICATION||IARole==ROLE_SYSTEM_DIALOG))||IARole==ROLE_SYSTEM_OUTLINE)
{
+ } else
if((!isRoot&&(IARole==ROLE_SYSTEM_APPLICATION||IARole==ROLE_SYSTEM_DIALOG))
+ ||IARole==ROLE_SYSTEM_OUTLINE
+ ||nodeName.compare(L"MATH")==0
+ ) {
contentString=L" ";
} else {
renderChildren=true;

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index 6589148..e8a3adc 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -467,3 +467,10 @@ void
MshtmlVBufStorage_controlFieldNode_t::postProcessLiveRegion(VBufStorage_con
this->reportLiveText(newChildrenText);
}
}
+
+void
MshtmlVBufStorage_controlFieldNode_t::generateAttributesForMarkupOpeningTag(wstring&
text, int startOffset, int endOffset) {
+
VBufStorage_controlFieldNode_t::generateAttributesForMarkupOpeningTag(text,
startOffset, endOffset);
+ wostringstream s;
+ s << L"language=\"" << language << L"\" ";
+ text += s.str();
+}

diff --git a/nvdaHelper/vbufBackends/mshtml/node.h
b/nvdaHelper/vbufBackends/mshtml/node.h
index af391c6..0d9a8e3 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.h
+++ b/nvdaHelper/vbufBackends/mshtml/node.h
@@ -40,6 +40,7 @@ class MshtmlVBufStorage_controlFieldNode_t : public
VBufStorage_controlFieldNode
void reportLiveAddition();
void preProcessLiveRegion(const MshtmlVBufStorage_controlFieldNode_t*
parent, const std::map<std::wstring,std::wstring>& attribsMap);
void postProcessLiveRegion(VBufStorage_controlFieldNode_t* oldNode,
std::set<VBufStorage_controlFieldNode_t*>& atomicNodes);
+ virtual void generateAttributesForMarkupOpeningTag(std::wstring& text,
int startOffset, int endOffset);
bool isRootNode;
MshtmlVBufStorage_controlFieldNode_t(int docHandle, int ID, bool
isBlock, MshtmlVBufBackend_t* backend, bool isRootNode, IHTMLDOMNode*
pHTMLDOMNode, const std::wstring& lang);
~MshtmlVBufStorage_controlFieldNode_t();

diff --git a/source/IAccessibleHandler.py b/source/IAccessibleHandler.py
index ce4e868..ef49b9d 100644
--- a/source/IAccessibleHandler.py
+++ b/source/IAccessibleHandler.py
@@ -202,7 +202,7 @@ IAccessibleRolesToNVDARoles={
oleacc.ROLE_SYSTEM_DIAL:controlTypes.ROLE_DIAL,
oleacc.ROLE_SYSTEM_DROPLIST:controlTypes.ROLE_DROPLIST,
oleacc.ROLE_SYSTEM_BUTTONMENU:controlTypes.ROLE_MENUBUTTON,
- oleacc.ROLE_SYSTEM_EQUATION:controlTypes.ROLE_EQUATION,
+ oleacc.ROLE_SYSTEM_EQUATION:controlTypes.ROLE_MATH,
oleacc.ROLE_SYSTEM_GRIP:controlTypes.ROLE_GRIP,
oleacc.ROLE_SYSTEM_HOTKEYFIELD:controlTypes.ROLE_HOTKEYFIELD,
oleacc.ROLE_SYSTEM_INDICATOR:controlTypes.ROLE_INDICATOR,

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index 709e39f..a797442 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -1,6 +1,6 @@
#NVDAObjects/MSHTML.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2015 NV Access Limited, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -119,6 +119,7 @@ nodeNamesToNVDARoles={
"FIELDSET":controlTypes.ROLE_GROUPING,
"OPTION":controlTypes.ROLE_LISTITEM,
"BLOCKQUOTE":controlTypes.ROLE_BLOCKQUOTE,
+ "MATH":controlTypes.ROLE_MATH,
}

def getZoomFactorsFromHTMLDocument(HTMLDocument):
@@ -482,6 +483,8 @@ class MSHTML(IAccessible):
clsList.append(Object)
elif nodeName=="FIELDSET":
clsList.append(Fieldset)
+ elif nodeName=="MATH":
+ clsList.append(Math)
clsList.append(MSHTML)
if not self.HTMLNodeHasAncestorIAccessible:
# The IAccessibleObject is for this node (not an
ancestor), so IAccessible overlay classes are relevant.
@@ -950,6 +953,17 @@ class MSHTML(IAccessible):
info.append("MSHTML nodeName: %s" % ret)
return info

+ def _get_language(self):
+ ti = self.treeInterceptor
+ if not ti:
+ # This is too slow to calculate without a buffer.
+ # This case should be pretty rare anyway.
+ return None
+ try:
+ return ti.getControlFieldForNVDAObject(self)["language"]
+ except LookupError:
+ return None
+
class V6ComboBox(IAccessible):
"""The object which receives value change events for combo boxes in
MSHTML/IE 6.
"""
@@ -1051,6 +1065,16 @@ class RootClient(IAccessible):
class MSAATextLeaf(IAccessible):
role=controlTypes.ROLE_STATICTEXT

+class Math(MSHTML):
+ role = controlTypes.ROLE_MATH
+
+ def _get_mathMl(self):
+ import mathPres
+ mathMl = mathPres.stripExtraneousXml(self.HTMLNode.outerHTML)
+ if not mathPres.getLanguageFromMath(mathMl) and self.language:
+ mathMl = mathPres.insertLanguageIntoMath(mathMl,
self.language)
+ return mathMl
+
def findExtraIAccessibleOverlayClasses(obj, clsList):
"""Determine the most appropriate class for MSHTML objects.
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses}
except that it never calls any other findOverlayClasses method.

diff --git a/source/NVDAObjects/IAccessible/__init__.py
b/source/NVDAObjects/IAccessible/__init__.py
index 17a3bdd..d34aecb 100644
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -1,5 +1,5 @@
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2012 NVDA Contributors
+#Copyright (C) 2006-2015 NVDA Contributors
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -1433,6 +1433,17 @@ the NVDAObject for IAccessible
info.append("IAccessible2 attributes: %s" % ret)
return info

+ def _get_language(self):
+ try:
+ ia2Locale = self.IAccessibleObject.locale
+ except (AttributeError, COMError):
+ return None
+ if ia2Locale.language and ia2Locale.country:
+ return "%s_%s" % (ia2Locale.language, ia2Locale.country)
+ elif ia2Locale.language:
+ return ia2Locale.language
+ return None
+
class ContentGenericClient(IAccessible):

TextInfo=displayModel.DisplayModelTextInfo

diff --git a/source/NVDAObjects/IAccessible/adobeAcrobat.py
b/source/NVDAObjects/IAccessible/adobeAcrobat.py
index d4d3639..13240e3 100644
--- a/source/NVDAObjects/IAccessible/adobeAcrobat.py
+++ b/source/NVDAObjects/IAccessible/adobeAcrobat.py
@@ -1,3 +1,9 @@
+#braille.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2008-2014 NV Access Limited
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
import api
import controlTypes
import eventHandler
@@ -27,7 +33,8 @@ stdNamesToRoles = {
"P": controlTypes.ROLE_PARAGRAPH,
"H": controlTypes.ROLE_HEADING,
# H1 to H6 handled separately
- # Span, Quote, Note, Reference, BibEntry, Code, Figure, Formula
+ # Span, Quote, Note, Reference, BibEntry, Code, Figure
+ "Formula": controlTypes.ROLE_MATH,
"Form": controlTypes.ROLE_FORM,
}

@@ -97,6 +104,40 @@ class AcrobatNode(IAccessible):
return self.accID == other.accID
return super(AcrobatNode, self)._isEqual(other)

+ def _getNodeMathMl(self, node):
+ tag = node.GetTagName()
+ yield "<%s" % tag
+ # Output relevant attributes.
+ if tag == "mfenced":
+ for attr in "open", "close", "separators":
+ val = node.GetAttribute(attr, "XML-1.00")
+ if val:
+ yield ' %s="%s"' % (attr, val)
+ yield ">"
+ val = node.GetValue()
+ if val:
+ yield val
+ else:
+ for childNum in xrange(node.GetChildCount()):
+ try:
+ subNode =
node.GetChild(childNum).QueryInterface(IPDDomElement)
+ except COMError:
+ continue
+ for sub in self._getNodeMathMl(subNode):
+ yield sub
+ yield "</%s>" % tag
+
+ def _get_mathMl(self):
+ # There could be other stuff before the math element. Ug.
+ for childNum in xrange(self.pdDomNode.GetChildCount()):
+ try:
+ child =
self.pdDomNode.GetChild(childNum).QueryInterface(IPDDomElement)
+ except COMError:
+ continue
+ if child.GetTagName() == "math":
+ return "".join(self._getNodeMathMl(child))
+ raise LookupError
+
class RootNode(AcrobatNode):
shouldAllowIAccessibleFocusEvent = True


diff --git a/source/NVDAObjects/IAccessible/mozilla.py
b/source/NVDAObjects/IAccessible/mozilla.py
index a96f0c6..8676ab5 100755
--- a/source/NVDAObjects/IAccessible/mozilla.py
+++ b/source/NVDAObjects/IAccessible/mozilla.py
@@ -1,14 +1,16 @@
+# -*- coding: UTF-8 -*-
#NVDAObjects/IAccessible/mozilla.py
#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) 2006-2010 Michael Curran <mick@xxxxxxxxxx>, James Teh
<jamie@xxxxxxxxxxx>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner

from collections import namedtuple
+from ctypes import c_short
import IAccessibleHandler
import oleacc
import winUser
-from comtypes import IServiceProvider, COMError
+from comtypes import IServiceProvider, COMError, BSTR
import eventHandler
import controlTypes
from . import IAccessible, Dialog, WindowRoot
@@ -170,6 +172,27 @@ class TextLeaf(Mozilla):
class Application(Document):
shouldCreateTreeInterceptor = False

+class Math(Mozilla):
+
+ def _get_mathMl(self):
+ from comtypes.gen.ISimpleDOM import ISimpleDOMNode
+ node = self.IAccessibleObject.QueryInterface(ISimpleDOMNode)
+ # Try the data-mathml attribute.
+ attr = node.attributesForNames(1, (BSTR * 1)("data-mathml"),
(c_short * 1)(0,))
+ if attr:
+ import mathPres
+ if not mathPres.getLanguageFromMath(attr) and
self.language:
+ attr = mathPres.insertLanguageIntoMath(attr,
self.language)
+ return attr
+ if self.IA2Attributes.get("tag") != "math":
+ # This isn't MathML.
+ raise LookupError
+ if self.language:
+ attrs = ' xml:lang="%s"' % self.language
+ else:
+ attrs = ""
+ return "<math%s>%s</math>" % (attrs, node.innerHTML)
+
def findExtraOverlayClasses(obj, clsList):
"""Determine the most appropriate class if this is a Mozilla object.
This works similarly to L{NVDAObjects.NVDAObject.findOverlayClasses}
except that it never calls any other findOverlayClasses method.
@@ -246,6 +269,7 @@ _IAccessibleRolesToOverlayClasses = {
"object": EmbeddedObject,
oleacc.ROLE_SYSTEM_APPLICATION: Application,
oleacc.ROLE_SYSTEM_DIALOG: Application,
+ oleacc.ROLE_SYSTEM_EQUATION: Math,
}

#: Roles that mightn't set the focused state when they are focused.

diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
index 4534ee7..0a46dc0 100644
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -1,6 +1,7 @@
+# -*- coding: UTF-8 -*-
#NVDAObjects/__init__.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-20012 NVDA Contributors
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
Patrick Zajda
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -1042,3 +1043,15 @@ This code is executed if a gain focus event is received
by this object.
# Don't cache sleepMode, as it is derived from a property which might
change
# and we want the changed value immediately.
_cache_sleepMode = False
+
+ def _get_mathMl(self):
+ """Obtain the MathML markup for an object containing math
content.
+ This will only be called (and thus only needs to be
implemented) for
+ objects with a role of L{controlTypes.ROLE_MATH}.
+ @raise LookupError: If MathML can't be retrieved for this
object.
+ """
+ raise NotImplementedError
+
+ #: The language/locale of this object.
+ #: @type: basestring
+ language = None

diff --git a/source/NVDAObjects/window/winword.py
b/source/NVDAObjects/window/winword.py
index d0b2169..2ab302f 100755
--- a/source/NVDAObjects/window/winword.py
+++ b/source/NVDAObjects/window/winword.py
@@ -1,6 +1,6 @@
#appModules/winword.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2012 NVDA Contributors
+#Copyright (C) 2006-2015 NV Access Limited, Manish Agrawal
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -418,6 +418,10 @@ class WordDocumentTextInfo(textInfos.TextInfo):
shouldIncludeLayoutTables=True #: layout tables should always be
included (no matter the user's browse mode setting).

def activate(self):
+ import mathPres
+ mathMl=mathPres.getMathMlFromTextInfo(self)
+ if mathMl:
+ return mathPres.interactWithMathMl(mathMl)
# Handle activating links.
# It is necessary to expand to word to get a link as the link's
first character is never actually in the link!
tempRange=self._rangeObj.duplicate
@@ -523,7 +527,12 @@ class WordDocumentTextInfo(textInfos.TextInfo):
elif role=="graphic":
role=controlTypes.ROLE_GRAPHIC
elif role=="object":
- role=controlTypes.ROLE_EMBEDDEDOBJECT
+ progid=field.get("progid")
+ if progid and progid.startswith("Equation.DSMT"):
+ # MathType.
+ role=controlTypes.ROLE_MATH
+ else:
+ role=controlTypes.ROLE_EMBEDDEDOBJECT
else:
fieldType=int(field.pop('wdFieldType',-1))
if fieldType!=-1:
@@ -768,6 +777,19 @@ class WordDocumentTextInfo(textInfos.TextInfo):
self.obj.WinwordWindowObject.ScrollIntoView(self._rangeObj)

self.obj.WinwordSelectionObject.SetRange(self._rangeObj.Start,self._rangeObj.End)

+ def getMathMl(self, field):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ range = self._rangeObj.Duplicate
+ range.Start = int(field["shapeoffset"])
+ obj = range.InlineShapes[0].OLEFormat
+ try:
+ return mathType.getMathMl(obj)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
class WordDocumentTextInfoForTreeInterceptor(WordDocumentTextInfo):

def _get_shouldIncludeLayoutTables(self):
@@ -826,6 +848,9 @@ class BrowseModeWordDocumentTextInfo(textInfos.TextInfo):
def expand(self,unit):
return self.innerTextInfo.expand(unit)

+ def getMathMl(self, field):
+ return self.innerTextInfo.getMathMl(field)
+
class
WordDocumentTreeInterceptor(CursorManager,browseMode.BrowseModeTreeInterceptor,treeInterceptorHandler.DocumentTreeInterceptor):

TextInfo=BrowseModeWordDocumentTextInfo

diff --git a/source/appModules/powerpnt.py b/source/appModules/powerpnt.py
index 89d9993..c75a1f8 100644
--- a/source/appModules/powerpnt.py
+++ b/source/appModules/powerpnt.py
@@ -1,6 +1,6 @@
#appModules/powerpnt.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2012-2013 NV Access Limited
+#Copyright (C) 2012-2014 NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -37,6 +37,8 @@ import scriptHandler
# These also all request to have their (incomplete) UI Automation
implementations disabled. [MS Office 2013]
objectModelWindowClasses=set(["paneClassDC","mdiClass","screenClass"])

+MATHTYPE_PROGID = "Equation.DSMT"
+
#comtypes COM interface definition for Powerpoint application object's events
class EApplication(IDispatch):
_iid_=comtypes.GUID('{914934C2-5A91-11CF-8700-00AA0060263B}')
@@ -515,6 +517,12 @@ class Shape(PpObject):

presentationType=Window.presType_content

+ def __init__(self, **kwargs):
+ super(Shape, self).__init__(**kwargs)
+ if self.role == controlTypes.ROLE_EMBEDDEDOBJECT:
+ if
self.ppObject.OLEFormat.ProgID.startswith(MATHTYPE_PROGID):
+ self.role = controlTypes.ROLE_MATH
+
def _get__overlapInfo(self):

slideWidth=self.appModule._ppApplication.activePresentation.pageSetup.slideWidth

slideHeight=self.appModule._ppApplication.activePresentation.pageSetup.slideHeight
@@ -762,6 +770,19 @@ class Shape(PpObject):
states.add(controlTypes.STATE_OFFSCREEN)
return states

+ def _get_mathMl(self):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ obj = self.ppObject.OLEFormat
+ try:
+ # Don't call RunForConversion, as this seems to make
focus bounce.
+ # We don't seem to need it for PowerPoint anyway.
+ return mathType.getMathMl(obj, runForConversion=False)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
__gestures={
"kb:leftArrow":"moveHorizontal",
"kb:rightArrow":"moveHorizontal",
@@ -933,6 +954,44 @@ class SlideShowTreeInterceptorTextInfo(NVDAObjectTextInfo):
return (0,self._getStoryLength())
raise LookupError

+ def getTextWithFields(self,formatConfig=None):
+ fields = self.obj.rootNVDAObject.basicTextFields
+ text = self.obj.rootNVDAObject.basicText
+ out = []
+ textOffset = self._startOffset
+ for fieldOffset, field in fields:
+ if fieldOffset < self._startOffset:
+ continue
+ elif fieldOffset >= self._endOffset:
+ break
+ # Output any text before the field.
+ chunk = text[textOffset:fieldOffset]
+ if chunk:
+ out.append(chunk)
+ # Output the field.
+ out.extend((
+ # Copy the field so the original isn't modified.
+ textInfos.FieldCommand("controlStart",
textInfos.ControlField(field)),
+ u" ", textInfos.FieldCommand("controlEnd",
None)))
+ textOffset = fieldOffset + 1
+ # Output any text after all fields in this range.
+ chunk = text[textOffset:self._endOffset]
+ if chunk:
+ out.append(chunk)
+ return out
+
+ def getMathMl(self, field):
+ try:
+ import mathType
+ except:
+ raise LookupError("MathType not installed")
+ try:
+ # Don't call RunForConversion, as this seems to make
focus bounce.
+ # We don't seem to need it for PowerPoint anyway.
+ return mathType.getMathMl(field["oleFormat"],
runForConversion=False)
+ except:
+ raise LookupError("Couldn't get MathML from MathType")
+
class SlideShowTreeInterceptor(TreeInterceptor):
"""A TreeInterceptor for showing Slide show content. Has no caret
navigation, a CursorManager must be used on top. """

@@ -1039,6 +1098,12 @@ class SlideShowWindow(PaneClassDC):
for chunk in
self._getShapeText(cell.shape,cellShape=True):
yield chunk
return
+ if shapeType==msoEmbeddedOLEObject:
+ oleFormat=shape.OLEFormat
+ if oleFormat.ProgID.startswith(MATHTYPE_PROGID):
+ yield
textInfos.ControlField(role=controlTypes.ROLE_MATH,
+ oleFormat=oleFormat, _startOfNode=True)
+ return
label=shape.alternativeText
if not label:
try:
@@ -1059,9 +1124,20 @@ class SlideShowWindow(PaneClassDC):
ppObject=self.currentSlide.ppObject
if self.notesMode:
ppObject=ppObject.notesPage
+ # Maintain a list of fields and the offsets at which they occur.
+ # For now, these are only control fields that consume a space.
+ fields=self.basicTextFields=[]
+ # Incrementation of textLen must include line feed added by
join.
+ textLen=0
for shape in ppObject.shapes:
for chunk in self._getShapeText(shape):
- chunks.append(chunk)
+ if isinstance(chunk,textInfos.ControlField):
+ fields.append((textLen,chunk))
+ chunks.append(" ")
+ textLen+=2
+ else:
+ chunks.append(chunk)
+ textLen+=len(chunk)+1
self.basicText="\n".join(chunks)
if not self.basicText:
if self.notesMode:

diff --git a/source/braille.py b/source/braille.py
index d49b588..fe54cdf 100644
--- a/source/braille.py
+++ b/source/braille.py
@@ -2,7 +2,7 @@
#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) 2008-2012 NV Access Limited
+#Copyright (C) 2008-2014 NV Access Limited

import itertools
import os
@@ -593,7 +593,8 @@ class NVDAObjectRegion(Region):
columnNumber=obj.columnNumber
except NotImplementedError:
columnNumber=None
- text = getBrailleTextForProperties(name=obj.name, role=obj.role,
+ role = obj.role
+ text = getBrailleTextForProperties(name=obj.name, role=role,
value=obj.value if not NVDAObjectHasUsefulText(obj)
else None ,
states=obj.states,
description=obj.description if
presConfig["reportObjectDescriptions"] else None,
@@ -605,6 +606,15 @@ class NVDAObjectRegion(Region):
rowHeaderText=obj.rowHeaderText if hasattr(obj,
"rowHeaderText") and config.conf["documentFormatting"]["reportTableHeaders"]
else None,
cellCoordsText=obj.cellCoordsText if
config.conf["documentFormatting"]["reportTableCellCoords"] else None,
)
+ if role == controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.brailleProvider:
+ try:
+ text += " " +
mathPres.brailleProvider.getBrailleForMathMl(
+ obj.mathMl)
+ except (NotImplementedError, LookupError):
+ pass
self.rawText = text + self.appendText
super(NVDAObjectRegion, self).update()

@@ -614,8 +624,10 @@ class NVDAObjectRegion(Region):
except NotImplementedError:
pass

-def getControlFieldBraille(field, ancestors, reportStart, formatConfig):
+def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig):
presCat = field.getPresentationCategory(ancestors, formatConfig)
+ # Cache this for later use.
+ field._presCat = presCat
if reportStart:
# If this is a container, only report it if this is the start
of the node.
if presCat == field.PRESCAT_CONTAINER and not
field.get("_startOfNode"):
@@ -652,7 +664,11 @@ def getControlFieldBraille(field, ancestors, reportStart,
formatConfig):
return getBrailleTextForProperties(**props)

elif reportStart:
- props = {"role": role, "states": states,"value":value}
+ props = {
+ # Don't report the role for math here.
+ # However, we still need to pass it (hence "_role").
+ "_role" if role == controlTypes.ROLE_MATH else "role":
role,
+ "states": states,"value":value}
if config.conf["presentation"]["reportKeyboardShortcuts"]:
kbShortcut = field.get("keyboardShortcut")
if kbShortcut:
@@ -660,7 +676,19 @@ def getControlFieldBraille(field, ancestors, reportStart,
formatConfig):
level = field.get("level")
if level:
props["positionInfo"] = {"level": level}
- return getBrailleTextForProperties(**props)
+ text = getBrailleTextForProperties(**props)
+ if role == controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.brailleProvider:
+ try:
+ if text:
+ text += " "
+ text +=
mathPres.brailleProvider.getBrailleForMathMl(
+ info.getMathMl(field))
+ except (NotImplementedError, LookupError):
+ pass
+ return text
else:
# Translators: Displayed in braille at the end of a control
field such as a list or table.
# %s is replaced with the control's role.
@@ -785,10 +813,22 @@ class TextInfoRegion(Region):
ctrlFields.append(field)
if not text:
continue
+ if getattr(field, "_presCat") ==
field.PRESCAT_MARKER:
+ # In this case, the field text
is what the user cares about,
+ # not the actual content.
+ fieldStart = len(self.rawText)
+ if fieldStart > 0:
+ # There'll be a space
before the field text.
+ fieldStart += 1
+ if
shouldMoveCursorToFirstContent:
+
shouldMoveCursorToFirstContent = False
+ self.cursorPos =
fieldStart
+ elif isSelection and
self._selectionStart is None:
+ self._selectionStart =
fieldStart
self._addFieldText(text)
elif cmd == "controlEnd":
field = ctrlFields.pop()
- text = getControlFieldBraille(field,
ctrlFields, False, formatConfig)
+ text =
info.getControlFieldBraille(field, ctrlFields, False, formatConfig)
if not text:
continue
# Separate this field text from the
rest of the text.
@@ -1238,6 +1278,17 @@ def getFocusContextRegions(obj, oldFocusRegions=None):
_cachedFocusAncestorsEnd = ancestorsEnd

def getFocusRegions(obj, review=False):
+ # Allow objects to override normal behaviour.
+ try:
+ regions = obj.getBrailleRegions(review=review)
+ except (AttributeError, NotImplementedError):
+ pass
+ else:
+ for region in regions:
+ region.update()
+ yield region
+ return
+
# Late import to avoid circular import.
from treeInterceptorHandler import TreeInterceptor
from cursorManager import CursorManager

diff --git a/source/comInterfaces_sconscript b/source/comInterfaces_sconscript
index 1204606..4896a4c 100755
--- a/source/comInterfaces_sconscript
+++ b/source/comInterfaces_sconscript
@@ -38,6 +38,8 @@
sys.modules['comtypes.gen']=comtypes.gen=__import__("comInterfaces",globals(),lo
COM_INTERFACES = {
"UIAutomationClient.py": ('{944de083-8fb8-45cf-bcb7-c477acb2f897}',1,0),
"IAccessible2Lib.py": "typelibs/ia2.tlb",
+ "ISimpleDOM.py": "typelibs/ISimpleDOMNode.tlb",
+ "mathPlayer.py": "typelibs/mathPlayerDLL.tlb",
#"Accessibility.py": ('{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}',1,0),
"tom.py": ('{8CC497C9-A1DF-11CE-8098-00AA0047BE5D}',1,0),
"SpeechLib.py": ('{C866CA3A-32F7-11D2-9602-00C04F8EE628}',5,0),

diff --git a/source/controlTypes.py b/source/controlTypes.py
index e543fa3..b3ab20e 100644
--- a/source/controlTypes.py
+++ b/source/controlTypes.py
@@ -2,7 +2,7 @@
#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) 2007-2012 NV Access Limited
+#Copyright (C) 2007-2014 NV Access Limited

ROLE_UNKNOWN=0
ROLE_WINDOW=1
@@ -106,7 +106,8 @@ ROLE_DROPLIST=100
ROLE_SPLITBUTTON=101
ROLE_MENUBUTTON=102
ROLE_DROPDOWNBUTTONGRID=103
-ROLE_EQUATION=104
+ROLE_MATH=104
+ROLE_EQUATION=ROLE_MATH # Deprecated; for backwards compatibility.
ROLE_GRIP=105
ROLE_HOTKEYFIELD=106
ROLE_INDICATOR=107
@@ -402,8 +403,8 @@ roleLabels={
ROLE_MENUBUTTON:_("menu button"),
# Translators: Reported for a button which expands a grid when it is
pressed.
ROLE_DROPDOWNBUTTONGRID:_("drop down button grid"),
- # Translators: Identifies an equation.
- ROLE_EQUATION:_("equation"),
+ # Translators: Identifies mathematical content.
+ ROLE_MATH:_("math"),
# Translators: Identifies a grip control.
ROLE_GRIP:_("grip"),
# Translators: Identifies a hot key field (a field where one can enter
a hot key for something, such as assigning shortcut for icons on the desktop).

diff --git a/source/globalCommands.py b/source/globalCommands.py
index b30b832..bae043f 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -3,7 +3,7 @@
#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) 2006-2012 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista

import time
import itertools
@@ -1382,7 +1382,26 @@ class GlobalCommands(ScriptableObject):
wx.CallAfter(gui.mainFrame.onConfigProfilesCommand, None)
# Translators: Describes the command to open the Configuration Profiles
dialog.
script_activateConfigProfilesDialog.__doc__ = _("Shows the NVDA
Configuration Profiles dialog")
-
+
+ def script_interactWithMath(self, gesture):
+ import mathPres
+ mathMl = mathPres.getMathMlFromTextInfo(api.getReviewPosition())
+ if not mathMl:
+ obj = api.getNavigatorObject()
+ if obj.role == controlTypes.ROLE_MATH:
+ try:
+ mathMl = obj.mathMl
+ except (NotImplementedError, LookupError):
+ mathMl = None
+ if not mathMl:
+ # Translators: Reported when the user attempts math
interaction
+ # with something that isn't math.
+ ui.message(_("Not math"))
+ return
+ mathPres.interactWithMathMl(mathMl)
+ # Translators: Describes a command.
+ script_interactWithMath.__doc__ = _("Begins interaction with math
content")
+
__gestures = {
# Basic
"kb:NVDA+n": "showGui",
@@ -1560,6 +1579,7 @@ class GlobalCommands(ScriptableObject):
"kb:NVDA+control+z": "activatePythonConsole",
"kb:NVDA+control+f3": "reloadPlugins",
"kb(desktop):NVDA+control+f2": "test_navigatorDisplayModelText",
+ "kb:NVDA+alt+m": "interactWithMath",
}

#: The single global commands instance.

diff --git a/source/locale/en/symbols.dic b/source/locale/en/symbols.dic
index 37698cc..2707d4c 100644
--- a/source/locale/en/symbols.dic
+++ b/source/locale/en/symbols.dic
@@ -13,9 +13,9 @@ complexSymbols:
; phrase ending (?<=[^\s;]);(?=\s|$)
: phrase ending (?<=[^\s:]):(?=\s|$)
# Others
-decimal point (?<=\d)\.(?=\d)
+decimal point (?<![^\d -])\.(?=\d)
in-word ' (?<=[^\W_])['’]
-negative number (?<!\w)-(?=[$£€¥]?\d)
+negative number (?<!\w)-(?=[$£€¥.]?\d)

symbols:
# identifier replacement[[ level][ preserve]][ # display name]

diff --git a/source/mathPres/__init__.py b/source/mathPres/__init__.py
new file mode 100644
index 0000000..cf0cb52
--- /dev/null
+++ b/source/mathPres/__init__.py
@@ -0,0 +1,186 @@
+#mathPres/__init__.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2014 NV Access Limited
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+"""Framework for presentation of math.
+Three types of presentation are supported: speech, braille and interaction.
+All of these accept MathML markup.
+Plugins can register their own implementation for any or all of these
+using L{registerProvider}.
+"""
+
+import re
+from NVDAObjects.window import Window
+import controlTypes
+import api
+import virtualBuffers
+import eventHandler
+from logHandler import log
+import ui
+import textInfos
+
+class MathPresentationProvider(object):
+ """Implements presentation of math content.
+ A single provider does not need to implement all presentation types.
+ """
+
+ def getSpeechForMathMl(self, mathMl):
+ """Get speech output for specified MathML markup.
+ @param mathMl: The MathML markup.
+ @type mathMl: basestring
+ @return: A speech sequence.
+ @rtype: list of unicode and/or L{speech.SpeechCommand}
+ """
+ raise NotImplementedError
+
+ def getBrailleForMathMl(self, mathMl):
+ """Get braille output for specified MathML markup.
+ @param mathMl: The MathML markup.
+ @type mathMl: basestring
+ @return: A string of Unicode braille.
+ @rtype: unicode
+ """
+ raise NotImplementedError
+
+ def interactWithMathMl(self, mathMl):
+ """Begin interaction with specified MathML markup.
+ @param mathMl: The MathML markup.
+ """
+ raise NotImplementedError
+
+speechProvider = None
+brailleProvider = None
+interactionProvider = None
+
+def registerProvider(provider, speech=False, braille=False, interaction=False):
+ """Register a math presentation provider.
+ @param provider: The provider to register.
+ @type provider: L{MathPresentationProvider}
+ @param speech: Whether this provider supports speech output.
+ @type speech: bool
+ @param braille: Whether this provider supports braille output.
+ @type braille: bool
+ @param interaction: Whether this provider supports interaction.
+ @type interaction: bool
+ """
+ global speechProvider, brailleProvider, interactionProvider
+ if speech:
+ speechProvider = provider
+ if braille:
+ brailleProvider = provider
+ if interaction:
+ interactionProvider = provider
+
+def ensureInit():
+ # Register builtin providers if a plugin hasn't registered others.
+ if not speechProvider or not brailleProvider or not interactionProvider:
+ from . import mathPlayer
+ try:
+ provider = mathPlayer.MathPlayer()
+ except:
+ log.warning("MathPlayer 4 not available")
+ else:
+ registerProvider(provider, speech=not speechProvider,
+ braille=not brailleProvider, interaction=not
interactionProvider)
+
+class MathInteractionNVDAObject(Window):
+ """Base class for a fake NVDAObject which can be focused while
interacting with math.
+ Subclasses can bind commands to itneract with the content
+ and produce speech and braille output as they wish.
+ To begin interaction, call L{setFocus}.
+ Pressing escape exits interaction.
+ """
+
+ role = controlTypes.ROLE_MATH
+ # Override the window name.
+ name = None
+ # Any tree interceptor should not apply here.
+ treeInterceptor = None
+
+ def __init__(self, provider=None, mathMl=None):
+ self.parent = parent = api.getFocusObject()
+ self.provider = provider
+ super(MathInteractionNVDAObject,
self).__init__(windowHandle=parent.windowHandle)
+
+ def setFocus(self):
+ ti = self.parent.treeInterceptor
+ if isinstance(ti, virtualBuffers.VirtualBuffer):
+ # Normally, when entering browse mode from a descendant
(e.g. dialog),
+ # we want the cursor to move to the focus (#3145).
+ # However, we don't want this for math, as math isn't
focusable.
+ ti._enteringFromOutside = True
+ eventHandler.executeEvent("gainFocus", self)
+
+ def script_exit(self, gesture):
+ eventHandler.executeEvent("gainFocus", self.parent)
+ # Translators: Describes a command.
+ script_exit.__doc__ = _("Exit math interaction")
+
+ __gestures = {
+ "kb:escape": "exit",
+ }
+
+RE_STRIP_XML_PREFIX = re.compile(r"^.*?(?=<(?:\w+:)?math[ >])")
+def stripExtraneousXml(xml):
+ """Strip extraneous XML from MathML.
+ This is needed where retrieving MathML produces more than just the math
tag.
+ Currently, this strips anything before the opening of the math tag.
+ """
+ return RE_STRIP_XML_PREFIX.sub("", xml)
+
+def getMathMlFromTextInfo(pos):
+ """Get MathML (if any) at the start of a TextInfo.
+ The caller need not call L{ensureInit} before calling this function.
+ @param pos: The TextInfo in question.
+ @type pos: L{textInfos.TextInfo}
+ @return: The MathML or C{None} if there is no math.
+ @rtype: basestring
+ """
+ pos = pos.copy()
+ pos.expand(textInfos.UNIT_CHARACTER)
+ for item in reversed(pos.getTextWithFields()):
+ if not isinstance(item, textInfos.FieldCommand) or item.command
!= "controlStart":
+ continue
+ field = item.field
+ if field.get("role") != controlTypes.ROLE_MATH:
+ continue
+ try:
+ return pos.getMathMl(field)
+ except (NotImplementedError, LookupError):
+ continue
+ return None
+
+def interactWithMathMl(mathMl):
+ """Begin interaction with specified MathML markup, reporting any errors
to the user.
+ This is intended to be called from scripts.
+ If interaction isn't supported, this will be reported to the user.
+ The script should return after calling this function.
+ The caller need not call L{ensureInit} before calling this function.
+ @param mathMl: The MathML markup.
+ """
+ ensureInit()
+ if not interactionProvider:
+ # Translators: Reported when the user attempts math interaction
+ # but math interaction is not supported.
+ ui.message(_("Math interaction not supported."))
+ return
+ return interactionProvider.interactWithMathMl(mathMl)
+
+RE_MATH_LANG = re.compile(r"""<math.*? xml:lang=["']([^"']+)["'].*?>""")
+def getLanguageFromMath(mathMl):
+ """Get the language specified in a math tag.
+ @return: The language or C{None} if unspeicifed.
+ @rtype: basestring
+ """
+ m = RE_MATH_LANG.search(mathMl)
+ if m:
+ return m.group(1)
+ return None
+
+RE_MATH_APPEND = re.compile(r"(<math[^>]*)>")
+def insertLanguageIntoMath(mathMl, language):
+ """Insert the specified language into a math tag.
+ """
+ return RE_MATH_APPEND.sub(r'\1 xml:lang="%s">' % language, mathMl,
count=1)

diff --git a/source/mathPres/mathPlayer.py b/source/mathPres/mathPlayer.py
new file mode 100644
index 0000000..e21627a
--- /dev/null
+++ b/source/mathPres/mathPlayer.py
@@ -0,0 +1,145 @@
+# -*- coding: UTF-8 -*-
+#mathPlayer.py
+#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) 2014-2015 NV Access Limited
+
+"""Support for math presentation using MathPlayer 4.
+"""
+
+import re
+import comtypes.client
+from comtypes import COMError
+from comtypes.gen.MathPlayer import MPInterface, IMathSpeech,
IMathSpeechSettings, IMathNavigation, IMathBraille
+import speech
+from keyboardHandler import KeyboardInputGesture
+import braille
+import mathPres
+
+RE_MP_SPEECH = re.compile(
+ # Break.
+ r"<break time='(?P<break>\d+)ms'/> ?"
+ # Pronunciation of characters.
+ ur"|<say-as interpret-as='characters'>(?P<char>[^<])</say-as> ?"
+ # Specific pronunciation.
+ ur"|<phoneme alphabet='ipa' ph='(?P<ipa>[^']+)'> (?P<phonemeText>[^
<]+)</phoneme> ?"
+ # Prosody.
+ r"|<prosody(?: pitch='(?P<pitch>\d+)%')?(?:
volume='(?P<volume>\d+)%')?(?: rate='(?P<rate>\d+)%')?> ?"
+ r"|(?P<prosodyReset></prosody>) ?"
+ # Other tags, which we don't care about.
+ r"|<[^>]+> ?"
+ # Commas indicating pauses in navigation messages.
+ r"| ?(?P<comma>,) ?"
+ # Actual content.
+ r"|(?P<content>[^<,]+)")
+PROSODY_COMMANDS = {
+ "pitch": speech.PitchCommand,
+ "volume": speech.VolumeCommand,
+ "rate": speech.RateCommand,
+}
+def _processMpSpeech(text, language):
+ # MathPlayer's default rate is 180 wpm.
+ # Assume that 0% is 80 wpm and 100% is 450 wpm and scale accordingly.
+ synth = speech.getSynth()
+ wpm = synth._percentToParam(synth.rate, 80, 450)
+ breakMulti = 180.0 / wpm
+ out = []
+ if language:
+ out.append(speech.LangChangeCommand(language))
+ resetProsody = set()
+ for m in RE_MP_SPEECH.finditer(text):
+ if m.lastgroup == "break":
+
out.append(speech.BreakCommand(time=int(m.group("break")) * breakMulti))
+ elif m.lastgroup == "char":
+ out.extend((speech.CharacterModeCommand(True),
+ m.group("char"),
speech.CharacterModeCommand(False)))
+ elif m.lastgroup == "comma":
+ out.append(speech.BreakCommand(time=100))
+ elif m.lastgroup in PROSODY_COMMANDS:
+ command = PROSODY_COMMANDS[m.lastgroup]
+ out.append(command(multiplier=int(m.group(m.lastgroup))
/ 100.0))
+ resetProsody.add(command)
+ elif m.lastgroup == "prosodyReset":
+ for command in resetProsody:
+ out.append(command(multiplier=1))
+ resetProsody.clear()
+ elif m.lastgroup == "phonemeText":
+ out.append(speech.PhonemeCommand(m.group("ipa"),
+ text=m.group("phonemeText")))
+ elif m.lastgroup == "content":
+ out.append(m.group(0))
+ if language:
+ out.append(speech.LangChangeCommand(None))
+ return out
+
+class MathPlayerInteraction(mathPres.MathInteractionNVDAObject):
+
+ def __init__(self, provider=None, mathMl=None):
+ super(MathPlayerInteraction, self).__init__(provider=provider,
mathMl=mathMl)
+ provider._setSpeechLanguage(mathMl)
+ provider._mpSpeech.SetMathML(mathMl)
+
+ def reportFocus(self):
+ super(MathPlayerInteraction, self).reportFocus()
+
speech.speak(_processMpSpeech(self.provider._mpSpeech.GetSpokenText(),
+ self.provider._language))
+
+ def getBrailleRegions(self, review=False):
+ yield braille.NVDAObjectRegion(self, appendText=" ")
+ region = braille.Region()
+ region.focusToHardLeft = True
+
self.provider._mpBraille.SetBrailleWidth(braille.handler.displaySize)
+ region.rawText = self.provider._mpBraille.GetBraille()
+ yield region
+
+ def getScript(self, gesture):
+ # Pass most keys to MathPlayer. Pretty ugly.
+ if isinstance(gesture, KeyboardInputGesture) and "NVDA" not in
gesture.modifierNames and (
+ gesture.mainKeyName in {
+ "leftArrow", "rightArrow", "upArrow",
"downArrow",
+ "home", "end",
+ "space", "backspace", "enter",
+ }
+ or len(gesture.mainKeyName) == 1
+ ):
+ return self.script_navigate
+ return super(MathPlayerInteraction, self).getScript(gesture)
+
+ def script_navigate(self, gesture):
+ modNames = gesture.modifierNames
+ try:
+ text =
self.provider._mpNavigation.DoNavigateKeyPress(gesture.vkCode,
+ "shift" in modNames, "control" in modNames,
"alt" in modNames, False)
+ except COMError:
+ return
+ speech.speak(_processMpSpeech(text, self.provider._language))
+
+class MathPlayer(mathPres.MathPresentationProvider):
+
+ def __init__(self):
+ mpSpeech = self._mpSpeech =
comtypes.client.CreateObject(MPInterface, interface=IMathSpeech)
+ mpSpeechSettings = self._mpSpeechSettings =
mpSpeech.QueryInterface(IMathSpeechSettings)
+ mpSpeechSettings.SetSpeechTags("SSML")
+ self._mpNavigation = mpSpeech.QueryInterface(IMathNavigation)
+ self._mpBraille = mpSpeech.QueryInterface(IMathBraille)
+
+ def _setSpeechLanguage(self, mathMl):
+ lang = mathPres.getLanguageFromMath(mathMl)
+ if not lang:
+ lang = speech.getCurrentLanguage()
+ self._mpSpeechSettings.SetLanguage(lang.replace("_", "-"))
+ self._language = lang
+
+ def getSpeechForMathMl(self, mathMl):
+ self._setSpeechLanguage(mathMl)
+ self._mpSpeech.SetMathML(mathMl)
+ return _processMpSpeech(self._mpSpeech.GetSpokenText(),
self._language)
+
+ def getBrailleForMathMl(self, mathMl):
+ self._mpSpeech.SetMathML(mathMl)
+ self._mpBraille.SetBrailleWidth(braille.handler.displaySize)
+ return self._mpBraille.GetBraille()
+
+ def interactWithMathMl(self, mathMl):
+ MathPlayerInteraction(provider=self, mathMl=mathMl).setFocus()

diff --git a/source/mathType.py b/source/mathType.py
new file mode 100644
index 0000000..e3930e5
--- /dev/null
+++ b/source/mathType.py
@@ -0,0 +1,37 @@
+#mathType.py
+#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) 2014 NV Access Limited
+
+"""Utilities for working with MathType.
+"""
+
+import _winreg as winreg
+import ctypes
+import mathPres
+
+def _getDllPath():
+ with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Design
Science\DSMT6\Directories", 0, winreg.KEY_WOW64_32KEY | winreg.KEY_QUERY_VALUE)
as key:
+ return winreg.QueryValueEx(key, "AppSystemDir32")[0] +
"\\MT6.dll"
+
+lib = ctypes.windll[_getDllPath()]
+
+def getMathMl(oleFormat, runForConversion=True):
+ """Get MathML from a MathType OLEFormat object.
+ """
+ if runForConversion:
+ oleFormat.DoVerb(2) # "RunForConversion"
+ mt = oleFormat.object._comobj
+ length = ctypes.c_long()
+ # 2 is get MathML
+ try:
+ if lib.MTGetLangStrFromEqn(mt, 2, None, ctypes.byref(length))
!= 0:
+ raise RuntimeError
+ mathMl = (ctypes.c_char * length.value)()
+ if lib.MTGetLangStrFromEqn(mt, 2, ctypes.byref(mathMl),
ctypes.byref(length)) != 0:
+ raise RuntimeError
+ finally:
+ # 1 is OLECLOSE_NOSAVE
+ lib.MTCloseOleObject(1, mt)
+ return mathPres.stripExtraneousXml(mathMl.value)

diff --git a/source/speech.py b/source/speech.py
index e4bba7f..d838696 100755
--- a/source/speech.py
+++ b/source/speech.py
@@ -3,7 +3,7 @@
#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) 2006-2012 NV Access Limited, Peter Vágner, Aleksey Sadovoy
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy

"""High-level functions to speak information.
"""
@@ -311,7 +311,8 @@ def
speakObjectProperties(obj,reason=controlTypes.REASON_QUERY,index=None,**allo

def speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
from NVDAObjects import NVDAObjectTextInfo
- isEditable=(reason!=controlTypes.REASON_FOCUSENTERED and
obj.TextInfo!=NVDAObjectTextInfo and (obj.role in
(controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_TERMINAL) or
controlTypes.STATE_EDITABLE in obj.states))
+ role=obj.role
+ isEditable=(reason!=controlTypes.REASON_FOCUSENTERED and
obj.TextInfo!=NVDAObjectTextInfo and (role in
(controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_TERMINAL) or
controlTypes.STATE_EDITABLE in obj.states))

allowProperties={'name':True,'role':True,'states':True,'value':True,'description':True,'keyboardShortcut':True,'positionInfo_level':True,'positionInfo_indexInGroup':True,'positionInfo_similarItemsInGroup':True,"cellCoordsText":True,"rowNumber":True,"columnNumber":True,"includeTableCellCoords":True,"columnCount":True,"rowCount":True,"rowHeaderText":True,"columnHeaderText":True}

if reason==controlTypes.REASON_FOCUSENTERED:
@@ -349,7 +350,9 @@ def
speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
allowProperties['value']=False

speakObjectProperties(obj,reason=reason,index=index,**allowProperties)
- if reason!=controlTypes.REASON_ONLYCACHE and isEditable:
+ if reason==controlTypes.REASON_ONLYCACHE:
+ return
+ if isEditable:
try:
info=obj.makeTextInfo(textInfos.POSITION_SELECTION)
if not info.isCollapsed:
@@ -361,6 +364,14 @@ def
speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
except:
newInfo=obj.makeTextInfo(textInfos.POSITION_ALL)

speakTextInfo(newInfo,unit=textInfos.UNIT_PARAGRAPH,reason=controlTypes.REASON_CARET)
+ elif role==controlTypes.ROLE_MATH:
+ import mathPres
+ mathPres.ensureInit()
+ if mathPres.speechProvider:
+ try:
+
speak(mathPres.speechProvider.getSpeechForMathMl(obj.mathMl))
+ except (NotImplementedError, LookupError):
+ pass

def
speakText(text,index=None,reason=controlTypes.REASON_MESSAGE,symbolLevel=None):
"""Speaks some text.
@@ -474,12 +485,17 @@ def speak(speechSequence,symbolLevel=None):
if symbolLevel is None:
symbolLevel=config.conf["speech"]["symbolLevel"]
curLanguage=defaultLanguage
+ inCharacterMode=False
for index in xrange(len(speechSequence)):
item=speechSequence[index]
+ if isinstance(item,CharacterModeCommand):
+ inCharacterMode=item.state
if autoLanguageSwitching and isinstance(item,LangChangeCommand):
curLanguage=item.lang
if isinstance(item,basestring):
-
speechSequence[index]=processText(curLanguage,item,symbolLevel)+CHUNK_SEPARATOR
+
speechSequence[index]=processText(curLanguage,item,symbolLevel)
+ if not inCharacterMode:
+ speechSequence[index]+=CHUNK_SEPARATOR
getSynth().speak(speechSequence)

def speakSelectionMessage(message,text):
@@ -618,6 +634,16 @@ class SpeakTextInfoState(object):
def copy(self):
return self.__class__(self)

+def _speakTextInfo_addMath(speechSequence, info, field):
+ import mathPres
+ mathPres.ensureInit()
+ if not mathPres.speechProvider:
+ return
+ try:
+
speechSequence.extend(mathPres.speechProvider.getSpeechForMathMl(info.getMathMl(field)))
+ except (NotImplementedError, LookupError):
+ return
+
def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlTypes.REASON_QUERY,index=None,onlyInitialFields=False,suppressBlanks=False):
if isinstance(useCache,SpeakTextInfoState):
speakTextInfoState=useCache
@@ -702,7 +728,7 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
if not endingBlock and reason==controlTypes.REASON_SAYALL:

endingBlock=bool(int(controlFieldStackCache[count].get('isBlock',0)))
if endingBlock:
- speechSequence.append(BreakCommand())
+ speechSequence.append(SpeakWithoutPausesBreakCommand())
# The TextInfo should be considered blank if we are only exiting fields
(i.e. we aren't entering any new fields and there is no text).
isTextBlank=True

@@ -713,17 +739,25 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT
#Get speech text for any fields that are in both controlFieldStacks, if
extra detail is not requested
if not extraDetail:
for count in xrange(commonFieldCount):
-
text=info.getControlFieldSpeech(newControlFieldStack[count],newControlFieldStack[0:count],"start_inControlFieldStack",formatConfig,extraDetail,reason=reason)
+ field=newControlFieldStack[count]
+
text=info.getControlFieldSpeech(field,newControlFieldStack[0:count],"start_inControlFieldStack",formatConfig,extraDetail,reason=reason)
if text:
speechSequence.append(text)
isTextBlank=False
+ if field.get("role")==controlTypes.ROLE_MATH:
+ isTextBlank=False
+
_speakTextInfo_addMath(speechSequence,info,field)

#Get speech text for any fields in the new controlFieldStack that are
not in the old controlFieldStack
for count in xrange(commonFieldCount,len(newControlFieldStack)):
-
text=info.getControlFieldSpeech(newControlFieldStack[count],newControlFieldStack[0:count],"start_addedToControlFieldStack",formatConfig,extraDetail,reason=reason)
+ field=newControlFieldStack[count]
+
text=info.getControlFieldSpeech(field,newControlFieldStack[0:count],"start_addedToControlFieldStack",formatConfig,extraDetail,reason=reason)
if text:
speechSequence.append(text)
isTextBlank=False
+ if field.get("role")==controlTypes.ROLE_MATH:
+ isTextBlank=False
+ _speakTextInfo_addMath(speechSequence,info,field)
commonFieldCount+=1

#Fetch the text for format field attributes that have changed between
what was previously cached, and this textInfo's initialFormatField.
@@ -800,6 +834,8 @@ def
speakTextInfo(info,useCache=True,formatConfig=None,unit=None,reason=controlT

relativeSpeechSequence.append(LangChangeCommand(None))
lastLanguage=None
relativeSpeechSequence.append(fieldText)
+ if command.command=="controlStart" and
command.field.get("role")==controlTypes.ROLE_MATH:
+
_speakTextInfo_addMath(relativeSpeechSequence,info,command.field)
if autoLanguageSwitching and
newLanguage!=lastLanguage:

relativeSpeechSequence.append(LangChangeCommand(newLanguage))
lastLanguage=newLanguage
@@ -872,7 +908,7 @@ def
getSpeechTextForProperties(reason=controlTypes.REASON_QUERY,**propertyValues
rowNumber=propertyValues.get('rowNumber')
columnNumber=propertyValues.get('columnNumber')
includeTableCellCoords=propertyValues.get('includeTableCellCoords',True)
- if speakRole and (reason not in
(controlTypes.REASON_SAYALL,controlTypes.REASON_CARET,controlTypes.REASON_FOCUS)
or not (name or value or cellCoordsText or rowNumber or columnNumber) or role
not in controlTypes.silentRolesOnFocus):
+ if speakRole and (reason not in
(controlTypes.REASON_SAYALL,controlTypes.REASON_CARET,controlTypes.REASON_FOCUS)
or not (name or value or cellCoordsText or rowNumber or columnNumber) or role
not in controlTypes.silentRolesOnFocus) and (role!=controlTypes.ROLE_MATH or
reason not in (controlTypes.REASON_CARET,controlTypes.REASON_SAYALL)):
textList.append(controlTypes.roleLabels[role])
if value:
textList.append(value)
@@ -1006,7 +1042,7 @@ def
getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD
speakEntry=True
speakWithinForLine=True
speakExitForOther=True
- elif presCat == attrs.PRESCAT_MARKER:
+ elif presCat in (attrs.PRESCAT_MARKER, attrs.PRESCAT_CELL):
speakEntry=True
elif presCat == attrs.PRESCAT_CONTAINER:
speakEntry=True
@@ -1393,7 +1429,7 @@ def speakWithoutPauses(speechSequence,detectBreaks=True):
if detectBreaks and speechSequence:
sequenceLen=len(speechSequence)
for index in xrange(sequenceLen):
- if isinstance(speechSequence[index],BreakCommand):
+ if
isinstance(speechSequence[index],SpeakWithoutPausesBreakCommand):
if index>0 and lastStartIndex<index:

speakWithoutPauses(speechSequence[lastStartIndex:index],detectBreaks=False)
speakWithoutPauses(None)
@@ -1497,5 +1533,91 @@ class LangChangeCommand(SpeechCommand):
def __repr__(self):
return "LangChangeCommand (%r)"%self.lang

-class BreakCommand(object):
- """Forces speakWithoutPauses to flush its buffer and therefore break
the sentence at this point."""
+class SpeakWithoutPausesBreakCommand(SpeechCommand):
+ """Forces speakWithoutPauses to flush its buffer and therefore break
the sentence at this point.
+ This should only be used with the L{speakWithoutPauses} function.
+ This will be removed during processing.
+ """
+
+class BreakCommand(SpeechCommand):
+ """Insert a break between words.
+ """
+
+ def __init__(self, time=0):
+ """
+ @param time: The duration of the pause to be inserted in
milliseconds.
+ @param time: int
+ """
+ self.time = time
+
+ def __repr__(self):
+ return "BreakCommand(time=%d)" % self.time
+
+class PitchCommand(SpeechCommand):
+ """Change the pitch of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
pitch setting;
+ e.g. 0.5 is half, 1 returns to the current pitch
setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "PitchCommand(multiplier=%g)" % self.multiplier
+
+class VolumeCommand(SpeechCommand):
+ """Change the volume of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
volume setting;
+ e.g. 0.5 is half, 1 returns to the current volume
setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "VolumeCommand(multiplier=%g)" % self.multiplier
+
+class RateCommand(SpeechCommand):
+ """Change the rate of the voice.
+ """
+
+ def __init__(self, multiplier=1):
+ """
+ @param multiplier: The number by which to multiply the current
rate setting;
+ e.g. 0.5 is half, 1 returns to the current rate setting.
+ @param multiplier: int/float
+ """
+ self.multiplier = multiplier
+
+ def __repr__(self):
+ return "RateCommand(multiplier=%g)" % self.multiplier
+
+class PhonemeCommand(SpeechCommand):
+ """Insert a specific pronunciation.
+ This command accepts Unicode International Phonetic Alphabet (IPA)
characters.
+ Note that this is not well supported by synthesizers.
+ """
+
+ def __init__(self, ipa, text=None):
+ """
+ @param ipa: Unicode IPA characters.
+ @type ipa: unicode
+ @param text: Text to speak if the synthesizer does not support
+ some or all of the specified IPA characters,
+ C{None} to ignore this command instead.
+ @type text: unicode
+ """
+ self.ipa = ipa
+ self.text = text
+
+ def __repr__(self):
+ out = "PhonemeCommand(%r" % self.ipa
+ if self.text:
+ out += ", text=%r" % self.text
+ return out + ")"

diff --git a/source/synthDrivers/_espeak.py b/source/synthDrivers/_espeak.py
index d309d81..128fc01 100755
--- a/source/synthDrivers/_espeak.py
+++ b/source/synthDrivers/_espeak.py
@@ -173,7 +173,7 @@ def _speak(text):
global isSpeaking
uniqueID=c_int()
isSpeaking = True
- flags = espeakCHARS_WCHAR | espeakSSML
+ flags = espeakCHARS_WCHAR | espeakSSML | espeakPHONEMES
return espeakDLL.espeak_Synth(text,0,0,0,0,flags,byref(uniqueID),0)

def speak(text):

diff --git a/source/synthDrivers/espeak.py b/source/synthDrivers/espeak.py
index f58a68f..72a46d7 100644
--- a/source/synthDrivers/espeak.py
+++ b/source/synthDrivers/espeak.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#synthDrivers/espeak.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2007-2013 NV Access Limited, Peter Vágner
+#Copyright (C) 2007-2015 NV Access Limited, Peter Vágner, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -50,17 +50,39 @@ class SynthDriver(SynthDriver):
def _get_language(self):
return self._language

+ PROSODY_ATTRS = {
+ speech.PitchCommand: "pitch",
+ speech.VolumeCommand: "volume",
+ speech.RateCommand: "rate",
+ }
+
+ IPA_TO_ESPEAK = {
+ u"θ": u"T",
+ u"s": u"s",
+ u"ˈ": u"'",
+ }
+
+ def _processText(self, text):
+ text = unicode(text)
+ # We need to make several replacements.
+ return text.translate({
+ 0x1: None, # used for embedded commands
+ 0x3C: u"&lt;", # <: because of XML
+ 0x3E: u"&gt;", # >: because of XML
+ 0x5B: u" [", # [: [[ indicates phonemes
+ })
+
def speak(self,speechSequence):
defaultLanguage=self._language
textList=[]
langChanged=False
+ prosody={}
+ # We output malformed XML, as we might close an outer tag after
opening an inner one; e.g.
+ # <voice><prosody></voice></prosody>.
+ # However, eSpeak doesn't seem to mind.
for item in speechSequence:
if isinstance(item,basestring):
- s=unicode(item)
- # Replace \01, as this is used for embedded
commands.
- #Also replace < and > as espeak handles xml
-
s=s.translate({ord(u'\01'):None,ord(u'<'):u'&lt;',ord(u'>'):u'&gt;'})
- textList.append(s)
+ textList.append(self._processText(item))
elif isinstance(item,speech.IndexCommand):
textList.append("<mark name=\"%d\"
/>"%item.index)
elif isinstance(item,speech.CharacterModeCommand):
@@ -70,12 +92,47 @@ class SynthDriver(SynthDriver):
textList.append("</voice>")
textList.append("<voice
xml:lang=\"%s\">"%(item.lang if item.lang else
defaultLanguage).replace('_','-'))
langChanged=True
+ elif isinstance(item,speech.BreakCommand):
+ textList.append('<break time="%dms" />' %
item.time)
+ elif type(item) in self.PROSODY_ATTRS:
+ if prosody:
+ # Close previous prosody tag.
+ textList.append("</prosody>")
+ attr=self.PROSODY_ATTRS[type(item)]
+ if item.multiplier==1:
+ # Returning to normal.
+ try:
+ del prosody[attr]
+ except KeyError:
+ pass
+ else:
+ prosody[attr]=int(item.multiplier* 100)
+ if not prosody:
+ continue
+ textList.append("<prosody")
+ for attr,val in prosody.iteritems():
+ textList.append(' %s="%d%%"'%(attr,val))
+ textList.append(">")
+ elif isinstance(item,speech.PhonemeCommand):
+ # We can't use unicode.translate because we
want to reject unknown characters.
+ try:
+
phonemes="".join([self.IPA_TO_ESPEAK[char] for char in item.ipa])
+ # There needs to be a space after the
phoneme command.
+ # Otherwise, eSpeak will announce a
subsequent SSML tag instead of processing it.
+ textList.append(u"[[%s]] "%phonemes)
+ except KeyError:
+ log.debugWarning("Unknown character in
IPA string: %s"%item.ipa)
+ if item.text:
+
textList.append(self._processText(item.text))
elif isinstance(item,speech.SpeechCommand):
log.debugWarning("Unsupported speech command:
%s"%item)
else:
log.error("Unknown speech: %s"%item)
+ # Close any open tags.
if langChanged:
textList.append("</voice>")
+ if prosody:
+ textList.append("</prosody>")
text=u"".join(textList)
_espeak.speak(text)


diff --git a/source/synthDrivers/sapi5.py b/source/synthDrivers/sapi5.py
index 1c866de..2117b03 100644
--- a/source/synthDrivers/sapi5.py
+++ b/source/synthDrivers/sapi5.py
@@ -1,6 +1,7 @@
+# -*- coding: UTF-8 -*-
#synthDrivers/sapi5.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -92,8 +93,11 @@ class SynthDriver(SynthDriver):
else:
return None

+ def _percentToRate(self, percent):
+ return (percent - 50) / 5
+
def _set_rate(self,rate):
- self.tts.Rate = (rate-50)/5
+ self.tts.Rate = self._percentToRate(rate)

def _set_pitch(self,value):
#pitch is really controled with xml around speak commands
@@ -127,25 +131,121 @@ class SynthDriver(SynthDriver):
return
self._initTts(voice=voice)

- def speak(self,speechSequence):
- textList=[]
+ def _percentToPitch(self, percent):
+ return percent / 2 - 25
+
+ IPA_TO_SAPI = {
+ u"θ": u"th",
+ u"s": u"s",
+ }
+ def _convertPhoneme(self, ipa):
+ # We only know about US English phonemes.
+ # Rather than just ignoring unknown phonemes, SAPI throws an
exception.
+ # Therefore, don't bother with any other language.
+ if self.tts.voice.GetAttribute("language") != "409":
+ raise LookupError("No data for this language")
+ out = []
+ outAfter = None
+ for ipaChar in ipa:
+ if ipaChar == u"ˈ":
+ outAfter = u"1"
+ continue
+ out.append(self.IPA_TO_SAPI[ipaChar])
+ if outAfter:
+ out.append(outAfter)
+ outAfter = None
+ if outAfter:
+ out.append(outAfter)
+ return u" ".join(out)
+
+ def speak(self, speechSequence):
+ textList = []
+
+ # NVDA SpeechCommands are linear, but XML is hierarchical.
+ # Therefore, we track values for non-empty tags.
+ # When a tag changes, we close all previously opened tags and
open new ones.
+ tags = {}
+ # We have to use something mutable here because it needs to be
changed by the inner function.
+ tagsChanged = [True]
+ openedTags = []
+ def outputTags():
+ if not tagsChanged[0]:
+ return
+ for tag in reversed(openedTags):
+ textList.append("</%s>" % tag)
+ del openedTags[:]
+ for tag, attrs in tags.iteritems():
+ textList.append("<%s" % tag)
+ for attr, val in attrs.iteritems():
+ textList.append(' %s="%s"' % (attr,
val))
+ textList.append(">")
+ openedTags.append(tag)
+ tagsChanged[0] = False
+
+ pitch = self._pitch
+ # Pitch must always be specified in the markup.
+ tags["pitch"] = {"absmiddle": self._percentToPitch(pitch)}
+ rate = self.rate
+ volume = self.volume
+
for item in speechSequence:
- if isinstance(item,basestring):
- textList.append(item.replace("<","&lt;"))
- elif isinstance(item,speech.IndexCommand):
- textList.append("<Bookmark Mark=\"%d\"
/>"%item.index)
- elif isinstance(item,speech.CharacterModeCommand):
- textList.append("<spell>" if item.state else
"</spell>")
- elif isinstance(item,speech.SpeechCommand):
- log.debugWarning("Unsupported speech command:
%s"%item)
+ if isinstance(item, basestring):
+ outputTags()
+ textList.append(item.replace("<", "&lt;"))
+ elif isinstance(item, speech.IndexCommand):
+ textList.append('<Bookmark Mark="%d" />' %
item.index)
+ elif isinstance(item, speech.CharacterModeCommand):
+ if item.state:
+ tags["spell"] = {}
+ else:
+ try:
+ del tags["spell"]
+ except KeyError:
+ pass
+ tagsChanged[0] = True
+ elif isinstance(item, speech.BreakCommand):
+ textList.append('<silence msec="%d" />' %
item.time)
+ elif isinstance(item, speech.PitchCommand):
+ tags["pitch"] = {"absmiddle":
self._percentToPitch(int(pitch * item.multiplier))}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.VolumeCommand):
+ if item.multiplier == 1:
+ try:
+ del tags["volume"]
+ except KeyError:
+ pass
+ else:
+ tags["volume"] = {"level": int(volume *
item.multiplier)}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.RateCommand):
+ if item.multiplier == 1:
+ try:
+ del tags["rate"]
+ except KeyError:
+ pass
+ else:
+ tags["rate"] = {"absspeed":
self._percentToRate(int(rate * item.multiplier))}
+ tagsChanged[0] = True
+ elif isinstance(item, speech.PhonemeCommand):
+ try:
+ textList.append(u'<pron
sym="%s">%s</pron>'
+ %
(self._convertPhoneme(item.ipa), item.text or u""))
+ except LookupError:
+ log.debugWarning("Couldn't convert
character in IPA string: %s" % item.ipa)
+ if item.text:
+ textList.append(item.text)
+ elif isinstance(item, speech.SpeechCommand):
+ log.debugWarning("Unsupported speech command:
%s" % item)
else:
- log.error("Unknown speech: %s"%item)
- text="".join(textList)
- #Pitch must always be hardcoded
- pitch=(self._pitch/2)-25
- text="<pitch absmiddle=\"%s\">%s</pitch>"%(pitch,text)
- flags=constants.SVSFIsXML|constants.SVSFlagsAsync
- self.tts.Speak(text,flags)
+ log.error("Unknown speech: %s" % item)
+ # Close any tags that are still open.
+ tags.clear()
+ tagsChanged[0] = True
+ outputTags()
+
+ text = "".join(textList)
+ flags = constants.SVSFIsXML | constants.SVSFlagsAsync
+ self.tts.Speak(text, flags)

def cancel(self):
#if self.tts.Status.RunningState == 2:

diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py
index 35f894c..32e1476 100755
--- a/source/textInfos/__init__.py
+++ b/source/textInfos/__init__.py
@@ -2,7 +2,7 @@
#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) 2006-2012 NV Access Limited
+#Copyright (C) 2006-2014 NV Access Limited

"""Framework for accessing text content in widgets.
The core component of this framework is the L{TextInfo} class.
@@ -31,10 +31,13 @@ class ControlField(Field):

#: This field is usually a single line item; e.g. a link or heading.
PRESCAT_SINGLELINE = "singleLine"
- #: This field is a marker; e.g. a separator or table cell.
+ #: This field is a marker; e.g. a separator or footnote.
PRESCAT_MARKER = "marker"
#: This field is a container, usually multi-line.
PRESCAT_CONTAINER = "container"
+ #: This field is a section of a larger container which is adjacent to
another similar section;
+ #: e.g. a table cell.
+ PRESCAT_CELL = "cell"
#: This field is just for layout.
PRESCAT_LAYOUT = None

@@ -76,8 +79,10 @@ class ControlField(Field):
or (role == controlTypes.ROLE_LIST and
controlTypes.STATE_READONLY not in states)
):
return self.PRESCAT_SINGLELINE
- elif role in (controlTypes.ROLE_SEPARATOR,
controlTypes.ROLE_FOOTNOTE, controlTypes.ROLE_ENDNOTE,
controlTypes.ROLE_EMBEDDEDOBJECT, controlTypes.ROLE_TABLECELL,
controlTypes.ROLE_TABLECOLUMNHEADER, controlTypes.ROLE_TABLEROWHEADER,
controlTypes.ROLE_APPLICATION, controlTypes.ROLE_DIALOG):
+ elif role in (controlTypes.ROLE_SEPARATOR,
controlTypes.ROLE_FOOTNOTE, controlTypes.ROLE_ENDNOTE,
controlTypes.ROLE_EMBEDDEDOBJECT, controlTypes.ROLE_APPLICATION,
controlTypes.ROLE_DIALOG, controlTypes.ROLE_MATH):
return self.PRESCAT_MARKER
+ elif role in (controlTypes.ROLE_TABLECELL,
controlTypes.ROLE_TABLECOLUMNHEADER, controlTypes.ROLE_TABLEROWHEADER):
+ return self.PRESCAT_CELL
elif (
role in (controlTypes.ROLE_BLOCKQUOTE,
controlTypes.ROLE_FRAME, controlTypes.ROLE_INTERNALFRAME,
controlTypes.ROLE_TOOLBAR, controlTypes.ROLE_MENUBAR,
controlTypes.ROLE_POPUPMENU, controlTypes.ROLE_TABLE)
or (role == controlTypes.ROLE_EDITABLETEXT and
(controlTypes.STATE_READONLY not in states or controlTypes.STATE_FOCUSABLE in
states) and controlTypes.STATE_MULTILINE in states)
@@ -423,7 +428,7 @@ class TextInfo(baseObject.AutoPropertyObject):
def getControlFieldBraille(self, field, ancestors, reportStart,
formatConfig):
# Import late to avoid circular import.
import braille
- return braille.getControlFieldBraille(field, ancestors,
reportStart, formatConfig)
+ return braille.getControlFieldBraille(self, field, ancestors,
reportStart, formatConfig)

def getEmbeddedObject(self, offset=0):
"""Retrieve the embedded object associated with a particular
embedded object character.
@@ -451,6 +456,13 @@ class TextInfo(baseObject.AutoPropertyObject):
winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP,0,0,None,None)
winUser.setCursorPos(oldX,oldY)

+ def getMathMl(self, field):
+ """Get MathML for a math control field.
+ This will only be called for control fields with a role of
L{controlTypes.ROLE_MATH}.
+ @raise LookupError: If MathML can't be retrieved for this field.
+ """
+ raise NotImplementedError
+
RE_EOL = re.compile("\r\n|[\n\r]")
def convertToCrlf(text):
"""Convert a string so that it contains only CRLF line endings.

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/29810e23a015/
Changeset: 29810e23a015
Branch: None
User: jteh
Date: 2015-04-20 01:58:53+00:00
Summary: It is now possible to assign input gestures (keyboard commands,
touch gestures, etc.) for all NVDA preferences dialogs and document formatting
options using the Input Gestures dialog.

Authors: Joseph Lee <joseph.lee22590@xxxxxxxxx>, Leonard de Ruijter
<mail@xxxxxxxxxxxxx>

Affected #: 2 files

diff --git a/source/globalCommands.py b/source/globalCommands.py
index a99412e..032b566 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -3,7 +3,7 @@
#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) 2006-2012 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista
+#Copyright (C) 2006-2015 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista, Joseph Lee, Leonard de Ruijter

import time
import itertools
@@ -39,10 +39,10 @@ import virtualBuffers
import characterProcessing
from baseObject import ScriptableObject

-#: Script category for text review commands.
+#: Script category for text review commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_TEXTREVIEW = _("Text review")
-#: Script category for Object navigation commands.
+#: Script category for Object navigation commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_OBJECTNAVIGATION = _("Object navigation")
#: Script category for system caret commands.
@@ -51,7 +51,7 @@ SCRCAT_SYSTEMCARET = _("System caret")
#: Script category for mouse commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_MOUSE = _("Mouse")
-#: Script category for mouse commands.
+#: Script category for speech commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_SPEECH = _("Speech")
#: Script category for configuration dialogs commands.
@@ -69,12 +69,15 @@ SCRCAT_TOUCH = _("Touch screen")
#: Script category for focus commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_FOCUS = _("System focus")
-#: Script category for system status commands.
+#: Script category for system status commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_SYSTEM = _("System status")
-#: Script category for input commands.
+#: Script category for input commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_INPUT = _("Input")
+#: Script category for document formatting commands.
+# Translators: The name of a category of NVDA commands.
+SCRCAT_DOCUMENTFORMATTING = _("Document formatting")

class GlobalCommands(ScriptableObject):
"""Commands that are available at all times, regardless of the current
focus.
@@ -92,7 +95,6 @@ class GlobalCommands(ScriptableObject):
script_toggleInputHelp.__doc__=_("Turns input help on or off. When on,
any input such as pressing a key on the keyboard will tell you what script is
associated with that input, if any.")
script_toggleInputHelp.category=SCRCAT_INPUT

-
def script_toggleCurrentAppSleepMode(self,gesture):
curFocus=api.getFocusObject()
curApp=curFocus.appModule
@@ -286,6 +288,328 @@ class GlobalCommands(ScriptableObject):
script_toggleSpeakCommandKeys.__doc__=_("Toggles on and off the
speaking of typed keys, that are not specifically characters")
script_toggleSpeakCommandKeys.category=SCRCAT_SPEECH

+ def script_toggleReportFontName(self,gesture):
+ if config.conf["documentFormatting"]["reportFontName"]:
+ # Translators: The message announced when toggling the
report font name document formatting setting.
+ state = _("report font name off")
+
config.conf["documentFormatting"]["reportFontName"]=False
+ else:
+ # Translators: The message announced when toggling the
report font name document formatting setting.
+ state = _("report font name on")
+ config.conf["documentFormatting"]["reportFontName"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font name
command.
+ script_toggleReportFontName.__doc__=_("Toggles on and off the reporting
of font changes")
+ script_toggleReportFontName.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFontSize(self,gesture):
+ if config.conf["documentFormatting"]["reportFontSize"]:
+ # Translators: The message announced when toggling the
report font size document formatting setting.
+ state = _("report font size off")
+
config.conf["documentFormatting"]["reportFontSize"]=False
+ else:
+ # Translators: The message announced when toggling the
report font size document formatting setting.
+ state = _("report font size on")
+ config.conf["documentFormatting"]["reportFontSize"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font size
command.
+ script_toggleReportFontSize.__doc__=_("Toggles on and off the reporting
of font size changes")
+ script_toggleReportFontSize.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFontAttributes(self,gesture):
+ if config.conf["documentFormatting"]["reportFontAttributes"]:
+ # Translators: The message announced when toggling the
report font attributes document formatting setting.
+ state = _("report font attributes off")
+
config.conf["documentFormatting"]["reportFontAttributes"]=False
+ else:
+ # Translators: The message announced when toggling the
report font attributes document formatting setting.
+ state = _("report font attributes on")
+
config.conf["documentFormatting"]["reportFontAttributes"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font
attributes command.
+ script_toggleReportFontAttributes.__doc__=_("Toggles on and off the
reporting of font attributes")
+ script_toggleReportFontAttributes.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportRevisions(self,gesture):
+ if config.conf["documentFormatting"]["reportRevisions"]:
+ # Translators: The message announced when toggling the
report revisions document formatting setting.
+ state = _("report revisions off")
+
config.conf["documentFormatting"]["reportRevisions"]=False
+ else:
+ # Translators: The message announced when toggling the
report revisions document formatting setting.
+ state = _("report revisions on")
+
config.conf["documentFormatting"]["reportRevisions"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report revisions
command.
+ script_toggleReportRevisions.__doc__=_("Toggles on and off the
reporting of revisions")
+ script_toggleReportRevisions.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportColor(self,gesture):
+ if config.conf["documentFormatting"]["reportColor"]:
+ # Translators: The message announced when toggling the
report colors document formatting setting.
+ state = _("report colors off")
+ config.conf["documentFormatting"]["reportColor"]=False
+ else:
+ # Translators: The message announced when toggling the
report colors document formatting setting.
+ state = _("report colors on")
+ config.conf["documentFormatting"]["reportColor"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report colors command.
+ script_toggleReportColor.__doc__=_("Toggles on and off the reporting of
colors")
+ script_toggleReportColor.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportAlignment(self,gesture):
+ if config.conf["documentFormatting"]["reportAlignment"]:
+ # Translators: The message announced when toggling the
report alignment document formatting setting.
+ state = _("report alignment off")
+
config.conf["documentFormatting"]["reportAlignment"]=False
+ else:
+ # Translators: The message announced when toggling the
report alignment document formatting setting.
+ state = _("report alignment on")
+
config.conf["documentFormatting"]["reportAlignment"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report alignment
command.
+ script_toggleReportAlignment.__doc__=_("Toggles on and off the
reporting of text alignment")
+ script_toggleReportAlignment.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportStyle(self,gesture):
+ if config.conf["documentFormatting"]["reportStyle"]:
+ # Translators: The message announced when toggling the
report style document formatting setting.
+ state = _("report style off")
+ config.conf["documentFormatting"]["reportStyle"]=False
+ else:
+ # Translators: The message announced when toggling the
report style document formatting setting.
+ state = _("report style on")
+ config.conf["documentFormatting"]["reportStyle"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report style command.
+ script_toggleReportStyle.__doc__=_("Toggles on and off the reporting of
style changes")
+ script_toggleReportStyle.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportSpellingErrors(self,gesture):
+ if config.conf["documentFormatting"]["reportSpellingErrors"]:
+ # Translators: The message announced when toggling the
report spelling errors document formatting setting.
+ state = _("report spelling errors off")
+
config.conf["documentFormatting"]["reportSpellingErrors"]=False
+ else:
+ # Translators: The message announced when toggling the
report spelling errors document formatting setting.
+ state = _("report spelling errors on")
+
config.conf["documentFormatting"]["reportSpellingErrors"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report spelling
errors command.
+ script_toggleReportSpellingErrors.__doc__=_("Toggles on and off the
reporting of spelling errors")
+ script_toggleReportSpellingErrors.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportPage(self,gesture):
+ if config.conf["documentFormatting"]["reportPage"]:
+ # Translators: The message announced when toggling the
report pages document formatting setting.
+ state = _("report pages off")
+ config.conf["documentFormatting"]["reportPage"]=False
+ else:
+ # Translators: The message announced when toggling the
report pages document formatting setting.
+ state = _("report pages on")
+ config.conf["documentFormatting"]["reportPage"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report pages command.
+ script_toggleReportPage.__doc__=_("Toggles on and off the reporting of
pages")
+ script_toggleReportPage.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLineNumber(self,gesture):
+ if config.conf["documentFormatting"]["reportLineNumber"]:
+ # Translators: The message announced when toggling the
report line numbers document formatting setting.
+ state = _("report line numbers off")
+
config.conf["documentFormatting"]["reportLineNumber"]=False
+ else:
+ # Translators: The message announced when toggling the
report line numbers document formatting setting.
+ state = _("report line numbers on")
+
config.conf["documentFormatting"]["reportLineNumber"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report line numbers
command.
+ script_toggleReportLineNumber.__doc__=_("Toggles on and off the
reporting of line numbers")
+ script_toggleReportLineNumber.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLineIndentation(self,gesture):
+ if config.conf["documentFormatting"]["reportLineIndentation"]:
+ # Translators: The message announced when toggling the
report line indentation document formatting setting.
+ state = _("report line indentation off")
+
config.conf["documentFormatting"]["reportLineIndentation"]=False
+ else:
+ # Translators: The message announced when toggling the
report line indentation document formatting setting.
+ state = _("report line indentation on")
+
config.conf["documentFormatting"]["reportLineIndentation"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report line
indentation command.
+ script_toggleReportLineIndentation.__doc__=_("Toggles on and off the
reporting of line indentation")
+ script_toggleReportLineIndentation.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportParagraphIndentation(self,gesture):
+ if
config.conf["documentFormatting"]["reportParagraphIndentation"]:
+ # Translators: The message announced when toggling the
report paragraph indentation document formatting setting.
+ state = _("report paragraph indentation off")
+
config.conf["documentFormatting"]["reportParagraphIndentation"]=False
+ else:
+ # Translators: The message announced when toggling the
report paragraph indentation document formatting setting.
+ state = _("report paragraph indentation on")
+
config.conf["documentFormatting"]["reportParagraphIndentation"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report paragraph
indentation command.
+ script_toggleReportParagraphIndentation.__doc__=_("Toggles on and off
the reporting of paragraph indentation")
+
script_toggleReportParagraphIndentation.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTables(self,gesture):
+ if config.conf["documentFormatting"]["reportTables"]:
+ # Translators: The message announced when toggling the
report tables document formatting setting.
+ state = _("report tables off")
+ config.conf["documentFormatting"]["reportTables"]=False
+ else:
+ # Translators: The message announced when toggling the
report tables document formatting setting.
+ state = _("report tables on")
+ config.conf["documentFormatting"]["reportTables"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report tables command.
+ script_toggleReportTables.__doc__=_("Toggles on and off the reporting
of tables")
+ script_toggleReportTables.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTableHeaders(self,gesture):
+ if config.conf["documentFormatting"]["reportTableHeaders"]:
+ # Translators: The message announced when toggling the
report table row/column headers document formatting setting.
+ state = _("report table row and column headers off")
+
config.conf["documentFormatting"]["reportTableHeaders"]=False
+ else:
+ # Translators: The message announced when toggling the
report table row/column headers document formatting setting.
+ state = _("report table row and column headers on")
+
config.conf["documentFormatting"]["reportTableHeaders"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report table
row/column headers command.
+ script_toggleReportTableHeaders.__doc__=_("Toggles on and off the
reporting of table row and column headers")
+ script_toggleReportTableHeaders.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTableCellCoords(self,gesture):
+ if config.conf["documentFormatting"]["reportTableCellCoords"]:
+ # Translators: The message announced when toggling the
report table cell coordinates document formatting setting.
+ state = _("report table cell coordinates off")
+
config.conf["documentFormatting"]["reportTableCellCoords"]=False
+ else:
+ # Translators: The message announced when toggling the
report table cell coordinates document formatting setting.
+ state = _("report table cell coordinates on")
+
config.conf["documentFormatting"]["reportTableCellCoords"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report table cell
coordinates command.
+ script_toggleReportTableCellCoords.__doc__=_("Toggles on and off the
reporting of table cell coordinates")
+ script_toggleReportTableCellCoords.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLinks(self,gesture):
+ if config.conf["documentFormatting"]["reportLinks"]:
+ # Translators: The message announced when toggling the
report links document formatting setting.
+ state = _("report links off")
+ config.conf["documentFormatting"]["reportLinks"]=False
+ else:
+ # Translators: The message announced when toggling the
report links document formatting setting.
+ state = _("report links on")
+ config.conf["documentFormatting"]["reportLinks"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report links command.
+ script_toggleReportLinks.__doc__=_("Toggles on and off the reporting of
links")
+ script_toggleReportLinks.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportComments(self,gesture):
+ if config.conf["documentFormatting"]["reportComments"]:
+ # Translators: The message announced when toggling the
report comments document formatting setting.
+ state = _("report comments off")
+
config.conf["documentFormatting"]["reportComments"]=False
+ else:
+ # Translators: The message announced when toggling the
report comments document formatting setting.
+ state = _("report comments on")
+ config.conf["documentFormatting"]["reportComments"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report comments
command.
+ script_toggleReportComments.__doc__=_("Toggles on and off the reporting
of comments")
+ script_toggleReportComments.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLists(self,gesture):
+ if config.conf["documentFormatting"]["reportLists"]:
+ # Translators: The message announced when toggling the
report lists document formatting setting.
+ state = _("report lists off")
+ config.conf["documentFormatting"]["reportLists"]=False
+ else:
+ # Translators: The message announced when toggling the
report lists document formatting setting.
+ state = _("report lists on")
+ config.conf["documentFormatting"]["reportLists"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report lists command.
+ script_toggleReportLists.__doc__=_("Toggles on and off the reporting of
lists")
+ script_toggleReportLists.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportHeadings(self,gesture):
+ if config.conf["documentFormatting"]["reportHeadings"]:
+ # Translators: The message announced when toggling the
report headings document formatting setting.
+ state = _("report headings off")
+
config.conf["documentFormatting"]["reportHeadings"]=False
+ else:
+ # Translators: The message announced when toggling the
report headings document formatting setting.
+ state = _("report headings on")
+ config.conf["documentFormatting"]["reportHeadings"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report headings
command.
+ script_toggleReportHeadings.__doc__=_("Toggles on and off the reporting
of headings")
+ script_toggleReportHeadings.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportBlockQuotes(self,gesture):
+ if config.conf["documentFormatting"]["reportBlockQuotes"]:
+ # Translators: The message announced when toggling the
report block quotes document formatting setting.
+ state = _("report block quotes off")
+
config.conf["documentFormatting"]["reportBlockQuotes"]=False
+ else:
+ # Translators: The message announced when toggling the
report block quotes document formatting setting.
+ state = _("report block quotes on")
+
config.conf["documentFormatting"]["reportBlockQuotes"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report block quotes
command.
+ script_toggleReportBlockQuotes.__doc__=_("Toggles on and off the
reporting of block quotes")
+ script_toggleReportBlockQuotes.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLandmarks(self,gesture):
+ if config.conf["documentFormatting"]["reportLandmarks"]:
+ # Translators: The message announced when toggling the
report landmarks document formatting setting.
+ state = _("report landmarks off")
+
config.conf["documentFormatting"]["reportLandmarks"]=False
+ else:
+ # Translators: The message announced when toggling the
report landmarks document formatting setting.
+ state = _("report landmarks on")
+
config.conf["documentFormatting"]["reportLandmarks"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report landmarks
command.
+ script_toggleReportLandmarks.__doc__=_("Toggles on and off the
reporting of landmarks")
+ script_toggleReportLandmarks.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFrames(self,gesture):
+ if config.conf["documentFormatting"]["reportFrames"]:
+ # Translators: The message announced when toggling the
report frames document formatting setting.
+ state = _("report frames off")
+ config.conf["documentFormatting"]["reportFrames"]=False
+ else:
+ # Translators: The message announced when toggling the
report frames document formatting setting.
+ state = _("report frames on")
+ config.conf["documentFormatting"]["reportFrames"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report frames command.
+ script_toggleReportFrames.__doc__=_("Toggles on and off the reporting
of frames")
+ script_toggleReportFrames.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportClickable(self,gesture):
+ if config.conf["documentFormatting"]["reportClickable"]:
+ # Translators: The message announced when toggling the
report if clickable document formatting setting.
+ state = _("report if clickable off")
+
config.conf["documentFormatting"]["reportClickable"]=False
+ else:
+ # Translators: The message announced when toggling the
report if clickable document formatting setting.
+ state = _("report if clickable on")
+
config.conf["documentFormatting"]["reportClickable"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report if clickable
command.
+ script_toggleReportClickable.__doc__=_("Toggles on and off reporting if
clickable")
+ script_toggleReportClickable.category=SCRCAT_DOCUMENTFORMATTING
+
def script_cycleSpeechSymbolLevel(self,gesture):
curLevel = config.conf["speech"]["symbolLevel"]
for level in
characterProcessing.CONFIGURABLE_SPEECH_SYMBOL_LEVELS:
@@ -1112,7 +1436,6 @@ class GlobalCommands(ScriptableObject):
script_activateGeneralSettingsDialog.__doc__ = _("Shows the NVDA
general settings dialog")
script_activateGeneralSettingsDialog.category=SCRCAT_CONFIG

-
def script_activateSynthesizerDialog(self, gesture):
wx.CallAfter(gui.mainFrame.onSynthesizerCommand, None)
# Translators: Input help mode message for go to synthesizer dialog
command.
@@ -1125,6 +1448,12 @@ class GlobalCommands(ScriptableObject):
script_activateVoiceDialog.__doc__ = _("Shows the NVDA voice settings
dialog")
script_activateVoiceDialog.category=SCRCAT_CONFIG

+ def script_activateBrailleSettingsDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onBrailleCommand, None)
+ # Translators: Input help mode message for go to braille settings
dialog command.
+ script_activateBrailleSettingsDialog.__doc__ = _("Shows the NVDA
braille settings dialog")
+ script_activateBrailleSettingsDialog.category=SCRCAT_CONFIG
+
def script_activateKeyboardSettingsDialog(self, gesture):
wx.CallAfter(gui.mainFrame.onKeyboardSettingsCommand, None)
# Translators: Input help mode message for go to keyboard settings
dialog command.
@@ -1137,6 +1466,18 @@ class GlobalCommands(ScriptableObject):
script_activateMouseSettingsDialog.__doc__ = _("Shows the NVDA mouse
settings dialog")
script_activateMouseSettingsDialog.category=SCRCAT_CONFIG

+ def script_activateReviewCursorDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onReviewCursorCommand, None)
+ # Translators: Input help mode message for go to review cursor settings
dialog command.
+ script_activateReviewCursorDialog.__doc__ = _("Shows the NVDA review
cursor settings dialog")
+ script_activateReviewCursorDialog.category=SCRCAT_CONFIG
+
+ def script_activateInputCompositionDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onInputCompositionCommand, None)
+ # Translators: Input help mode message for go to input composition
dialog.
+ script_activateInputCompositionDialog.__doc__ = _("Shows the NVDA input
composition settings dialog")
+ script_activateInputCompositionDialog.category=SCRCAT_CONFIG
+
def script_activateObjectPresentationDialog(self, gesture):
wx.CallAfter(gui.mainFrame. onObjectPresentationCommand, None)
# Translators: Input help mode message for go to object presentation
dialog command.
@@ -1155,6 +1496,36 @@ class GlobalCommands(ScriptableObject):
script_activateDocumentFormattingDialog.__doc__ = _("Shows the NVDA
document formatting settings dialog")
script_activateDocumentFormattingDialog.category=SCRCAT_CONFIG

+ def script_activateDefaultDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onDefaultDictionaryCommand, None)
+ # Translators: Input help mode message for opening default dictionary
dialog.
+ script_activateDefaultDictionaryDialog.__doc__ = _("Shows the NVDA
default dictionary dialog")
+ script_activateDefaultDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateVoiceDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onVoiceDictionaryCommand, None)
+ # Translators: Input help mode message for opening voice-specific
dictionary dialog.
+ script_activateVoiceDictionaryDialog.__doc__ = _("Shows the NVDA
voice-specific dictionary dialog")
+ script_activateVoiceDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateTemporaryDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onTemporaryDictionaryCommand, None)
+ # Translators: Input help mode message for opening temporary dictionary.
+ script_activateTemporaryDictionaryDialog.__doc__ = _("Shows the NVDA
temporary dictionary dialog")
+ script_activateTemporaryDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateSpeechSymbolsDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onSpeechSymbolsCommand, None)
+ # Translators: Input help mode message for go to punctuation/symbol
pronunciation dialog.
+ script_activateSpeechSymbolsDialog.__doc__ = _("Shows the NVDA symbol
pronunciation dialog")
+ script_activateSpeechSymbolsDialog.category=SCRCAT_CONFIG
+
+ def script_activateInputGesturesDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onInputGesturesCommand, None)
+ # Translators: Input help mode message for go to input gestures dialog
command.
+ script_activateInputGesturesDialog.__doc__ = _("Shows the NVDA input
gestures dialog")
+ script_activateInputGesturesDialog.category=SCRCAT_CONFIG
+
def script_saveConfiguration(self,gesture):
wx.CallAfter(gui.mainFrame.onSaveConfigurationCommand, None)
# Translators: Input help mode message for save current configuration
command.
@@ -1183,6 +1554,28 @@ class GlobalCommands(ScriptableObject):
script_activatePythonConsole.__doc__ = _("Activates the NVDA Python
Console, primarily useful for development")
script_activatePythonConsole.category=SCRCAT_TOOLS

+ def script_activateAddonsManager(self,gesture):
+ wx.CallAfter(gui.mainFrame.onAddonsManagerCommand, None)
+ # Translators: Input help mode message for activate manage
add-ons command.
+ script_activateAddonsManager.__doc__ = _("Activates the NVDA Add-ons
Manager to install and uninstall add-on packages for NVDA")
+ script_activateAddonsManager.category=SCRCAT_TOOLS
+
+ def script_toggleSpeechViewer(self,gesture):
+ if gui.speechViewer.isActive:
+ # Translators: The message announced when disabling
speech viewer.
+ state = _("speech viewer disabled")
+ gui.speechViewer.deactivate()
+
gui.mainFrame.sysTrayIcon.menu_tools_toggleSpeechViewer.Check(False)
+ else:
+ # Translators: The message announced when enabling
speech viewer.
+ state = _("speech viewer enabled")
+ gui.speechViewer.activate()
+
gui.mainFrame.sysTrayIcon.menu_tools_toggleSpeechViewer.Check(True)
+ ui.message(state)
+ # Translators: Input help mode message for toggle speech viewer
command.
+ script_toggleSpeechViewer.__doc__ = _("Toggles the NVDA Speech viewer,
a floating window that allows you to view all the text that NVDA is currently
speaking")
+ script_toggleSpeechViewer.category=SCRCAT_TOOLS
+
def script_braille_toggleTether(self, gesture):
if braille.handler.tether == braille.handler.TETHER_FOCUS:
braille.handler.tether = braille.handler.TETHER_REVIEW
@@ -1382,6 +1775,7 @@ class GlobalCommands(ScriptableObject):
wx.CallAfter(gui.mainFrame.onConfigProfilesCommand, None)
# Translators: Describes the command to open the Configuration Profiles
dialog.
script_activateConfigProfilesDialog.__doc__ = _("Shows the NVDA
Configuration Profiles dialog")
+ script_activateConfigProfilesDialog.category=SCRCAT_CONFIG

__gestures = {
# Basic

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 677431b..a858032 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -589,6 +589,9 @@ In all NVDA settings dialog boxes, press the OK button to
accept any changes you
To cancel any changes, press the Cancel button or the escape key.
Some settings can also be changed using shortcut keys, which are listed where
relevant in the sections below.

+Note that by default, not all preferences dialogs can be accessed with input
gestures (keyboard commands, touch gestures, etc.).
+If you wish to access dialogs which don't have dedicated shortcut keys, use
the [Input Gestures dialog #InputGestures] to add custom gesture for that
dialog.
+
+++ General Settings (NVDA+control+g) +++
The General settings dialog box is found in the Preferences menu.
It contains the following options:
@@ -1063,6 +1066,8 @@ You can configure reporting of:
- Frames
-

+To toggle these settings from anywhere, please assign custom gestures using
the [Input Gestures dialog #InputGestures].
+
==== Announce formatting changes after the cursor ====
If enabled, this setting tells NVDA to try and detect all the formatting
changes on a line as it speaks it, even if doing this may slow down NVDA's
performance.

@@ -1079,6 +1084,8 @@ They are:
- Temporary: rules in this dictionary affect all speech in NVDA, but only for
the current session. These rules are temporary and will be lost if NVDA is
restarted.
-

+You need to assign custom gestures using the [Input Gestures dialog
#InputGestures] if you wish to open any of these dictionary dialogs from
anywhere.
+
All dictionary dialogs contain a list of rules which will be used for
processing the speech.
The dialog also contains Add, Edit and Remove buttons.

@@ -1120,7 +1127,7 @@ You can remove a symbol you previously added by pressing
the Remove button.

When you are finished, press the OK button to save your changes or the Cancel
button to discard them.

-+++ Input Gestures +++
++++ Input Gestures +++[InputGestures]
In this dialog, you can customize the input gestures (keys on the keyboard,
buttons on a braille display, etc.) for NVDA commands.

Only commands that are applicable immediately before the dialog is opened are
shown.
@@ -1256,6 +1263,8 @@ Uncheck the menu item to disable it.
While the speech viewer is enabled, it constantly updates to show you the most
current text being spoken.
However, if you click or focus inside the viewer, NVDA will temporarily stop
updating the text, so that you are able to easily select or copy the existing
content.

+To toggle the speech viewer from anywhere, please assign a custom gesture
using the [Input Gestures dialog #InputGestures].
+
++ Add-ons Manager ++
The Add-ons Manager, accessed by selecting Manage add-ons under Tools in the
NVDA menu, allows you to install and uninstall add-on packages for NVDA.
These packages are provided by the community and contain custom code that may
add or change features in NVDA or even provide support for extra Braille
displays or speech synthesizers.
@@ -1290,6 +1299,8 @@ In the past it has been possible to extend NVDA's
functionality by copying indiv
Although this version of NVDA may still load them, they will not be shown
in the Add-on Manager.
It is best to remove these files from your configuration and install the
appropriate add-on if one is available.

+To access the Add-ons Manager from anywhere, please assign a custom gesture
using the [Input Gestures dialog #InputGestures].
+
++ Python Console ++
The NVDA Python console, found under Tools in the NVDA menu, is a development
tool which is useful for debugging, general inspection of NVDA internals or
inspection of the accessibility hierarchy of an application.
For more information, please see the Developer Guide available from [the
Development section of the NVDA web site
http://community.nvda-project.org/wiki/Development].


https://bitbucket.org/nvdaaddonteam/nvda/commits/bb6ea40acf8e/
Changeset: bb6ea40acf8e
Branch: None
User: jteh
Date: 2015-04-20 02:01:24+00:00
Summary: Merge branch 't4898' into next

Incubates #4898.

Affected #: 2 files

diff --git a/source/globalCommands.py b/source/globalCommands.py
index bae043f..7764318 100755
--- a/source/globalCommands.py
+++ b/source/globalCommands.py
@@ -3,7 +3,7 @@
#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) 2006-2014 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista
+#Copyright (C) 2006-2015 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui
Batista, Joseph Lee, Leonard de Ruijter

import time
import itertools
@@ -39,10 +39,10 @@ import virtualBuffers
import characterProcessing
from baseObject import ScriptableObject

-#: Script category for text review commands.
+#: Script category for text review commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_TEXTREVIEW = _("Text review")
-#: Script category for Object navigation commands.
+#: Script category for Object navigation commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_OBJECTNAVIGATION = _("Object navigation")
#: Script category for system caret commands.
@@ -51,7 +51,7 @@ SCRCAT_SYSTEMCARET = _("System caret")
#: Script category for mouse commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_MOUSE = _("Mouse")
-#: Script category for mouse commands.
+#: Script category for speech commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_SPEECH = _("Speech")
#: Script category for configuration dialogs commands.
@@ -69,12 +69,15 @@ SCRCAT_TOUCH = _("Touch screen")
#: Script category for focus commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_FOCUS = _("System focus")
-#: Script category for system status commands.
+#: Script category for system status commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_SYSTEM = _("System status")
-#: Script category for input commands.
+#: Script category for input commands.
# Translators: The name of a category of NVDA commands.
SCRCAT_INPUT = _("Input")
+#: Script category for document formatting commands.
+# Translators: The name of a category of NVDA commands.
+SCRCAT_DOCUMENTFORMATTING = _("Document formatting")

class GlobalCommands(ScriptableObject):
"""Commands that are available at all times, regardless of the current
focus.
@@ -92,7 +95,6 @@ class GlobalCommands(ScriptableObject):
script_toggleInputHelp.__doc__=_("Turns input help on or off. When on,
any input such as pressing a key on the keyboard will tell you what script is
associated with that input, if any.")
script_toggleInputHelp.category=SCRCAT_INPUT

-
def script_toggleCurrentAppSleepMode(self,gesture):
curFocus=api.getFocusObject()
curApp=curFocus.appModule
@@ -286,6 +288,328 @@ class GlobalCommands(ScriptableObject):
script_toggleSpeakCommandKeys.__doc__=_("Toggles on and off the
speaking of typed keys, that are not specifically characters")
script_toggleSpeakCommandKeys.category=SCRCAT_SPEECH

+ def script_toggleReportFontName(self,gesture):
+ if config.conf["documentFormatting"]["reportFontName"]:
+ # Translators: The message announced when toggling the
report font name document formatting setting.
+ state = _("report font name off")
+
config.conf["documentFormatting"]["reportFontName"]=False
+ else:
+ # Translators: The message announced when toggling the
report font name document formatting setting.
+ state = _("report font name on")
+ config.conf["documentFormatting"]["reportFontName"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font name
command.
+ script_toggleReportFontName.__doc__=_("Toggles on and off the reporting
of font changes")
+ script_toggleReportFontName.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFontSize(self,gesture):
+ if config.conf["documentFormatting"]["reportFontSize"]:
+ # Translators: The message announced when toggling the
report font size document formatting setting.
+ state = _("report font size off")
+
config.conf["documentFormatting"]["reportFontSize"]=False
+ else:
+ # Translators: The message announced when toggling the
report font size document formatting setting.
+ state = _("report font size on")
+ config.conf["documentFormatting"]["reportFontSize"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font size
command.
+ script_toggleReportFontSize.__doc__=_("Toggles on and off the reporting
of font size changes")
+ script_toggleReportFontSize.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFontAttributes(self,gesture):
+ if config.conf["documentFormatting"]["reportFontAttributes"]:
+ # Translators: The message announced when toggling the
report font attributes document formatting setting.
+ state = _("report font attributes off")
+
config.conf["documentFormatting"]["reportFontAttributes"]=False
+ else:
+ # Translators: The message announced when toggling the
report font attributes document formatting setting.
+ state = _("report font attributes on")
+
config.conf["documentFormatting"]["reportFontAttributes"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report font
attributes command.
+ script_toggleReportFontAttributes.__doc__=_("Toggles on and off the
reporting of font attributes")
+ script_toggleReportFontAttributes.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportRevisions(self,gesture):
+ if config.conf["documentFormatting"]["reportRevisions"]:
+ # Translators: The message announced when toggling the
report revisions document formatting setting.
+ state = _("report revisions off")
+
config.conf["documentFormatting"]["reportRevisions"]=False
+ else:
+ # Translators: The message announced when toggling the
report revisions document formatting setting.
+ state = _("report revisions on")
+
config.conf["documentFormatting"]["reportRevisions"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report revisions
command.
+ script_toggleReportRevisions.__doc__=_("Toggles on and off the
reporting of revisions")
+ script_toggleReportRevisions.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportColor(self,gesture):
+ if config.conf["documentFormatting"]["reportColor"]:
+ # Translators: The message announced when toggling the
report colors document formatting setting.
+ state = _("report colors off")
+ config.conf["documentFormatting"]["reportColor"]=False
+ else:
+ # Translators: The message announced when toggling the
report colors document formatting setting.
+ state = _("report colors on")
+ config.conf["documentFormatting"]["reportColor"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report colors command.
+ script_toggleReportColor.__doc__=_("Toggles on and off the reporting of
colors")
+ script_toggleReportColor.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportAlignment(self,gesture):
+ if config.conf["documentFormatting"]["reportAlignment"]:
+ # Translators: The message announced when toggling the
report alignment document formatting setting.
+ state = _("report alignment off")
+
config.conf["documentFormatting"]["reportAlignment"]=False
+ else:
+ # Translators: The message announced when toggling the
report alignment document formatting setting.
+ state = _("report alignment on")
+
config.conf["documentFormatting"]["reportAlignment"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report alignment
command.
+ script_toggleReportAlignment.__doc__=_("Toggles on and off the
reporting of text alignment")
+ script_toggleReportAlignment.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportStyle(self,gesture):
+ if config.conf["documentFormatting"]["reportStyle"]:
+ # Translators: The message announced when toggling the
report style document formatting setting.
+ state = _("report style off")
+ config.conf["documentFormatting"]["reportStyle"]=False
+ else:
+ # Translators: The message announced when toggling the
report style document formatting setting.
+ state = _("report style on")
+ config.conf["documentFormatting"]["reportStyle"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report style command.
+ script_toggleReportStyle.__doc__=_("Toggles on and off the reporting of
style changes")
+ script_toggleReportStyle.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportSpellingErrors(self,gesture):
+ if config.conf["documentFormatting"]["reportSpellingErrors"]:
+ # Translators: The message announced when toggling the
report spelling errors document formatting setting.
+ state = _("report spelling errors off")
+
config.conf["documentFormatting"]["reportSpellingErrors"]=False
+ else:
+ # Translators: The message announced when toggling the
report spelling errors document formatting setting.
+ state = _("report spelling errors on")
+
config.conf["documentFormatting"]["reportSpellingErrors"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report spelling
errors command.
+ script_toggleReportSpellingErrors.__doc__=_("Toggles on and off the
reporting of spelling errors")
+ script_toggleReportSpellingErrors.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportPage(self,gesture):
+ if config.conf["documentFormatting"]["reportPage"]:
+ # Translators: The message announced when toggling the
report pages document formatting setting.
+ state = _("report pages off")
+ config.conf["documentFormatting"]["reportPage"]=False
+ else:
+ # Translators: The message announced when toggling the
report pages document formatting setting.
+ state = _("report pages on")
+ config.conf["documentFormatting"]["reportPage"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report pages command.
+ script_toggleReportPage.__doc__=_("Toggles on and off the reporting of
pages")
+ script_toggleReportPage.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLineNumber(self,gesture):
+ if config.conf["documentFormatting"]["reportLineNumber"]:
+ # Translators: The message announced when toggling the
report line numbers document formatting setting.
+ state = _("report line numbers off")
+
config.conf["documentFormatting"]["reportLineNumber"]=False
+ else:
+ # Translators: The message announced when toggling the
report line numbers document formatting setting.
+ state = _("report line numbers on")
+
config.conf["documentFormatting"]["reportLineNumber"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report line numbers
command.
+ script_toggleReportLineNumber.__doc__=_("Toggles on and off the
reporting of line numbers")
+ script_toggleReportLineNumber.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLineIndentation(self,gesture):
+ if config.conf["documentFormatting"]["reportLineIndentation"]:
+ # Translators: The message announced when toggling the
report line indentation document formatting setting.
+ state = _("report line indentation off")
+
config.conf["documentFormatting"]["reportLineIndentation"]=False
+ else:
+ # Translators: The message announced when toggling the
report line indentation document formatting setting.
+ state = _("report line indentation on")
+
config.conf["documentFormatting"]["reportLineIndentation"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report line
indentation command.
+ script_toggleReportLineIndentation.__doc__=_("Toggles on and off the
reporting of line indentation")
+ script_toggleReportLineIndentation.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportParagraphIndentation(self,gesture):
+ if
config.conf["documentFormatting"]["reportParagraphIndentation"]:
+ # Translators: The message announced when toggling the
report paragraph indentation document formatting setting.
+ state = _("report paragraph indentation off")
+
config.conf["documentFormatting"]["reportParagraphIndentation"]=False
+ else:
+ # Translators: The message announced when toggling the
report paragraph indentation document formatting setting.
+ state = _("report paragraph indentation on")
+
config.conf["documentFormatting"]["reportParagraphIndentation"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report paragraph
indentation command.
+ script_toggleReportParagraphIndentation.__doc__=_("Toggles on and off
the reporting of paragraph indentation")
+
script_toggleReportParagraphIndentation.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTables(self,gesture):
+ if config.conf["documentFormatting"]["reportTables"]:
+ # Translators: The message announced when toggling the
report tables document formatting setting.
+ state = _("report tables off")
+ config.conf["documentFormatting"]["reportTables"]=False
+ else:
+ # Translators: The message announced when toggling the
report tables document formatting setting.
+ state = _("report tables on")
+ config.conf["documentFormatting"]["reportTables"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report tables command.
+ script_toggleReportTables.__doc__=_("Toggles on and off the reporting
of tables")
+ script_toggleReportTables.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTableHeaders(self,gesture):
+ if config.conf["documentFormatting"]["reportTableHeaders"]:
+ # Translators: The message announced when toggling the
report table row/column headers document formatting setting.
+ state = _("report table row and column headers off")
+
config.conf["documentFormatting"]["reportTableHeaders"]=False
+ else:
+ # Translators: The message announced when toggling the
report table row/column headers document formatting setting.
+ state = _("report table row and column headers on")
+
config.conf["documentFormatting"]["reportTableHeaders"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report table
row/column headers command.
+ script_toggleReportTableHeaders.__doc__=_("Toggles on and off the
reporting of table row and column headers")
+ script_toggleReportTableHeaders.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportTableCellCoords(self,gesture):
+ if config.conf["documentFormatting"]["reportTableCellCoords"]:
+ # Translators: The message announced when toggling the
report table cell coordinates document formatting setting.
+ state = _("report table cell coordinates off")
+
config.conf["documentFormatting"]["reportTableCellCoords"]=False
+ else:
+ # Translators: The message announced when toggling the
report table cell coordinates document formatting setting.
+ state = _("report table cell coordinates on")
+
config.conf["documentFormatting"]["reportTableCellCoords"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report table cell
coordinates command.
+ script_toggleReportTableCellCoords.__doc__=_("Toggles on and off the
reporting of table cell coordinates")
+ script_toggleReportTableCellCoords.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLinks(self,gesture):
+ if config.conf["documentFormatting"]["reportLinks"]:
+ # Translators: The message announced when toggling the
report links document formatting setting.
+ state = _("report links off")
+ config.conf["documentFormatting"]["reportLinks"]=False
+ else:
+ # Translators: The message announced when toggling the
report links document formatting setting.
+ state = _("report links on")
+ config.conf["documentFormatting"]["reportLinks"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report links command.
+ script_toggleReportLinks.__doc__=_("Toggles on and off the reporting of
links")
+ script_toggleReportLinks.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportComments(self,gesture):
+ if config.conf["documentFormatting"]["reportComments"]:
+ # Translators: The message announced when toggling the
report comments document formatting setting.
+ state = _("report comments off")
+
config.conf["documentFormatting"]["reportComments"]=False
+ else:
+ # Translators: The message announced when toggling the
report comments document formatting setting.
+ state = _("report comments on")
+ config.conf["documentFormatting"]["reportComments"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report comments
command.
+ script_toggleReportComments.__doc__=_("Toggles on and off the reporting
of comments")
+ script_toggleReportComments.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLists(self,gesture):
+ if config.conf["documentFormatting"]["reportLists"]:
+ # Translators: The message announced when toggling the
report lists document formatting setting.
+ state = _("report lists off")
+ config.conf["documentFormatting"]["reportLists"]=False
+ else:
+ # Translators: The message announced when toggling the
report lists document formatting setting.
+ state = _("report lists on")
+ config.conf["documentFormatting"]["reportLists"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report lists command.
+ script_toggleReportLists.__doc__=_("Toggles on and off the reporting of
lists")
+ script_toggleReportLists.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportHeadings(self,gesture):
+ if config.conf["documentFormatting"]["reportHeadings"]:
+ # Translators: The message announced when toggling the
report headings document formatting setting.
+ state = _("report headings off")
+
config.conf["documentFormatting"]["reportHeadings"]=False
+ else:
+ # Translators: The message announced when toggling the
report headings document formatting setting.
+ state = _("report headings on")
+ config.conf["documentFormatting"]["reportHeadings"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report headings
command.
+ script_toggleReportHeadings.__doc__=_("Toggles on and off the reporting
of headings")
+ script_toggleReportHeadings.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportBlockQuotes(self,gesture):
+ if config.conf["documentFormatting"]["reportBlockQuotes"]:
+ # Translators: The message announced when toggling the
report block quotes document formatting setting.
+ state = _("report block quotes off")
+
config.conf["documentFormatting"]["reportBlockQuotes"]=False
+ else:
+ # Translators: The message announced when toggling the
report block quotes document formatting setting.
+ state = _("report block quotes on")
+
config.conf["documentFormatting"]["reportBlockQuotes"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report block quotes
command.
+ script_toggleReportBlockQuotes.__doc__=_("Toggles on and off the
reporting of block quotes")
+ script_toggleReportBlockQuotes.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportLandmarks(self,gesture):
+ if config.conf["documentFormatting"]["reportLandmarks"]:
+ # Translators: The message announced when toggling the
report landmarks document formatting setting.
+ state = _("report landmarks off")
+
config.conf["documentFormatting"]["reportLandmarks"]=False
+ else:
+ # Translators: The message announced when toggling the
report landmarks document formatting setting.
+ state = _("report landmarks on")
+
config.conf["documentFormatting"]["reportLandmarks"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report landmarks
command.
+ script_toggleReportLandmarks.__doc__=_("Toggles on and off the
reporting of landmarks")
+ script_toggleReportLandmarks.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportFrames(self,gesture):
+ if config.conf["documentFormatting"]["reportFrames"]:
+ # Translators: The message announced when toggling the
report frames document formatting setting.
+ state = _("report frames off")
+ config.conf["documentFormatting"]["reportFrames"]=False
+ else:
+ # Translators: The message announced when toggling the
report frames document formatting setting.
+ state = _("report frames on")
+ config.conf["documentFormatting"]["reportFrames"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report frames command.
+ script_toggleReportFrames.__doc__=_("Toggles on and off the reporting
of frames")
+ script_toggleReportFrames.category=SCRCAT_DOCUMENTFORMATTING
+
+ def script_toggleReportClickable(self,gesture):
+ if config.conf["documentFormatting"]["reportClickable"]:
+ # Translators: The message announced when toggling the
report if clickable document formatting setting.
+ state = _("report if clickable off")
+
config.conf["documentFormatting"]["reportClickable"]=False
+ else:
+ # Translators: The message announced when toggling the
report if clickable document formatting setting.
+ state = _("report if clickable on")
+
config.conf["documentFormatting"]["reportClickable"]=True
+ ui.message(state)
+ # Translators: Input help mode message for toggle report if clickable
command.
+ script_toggleReportClickable.__doc__=_("Toggles on and off reporting if
clickable")
+ script_toggleReportClickable.category=SCRCAT_DOCUMENTFORMATTING
+
def script_cycleSpeechSymbolLevel(self,gesture):
curLevel = config.conf["speech"]["symbolLevel"]
for level in
characterProcessing.CONFIGURABLE_SPEECH_SYMBOL_LEVELS:
@@ -1112,7 +1436,6 @@ class GlobalCommands(ScriptableObject):
script_activateGeneralSettingsDialog.__doc__ = _("Shows the NVDA
general settings dialog")
script_activateGeneralSettingsDialog.category=SCRCAT_CONFIG

-
def script_activateSynthesizerDialog(self, gesture):
wx.CallAfter(gui.mainFrame.onSynthesizerCommand, None)
# Translators: Input help mode message for go to synthesizer dialog
command.
@@ -1125,6 +1448,12 @@ class GlobalCommands(ScriptableObject):
script_activateVoiceDialog.__doc__ = _("Shows the NVDA voice settings
dialog")
script_activateVoiceDialog.category=SCRCAT_CONFIG

+ def script_activateBrailleSettingsDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onBrailleCommand, None)
+ # Translators: Input help mode message for go to braille settings
dialog command.
+ script_activateBrailleSettingsDialog.__doc__ = _("Shows the NVDA
braille settings dialog")
+ script_activateBrailleSettingsDialog.category=SCRCAT_CONFIG
+
def script_activateKeyboardSettingsDialog(self, gesture):
wx.CallAfter(gui.mainFrame.onKeyboardSettingsCommand, None)
# Translators: Input help mode message for go to keyboard settings
dialog command.
@@ -1137,6 +1466,18 @@ class GlobalCommands(ScriptableObject):
script_activateMouseSettingsDialog.__doc__ = _("Shows the NVDA mouse
settings dialog")
script_activateMouseSettingsDialog.category=SCRCAT_CONFIG

+ def script_activateReviewCursorDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onReviewCursorCommand, None)
+ # Translators: Input help mode message for go to review cursor settings
dialog command.
+ script_activateReviewCursorDialog.__doc__ = _("Shows the NVDA review
cursor settings dialog")
+ script_activateReviewCursorDialog.category=SCRCAT_CONFIG
+
+ def script_activateInputCompositionDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onInputCompositionCommand, None)
+ # Translators: Input help mode message for go to input composition
dialog.
+ script_activateInputCompositionDialog.__doc__ = _("Shows the NVDA input
composition settings dialog")
+ script_activateInputCompositionDialog.category=SCRCAT_CONFIG
+
def script_activateObjectPresentationDialog(self, gesture):
wx.CallAfter(gui.mainFrame. onObjectPresentationCommand, None)
# Translators: Input help mode message for go to object presentation
dialog command.
@@ -1155,6 +1496,36 @@ class GlobalCommands(ScriptableObject):
script_activateDocumentFormattingDialog.__doc__ = _("Shows the NVDA
document formatting settings dialog")
script_activateDocumentFormattingDialog.category=SCRCAT_CONFIG

+ def script_activateDefaultDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onDefaultDictionaryCommand, None)
+ # Translators: Input help mode message for opening default dictionary
dialog.
+ script_activateDefaultDictionaryDialog.__doc__ = _("Shows the NVDA
default dictionary dialog")
+ script_activateDefaultDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateVoiceDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onVoiceDictionaryCommand, None)
+ # Translators: Input help mode message for opening voice-specific
dictionary dialog.
+ script_activateVoiceDictionaryDialog.__doc__ = _("Shows the NVDA
voice-specific dictionary dialog")
+ script_activateVoiceDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateTemporaryDictionaryDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onTemporaryDictionaryCommand, None)
+ # Translators: Input help mode message for opening temporary dictionary.
+ script_activateTemporaryDictionaryDialog.__doc__ = _("Shows the NVDA
temporary dictionary dialog")
+ script_activateTemporaryDictionaryDialog.category=SCRCAT_CONFIG
+
+ def script_activateSpeechSymbolsDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onSpeechSymbolsCommand, None)
+ # Translators: Input help mode message for go to punctuation/symbol
pronunciation dialog.
+ script_activateSpeechSymbolsDialog.__doc__ = _("Shows the NVDA symbol
pronunciation dialog")
+ script_activateSpeechSymbolsDialog.category=SCRCAT_CONFIG
+
+ def script_activateInputGesturesDialog(self, gesture):
+ wx.CallAfter(gui.mainFrame.onInputGesturesCommand, None)
+ # Translators: Input help mode message for go to input gestures dialog
command.
+ script_activateInputGesturesDialog.__doc__ = _("Shows the NVDA input
gestures dialog")
+ script_activateInputGesturesDialog.category=SCRCAT_CONFIG
+
def script_saveConfiguration(self,gesture):
wx.CallAfter(gui.mainFrame.onSaveConfigurationCommand, None)
# Translators: Input help mode message for save current configuration
command.
@@ -1183,6 +1554,28 @@ class GlobalCommands(ScriptableObject):
script_activatePythonConsole.__doc__ = _("Activates the NVDA Python
Console, primarily useful for development")
script_activatePythonConsole.category=SCRCAT_TOOLS

+ def script_activateAddonsManager(self,gesture):
+ wx.CallAfter(gui.mainFrame.onAddonsManagerCommand, None)
+ # Translators: Input help mode message for activate manage
add-ons command.
+ script_activateAddonsManager.__doc__ = _("Activates the NVDA Add-ons
Manager to install and uninstall add-on packages for NVDA")
+ script_activateAddonsManager.category=SCRCAT_TOOLS
+
+ def script_toggleSpeechViewer(self,gesture):
+ if gui.speechViewer.isActive:
+ # Translators: The message announced when disabling
speech viewer.
+ state = _("speech viewer disabled")
+ gui.speechViewer.deactivate()
+
gui.mainFrame.sysTrayIcon.menu_tools_toggleSpeechViewer.Check(False)
+ else:
+ # Translators: The message announced when enabling
speech viewer.
+ state = _("speech viewer enabled")
+ gui.speechViewer.activate()
+
gui.mainFrame.sysTrayIcon.menu_tools_toggleSpeechViewer.Check(True)
+ ui.message(state)
+ # Translators: Input help mode message for toggle speech viewer
command.
+ script_toggleSpeechViewer.__doc__ = _("Toggles the NVDA Speech viewer,
a floating window that allows you to view all the text that NVDA is currently
speaking")
+ script_toggleSpeechViewer.category=SCRCAT_TOOLS
+
def script_braille_toggleTether(self, gesture):
if braille.handler.tether == braille.handler.TETHER_FOCUS:
braille.handler.tether = braille.handler.TETHER_REVIEW
@@ -1382,6 +1775,7 @@ class GlobalCommands(ScriptableObject):
wx.CallAfter(gui.mainFrame.onConfigProfilesCommand, None)
# Translators: Describes the command to open the Configuration Profiles
dialog.
script_activateConfigProfilesDialog.__doc__ = _("Shows the NVDA
Configuration Profiles dialog")
+ script_activateConfigProfilesDialog.category=SCRCAT_CONFIG

def script_interactWithMath(self, gesture):
import mathPres

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 9880de5..17cbf34 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -626,6 +626,9 @@ In all NVDA settings dialog boxes, press the OK button to
accept any changes you
To cancel any changes, press the Cancel button or the escape key.
Some settings can also be changed using shortcut keys, which are listed where
relevant in the sections below.

+Note that by default, not all preferences dialogs can be accessed with input
gestures (keyboard commands, touch gestures, etc.).
+If you wish to access dialogs which don't have dedicated shortcut keys, use
the [Input Gestures dialog #InputGestures] to add custom gesture for that
dialog.
+
+++ General Settings (NVDA+control+g) +++
The General settings dialog box is found in the Preferences menu.
It contains the following options:
@@ -1100,6 +1103,8 @@ You can configure reporting of:
- Frames
-

+To toggle these settings from anywhere, please assign custom gestures using
the [Input Gestures dialog #InputGestures].
+
==== Announce formatting changes after the cursor ====
If enabled, this setting tells NVDA to try and detect all the formatting
changes on a line as it speaks it, even if doing this may slow down NVDA's
performance.

@@ -1116,6 +1121,8 @@ They are:
- Temporary: rules in this dictionary affect all speech in NVDA, but only for
the current session. These rules are temporary and will be lost if NVDA is
restarted.
-

+You need to assign custom gestures using the [Input Gestures dialog
#InputGestures] if you wish to open any of these dictionary dialogs from
anywhere.
+
All dictionary dialogs contain a list of rules which will be used for
processing the speech.
The dialog also contains Add, Edit and Remove buttons.

@@ -1157,7 +1164,7 @@ You can remove a symbol you previously added by pressing
the Remove button.

When you are finished, press the OK button to save your changes or the Cancel
button to discard them.

-+++ Input Gestures +++
++++ Input Gestures +++[InputGestures]
In this dialog, you can customize the input gestures (keys on the keyboard,
buttons on a braille display, etc.) for NVDA commands.

Only commands that are applicable immediately before the dialog is opened are
shown.
@@ -1293,6 +1300,8 @@ Uncheck the menu item to disable it.
While the speech viewer is enabled, it constantly updates to show you the most
current text being spoken.
However, if you click or focus inside the viewer, NVDA will temporarily stop
updating the text, so that you are able to easily select or copy the existing
content.

+To toggle the speech viewer from anywhere, please assign a custom gesture
using the [Input Gestures dialog #InputGestures].
+
++ Add-ons Manager ++
The Add-ons Manager, accessed by selecting Manage add-ons under Tools in the
NVDA menu, allows you to install and uninstall add-on packages for NVDA.
These packages are provided by the community and contain custom code that may
add or change features in NVDA or even provide support for extra Braille
displays or speech synthesizers.
@@ -1327,6 +1336,8 @@ In the past it has been possible to extend NVDA's
functionality by copying indiv
Although this version of NVDA may still load them, they will not be shown
in the Add-on Manager.
It is best to remove these files from your configuration and install the
appropriate add-on if one is available.

+To access the Add-ons Manager from anywhere, please assign a custom gesture
using the [Input Gestures dialog #InputGestures].
+
++ Python Console ++
The NVDA Python console, found under Tools in the NVDA menu, is a development
tool which is useful for debugging, general inspection of NVDA internals or
inspection of the accessibility hierarchy of an application.
For more information, please see the Developer Guide available from [the
Development section of the NVDA web site
http://community.nvda-project.org/wiki/Development].


https://bitbucket.org/nvdaaddonteam/nvda/commits/3c91f0dadcbe/
Changeset: 3c91f0dadcbe
Branch: None
User: jteh
Date: 2015-04-20 02:30:45+00:00
Summary: Refactor beep generation code to fix incorrect frequencies and
other issues.

Authors: Austin Hicks <camlorn38@xxxxxxxxx>, Davy Kager <mail@xxxxxxxxxxxx>

Affected #: 4 files

diff --git a/nvdaHelper/local/beeps.cpp b/nvdaHelper/local/beeps.cpp
index 5006194..c8b8772 100644
--- a/nvdaHelper/local/beeps.cpp
+++ b/nvdaHelper/local/beeps.cpp
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.
@@ -15,26 +15,23 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#define _USE_MATH_DEFINES
#include <cmath>
#include "beeps.h"
-using namespace std;

-const double PITWO=M_PI*2;
-const unsigned sampleRate=44100;
+const int sampleRate=44100;
const int amplitude=14000;

-unsigned generateBeep(short* buf, const float hz, const unsigned length, const
unsigned char left, const unsigned char right) {
- const unsigned samplesPerCycle=static_cast<unsigned int>(sampleRate/hz);
- unsigned totalSamples=static_cast<unsigned
int>((length/1000.0)/(1.0/sampleRate));
- totalSamples+=(samplesPerCycle-(totalSamples%samplesPerCycle));
+int generateBeep(short* buf, const float hz, const int length, const int left,
const int right) {
+ const int samplesPerCycle=static_cast<int>(sampleRate/hz);
+ int totalSamples=static_cast<int>((length/1000.0)/(1.0/sampleRate));
+ totalSamples+=samplesPerCycle-(totalSamples%samplesPerCycle);
if (!buf) { //just return buffer length
return totalSamples*4;
}
- const double sinFreq=PITWO/samplesPerCycle;
- for (unsigned sampleNum=0; sampleNum<totalSamples; ++sampleNum) {
- const short
sample=static_cast<short>(min(max(sin((sampleNum%sampleRate)*sinFreq)*2,-1),1)*amplitude);
- const short leftSample=static_cast<short>(sample*(left/100.0));
- const short
rightSample=static_cast<short>(sample*(right/100.0));
- buf[sampleNum*2]=leftSample;
- buf[sampleNum*2+1]=rightSample;
+ const double lpan=(left/100.0)*amplitude, rpan=(right/100.0)*amplitude;
+ const double sinFreq=(2.0*M_PI)/(sampleRate/hz); //DON'T use
samplesPerCycle here
+ for (int sampleNum=0; sampleNum<totalSamples; ++sampleNum) {
+ const double
sample=min(max(sin((sampleNum%sampleRate)*sinFreq)*2.0,-1.0),1.0);
+ buf[sampleNum*2]=static_cast<short>(sample*lpan);
+ buf[sampleNum*2+1]=static_cast<short>(sample*rpan);
}
return totalSamples*4;
-}
\ No newline at end of file
+}

diff --git a/nvdaHelper/local/beeps.h b/nvdaHelper/local/beeps.h
index 10f8ab2..5490fed 100644
--- a/nvdaHelper/local/beeps.h
+++ b/nvdaHelper/local/beeps.h
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.
@@ -17,6 +17,6 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

#include "nvdaHelperLocal.h"

-unsigned generateBeep(short* buf, const float hz, const unsigned length, const
unsigned char left=50, const unsigned char right = 50);
+int generateBeep(short* buf, const float hz, const int length, const int
left=50, const int right=50);

-#endif
\ No newline at end of file
+#endif

diff --git a/source/NVDAHelper.py b/source/NVDAHelper.py
index 90474fd..ed03d9f 100755
--- a/source/NVDAHelper.py
+++ b/source/NVDAHelper.py
@@ -439,8 +439,8 @@ def initialize():
raise e
localLib.nvdaHelperLocal_initialize()
generateBeep=localLib.generateBeep
- generateBeep.argtypes=[c_char_p,c_float,c_uint,c_ubyte,c_ubyte]
- generateBeep.restype=c_uint
+ generateBeep.argtypes=[c_char_p,c_float,c_int,c_int,c_int]
+ generateBeep.restype=c_int
# Handle VBuf_getTextInRange's BSTR out parameter so that the BSTR will
be freed automatically.
VBuf_getTextInRange = CFUNCTYPE(c_int, c_int, c_int, c_int,
POINTER(BSTR), c_int)(
("VBuf_getTextInRange", localLib),

diff --git a/source/tones.py b/source/tones.py
index 020067e..71ef883 100644
--- a/source/tones.py
+++ b/source/tones.py
@@ -29,7 +29,7 @@ def beep(hz,length,left=50,right=50):
@param left: volume of the left channel (0 to 100)
@type left: integer
@param right: volume of the right channel (0 to 100)
- @type right: float
+ @type right: integer
"""
log.io("Beep at pitch %s, for %s ms, left volume %s, right volume
%s"%(hz,length,left,right))
if not player:


https://bitbucket.org/nvdaaddonteam/nvda/commits/a05278ba3e08/
Changeset: a05278ba3e08
Branch: None
User: jteh
Date: 2015-04-20 02:33:22+00:00
Summary: Merge branch 't5023' into next

Incubates #5023.

Affected #: 4 files

diff --git a/nvdaHelper/local/beeps.cpp b/nvdaHelper/local/beeps.cpp
index 5006194..c8b8772 100644
--- a/nvdaHelper/local/beeps.cpp
+++ b/nvdaHelper/local/beeps.cpp
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.
@@ -15,26 +15,23 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#define _USE_MATH_DEFINES
#include <cmath>
#include "beeps.h"
-using namespace std;

-const double PITWO=M_PI*2;
-const unsigned sampleRate=44100;
+const int sampleRate=44100;
const int amplitude=14000;

-unsigned generateBeep(short* buf, const float hz, const unsigned length, const
unsigned char left, const unsigned char right) {
- const unsigned samplesPerCycle=static_cast<unsigned int>(sampleRate/hz);
- unsigned totalSamples=static_cast<unsigned
int>((length/1000.0)/(1.0/sampleRate));
- totalSamples+=(samplesPerCycle-(totalSamples%samplesPerCycle));
+int generateBeep(short* buf, const float hz, const int length, const int left,
const int right) {
+ const int samplesPerCycle=static_cast<int>(sampleRate/hz);
+ int totalSamples=static_cast<int>((length/1000.0)/(1.0/sampleRate));
+ totalSamples+=samplesPerCycle-(totalSamples%samplesPerCycle);
if (!buf) { //just return buffer length
return totalSamples*4;
}
- const double sinFreq=PITWO/samplesPerCycle;
- for (unsigned sampleNum=0; sampleNum<totalSamples; ++sampleNum) {
- const short
sample=static_cast<short>(min(max(sin((sampleNum%sampleRate)*sinFreq)*2,-1),1)*amplitude);
- const short leftSample=static_cast<short>(sample*(left/100.0));
- const short
rightSample=static_cast<short>(sample*(right/100.0));
- buf[sampleNum*2]=leftSample;
- buf[sampleNum*2+1]=rightSample;
+ const double lpan=(left/100.0)*amplitude, rpan=(right/100.0)*amplitude;
+ const double sinFreq=(2.0*M_PI)/(sampleRate/hz); //DON'T use
samplesPerCycle here
+ for (int sampleNum=0; sampleNum<totalSamples; ++sampleNum) {
+ const double
sample=min(max(sin((sampleNum%sampleRate)*sinFreq)*2.0,-1.0),1.0);
+ buf[sampleNum*2]=static_cast<short>(sample*lpan);
+ buf[sampleNum*2+1]=static_cast<short>(sample*rpan);
}
return totalSamples*4;
-}
\ No newline at end of file
+}

diff --git a/nvdaHelper/local/beeps.h b/nvdaHelper/local/beeps.h
index 10f8ab2..5490fed 100644
--- a/nvdaHelper/local/beeps.h
+++ b/nvdaHelper/local/beeps.h
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.
@@ -17,6 +17,6 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

#include "nvdaHelperLocal.h"

-unsigned generateBeep(short* buf, const float hz, const unsigned length, const
unsigned char left=50, const unsigned char right = 50);
+int generateBeep(short* buf, const float hz, const int length, const int
left=50, const int right=50);

-#endif
\ No newline at end of file
+#endif

diff --git a/source/NVDAHelper.py b/source/NVDAHelper.py
index aa31895..129aaaf 100755
--- a/source/NVDAHelper.py
+++ b/source/NVDAHelper.py
@@ -438,8 +438,8 @@ def initialize():
raise e
localLib.nvdaHelperLocal_initialize()
generateBeep=localLib.generateBeep
- generateBeep.argtypes=[c_char_p,c_float,c_uint,c_ubyte,c_ubyte]
- generateBeep.restype=c_uint
+ generateBeep.argtypes=[c_char_p,c_float,c_int,c_int,c_int]
+ generateBeep.restype=c_int
# Handle VBuf_getTextInRange's BSTR out parameter so that the BSTR will
be freed automatically.
VBuf_getTextInRange = CFUNCTYPE(c_int, c_int, c_int, c_int,
POINTER(BSTR), c_int)(
("VBuf_getTextInRange", localLib),

diff --git a/source/tones.py b/source/tones.py
index 020067e..71ef883 100644
--- a/source/tones.py
+++ b/source/tones.py
@@ -29,7 +29,7 @@ def beep(hz,length,left=50,right=50):
@param left: volume of the left channel (0 to 100)
@type left: integer
@param right: volume of the right channel (0 to 100)
- @type right: float
+ @type right: integer
"""
log.io("Beep at pitch %s, for %s ms, left volume %s, right volume
%s"%(hz,length,left,right))
if not player:


https://bitbucket.org/nvdaaddonteam/nvda/commits/3aff5eb8c4cb/
Changeset: 3aff5eb8c4cb
Branch: None
User: jteh
Date: 2015-04-20 06:39:58+00:00
Summary: Merge branch 'master' into next

Affected #: 1 file

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 7fab72d..bd19731 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -1,6 +1,6 @@
#NVDAObjects/excel.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2014 NVDA Contributors <http://www.nvaccess.org/>
+#Copyright (C) 2006-2015 NV Access Limited, Siddhartha Gupta
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -908,11 +908,14 @@ class ExcelCell(ExcelBase):
isWrapText = self.excelCellObject.WrapText
isShrinkToFit = self.excelCellObject.ShrinkToFit
isMerged = self.excelWindowObject.Selection.MergeCells
- adjacentCell = self.excelCellObject.Offset(0,1)
- if adjacentCell.Text:
- isAdjacentCellEmpty = False
- else:
+ try:
+ adjacentCell = self.excelCellObject.Offset(0,1)
+ except COMError:
+ # #5041: This cell is at the right edge.
+ # For our purposes, treat this as if there is an empty
cell to the right.
isAdjacentCellEmpty = True
+ else:
+ isAdjacentCellEmpty = not adjacentCell.Text
info = {}
if isMerged:
columnCountInMergeArea =
self.excelCellObject.MergeArea.Columns.Count


https://bitbucket.org/nvdaaddonteam/nvda/commits/33534ca96e8d/
Changeset: 33534ca96e8d
Branch: None
User: jteh
Date: 2015-04-23 04:13:32+00:00
Summary: Merge branch 'master' into next

Affected #: 33 files

diff --git a/contributors.txt b/contributors.txt
index c2256f0..cd59806 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -166,3 +166,4 @@ Tyler Spivey
Siddhartha Gupta
Siddharth
Aleksandr Lin'kov
+Davy Kager

diff --git a/source/locale/an/LC_MESSAGES/nvda.po
b/source/locale/an/LC_MESSAGES/nvda.po
index ea2e5bf..9022cd3 100644
--- a/source/locale/an/LC_MESSAGES/nvda.po
+++ b/source/locale/an/LC_MESSAGES/nvda.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: NVDA bzr main:5884\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-03 19:12+1000\n"
+"POT-Creation-Date: 2015-04-15 11:28-0700\n"
"PO-Revision-Date: \n"
"Last-Translator: Jorge Pérez Pérez <jorgtum@xxxxxxxxx>\n"
"Language-Team: Softaragonés\n"
@@ -135,6 +135,16 @@ msgstr "Persa grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Assamese grade 1"
+msgstr "Asamés grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Bengali grade 1"
+msgstr "Bengalí grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Bulgarian 8 dot computer braille"
msgstr "Braille Bulgaro computerizau de 8 puntos"

@@ -269,6 +279,11 @@ msgstr "Francés (unificau) Grau 2"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Gujarati grade 1"
+msgstr "Gujarati grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Greek (Greece) grade 1"
msgstr "Griego (Grecia) grau 1"

@@ -314,6 +329,11 @@ msgstr "Braille computerizau italián de 8 puntos"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kannada grade 1"
+msgstr "Canarés grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Korean grade 1"
msgstr "Coreán grau 1"

@@ -324,11 +344,31 @@ msgstr "Coreán grau 2"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Kashmiri grade 1"
+msgstr "Cachemir grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Latvian grade 1"
msgstr "Letón grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Malayalam grade 1"
+msgstr "Malayalam grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Manipuri grade 1"
+msgstr "Manipuri grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Marathi grade 1"
+msgstr "Maratí grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Dutch (Belgium) grade 1"
msgstr "Neerlandés (Belchica) grau 1"

@@ -364,6 +404,16 @@ msgstr "Noruego grau 3"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Nepali grade 1"
+msgstr "Nepalí grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Oriya grade 1"
+msgstr "Oriya grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Polish grade 1"
msgstr "Polaco grau 1"

@@ -384,6 +434,11 @@ msgstr "Portugués grau 2"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Punjabi grade 1"
+msgstr "Punjabí grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Russian braille for computer code"
msgstr "Braille ruso ta codigo d'ordinador"

@@ -394,6 +449,11 @@ msgstr "Ruso grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Sanskrit grade 1"
+msgstr "Sanscrito grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Swedish grade 1"
msgstr "Sueco grau 1"

@@ -419,6 +479,11 @@ msgstr "Tamil grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "Telegu grade 1"
+msgstr "Telegu grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Turkish grade 1"
msgstr "Turco grau 1"

@@ -634,9 +699,9 @@ msgstr "modo de navegación"
msgid "Not supported in this document"
msgstr "No ye suportau en iste documento"

-#. Translators: the description for the elements list dialog script on
virtualBuffers.
-msgid "Presents a list of links, headings or landmarks"
-msgstr "Presienta una lista de vinclos, capiters u zonas"
+#. Translators: the description for the Elements List command in browse mode.
+msgid "Lists various types of elements in this document"
+msgstr "Lista qualques menas de elementos en iste documento"

#. Translators: the description for the activatePosition script on
virtualBuffers.
msgid "activates the current object in the document"
@@ -1142,78 +1207,705 @@ msgstr "caracter"
msgid "unknown color"
msgstr "color desconoixida"

-#. Translators: The color black.
-msgid "black"
-msgstr "negra"
-
-#. Translators: The color dark green.
-msgid "dark green"
-msgstr "verda escura"
-
-#. Translators: The light gray color.
-msgid "light grey"
-msgstr "grisa floixa"
+#. Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Alice Blue"
+msgstr "azula Alicia"

-#. Translators: The color green (full brightness)
-msgid "green"
-msgstr "verda"
+#. Translators: the color Antique White (RGB 250, 235, 215) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Antique White"
+msgstr "blanca antiga"

-#. Translators: The color gray (halfway between white and black).
-msgid "grey"
-msgstr "grisa"
+#. Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Aqua"
+msgstr "augua"

-#. Translators: the color olive.
-#. For more info see: http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
-msgid "olive"
-msgstr "verda oliva"
-
-#. Translators: The color white.
-msgid "white"
-msgstr "blanca"
+#. Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Aquamarine"
+msgstr "auguamarina"

-#. Translators: The color yellow.
-msgid "yellow"
-msgstr "amariella"
+#. Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Azure"
+msgstr "azula celest"
+
+#. Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Beige"
+msgstr "beis"
+
+#. Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Bisque"
+msgstr "bisque"
+
+#. Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Black"
+msgstr "Negra"
+
+#. Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blanched Almond"
+msgstr "almendra blanquiada"
+
+#. Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blue"
+msgstr "Azula"
+
+#. Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blue Violet"
+msgstr "azula violeta"
+
+#. Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Brown"
+msgstr "marrona"
+
+#. Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Burly Wood"
+msgstr "Fusta firme"
+
+#. Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cadet Blue"
+msgstr "azula cadet"
+
+#. Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Chartreuse"
+msgstr "chartreuse"
+
+#. Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Chocolate"
+msgstr "Chicolate"
+
+#. Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Coral"
+msgstr "coral"
+
+#. Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cornflower Blue"
+msgstr "azula aciano"
+
+#. Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cornsilk"
+msgstr "seda de panizo"
+
+#. Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Crimson"
+msgstr "carmesí"
+
+#. Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cyan"
+msgstr "Cián"
+
+#. Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Blue"
+msgstr "azula escura"
+
+#. Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Cyan"
+msgstr "cian escura"
+
+#. Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Goldenrod"
+msgstr "barra d'oro escura"
+
+#. Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Gray"
+msgstr "Grisa escura"
+
+#. Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Green"
+msgstr "verda escura"

-#. Translators: The dark red color.
-msgid "dark red"
+#. Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Khaki"
+msgstr "caqui escura"
+
+#. Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Magenta"
+msgstr "machenta escura"
+
+#. Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Olive Green"
+msgstr "oliva verda escura"
+
+#. Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Orange"
+msgstr "Narancha escura"
+
+#. Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Orchid"
+msgstr "orquidia escura"
+
+#. Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Red"
msgstr "roya escura"

-#. Translators: The color navy blue (dark blue).
-#. For more info see http://en.wikipedia.org/wiki/Navy_blue
-msgid "navy blue"
-msgstr "azula marina"
-
-#. Translators: The color red.
-msgid "red"
-msgstr "roya"
-
-#. Translators: The color blue.
-msgid "blue"
-msgstr "azula"
-
-#. Translators: The color purple.
-msgid "purple"
-msgstr "morada"
-
-#. Translators: The color teal, which is a mix of green and blue, mostly green.
-#. For more info see http://en.wikipedia.org/wiki/Teal
-msgid "teal"
-msgstr "azula verdosa"
-
-#. Translators: The color fuchsia is a mix of blue and red.
-#. For more info see: http://en.wikipedia.org/wiki/Magenta
-msgid "fuchsia"
-msgstr "fuxia"
+#. Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Salmon"
+msgstr "salmón escura"
+
+#. Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Sea Green"
+msgstr "verda mar escura"
+
+#. Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Slate Blue"
+msgstr "azula pizarra escura"
+
+#. Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Slate Gray"
+msgstr "grisa pizarra escura"
+
+#. Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Turquoise"
+msgstr "turquesa escura"
+
+#. Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Violet"
+msgstr "violeta escura"
+
+#. Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Deep Pink"
+msgstr "rosa funda"
+
+#. Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Deep Sky Blue"
+msgstr "azula ciel funda"
+
+#. Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dim Gray"
+msgstr "grisa fosca"
+
+#. Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dodger Blue"
+msgstr "azula 'dodger '"
+
+#. Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Fire Brick"
+msgstr "ladriello de fuego"
+
+#. Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Floral White"
+msgstr "blanca de flors"
+
+#. Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Forest Green"
+msgstr "verda selva"
+
+#. Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Fuchsia"
+msgstr "fucsia"
+
+#. Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gainsboro"
+msgstr "gainsboro"
+
+#. Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Ghost White"
+msgstr "blanca totón"
+
+#. Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gold"
+msgstr "dorada"
+
+#. Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Goldenrod"
+msgstr "barra d'oro"
+
+#. Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gray"
+msgstr "Grisa"
+
+#. Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Green"
+msgstr "Verda"
+
+#. Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Green Yellow"
+msgstr "amariella verda"
+
+#. Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Honeydew"
+msgstr "verda melón"
+
+#. Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Hot Pink"
+msgstr "rosa calient"
+
+#. Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Indian Red"
+msgstr "roya indica"
+
+#. Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Indigo"
+msgstr "anyil"
+
+#. Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Ivory"
+msgstr "marfil"
+
+#. Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Khaki"
+msgstr "caqui"
+
+#. Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lavender"
+msgstr "espígol"
+
+#. Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lavender Blush"
+msgstr "espígol enroyau"
+
+#. Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lawn Green"
+msgstr "verda tasca"
+
+#. Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lemon Chiffon"
+msgstr "gasa de limón"
+
+#. Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Blue"
+msgstr "azula floixa"
+
+#. Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Coral"
+msgstr "coral floixa"
+
+#. Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Cyan"
+msgstr "cian floixa"
+
+#. Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Goldenrod Yellow"
+msgstr "barra d'oro amariella floixa"
+
+#. Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Green"
+msgstr "verda floixa"
+
+#. Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Grey"
+msgstr "grisa floixa"

-#. Translators: The aqua color is an equal amount of blue and green.
-#. For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
-msgid "aqua"
-msgstr "auguamarina"
+#. Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Pink"
+msgstr "rosa floixa"
+
+#. Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Salmon"
+msgstr "salmón floixa"
+
+#. Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Sea Green"
+msgstr "verda mar floixa"
+
+#. Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Sky Blue"
+msgstr "Azula ciel floixa"
+
+#. Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Slate Gray"
+msgstr "grisa pizarra floixa"
+
+#. Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Steel Blue"
+msgstr "azula acero floixa"
+
+#. Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Yellow"
+msgstr "amariella floixa"
+
+#. Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lime"
+msgstr "lima"
+
+#. Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lime Green"
+msgstr "verda lima"
+
+#. Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Linen"
+msgstr "lin"
+
+#. Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Magenta"
+msgstr "Machenta"
+
+#. Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Maroon"
+msgstr "marrona"
+
+#. Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Aquamarine"
+msgstr "auguamarina meya"
+
+#. Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Blue"
+msgstr "azula meya"
+
+#. Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Orchid"
+msgstr "orquidia meya"
+
+#. Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Purple"
+msgstr "purpura meya"
+
+#. Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Sea Green"
+msgstr "verda mar meya"
+
+#. Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Slate Blue"
+msgstr "azula pizarra meya"
+
+#. Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Spring Green"
+msgstr "verda primavera meya"
+
+#. Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Turquoise"
+msgstr "turquesa meya"
+
+#. Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Violet Red"
+msgstr "roya violeta meya"
+
+#. Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Midnight Blue"
+msgstr "azula meya nueit"
+
+#. Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Mint Cream"
+msgstr "crema de pipireta"
+
+#. Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Misty Rose"
+msgstr "rosa boirosa"
+
+#. Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Moccasin"
+msgstr "mocasín"
+
+#. Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Navajo White"
+msgstr "blanca navalla"
+
+#. Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Navy"
+msgstr "azula marina"

-#. Translators: This is the color orange.
-msgid "orange"
-msgstr "narancha"
+#. Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Old Lace"
+msgstr "encordadera viella"
+
+#. Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Olive"
+msgstr "oliva"
+
+#. Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Olive Drab"
+msgstr "grisa oliva"
+
+#. Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orange"
+msgstr "Narancha"
+
+#. Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orange Red"
+msgstr "narancha roya"
+
+#. Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orchid"
+msgstr "orquidia"
+
+#. Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Goldenrod"
+msgstr "barra d'oro esbufalida"
+
+#. Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Green"
+msgstr "verda esbufalida"
+
+#. Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Turquoise"
+msgstr "turquesa esbufalida"
+
+#. Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Violet Red"
+msgstr "roya violeta esbufalida"
+
+#. Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Papaya Whip"
+msgstr "batiu de papaya"
+
+#. Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Peach Puff"
+msgstr "soflo de cocón"
+
+#. Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Peru"
+msgstr "perú"
+
+#. Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pink"
+msgstr "Rosa"
+
+#. Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Plum"
+msgstr "Cirgüella"
+
+#. Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Powder Blue"
+msgstr "areniella azula"
+
+#. Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Purple"
+msgstr "purpura"
+
+#. Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Red"
+msgstr "Roya"
+
+#. Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Rosy Brown"
+msgstr "marrona rosa"
+
+#. Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Royal Blue"
+msgstr "azula reyal"
+
+#. Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Saddle Brown"
+msgstr "marrona siella"
+
+#. Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Salmon"
+msgstr "salmón"
+
+#. Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sandy Brown"
+msgstr "arena marrona"
+
+#. Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sea Green"
+msgstr "verda mar"
+
+#. Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Seashell"
+msgstr "casca"
+
+#. Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sienna"
+msgstr "siena"
+
+#. Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Silver"
+msgstr "platiada"
+
+#. Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sky Blue"
+msgstr "Azula ciel"
+
+#. Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Slate Blue"
+msgstr "azula pizarra"
+
+#. Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Slate Gray"
+msgstr "grisa pizarra"
+
+#. Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Snow"
+msgstr "nieu"
+
+#. Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Spring Green"
+msgstr "verda primavera"
+
+#. Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Steel Blue"
+msgstr "azula acero"
+
+#. Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Tan"
+msgstr "bronciada"
+
+#. Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Teal"
+msgstr "verda azulada"
+
+#. Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Thistle"
+msgstr "cardo"
+
+#. Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Tomato"
+msgstr "tomate"
+
+#. Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Turquoise"
+msgstr "turquesa"
+
+#. Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Violet"
+msgstr "violeta"
+
+#. Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Wheat"
+msgstr "panizo"
+
+#. Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "White"
+msgstr "Blanca"
+
+#. Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "White Smoke"
+msgstr "blanca fumo"
+
+#. Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Yellow"
+msgstr "Amariella"
+
+#. Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Yellow Green"
+msgstr "amariella verda"

#. Translators: This is spoken to indicate what has been selected. for example
'selected hello world'
#, python-format
@@ -1937,6 +2629,14 @@ msgstr "tien comentario"
msgid "obscured"
msgstr "enfoscau"

+#. Translators: a state that denotes that the object(text) is cropped as it
couldn't be accommodated in the allocated/available space
+msgid "cropped"
+msgstr "retallau"
+
+#. Translators: a state that denotes that the object(text) is overflowing into
the adjacent space
+msgid "overflowing"
+msgstr "esvolastriando"
+
#. Translators: This is presented when a selectable object (e.g. a list item)
is not selected.
msgid "not selected"
msgstr "no trigau"
@@ -5711,13 +6411,13 @@ msgstr "Anunciar o pape&r quan o churi dentre en
l'obchecto"

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "play audio coordinates when mouse moves"
-msgstr "reproducir son quan se mueva o churi"
+msgid "&Play audio coordinates when mouse moves"
+msgstr "re&producir as coordenadas d'audio en que se mueva o churi"

#. Translators: This is the label for a checkbox in the
#. mouse settings dialog.
-msgid "brightness controls audio coordinates volume"
-msgstr "o brilo controla o volumen d'as coordenadas d'o son"
+msgid "&Brightness controls audio coordinates volume"
+msgstr "o &brilo controla o volumen d'as coordenadas d'audio"

#. Translators: This is the label for the review cursor settings dialog.
msgid "Review Cursor Settings"
@@ -5910,8 +6610,8 @@ msgstr ""

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report font &name"
-msgstr "Anunciar o &nombre d'a fuent"
+msgid "Report &font name"
+msgstr "Anunciar o nombre d'a &fuent"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
@@ -5955,7 +6655,7 @@ msgstr "Anunciar as pa&chinas"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &line numbers"
+msgid "Report line &numbers"
msgstr "Anunciar os &numeros de linia"

#. Translators: This message is presented in the document formatting settings
dialogue
@@ -5986,7 +6686,7 @@ msgstr "Anunciar as c&oordenadas de celdas de tabla"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report &links"
+msgid "Report lin&ks"
msgstr "Anunciar os &vinclos"

#. Translators: This is the label for a checkbox in the
@@ -5996,7 +6696,7 @@ msgstr "Anunciar os &capiters"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
-msgid "Report l&ists"
+msgid "Report &lists"
msgstr "Anunciar as &listas"

#. Translators: This is the label for a checkbox in the
@@ -6150,8 +6850,10 @@ msgid "Symbol:"
msgstr "Simbolo:"

#. Translators: This is the label for the symbol pronunciation dialog.
-msgid "Symbol Pronunciation"
-msgstr "Pronuncia de simbolo"
+#. %s is replaced by the language for which symbol pronunciation is being
edited.
+#, python-format
+msgid "Symbol Pronunciation (%s)"
+msgstr "Pronuncia de simbolo (%s)"

#. Translators: The label for symbols list in symbol pronunciation dialog.
msgid "&Symbols"
@@ -6314,6 +7016,10 @@ msgstr ""
msgid "Taskbar"
msgstr "Barra de quefers"

+#. Translators: a color, broken down into its RGB red, green, blue parts.
+msgid "RGB red {rgb.red}, green {rgb.green}, blue {rgb.blue}"
+msgstr "RGB roya {rgb.red}, verda {rgb.green}, azula {rgb.blue}"
+
#, python-format
msgid "%s items"
msgstr "%s elementos"
@@ -6700,6 +7406,27 @@ msgstr "Serie d'a HIMS Braille Sense/Braille EDGE"
msgid "HIMS SyncBraille"
msgstr "HIMS SyncBraille"

+#~ msgid "Presents a list of links, headings or landmarks"
+#~ msgstr "Presienta una lista de vinclos, capiters u zonas"
+
+#~ msgid "grey"
+#~ msgstr "grisa"
+
+#~ msgid "navy blue"
+#~ msgstr "azula marina"
+
+#~ msgid "red"
+#~ msgstr "roya"
+
+#~ msgid "blue"
+#~ msgstr "azula"
+
+#~ msgid "teal"
+#~ msgstr "azula verdosa"
+
+#~ msgid "aqua"
+#~ msgstr "auguamarina"
+
#~ msgid ""
#~ "In NVDA 2013.1, the laptop keyboard layout has been completely redesigned "
#~ "in order to make it more intuitive and consistent.\n"

diff --git a/source/locale/ar/LC_MESSAGES/nvda.po
b/source/locale/ar/LC_MESSAGES/nvda.po
index 733e98a..b6e8690 100644
--- a/source/locale/ar/LC_MESSAGES/nvda.po
+++ b/source/locale/ar/LC_MESSAGES/nvda.po
@@ -4,8 +4,8 @@ msgid ""
msgstr ""
"Project-Id-Version: master-10703,53a09c4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-03-26 19:04-0700\n"
-"PO-Revision-Date: 2015-03-31 12:28+0200\n"
+"POT-Creation-Date: 2015-04-15 11:28-0700\n"
+"PO-Revision-Date: 2015-04-16 19:32+0200\n"
"Last-Translator: \n"
"Language-Team: AR <arabictranslationteam@xxxxxxxxxxxxxxxx>\n"
"Language: ar\n"
@@ -700,9 +700,9 @@ msgstr "بيئة التصفح"
msgid "Not supported in this document"
msgstr "غير مدعوم بهذا المستند"

-#. Translators: the description for the elements list dialog script on
virtualBuffers.
-msgid "Presents a list of links, headings or landmarks"
-msgstr "عرض قائمة بالروابط, ورؤوس الموضوعات أو علامار دليلية"
+#. Translators: the description for the Elements List command in browse mode.
+msgid "Lists various types of elements in this document"
+msgstr "سرد قائمة بالعناصر المختلفة الموجودة بالمستند"

#. Translators: the description for the activatePosition script on
virtualBuffers.
msgid "activates the current object in the document"
@@ -1208,79 +1208,715 @@ msgstr "حرف [ symbolLevel ]"
msgid "unknown color"
msgstr "لون غير معروف"

-#. Translators: The color black.
-msgid "black"
+#. Translators: the color Alice Blue (RGB 240, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Alice Blue"
+msgstr ""
+
+#. Translators: the color Antique White (RGB 250, 235, 215) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Antique White"
+msgstr ""
+
+#. Translators: the color Aqua (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Aqua"
+msgstr "فيروزي"
+
+#. Translators: the color Aquamarine (RGB 127, 255, 212) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Aquamarine"
+msgstr ""
+
+#. Translators: the color Azure (RGB 240, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Azure"
+msgstr "أزرق سماوي"
+
+#. Translators: the color Beige (RGB 245, 245, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Beige"
+msgstr "بايج"
+
+#. Translators: the color Bisque (RGB 255, 228, 196) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Bisque"
+msgstr ""
+
+#. Translators: the color Black (RGB 0, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Black"
msgstr "أسود"

-#. Translators: The color dark green.
-msgid "dark green"
+#. Translators: the color Blanched Almond (RGB 255, 235, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blanched Almond"
+msgstr ""
+
+#. Translators: the color Blue (RGB 0, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blue"
+msgstr "أزرق"
+
+#. Translators: the color Blue Violet (RGB 138, 43, 226) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Blue Violet"
+msgstr "بنفسجي مزرق"
+
+#. Translators: the color Brown (RGB 165, 42, 42) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Brown"
+msgstr "بني"
+
+#. Translators: the color Burly Wood (RGB 222, 184, 135) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Burly Wood"
+msgstr ""
+
+#. Translators: the color Cadet Blue (RGB 95, 158, 160) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cadet Blue"
+msgstr ""
+
+#. Translators: the color Chartreuse (RGB 127, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Chartreuse"
+msgstr ""
+
+#. Translators: the color Chocolate (RGB 210, 105, 30) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Chocolate"
+msgstr "لون الشيكولاتة"
+
+#. Translators: the color Coral (RGB 255, 127, 80) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Coral"
+msgstr "مرجان"
+
+#. Translators: the color Cornflower Blue (RGB 100, 149, 237) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cornflower Blue"
+msgstr ""
+
+#. Translators: the color Cornsilk (RGB 255, 248, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cornsilk"
+msgstr ""
+
+#. Translators: the color Crimson (RGB 220, 20, 60) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Crimson"
+msgstr ""
+
+#. Translators: the color Cyan (RGB 0, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Cyan"
+msgstr "سماوي"
+
+#. Translators: the color Dark Blue (RGB 0, 0, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Blue"
+msgstr "أزرق داكن"
+
+#. Translators: the color Dark Cyan (RGB 0, 139, 139) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Cyan"
+msgstr "سماوي داكن"
+
+#. Translators: the color Dark Goldenrod (RGB 184, 134, 11) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Goldenrod"
+msgstr ""
+
+#. Translators: the color Dark Gray (RGB 169, 169, 169) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Gray"
+msgstr "رماضي داكن"
+
+#. Translators: the color Dark Green (RGB 0, 100, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Green"
msgstr "أخضر داكن"

-#. Translators: The light gray color.
-msgid "light grey"
-msgstr "رماضي فاتح"
+#. Translators: the color Dark Khaki (RGB 189, 183, 107) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Khaki"
+msgstr ""

-#. Translators: The color green (full brightness)
-msgid "green"
-msgstr "أخضر"
+#. Translators: the color Dark Magenta (RGB 139, 0, 139) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Dark Magenta"
+msgstr "أخضر داكن"
+
+#. Translators: the color Dark Olive Green (RGB 85, 107, 47) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Dark Olive Green"
+msgstr "أخضر داكن"
+
+#. Translators: the color Dark Orange (RGB 255, 140, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Orange"
+msgstr "برتقالي داكن"
+
+#. Translators: the color Dark Orchid (RGB 153, 50, 204) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Dark Orchid"
+msgstr "أحمر داكن"
+
+#. Translators: the color Dark Red (RGB 139, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Red"
+msgstr "أحمر داكن"
+
+#. Translators: the color Dark Salmon (RGB 233, 150, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Salmon"
+msgstr ""
+
+#. Translators: the color Dark Sea Green (RGB 143, 188, 143) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Dark Sea Green"
+msgstr "أخضر داكن"
+
+#. Translators: the color Dark Slate Blue (RGB 72, 61, 139) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Slate Blue"
+msgstr ""
+
+#. Translators: the color Dark Slate Gray (RGB 47, 79, 79) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Slate Gray"
+msgstr ""
+
+#. Translators: the color Dark Turquoise (RGB 0, 206, 209) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Turquoise"
+msgstr "تركواز داكن"
+
+#. Translators: the color Dark Violet (RGB 148, 0, 211) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dark Violet"
+msgstr "بنفسجي داكن"
+
+#. Translators: the color Deep Pink (RGB 255, 20, 147) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Deep Pink"
+msgstr ""
+
+#. Translators: the color Deep Sky Blue (RGB 0, 191, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Deep Sky Blue"
+msgstr ""
+
+#. Translators: the color Dim Gray (RGB 105, 105, 105) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dim Gray"
+msgstr "رماضي معتم"
+
+#. Translators: the color Dodger Blue (RGB 30, 144, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Dodger Blue"
+msgstr ""
+
+#. Translators: the color Fire Brick (RGB 178, 34, 34) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Fire Brick"
+msgstr ""
+
+#. Translators: the color Floral White (RGB 255, 250, 240) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Floral White"
+msgstr ""
+
+#. Translators: the color Forest Green (RGB 34, 139, 34) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Forest Green"
+msgstr ""
+
+#. Translators: the color Fuchsia (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Fuchsia"
+msgstr "فوشيا"
+
+#. Translators: the color Gainsboro (RGB 220, 220, 220) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gainsboro"
+msgstr ""
+
+#. Translators: the color Ghost White (RGB 248, 248, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Ghost White"
+msgstr ""
+
+#. Translators: the color Gold (RGB 255, 215, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gold"
+msgstr "ذهب"

-#. Translators: The color gray (halfway between white and black).
-msgid "grey"
+#. Translators: the color Goldenrod (RGB 218, 165, 32) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Goldenrod"
+msgstr ""
+
+#. Translators: the color Gray (RGB 128, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Gray"
msgstr "رماضي"

-#. Translators: the color olive.
-#. For more info see: http://en.wikipedia.org/wiki/Olive_%28color%29#Olive
-msgid "olive"
-msgstr "زيتوني"
+#. Translators: the color Green (RGB 0, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Green"
+msgstr "أخضر"

-#. Translators: The color white.
-msgid "white"
-msgstr "أبيض"
+#. Translators: the color Green Yellow (RGB 173, 255, 47) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Green Yellow"
+msgstr "أصفر مخضر"

-#. Translators: The color yellow.
-msgid "yellow"
-msgstr "أصفر"
+#. Translators: the color Honeydew (RGB 240, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Honeydew"
+msgstr ""

-#. Translators: The dark red color.
-msgid "dark red"
-msgstr "أحمر داكن"
+#. Translators: the color Hot Pink (RGB 255, 105, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Hot Pink"
+msgstr "وردي ساخن"

-#. Translators: The color navy blue (dark blue).
-#. For more info see http://en.wikipedia.org/wiki/Navy_blue
-msgid "navy blue"
-msgstr "أزرق داكن"
+#. Translators: the color Indian Red (RGB 205, 92, 92) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Indian Red"
+msgstr "أحمر هندي"

-#. Translators: The color red.
-msgid "red"
-msgstr "أحمر"
+#. Translators: the color Indigo (RGB 75, 0, 130) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Indigo"
+msgstr ""

-#. Translators: The color blue.
-msgid "blue"
-msgstr "أزرق"
+#. Translators: the color Ivory (RGB 255, 255, 240) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Ivory"
+msgstr ""
+
+#. Translators: the color Khaki (RGB 240, 230, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Khaki"
+msgstr ""
+
+#. Translators: the color Lavender (RGB 230, 230, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lavender"
+msgstr ""
+
+#. Translators: the color Lavender Blush (RGB 255, 240, 245) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lavender Blush"
+msgstr ""
+
+#. Translators: the color Lawn Green (RGB 124, 252, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Lawn Green"
+msgstr "أخضر داكن"
+
+#. Translators: the color Lemon Chiffon (RGB 255, 250, 205) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lemon Chiffon"
+msgstr ""
+
+#. Translators: the color Light Blue (RGB 173, 216, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Blue"
+msgstr "أزرق فاتح"
+
+#. Translators: the color Light Coral (RGB 240, 128, 128) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Light Coral"
+msgstr "right alt"
+
+#. Translators: the color Light Cyan (RGB 224, 255, 255) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Cyan"
+msgstr "سماوي فاتح"
+
+#. Translators: the color Light Goldenrod Yellow (RGB 250, 250, 210) from CSS
color list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Goldenrod Yellow"
+msgstr ""
+
+#. Translators: the color Light Green (RGB 144, 238, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Green"
+msgstr "أخضر فاتح"
+
+#. Translators: the color Light Grey (RGB 211, 211, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Grey"
+msgstr "رماضي فاتح"
+
+#. Translators: the color Light Pink (RGB 255, 182, 193) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Pink"
+msgstr "وردي فاتح"
+
+#. Translators: the color Light Salmon (RGB 255, 160, 122) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Light Salmon"
+msgstr "right alt"
+
+#. Translators: the color Light Sea Green (RGB 32, 178, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Sea Green"
+msgstr ""
+
+#. Translators: the color Light Sky Blue (RGB 135, 206, 250) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Sky Blue"
+msgstr ""
+
+#. Translators: the color Light Slate Gray (RGB 119, 136, 153) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Slate Gray"
+msgstr ""

-#. Translators: The color purple.
-msgid "purple"
+#. Translators: the color Light Steel Blue (RGB 176, 196, 222) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Steel Blue"
+msgstr ""
+
+#. Translators: the color Light Yellow (RGB 255, 255, 224) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Light Yellow"
+msgstr "أصفر فاتح"
+
+#. Translators: the color Lime (RGB 0, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lime"
+msgstr "ليموني"
+
+#. Translators: the color Lime Green (RGB 50, 205, 50) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Lime Green"
+msgstr "أخضر ليموني"
+
+#. Translators: the color Linen (RGB 250, 240, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Linen"
+msgstr "كتاني"
+
+#. Translators: the color Magenta (RGB 255, 0, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Magenta"
msgstr "أرجواني"

-#. Translators: The color teal, which is a mix of green and blue, mostly green.
-#. For more info see http://en.wikipedia.org/wiki/Teal
-msgid "teal"
-msgstr "أخضر مائل إلى الزرقة"
+#. Translators: the color Maroon (RGB 128, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Maroon"
+msgstr "كستنائي"

-#. Translators: The color fuchsia is a mix of blue and red.
-#. For more info see: http://en.wikipedia.org/wiki/Magenta
-msgid "fuchsia"
-msgstr "فوشيا"
+#. Translators: the color Medium Aquamarine (RGB 102, 205, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Aquamarine"
+msgstr ""
+
+#. Translators: the color Medium Blue (RGB 0, 0, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Blue"
+msgstr ""
+
+#. Translators: the color Medium Orchid (RGB 186, 85, 211) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Orchid"
+msgstr ""
+
+#. Translators: the color Medium Purple (RGB 147, 112, 219) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Purple"
+msgstr ""
+
+#. Translators: the color Medium Sea Green (RGB 60, 179, 113) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Sea Green"
+msgstr ""
+
+#. Translators: the color Medium Slate Blue (RGB 123, 104, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Slate Blue"
+msgstr ""
+
+#. Translators: the color Medium Spring Green (RGB 0, 250, 154) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Spring Green"
+msgstr ""
+
+#. Translators: the color Medium Turquoise (RGB 72, 209, 204) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Turquoise"
+msgstr ""
+
+#. Translators: the color Medium Violet Red (RGB 199, 21, 133) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Medium Violet Red"
+msgstr ""
+
+#. Translators: the color Midnight Blue (RGB 25, 25, 112) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Midnight Blue"
+msgstr ""
+
+#. Translators: the color Mint Cream (RGB 245, 255, 250) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Mint Cream"
+msgstr ""
+
+#. Translators: the color Misty Rose (RGB 255, 228, 225) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Misty Rose"
+msgstr ""
+
+#. Translators: the color Moccasin (RGB 255, 228, 181) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Moccasin"
+msgstr ""
+
+#. Translators: the color Navajo White (RGB 255, 222, 173) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Navajo White"
+msgstr ""

-#. Translators: The aqua color is an equal amount of blue and green.
-#. For more info see: http://en.wikipedia.org/wiki/Aqua_%28color%29
-msgid "aqua"
-msgstr "أزرق مائل إلى الخضرة"
+#. Translators: the color Navy (RGB 0, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Navy"
+msgstr ""
+
+#. Translators: the color Old Lace (RGB 253, 245, 230) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Old Lace"
+msgstr ""
+
+#. Translators: the color Olive (RGB 128, 128, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Olive"
+msgstr "زيتوني"
+
+#. Translators: the color Olive Drab (RGB 107, 142, 35) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Olive Drab"
+msgstr ""

-#. Translators: This is the color orange.
-msgid "orange"
+#. Translators: the color Orange (RGB 255, 165, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orange"
msgstr "برتقالي"

+#. Translators: the color Orange Red (RGB 255, 69, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orange Red"
+msgstr "أحمر برتقالي"
+
+#. Translators: the color Orchid (RGB 218, 112, 214) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Orchid"
+msgstr ""
+
+#. Translators: the color Pale Goldenrod (RGB 238, 232, 170) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Goldenrod"
+msgstr ""
+
+#. Translators: the color Pale Green (RGB 152, 251, 152) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Green"
+msgstr "أخضر شاحب"
+
+#. Translators: the color Pale Turquoise (RGB 175, 238, 238) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Turquoise"
+msgstr "تركواز شاحب"
+
+#. Translators: the color Pale Violet Red (RGB 219, 112, 147) from CSS color
list at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pale Violet Red"
+msgstr ""
+
+#. Translators: the color Papaya Whip (RGB 255, 239, 213) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Papaya Whip"
+msgstr ""
+
+#. Translators: the color Peach Puff (RGB 255, 218, 185) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Peach Puff"
+msgstr ""
+
+#. Translators: the color Peru (RGB 205, 133, 63) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Peru"
+msgstr ""
+
+#. Translators: the color Pink (RGB 255, 192, 203) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Pink"
+msgstr "وردي"
+
+#. Translators: the color Plum (RGB 221, 160, 221) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Plum"
+msgstr ""
+
+#. Translators: the color Powder Blue (RGB 176, 224, 230) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Powder Blue"
+msgstr ""
+
+#. Translators: the color Purple (RGB 128, 0, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Purple"
+msgstr "أرجواني"
+
+#. Translators: the color Red (RGB 255, 0, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Red"
+msgstr "أحمر"
+
+#. Translators: the color Rosy Brown (RGB 188, 143, 143) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Rosy Brown"
+msgstr ""
+
+#. Translators: the color Royal Blue (RGB 65, 105, 225) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Royal Blue"
+msgstr ""
+
+#. Translators: the color Saddle Brown (RGB 139, 69, 19) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Saddle Brown"
+msgstr ""
+
+#. Translators: the color Salmon (RGB 250, 128, 114) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Salmon"
+msgstr ""
+
+#. Translators: the color Sandy Brown (RGB 244, 164, 96) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sandy Brown"
+msgstr ""
+
+#. Translators: the color Sea Green (RGB 46, 139, 87) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Sea Green"
+msgstr "أخضر داكن"
+
+#. Translators: the color Seashell (RGB 255, 245, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Seashell"
+msgstr ""
+
+#. Translators: the color Sienna (RGB 160, 82, 45) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sienna"
+msgstr ""
+
+#. Translators: the color Silver (RGB 192, 192, 192) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Silver"
+msgstr "فضي"
+
+#. Translators: the color Sky Blue (RGB 135, 206, 235) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Sky Blue"
+msgstr ""
+
+#. Translators: the color Slate Blue (RGB 106, 90, 205) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Slate Blue"
+msgstr ""
+
+#. Translators: the color Slate Gray (RGB 112, 128, 144) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Slate Gray"
+msgstr ""
+
+#. Translators: the color Snow (RGB 255, 250, 250) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Snow"
+msgstr "ثلجي"
+
+#. Translators: the color Spring Green (RGB 0, 255, 127) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+#, fuzzy
+msgctxt "color name"
+msgid "Spring Green"
+msgstr "print screen"
+
+#. Translators: the color Steel Blue (RGB 70, 130, 180) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Steel Blue"
+msgstr ""
+
+#. Translators: the color Tan (RGB 210, 180, 140) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Tan"
+msgstr "أسمر"
+
+#. Translators: the color Teal (RGB 0, 128, 128) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Teal"
+msgstr ""
+
+#. Translators: the color Thistle (RGB 216, 191, 216) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Thistle"
+msgstr ""
+
+#. Translators: the color Tomato (RGB 255, 99, 71) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Tomato"
+msgstr "طماطم"
+
+#. Translators: the color Turquoise (RGB 64, 224, 208) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Turquoise"
+msgstr "تركواز"
+
+#. Translators: the color Violet (RGB 238, 130, 238) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Violet"
+msgstr "بنفسجي"
+
+#. Translators: the color Wheat (RGB 245, 222, 179) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Wheat"
+msgstr ""
+
+#. Translators: the color White (RGB 255, 255, 255) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "White"
+msgstr "أبيض"
+
+#. Translators: the color White Smoke (RGB 245, 245, 245) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "White Smoke"
+msgstr ""
+
+#. Translators: the color Yellow (RGB 255, 255, 0) from CSS color list at
http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Yellow"
+msgstr "أصفر"
+
+#. Translators: the color Yellow Green (RGB 154, 205, 50) from CSS color list
at http://www.w3schools.com/cssref/css_colornames.asp
+msgctxt "color name"
+msgid "Yellow Green"
+msgstr "أخضر مصفر"
+
#. Translators: This is spoken to indicate what has been selected. for example
'selected hello world'
#, python-format
msgid "selected %s"
@@ -2003,6 +2639,14 @@ msgstr "يحتوي على تعليق"
msgid "obscured"
msgstr "محجوب"

+#. Translators: a state that denotes that the object(text) is cropped as it
couldn't be accommodated in the allocated/available space
+msgid "cropped"
+msgstr ""
+
+#. Translators: a state that denotes that the object(text) is overflowing into
the adjacent space
+msgid "overflowing"
+msgstr "متداخل"
+
#. Translators: This is presented when a selectable object (e.g. a list item)
is not selected.
msgid "not selected"
msgstr "غير محدد"
@@ -6058,8 +6702,10 @@ msgid "Symbol:"
msgstr "الرمز:"

#. Translators: This is the label for the symbol pronunciation dialog.
-msgid "Symbol Pronunciation"
-msgstr "نطق الرموز"
+#. %s is replaced by the language for which symbol pronunciation is being
edited.
+#, python-format
+msgid "Symbol Pronunciation (%s)"
+msgstr "نطق الرموز (%s)"

#. Translators: The label for symbols list in symbol pronunciation dialog.
msgid "&Symbols"
@@ -6216,6 +6862,10 @@ msgstr "المرور بنهاية الكائنات التي تحتوي على ع
msgid "Taskbar"
msgstr "شريط المهام"

+#. Translators: a color, broken down into its RGB red, green, blue parts.
+msgid "RGB red {rgb.red}, green {rgb.green}, blue {rgb.blue}"
+msgstr ""
+
#, python-format
msgid "%s items"
msgstr "%s عناصر"
@@ -6580,6 +7230,27 @@ msgstr "HIMS Braille Sense/Braille EDGE series"
msgid "HIMS SyncBraille"
msgstr "HIMS SyncBraille"

+#~ msgid "Presents a list of links, headings or landmarks"
+#~ msgstr "عرض قائمة بالروابط, ورؤوس الموضوعات أو علامار دليلية"
+
+#~ msgid "grey"
+#~ msgstr "رماضي"
+
+#~ msgid "navy blue"
+#~ msgstr "أزرق داكن"
+
+#~ msgid "red"
+#~ msgstr "أحمر"
+
+#~ msgid "blue"
+#~ msgstr "أزرق"
+
+#~ msgid "teal"
+#~ msgstr "أخضر مائل إلى الزرقة"
+
+#~ msgid "aqua"
+#~ msgstr "أزرق مائل إلى الخضرة"
+
#~ msgid ""
#~ "In NVDA 2013.1, the laptop keyboard layout has been completely redesigned
in "
#~ "order to make it more intuitive and consistent.\n"

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/99db423df411/
Changeset: 99db423df411
Branch: None
User: mdcurran
Date: 2015-04-27 05:05:41+00:00
Summary: MSHTML virtualBuffer: quick nav to graphics should find nodes with
an ARIA role of img, not just a tag of img.

Affected #: 1 file

diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py
index 87f4c7c..e7e4511 100644
--- a/source/virtualBuffers/MSHTML.py
+++ b/source/virtualBuffers/MSHTML.py
@@ -252,7 +252,7 @@ class MSHTML(VirtualBuffer):
elif nodeType == "blockQuote":
attrs = {"IHTMLDOMNode::nodeName": ["BLOCKQUOTE"]}
elif nodeType == "graphic":
- attrs = {"IHTMLDOMNode::nodeName": ["IMG"]}
+ attrs = [{"IHTMLDOMNode::nodeName":
["IMG"]},{"HTMLAttrib::role":["img"]}]
elif nodeType == "frame":
attrs = {"IHTMLDOMNode::nodeName": ["FRAME","IFRAME"]}
elif nodeType=="focusable":


https://bitbucket.org/nvdaaddonteam/nvda/commits/4da9b2e03e56/
Changeset: 4da9b2e03e56
Branch: None
User: mdcurran
Date: 2015-04-27 05:06:57+00:00
Summary: Merge branch 't5062' into next. Incubates #5062

Affected #: 1 file

diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py
index 87f4c7c..e7e4511 100644
--- a/source/virtualBuffers/MSHTML.py
+++ b/source/virtualBuffers/MSHTML.py
@@ -252,7 +252,7 @@ class MSHTML(VirtualBuffer):
elif nodeType == "blockQuote":
attrs = {"IHTMLDOMNode::nodeName": ["BLOCKQUOTE"]}
elif nodeType == "graphic":
- attrs = {"IHTMLDOMNode::nodeName": ["IMG"]}
+ attrs = [{"IHTMLDOMNode::nodeName":
["IMG"]},{"HTMLAttrib::role":["img"]}]
elif nodeType == "frame":
attrs = {"IHTMLDOMNode::nodeName": ["FRAME","IFRAME"]}
elif nodeType=="focusable":


https://bitbucket.org/nvdaaddonteam/nvda/commits/462ae85f4e7a/
Changeset: 462ae85f4e7a
Branch: None
User: mdcurran
Date: 2015-04-28 02:08:21+00:00
Summary: Merge branch 't4838' into next

Affected #: 1 file

diff --git a/source/appModules/powerpnt.py b/source/appModules/powerpnt.py
index c75a1f8..182a4fa 100644
--- a/source/appModules/powerpnt.py
+++ b/source/appModules/powerpnt.py
@@ -18,7 +18,7 @@ import speech
import sayAllHandler
import NVDAHelper
import winUser
-from treeInterceptorHandler import TreeInterceptor
+from treeInterceptorHandler import DocumentTreeInterceptor
from NVDAObjects import NVDAObjectTextInfo
from displayModel import DisplayModelTextInfo, EditableTextDisplayModelTextInfo
import textInfos.offsets
@@ -992,7 +992,7 @@ class SlideShowTreeInterceptorTextInfo(NVDAObjectTextInfo):
except:
raise LookupError("Couldn't get MathML from MathType")

-class SlideShowTreeInterceptor(TreeInterceptor):
+class SlideShowTreeInterceptor(DocumentTreeInterceptor):
"""A TreeInterceptor for showing Slide show content. Has no caret
navigation, a CursorManager must be used on top. """

def _get_isAlive(self):


https://bitbucket.org/nvdaaddonteam/nvda/commits/051c11f111aa/
Changeset: 051c11f111aa
Branch: None
User: mdcurran
Date: 2015-04-29 05:37:58+00:00
Summary: Merge branch 't4174' into next. Incubates #4174

Affected #: 3 files

diff --git a/source/NVDAObjects/UIA/__init__.py
b/source/NVDAObjects/UIA/__init__.py
index 4c57ae2..68a12dd 100644
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -122,13 +122,15 @@ class UIATextInfo(textInfos.TextInfo):
def _iterUIARangeByUnit(self,rangeObj,unit):
tempRange=rangeObj.clone()

tempRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,rangeObj,UIAHandler.TextPatternRangeEndpoint_Start)
- while
tempRange.MoveEndpointByUnit(UIAHandler.TextPatternRangeEndpoint_End,unit,1)>0:
+ endRange=tempRange.Clone()
+ while endRange.Move(unit,1)>0:
+
tempRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,endRange,UIAHandler.TextPatternRangeEndpoint_Start)

pastEnd=tempRange.CompareEndpoints(UIAHandler.TextPatternRangeEndpoint_End,rangeObj,UIAHandler.TextPatternRangeEndpoint_End)>0
if pastEnd:

tempRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,rangeObj,UIAHandler.TextPatternRangeEndpoint_End)
yield tempRange.clone()
if pastEnd:
- break
+ return

tempRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_Start,tempRange,UIAHandler.TextPatternRangeEndpoint_End)
# Ensure that we always reach the end of the outer range, even
if the units seem to stop somewhere inside
if
tempRange.CompareEndpoints(UIAHandler.TextPatternRangeEndpoint_End,rangeObj,UIAHandler.TextPatternRangeEndpoint_End)<0:
@@ -149,6 +151,8 @@ class UIATextInfo(textInfos.TextInfo):
elif
annotationTypes==UIAHandler.handler.ReservedMixedAttributeValue:
for r in
self._iterUIARangeByUnit(tempRange,UIAHandler.TextUnit_Word):
text=r.GetText(-1)
+ if not text:
+ continue

r.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,r,UIAHandler.TextPatternRangeEndpoint_Start)

r.ExpandToEnclosingUnit(UIAHandler.TextUnit_Character)
try:

diff --git a/source/appModules/powerpnt.py b/source/appModules/powerpnt.py
index 182a4fa..317ce2d 100644
--- a/source/appModules/powerpnt.py
+++ b/source/appModules/powerpnt.py
@@ -1039,6 +1039,9 @@ class SlideShowTreeInterceptor(DocumentTreeInterceptor):
gesture.send()
self.rootNVDAObject.handleSlideChange()

+class
ReviewableSlideshowTreeInterceptor(ReviewCursorManager,SlideShowTreeInterceptor):
+ """A TreeInterceptor for Slide show content but with caret navigation
via ReviewCursorManager."""
+
__gestures={
"kb:space":"slideChange",
"kb:enter":"slideChange",
@@ -1048,10 +1051,6 @@ class SlideShowTreeInterceptor(DocumentTreeInterceptor):
"kb:control+shift+s":"toggleNotesMode",
}

-class
ReviewableSlideshowTreeInterceptor(ReviewCursorManager,SlideShowTreeInterceptor):
- """A TreeInterceptor for Slide show content but with caret navigation
via ReivewCursorManager."""
- pass
-
class SlideShowWindow(PaneClassDC):

_lastSlideChangeID=None

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 3b014db..b97d57b 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -21,9 +21,10 @@
== Bug Fixes ==
- Character descriptions are now handled correctly for conjunct characters in
certain Indian languages. (#4582)
- If the "Trust voice's language when processing characters and symbols"
option is enabled, the Punctuation/Symbol pronunciation dialog now correctly
uses the voice language. Also, the language for which pronunciation is being
edited is shown in the dialog's title. (#4930)
--In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)
+- In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)
- When selecting colors in Microsoft Office applications, color names are now
reported. (#3045)
- Danish braille output now works again. (#4986)
+- pageUp / pageDown can now be used again to change slides within a PowerPoint
slide show. (#4850)


== Changes for Developers ==


https://bitbucket.org/nvdaaddonteam/nvda/commits/8bc3096a29e8/
Changeset: 8bc3096a29e8
Branch: None
User: mdcurran
Date: 2015-04-29 06:17:40+00:00
Summary: Merge branch 'master' into next

Conflicts:
source/NVDAObjects/window/excel.py

Affected #: 3 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index bd19731..41f7003 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -1,6 +1,6 @@
#NVDAObjects/excel.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2015 NV Access Limited, Siddhartha Gupta
+#Copyright (C) 2006-2015 NV Access Limited, Dinesh Kaushal, Siddhartha Gupta
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -27,9 +27,9 @@ import controlTypes
from . import Window
from .. import NVDAObjectTextInfo
import scriptHandler
-import ctypes
import browseMode
-
+import ctypes
+
xlCenter=-4108
xlJustify=-4130
xlLeft=-4131

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index b97d57b..2733f03 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -9,6 +9,8 @@
- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
- New braille translation tables for several Indian languages. (#4778)
- In Microsoft Excel, NVDA now reports when a cell has overflowing or cropped
content. (#3040)
+- An elements list for Microsoft Excel (NVDA+f7), to allow listing of charts,
comments and formulas. (#1987)
+- Support for reading charts in Microsoft Excel: Select the chart using the
Elements List (NVDA+f7) and then use the arrow keys to move to all the data
points. (#1987)


== Changes ==

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 8a65911..fa29318 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -580,7 +580,7 @@ NVDA provides its own extra commands for some applications
to make certain tasks
| Set column headers | NVDA+shift+c | Pressing this once tells NVDA this is
the first header cell in the row that contains column headers, which should be
automatically announced when moving between columns below this row. Pressing
twice will clear the setting. |
| Set row headers | NVDA+shift+r | Pressing this once tells NVDA this is the
first header cell in the column that contains row headers, which should be
automatically announced when moving between rows after this column. Pressing
twice will clear the setting. |
| Report comment | NVDA+alt+c | Reports the comment on the current cell if
any. |
-| Cell List dialog | NVDA+f7 | opens the Cell List dialog showing cells with
comments or formulas. Cells can be also grouped by region. |
+| Elements List dialog | NVDA+f7 | opens the Elements List dialog showing
charts, cells with comments, or cells with formulas. |
%kc:endInclude

++ Microsoft PowerPoint ++


https://bitbucket.org/nvdaaddonteam/nvda/commits/8ef743c1eb7a/
Changeset: 8ef743c1eb7a
Branch: None
User: mdcurran
Date: 2015-04-30 00:44:07+00:00
Summary: Merge branch 't5021' into next. Incubates #5021

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index a797442..ccdc627 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -94,6 +94,7 @@ nodeNamesToNVDARoles={
"A":controlTypes.ROLE_LINK,
"LABEL":controlTypes.ROLE_LABEL,
"#text":controlTypes.ROLE_STATICTEXT,
+ "#TEXT":controlTypes.ROLE_STATICTEXT,
"H1":controlTypes.ROLE_HEADING,
"H2":controlTypes.ROLE_HEADING,
"H3":controlTypes.ROLE_HEADING,
@@ -120,6 +121,9 @@ nodeNamesToNVDARoles={
"OPTION":controlTypes.ROLE_LISTITEM,
"BLOCKQUOTE":controlTypes.ROLE_BLOCKQUOTE,
"MATH":controlTypes.ROLE_MATH,
+ "NAV":controlTypes.ROLE_SECTION,
+ "SECTION":controlTypes.ROLE_SECTION,
+ "ARTICLE":controlTypes.ROLE_DOCUMENT,
}

def getZoomFactorsFromHTMLDocument(HTMLDocument):
@@ -703,8 +707,8 @@ class MSHTML(IAccessible):
if nodeName:
if nodeName in ("OBJECT","EMBED","APPLET"):
return controlTypes.ROLE_EMBEDDEDOBJECT
- if self.HTMLNodeHasAncestorIAccessible or
nodeName in ("BODY","FRAMESET","FRAME","IFRAME","LABEL"):
- return
nodeNamesToNVDARoles.get(nodeName,controlTypes.ROLE_TEXTFRAME)
+ if self.HTMLNodeHasAncestorIAccessible or
nodeName in
("BODY","FRAMESET","FRAME","IFRAME","LABEL","NAV","SECTION","ARTICLE"):
+ return
nodeNamesToNVDARoles.get(nodeName,controlTypes.ROLE_SECTION)
if self.IAccessibleChildID>0:
states=super(MSHTML,self).states
if controlTypes.STATE_LINKED in states:
@@ -929,7 +933,10 @@ class MSHTML(IAccessible):

def _get_HTMLNodeUniqueNumber(self):
if not hasattr(self,'_HTMLNodeUniqueNumber'):
- self._HTMLNodeUniqueNumber=self.HTMLNode.uniqueNumber
+ try:
+
self._HTMLNodeUniqueNumber=self.HTMLNode.uniqueNumber
+ except COMError:
+ return None
return self._HTMLNodeUniqueNumber

def _get_HTMLNodeName(self):


https://bitbucket.org/nvdaaddonteam/nvda/commits/81411a75b9e2/
Changeset: 81411a75b9e2
Branch: None
User: mdcurran
Date: 2015-04-30 01:59:33+00:00
Summary: Merge branch 't5025' into next. Incubates #5025

Affected #: 1 file

diff --git a/source/NVDAObjects/IAccessible/MSHTML.py
b/source/NVDAObjects/IAccessible/MSHTML.py
index ccdc627..9bef899 100644
--- a/source/NVDAObjects/IAccessible/MSHTML.py
+++ b/source/NVDAObjects/IAccessible/MSHTML.py
@@ -640,7 +640,7 @@ class MSHTML(IAccessible):
if (
self.HTMLNodeHasAncestorIAccessible or
#IE inappropriately generates the name from descendants
on some controls
- self.IAccessibleRole in
(oleacc.ROLE_SYSTEM_MENUBAR,oleacc.ROLE_SYSTEM_TOOLBAR,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_TABLE,oleacc.ROLE_SYSTEM_DOCUMENT)
or
+ self.IAccessibleRole in
(oleacc.ROLE_SYSTEM_MENUBAR,oleacc.ROLE_SYSTEM_TOOLBAR,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_TABLE,oleacc.ROLE_SYSTEM_DOCUMENT,oleacc.ROLE_SYSTEM_DIALOG)
or
#Adding an ARIA landmark or unknown role to a DIV or
NAV node makes an IAccessible with role_system_grouping and a name calculated
from descendants.
# This name should also be ignored, but check NVDA's
role, not accRole as its possible that NVDA chose a better role
# E.g. row (#2780)


https://bitbucket.org/nvdaaddonteam/nvda/commits/3f73d94efeff/
Changeset: 3f73d94efeff
Branch: None
User: mdcurran
Date: 2015-04-30 04:57:12+00:00
Summary: Merge branch 't3805' into next. Incubates #3805

Affected #: 1 file

diff --git a/source/locale/en/symbols.dic b/source/locale/en/symbols.dic
index 2707d4c..24be9a7 100644
--- a/source/locale/en/symbols.dic
+++ b/source/locale/en/symbols.dic
@@ -115,3 +115,49 @@ _ line most
→ right arrow some
✓ check some
✔ check some
+#Mathematical Operators U+2200 to U+220F
+
+∀ For All none
+∁ Complement none
+∂ Partial Derivative none
+∃ There exists none
+∄ There Does Not Exist none
+∅ EMPTY SET none
+∆ INCREMENT none
+∇ NABLA none
+∈ ELEMENT OF none
+∉ NOT AN ELEMENT OF none
+∊ SMALL ELEMENT OF none
+∋ CONTAINS AS MEMBER none
+∌ DOES NOT CONTAIN AS MEMBER none
+∍ SMALL CONTAINS AS MEMBER none
+∎ END OF PROOF none
+∏ N-ARY PRODUCT none
+
+# Miscellaneous Mathematical Operators
+
+∑ N-ARY SUMMATION none
+√ SQUARE ROOT none
+∛ CUBE ROOT none
+∜ FOURTH ROOT none
+∝ PROPORTIONAL TO none
+∞ INFINITY none
+∟ RIGHT ANGLE none
+∠ ANGLE none
+∥ PARALLEL TO none
+∦ NOT PARALLEL TO none
+∧ LOGICAL AND none
+∨ LOGICAL OR none
+∩ INTERSECTION none
+∪ UNION none
+∫ INTEGRAL none
+∴ THEREFORE none
+∵ BECAUSE none
+∶ RATIO none
+∷ PROPORTION none
+≤ LESS-THAN OR EQUAL TO none
+≥ GREATER-THAN OR EQUAL TO none
+⊂ SUBSET OF none
+⊃ SUPERSET OF none
+⊆ SUBSET OF OR EQUAL TO none
+⊇ SUPERSET OF OR EQUAL TO none


https://bitbucket.org/nvdaaddonteam/nvda/commits/1ad91ad5a83b/
Changeset: 1ad91ad5a83b
Branch: None
User: jteh
Date: 2015-05-01 11:59:47+00:00
Summary: Merge branch 'master' into next

Affected #: 4 files

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index e8a3adc..b017901 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.

diff --git a/nvdaHelper/vbufBackends/mshtml/node.h
b/nvdaHelper/vbufBackends/mshtml/node.h
index 0d9a8e3..7350066 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.h
+++ b/nvdaHelper/vbufBackends/mshtml/node.h
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
-Copyright 2006-2010 NVDA contributers.
+Copyright 2006-2015 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as
published by
the Free Software Foundation.

diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py
index edc5ce2..71c2106 100644
--- a/source/gui/settingsDialogs.py
+++ b/source/gui/settingsDialogs.py
@@ -1718,6 +1718,8 @@ class InputGesturesDialog(SettingsDialog):
def populateTree(self, filter=''):
if filter:
#This regexp uses a positive lookahead (?=...) for
every word in the filter, which just makes sure the word is present in the
string to be tested without matching position or order.
+ # #5060: Escape the filter text to prevent unexpected
matches and regexp errors.
+ filter = re.escape(filter)
filterReg = re.compile(r'(?=.*?' +
r')(?=.*?'.join(filter.split(' ')) + r')', re.U|re.IGNORECASE)
for category in sorted(self.gestures):
treeCat = self.tree.AppendItem(self.treeRoot, category)

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 2733f03..afcaa3b 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -4,13 +4,15 @@
%!includeconf: ../changes.t2tconf

= 2015.2 =
+Highlights of this release include the ability to read charts in Microsoft
Excel and support for reading and interactive navigation of mathematical
content.

== New Features ==
-- moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
+- Moving forward and backward by sentence in Microsoft Word is now possible
with alt+downArrow and alt+upArrow respectively. (#3288)
- New braille translation tables for several Indian languages. (#4778)
- In Microsoft Excel, NVDA now reports when a cell has overflowing or cropped
content. (#3040)
-- An elements list for Microsoft Excel (NVDA+f7), to allow listing of charts,
comments and formulas. (#1987)
-- Support for reading charts in Microsoft Excel: Select the chart using the
Elements List (NVDA+f7) and then use the arrow keys to move to all the data
points. (#1987)
+- In Microsoft Excel, you can now use the Elements List (NVDA+f7) to allow
listing of charts, comments and formulas. (#1987)
+- Support for reading charts in Microsoft Excel. To use this, select the chart
using the Elements List (NVDA+f7) and then use the arrow keys to move between
the data points. (#1987)
+- Using MathPlayer 4 from Design Science, NVDA can now read and interactively
navigate mathematical content in web browsers and in Microsoft Word and
PowerPoint. See the "Reading Mathematical Content" section in the User Guide
for details. (#4673)


== Changes ==
@@ -26,12 +28,17 @@
- In Internet Explorer and other MSHTML controls, typed characters are no
longer inappropriately announced in editable combo boxes such as the Google
search field on the Google home page. (#4976)
- When selecting colors in Microsoft Office applications, color names are now
reported. (#3045)
- Danish braille output now works again. (#4986)
-- pageUp / pageDown can now be used again to change slides within a PowerPoint
slide show. (#4850)
+- PageUp/pageDown can again be used to change slides within a PowerPoint slide
show. (#4850)
+- In Skype for Desktop 7.2 and later, typing notifications are now reported
and problems immediately after moving focus out of a conversation have been
fixed. (#4972)
+- Fixed problems when typing certain punctuation/symbols such as brackets into
the filter field in the Input Gestures dialog. (#5060)


== Changes for Developers ==
-- brailleInput.handler.sendChars(mychar) will no longer filter out a character
if it is equal to the previous character, by ensuring that the key sent is
correctly released.
-- scripts for changing touch modes will now honor new labeles added to
touchHandler.touchModeLabels. (#4699)
+- brailleInput.handler.sendChars(mychar) will no longer filter out a character
if it is equal to the previous character by ensuring that the key sent is
correctly released. (#4139)
+- Scripts for changing touch modes will now honor new labeles added to
touchHandler.touchModeLabels. (#4699)
+- Add-ons can provide their own math presentation implementations. See the
mathPres package for details. (#4509)
+- Speech commands have been implemented to insert a break between words and to
change the pitch, volume and rate. See BreakCommand, PitchCommand,
VolumeCommand and RateCommand in the speech module. (#4674)
+ - There is also speech.PhonemeCommand to insert specific pronunciation, but
the current implementations only support a very limited number of phonemes.


= 2015.1 =


https://bitbucket.org/nvdaaddonteam/nvda/commits/24e5fd60bff0/
Changeset: 24e5fd60bff0
Branch: None
User: jteh
Date: 2015-05-01 12:19:36+00:00
Summary: Merge branch 'master' into next

Affected #: 2 files

diff --git a/source/NVDAObjects/window/excel.py
b/source/NVDAObjects/window/excel.py
index 41f7003..458a08f 100755
--- a/source/NVDAObjects/window/excel.py
+++ b/source/NVDAObjects/window/excel.py
@@ -284,8 +284,8 @@ class
ExcelBrowseModeTreeInterceptor(browseMode.BrowseModeTreeInterceptor):

def script_elementsList(self,gesture):

super(ExcelBrowseModeTreeInterceptor,self).script_elementsList(gesture)
- # Translators: the description for the elements list dialog script on
virtualBuffers.
- script_elementsList.__doc__ = _("Presents a list of links, headings or
landmarks")
+ # Translators: the description for the elements list command in
Microsoft Excel.
+ script_elementsList.__doc__ = _("Presents a list of charts, cells with
comments and cells with formulas")
script_elementsList.ignoreTreeInterceptorPassThrough=True

class ElementsListDialog(browseMode.ElementsListDialog):

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index afcaa3b..291ab6d 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -13,6 +13,7 @@ Highlights of this release include the ability to read charts
in Microsoft Excel
- In Microsoft Excel, you can now use the Elements List (NVDA+f7) to allow
listing of charts, comments and formulas. (#1987)
- Support for reading charts in Microsoft Excel. To use this, select the chart
using the Elements List (NVDA+f7) and then use the arrow keys to move between
the data points. (#1987)
- Using MathPlayer 4 from Design Science, NVDA can now read and interactively
navigate mathematical content in web browsers and in Microsoft Word and
PowerPoint. See the "Reading Mathematical Content" section in the User Guide
for details. (#4673)
+- It is now possible to assign input gestures (keyboard commands, touch
gestures, etc.) for all NVDA preferences dialogs and document formatting
options using the Input Gestures dialog. (#4898)


== Changes ==


https://bitbucket.org/nvdaaddonteam/nvda/commits/921175c32224/
Changeset: 921175c32224
Branch: None
User: mdcurran
Date: 2015-05-07 02:33:33+00:00
Summary: English symbols: move several more symbols from most to some
including #<>±×÷ and always preserve ()– to ensure synths pause/inflect
properly for these characters if supported. Re

Affected #: 1 file

diff --git a/source/locale/en/symbols.dic b/source/locale/en/symbols.dic
index 2707d4c..faeadb8 100644
--- a/source/locale/en/symbols.dic
+++ b/source/locale/en/symbols.dic
@@ -42,7 +42,7 @@ negative number minus none norep
# Standard punctuation/symbols
! bang all
" quote most
-\# number most
+\# number some
$ dollar all norep
£ pound all norep
€ euro all norep
@@ -51,8 +51,8 @@ $ dollar all norep
% percent some
& and some
' tick all
-( left paren most
-) right paren most
+( left paren most always
+) right paren most always
* star some
+ plus some
, comma all always
@@ -61,8 +61,8 @@ $ dollar all norep
/ slash some
: colon most norep
; semi most
-< less most
-> greater most
+< less some
+> greater some
= equals some
? question all
@ at some
@@ -86,7 +86,7 @@ _ line most
” right quote most
‘ left tick most
’ right tick most
-– en dash most
+– en dash most always
— em dash most
● circle most
¨ diaeresis most
@@ -108,9 +108,9 @@ _ line most
® registered some
™ Trademark some
© Copyright some
-± Plus or Minus most
-× times most
-÷ divide by most
+± Plus or Minus some
+× times some
+÷ divide by some
← left arrow some
→ right arrow some
✓ check some


https://bitbucket.org/nvdaaddonteam/nvda/commits/c5841029a6db/
Changeset: c5841029a6db
Branch: None
User: mdcurran
Date: 2015-05-07 02:37:57+00:00
Summary: Merge branch 't3799' into next. Incubates #3799

Affected #: 1 file

diff --git a/source/locale/en/symbols.dic b/source/locale/en/symbols.dic
index 24be9a7..a7e542e 100644
--- a/source/locale/en/symbols.dic
+++ b/source/locale/en/symbols.dic
@@ -42,7 +42,7 @@ negative number minus none norep
# Standard punctuation/symbols
! bang all
" quote most
-\# number most
+\# number some
$ dollar all norep
£ pound all norep
€ euro all norep
@@ -51,8 +51,8 @@ $ dollar all norep
% percent some
& and some
' tick all
-( left paren most
-) right paren most
+( left paren most always
+) right paren most always
* star some
+ plus some
, comma all always
@@ -61,8 +61,8 @@ $ dollar all norep
/ slash some
: colon most norep
; semi most
-< less most
-> greater most
+< less some
+> greater some
= equals some
? question all
@ at some
@@ -86,7 +86,7 @@ _ line most
” right quote most
‘ left tick most
’ right tick most
-– en dash most
+– en dash most always
— em dash most
● circle most
¨ diaeresis most
@@ -108,9 +108,9 @@ _ line most
® registered some
™ Trademark some
© Copyright some
-± Plus or Minus most
-× times most
-÷ divide by most
+± Plus or Minus some
+× times some
+÷ divide by some
← left arrow some
→ right arrow some
✓ check some


https://bitbucket.org/nvdaaddonteam/nvda/commits/3a32fe2eab06/
Changeset: 3a32fe2eab06
Branch: None
User: mdcurran
Date: 2015-05-08 01:32:28+00:00
Summary: Merge branch 't4638' into next. Incubates #4638

Affected #: 3 files

diff --git a/source/NVDAObjects/IAccessible/mozilla.py
b/source/NVDAObjects/IAccessible/mozilla.py
index 8676ab5..21fdd36 100755
--- a/source/NVDAObjects/IAccessible/mozilla.py
+++ b/source/NVDAObjects/IAccessible/mozilla.py
@@ -249,10 +249,11 @@ def findExtraOverlayClasses(obj, clsList):
if ver and ver.full.startswith("1.9"):
clsList.append(Gecko1_9)

- if iaRole == oleacc.ROLE_SYSTEM_DIALOG:
+ if iaRole in
(oleacc.ROLE_SYSTEM_DIALOG,oleacc.ROLE_SYSTEM_PROPERTYPAGE):
xmlRoles = obj.IA2Attributes.get("xml-roles", "").split(" ")
- if "dialog" in xmlRoles:
+ if "dialog" in xmlRoles or "tabpanel" in xmlRoles:
# #2390: Don't try to calculate text for ARIA dialogs.
+ # #4638: Don't try to calculate text for ARIA tab
panels.
try:
clsList.remove(Dialog)
except ValueError:

diff --git a/source/NVDAObjects/window/excelChart.py
b/source/NVDAObjects/window/excelChart.py
index bd9ab23..f028ae3 100644
--- a/source/NVDAObjects/window/excelChart.py
+++ b/source/NVDAObjects/window/excelChart.py
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#NVDAObjects/excel.py
#A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2014-2015 Dinesh Kaushal, NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

@@ -119,233 +119,227 @@ xlXYScatterSmoothNoMarkers = 73

# Dictionary for the Description of chart types.
chartTypeDict = {
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DArea : _( "3D Area" ),
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DAreaStacked : _( "3D Stacked Area" ),
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DAreaStacked100 : _( "100 percent Stacked Area" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DBarClustered : _( "3D Clustered Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DBarStacked : _( "3D Stacked Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DBarStacked100 : _( "3D 100 percent Stacked Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DColumn : _( "3D Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DColumnClustered : _( "3D Clustered Column" ),
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DColumnStacked : _( "3D Stacked Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DColumnStacked100 : _( "3D 100 percent Stacked Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DLine : _( "3D Line" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DPie : _( "3D Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xl3DPieExploded : _( "Exploded 3D Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlArea : _( "Area" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlAreaStacked : _( "Stacked Area" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlAreaStacked100 : _( "100 percent Stacked Area" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBarClustered : _( "Clustered Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBarOfPie : _( "Bar of Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBarStacked : _( "Stacked Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBarStacked100 : _( "100 percent Stacked Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBubble : _( "Bubble" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlBubble3DEffect : _( "Bubble with 3D effects" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlColumnClustered : _( "Clustered Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlColumnStacked : _( "Stacked Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlColumnStacked100 : _( "100 percent Stacked Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeBarClustered : _( "Clustered Cone Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeBarStacked : _( "Stacked Cone Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeBarStacked100 : _( "100 percent Stacked Cone Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeCol : _( "3D Cone Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeColClustered : _( "Clustered Cone Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeColStacked : _( "Stacked Cone Column" ),
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlConeColStacked100 : _( "100 percent Stacked Cone Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderBarClustered : _( "Clustered Cylinder Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderBarStacked : _( "Stacked Cylinder Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderBarStacked100 : _( "100 percent Stacked Cylinder Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderCol : _( "3D Cylinder Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderColClustered : _( "Clustered Cone Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderColStacked : _( "Stacked Cone Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlCylinderColStacked100 : _( "100 percent Stacked Cylinder Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlDoughnut : _( "Doughnut" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlDoughnutExploded : _( "Exploded Doughnut" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLine : _( "Line" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLineMarkers : _( "Line with Markers" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLineMarkersStacked : _( "Stacked Line with Markers" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLineMarkersStacked100 : _( "100 percent Stacked Line with Markers" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLineStacked : _( "Stacked Line" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlLineStacked100 : _( "100 percent Stacked Line" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlPie : _( "Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlPieExploded : _( "Exploded Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlPieOfPie : _( "Pie of Pie" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidBarClustered : _( "Clustered Pyramid Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidBarStacked : _( "Stacked Pyramid Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidBarStacked100 : _( "100 percent Stacked Pyramid Bar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidCol : _( "3D Pyramid Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidColClustered : _( "Clustered Pyramid Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidColStacked : _( "Stacked Pyramid Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
xlPyramidColStacked100 : _( "100 percent Stacked Pyramid Column" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlRadar : _( "Radar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlRadarFilled : _( "Filled Radar" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlRadarMarkers : _( "Radar with Data Markers" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlStockHLC : _( "High-Low-Close" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlStockOHLC : _( "Open-High-Low-Close" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlStockVHLC : _( "Volume-High-Low-Close" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlStockVOHLC : _( "Volume-Open-High-Low-Close" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlSurface : _( "3D Surface" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlSurfaceTopView : _( "Surface (Top View)" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlSurfaceTopViewWireframe : _( "Surface (Top View wireframe)" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlSurfaceWireframe : _( "3D Surface (wireframe)" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlXYScatter : _( "Scatter" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlXYScatterLines : _( "Scatter with Lines" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlXYScatterLinesNoMarkers : _( "Scatter with Lines and No Data Markers"
) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlXYScatterSmooth : _( "Scatter with Smoothed Lines" ) ,
- # Translators: Chart type
+ # Translators: A type of chart in Microsoft Excel.
+ # See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
xlXYScatterSmoothNoMarkers : _( "Scatter with Smoothed Lines and No
Data Markers")
}

-# Dictionary for the segments of different chart types.
-chartSegmentDict = {
- xl3DArea : "3D Area",
- xl3DAreaStacked : "3D Stacked Area",
- xl3DAreaStacked100 : "100 percent Stacked Area",
- xl3DBarClustered : "3D Clustered Bar",
- xl3DBarStacked : "3D Stacked Bar",
- xl3DBarStacked100 : "3D 100 percent Stacked Bar",
- xl3DColumn : "Column",
- xl3DColumnClustered : "Column",
- xl3DColumnStacked : "Column",
- xl3DColumnStacked100 : "Column",
- xl3DLine : "Line",
- xl3DPie : "Slice",
- xl3DPieExploded : "Slice",
- xlArea : "Area",
- xlAreaStacked : "Stacked Area",
- xlAreaStacked100 : "100 percent Stacked Area",
- xlBarClustered : "Clustered Bar",
- xlBarOfPie : "Bar of Pie",
- xlBarStacked : "Stacked Bar",
- xlBarStacked100 : "100 percent Stacked Bar",
- xlBubble : "Bubble",
- xlBubble3DEffect : "Bubble with 3D effects",
- xlColumnClustered : "Column",
- xlColumnStacked : "Column",
- xlColumnStacked100 : "Column",
- xlConeBarClustered : "Clustered Cone Bar",
- xlConeBarStacked : "Stacked Cone Bar",
- xlConeBarStacked100 : "100 percent Stacked Cone Bar",
- xlConeCol : "3D Cone Column",
- xlConeColClustered : "Clustered Cone Column",
- xlConeColStacked : "Stacked Cone Column",
- xlConeColStacked100 : "100 percent Stacked Cone Column",
- xlCylinderBarClustered : "Clustered Cylinder Bar",
- xlCylinderBarStacked : "Stacked Cylinder Bar",
- xlCylinderBarStacked100 : "100 percent Stacked Cylinder Bar",
- xlCylinderCol : "3D Cylinder Column",
- xlCylinderColClustered : "Clustered Cone Column",
- xlCylinderColStacked : "Stacked Cone Column",
- xlCylinderColStacked100 : "100 percent Stacked Cylinder Column",
- xlDoughnut : "Doughnut",
- xlDoughnutExploded : "Exploded Doughnut",
- xlLine : "Line",
- xlLineMarkers : "Line",
- xlLineMarkersStacked : "Line",
- xlLineMarkersStacked100 : "Line",
- xlLineStacked : "Line",
- xlLineStacked100 : "Line",
- xlPie : "slice",
- xlPieExploded : "Exploded Pie",
- xlPieOfPie : "Pie of Pie",
- xlPyramidBarClustered : "Clustered Pyramid Bar",
- xlPyramidBarStacked : "Stacked Pyramid Bar",
- xlPyramidBarStacked100 : "100 percent Stacked Pyramid Bar",
- xlPyramidCol : "3D Pyramid Column",
- xlPyramidColClustered : "Clustered Pyramid Column",
- xlPyramidColStacked : "Stacked Pyramid Column",
- xlPyramidColStacked100 : "100 percent Stacked Pyramid Column",
- xlRadar : "Radar",
- xlRadarFilled : "Filled Radar",
- xlRadarMarkers : "Radar with Data Markers",
- xlStockHLC : "High-Low-Close",
- xlStockOHLC : "Open-High-Low-Close",
- xlStockVHLC : "Volume-High-Low-Close",
- xlStockVOHLC : "Volume-Open-High-Low-Close",
- xlSurface : "3D Surface",
- xlSurfaceTopView : "Surface (Top View)",
- xlSurfaceTopViewWireframe : "Surface (Top View wireframe)",
- xlSurfaceWireframe : "3D Surface (wireframe)",
- xlXYScatter : "Scatter",
- xlXYScatterLines : "Scatter with Lines",
- xlXYScatterLinesNoMarkers : "Scatter with Lines and No Data Markers",
- xlXYScatterSmooth : "Scatter with Smoothed Lines",
- xlXYScatterSmoothNoMarkers : "Scatter with Smoothed Lines and No Data
Markers"
-}
-
-
-
# Axis types in chart
xlCategory = 1
xlValue = 2
@@ -416,15 +410,13 @@ class ExcelChart(excel.ExcelBase):
name=self.excelChartObject.ChartTitle.Text
else:
name=self.excelChartObject.Name
-#find the type of the chart
+ #find the type of the chart
chartType = self.excelChartObject.ChartType
- if chartType in chartTypeDict.keys():
- chartTypeText = "%s" %(chartTypeDict[chartType])
- else:
- # Translators: chart type to be reported when the type
is not available
- chartTypeText=_("unknown")
- # Translators: prompt for chart title and chart type to be
reported
- return _("Chart title equals {chartTitle} type equals
{chartType}").format(chartTitle=name, chartType=chartTypeText)
+ chartTypeText = chartTypeDict.get(chartType,
+ # Translators: Reported when the type of a chart is not
known.
+ _("unknown"))
+ # Translators: Message reporting the title and type of a chart.
+ return _("Chart title: {chartTitle}, type:
{chartType}").format(chartTitle=name, chartType=chartTypeText)

def _get_title(self):
try:
@@ -432,10 +424,10 @@ class ExcelChart(excel.ExcelBase):
except COMError:
title=None
return title
-
+
def _get_role(self):
return controlTypes.ROLE_CHART
-
+
def script_switchToCell(self,gesture):
cell=self.excelWindowObject.ActiveCell
cell.Activate()
@@ -444,19 +436,7 @@ class ExcelChart(excel.ExcelBase):
script_switchToCell.canPropagate=True

def event_gainFocus(self):
- if self.excelChartObject.HasTitle:
- name=self.excelChartObject.ChartTitle.Text
- else:
- name=self.excelChartObject.Name
-#find the type of the chart
- chartType = self.excelChartObject.ChartType
- if chartType in chartTypeDict.keys():
- chartTypeText=_("%s" %(chartTypeDict[chartType]))
- else:
- # Translators: chart type to be reported when the type
is not available
- chartTypeText=_("unknown")
- # Translators: prompt for chart title and chart type to be
reported
- ui.message( _("Chart title equals {chartTitle} type equals
{chartType}").format(chartTitle=name, chartType=chartTypeText))
+ ui.message(self.name)
self.reportSeriesSummary()

def script_reportTitle(self,gesture):
@@ -467,13 +447,17 @@ class ExcelChart(excel.ExcelBase):
axis=None
if self.excelChartObject.HasAxis(axisType, xlPrimary):
axis = self.excelChartObject.Axes(axisType, xlPrimary)
- else:
- pass
- # Translators: Axis title to be reported when the title is not
available
+ # Translators: Reported when there is no title for an axis in a
chart.
axisTitle = axis.AxisTitle.Text if axis and axis.HasTitle else
_("Not defined")
- # Translators: Chart Axis types
- axisName = _( "Category" ) if axisType==xlCategory else _(
"Value" ) if axisType==xlValue else _( "Series" )
- # Translators: Prompt for axis title and axis type to be
reported
+ axisName = (
+ # Translators: A type of axis in a chart.
+ _( "Category" ) if axisType==xlCategory
+ # Translators: A type of axis in a chart.
+ else _( "Value" ) if axisType==xlValue
+ # Translators: A type of axis in a chart.
+ else _( "Series" ))
+ # Translators: Message reporting the type and title of an axis
in a chart.
+ # For example, this might report "Category axis is month"
text=_("{axisName} Axis is
{axisTitle}").format(axisName=axisName, axisTitle=axisTitle)
ui.message(text)

@@ -493,18 +477,18 @@ class ExcelChart(excel.ExcelBase):
count = self.excelChartObject.SeriesCollection().count
if count>0:
if count == 1:
- # Translators: Number of series when there is
only one series
- seriesValueString = _( "There is %d series in
this chart" ) %(count)
+ # Translators: Indicates that there is 1 series
in a chart.
+ seriesValueString = _( "There is 1 series in
this chart" )
else:
- # Translators: Number of series when there are
multiple series
+ # Translators: Indicates the number of series
in a chart where there are multiple series.
seriesValueString = _( "There are total %d
series in this chart" ) %(count)

for i in xrange(1, count+1):
- # Translators: prompt for series number and
name to be reported
- seriesValueString += ", Series %d %s" %(i,
self.excelChartObject.SeriesCollection(i).Name)
+ # Translators: Specifies the number and name of
a series when listing series in a chart.
+ seriesValueString += ", " + _("series {number}
{name}").format(number=i, name=self.excelChartObject.SeriesCollection(i).Name)
text = seriesValueString
else:
- # Translators: prompt to be reported when there is no
series
+ # Translators: Indicates that there are no series in a
chart.
text=_("No Series defined.")
ui.message(text)

@@ -601,15 +585,22 @@ class ExcelChartElementBase(Window):

def GetChartSegment(self):
chartType = self.excelChartObject.ChartType
- if chartType in chartSegmentDict.keys():
- text= chartSegmentDict[chartType]
+ if chartType in (xl3DPie, xl3DPieExploded, xlPie,
xlPieExploded, xlPieOfPie):
+ # Translators: A slice in a pie chart.
+ text=_("slice")
+ elif chartType in (xl3DColumn, xl3DColumnClustered,
xl3DColumnStacked, xl3DColumnStacked100, xlColumnClustered, xlColumnStacked100,
xlColumnStacked):
+ # Translators: A column in a column chart.
+ text=_("column")
+ elif chartType in (xl3DLine, xlLine, xlLineMarkers,
xlLineMarkersStacked, xlLineMarkersStacked100, xlLineStacked, xlLineStacked100):
+ # Translators: A data point in a line chart.
+ text=_("data point")
else:
- # Translators: Chart segment such as slice for pie
chart etc this is reported when there is no segment available.
+ # Translators: A segment of a chart for charts which
don't have a specific name for segments.
text=_("item")
return text

def _get_role(self):
- return controlTypes.ROLE_UNKNOWN
+ return controlTypes.ROLE_UNKNOWN

def _get_name(self):
return self._getChartElementText(self.elementID , self.arg1 ,
self.arg2)
@@ -620,94 +611,54 @@ class ExcelChartElementBase(Window):
def script_reportCurrentChartElementColor(self,gesture):
if self.elementID == xlSeries:
if self.arg2 == -1:
- ui.message ( _( "Series color: {}
").format(colors.RGB.fromCOLORREF(int( self.excelChartObject.SeriesCollection(
self.arg1 ).Interior.Color ) ).name ) )
-
+ ui.message ( _( "Series color: {colorName}
").format(colorName=colors.RGB.fromCOLORREF(int(
self.excelChartObject.SeriesCollection( self.arg1 ).Interior.Color ) ).name ) )
+
+ ELEMENT_IDS = {
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlDisplayUnitLabel: _("Display Unit Label"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlMajorGridlines: _("Major Gridlines"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlMinorGridlines: _("Minor Gridlines"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlPivotChartDropZone: _("Pivot Chart Drop Zone"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlPivotChartFieldButton: _("Pivot Chart Field Button"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlDownBars: _("Down Bars"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlDropLines: _("Drop Lines"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlHiLoLines: _("Hi Lo Lines"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlRadarAxisLabels: _("Radar Axis Labels"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlSeriesLines: _("Series Lines"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlUpBars: _("Up Bars"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlCorners: _("Corners"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlDataTable: _("Data Table"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlFloor: _("Floor"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlNothing: _("Nothing"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlWalls: _("Walls"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlDataLabel: _("Data Label"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlErrorBars: _("Error Bars"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlXErrorBars: _("X Error Bars"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlYErrorBars: _("Y Error Bars"),
+ # Translators: A type of element in a Microsoft Excel chart.
+ xlShape: _("Shape"),
+ }
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
- if ElementID == xlDisplayUnitLabel:
- # Translators: prompt for xlDisplayUnitLabel
- return _( "Display Unit Label")
-
- elif ElementID == xlMajorGridlines:
- # Translators: prompt for xlMajorGridlines
- return _( "Major Gridlines" )
-
- elif ElementID == xlMinorGridlines:
- # Translators: prompt for xlMinorGridlines
- return _( "Minor Gridlines" )
-
- elif ElementID == xlPivotChartDropZone:
- # Translators: prompt for xlPivotChartDropZone
- return _( "Pivot Chart Drop Zone" )
-
- elif ElementID == xlPivotChartFieldButton:
- # Translators: prompt for xlPivotChartFieldButton
- return _( "Pivot Chart Field Button" )
-
- elif ElementID == xlDownBars:
- # Translators: prompt for xlDownBars
- return _( "Down Bars" )
-
- elif ElementID == xlDropLines:
- # Translators: prompt for xlDropLines
- return _( "Drop Lines" )
-
- elif ElementID == xlHiLoLines:
- # Translators: prompt for xlHiLoLines
- return _( "Hi Lo Lines" )
-
- elif ElementID == xlRadarAxisLabels:
- # Translators: prompt for xlRadarAxisLabels
- return _( "Radar Axis Labels" )
-
- elif ElementID == xlSeriesLines:
- # Translators: prompt for xlSeriesLines
- return _( "Series Lines" )
-
- elif ElementID == xlUpBars:
- # Translators: prompt for xlUpBars
- return _( "Up Bars" )
-
- elif ElementID == xlCorners:
- # Translators: prompt for xlCorners
- return _( "Corners" )
-
- elif ElementID == xlDataTable:
- # Translators: prompt for xlDataTable
- return _( "Data Table" )
-
- elif ElementID == xlFloor:
- # Translators: prompt for xlFloor
- return _( "Floor" )
-
- elif ElementID == xlNothing:
- # Translators: prompt for xlNothing
- return _( "xlNothing" )
-
- elif ElementID == xlWalls:
- # Translators: prompt for xlWalls
- return _( "Walls" )
-
- elif ElementID == xlDataLabel:
- # Translators: prompt for xlDataLabel
- return _( "Data Label" )
-
- elif ElementID == xlErrorBars:
- # Translators: prompt for xlErrorBars
- return _( "Error Bars" )
-
- elif ElementID == xlXErrorBars:
- # Translators: prompt for xlXErrorBars
- return _( "X Error Bars" )
-
- elif ElementID == xlYErrorBars:
- # Translators: prompt for xlYErrorBars
- return _( "Y Error Bars" )
-
- elif ElementID == xlShape:
- # Translators: prompt for xlShape
- return _( "Shape" )
-
- #end def _Select
+ return self.ELEMENT_IDS[ElementID]

__gestures = {
"kb:NVDA+d" : "reportCurrentChartElementWithExtraInfo",
@@ -727,50 +678,59 @@ class ExcelChartElementSeries(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlSeries:
if arg2 == -1:
- # Translators: Prompt for series details in the
format: Name series index of count
- return _( "{} Series {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
+ # Translators: Details about a series in a
chart.
+ # For example, this might report "foo series 1
of 2"
+ return _( "{seriesName} series {seriesIndex} of
{seriesCount}").format( seriesName =
self.excelChartObject.SeriesCollection(arg1).Name , seriesIndex = arg1 ,
seriesCount = self.excelChartObject.SeriesCollection().Count )
else:
-# if XValue is a float, change it to int, else dates are shown with points.
hope this does not introduce another bug
+ # if XValue is a float, change it to int, else
dates are shown with points. hope this does not introduce another bug
if isinstance(
self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1] , float):
excelSeriesXValue =
int(self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1] )
else:
excelSeriesXValue =
self.excelChartObject.SeriesCollection(arg1).XValues[arg2 - 1]

output=""
- if self.excelChartObject.ChartType == xlLine or
self.excelChartObject.ChartType == xlLineMarkers or
self.excelChartObject.ChartType == xlLineMarkersStacked or
self.excelChartObject.ChartType == xlLineMarkersStacked100 or
self.excelChartObject.ChartType == xlLineStacked or
self.excelChartObject.ChartType == xlLineStacked100:
+ if self.excelChartObject.ChartType in (xlLine,
xlLineMarkers , xlLineMarkersStacked, xlLineMarkersStacked100, xlLineStacked,
xlLineStacked100):
if arg2 > 1:

if
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] ==
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2]:
- # Translators: for line
charts, no change from the previous element
- output += _( "no change
from point {}, ").format( arg2 - 1 )
+ # Translators: For line
charts, indicates no change from the previous data point on the left
+ output += _( "no change
from point {previousIndex}, ").format( previousIndex = arg2 - 1 )
elif
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] >
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2]:
- # Translators: for line
charts, increase from the previous element
- output += _( "Increased
by {} from point {}, ").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] , arg2 - 1 )
+ # Translators: For line
charts, indicates an increase from the previous data point on the left
+ output += _( "Increased
by {incrementValue} from point {previousIndex}, ").format( incrementValue =
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] , previousIndex =
arg2 - 1 )
else:
- # Translators: for line
charts, decrease from the previous element
- output += _( "decreased
by {} from point {}, ").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] , arg2 - 1 )
+ # Translators: For line
charts, indicates a decrease from the previous data point on the left
+ output += _( "decreased
by {decrementValue} from point {previousIndex}, ").format( decrementValue =
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 2] -
self.excelChartObject.SeriesCollection(arg1).Values[arg2 - 1] , previousIndex =
arg2 - 1 )

if self.excelChartObject.HasAxis(xlCategory)
and self.excelChartObject.Axes(xlCategory).HasTitle:
- # Translators: report category axis
title if available in the format title value
- output += _( "{} {}: ").format(
self.excelChartObject.Axes(xlCategory).AxisTitle.Text , excelSeriesXValue )
+ # Translators: Specifies the category
of a data point.
+ # {categoryAxisTitle} will be replaced
with the title of the category axis; e.g. "Month".
+ # {categoryAxisData} will be replaced
with the category itself; e.g. "January".
+ output += _( "{categoryAxisTitle}
{categoryAxisData}: ").format( categoryAxisTitle =
self.excelChartObject.Axes(xlCategory).AxisTitle.Text , categoryAxisData =
excelSeriesXValue )
else:
- # Translators: report category axis
title as Category if axis title is not available in the format "category" value
- output += _( "Category {}: ").format(
excelSeriesXValue )
+ # Translators: Specifies the category
of a data point.
+ # {categoryAxisData} will be replaced
with the category itself; e.g. "January".
+ output += _( "Category
{categoryAxisData}: ").format( categoryAxisData = excelSeriesXValue )

if self.excelChartObject.HasAxis(xlValue) and
self.excelChartObject.Axes(xlValue).HasTitle:
- # Translators: report value axis title
if available in the format title value
- output += _( "{} {}").format(
self.excelChartObject.Axes(xlValue).AxisTitle.Text ,
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])
+ # Translators: Specifies the value of a
data point.
+ # {valueAxisTitle} will be replaced
with the title of the value axis; e.g. "Amount".
+ # {valueAxisData} will be replaced with
the value itself; e.g. "1000".
+ output += _( "{valueAxisTitle}
{valueAxisData}").format( valueAxisTitle =
self.excelChartObject.Axes(xlValue).AxisTitle.Text , valueAxisData =
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])
else:
- # Translators: report value axis title
as value if axis title is not available in the format "Value" value
- output += _( "value {}").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])
+ # Translators: Specifies the value of a
data point.
+ # {valueAxisData} will be replaced with
the value itself; e.g. "1000".
+ output += _( "value
{valueAxisData}").format( valueAxisData =
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1])

- if self.excelChartObject.ChartType == xlPie or
self.excelChartObject.ChartType == xlPieExploded or
self.excelChartObject.ChartType == xlPieOfPie:
+ if self.excelChartObject.ChartType in (xlPie,
xlPieExploded, xlPieOfPie):
total = math.fsum(
self.excelChartObject.SeriesCollection(arg1).Values )
- # Translators: Prompt for pie chart in
the format: fraction nn percent slice index of count
- output += _( " fraction {:.2f} Percent
{} {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Values[arg2-1] / total *100.00 ,
self.GetChartSegment() , arg2 , len(
self.excelChartObject.SeriesCollection(arg1).Values ) )
+ # Translators: Details about a slice of
a pie chart.
+ # For example, this might report
"fraction 25.25 percent slice 1 of 5"
+ output += _( " fraction
{fractionValue:.2f} Percent slice {pointIndex} of {pointCount}").format(
fractionValue = self.excelChartObject.SeriesCollection(arg1).Values[arg2-1] /
total *100.00 , pointIndex = arg2 , pointCount = len(
self.excelChartObject.SeriesCollection(arg1).Values ) )
else:
- # Translators: Prompt for other charts
in the format: segment type index of count
- output += _( " {} {} of {}").format(
self.GetChartSegment() , arg2 , len(
self.excelChartObject.SeriesCollection(arg1).Values ) )
+ # Translators: Details about a segment
of a chart.
+ # For example, this might report
"column 1 of 5"
+ output += _( " {segmentType}
{pointIndex} of {pointCount}").format( segmentType = self.GetChartSegment() ,
pointIndex = arg2 , pointCount = len(
self.excelChartObject.SeriesCollection(arg1).Values ) )

return output

@@ -782,29 +742,32 @@ class ExcelChartElementAxis(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlAxis:
if arg1 == xlPrimary:
- # Translators: axis group
+ # Translators: The primary axis group in a
Microsoft Excel chart.
axisGroup = _("Primary")
elif arg1 == xlSecondary :
- # Translators: axis group
+ # Translators: The secondary axis group in a
Microsoft Excel chart.
axisGroup = _("Secondary")

if arg2 == xlCategory:
- # Translators: axis type
+ # Translators: The category axis in a Microsoft
Excel chart.
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
axisType= _("Category")
elif arg2 == xlValue:
- # Translators: axis type
+ # Translators: The value axis in a Microsoft
Excel chart.
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
axisType= _("Value")
elif arg2 == xlSeriesAxis:
- # Translators: axis type
+ # Translators: The series axis in a Microsoft
Excel chart.
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
axisType= _("Series")

axisDescription =""
if self.excelChartObject.HasAxis( arg2 ) and
self.excelChartObject.Axes( arg2 ).HasTitle:
- # Translators: Prompt for axis details such as:
type, group, and title
- axisDescription += _("Chart Axis, type equals
{}, group equals {}, Title equals {}").format( axisType , axisGroup ,
self.excelChartObject.Axes( arg2 , arg1 ).AxisTitle.Text )
- elif self.excelChartObject.HasAxis( arg2 ) and not
self.excelChartObject.Axes( arg2 ).HasTitle:
- # Translators: Prompt for axis details such as:
type, group, and title when there is no title
- axisDescription += _("Chart Axis, type equals
{}, group equals {}, Title equals {}").format( axisType , axisGroup , _("none")
)
+ # Translators: Details about an axis in a chart.
+ axisDescription += _("Chart axis, type:
{axisType}, group: {axisGroup}, title: {axisTitle}").format( axisType =
axisType , axisGroup = axisGroup , axisTitle = self.excelChartObject.Axes( arg2
, arg1 ).AxisTitle.Text )
+ else:
+ # Translators: Details about an untitled axis
in a chart.
+ axisDescription += _("Chart axis, type:
{axisType}, group: {axisGroup}").format( axisType = axisType , axisGroup =
axisGroup)

return axisDescription

@@ -815,13 +778,10 @@ class ExcelChartElementAxisTitle(ExcelChartElementBase):

def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlAxisTitle:
- axisTitle=""
+ # Translators: Indicates a chart axis title in
Microsoft Excel.
+ axisTitle=_("Chart axis title")
if self.excelChartObject.HasAxis( arg2 ) and
self.excelChartObject.Axes( arg2 ).HasTitle:
- # Translators: Prompt for axis title if axis
has title
- axisTitle += _("Chart Axis Title equals {}
").format( self.excelChartObject.Axes( arg2 , arg1 ).AxisTitle.Text )
- elif self.excelChartObject.HasAxis( arg2 ) and not
self.excelChartObject.Axes( arg2 ).HasTitle:
- # Translators: Prompt for axis title without
title
- axisTitle += _("Chart Axis Title equals {}
").format( _("none") )
+ axisTitle += ": " + self.excelChartObject.Axes(
arg2 , arg1 ).AxisTitle.Text

return axisTitle

@@ -832,13 +792,13 @@ class ExcelChartElementTrendline(ExcelChartElementBase):

def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlTrendline:
+ # Translators: Indicates a trendline in a Microsoft
Excel chart.
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+ text = _("trendline")
if
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DisplayEquation
or
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DisplayRSquared:
- trendlineText = unicode(
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DataLabel.Text
).encode("utf-8").replace("\xc2\xb2" , _( " square " ) )
- # Translators: Prompt for trendline with
equation or r square
- return _( " trendline {} ").format(
trendlineText )
- else:
- # Translators: Prompt for trendline without
equation or r square
- return _( "Trendline" )
+ # Translators: Describes the squared symbol
used in the label for a trendline in a Microsoft Excel chart.
+ text += " " +
self.excelChartObject.SeriesCollection(arg1).Trendlines(arg2).DataLabel.Text.replace(u"²",
_( " squared " ) )
+ return text

class ExcelChartElementChartTitle(ExcelChartElementBase):

@@ -848,10 +808,10 @@ class ExcelChartElementChartTitle(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlChartTitle:
if self.excelChartObject.HasTitle:
- # Translators: Prompt for chart title
- return _( "Chart Title equals {}").format (
self.excelChartObject.ChartTitle.Text )
+ # Translators: Details about a chart title in
Microsoft Excel.
+ return _( "Chart title: {chartTitle}").format (
chartTitle = self.excelChartObject.ChartTitle.Text )
else:
- # Translators: Prompt for chart title when the
title is not available
+ # Translators: Indicates an untitled chart in
Microsoft Excel.
return _( "Untitled chart" )

class ExcelChartElementChartArea(ExcelChartElementBase):
@@ -862,10 +822,10 @@ class ExcelChartElementChartArea(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlChartArea:
if reportExtraInfo:
- # Translators: Prompt for chart area with
dimentions
- return _( "Chart area height equals {}, width
equals {}, top equals {}, left equals {}").format (
self.excelChartObject.ChartArea.Height , self.excelChartObject.ChartArea.Width
, self.excelChartObject.ChartArea.Top , self.excelChartObject.ChartArea.Left)
+ # Translators: Details about the chart area in
a Microsoft Excel chart.
+ return _( "Chart area, height:
{chartAreaHeight}, width: {chartAreaWidth}, top: {chartAreaTop}, left:
{chartAreaLeft}").format ( chartAreaHeight =
self.excelChartObject.ChartArea.Height , chartAreaWidth =
self.excelChartObject.ChartArea.Width , chartAreaTop =
self.excelChartObject.ChartArea.Top , chartAreaLeft =
self.excelChartObject.ChartArea.Left)
else:
- # Translators: Prompt for chart area
+ # Translators: Indicates the chart area of a
Microsoft Excel chart.
return _( "Chart area ")

class ExcelChartElementPlotArea(ExcelChartElementBase):
@@ -876,12 +836,12 @@ class ExcelChartElementPlotArea(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlPlotArea:
if reportExtraInfo:
- # useing {:.0f} to remove fractions
- # Translators: Prompt for plot area with inner
dimentions
- return _( "Plot Area inside height equals
{:.0f}, inside width equals {:.0f}, inside top equals {:.0f}, inside left
equals {:.0f}").format ( self.excelChartObject.PlotArea.InsideHeight ,
self.excelChartObject.PlotArea.InsideWidth ,
self.excelChartObject.PlotArea.InsideTop ,
self.excelChartObject.PlotArea.InsideLeft )
+ # useing {:.0f} to remove fractions
+ # Translators: Details about the plot area of a
Microsoft Excel chart.
+ return _( "Plot area, inside height:
{plotAreaInsideHeight:.0f}, inside width: {plotAreaInsideWidth:.0f}, inside
top: {plotAreaInsideTop:.0f}, inside left: {plotAreaInsideLeft:.0f}").format (
plotAreaInsideHeight = self.excelChartObject.PlotArea.InsideHeight ,
plotAreaInsideWidth = self.excelChartObject.PlotArea.InsideWidth ,
plotAreaInsideTop = self.excelChartObject.PlotArea.InsideTop ,
plotAreaInsideLeft = self.excelChartObject.PlotArea.InsideLeft )
else:
- # Translators: Prompt for plot area
- return _( "Plot Area " )
+ # Translators: Indicates the plot area of a
Microsoft Excel chart.
+ return _( "Plot area " )

class ExcelChartElementLegend(ExcelChartElementBase):

@@ -891,10 +851,11 @@ class ExcelChartElementLegend(ExcelChartElementBase):
def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlLegend:
if self.excelChartObject.HasLegend:
- # Translators: Prompt for Legend
+ # Translators: Indicates the legend in a
Microsoft Excel chart.
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
return _( "Legend" )
else:
- # Translators: Prompt for Legend when no legend is
present
+ # Translators: Indicates that there is no
legend in a Microsoft Excel chart.
return _( "No legend" )

class ExcelChartElementLegendEntry(ExcelChartElementBase):
@@ -904,8 +865,9 @@ class ExcelChartElementLegendEntry(ExcelChartElementBase):

def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlLegendEntry:
- # Translators: Prompt for Legend entry for series name
index of count
- return _( "Legend entry for Series {}, {} of
{}").format( self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
+ # Translators: Details about a legend entry for a
series in a Microsoft Excel chart.
+ # For example, this might report "Legend entry for
series Temperature 1 of 2"
+ return _( "Legend entry for series {seriesName}
{seriesIndex} of {seriesCount}").format( seriesName =
self.excelChartObject.SeriesCollection(arg1).Name , seriesIndex = arg1 ,
seriesCount = self.excelChartObject.SeriesCollection().Count )

class ExcelChartElementLegendKey(ExcelChartElementBase):

@@ -914,7 +876,7 @@ class ExcelChartElementLegendKey(ExcelChartElementBase):

def _getChartElementText(self, ElementID ,arg1,arg2 ,
reportExtraInfo=False ):
if ElementID == xlLegendKey:
- # Translators: Prompt for Legend key for series name
index of count
- return _( "Legend key for Series {} {} of {}").format(
self.excelChartObject.SeriesCollection(arg1).Name , arg1 ,
self.excelChartObject.SeriesCollection().Count )
-
-
+ # Translators: Details about a legend key for a series
in a Microsoft Excel chart.
+ # For example, this might report "Legend key for series
Temperature 1 of 2"
+ # See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+ return _( "Legend key for Series {seriesName}
{seriesIndex} of {seriesCount}").format( seriesName =
self.excelChartObject.SeriesCollection(arg1).Name , seriesIndex = arg1 ,
seriesCount = self.excelChartObject.SeriesCollection().Count )

diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index fa29318..6bd9dd1 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -1796,6 +1796,7 @@ Following are the Papenmeier command assignments for NVDA:
| Route to braille cell | routing |
| Report current character in review | l1 |
| Activate current navigator object | l2 |
+| Toggle braille tethered to | r2 |
| Report title | l1+up |
| Report Status Bar | l2+down |
| Move to containing object | up2 |


https://bitbucket.org/nvdaaddonteam/nvda/commits/7c7aad117aa4/
Changeset: 7c7aad117aa4
Branch: None
User: mdcurran
Date: 2015-05-08 03:06:58+00:00
Summary: Merge branch 't4204' into next. Incubates #4204

Affected #: 1 file

diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py
index e7e4511..59edc39 100644
--- a/source/virtualBuffers/MSHTML.py
+++ b/source/virtualBuffers/MSHTML.py
@@ -226,7 +226,11 @@ class MSHTML(VirtualBuffer):
elif nodeType=="unvisitedLink":

attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_LINKED:[1],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_TRAVERSED:[None]}
elif nodeType=="formField":
-
attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_OUTLINE,oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]}
+ attrs=[
+
{"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_OUTLINE,oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]},
+ {"IHTMLDOMNode::nodeName":["SELECT"]},
+ {"HTMLAttrib::role":["listbox"]},
+ ]
elif nodeType=="button":

attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON]}
elif nodeType=="edit":


https://bitbucket.org/nvdaaddonteam/nvda/commits/f402958998fc/
Changeset: f402958998fc
Branch: None
User: mdcurran
Date: 2015-05-25 04:28:35+00:00
Summary: BrowseMode: add a way to toggle single letter navigation on and
off (NVDA+shift+space). When off, keys like h for heading will not work and
instead go straight through to the app, but arrow keys etc will still work like
they always would in browse mode.

Affected #: 2 files

diff --git a/source/browseMode.py b/source/browseMode.py
index a071c1e..ef132ec 100644
--- a/source/browseMode.py
+++ b/source/browseMode.py
@@ -176,6 +176,30 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
def script_trapNonCommandGesture(self,gesture):
winsound.PlaySound("default",1)

+ singleLetterNavEnabled=True #: Whether single letter navigation scripts
should be active (true) or if these letters should fall to the application.
+
+ def getScript(self,gesture):
+ script=super(BrowseModeTreeInterceptor,self).getScript(gesture)
+ if self.passThrough or not gesture.isCharacter:
+ return script
+ if not self.singleLetterNavEnabled:
+ return None
+ if not script and self.shouldTrapNonCommandGestures:
+ script=self.script_trapNonCommandGesture
+ return script
+
+ def script_toggleSingleLetterNav(self,gesture):
+ if self.singleLetterNavEnabled:
+ self.singleLetterNavEnabled=False
+ # Translators: single letter navigation in browse mode
is turned off.
+ ui.message(_("Single letter navigation off"))
+ else:
+ self.singleLetterNavEnabled=True
+ # Translators: single letter navigation in browse mode
is turned on.
+ ui.message(_("Single letter navigation on"))
+ # Translators: the description for the toggleSingleLetterNavigation
command in browse mode.
+ script_toggleSingleLetterNav.__doc__=_("Switches single letter
navigation mode on and off. When on single letter keys in browse mode jump to
various kinds of elements on the page, and when off, these keys are passed to
the application.")
+
def _get_ElementsListDialog(self):
return ElementsListDialog

@@ -251,6 +275,7 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
"kb:NVDA+f7": "elementsList",
"kb:enter": "activatePosition",
"kb:space": "activatePosition",
+ "kb:NVDA+shift+space":"toggleSingleLetterNav",
}

# Add quick navigation scripts.

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 70070e6..d90ea32 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -99,8 +99,6 @@ def findScript(gesture):
func = _getObjScript(treeInterceptor, gesture, globalMapScripts)
if func and (not treeInterceptor.passThrough or
getattr(func,"ignoreTreeInterceptorPassThrough",False)):
return func
- elif gesture.isCharacter and not treeInterceptor.passThrough
and treeInterceptor.shouldTrapNonCommandGestures:
- return treeInterceptor.script_trapNonCommandGesture

# NVDAObject level.
func = _getObjScript(focus, gesture, globalMapScripts)


https://bitbucket.org/nvdaaddonteam/nvda/commits/8e8fb5a1a02c/
Changeset: 8e8fb5a1a02c
Branch: None
User: mdcurran
Date: 2015-05-28 04:38:29+00:00
Summary: browseMode: ensure that trap non-command gestures and disabling of
single letter navigation still works when a user has custom gesture bindings.
BrowseModeTreeInterceptor now has a special getAlternativeScript method which
is used to filter or switch scripts whether they come from getScript or a
global gesture map etc.

Affected #: 2 files

diff --git a/source/browseMode.py b/source/browseMode.py
index ef132ec..7450644 100644
--- a/source/browseMode.py
+++ b/source/browseMode.py
@@ -178,8 +178,7 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):

singleLetterNavEnabled=True #: Whether single letter navigation scripts
should be active (true) or if these letters should fall to the application.

- def getScript(self,gesture):
- script=super(BrowseModeTreeInterceptor,self).getScript(gesture)
+ def getAlternativeScript(self,gesture,script):
if self.passThrough or not gesture.isCharacter:
return script
if not self.singleLetterNavEnabled:

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index d90ea32..668c074 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -97,6 +97,7 @@ def findScript(gesture):
treeInterceptor = focus.treeInterceptor
if treeInterceptor and treeInterceptor.isReady:
func = _getObjScript(treeInterceptor, gesture, globalMapScripts)
+ func=treeInterceptor.getAlternativeScript(gesture,func)
if func and (not treeInterceptor.passThrough or
getattr(func,"ignoreTreeInterceptorPassThrough",False)):
return func



https://bitbucket.org/nvdaaddonteam/nvda/commits/4e65bbd2fa91/
Changeset: 4e65bbd2fa91
Branch: None
User: mdcurran
Date: 2015-05-29 02:42:34+00:00
Summary: Merge branch 'master' into next

Affected #: 109 files

diff --git a/source/locale/an/LC_MESSAGES/nvda.po
b/source/locale/an/LC_MESSAGES/nvda.po
index 9022cd3..60b2f6f 100644
--- a/source/locale/an/LC_MESSAGES/nvda.po
+++ b/source/locale/an/LC_MESSAGES/nvda.po
@@ -3,15 +3,15 @@ msgid ""
msgstr ""
"Project-Id-Version: NVDA bzr main:5884\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-15 11:28-0700\n"
+"POT-Creation-Date: 2015-05-08 19:04+1000\n"
"PO-Revision-Date: \n"
-"Last-Translator: Jorge Pérez Pérez <jorgtum@xxxxxxxxx>\n"
+"Last-Translator: Chorche Pérez <jorgtum@xxxxxxxxx>\n"
"Language-Team: Softaragonés\n"
"Language: an\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.7.3\n"
+"X-Generator: Poedit 1.7.5\n"

#. Translators: Message to indicate User Account Control (UAC) or other secure
desktop screen is active.
msgid "Secure Desktop"
@@ -165,13 +165,23 @@ msgstr "Checo grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
-msgid "Danish grade 1"
-msgstr "Danés grau 1"
+msgid "Danish 6 dot grade 1"
+msgstr "Danés de 6 puntos grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
-msgid "Danish grade 2"
-msgstr "Danés grau 2"
+msgid "Danish 8 dot grade 1"
+msgstr "Danés de 8 puntos grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Danish 6 dot grade 2"
+msgstr "Danés de 6 puntos grau 2"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "Danish 8 dot grade 2"
+msgstr "Danés de 8 puntos grau 2"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
@@ -254,16 +264,6 @@ msgstr "Braille computerizau Finlandés de 8 puntos"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
-msgid "French (Canada) grade 1"
-msgstr "Francés (Canadá) grau 1"
-
-#. Translators: The name of a braille table displayed in the
-#. braille settings dialog.
-msgid "French (Canada) grade 2"
-msgstr "Francés (Canadá) grau 2"
-
-#. Translators: The name of a braille table displayed in the
-#. braille settings dialog.
msgid "French (unified) 6 dot computer braille"
msgstr "Braille d'ordinador de 6 puntos francés (unificau)"

@@ -279,6 +279,16 @@ msgstr "Francés (unificau) Grau 2"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
+msgid "French (Canada) grade 1"
+msgstr "Francés (Canadá) grau 1"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
+msgid "French (Canada) grade 2"
+msgstr "Francés (Canadá) grau 2"
+
+#. Translators: The name of a braille table displayed in the
+#. braille settings dialog.
msgid "Gujarati grade 1"
msgstr "Gujarati grau 1"

@@ -374,8 +384,8 @@ msgstr "Neerlandés (Belchica) grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
-msgid "Dutch (netherlands) grade 1"
-msgstr "Neerlandés (Países Baixos) grau 1"
+msgid "Dutch (Netherlands) grade 1"
+msgstr "Holandés (Países Baixos) grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
@@ -459,8 +469,8 @@ msgstr "Sueco grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
-msgid "Slovak"
-msgstr "Eslovaco"
+msgid "Slovak grade 1"
+msgstr "Eslovaco grau 1"

#. Translators: The name of a braille table displayed in the
#. braille settings dialog.
@@ -965,19 +975,19 @@ msgstr "no bi ha anterior campo d'edición"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the next frame"
-msgstr "se'n mueve t'o siguient marco"
+msgstr "se'n mueve t'a siguient bastida"

#. Translators: Message presented when the browse mode element is not found.
msgid "no next frame"
-msgstr "no bi ha siguient marco"
+msgstr "no bi ha siguient bastida"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the previous frame"
-msgstr "se'n mueve t'o marco anterior"
+msgstr "se'n mueve t'a bastida anterior"

#. Translators: Message presented when the browse mode element is not found.
msgid "no previous frame"
-msgstr "no bi ha marco anterior"
+msgstr "no bi ha bastida anterior"

#. Translators: Input help message for a quick navigation command in browse
mode.
msgid "moves to the next separator"
@@ -1913,6 +1923,7 @@ msgid "selected %s"
msgstr "seleccionau %s"

#. Translators: The word for an unknown control type.
+#. Translators: Reported when the type of a chart is not known.
msgid "unknown"
msgstr "desconoixiu"

@@ -2035,6 +2046,7 @@ msgid "cell"
msgstr "celda"

#. Translators: Identifies a column (a group of vertical cells in a table).
+#. Translators: A column in a column chart.
msgid "column"
msgstr "columna"

@@ -2325,9 +2337,9 @@ msgstr "botón de menú"
msgid "drop down button grid"
msgstr "botón desplegable de quadricula"

-#. Translators: Identifies an equation.
-msgid "equation"
-msgstr "equación"
+#. Translators: Identifies mathematical content.
+msgid "math"
+msgstr "matematico"

#. Translators: Identifies a grip control.
msgid "grip"
@@ -2372,7 +2384,7 @@ msgstr "alerta"

#. Translators: Identifies an internal frame (commonly called iframe; usually
seen when browsing some sites with Internet Explorer).
msgid "IFrame"
-msgstr "Marco en linia"
+msgstr "Bastida en linia"

#. Translators: Identifies desktop pane (the desktop window).
msgid "desktop pane"
@@ -2776,6 +2788,10 @@ msgstr "Estau d'o sistema"
msgid "Input"
msgstr "Dentrada"

+#. Translators: The name of a category of NVDA commands.
+msgid "Document formatting"
+msgstr "Formatiau de documentos"
+
#. Translators: This will be presented when the input help is toggled.
msgid "input help on"
msgstr "aduya de dentrada activada"
@@ -2933,6 +2949,283 @@ msgstr ""
"Enchega y desenchega o charrar as teclas en escribir, as qualas no son "
"caracters especificament"

+#. Translators: The message announced when toggling the report font name
document formatting setting.
+msgid "report font name off"
+msgstr "Anunciar o nombre d'a fuent desenchegau"
+
+#. Translators: The message announced when toggling the report font name
document formatting setting.
+msgid "report font name on"
+msgstr "Anunciar o nombre d'a fuent enchegau"
+
+#. Translators: Input help mode message for toggle report font name command.
+msgid "Toggles on and off the reporting of font changes"
+msgstr "Enchega y desenchega l'anunciau d'o nombre d'a fuent"
+
+#. Translators: The message announced when toggling the report font size
document formatting setting.
+msgid "report font size off"
+msgstr "Anunciar o tamanyo d'a fuent desenchegau"
+
+#. Translators: The message announced when toggling the report font size
document formatting setting.
+msgid "report font size on"
+msgstr "Anunciar o tamanyo d'a fuent enchegau"
+
+#. Translators: Input help mode message for toggle report font size command.
+msgid "Toggles on and off the reporting of font size changes"
+msgstr "Enchega y desenchega l'anunciau d'o tamaño d'a fuent"
+
+#. Translators: The message announced when toggling the report font attributes
document formatting setting.
+msgid "report font attributes off"
+msgstr "Anunciar os atributos d'a fuent desenchegau"
+
+#. Translators: The message announced when toggling the report font attributes
document formatting setting.
+msgid "report font attributes on"
+msgstr "Anunciar os atributos d'a fuent enchegau"
+
+#. Translators: Input help mode message for toggle report font attributes
command.
+msgid "Toggles on and off the reporting of font attributes"
+msgstr "Enchega y desenchega l'anunciau d'os atributos d'a fuent"
+
+#. Translators: The message announced when toggling the report revisions
document formatting setting.
+msgid "report revisions off"
+msgstr "Anunciar as revisions desenchegau"
+
+#. Translators: The message announced when toggling the report revisions
document formatting setting.
+msgid "report revisions on"
+msgstr "Anunciar as revisions enchegau"
+
+#. Translators: Input help mode message for toggle report revisions command.
+msgid "Toggles on and off the reporting of revisions"
+msgstr "Enchega y desenchega l'anunciau d'as revisions"
+
+#. Translators: The message announced when toggling the report colors document
formatting setting.
+msgid "report colors off"
+msgstr "Anunciar as colors desenchegau"
+
+#. Translators: The message announced when toggling the report colors document
formatting setting.
+msgid "report colors on"
+msgstr "Anunciar as colors enchegau"
+
+#. Translators: Input help mode message for toggle report colors command.
+msgid "Toggles on and off the reporting of colors"
+msgstr "Enchega y desenchega l'anunciau d'as colors"
+
+#. Translators: The message announced when toggling the report alignment
document formatting setting.
+msgid "report alignment off"
+msgstr "Anunciar l'aliniación desenchegau"
+
+#. Translators: The message announced when toggling the report alignment
document formatting setting.
+msgid "report alignment on"
+msgstr "Anunciar l'aliniación enchegau"
+
+#. Translators: Input help mode message for toggle report alignment command.
+msgid "Toggles on and off the reporting of text alignment"
+msgstr "Enchega y desenchega l'anunciau de l'aliniación"
+
+#. Translators: The message announced when toggling the report style document
formatting setting.
+msgid "report style off"
+msgstr "Anunciar o estilo desenchegau"
+
+#. Translators: The message announced when toggling the report style document
formatting setting.
+msgid "report style on"
+msgstr "Anunciar o estilo enchegau"
+
+#. Translators: Input help mode message for toggle report style command.
+msgid "Toggles on and off the reporting of style changes"
+msgstr "Enchega y desenchega l'anunciau d'os cambeos d'estilo"
+
+#. Translators: The message announced when toggling the report spelling errors
document formatting setting.
+msgid "report spelling errors off"
+msgstr "Anunciar as errors d'ortografía desenchegau"
+
+#. Translators: The message announced when toggling the report spelling errors
document formatting setting.
+msgid "report spelling errors on"
+msgstr "Anunciar as errors d'ortografía enchegau"
+
+#. Translators: Input help mode message for toggle report spelling errors
command.
+msgid "Toggles on and off the reporting of spelling errors"
+msgstr "Enchega y desenchega l'anunciau d'as errors d'ortografía"
+
+#. Translators: The message announced when toggling the report pages document
formatting setting.
+msgid "report pages off"
+msgstr "Anunciar as pachinas desenchegau"
+
+#. Translators: The message announced when toggling the report pages document
formatting setting.
+msgid "report pages on"
+msgstr "Anunciar as pachinas enchegau"
+
+#. Translators: Input help mode message for toggle report pages command.
+msgid "Toggles on and off the reporting of pages"
+msgstr "Enchega y desenchega l'anunciau d'as pachinas"
+
+#. Translators: The message announced when toggling the report line numbers
document formatting setting.
+msgid "report line numbers off"
+msgstr "Anunciar os numeros de linia desenchegau"
+
+#. Translators: The message announced when toggling the report line numbers
document formatting setting.
+msgid "report line numbers on"
+msgstr "Anunciar os numeros de linia enchegau"
+
+#. Translators: Input help mode message for toggle report line numbers command.
+msgid "Toggles on and off the reporting of line numbers"
+msgstr "Enchega y desenchega l'anunciau d'os números de linia"
+
+#. Translators: The message announced when toggling the report line
indentation document formatting setting.
+msgid "report line indentation off"
+msgstr "Anunciar a sangría d'a linia desenchegau"
+
+#. Translators: The message announced when toggling the report line
indentation document formatting setting.
+msgid "report line indentation on"
+msgstr "Anunciar a sangría d'a linia enchegau"
+
+#. Translators: Input help mode message for toggle report line indentation
command.
+msgid "Toggles on and off the reporting of line indentation"
+msgstr "Enchega y desenchega l'anunciau d'a sangría d'a linia"
+
+#. Translators: The message announced when toggling the report paragraph
indentation document formatting setting.
+msgid "report paragraph indentation off"
+msgstr "Anunciar a sangría d'o paragrafo desenchegau"
+
+#. Translators: The message announced when toggling the report paragraph
indentation document formatting setting.
+msgid "report paragraph indentation on"
+msgstr "Anunciar a sangría d'o paragrafo enchegau"
+
+#. Translators: Input help mode message for toggle report paragraph
indentation command.
+msgid "Toggles on and off the reporting of paragraph indentation"
+msgstr "Enchega y desenchega l'anunciau d'a sangría d'o paragrafo"
+
+#. Translators: The message announced when toggling the report tables document
formatting setting.
+msgid "report tables off"
+msgstr "Anunciar as tablas desenchegau"
+
+#. Translators: The message announced when toggling the report tables document
formatting setting.
+msgid "report tables on"
+msgstr "Anunciar as tablas enchegau"
+
+#. Translators: Input help mode message for toggle report tables command.
+msgid "Toggles on and off the reporting of tables"
+msgstr "Enchega y desenchega l'anunciau d'as tablas"
+
+#. Translators: The message announced when toggling the report table
row/column headers document formatting setting.
+msgid "report table row and column headers off"
+msgstr "Anunciar os capiters de ringlera y columna de tabla desenchegau"
+
+#. Translators: The message announced when toggling the report table
row/column headers document formatting setting.
+msgid "report table row and column headers on"
+msgstr "Anunciar os capiters de ringlera y columna de tabla enchegau"
+
+#. Translators: Input help mode message for toggle report table row/column
headers command.
+msgid "Toggles on and off the reporting of table row and column headers"
+msgstr ""
+"Enchega y desenchega l'anunciau d'os capiters de ringlera y columna de tabla"
+
+#. Translators: The message announced when toggling the report table cell
coordinates document formatting setting.
+msgid "report table cell coordinates off"
+msgstr "Anunciar as coordenadas de celdas de tabla desenchegau"
+
+#. Translators: The message announced when toggling the report table cell
coordinates document formatting setting.
+msgid "report table cell coordinates on"
+msgstr "Anunciar as coordenadas de celdas de tabla enchegau"
+
+#. Translators: Input help mode message for toggle report table cell
coordinates command.
+msgid "Toggles on and off the reporting of table cell coordinates"
+msgstr "Enchega y desenchega l'anunciau d'as coordenadas de tabla"
+
+#. Translators: The message announced when toggling the report links document
formatting setting.
+msgid "report links off"
+msgstr "Anunciar os vinclos desenchegau"
+
+#. Translators: The message announced when toggling the report links document
formatting setting.
+msgid "report links on"
+msgstr "Anunciar os vinclos enchegau"
+
+#. Translators: Input help mode message for toggle report links command.
+msgid "Toggles on and off the reporting of links"
+msgstr "Enchega y desenchega l'anunciau d'os vinclos"
+
+#. Translators: The message announced when toggling the report comments
document formatting setting.
+msgid "report comments off"
+msgstr "Anunciar os comentarios desenchegau"
+
+#. Translators: The message announced when toggling the report comments
document formatting setting.
+msgid "report comments on"
+msgstr "Anunciar os comentarios enchegau"
+
+#. Translators: Input help mode message for toggle report comments command.
+msgid "Toggles on and off the reporting of comments"
+msgstr "Enchega y desenchega l'anunciau d'os comentarios"
+
+#. Translators: The message announced when toggling the report lists document
formatting setting.
+msgid "report lists off"
+msgstr "Anunciar as listas desenchegau"
+
+#. Translators: The message announced when toggling the report lists document
formatting setting.
+msgid "report lists on"
+msgstr "Anunciar as listas enchegau"
+
+#. Translators: Input help mode message for toggle report lists command.
+msgid "Toggles on and off the reporting of lists"
+msgstr "Enchega y desenchega l'anunciau d'as listas"
+
+#. Translators: The message announced when toggling the report headings
document formatting setting.
+msgid "report headings off"
+msgstr "Anunciar os capiters desenchegau"
+
+#. Translators: The message announced when toggling the report headings
document formatting setting.
+msgid "report headings on"
+msgstr "Anunciar os capiters enchegau"
+
+#. Translators: Input help mode message for toggle report headings command.
+msgid "Toggles on and off the reporting of headings"
+msgstr "Enchega y desenchega l'anunciau d'os capiters"
+
+#. Translators: The message announced when toggling the report block quotes
document formatting setting.
+msgid "report block quotes off"
+msgstr "Anunciar as citas desenchegau"
+
+#. Translators: The message announced when toggling the report block quotes
document formatting setting.
+msgid "report block quotes on"
+msgstr "Anunciar as citas enchegau"
+
+#. Translators: Input help mode message for toggle report block quotes command.
+msgid "Toggles on and off the reporting of block quotes"
+msgstr "Enchega y desenchega l'anunciau d'as citas"
+
+#. Translators: The message announced when toggling the report landmarks
document formatting setting.
+msgid "report landmarks off"
+msgstr "Anunciar as zonas desenchegau"
+
+#. Translators: The message announced when toggling the report landmarks
document formatting setting.
+msgid "report landmarks on"
+msgstr "Anunciar as zonas enchegau"
+
+#. Translators: Input help mode message for toggle report landmarks command.
+msgid "Toggles on and off the reporting of landmarks"
+msgstr "Enchega y desenchega l'anunciau d'as zonas"
+
+#. Translators: The message announced when toggling the report frames document
formatting setting.
+msgid "report frames off"
+msgstr "Anunciar as bastidas desenchegau"
+
+#. Translators: The message announced when toggling the report frames document
formatting setting.
+msgid "report frames on"
+msgstr "Anunciar as bastidas enchegau"
+
+#. Translators: Input help mode message for toggle report frames command.
+msgid "Toggles on and off the reporting of frames"
+msgstr "Enchega y desenchega l'anunciau d'as bastidas"
+
+#. Translators: The message announced when toggling the report if clickable
document formatting setting.
+msgid "report if clickable off"
+msgstr "Anunciar si ye clicable desenchegau"
+
+#. Translators: The message announced when toggling the report if clickable
document formatting setting.
+msgid "report if clickable on"
+msgstr "Anunciar si ye clicable enchegau"
+
+#. Translators: Input help mode message for toggle report if clickable command.
+msgid "Toggles on and off reporting if clickable"
+msgstr "Enchega y desenchega l'anunciau de si ye clicable"
+
#. Translators: Reported when the user cycles through speech symbol levels
#. which determine what symbols are spoken.
#. %s will be replaced with the symbol level; e.g. none, some, most and all.
@@ -3503,6 +3796,10 @@ msgstr "Amuestra o dialogo Sintetizadors d'o NVDA"
msgid "Shows the NVDA voice settings dialog"
msgstr "Amuestra o dialogo d'Opcions de Voz d'o NVDA"

+#. Translators: Input help mode message for go to braille settings dialog
command.
+msgid "Shows the NVDA braille settings dialog"
+msgstr "Amuestra o dialogo Opcions de braille d'o NVDA"
+
#. Translators: Input help mode message for go to keyboard settings dialog
command.
msgid "Shows the NVDA keyboard settings dialog"
msgstr "Amuestra o dialogo Opcions de Teclau d'o NVDA"
@@ -3511,6 +3808,14 @@ msgstr "Amuestra o dialogo Opcions de Teclau d'o NVDA"
msgid "Shows the NVDA mouse settings dialog"
msgstr "Amuestra o dialogo Opcions d'o Churi d'o NVDA"

+#. Translators: Input help mode message for go to review cursor settings
dialog command.
+msgid "Shows the NVDA review cursor settings dialog"
+msgstr "Amuestra o dialogo d'Opcions d'o cursor de revisión d'o NVDA"
+
+#. Translators: Input help mode message for go to input composition dialog.
+msgid "Shows the NVDA input composition settings dialog"
+msgstr "Amuestra o dialogo Opcions de redacción de dentrada d'o NVDA"
+
#. Translators: Input help mode message for go to object presentation dialog
command.
msgid "Shows the NVDA object presentation settings dialog"
msgstr "Amuestra o dialogo Presentación d'Obchectos d'o NVDA"
@@ -3523,6 +3828,26 @@ msgstr "Amuestra o dialogo d'opcions d'o modo de
Navegación d'o NVDA"
msgid "Shows the NVDA document formatting settings dialog"
msgstr "Amuestra o dialogo Formatiau de documentos d'o NVDA"

+#. Translators: Input help mode message for opening default dictionary dialog.
+msgid "Shows the NVDA default dictionary dialog"
+msgstr "Amuestra o dialogo Opcions d'o diccionario predeterminau d'o NVDA"
+
+#. Translators: Input help mode message for opening voice-specific dictionary
dialog.
+msgid "Shows the NVDA voice-specific dictionary dialog"
+msgstr "Amuestra o dialogo Diccionario por Voz d'o NVDA"
+
+#. Translators: Input help mode message for opening temporary dictionary.
+msgid "Shows the NVDA temporary dictionary dialog"
+msgstr "Amuestra o dialogo Opcions d'o diccionario temporal d'o NVDA"
+
+#. Translators: Input help mode message for go to punctuation/symbol
pronunciation dialog.
+msgid "Shows the NVDA symbol pronunciation dialog"
+msgstr "Amuestra o dialogo Pronuncia de simbolos d'o NVDA"
+
+#. Translators: Input help mode message for go to input gestures dialog
command.
+msgid "Shows the NVDA input gestures dialog"
+msgstr "Amuestra o dialogo Cenyos de dentrada d'o NVDA"
+
#. Translators: Input help mode message for save current configuration command.
msgid "Saves the current NVDA configuration"
msgstr "Alza a configuración actual d'o NVDA"
@@ -3540,6 +3865,30 @@ msgstr ""
msgid "Activates the NVDA Python Console, primarily useful for development"
msgstr "Activa a Consola Python d'o NVDA, util mas que mas ta desembolicadors"

+#. Translators: Input help mode message for activate manage add-ons command.
+msgid ""
+"Activates the NVDA Add-ons Manager to install and uninstall add-on packages "
+"for NVDA"
+msgstr ""
+"Activa l'administrador de complementos d'o NVDA ta instalar y desinstalar "
+"paquetz de complementos t'o NVDA"
+
+#. Translators: The message announced when disabling speech viewer.
+msgid "speech viewer disabled"
+msgstr "Visualizador d'a Voz desenchegau"
+
+#. Translators: The message announced when enabling speech viewer.
+msgid "speech viewer enabled"
+msgstr "Visualizador d'a Voz enchegau"
+
+#. Translators: Input help mode message for toggle speech viewer command.
+msgid ""
+"Toggles the NVDA Speech viewer, a floating window that allows you to view "
+"all the text that NVDA is currently speaking"
+msgstr ""
+"Conmuta o visualizador d'a voz d'o NVDA, una finestra flotant que te permit "
+"de veyer tot o texto que o NVDA ye charrando actualment"
+
#. Translators: One of the options for tethering braille (see the comment on
"braille tethered to" message for more information).
msgid "review"
msgstr "revisión"
@@ -3693,6 +4042,15 @@ msgstr ""
msgid "Shows the NVDA Configuration Profiles dialog"
msgstr "Amuestra o dialogo de perfils de configuración d'o NVDA"

+#. Translators: Reported when the user attempts math interaction
+#. with something that isn't math.
+msgid "Not math"
+msgstr "No matematico"
+
+#. Translators: Describes a command.
+msgid "Begins interaction with math content"
+msgstr "Empecipia la interacción con o conteniu matematico"
+
#. Translators: The name of a category of NVDA commands.
msgid "Emulated system keyboard keys"
msgstr "Teclas de sistema de teclau emulau"
@@ -6662,7 +7020,7 @@ msgstr "Anunciar os &numeros de linia"
#. If this option is selected, NVDA will cound the leading spaces and tabs of
a line and speak it.
#.
msgid "Report l&ine indentation"
-msgstr "Anunciar a sangría d'a l&ínea"
+msgstr "Anunciar a sangría d'a l&inia"

#. Translators: This message is presented in the document formatting settings
dialogue
#. If this option is selected, NVDA will report paragraph indentation if
available.
@@ -6712,7 +7070,7 @@ msgstr "Anunciar as &zonas"
#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
msgid "Report fra&mes"
-msgstr "Anunciar os &marcos"
+msgstr "Anunciar as &bastidas"

#. Translators: This is the label for a checkbox in the
#. document formatting settings dialog.
@@ -6909,6 +7267,15 @@ msgstr ""
"S'ha produciu una error alzando los cenyos definius por l'usuario - "
"prebablement yes en un sistema de fichers de nomás lectura."

+#. Translators: Describes a command.
+msgid "Exit math interaction"
+msgstr "Salir d'a interacción matematica"
+
+#. Translators: Reported when the user attempts math interaction
+#. but math interaction is not supported.
+msgid "Math interaction not supported."
+msgstr "A interacción matematica no ye suportada."
+
#. Translators: name of the default espeak varient.
msgctxt "espeakVarient"
msgid "none"
@@ -7033,6 +7400,26 @@ msgstr "Escritorio"
msgid "default color"
msgstr "color predeterminada"

+#. Translators: the description for the elements list command in Microsoft
Excel.
+msgid "Presents a list of charts, cells with comments and cells with formulas"
+msgstr ""
+"Presienta una lista de graficos, celdas con comentarios y celdas con formulas"
+
+#. Translators: The label of a radio button to select the type of element
+#. in the browse mode Elements List dialog.
+msgid "&Chart"
+msgstr "Grafi&co"
+
+#. Translators: The label of a radio button to select the type of element
+#. in the browse mode Elements List dialog.
+msgid "C&omment"
+msgstr "C&omentario"
+
+#. Translators: The label of a radio button to select the type of element
+#. in the browse mode Elements List dialog.
+msgid "&Formula"
+msgstr "&Formula"
+
#. Translators: Used to express an address range in excel.
msgid "{start} through {end}"
msgstr "{start} dica {end}"
@@ -7114,6 +7501,640 @@ msgstr "Se son editando os comentarios d'a celda
{address}"
msgid "{firstAddress} {firstContent} through {lastAddress} {lastContent}"
msgstr "{firstAddress} {firstContent} a traviés de {lastAddress} {lastContent}"

+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Area"
+msgstr "Aria 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Stacked Area"
+msgstr "Arias 3D apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "100 percent Stacked Area"
+msgstr "Arias 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Clustered Bar"
+msgstr "Barras 3D agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Stacked Bar"
+msgstr "Barras 3D apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D 100 percent Stacked Bar"
+msgstr "Barras 3D 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Column"
+msgstr "Columnas 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Clustered Column"
+msgstr "Columnas 3D agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Stacked Column"
+msgstr "Columnas 3D apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D 100 percent Stacked Column"
+msgstr "Columnas 3D 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Line"
+msgstr "Linias 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Pie"
+msgstr "Cercular 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Exploded 3D Pie"
+msgstr "Cercular 3D seccionau"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Area"
+msgstr "Arias"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Stacked Area"
+msgstr "Arias apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Clustered Bar"
+msgstr "Barras agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Bar of Pie"
+msgstr "Barra d'o cercular"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Stacked Bar"
+msgstr "Barras apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "100 percent Stacked Bar"
+msgstr "Barras 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Bubble"
+msgstr "Bambolla"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Bubble with 3D effects"
+msgstr "Bambolla con efectos 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Clustered Column"
+msgstr "Columnas agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Stacked Column"
+msgstr "Columnas apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "100 percent Stacked Column"
+msgstr "Columnas 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Clustered Cone Bar"
+msgstr "Barras conicas agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Stacked Cone Bar"
+msgstr "Barras conicas apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Cone Bar"
+msgstr "Barras conicas 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "3D Cone Column"
+msgstr "Columnas 3D conicas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Clustered Cone Column"
+msgstr "Columnas conicas agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Stacked Cone Column"
+msgstr "Columnas conicas apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Cone Column"
+msgstr "Columnas conicas 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Clustered Cylinder Bar"
+msgstr "Barras cilindricas agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Stacked Cylinder Bar"
+msgstr "Barras cilindricas apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Cylinder Bar"
+msgstr "Barras cilindricas 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "3D Cylinder Column"
+msgstr "Columnas 3D cilindricas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Cylinder Column"
+msgstr "Columnas 3D 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Doughnut"
+msgstr "Aniellos"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Exploded Doughnut"
+msgstr "Aniellos seccionaus"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Line"
+msgstr "Linias"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Line with Markers"
+msgstr "Linias con marcadors"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Stacked Line with Markers"
+msgstr "Linias con marcadors apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "100 percent Stacked Line with Markers"
+msgstr "Linias con marcadors 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Stacked Line"
+msgstr "Linias apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "100 percent Stacked Line"
+msgstr "Linias 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Pie"
+msgstr "Cercular"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Exploded Pie"
+msgstr "Cercular seccionau"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Pie of Pie"
+msgstr "Cercular de cerculars"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Clustered Pyramid Bar"
+msgstr "Barras piramidals agrupadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Stacked Pyramid Bar"
+msgstr "Barras piramidals apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Pyramid Bar"
+msgstr "Barras piramidals 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "3D Pyramid Column"
+msgstr "Columnas 3D piramidals"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Clustered Pyramid Column"
+msgstr "Columnas piramidals apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "Stacked Pyramid Column"
+msgstr "Columnas piramidals apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-b22a8bb9-a673-4d7f-b481-aa747c48eb3d
+msgid "100 percent Stacked Pyramid Column"
+msgstr "Columnas piramidals 100 por cient apuyaladas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Radar"
+msgstr "Radial"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Filled Radar"
+msgstr "Radial replén"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Radar with Data Markers"
+msgstr "Radial con marcadors de datos"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "High-Low-Close"
+msgstr "Alto-baixo-zarradura"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Open-High-Low-Close"
+msgstr "Ubridura-alto-baixo-zarradura"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Volume-High-Low-Close"
+msgstr "Volumen-alto-baixo-zarradura"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Volume-Open-High-Low-Close"
+msgstr "Volumen-ubridura-alto-baixo-zarradura"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Surface"
+msgstr "Superficie 3D"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Surface (Top View)"
+msgstr "Superficie (anvista superior)"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Surface (Top View wireframe)"
+msgstr "Superficie (anvista superior d'estructura)"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "3D Surface (wireframe)"
+msgstr "Superficie 3D (estructura)"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Scatter"
+msgstr "Dispersión"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Scatter with Lines"
+msgstr "Dispersión con linias"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Scatter with Lines and No Data Markers"
+msgstr "Dispersión con Linias y sin marcadors de datos"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Scatter with Smoothed Lines"
+msgstr "Dispersión con linias suavezadas"
+
+#. Translators: A type of chart in Microsoft Excel.
+#. See
https://support.office.com/en-in/article/Available-chart-types-a019c053-ba7f-4c46-a09a-82e17f3ee5be
+msgid "Scatter with Smoothed Lines and No Data Markers"
+msgstr "Dispersión con linias suavezadas y sin marcadors de datos"
+
+#. Translators: Message reporting the title and type of a chart.
+msgid "Chart title: {chartTitle}, type: {chartType}"
+msgstr "Titol d'o grafico: {chartTitle}, mena: {chartType}"
+
+#. Translators: Reported when there is no title for an axis in a chart.
+msgid "Not defined"
+msgstr "No definiu"
+
+#. Translators: A type of axis in a chart.
+#. Translators: The category axis in a Microsoft Excel chart.
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "Category"
+msgstr "Categoría"
+
+#. Translators: A type of axis in a chart.
+#. Translators: The value axis in a Microsoft Excel chart.
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "Value"
+msgstr "Valor"
+
+#. Translators: A type of axis in a chart.
+#. Translators: The series axis in a Microsoft Excel chart.
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "Series"
+msgstr "Series"
+
+#. Translators: Message reporting the type and title of an axis in a chart.
+#. For example, this might report "Category axis is month"
+msgid "{axisName} Axis is {axisTitle}"
+msgstr "L'eixe {axisName} ye {axisTitle}"
+
+#. Translators: Indicates that there is 1 series in a chart.
+msgid "There is 1 series in this chart"
+msgstr "Bi ha 1 serie en iste grafico"
+
+#. Translators: Indicates the number of series in a chart where there are
multiple series.
+#, python-format
+msgid "There are total %d series in this chart"
+msgstr "Bi ha un total de %d series en iste grafico"
+
+#. Translators: Specifies the number and name of a series when listing series
in a chart.
+msgid "series {number} {name}"
+msgstr "serie {number} {name}"
+
+#. Translators: Indicates that there are no series in a chart.
+msgid "No Series defined."
+msgstr "No bi ha Series definidas."
+
+#. Translators: A slice in a pie chart.
+msgid "slice"
+msgstr "tallada"
+
+#. Translators: A data point in a line chart.
+msgid "data point"
+msgstr "punto de dato"
+
+#. Translators: A segment of a chart for charts which don't have a specific
name for segments.
+msgid "item"
+msgstr "elemento"
+
+msgid "Series color: {colorName} "
+msgstr "Color d'as series: {colorName} "
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Display Unit Label"
+msgstr "Amostrar a etiqueta d'a unidat"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Major Gridlines"
+msgstr "Linias de quadricula mayors"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Minor Gridlines"
+msgstr "Linias de quadricula menors"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Pivot Chart Drop Zone"
+msgstr "Zona de baixada d'o grafico dinamico"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Pivot Chart Field Button"
+msgstr "Botón de campo d'o grafico dinamico"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Down Bars"
+msgstr "Barras inferiors"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Drop Lines"
+msgstr "Linias de chunión"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Hi Lo Lines"
+msgstr "Linias altas y baixas"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Radar Axis Labels"
+msgstr "Etiquetas d'os eixes radials"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Series Lines"
+msgstr "Linias d'as series"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Up Bars"
+msgstr "Barras superiors"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Corners"
+msgstr "Cantonadas"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Data Table"
+msgstr "Tabla de datos"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Floor"
+msgstr "Plan inferior"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Nothing"
+msgstr "Cosa"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Walls"
+msgstr "Plans laterals"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Data Label"
+msgstr "Etiqueta de datos"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Error Bars"
+msgstr "Barras d'error"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "X Error Bars"
+msgstr "Barras d'errors X"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Y Error Bars"
+msgstr "Barras d'errors Y"
+
+#. Translators: A type of element in a Microsoft Excel chart.
+msgid "Shape"
+msgstr "Forma"
+
+#. Translators: Details about a series in a chart.
+#. For example, this might report "foo series 1 of 2"
+msgid "{seriesName} series {seriesIndex} of {seriesCount}"
+msgstr "{seriesName} series {seriesIndex} de {seriesCount}"
+
+#. Translators: For line charts, indicates no change from the previous data
point on the left
+msgid "no change from point {previousIndex}, "
+msgstr "no bi ha cambeo dende o punto {previousIndex}, "
+
+#. Translators: For line charts, indicates an increase from the previous data
point on the left
+msgid "Increased by {incrementValue} from point {previousIndex}, "
+msgstr "Incrementau en {incrementValue} dende o punto {previousIndex}, "
+
+#. Translators: For line charts, indicates a decrease from the previous data
point on the left
+msgid "decreased by {decrementValue} from point {previousIndex}, "
+msgstr "decrementau en {decrementValue} dende o punto {previousIndex}, "
+
+#. Translators: Specifies the category of a data point.
+#. {categoryAxisTitle} will be replaced with the title of the category axis;
e.g. "Month".
+#. {categoryAxisData} will be replaced with the category itself; e.g.
"January".
+msgid "{categoryAxisTitle} {categoryAxisData}: "
+msgstr "{categoryAxisTitle} {categoryAxisData}: "
+
+#. Translators: Specifies the category of a data point.
+#. {categoryAxisData} will be replaced with the category itself; e.g.
"January".
+msgid "Category {categoryAxisData}: "
+msgstr "Categoría {categoryAxisData}: "
+
+#. Translators: Specifies the value of a data point.
+#. {valueAxisTitle} will be replaced with the title of the value axis; e.g.
"Amount".
+#. {valueAxisData} will be replaced with the value itself; e.g. "1000".
+msgid "{valueAxisTitle} {valueAxisData}"
+msgstr "{valueAxisTitle} {valueAxisData}"
+
+#. Translators: Specifies the value of a data point.
+#. {valueAxisData} will be replaced with the value itself; e.g. "1000".
+msgid "value {valueAxisData}"
+msgstr "valor {valueAxisData}"
+
+#. Translators: Details about a slice of a pie chart.
+#. For example, this might report "fraction 25.25 percent slice 1 of 5"
+msgid ""
+" fraction {fractionValue:.2f} Percent slice {pointIndex} of {pointCount}"
+msgstr ""
+" fracción {fractionValue:.2f} por cient tallada {pointIndex} de {pointCount}"
+
+#. Translators: Details about a segment of a chart.
+#. For example, this might report "column 1 of 5"
+msgid " {segmentType} {pointIndex} of {pointCount}"
+msgstr " {segmentType} {pointIndex} de {pointCount}"
+
+#. Translators: The primary axis group in a Microsoft Excel chart.
+msgid "Primary"
+msgstr "Primario"
+
+#. Translators: The secondary axis group in a Microsoft Excel chart.
+msgid "Secondary"
+msgstr "Secundario"
+
+#. Translators: Details about an axis in a chart.
+msgid "Chart axis, type: {axisType}, group: {axisGroup}, title: {axisTitle}"
+msgstr ""
+"Eixe d'o grafico, mena: {axisType}, grupo: {axisGroup}, Titol: {axisTitle}"
+
+#. Translators: Details about an untitled axis in a chart.
+msgid "Chart axis, type: {axisType}, group: {axisGroup}"
+msgstr "Eixe d'o grafico, mena: {axisType}, grupo: {axisGroup}"
+
+#. Translators: Indicates a chart axis title in Microsoft Excel.
+msgid "Chart axis title"
+msgstr "Titol de l'eixe d'o grafico"
+
+#. Translators: Indicates a trendline in a Microsoft Excel chart.
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "trendline"
+msgstr "linia de tendencia"
+
+#. Translators: Describes the squared symbol used in the label for a trendline
in a Microsoft Excel chart.
+msgid " squared "
+msgstr " quadrau "
+
+#. Translators: Details about a chart title in Microsoft Excel.
+msgid "Chart title: {chartTitle}"
+msgstr "Titol d'o grafico: {chartTitle}"
+
+#. Translators: Indicates an untitled chart in Microsoft Excel.
+msgid "Untitled chart"
+msgstr "Grafico sin titol"
+
+#. Translators: Details about the chart area in a Microsoft Excel chart.
+msgid ""
+"Chart area, height: {chartAreaHeight}, width: {chartAreaWidth}, top: "
+"{chartAreaTop}, left: {chartAreaLeft}"
+msgstr ""
+"Aria d'o grafico, altaria: {chartAreaHeight}, amplaria: {chartAreaWidth}, "
+"alto: {chartAreaTop}, cucha: {chartAreaLeft}"
+
+#. Translators: Indicates the chart area of a Microsoft Excel chart.
+msgid "Chart area "
+msgstr "Aria d'o grafico"
+
+#. Translators: Details about the plot area of a Microsoft Excel chart.
+msgid ""
+"Plot area, inside height: {plotAreaInsideHeight:.0f}, inside width: "
+"{plotAreaInsideWidth:.0f}, inside top: {plotAreaInsideTop:.0f}, inside left: "
+"{plotAreaInsideLeft:.0f}"
+msgstr ""
+"Aria d'o trazau, altaria interior: {plotAreaInsideHeight:.0f}, amplaria "
+"interior: {plotAreaInsideWidth:.0f}, alto interior: {plotAreaInsideTop:.0f}, "
+"cucha interior: {plotAreaInsideLeft:.0f}"
+
+#. Translators: Indicates the plot area of a Microsoft Excel chart.
+msgid "Plot area "
+msgstr "Aria d'o trazau"
+
+#. Translators: Indicates the legend in a Microsoft Excel chart.
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "Legend"
+msgstr "Lechenda"
+
+#. Translators: Indicates that there is no legend in a Microsoft Excel chart.
+msgid "No legend"
+msgstr "Sin lechenda"
+
+#. Translators: Details about a legend entry for a series in a Microsoft Excel
chart.
+#. For example, this might report "Legend entry for series Temperature 1 of 2"
+msgid "Legend entry for series {seriesName} {seriesIndex} of {seriesCount}"
+msgstr ""
+"Dentrada en a lechenda ta serie {seriesName}, {seriesIndex} de {seriesCount}"
+
+#. Translators: Details about a legend key for a series in a Microsoft Excel
chart.
+#. For example, this might report "Legend key for series Temperature 1 of 2"
+#. See
https://support.office.com/en-us/article/Excel-Glossary-53b6ce43-1a9f-4ac2-a33c-d6f64ea2d1fc?CorrelationId=44f003e6-453a-4b14-a9a6-3fb5287109c7&ui=en-US&rs=en-US&ad=US
+msgid "Legend key for Series {seriesName} {seriesIndex} of {seriesCount}"
+msgstr ""
+"Clau en a lechenda ta series {seriesName} {seriesIndex} de {seriesCount}"
+
#. Translators: a Microsoft Word revision type (inserted content)
msgid "insertion"
msgstr "inserción"
@@ -7210,7 +8231,7 @@ msgid "Primary header"
msgstr "Capitero de pachina prencipal"

msgid "Text frame"
-msgstr "Marco de texto"
+msgstr "Bastida de texto"

msgid "comment: {text} by {author} on {date}"
msgstr "comentario: {text} por {author} a {date}"
@@ -7406,9 +8427,46 @@ msgstr "Serie d'a HIMS Braille Sense/Braille EDGE"
msgid "HIMS SyncBraille"
msgstr "HIMS SyncBraille"

+#~ msgid "%s"
+#~ msgstr "%s"
+
+#~ msgid "{} Series {} of {}"
+#~ msgstr "{} series {} de {}"
+
+#~ msgid "{} {}: "
+#~ msgstr "{} {}: "
+
+#~ msgid "{} {}"
+#~ msgstr "{} {}"
+
+#~ msgid "value {}"
+#~ msgstr "valor {}"
+
+#~ msgid " {} {} of {}"
+#~ msgstr " {} {} de {}"
+
+#~ msgid "none"
+#~ msgstr "garra"
+
+#~ msgid " trendline {} "
+#~ msgstr " linia de tendencia {} "
+
+#~ msgid ""
+#~ "Chart area height equals {}, width equals {}, top equals {}, left equals "
+#~ "{}"
+#~ msgstr ""
+#~ "Altaria de l'aria d'o grafico igual {}, amplaria igual {}, alto igual {}, "
+#~ "cucha igual {}"
+
+#~ msgid "equation"
+#~ msgstr "equación"
+
#~ msgid "Presents a list of links, headings or landmarks"
#~ msgstr "Presienta una lista de vinclos, capiters u zonas"

+#~ msgid "Slovak"
+#~ msgstr "Eslovaco"
+
#~ msgid "grey"
#~ msgstr "grisa"

@@ -7498,9 +8556,6 @@ msgstr "HIMS SyncBraille"
#~ msgid "Set row header column"
#~ msgstr "Configurar a columna de capiters de ringlera"

-#~ msgid "Cleared row header column"
-#~ msgstr "S'ha limpiau a columna de capiters de ringlera"
-
#~ msgid ""
#~ "Pressing once will set the current column as the column where row headers "
#~ "should be found. Pressing twice clears the setting."

diff --git a/source/locale/an/symbols.dic b/source/locale/an/symbols.dic
index a02cd93..6dc368a 100644
--- a/source/locale/an/symbols.dic
+++ b/source/locale/an/symbols.dic
@@ -21,9 +21,9 @@ complexSymbols:
: phrase ending (?<=[^\s:]):(?=\s|$)

# Others
-decimal point (?<=\d)\.(?=\d)
+decimal point (?<![^\d -])\.(?=\d)
in-word - (?<=[^\W_])[-]
-negative number (?<!\w)-(?=[$£€¥]?\d)
+negative number (?<!\w)-(?=[$£€¥.]?\d)
dates /
((?<=\b\d\d)\/(?=\d\d/(\d{2}|\d{4})\b))|((?<=\b\d\d/\d\d)\/(?=(\d{2}|\d{4})\b))

symbols:

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

https://bitbucket.org/nvdaaddonteam/nvda/commits/c8ce76cf5938/
Changeset: c8ce76cf5938
Branch: None
User: mdcurran
Date: 2015-05-29 02:42:48+00:00
Summary: Merge branch 't5116' into next. Incubates #5116

Affected #: 1 file

diff --git a/source/appModules/explorer.py b/source/appModules/explorer.py
index 1ff91bb..a606376 100644
--- a/source/appModules/explorer.py
+++ b/source/appModules/explorer.py
@@ -17,6 +17,10 @@ from NVDAObjects.window import Window
from NVDAObjects.IAccessible import sysListView32, IAccessible
from NVDAObjects.UIA import UIA

+# Suppress incorrect Win 10 Task switching window focus
+class MultitaskingViewFrameWindow(UIA):
+ shouldAllowUIAFocusEvent=False
+
# support for Win8 start screen search suggestions.
class SuggestionListItem(UIA):

@@ -175,6 +179,8 @@ class AppModule(appModuleHandler.AppModule):
clsList.insert(0, ImmersiveLauncher)
elif uiaClassName=="ListViewItem" and
obj.UIAElement.cachedAutomationId.startswith('Suggestion_'):
clsList.insert(0,SuggestionListItem)
+ elif uiaClassName=="MultitaskingViewFrame" and
role==controlTypes.ROLE_WINDOW:
+ clsList.insert(0,MultitaskingViewFrameWindow)

def event_NVDAObject_init(self, obj):
windowClass = obj.windowClassName


https://bitbucket.org/nvdaaddonteam/nvda/commits/db8178259ed3/
Changeset: db8178259ed3
Branch: None
User: josephsl
Date: 2015-06-03 00:30:48+00:00
Summary: UIA: Support toast announcements in Windows 10. re #5136

Affected #: 1 file

diff --git a/source/NVDAObjects/UIA/__init__.py
b/source/NVDAObjects/UIA/__init__.py
index 68a12dd..794fd38 100644
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -2,7 +2,7 @@
#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) 2009-2012 NV Access Limited
+#Copyright (C) 2009-2015 NV Access Limited

from ctypes import byref
from ctypes.wintypes import POINT, RECT
@@ -294,7 +294,9 @@ class UIA(Window):
UIAClassName=self.UIAElement.cachedClassName
if UIAClassName=="WpfTextView":
clsList.append(WpfTextView)
- elif UIAClassName=="ToastContentHost" and
UIAControlType==UIAHandler.UIA_ToolTipControlTypeId:
+ # #5136: Windows 8.x and Windows 10 uses different window class
and other attributes for toast notifications.
+ elif ((UIAClassName=="ToastContentHost" and
UIAControlType==UIAHandler.UIA_ToolTipControlTypeId) #Windows 8.x
+ or (self.windowClassName=="Windows.UI.Core.CoreWindow" and
UIAControlType==UIAHandler.UIA_WindowControlTypeId and
self.UIAElement.cachedAutomationId=="NormalToastView")): # Windows 10
clsList.append(Toast)
if UIAControlType==UIAHandler.UIA_ProgressBarControlTypeId:
clsList.append(ProgressBar)


https://bitbucket.org/nvdaaddonteam/nvda/commits/faffb8a8304d/
Changeset: faffb8a8304d
Branch: None
User: mdcurran
Date: 2015-06-09 23:19:17+00:00
Summary: Merge branch 't5049' into next. Incubates #5049

Affected #: 5 files

diff --git a/source/NVDAObjects/UIA/__init__.py
b/source/NVDAObjects/UIA/__init__.py
index 68a12dd..06c4a44 100644
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -693,6 +693,20 @@ class UIA(Window):
parentCount+=1
return info

+ def _get_controllerFor(self):
+
e=self.UIAElement.getCurrentPropertyValue(UIAHandler.UIA_ControllerForPropertyId)
+ if UIAHandler.handler.clientObject.checkNotSupported(e):
+ return None
+ a=e.QueryInterface(UIAHandler.IUIAutomationElementArray)
+ objList=[]
+ for index in xrange(a.length):
+ e=a.getElement(index)
+
e=e.buildUpdatedCache(UIAHandler.handler.baseCacheRequest)
+ obj=UIA(UIAElement=e)
+ if obj:
+ objList.append(obj)
+ return objList
+
def event_UIA_elementSelected(self):
self.event_stateChange()


diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py
index 0a46dc0..c84c594 100644
--- a/source/NVDAObjects/__init__.py
+++ b/source/NVDAObjects/__init__.py
@@ -391,6 +391,10 @@ class NVDAObject(baseObject.ScriptableObject):
"""
return ""

+ def _get_controllerFor(self):
+ """Retreaves the object/s that this object controls."""
+ return []
+
def _get_actionCount(self):
"""Retreaves the number of actions supported by this object."""
return 0

diff --git a/source/appModules/searchui.py b/source/appModules/searchui.py
new file mode 100644
index 0000000..a6548d1
--- /dev/null
+++ b/source/appModules/searchui.py
@@ -0,0 +1,28 @@
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2015 NV Access Limited
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+import appModuleHandler
+import controlTypes
+import api
+import speech
+from NVDAObjects.UIA import UIA
+
+# Windows 10 Search UI suggestion list item
+class SuggestionListItem(UIA):
+
+ role=controlTypes.ROLE_LISTITEM
+
+ def event_UIA_elementSelected(self):
+ focusControllerFor=api.getFocusObject().controllerFor
+ if len(focusControllerFor)>0 and
focusControllerFor[0].appModule is self.appModule:
+ speech.cancelSpeech()
+ api.setNavigatorObject(self)
+ self.reportFocus()
+
+class AppModule(appModuleHandler.AppModule):
+
+ def chooseNVDAObjectOverlayClasses(self,obj,clsList):
+ if isinstance(obj,UIA) and obj.role==controlTypes.ROLE_DATAITEM
and isinstance(obj.parent,UIA) and obj.parent.role==controlTypes.ROLE_LIST:
+ clsList.insert(0,SuggestionListItem)

diff --git a/source/versionInfo.py b/source/versionInfo.py
index 966022c..a0ad2e2 100644
--- a/source/versionInfo.py
+++ b/source/versionInfo.py
@@ -31,7 +31,7 @@ def _updateVersionFromVCS():
# Otherwise, py2exe will break.
name="NVDA"
longName=_("NonVisual Desktop Access")
-version="2015.2dev"
+version="2015.3dev"
publisher="unknown"
updateVersionType=None
try:

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 827957e..7932e91 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -3,6 +3,12 @@

%!includeconf: ../changes.t2tconf

+= 2015.3 =
+
+== New Features ==
+- The existance of spelling errors is announced in editable fields for
Internet Explorer and other MSHTML controls. (#4174)
+
+
= 2015.2 =
Highlights of this release include the ability to read charts in Microsoft
Excel and support for reading and interactive navigation of mathematical
content.



https://bitbucket.org/nvdaaddonteam/nvda/commits/b3c8514b7c99/
Changeset: b3c8514b7c99
Branch: None
User: mdcurran
Date: 2015-06-09 23:33:19+00:00
Summary: Merge branch 'toggleSingleLetterNav' into next. Incubates #3203

Affected #: 2 files

diff --git a/source/browseMode.py b/source/browseMode.py
index a071c1e..7450644 100644
--- a/source/browseMode.py
+++ b/source/browseMode.py
@@ -176,6 +176,29 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
def script_trapNonCommandGesture(self,gesture):
winsound.PlaySound("default",1)

+ singleLetterNavEnabled=True #: Whether single letter navigation scripts
should be active (true) or if these letters should fall to the application.
+
+ def getAlternativeScript(self,gesture,script):
+ if self.passThrough or not gesture.isCharacter:
+ return script
+ if not self.singleLetterNavEnabled:
+ return None
+ if not script and self.shouldTrapNonCommandGestures:
+ script=self.script_trapNonCommandGesture
+ return script
+
+ def script_toggleSingleLetterNav(self,gesture):
+ if self.singleLetterNavEnabled:
+ self.singleLetterNavEnabled=False
+ # Translators: single letter navigation in browse mode
is turned off.
+ ui.message(_("Single letter navigation off"))
+ else:
+ self.singleLetterNavEnabled=True
+ # Translators: single letter navigation in browse mode
is turned on.
+ ui.message(_("Single letter navigation on"))
+ # Translators: the description for the toggleSingleLetterNavigation
command in browse mode.
+ script_toggleSingleLetterNav.__doc__=_("Switches single letter
navigation mode on and off. When on single letter keys in browse mode jump to
various kinds of elements on the page, and when off, these keys are passed to
the application.")
+
def _get_ElementsListDialog(self):
return ElementsListDialog

@@ -251,6 +274,7 @@ class
BrowseModeTreeInterceptor(treeInterceptorHandler.TreeInterceptor):
"kb:NVDA+f7": "elementsList",
"kb:enter": "activatePosition",
"kb:space": "activatePosition",
+ "kb:NVDA+shift+space":"toggleSingleLetterNav",
}

# Add quick navigation scripts.

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 70070e6..668c074 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -97,10 +97,9 @@ def findScript(gesture):
treeInterceptor = focus.treeInterceptor
if treeInterceptor and treeInterceptor.isReady:
func = _getObjScript(treeInterceptor, gesture, globalMapScripts)
+ func=treeInterceptor.getAlternativeScript(gesture,func)
if func and (not treeInterceptor.passThrough or
getattr(func,"ignoreTreeInterceptorPassThrough",False)):
return func
- elif gesture.isCharacter and not treeInterceptor.passThrough
and treeInterceptor.shouldTrapNonCommandGestures:
- return treeInterceptor.script_trapNonCommandGesture

# NVDAObject level.
func = _getObjScript(focus, gesture, globalMapScripts)


https://bitbucket.org/nvdaaddonteam/nvda/commits/342973d119a4/
Changeset: 342973d119a4
Branch: None
User: mdcurran
Date: 2015-06-15 20:40:58+00:00
Summary: scriptHandler: getAlternativeScript is only on
BrowseModeTreeInterceptors.

Affected #: 1 file

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 668c074..b9d0845 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -97,7 +97,9 @@ def findScript(gesture):
treeInterceptor = focus.treeInterceptor
if treeInterceptor and treeInterceptor.isReady:
func = _getObjScript(treeInterceptor, gesture, globalMapScripts)
- func=treeInterceptor.getAlternativeScript(gesture,func)
+ from browseMode import BrowseModeTreeInterceptor
+ if isinstance(treeInterceptor,BrowseModeTreeInterceptor):
+ func=treeInterceptor.getAlternativeScript(gesture,func)
if func and (not treeInterceptor.passThrough or
getattr(func,"ignoreTreeInterceptorPassThrough",False)):
return func



https://bitbucket.org/nvdaaddonteam/nvda/commits/1d9596fa76d8/
Changeset: 1d9596fa76d8
Branch: None
User: mdcurran
Date: 2015-06-15 20:41:34+00:00
Summary: Merge branch 'toggleSingleLetterNav' into next. Fixes #5151.
Incubates #3203.

Affected #: 1 file

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 668c074..b9d0845 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -97,7 +97,9 @@ def findScript(gesture):
treeInterceptor = focus.treeInterceptor
if treeInterceptor and treeInterceptor.isReady:
func = _getObjScript(treeInterceptor, gesture, globalMapScripts)
- func=treeInterceptor.getAlternativeScript(gesture,func)
+ from browseMode import BrowseModeTreeInterceptor
+ if isinstance(treeInterceptor,BrowseModeTreeInterceptor):
+ func=treeInterceptor.getAlternativeScript(gesture,func)
if func and (not treeInterceptor.passThrough or
getattr(func,"ignoreTreeInterceptorPassThrough",False)):
return func



https://bitbucket.org/nvdaaddonteam/nvda/commits/c5e59ead8c46/
Changeset: c5e59ead8c46
Branch: None
User: jteh
Date: 2015-06-16 07:16:39+00:00
Summary: Merge branch 't3541' into next

Incubates #3541.

Affected #: 1 file

diff --git a/source/brailleDisplayDrivers/baum.py
b/source/brailleDisplayDrivers/baum.py
index 71c15b9..b7028fc 100644
--- a/source/brailleDisplayDrivers/baum.py
+++ b/source/brailleDisplayDrivers/baum.py
@@ -3,7 +3,7 @@
#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-2013 NV Access Limited
+#Copyright (C) 2010-2015 NV Access Limited

import time
from collections import OrderedDict
@@ -246,7 +246,12 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver):
# Press.
# This begins a new key combination.
self._ignoreKeyReleases = False
- self._keysDown[command] = arg
+ if arg > 0:
+ self._keysDown[command] = arg
+ elif command in self._keysDown:
+ # All keys in this group have been released.
+ # #3541: Remove this group so it doesn't count
as a group with keys down.
+ del self._keysDown[command]

elif command == BAUM_POWERDOWN:
log.debug("Power down")


https://bitbucket.org/nvdaaddonteam/nvda/commits/56fc89467601/
Changeset: 56fc89467601
Branch: None
User: jteh
Date: 2015-06-17 04:19:08+00:00
Summary: Merge branch 't3541' into next: Minor cosmetic tweaks.

Incubates #3541.

Affected #: 1 file

diff --git a/source/brailleDisplayDrivers/baum.py
b/source/brailleDisplayDrivers/baum.py
index b7028fc..348af91 100644
--- a/source/brailleDisplayDrivers/baum.py
+++ b/source/brailleDisplayDrivers/baum.py
@@ -227,8 +227,12 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver):
if command == BAUM_CELL_COUNT:
self.numCells = ord(arg)
elif command == BAUM_DEVICE_ID:
- self._deviceID = arg
-
+ if arg == "Refreshabraille ":
+ # For most Baum devices, the argument is 16
bytes,
+ # but it is 18 bytes for the Refreshabraille.
+ arg += self._ser.read(2)
+ # Short ids can be padded with either nulls or spaces.
+ self._deviceID = arg.rstrip("\0 ")
elif command in KEY_NAMES:
arg = sum(ord(byte) << offset * 8 for offset, byte in
enumerate(arg))
if arg < self._keysDown.get(command, 0):


https://bitbucket.org/nvdaaddonteam/nvda/commits/a9576724a381/
Changeset: a9576724a381
Branch: None
User: mdcurran
Date: 2015-06-18 03:19:22+00:00
Summary: Merge branch 't5116' into next. Incubates #5116

Affected #: 1 file

diff --git a/source/appModules/explorer.py b/source/appModules/explorer.py
index a606376..a3defd9 100644
--- a/source/appModules/explorer.py
+++ b/source/appModules/explorer.py
@@ -21,6 +21,15 @@ from NVDAObjects.UIA import UIA
class MultitaskingViewFrameWindow(UIA):
shouldAllowUIAFocusEvent=False

+# suppress focus ancestry for task switching list items if alt is held down
(alt+tab)
+class MultitaskingViewFrameListItem(UIA):
+
+ def _get_container(self):
+ if winUser.getAsyncKeyState(winUser.VK_MENU)&32768:
+ return api.getDesktopObject()
+ else:
+ return
super(MultitaskingViewFrameListItem,self).container
+
# support for Win8 start screen search suggestions.
class SuggestionListItem(UIA):

@@ -181,6 +190,8 @@ class AppModule(appModuleHandler.AppModule):
clsList.insert(0,SuggestionListItem)
elif uiaClassName=="MultitaskingViewFrame" and
role==controlTypes.ROLE_WINDOW:
clsList.insert(0,MultitaskingViewFrameWindow)
+ elif obj.windowClassName=="MultitaskingViewFrame" and
role==controlTypes.ROLE_LISTITEM:
+ clsList.insert(0,MultitaskingViewFrameListItem)

def event_NVDAObject_init(self, obj):
windowClass = obj.windowClassName


https://bitbucket.org/nvdaaddonteam/nvda/commits/e3f5b7a687b4/
Changeset: e3f5b7a687b4
Branch: None
User: mdcurran
Date: 2015-06-19 19:10:12+00:00
Summary: Merge branch 'master' into next

Affected #: 1 file

diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t
index 7932e91..76b04f0 100644
--- a/user_docs/en/changes.t2t
+++ b/user_docs/en/changes.t2t
@@ -7,6 +7,13 @@

== New Features ==
- The existance of spelling errors is announced in editable fields for
Internet Explorer and other MSHTML controls. (#4174)
+- Many more unicode math symbols are now spoken when they appear in text.
(#3805)
+
+
+== Bug Fixes ==
+- In browse mode for Internet Explorer and other MSHTML controls, quick
navigation by form field no longer incorrectly includes presentational list
items. (#4204)
+- In Firefox, NVDA no longer tries to create a description for ARIA tab panels
based on all text inside. (#4638)
+- In Internet Explorer and other MSHTML controls, tabbing into sections,
articles or dialogs no longer reports all contents of the container as its
name. (#5021, #5025)


= 2015.2 =


https://bitbucket.org/nvdaaddonteam/nvda/commits/43f524458af2/
Changeset: 43f524458af2
Branch: None
User: mdcurran
Date: 2015-06-19 19:59:59+00:00
Summary: MSHTML vbufBackend: force an instant update of the content for
onfocus events in case the focus moves to something that was newly
created/changed.

Affected #: 1 file

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index b017901..c8f7bf3 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -127,6 +127,9 @@ class CDispatchChangeSink : public IDispatch {
this->storageNode->backend->forceUpdate();
}
return S_OK;
+ } else if(dispIdMember==DISPID_EVMETH_ONFOCUS) {
+ this->storageNode->backend->forceUpdate();
+ return S_OK;
}
return E_FAIL;
}


https://bitbucket.org/nvdaaddonteam/nvda/commits/5cfc707f3e3b/
Changeset: 5cfc707f3e3b
Branch: None
User: mdcurran
Date: 2015-06-19 20:00:44+00:00
Summary: Merge branch 't5040' into next. Incubates #5040

Affected #: 1 file

diff --git a/nvdaHelper/vbufBackends/mshtml/node.cpp
b/nvdaHelper/vbufBackends/mshtml/node.cpp
index b017901..c8f7bf3 100755
--- a/nvdaHelper/vbufBackends/mshtml/node.cpp
+++ b/nvdaHelper/vbufBackends/mshtml/node.cpp
@@ -127,6 +127,9 @@ class CDispatchChangeSink : public IDispatch {
this->storageNode->backend->forceUpdate();
}
return S_OK;
+ } else if(dispIdMember==DISPID_EVMETH_ONFOCUS) {
+ this->storageNode->backend->forceUpdate();
+ return S_OK;
}
return E_FAIL;
}


https://bitbucket.org/nvdaaddonteam/nvda/commits/ebca71200604/
Changeset: ebca71200604
Branch: None
User: mdcurran
Date: 2015-06-22 04:47:09+00:00
Summary: InputGesture.execute: if an intercepted command script (script
that sends the gesture it intercepts) is queued and or has not yet completed
its execution, queue any further gestures that do not have a script via a fake
script that just sends the gesture. this ensures that input stays in order even
if it was delayed by NVDA.

Affected #: 2 files

diff --git a/source/inputCore.py b/source/inputCore.py
index 5b62510..ae72131 100644
--- a/source/inputCore.py
+++ b/source/inputCore.py
@@ -434,6 +434,12 @@ class InputManager(baseObject.AutoPropertyObject):

gesture.reportExtra()

+ # #2953: if an intercepted command Script (script that sends a
gesture) is queued
+ # then queue all following gestures (that don't have a script)
with a fake script so that they remain in order.
+ if not script and
scriptHandler._numUncompleteInterceptedCommandScripts:
+ script=lambda gesture: gesture.send()
+
+
if script:
scriptHandler.queueScript(script, gesture)
return

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index 70070e6..83e73d0 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -19,6 +19,7 @@ import globalPluginHandler
import braille

_numScriptsQueued=0 #Number of scripts that are queued to be executed
+_numUncompleteInterceptedCommandScripts=0 #Number of scripts (that send
gestures on) that are queued to be executed, or are currently being executed
_lastScriptTime=0 #Time in MS of when the last script was executed
_lastScriptRef=None #Holds a weakref to the last script that was executed
_lastScriptCount=0 #The amount of times the last script was repeated
@@ -132,14 +133,21 @@ def getScriptLocation(script):
if name in cls.__dict__:
return "%s.%s"%(cls.__module__,cls.__name__)

+def _isInterceptedCommandScript(script):
+ return not getattr(script,'__doc__',None)
+
def _queueScriptCallback(script,gesture):
- global _numScriptsQueued
+ global _numScriptsQueued, _numUncompleteInterceptedCommandScripts
_numScriptsQueued-=1
executeScript(script,gesture)
+ if _isInterceptedCommandScript(script):
+ _numUncompleteInterceptedCommandScripts-=1

def queueScript(script,gesture):
- global _numScriptsQueued
+ global _numScriptsQueued, _numUncompleteInterceptedCommandScripts
_numScriptsQueued+=1
+ if _isInterceptedCommandScript(script):
+ _numUncompleteInterceptedCommandScripts+=1

queueHandler.queueFunction(queueHandler.eventQueue,_queueScriptCallback,script,gesture)

def willSayAllResume(gesture):


https://bitbucket.org/nvdaaddonteam/nvda/commits/46d0a2e10da9/
Changeset: 46d0a2e10da9
Branch: None
User: mdcurran
Date: 2015-06-22 04:50:31+00:00
Summary: Merge branch 't2953' into next. Incubates #2953

Affected #: 2 files

diff --git a/source/inputCore.py b/source/inputCore.py
index 5b62510..ae72131 100644
--- a/source/inputCore.py
+++ b/source/inputCore.py
@@ -434,6 +434,12 @@ class InputManager(baseObject.AutoPropertyObject):

gesture.reportExtra()

+ # #2953: if an intercepted command Script (script that sends a
gesture) is queued
+ # then queue all following gestures (that don't have a script)
with a fake script so that they remain in order.
+ if not script and
scriptHandler._numUncompleteInterceptedCommandScripts:
+ script=lambda gesture: gesture.send()
+
+
if script:
scriptHandler.queueScript(script, gesture)
return

diff --git a/source/scriptHandler.py b/source/scriptHandler.py
index b9d0845..9a432a0 100644
--- a/source/scriptHandler.py
+++ b/source/scriptHandler.py
@@ -19,6 +19,7 @@ import globalPluginHandler
import braille

_numScriptsQueued=0 #Number of scripts that are queued to be executed
+_numUncompleteInterceptedCommandScripts=0 #Number of scripts (that send
gestures on) that are queued to be executed, or are currently being executed
_lastScriptTime=0 #Time in MS of when the last script was executed
_lastScriptRef=None #Holds a weakref to the last script that was executed
_lastScriptCount=0 #The amount of times the last script was repeated
@@ -133,14 +134,21 @@ def getScriptLocation(script):
if name in cls.__dict__:
return "%s.%s"%(cls.__module__,cls.__name__)

+def _isInterceptedCommandScript(script):
+ return not getattr(script,'__doc__',None)
+
def _queueScriptCallback(script,gesture):
- global _numScriptsQueued
+ global _numScriptsQueued, _numUncompleteInterceptedCommandScripts
_numScriptsQueued-=1
executeScript(script,gesture)
+ if _isInterceptedCommandScript(script):
+ _numUncompleteInterceptedCommandScripts-=1

def queueScript(script,gesture):
- global _numScriptsQueued
+ global _numScriptsQueued, _numUncompleteInterceptedCommandScripts
_numScriptsQueued+=1
+ if _isInterceptedCommandScript(script):
+ _numUncompleteInterceptedCommandScripts+=1

queueHandler.queueFunction(queueHandler.eventQueue,_queueScriptCallback,script,gesture)

def willSayAllResume(gesture):

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

--

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

Other related posts: