Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MS Word documents: report when headings are collapsed in both speech and braille. #17499

Merged
merged 10 commits into from
Jan 20, 2025
3 changes: 2 additions & 1 deletion nvdaHelper/remote/WinWord/Constants.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2016-2023 NVDA contributors.
Copyright 2016-2025 NVDA contributors.
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.
Expand Down Expand Up @@ -79,6 +79,7 @@ constexpr int wdDISPID_PAGESETUP_PAGEWIDTH = 105;
constexpr int wdDISPID_PAGESETUP_SECTIONSTART = 114;
constexpr int wdDISPID_PAGESETUP_TEXTCOLUMNS = 119;
constexpr int wdDISPID_PARAGRAPH_OUTLINELEVEL = 202;
constexpr int wdDISPID_PARAGRAPH_COLLAPSED_STATE = 1203;
constexpr int wdDISPID_PARAGRAPH_RANGE = 0;
constexpr int wdDISPID_PARAGRAPH_STYLE = 100;
constexpr int wdDISPID_PARAGRAPHFORMAT_ALIGNMENT = 101;
Expand Down
6 changes: 5 additions & 1 deletion nvdaHelper/remote/winword.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2023 NVDA contributors.
Copyright 2006-2025 NVDA contributors.
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.
Expand Down Expand Up @@ -304,6 +304,10 @@ int generateHeadingXML(IDispatch* pDispatchParagraph, IDispatch* pDispatchParagr
int headingLevel=getHeadingLevelFromParagraph(pDispatchParagraph);
if(!headingLevel) return 0;
XMLStream<<L"<control role=\"heading\" level=\""<<headingLevel<<L"\" ";
// Expose the collapsed state of the heading
BOOL isCollapsed=false;
_com_dispatch_raw_propget(pDispatchParagraph, wdDISPID_PARAGRAPH_COLLAPSED_STATE, VT_BOOL, &isCollapsed);
XMLStream<<L"collapsedState=\""<<(isCollapsed ? L"true" : L"false")<<L"\" ";
if(pDispatchParagraphRange) {
long iVal=0;
if(_com_dispatch_raw_propget(pDispatchParagraphRange,wdDISPID_RANGE_START,VT_I4,&iVal)==S_OK&&iVal>=startOffset) {
Expand Down
18 changes: 17 additions & 1 deletion source/NVDAObjects/UIA/wordDocument.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is covered by the GNU General Public License.
# A part of NonVisual Desktop Access (NVDA)
# See the file COPYING for more details.
# Copyright (C) 2016-2023 NV Access Limited, Joseph Lee, Jakub Lukowicz, Cyrille Bougot
# Copyright (C) 2016-2025 NV Access Limited, Joseph Lee, Jakub Lukowicz, Cyrille Bougot

from typing import (
Optional,
Expand Down Expand Up @@ -51,6 +51,13 @@ class UIACustomAttributeID(enum.IntEnum):
COLUMN_NUMBER = 2
SECTION_NUMBER = 3
BOOKMARK_NAME = 4
COLUMNS_IN_SECTION = 5
SaschaCowley marked this conversation as resolved.
Show resolved Hide resolved
EXPAND_COLLAPSE_STATE = 6


class EXPAND_COLLAPSE_STATE(enum.IntEnum):
COLLAPSED = 0
EXPANDED = 1


#: the non-printable unicode character that represents the end of cell or end of row mark in Microsoft Word
Expand Down Expand Up @@ -483,6 +490,15 @@ def _getFormatFieldAtRange(self, textRange, formatConfig, ignoreMixedValues=Fals
)
if isinstance(textColumnNumber, int):
formatField.field["text-column-number"] = textColumnNumber
expandCollapseState = UIARemote.msWord_getCustomAttributeValue(
docElement,
textRange,
UIACustomAttributeID.EXPAND_COLLAPSE_STATE,
)
if expandCollapseState == EXPAND_COLLAPSE_STATE.COLLAPSED:
formatField.field["collapsed"] = True
elif expandCollapseState == EXPAND_COLLAPSE_STATE.EXPANDED:
formatField.field["collapsed"] = False
return formatField

def _getIndentValueDisplayString(self, val: float) -> str:
Expand Down
6 changes: 5 additions & 1 deletion source/NVDAObjects/window/winword.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2024 NV Access Limited, Manish Agrawal, Derek Riemer, Babbage B.V., Cyrille Bougot
# Copyright (C) 2006-2025 NV Access Limited, Manish Agrawal, Derek Riemer, Babbage B.V., Cyrille Bougot
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

Expand Down Expand Up @@ -1113,6 +1113,10 @@ def _normalizeControlField(self, field):
field["name"] = name
field["alwaysReportName"] = True
field["role"] = controlTypes.Role.FRAME
if field.pop("collapsedState", None) == "true":
if "states" not in field:
field["states"] = set()
field["states"].add(controlTypes.State.COLLAPSED)
newField = LazyControlField_RowAndColumnHeaderText(self)
newField.update(field)
return newField
Expand Down
5 changes: 4 additions & 1 deletion source/braille.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,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-2024 NV Access Limited, Joseph Lee, Babbage B.V., Davy Kager, Bram Duvigneau,
# Copyright (C) 2008-2025 NV Access Limited, Joseph Lee, Babbage B.V., Davy Kager, Bram Duvigneau,
# Leonard de Ruijter, Burman's Computer and Education Ltd., Julien Cochuyt

from enum import StrEnum
Expand Down Expand Up @@ -1160,6 +1160,9 @@ def getFormatFieldBraille(field, fieldCache, isAtStart, formatConfig):
# Translators: Displayed in braille for a heading with a level.
# %s is replaced with the level.
textList.append(_("h%s") % headingLevel)
collapsed = field.get("collapsed")
if collapsed:
textList.append(positiveStateLabels[controlTypes.State.COLLAPSED])
if formatConfig["reportLinks"]:
link = field.get("link")
oldLink = fieldCache.get("link")
Expand Down
15 changes: 14 additions & 1 deletion source/speech/speech.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,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-2024 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Babbage B.V., Bill Dengler,
# Copyright (C) 2006-2025 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Babbage B.V., Bill Dengler,
# Julien Cochuyt, Derek Riemer, Cyrille Bougot, Leonard de Ruijter, Łukasz Golonka

"""High-level functions to speak information."""
Expand Down Expand Up @@ -2620,6 +2620,19 @@ def getFormatFieldSpeech( # noqa: C901
# Translators: Speaks the heading level (example output: heading level 2).
text = _("heading level %d") % headingLevel
textList.append(text)
collapsed = attrs.get("collapsed")
oldCollapsed = attrsCache.get("collapsed") if attrsCache is not None else None
# collapsed state should be spoken when beginning to speak lines or paragraphs
# Ensuring a similar experience to if it was a state on a controlField
if collapsed and (
initialFormat
and (
reason in [OutputReason.FOCUS, OutputReason.QUICKNAV]
or unit in (textInfos.UNIT_LINE, textInfos.UNIT_PARAGRAPH)
)
or collapsed != oldCollapsed
):
textList.append(State.COLLAPSED.displayString)
if formatConfig["reportStyle"]:
style = attrs.get("style")
oldStyle = attrsCache.get("style") if attrsCache is not None else None
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ To use this feature, "allow NVDA to control the volume of other applications" mu
* Automatic language switching is now supported when using Microsoft Speech API version 5 (SAPI5) and Microsoft Speech Platform voices. (#17146, @gexgd0419)
* NVDA can now be configured to speak the current line or paragraph when navigating with braille navigation keys. (#17053, @nvdaes)
* In Word, the selection update is now reported when using Word commands to extend or reduce the selection (`f8` or `shift+f8`). (#3293, @CyrilleB79)
* In Microsoft Word 16.0.18226 and higher or when using Word object model, NVDA will now report if a heading is collapsed in both speech and braille. (#17499)

### Changes

Expand Down
Loading