Skip to content

Commit eadfe84

Browse files
authored
Merge 741028c into 3df7605
2 parents 3df7605 + 741028c commit eadfe84

11 files changed

Lines changed: 256 additions & 101 deletions

File tree

nvdaHelper/remote/WinWord/Constants.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2016 NVDA contributers.
4+
Copyright 2016-2023 NVDA contributors.
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -186,10 +186,12 @@ constexpr int wdMaximumNumberOfColumns = 18;
186186
constexpr int wdHorizontalPositionRelativeToPage = 5;
187187

188188
// WdParagraphAlignment Enumeration
189+
// (see https://docs.microsoft.com/en-us/office/vba/api/word.wdparagraphalignment)
189190
constexpr int wdAlignParagraphLeft = 0;
190191
constexpr int wdAlignParagraphCenter = 1;
191192
constexpr int wdAlignParagraphRight = 2;
192193
constexpr int wdAlignParagraphJustify = 3;
194+
constexpr int wdAlignParagraphDistribute = 4;
193195

194196
// WdLanguageID Enumeration
195197
constexpr int wdLanguageNone = 0; //&H0

nvdaHelper/remote/winword.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This file is a part of the NVDA project.
33
URL: http://www.nvda-project.org/
4-
Copyright 2006-2010 NVDA contributers.
4+
Copyright 2006-2023 NVDA contributors.
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License version 2.0, as published by
77
the Free Software Foundation.
@@ -561,7 +561,10 @@ void generateXMLAttribsForFormatting(IDispatch* pDispatchRange, int startOffset,
561561
formatAttribsStream<<L"text-align=\"right\" ";
562562
break;
563563
case wdAlignParagraphJustify:
564-
formatAttribsStream<<L"text-align=\"justified\" ";
564+
formatAttribsStream<<L"text-align=\"justify\" ";
565+
break;
566+
case wdAlignParagraphDistribute:
567+
formatAttribsStream<<L"text-align=\"distribute\" ";
565568
break;
566569
}
567570
}

source/NVDAObjects/IAccessible/__init__.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import config
5151
import controlTypes
5252
from controlTypes import TextPosition
53-
from controlTypes.formatFields import FontSize
53+
from controlTypes.formatFields import FontSize, TextAlign
5454
from NVDAObjects.window import Window
5555
from NVDAObjects import NVDAObject, NVDAObjectTextInfo, InvalidNVDAObject
5656
import NVDAObjects.JAB
@@ -86,11 +86,23 @@ def getNVDAObjectFromPoint(x,y):
8686
FORMAT_OBJECT_ATTRIBS = frozenset({"text-align"})
8787
def normalizeIA2TextFormatField(formatField):
8888
try:
89-
textAlign=formatField.pop("text-align")
89+
val = formatField.pop("text-align")
9090
except KeyError:
9191
textAlign=None
92+
else:
93+
mozillaTextAlign = {
94+
'-moz-left': 'left',
95+
'-moz-center': 'center',
96+
'-moz-right': 'right',
97+
}
98+
val = mozillaTextAlign.get(val, val)
99+
try:
100+
textAlign = TextAlign(val)
101+
except ValueError:
102+
log.debugWarning(f'Unsupported value for text-align attribute: "{val}"')
103+
textAlign = None
92104
if textAlign:
93-
formatField["text-align"]=textAlign
105+
formatField["text-align"] = textAlign
94106
try:
95107
fontWeight=formatField.pop("font-weight")
96108
except KeyError:

source/NVDAObjects/UIA/__init__.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import UIAHandler.customProps
2525
import UIAHandler.customAnnotations
2626
import controlTypes
27-
from controlTypes import TextPosition
27+
from controlTypes import TextPosition, TextAlign
2828
import config
2929
import speech
3030
import api
@@ -71,6 +71,13 @@
7171
UIAHandler.UIA_IndentationTrailingAttributeId,
7272
}
7373

74+
textAlignLabels = {
75+
UIAHandler.HorizontalTextAlignment_Left: TextAlign.LEFT,
76+
UIAHandler.HorizontalTextAlignment_Centered: TextAlign.CENTER,
77+
UIAHandler.HorizontalTextAlignment_Right: TextAlign.RIGHT,
78+
UIAHandler.HorizontalTextAlignment_Justified: TextAlign.JUSTIFY,
79+
}
80+
7481

7582
class UIATextInfo(textInfos.TextInfo):
7683
_rangeObj: IUIAutomationTextRangeT
@@ -270,19 +277,13 @@ def _getFormatFieldAtRange( # noqa: C901
270277
if formatConfig["reportParagraphIndentation"]:
271278
formatField.update(self._getFormatFieldIndent(fetcher, ignoreMixedValues=ignoreMixedValues))
272279
if formatConfig["reportAlignment"]:
273-
val=fetcher.getValue(UIAHandler.UIA_HorizontalTextAlignmentAttributeId,ignoreMixedValues=ignoreMixedValues)
274-
if val==UIAHandler.HorizontalTextAlignment_Left:
275-
val="left"
276-
elif val==UIAHandler.HorizontalTextAlignment_Centered:
277-
val="center"
278-
elif val==UIAHandler.HorizontalTextAlignment_Right:
279-
val="right"
280-
elif val==UIAHandler.HorizontalTextAlignment_Justified:
281-
val="justify"
282-
else:
283-
val=None
284-
if val:
285-
formatField['text-align']=val
280+
val = fetcher.getValue(
281+
UIAHandler.UIA_HorizontalTextAlignmentAttributeId,
282+
ignoreMixedValues=ignoreMixedValues,
283+
)
284+
textAlign = textAlignLabels.get(val)
285+
if textAlign:
286+
formatField['text-align'] = textAlign
286287
if formatConfig["reportColor"]:
287288
val=fetcher.getValue(UIAHandler.UIA_BackgroundColorAttributeId,ignoreMixedValues=ignoreMixedValues)
288289
if isinstance(val,int):

source/NVDAObjects/window/edit.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import textInfos
2929
import textInfos.offsets
3030
import controlTypes
31-
from controlTypes import TextPosition
31+
from controlTypes import TextPosition, TextAlign
3232
from . import Window
3333
from ..behaviors import EditableTextWithAutoSelectDetection
3434
import watchdog
@@ -522,13 +522,16 @@ def _getFormatFieldAtRange(self, textRange, formatConfig): # noqa: C901
522522
paraFormatObj = textRange.para
523523
alignment=paraFormatObj.alignment
524524
if alignment==comInterfaces.tom.tomAlignLeft:
525-
formatField["text-align"]="left"
525+
formatField["text-align"] = TextAlign.LEFT
526526
elif alignment==comInterfaces.tom.tomAlignCenter:
527-
formatField["text-align"]="center"
527+
formatField["text-align"] = TextAlign.CENTER
528528
elif alignment==comInterfaces.tom.tomAlignRight:
529-
formatField["text-align"]="right"
529+
formatField["text-align"] = TextAlign.RIGHT
530530
elif alignment==comInterfaces.tom.tomAlignJustify:
531-
formatField["text-align"]="justify"
531+
formatField["text-align"] = TextAlign.JUSTIFY
532+
else:
533+
log.debugWarning(f'Unsupported text-align: {alignment}')
534+
formatField["text-align"] = TextAlign.UNDEFINED
532535
if formatConfig["reportLineNumber"]:
533536
formatField["line-number"] = textRange.getIndex(comInterfaces.tom.tomLine)
534537
if formatConfig["reportFontName"]:

source/NVDAObjects/window/excel.py

Lines changed: 97 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import ctypes
99
import enum
1010
from typing import (
11-
Optional, Dict,
11+
Optional, Dict, Any
1212
)
1313

1414
from comtypes import COMError, BSTR
@@ -39,7 +39,7 @@
3939
import mouseHandler
4040
from displayModel import DisplayModelTextInfo
4141
import controlTypes
42-
from controlTypes import TextPosition
42+
from controlTypes import TextPosition, TextAlign, VerticalTextAlign
4343
from . import Window
4444
from .. import NVDAObjectTextInfo
4545
import scriptHandler
@@ -48,35 +48,103 @@
4848
import inputCore
4949
import ctypes
5050
import vision
51+
from utils.displayString import DisplayStringIntEnum
52+
import NVDAState
5153

5254
excel2010VersionMajor=14
5355

5456
xlNone=-4142
5557
xlSimple=-4154
5658
xlExtended=3
57-
xlCenter=-4108
58-
xlJustify=-4130
59-
xlLeft=-4131
60-
xlRight=-4152
61-
xlDistributed=-4117
62-
xlBottom=-4107
63-
xlTop=-4160
59+
60+
61+
class XlHAlign(DisplayStringIntEnum):
62+
# XlHAlign enumeration from https://docs.microsoft.com/en-us/office/vba/api/excel.xlhalign
63+
CENTER = -4108
64+
CENTER_ACROSS_SELECTION = 7
65+
DISTRIBUTED = -4117
66+
FILL = 5
67+
GENERAL = 1
68+
JUSTIFY = -4130
69+
LEFT = -4131
70+
RIGHT = -4152
71+
72+
@property
73+
def _displayStringLabels(self):
74+
return _horizontalAlignmentLabels
75+
76+
77+
class XlVAlign(DisplayStringIntEnum):
78+
# XlVAlign enumeration from https://docs.microsoft.com/en-us/office/vba/api/excel.xlvalign
79+
BOTTOM = -4107
80+
CENTER = -4108
81+
DISTRIBUTED = -4117
82+
JUSTIFY = -4130
83+
TOP = -4160
84+
85+
@property
86+
def _displayStringLabels(self):
87+
return _verticalAlignmentLabels
88+
89+
90+
_horizontalAlignmentLabels = {
91+
XlHAlign.CENTER: TextAlign.CENTER,
92+
XlHAlign.CENTER_ACROSS_SELECTION: TextAlign.CENTER_ACROSS_SELECTION,
93+
XlHAlign.DISTRIBUTED: TextAlign.DISTRIBUTE,
94+
XlHAlign.FILL: TextAlign.FILL,
95+
XlHAlign.GENERAL: TextAlign.GENERAL,
96+
XlHAlign.JUSTIFY: TextAlign.JUSTIFY,
97+
XlHAlign.LEFT: TextAlign.LEFT,
98+
XlHAlign.RIGHT: TextAlign.RIGHT,
99+
}
100+
101+
_verticalAlignmentLabels = {
102+
XlVAlign.BOTTOM: VerticalTextAlign.BOTTOM,
103+
XlVAlign.CENTER: VerticalTextAlign.CENTER,
104+
XlVAlign.DISTRIBUTED: VerticalTextAlign.DISTRIBUTE,
105+
XlVAlign.JUSTIFY: VerticalTextAlign.JUSTIFY,
106+
XlVAlign.TOP: VerticalTextAlign.TOP,
107+
}
108+
109+
110+
def __getattr__(attrName: str) -> Any:
111+
"""Module level `__getattr__` used to preserve backward compatibility."""
112+
_deprecatedConstantsMap = {
113+
"xlCenter": -4108, # XlHAlign.CENTER or XlVAlign.CENTER
114+
"xlJustify": -4130, # XlHAlign.JUSTIFY or XlVAlign.JUSTIFY
115+
"xlLeft": XlHAlign.LEFT.value,
116+
"xlRight": XlHAlign.RIGHT.value,
117+
"xlDistributed": -4117, # XlHAlign.DDISTRIBUTED or XlVAlign.DDISTRIBUTED
118+
"xlBottom": XlVAlign.BOTTOM.value,
119+
"xlTop": XlVAlign.TOP.value,
120+
"alignmentLabels": {
121+
XlHAlign.CENTER.value: "center",
122+
XlHAlign.JUSTIFY.value: "justify",
123+
XlHAlign.LEFT.value: "left",
124+
XlHAlign.RIGHT.value: "right",
125+
XlHAlign.DISTRIBUTED.value: "distributed",
126+
XlVAlign.BOTTOM.value: "botom",
127+
XlVAlign.TOP.value: "top",
128+
1: "default",
129+
}
130+
}
131+
if attrName in _deprecatedConstantsMap and NVDAState._allowDeprecatedAPI():
132+
replacementSymbol = _deprecatedConstantsMap[attrName]
133+
log.warning(
134+
f"Importing {attrName} from here is deprecated. "
135+
f"Import XlVAlign or XlHAlign enumerations instead.",
136+
stack_info=True,
137+
)
138+
return replacementSymbol
139+
raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}")
140+
141+
64142
xlDown=-4121
65143
xlToLeft=-4159
66144
xlToRight=-4161
67145
xlUp=-4162
68146
xlCellWidthUnitToPixels = 7.5919335705812574139976275207592
69147
xlSheetVisible=-1
70-
alignmentLabels={
71-
xlCenter:"center",
72-
xlJustify:"justify",
73-
xlLeft:"left",
74-
xlRight:"right",
75-
xlDistributed:"distributed",
76-
xlBottom:"botom",
77-
xlTop:"top",
78-
1:"default",
79-
}
80148

81149
xlA1 = 1
82150
xlRC = 2
@@ -1097,11 +1165,17 @@ def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
10971165
cellObj=self.obj.excelCellObject
10981166
fontObj=cellObj.font
10991167
if formatConfig['reportAlignment']:
1100-
value=alignmentLabels.get(self.obj.excelCellObject.horizontalAlignment)
1101-
if value:
1168+
try:
1169+
value = XlHAlign(self.obj.excelCellObject.horizontalAlignment).displayString
1170+
except ValueError:
1171+
pass
1172+
else:
11021173
formatField['text-align']=value
1103-
value=alignmentLabels.get(self.obj.excelCellObject.verticalAlignment)
1104-
if value:
1174+
try:
1175+
value = XlVAlign(self.obj.excelCellObject.verticalAlignment).displayString
1176+
except ValueError:
1177+
pass
1178+
else:
11051179
formatField['vertical-align']=value
11061180
if formatConfig['reportFontName']:
11071181
formatField['font-name']=fontObj.name

source/NVDAObjects/window/winword.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import colors
3333
import controlTypes
3434
from controlTypes import TextPosition
35+
from controlTypes.formatFields import TextAlign
3536
import treeInterceptorHandler
3637
import browseMode
3738
import review
@@ -972,6 +973,9 @@ def _normalizeFormatField(self,field,extraDetail=False):
972973
if fontSize is not None:
973974
# Translators: Abbreviation for points, a measurement of font size.
974975
field["font-size"] = pgettext("font size", "%s pt") % fontSize
976+
textAlign = field.pop('text-align', None)
977+
if textAlign:
978+
field['text-align'] = TextAlign(textAlign)
975979
return field
976980

977981
def expand(self,unit):

source/controlTypes/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# A part of NonVisual Desktop Access (NVDA)
22
# This file is covered by the GNU General Public License.
33
# See the file COPYING for more details.
4-
# Copyright (C) 2007-2021 NV Access Limited, Babbage B.V.
4+
# Copyright (C) 2007-2023 NV Access Limited, Babbage B.V., Cyrille Bougot
55

6-
from .formatFields import TextPosition
6+
from .formatFields import TextPosition, TextAlign, VerticalTextAlign
77
from .isCurrent import IsCurrent
88
from .outputReason import OutputReason
99
from .processAndLabelStates import processAndLabelStates
@@ -31,7 +31,9 @@
3131
"State",
3232
"STATES_SORTED",
3333
"DescriptionFrom",
34+
"TextAlign",
3435
"TextPosition",
3536
"transformRoleStates",
37+
"VerticalTextAlign",
3638
*deprecatedAliases.__all__
3739
]

0 commit comments

Comments
 (0)