├── addon ├── utilities │ ├── win32Ex │ │ ├── __init__.py │ │ ├── win32api.pyd │ │ ├── pywintypes311.dll │ │ ├── win32security.pyd │ │ └── license.txt │ ├── pycawEx │ │ ├── __init__.py │ │ └── pycaw │ │ │ ├── __init__.py │ │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── audioclient │ │ │ │ └── depend.py │ │ │ ├── endpointvolume │ │ │ │ └── depend.py │ │ │ └── mmdeviceapi │ │ │ │ └── depend │ │ │ │ ├── __init__.py │ │ │ │ └── structures.py │ │ │ ├── constants.py │ │ │ └── pycaw.py │ ├── pydubEx │ │ ├── __init__.py │ │ ├── logging_utils.py │ │ ├── exceptions.py │ │ └── playback.py │ ├── diff.zip │ ├── msgfmt.exe │ ├── xgettext.exe │ ├── psutilEx │ │ ├── python3.dll │ │ └── _psutil_windows.pyd │ └── markdownEx │ │ └── markdown │ │ ├── extensions │ │ ├── nl2br.py │ │ ├── legacy_em.py │ │ ├── extra.py │ │ ├── sane_lists.py │ │ ├── meta.py │ │ ├── legacy_attrs.py │ │ └── wikilinks.py │ │ ├── __meta__.py │ │ ├── __init__.py │ │ └── preprocessors.py ├── globalPlugins │ └── NVDAExtensionGlobalPlugin │ │ ├── scripts │ │ └── __init__.py │ │ ├── textAnalysis │ │ ├── __init_.py │ │ └── symbols.py │ │ ├── tools │ │ ├── manifest-translated.ini.tpl │ │ ├── manifest.ini.tpl │ │ ├── generate.py │ │ ├── buildVars.py.tpl │ │ └── gettextTools.py │ │ ├── activeWindowsListReport │ │ └── __init__.py │ │ ├── computerTools │ │ ├── waves │ │ │ ├── white_noise_10s.wav │ │ │ └── white_noise_3s.wav │ │ ├── tonesPatches.py │ │ ├── bluetoothAudio.py │ │ ├── __init__.py │ │ ├── beep.py │ │ ├── messageDialogs.py │ │ ├── audioUtils.py │ │ ├── waves.py │ │ └── pycawUtils.py │ │ ├── utils │ │ ├── secure.py │ │ ├── nvdaInfos.py │ │ ├── py3Compatibility.py │ │ ├── NVDAStrings.py │ │ ├── runInThread.py │ │ ├── numlock.py │ │ ├── keyboard.py │ │ └── textInfo.py │ │ ├── updateHandler │ │ ├── NVDAStrings.py │ │ ├── __init__.py │ │ └── state.py │ │ ├── browseModeEx │ │ ├── NVDAObjectsUIA.py │ │ ├── NVDAObjectsUIAChromium.py │ │ ├── UIAParagraph.py │ │ ├── __init__.py │ │ └── NVDAObjectsIAccessible.py │ │ ├── speechHistory │ │ ├── extensions.py │ │ ├── speechHistoryPatches.py │ │ └── __init__.py │ │ ├── speech │ │ ├── commands.py │ │ └── sayError.py │ │ ├── extendedNetUIHWND │ │ └── __init__.py │ │ ├── clipboardCommandAnnouncement │ │ ├── settingsDialogsPatche.py │ │ └── clipboard.py │ │ ├── __init__.py │ │ ├── userInputGestures │ │ └── inputGesturesExPatches.py │ │ ├── currentFolder │ │ └── __init__.py │ │ ├── commandKeysSelectiveAnnouncementAndRemanence │ │ └── patchs.py │ │ └── winExplorer │ │ └── __init__.py ├── newSymbols │ ├── symbols-fr.dic │ ├── symbols-tr.dic │ ├── symbols-en.dic │ ├── symbols-da.dic │ ├── symbols-pt.dic │ └── symbols-es.dic ├── doc │ ├── en │ │ ├── diff.zip │ │ ├── addon_informations.t2tconf │ │ └── to translators.txt │ ├── fr │ │ ├── diff.zip │ │ └── addon_informations.t2tconf │ ├── ar │ │ ├── addon_informations.t2tconf │ │ ├── addonUserManual.t2t │ │ └── addon_keys.t2tconf │ ├── ru │ │ └── addon_informations.t2tconf │ ├── sr │ │ ├── addon_informations.t2tconf │ │ └── changes.t2t │ ├── uk │ │ └── addon_informations.t2tconf │ ├── da │ │ └── addon_informations.t2tconf │ ├── pt │ │ └── addon_informations.t2tconf │ ├── pt_BR │ │ └── addon_informations.t2tconf │ ├── es │ │ └── addon_informations.t2tconf │ ├── addon_userManual.t2tconf │ ├── addon_global.t2tconf │ ├── addon_build.t2tconf │ ├── style_t2t.css │ ├── style.css │ └── styles.css ├── sounds │ ├── ringin.wav │ └── textAnalyzerAlerts │ │ ├── error.wav │ │ ├── uhoh.wav │ │ ├── nvda-error.wav │ │ ├── textError.wav │ │ ├── Bicycle Horn.wav │ │ ├── Windows Error.wav │ │ ├── Windows Error-raga.wav │ │ └── WindowsError-afternoon.wav ├── locale │ ├── ar │ │ ├── gestures-comp.ini │ │ ├── howToTranslate.txt │ │ ├── keyboard.ini │ │ ├── textAnalysis.ini │ │ └── symbolCategories.dic │ ├── fr │ │ ├── gestures-comp.ini │ │ ├── keyboard.ini │ │ └── textAnalysis.ini │ ├── da │ │ ├── keyboard.ini │ │ └── symbolCategories.dic │ ├── vi │ │ ├── keyboard.ini │ │ └── symbolCategories.dic │ ├── sr │ │ └── keyboard.ini │ ├── tr │ │ ├── keyboard.ini │ │ ├── textAnalysis.ini │ │ └── symbolCategories.dic │ ├── ru │ │ └── keyboard.ini │ ├── es │ │ ├── keyboard.ini │ │ └── textAnalysis.ini │ ├── cs │ │ ├── textAnalysis.ini │ │ ├── keyboard.ini │ │ └── symbolCategories.dic │ ├── en │ │ ├── textAnalysis.ini │ │ ├── keyboard.ini │ │ ├── symbolCategories.dic │ │ └── manifest.ini │ ├── sk │ │ ├── textAnalysis.ini │ │ ├── keyboard.ini │ │ └── symbolCategories.dic │ ├── pt_BR │ │ └── keyboard.ini │ └── pt │ │ └── keyboard.ini ├── used dependancies.txt ├── onInstall.py └── howToTranslate.txt ├── .gitignore ├── makePotFile.bat ├── msgfmt.exe ├── xgettext.exe ├── manifest-translated.ini.tpl ├── clean.bat ├── updateRepo.bat ├── makeAddon.bat ├── manifest.ini.tpl ├── .gitattributes ├── appveyor.yml ├── howToTranslate.txt ├── style.css └── site_scons └── site_tools └── gettexttool └── __init__.py /addon/utilities/win32Ex/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.mo 2 | *.pyc 3 | *.pyo 4 | *.nvda-addon 5 | .sconsign.dblite -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/textAnalysis/__init_.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /addon/utilities/pydubEx/__init__.py: -------------------------------------------------------------------------------- 1 | from .audio_segment import AudioSegment -------------------------------------------------------------------------------- /addon/newSymbols/symbols-fr.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | \v Tabulation verticale char never # \v 3 | -------------------------------------------------------------------------------- /makePotFile.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | call scons pot 3 | del *.pyc 4 | del .sconsign.dblite 5 | -------------------------------------------------------------------------------- /msgfmt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/msgfmt.exe -------------------------------------------------------------------------------- /xgettext.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/xgettext.exe -------------------------------------------------------------------------------- /manifest-translated.ini.tpl: -------------------------------------------------------------------------------- 1 | summary = "{addon_summary}" 2 | description = """{addon_description}""" 3 | -------------------------------------------------------------------------------- /addon/doc/en/diff.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/doc/en/diff.zip -------------------------------------------------------------------------------- /addon/doc/fr/diff.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/doc/fr/diff.zip -------------------------------------------------------------------------------- /addon/doc/ar/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY وظائف إضافية لبرنامج nvda -------------------------------------------------------------------------------- /addon/sounds/ringin.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/ringin.wav -------------------------------------------------------------------------------- /addon/doc/en/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY NVDA global commands extension -------------------------------------------------------------------------------- /addon/doc/ru/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY NVDA global commands extension -------------------------------------------------------------------------------- /addon/doc/sr/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY NVDA global commands extension -------------------------------------------------------------------------------- /addon/utilities/diff.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/diff.zip -------------------------------------------------------------------------------- /addon/utilities/msgfmt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/msgfmt.exe -------------------------------------------------------------------------------- /addon/doc/uk/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Глобальне розширення команд NVDA -------------------------------------------------------------------------------- /addon/utilities/xgettext.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/xgettext.exe -------------------------------------------------------------------------------- /addon/doc/da/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Udvidelse med globale NVDA-kommandoer -------------------------------------------------------------------------------- /addon/doc/fr/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Extension des commandes de base de NVDA -------------------------------------------------------------------------------- /addon/doc/pt/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Complemento Extensão de comandos do NVDA -------------------------------------------------------------------------------- /addon/doc/pt_BR/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Extensão de comandos globais do NVDA 3 | -------------------------------------------------------------------------------- /addon/locale/ar/gestures-comp.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/locale/ar/gestures-comp.ini -------------------------------------------------------------------------------- /addon/locale/fr/gestures-comp.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/locale/fr/gestures-comp.ini -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/tools/manifest-translated.ini.tpl: -------------------------------------------------------------------------------- 1 | summary = "{summary}" 2 | description = """{description}""" 3 | -------------------------------------------------------------------------------- /addon/locale/ar/howToTranslate.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/locale/ar/howToTranslate.txt -------------------------------------------------------------------------------- /addon/utilities/psutilEx/python3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/psutilEx/python3.dll -------------------------------------------------------------------------------- /addon/utilities/win32Ex/win32api.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/win32Ex/win32api.pyd -------------------------------------------------------------------------------- /addon/doc/es/addon_informations.t2tconf: -------------------------------------------------------------------------------- 1 | % add-on summary 2 | %!PostProc (html): ADDON_SUMMARY Complemento Extensión de las órdenes básicas de NVDA -------------------------------------------------------------------------------- /addon/newSymbols/symbols-tr.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | ‹ tek üçgen tırnak aç 3 | › tek üçgen tırnak kapa 4 | ℅ dikkat 5 | \v Dikey sekme char never # \v 6 | -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/error.wav -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/uhoh.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/uhoh.wav -------------------------------------------------------------------------------- /addon/utilities/win32Ex/pywintypes311.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/win32Ex/pywintypes311.dll -------------------------------------------------------------------------------- /addon/utilities/win32Ex/win32security.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/win32Ex/win32security.pyd -------------------------------------------------------------------------------- /addon/doc/addon_userManual.t2tconf: -------------------------------------------------------------------------------- 1 | % NOTHING TO TRANSLATE 2 | % ----- 3 | %!includeconf: addon_global.t2tconf 4 | %!Options: --toc 5 | %!style:..\style_t2t.css 6 | -------------------------------------------------------------------------------- /addon/newSymbols/symbols-en.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | ‹ Left Single Angle Quote 3 | › Right Single Angle Quote 4 | ℅ Care Of 5 | \v Vertical tabulation char never # \v 6 | -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/nvda-error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/nvda-error.wav -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/textError.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/textError.wav -------------------------------------------------------------------------------- /addon/utilities/psutilEx/_psutil_windows.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/utilities/psutilEx/_psutil_windows.pyd -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/Bicycle Horn.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/Bicycle Horn.wav -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/Windows Error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/Windows Error.wav -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/Windows Error-raga.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/Windows Error-raga.wav -------------------------------------------------------------------------------- /addon/sounds/textAnalyzerAlerts/WindowsError-afternoon.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/sounds/textAnalyzerAlerts/WindowsError-afternoon.wav -------------------------------------------------------------------------------- /clean.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | call scons -c -s 3 | del /s /q *.pyc 4 | del /s /q .sconsign.dblite 5 | del *.pot 6 | rd /s /q __pycache__ 7 | rd /s /q .\site_scons\site_tools\gettexttool\__pycache__ 8 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/activeWindowsListReport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/globalPlugins/NVDAExtensionGlobalPlugin/activeWindowsListReport/__init__.py -------------------------------------------------------------------------------- /addon/doc/en/to translators.txt: -------------------------------------------------------------------------------- 1 | Files to translate: 2 | addon_informations.t2tconf 3 | addon_keys.t2tconf 4 | addonUserManual.t2t 5 | changes.t2t 6 | 7 | The diff.zip contains file changes between this version and previous stable version. -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/waves/white_noise_10s.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/waves/white_noise_10s.wav -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/waves/white_noise_3s.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulber19/NVDAExtensionGlobalPlugin/HEAD/addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/waves/white_noise_3s.wav -------------------------------------------------------------------------------- /addon/newSymbols/symbols-da.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | # Daniel Gartmann June 23 2022: Not yet found official Danish translations, so open to change 3 | ‹ Venstre enkelt vinklet anførselstegn 4 | › Højre enkelt vinklet anførselstegn 5 | ℅ Attention 6 | \v Lodret tabulator char never # \v 7 | -------------------------------------------------------------------------------- /updateRepo.bat: -------------------------------------------------------------------------------- 1 | ;@echo off 2 | if exist .\addon\buildVars.py ( 3 | copy .\addon\buildVars.py . 4 | ) 5 | if exist .\addon\doc\en\readme.md ( 6 | copy .\addon\doc\en\readme.md . 7 | if exist .\addon\doc\style_md.css ( 8 | copy .\addon\doc\style_md.css . 9 | ) 10 | ) 11 | -------------------------------------------------------------------------------- /makeAddon.bat: -------------------------------------------------------------------------------- 1 | ;@echo off 2 | if exist .\addon\buildVars.py ( 3 | copy .\addon\buildVars.py . 4 | ) 5 | 6 | call scons -s 7 | ren *.nvda-addon *.nvda-addonTMP 8 | call scons -c 9 | ren *.nvda-addonTMP *.nvda-addon 10 | del /s /q *.pyc > NUL 11 | del .sconsign.dblite> NUL 12 | rd /s /q __pycache__ 13 | rd /s /q .\site_scons\site_tools\gettexttool\__pycache__ -------------------------------------------------------------------------------- /manifest.ini.tpl: -------------------------------------------------------------------------------- 1 | name = {addon_name} 2 | summary = "{addon_summary}" 3 | version = {addon_version} 4 | description = """{addon_description}""" 5 | author = "{addon_author}" 6 | url = "{addon_url}" 7 | docFileName = {addon_docFileName} 8 | minimumNVDAVersion = {addon_minimumNVDAVersion} 9 | lastTestedNVDAVersion = {addon_lastTestedNVDAVersion} 10 | updateChannel = {addon_updateChannel} 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behaviour, in case users don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Try to ensure that po files in the repo does not include 5 | # source code line numbers. 6 | # Every person expected to commit po files should change their personal config file as described here: 7 | # https://mail.gnome.org/archives/kupfer-list/2010-June/msg00002.html 8 | *.po filter=cleanpo 9 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/secure.py: -------------------------------------------------------------------------------- 1 | # NVDAExtensionGlobalPlugin/utils/secure.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2022 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import globalVars 8 | 9 | 10 | def inSecureMode(): 11 | return globalVars.appArgs.secure 12 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/tools/manifest.ini.tpl: -------------------------------------------------------------------------------- 1 | name = {addon_name} 2 | summary = "{addon_summary}" 3 | version = {addon_version} 4 | description = """{addon_description}""" 5 | author = "{addon_author}" 6 | url = "{addon_url}" 7 | docFileName = {addon_docFileName} 8 | minimumNVDAVersion = {addon_minimumNVDAVersion} 9 | lastTestedNVDAVersion = {addon_lastTestedNVDAVersion} 10 | updateChannel = {addon_updateChannel} 11 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/api/audioclient/depend.py: -------------------------------------------------------------------------------- 1 | from ctypes import Structure 2 | from ctypes.wintypes import WORD 3 | 4 | 5 | class WAVEFORMATEX(Structure): 6 | _fields_ = [ 7 | ("wFormatTag", WORD), 8 | ("nChannels", WORD), 9 | ("nSamplesPerSec", WORD), 10 | ("nAvgBytesPerSec", WORD), 11 | ("nBlockAlign", WORD), 12 | ("wBitsPerSample", WORD), 13 | ("cbSize", WORD), 14 | ] 15 | -------------------------------------------------------------------------------- /addon/utilities/pydubEx/logging_utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | """ 4 | import logging 5 | 6 | converter_logger = logging.getLogger("pydub.converter") 7 | 8 | def log_conversion(conversion_command): 9 | converter_logger.debug("subprocess.call(%s)", repr(conversion_command)) 10 | 11 | def log_subprocess_output(output): 12 | if output: 13 | for line in output.rstrip().splitlines(): 14 | converter_logger.debug('subprocess output: %s', line.rstrip()) 15 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/updateHandler/NVDAStrings.py: -------------------------------------------------------------------------------- 1 | # NVDAStrings.py 2 | # a common part of all of my addons. 3 | 4 | # Copyright (C) 2019 paulber19 5 | # This file is covered by the GNU General Public License. 6 | 7 | 8 | def NVDAString(s): 9 | """ A simple function to bypass the addon translation system, 10 | so it can take advantage from the NVDA translations directly. 11 | Based on implementation made by Alberto Buffolino 12 | https://github.com/nvaccess/nvda/issues/4652 """ 13 | 14 | return _(s) 15 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/api/endpointvolume/depend.py: -------------------------------------------------------------------------------- 1 | from ctypes import POINTER, Structure, c_float 2 | from ctypes.wintypes import BOOL, UINT 3 | 4 | from comtypes import GUID 5 | 6 | 7 | class AUDIO_VOLUME_NOTIFICATION_DATA(Structure): 8 | _fields_ = [ 9 | ("guidEventContext", GUID), 10 | ("bMuted", BOOL), 11 | ("fMasterVolume", c_float), 12 | ("nChannels", UINT), 13 | ("afChannelVolumes", c_float * 8), 14 | ] 15 | 16 | 17 | PAUDIO_VOLUME_NOTIFICATION_DATA = POINTER(AUDIO_VOLUME_NOTIFICATION_DATA) 18 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/nvdaInfos.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin/utils/nvdaInfos.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | try: 8 | # for nvda versions < 2026.1 9 | from versionInfo import version_year, version_major 10 | except ImportError: 11 | # for NVDA versions >= 2026.1 12 | from buildVersion import version_year, version_major 13 | 14 | NVDAVersion = [version_year, version_major] 15 | -------------------------------------------------------------------------------- /addon/utilities/pydubEx/exceptions.py: -------------------------------------------------------------------------------- 1 | class PydubException(Exception): 2 | """ 3 | Base class for any Pydub exception 4 | """ 5 | 6 | 7 | class TooManyMissingFrames(PydubException): 8 | pass 9 | 10 | 11 | class InvalidDuration(PydubException): 12 | pass 13 | 14 | 15 | class InvalidTag(PydubException): 16 | pass 17 | 18 | 19 | class InvalidID3TagVersion(PydubException): 20 | pass 21 | 22 | 23 | class CouldntDecodeError(PydubException): 24 | pass 25 | 26 | 27 | class CouldntEncodeError(PydubException): 28 | pass 29 | 30 | 31 | class MissingAudioParameter(PydubException): 32 | pass 33 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/py3Compatibility.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\utils\py3Compatibility.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright 2019 - 2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | import os 9 | 10 | 11 | def getCommonUtilitiesPath(): 12 | curAddonPath = getAddonPath() 13 | return os.path.join(curAddonPath, "utilities") 14 | 15 | 16 | def getAddonPath(addon=None): 17 | if addon is None: 18 | addon = addonHandler.getCodeAddon() 19 | return addon.path 20 | -------------------------------------------------------------------------------- /addon/doc/sr/changes.t2t: -------------------------------------------------------------------------------- 1 | ADDON_SUMMARY - istorija promena 2 | Autor: ADDON_AUTHOR_NAME 3 | 4 | 5 | %!includeconf: ../addon_global.t2tconf 6 | %!includeconf: addon_informations.t2tconf 7 | URL: [ADDON_REPOSITORY ADDON_REPOSITORY] 8 | 9 | 10 | Preuzimanje: 11 | - [Trenutna verzija: ADDON_CUR_VERSION ADDON_DOWNLOAD_SERVER1] 12 | - [Prethodna verzija: ADDON_PREV_VERSION ADDON_DOWNLOAD_PREVIOUS] 13 | - [Verzije u razvoju ADDON_DEV_URL] 14 | 15 | 16 | + v9.7 (04/01/2021) + 17 | - Nastavak funkcije za slanje svih zvučnih obaveštenja kao poruke na brajevom redu. 18 | 19 | 20 | + Starije verzije + 21 | Starije verzije nisu prevedene na Srpski. 22 | Molimo pogledajte Francusku ili Englesku dokumentaciju dodatka. -------------------------------------------------------------------------------- /addon/used dependancies.txt: -------------------------------------------------------------------------------- 1 | The following dependencies are embedded in the extension: 2 | - python markdown 3.7: Copyright 2007-2023 The Python Markdown Project (v. 1.7 and later). License: BSD. 3 | - pydub 0.25.1: Copyright © 2011 James Robert, http://jiaaro.co. License (MIT License). 4 | - part of wpywin32 306: Copyright (c) 1994-2008, Mark Hammond 5 | - msgfmt and xgettext of GNU Gettext tools : https://gnuwin32.sourceforge.net/downlinks/gettext.php 6 | - psutil 5.9.6: Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. 7 | - pycaw v20240210 Copyright (c) 2016 AndreMiras. License (MIT) 8 | -txt2tags 2.5: Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Aurelio Jargas, Copyright 2018, 2019 Takuya Nishimoto 9 | -------------------------------------------------------------------------------- /addon/locale/ar/keyboard.ini: -------------------------------------------------------------------------------- 1 | #هذا الملف يجب أن يكون بتنسيق utf-8 بدون BOM. 2 | [KeyboardKeys] 3 | # هذا القسم يحدد أحرف من مربع حوار "نطق اسماء المفاتيح". 4 | # كن حذرا: يجب أن يكون نفس إسم الحرف الذي يعلن عنه في مساعدة nvda+1. 5 | #على سبيل المثال لوحة مفاتيح سطح المكتب بالعربية هي : 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:ض ص ث ق ف غ ع ه خ ح ج د 8 | # row 3: ش س ي ب ل ا ت ن م ك ط 9 | # row 4: ئ ء ؤ ر لا ى ة و ز ظ 10 | # تعريف ترتيب المفاتيح في مربع الحوار. 11 | keys = "أبتثجحخدذرزسشصضطظعغفقكلمنهوي" 12 | [editionKeyCommands] 13 | [[default]] 14 | 15 | # هذا القسم يحدد نسخة أوامر لوحة المفاتيح في نظام ويندوز 16 | copy = control+c 17 | cut = control+x 18 | paste = control+v 19 | undo = control+z 20 | selectAll = control+a -------------------------------------------------------------------------------- /addon/newSymbols/symbols-pt.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | ‹ abrir aspas simples 3 | › fechar aspas simples 4 | ℅ à Atenção de 5 | \v Guia vertical char never # \v 6 | # Adding by raifer, letras Gregas 7 | α alfa 8 | Α alfa 9 | β beta 10 | Β beta 11 | γ gama 12 | Γ gama 13 | δ delta 14 | Δ delta 15 | ε epsilon 16 | Ε epsilon 17 | ζ zeta 18 | Ζ zeta 19 | η eta 20 | Η eta 21 | θ téta 22 | Θ téta 23 | ι iota 24 | Ι iota 25 | κ kapa 26 | Κ kapa 27 | λ lambda 28 | Λ lambda 29 | μ mu 30 | Μ mu 31 | ν nu 32 | Ν nu 33 | ξ xi 34 | Ξ xi 35 | ο omicron 36 | Ο omicron 37 | π pi 38 | Π pi 39 | ρ ró 40 | Ρ ró 41 | σ sigma 42 | ς sigma final 43 | Σ sigma 44 | τ tau 45 | Τ tau 46 | υ upsilon 47 | Υ upsilon 48 | φ fi 49 | Φ fi 50 | χ xi 51 | Χ xi 52 | ψ psi 53 | Ψ psi 54 | ω ómega 55 | Ω ómega 56 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/NVDAStrings.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\utils\NVDAStrings.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2017 - 2024 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | def NVDAString(s): 9 | """ A simple function to bypass the addon translation system, 10 | so it can take advantage from the NVDA translations directly. 11 | Based on implementation made by Alberto Buffolino 12 | https://github.com/nvaccess/nvda/issues/4652 """ 13 | return _(s) 14 | 15 | 16 | def NVDAString_pgettext(c, s): 17 | return pgettext(c, s) 18 | 19 | 20 | def NVDAString_ngettext(s, p, c): 21 | return ngettext(s, p, c) # noqa:F82 22 | -------------------------------------------------------------------------------- /addon/newSymbols/symbols-es.dic: -------------------------------------------------------------------------------- 1 | symbols: 2 | ‹ Abre Comillas Simple 3 | › Cerrar Comillas Simple 4 | ℅ Atención A 5 | \v Tabulación vertical char never # \v 6 | # Adding by raifer, letras Griegas 7 | α alfa 8 | Α alfa 9 | β beta 10 | Β beta 11 | γ gamma 12 | Γ gamma 13 | δ delta 14 | Δ delta 15 | ε épsilon 16 | Ε épsilon 17 | ζ dseta 18 | Ζ dseta 19 | η eta 20 | Η eta 21 | θ zeta 22 | Θ zeta 23 | ι iota 24 | Ι iota 25 | κ kappa 26 | Κ kappa 27 | λ lambda 28 | Λ lambda 29 | μ mi 30 | Μ mi 31 | ν ni 32 | Ν ni 33 | ξ xi 34 | Ξ xi 35 | ο ómicron 36 | Ο ómicron 37 | π pi 38 | Π pi 39 | ρ rho 40 | Ρ rho 41 | σ sigma 42 | ς sigma Final 43 | Σ sigma 44 | τ tau 45 | Τ tau 46 | υ ípsilon 47 | Υ ípsilon 48 | φ fi 49 | Φ fi 50 | χ ji 51 | Χ ji 52 | ψ psi 53 | Ψ psi 54 | ω omega 55 | Ω omega 56 | # End of adding -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/browseModeEx/NVDAObjectsUIA.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\browseModeEx\NVDAObjectsUIA.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from NVDAObjects.UIA.spartanEdge import EdgeHTMLRoot, EdgeHTMLTreeInterceptor 8 | from .browseModeUIAEx import UIABrowseModeDocumentEx, EdgeElementsListDialog 9 | 10 | 11 | class EdgeHTMLTreeInterceptorEx ( 12 | UIABrowseModeDocumentEx, EdgeHTMLTreeInterceptor): 13 | def _get_ElementsListDialog(self): 14 | return EdgeElementsListDialog 15 | 16 | 17 | class EdgeHTMLRootEx(EdgeHTMLRoot): 18 | treeInterceptorClass = EdgeHTMLTreeInterceptorEx 19 | -------------------------------------------------------------------------------- /addon/locale/ar/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | [SymbolToSymetric] 2 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 3 | # parenthese 4 | ( = ) 5 | #"bracket" 6 | "[" = ] 7 | # "brace" 8 | { = } 9 | #quote 10 | “ = ” 11 | # chevron 12 | ‹ = › 13 | # 14 | « = » 15 | [Punctuations] 16 | # defines all punctuations to be used in analysis. 17 | "All" = ()[]{},:.;!?“‹«”›»"'- 18 | # defines punctuations which must be preceded by a space. 19 | "NeedSpaceBefore" = ([{“‹« 20 | # defines punctuations which must be followed by a space. 21 | "NeedSpaceAfter" = )]}?!,.:;”›» 22 | # defines punctuations which must not be preceded by space. 23 | "NoSpaceBefore" = )]}.:;,”›»- 24 | # defines punctuations which must not be followed by a space. 25 | "NoSpaceAfter" = ([{“‹«- 26 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/browseModeEx/NVDAObjectsUIAChromium.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\browseModeEx\NVDAObjectsUIAChromium.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2021 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | from NVDAObjects.UIA.chromium import ChromiumUIADocument, ChromiumUIATreeInterceptor 9 | from .browseModeUIAEx import UIABrowseModeDocumentEx, EdgeElementsListDialog 10 | 11 | 12 | class ChromiumUIATreeInterceptorEx( 13 | UIABrowseModeDocumentEx, ChromiumUIATreeInterceptor): 14 | def _get_ElementsListDialog(self): 15 | return EdgeElementsListDialog 16 | 17 | 18 | class ChromiumUIADocumentEx(ChromiumUIADocument): 19 | treeInterceptorClass = ChromiumUIATreeInterceptorEx 20 | -------------------------------------------------------------------------------- /addon/locale/da/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a -------------------------------------------------------------------------------- /addon/locale/vi/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a -------------------------------------------------------------------------------- /addon/locale/sr/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./čćšđž" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a -------------------------------------------------------------------------------- /addon/locale/tr/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # cette section définit les caractères des touches des clavier de bureau utilisés dans le dialogue "Annonce sélective des touches de commandes" et qui peuvent être placés dans les gestes de commandes. 3 | # attention: ce doit être le caractère dit par NVDA en aide clavier activé. 4 | #par exemple pour un clavier de bureau français: 5 | # row 1:² 1 2 3 4 5 6 7 8 9 0 ° + 6 | # row 2: a z e r t y u i o p ^ $ 7 | # row 3: q s d f g h j k l m ù * 8 | # row 4: < w x c v b n , ; : ! 9 | # définit l'ordre des touches dans le dialogue. 10 | keys = abcdefghijklmnopqrstuvwxyz0123456789*-ş,<öç. 11 | 12 | 13 | [editionKeyCommands] 14 | [[default]] 15 | # cette section définit les commandes clavier d'édition de Windows 16 | copy = control+c 17 | cut = control+x 18 | paste = control+v 19 | undo = control+z 20 | selectAll = control+a 21 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/speechHistory/extensions.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\speechHistory\extensions.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | """ 8 | Extension points for prevent new speech 9 | """ 10 | 11 | from extensionPoints import Action 12 | from ..utils.nvdaInfos import NVDAVersion 13 | if NVDAVersion >= [2024, 2]: 14 | # we use NVDA pre_speech speech extensionPoint 15 | from speech.extensions import pre_speech 16 | my_pre_speech = pre_speech 17 | else: 18 | my_pre_speech = Action() 19 | """ 20 | Notifies when code attempts to speak text. 21 | @param speechSequence: the sequence of text and L{SpeechCommand} objects to speak 22 | @type speechSequence: speech.SpeechSequence 23 | """ 24 | -------------------------------------------------------------------------------- /addon/locale/fr/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # cette section définit les caractères des touches des clavier de bureau utilisés dans le dialogue "Annonce sélective des touches de commandes" et qui peuvent être placés dans les gestes de commandes. 3 | # attention: ce doit être le caractère dit par NVDA en aide clavier activé. 4 | #par exemple pour un clavier de bureau français: 5 | # row 1:² 1 2 3 4 5 6 7 8 9 0 ° + 6 | # row 2: a z e r t y u i o p ^ $ 7 | # row 3: q s d f g h j k l m ù * 8 | # row 4: < w x c v b n , ; : ! 9 | # définit l'ordre des touches dans le dialogue. 10 | keys = abcdefghijklmnopqrstuvwxyz0123456789²)=^$ù*<,;:! 11 | 12 | 13 | [editionKeyCommands] 14 | [[default]] 15 | # cette section définit les commandes clavier d'édition de Windows 16 | copy = control+c 17 | cut = control+x 18 | paste = control+v 19 | undo = control+z 20 | selectAll = control+a 21 | -------------------------------------------------------------------------------- /addon/locale/ru/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # cette section définit les caractères des touches des clavier de bureau utilisés dans le dialogue "Annonce sélective des touches de commandes" et qui peuvent être placés dans les gestes de commandes. 3 | # attention: ce doit être le caractère dit par NVDA en aide clavier activé. 4 | #par exemple pour un clavier de bureau français: 5 | # row 1:² 1 2 3 4 5 6 7 8 9 0 ° + 6 | # row 2: a z e r t y u i o p ^ $ 7 | # row 3: q s d f g h j k l m ù * 8 | # row 4: < w x c v b n , ; : ! 9 | # définit l'ordre des touches dans le dialogue. 10 | keys = abcdefghijklmnopqrstuvwxyz0123456789²)=^$ù*<,;:! 11 | 12 | 13 | [editionKeyCommands] 14 | [[default]] 15 | # cette section définit les commandes clavier d'édition de Windows 16 | copy = control+c 17 | cut = control+x 18 | paste = control+v 19 | undo = control+z 20 | selectAll = control+a 21 | -------------------------------------------------------------------------------- /addon/locale/es/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # esta sección define los caracteres de las teclas del teclado de escritorio utilizado en el diálogo "Anuncio selectivo de teclas de órden" y que se puede colocar en los gestos de entrada. 3 | # atención: este debe ser el carácter dicho por NVDA en el modo de ayuda de entrada activado. 4 | #por ejemplo para un teclado de escritorio español internacional: 5 | # row 1 :º 1 2 3 4 5 6 7 8 9 0 ' ¡ 6 | # row 2: q w e r t y u i o p ` + 7 | # row 3: a s d f g h j k l ñ ´ ç 8 | # row 4: < z x c v b n m , . - 9 | # define el orden de las teclas en el diálogo. 10 | keys = abcdefghijklmnopqrstuvwxyz0123456789º'¡`+<ñ´ç,.- 11 | 12 | [editionKeyCommands] 13 | [[default]] 14 | # esta sección se define los comandos de teclado (Windows edición 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a -------------------------------------------------------------------------------- /addon/locale/es/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = , 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = . 5 | [SymbolToSymetric] 6 | # parenthese 7 | ( = ) 8 | #"bracket" 9 | "[" = ] 10 | # "brace" 11 | { = } 12 | #quote 13 | “ = ” 14 | # chevron 15 | ‹ = › 16 | # 17 | « = » 18 | ¡ = ! 19 | ¿ = ? 20 | 21 | [Punctuations] 22 | # defines all punctuations to be used in analysis. 23 | "All" = ()[]{},:.;¡!¿?“‹«”›»"'- 24 | # defines punctuations which must be preceded by a space. 25 | "NeedSpaceBefore" = ([{¡¿“‹« 26 | # defines punctuations which must be followed by a space. 27 | "NeedSpaceAfter" = )]}?!,.:;”›» 28 | # defines punctuations which must not be preceded by space. 29 | "NoSpaceBefore" = )]}?!.:;,”›»- 30 | # defines punctuations which must not be followed by a space. 31 | "NoSpaceAfter" = ([{¡¿“‹«- 32 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{branch}-{build}' 2 | environment: 3 | PY_PYTHON: 2.7-32 4 | install: 5 | - cmd: >- 6 | python -m pip install wheel 7 | 8 | py -m pip install scons 9 | 10 | py -m pip install markdown 11 | build_script: 12 | - cmd: scons 13 | 14 | artifacts: 15 | - path: '*.nvda-addon' 16 | name: addon 17 | type: WebDeployPackage 18 | 19 | before_deploy: 20 | - ps: $env:REPO_NAME = $env:APPVEYOR_REPO_NAME.Substring($env:APPVEYOR_REPO_NAME.IndexOf('/') + 1) 21 | 22 | deploy: 23 | - provider: GitHub 24 | tag: $(APPVEYOR_REPO_TAG_NAME) 25 | release: Release $(APPVEYOR_REPO_TAG_NAME) 26 | description: This is the release $(APPVEYOR_REPO_TAG_NAME) of the $(REPO_NAME) addon for the NVDA screen reader built and uploaded to GitHub using Appveyor. 27 | 28 | auth_token: 29 | secure: Shqo5asiICk+0C1xjAfYUpTNdg3odsy2+Ycz0dMtbN2NaeAV+B8dxZn5Ad9pXnp 30 | artifact: addon 31 | on: 32 | appveyor_repo_tag: true -------------------------------------------------------------------------------- /addon/onInstall.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | # onInstall.py 3 | # A part of NVDAExtensionGlobalPlugin add-on 4 | # Copyright (C) 2016 - 2024 paulber19 5 | # This file is covered by the GNU General Public License. 6 | # See the file COPYING for more details. 7 | 8 | import addonHandler 9 | import gui 10 | import winUser 11 | 12 | addonHandler.initTranslation() 13 | 14 | 15 | def checkWindowListAddonInstalled(): 16 | h = winUser.getForegroundWindow() 17 | addonCheckList = [ 18 | "fakeClipboardAnouncement", 19 | "listDesFenetres", 20 | "ListeIconesZoneNotification", 21 | "DitDossierOuvrirEnregistrer"] 22 | for addon in addonHandler.getRunningAddons(): 23 | if addon.manifest["name"] in addonCheckList: 24 | # Translators: message of message box 25 | msg = _("""Attention, you must uninstall "%s" add-on because it is now included in this add-on""") # noqa:E501 26 | gui.messageBox(msg % addon.manifest["name"]) 27 | break 28 | winUser.setForegroundWindow(h) 29 | -------------------------------------------------------------------------------- /addon/locale/fr/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = , 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = . 5 | [SymbolToSymetric] 6 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 7 | # parenthese 8 | ( = ) 9 | #"bracket" 10 | "[" = ] 11 | # "brace" 12 | { = } 13 | #quote 14 | “ = ” 15 | # chevron 16 | ‹ = › 17 | # 18 | « = » 19 | [Punctuations] 20 | # defines all punctuations to be used in analysis. 21 | "All" = ()[]{},:.;!?“‹«”›»"'- 22 | # defines punctuations which must be preceded by a space. 23 | "NeedSpaceBefore" = ([{?!:;“‹« 24 | # defines punctuations which must be followed by a space. 25 | "NeedSpaceAfter" = )]}?!,.:;”›» 26 | # defines punctuations which must not be preceded by space. 27 | "NoSpaceBefore" = )]}.,”›» 28 | # defines punctuations which must not be followed by a space. 29 | "NoSpaceAfter" = ([{“‹« 30 | -------------------------------------------------------------------------------- /addon/locale/tr/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = , 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = . 5 | [SymbolToSymetric] 6 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 7 | # parenthese 8 | ( = ) 9 | #"bracket" 10 | "[" = ] 11 | # "brace" 12 | { = } 13 | #quote 14 | “ = ” 15 | # chevron 16 | ‹ = › 17 | # 18 | « = » 19 | [Punctuations] 20 | # defines all punctuations to be used in analysis. 21 | "All" = ()[]{},:.;!?“‹«”›»"'-— 22 | # defines punctuations which must be preceded by a space. 23 | "NeedSpaceBefore" = ([{“‹« 24 | # defines punctuations which must be followed by a space. 25 | "NeedSpaceAfter" = )]}?!,.:;”›» 26 | # defines punctuations which must not be preceded by space. 27 | "NoSpaceBefore" = )]}?!.:;,”›»— 28 | # defines punctuations which must not be followed by a space. 29 | "NoSpaceAfter" = ([{“‹«— 30 | -------------------------------------------------------------------------------- /addon/locale/cs/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = . 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = , 5 | [SymbolToSymetric] 6 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 7 | # parenthese 8 | ( = ) 9 | #"bracket" 10 | "[" = ] 11 | # "brace" 12 | { = } 13 | #quote 14 | “ = ” 15 | # chevron 16 | ‹ = › 17 | # 18 | « = » 19 | [Punctuations] 20 | # defines all punctuations to be used in analysis. 21 | "All" = ()[]{},:.;!?“‹«”›»"'-— 22 | # defines punctuations which must be preceded by a space. 23 | "NeedSpaceBefore" = ([{“‹«- 24 | # defines punctuations which must be followed by a space. 25 | "NeedSpaceAfter" = )]}?!,.:;”›»- 26 | # defines punctuations which must not be preceded by space. 27 | "NoSpaceBefore" = )]}?!.:;,”›»— 28 | # defines punctuations which must not be followed by a space. 29 | "NoSpaceAfter" = ([{“‹«— 30 | -------------------------------------------------------------------------------- /addon/locale/en/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = . 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = , 5 | [SymbolToSymetric] 6 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 7 | # parenthese 8 | ( = ) 9 | #"bracket" 10 | "[" = ] 11 | # "brace" 12 | { = } 13 | #quote 14 | “ = ” 15 | # chevron 16 | ‹ = › 17 | # 18 | « = » 19 | [Punctuations] 20 | # defines all punctuations to be used in analysis. 21 | "All" = ()[]{},:.;!?“‹«”›»"'-— 22 | # defines punctuations which must be preceded by a space. 23 | "NeedSpaceBefore" = ([{“‹«- 24 | # defines punctuations which must be followed by a space. 25 | "NeedSpaceAfter" = )]}?!,.:;”›»- 26 | # defines punctuations which must not be preceded by space. 27 | "NoSpaceBefore" = )]}?!.:;,”›»— 28 | # defines punctuations which must not be followed by a space. 29 | "NoSpaceAfter" = ([{“‹«— 30 | -------------------------------------------------------------------------------- /addon/locale/sk/textAnalysis.ini: -------------------------------------------------------------------------------- 1 | # to define the decimal symbol separator (3,414) 2 | decimalSymbol = . 3 | # to define the digit grouping symbol separator (1.212.333) 4 | digitGroupingSymbol = , 5 | [SymbolToSymetric] 6 | # this section defines the symbols and symetric symbols used by the mismatch analysis functionality. 7 | # parenthese 8 | ( = ) 9 | #"bracket" 10 | "[" = ] 11 | # "brace" 12 | { = } 13 | #quote 14 | “ = ” 15 | # chevron 16 | ‹ = › 17 | # 18 | « = » 19 | [Punctuations] 20 | # defines all punctuations to be used in analysis. 21 | "All" = ()[]{},:.;!?“‹«”›»"'-— 22 | # defines punctuations which must be preceded by a space. 23 | "NeedSpaceBefore" = ([{“‹«- 24 | # defines punctuations which must be followed by a space. 25 | "NeedSpaceAfter" = )]}?!,.:;”›»- 26 | # defines punctuations which must not be preceded by space. 27 | "NoSpaceBefore" = )]}?!.:;,”›»— 28 | # defines punctuations which must not be followed by a space. 29 | "NoSpaceAfter" = ([{“‹«— 30 | -------------------------------------------------------------------------------- /addon/doc/addon_global.t2tconf: -------------------------------------------------------------------------------- 1 | % NOTHING TO TRANSLATE 2 | % ----- 3 | %!Target: html 4 | %!Encoding: UTF-8 5 | % Remove the Table of Contents heading from the toc. 6 | %!PostProc(html): '^.*\\.*\.*$' '' 7 | % h1 in html should really be the document title only. 8 | % Therefore, change h1 through h5 in the output to h2 through h6. 9 | %!PostProc(html): ^
(.*)
$
\1
10 | %!PostProc(html): ^

(.*)

$
\1
11 | %!PostProc(html): ^

(.*)

$

\1

12 | %!PostProc(html): ^

(.*)

$

\1

13 | %!PostProc(html): ^

(.*)

$

\1

14 | % Some of our files contain the UTF-8 BOM. 15 | % txt2tags doesn't care about encodings internally, 16 | % so it will just include the BOM at the start of the title. 17 | % Therefore, strip the BOM from the title. 18 | %!PostProc(html): \<(TITLE|H1)\>\xef\xbb\xbf <\1> 19 | 20 | %!PostProc (html): ADDON_AUTHOR_NAME paulber19 (paulber19@laposte.net) 21 | %!PreProc (html): ADDON_AUTHOR_URL paulber19@laposte.net 22 | %!includeconf: addon_build.t2tconf -------------------------------------------------------------------------------- /addon/locale/pt_BR/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # Esta seção define os caracteres das teclas do teclado a serem usados no diálogo de anúncio seletivo de comandos por tecla. 3 | # Tenha cuidado: deve ser o caractere dito pelo NVDA quando a ajuda de entrada está ativada. 4 | # Por exemplo, as teclas de um teclado US (desktop) são: 5 | # linha 1: ` 1 2 3 4 5 6 7 8 9 0 - = 6 | # linha 2: q w e r t y u i o p [ ] 7 | # linha 3: a s d f g h j k l ; ' \ 8 | # linha 4: z x c v b n m , . / 9 | # Define a ordem das teclas no diálogo. 10 | keys = `1234567890-=qwertyuiop[]asdfghjkl;'\\zxcvbnm,./ 11 | 12 | [editionKeyCommands] 13 | [[default]] 14 | # Esta seção define os comandos de edição padrão do sistema Windows. 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a 20 | 21 | [[notepad]] 22 | # Esta seção define os comandos de edição do aplicativo Bloco de Notas, quando diferentes dos padrões do sistema. 23 | selectAll = control+a 24 | 25 | [[thunderbird]] 26 | # Esta seção define os comandos de edição do aplicativo Thunderbird, quando diferentes dos padrões do sistema. 27 | selectAll = control+a 28 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/speech/commands.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\speech\commands.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | 6 | import addonHandler 7 | # from logHandler import log 8 | import time 9 | import speech.commands 10 | 11 | addonHandler.initTranslation() 12 | 13 | 14 | class BeepWithPauseCommand(speech.commands.BaseCallbackCommand): 15 | """Produce a beep followed by a pause.""" 16 | 17 | def __init__(self, hz, length, left=50, right=50): 18 | self.hz = hz 19 | self.length = length 20 | self.left = left 21 | self.right = right 22 | 23 | def run(self): 24 | import tones 25 | 26 | tones.beep( 27 | self.hz, 28 | self.length, 29 | left=self.left, 30 | right=self.right, 31 | isSpeechBeepCommand=True, 32 | ) 33 | time.sleep(2 * self.length / 1000) 34 | 35 | def __repr__(self): 36 | return "BeepCommand({hz}, {length}, left={left}, right={right})".format( 37 | hz=self.hz, 38 | length=self.length, 39 | left=self.left, 40 | right=self.right, 41 | ) 42 | -------------------------------------------------------------------------------- /addon/locale/cs/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a 20 | # this section defines the edition keyboard for specific application 21 | # for example and for notepad.exe: 22 | # [[notepad]] 23 | # this section defines only the edition keyboard commands of notepad application which different from windows commands 24 | # selectAll = control+q 25 | -------------------------------------------------------------------------------- /addon/locale/en/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a 20 | # this section defines the edition keyboard for specific application 21 | # for example and for notepad.exe: 22 | # [[notepad]] 23 | # this section defines only the edition keyboard commands of notepad application which different from windows commands 24 | # selectAll = control+q 25 | -------------------------------------------------------------------------------- /addon/locale/sk/keyboard.ini: -------------------------------------------------------------------------------- 1 | # this file must be recorded in utf-8 without BOM. 2 | [KeyboardKeys] 3 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 4 | # becarefull: it must be the character said by NVDA in input help on. 5 | # for exemple, the keys of a desktop US keyboard are: 6 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 7 | # row 2:q w e r t y u i o p [ ] 8 | # row 3: a s d f g h j k l ; ' \ 9 | # row 4: \ z x c v b n m , . / 10 | # defines the order of the keys in the dialog. 11 | keys = "abcdefghijklmnopqrstuvwxyz0123456789`-=[];'\,./" 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+a 20 | # this section defines the edition keyboard for specific application 21 | # for example and for notepad.exe: 22 | # [[notepad]] 23 | # this section defines only the edition keyboard commands of notepad application which different from windows commands 24 | # selectAll = control+q 25 | -------------------------------------------------------------------------------- /addon/locale/pt/keyboard.ini: -------------------------------------------------------------------------------- 1 | [KeyboardKeys] 2 | # this section defines the characters of keyboard keys to be used in key command selective announcement dialog and can be used in a gesture. 3 | # becarefull: it must be the character said by NVDA in input help on. 4 | # for exemple, the keys of a desktop US keyboard are: 5 | # row 1: ` 1 2 3 4 5 6 7 8 9 0 - = 6 | # row 2:q w e r t y u i o p [ ] 7 | # row 3: a s d f g h j k l ; ' \ 8 | # row 4: \ z x c v b n m , . / 9 | # defines the order of the keys in the dialog. 10 | keys = abcdefghijklmnopqrstuvwxyz0123456789«+´<,.-~ 11 | 12 | [editionKeyCommands] 13 | [[default]] 14 | # this section defines the edition keyboard commands of Windows system 15 | copy = control+c 16 | cut = control+x 17 | paste = control+v 18 | undo = control+z 19 | selectAll = control+t 20 | [[notepad]] 21 | # this section defines only the edition keyboard commands of notePad application which different from windows commands 22 | selectAll = control+a 23 | [[thunderbird]] 24 | # this section defines only the edition keyboard commands of Thunderbird application which different from windows commands 25 | selectAll = control+a -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/constants.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, IntEnum 2 | 3 | from comtypes import GUID 4 | 5 | IID_Empty = GUID("{00000000-0000-0000-0000-000000000000}") 6 | 7 | CLSID_MMDeviceEnumerator = GUID("{BCDE0395-E52F-467C-8E3D-C4579291692E}") 8 | 9 | 10 | class ERole(Enum): 11 | eConsole = 0 12 | eMultimedia = 1 13 | eCommunications = 2 14 | ERole_enum_count = 3 15 | 16 | 17 | class EDataFlow(Enum): 18 | eRender = 0 19 | eCapture = 1 20 | eAll = 2 21 | EDataFlow_enum_count = 3 22 | 23 | 24 | class DEVICE_STATE(Enum): 25 | ACTIVE = 0x00000001 26 | DISABLED = 0x00000002 27 | NOTPRESENT = 0x00000004 28 | UNPLUGGED = 0x00000008 29 | MASK_ALL = 0x0000000F 30 | 31 | 32 | class AudioDeviceState(Enum): 33 | Active = 0x1 34 | Disabled = 0x2 35 | NotPresent = 0x4 36 | Unplugged = 0x8 37 | 38 | 39 | class STGM(Enum): 40 | STGM_READ = 0x00000000 41 | 42 | 43 | class AUDCLNT_SHAREMODE(Enum): 44 | AUDCLNT_SHAREMODE_SHARED = 0x00000001 45 | AUDCLNT_SHAREMODE_EXCLUSIVE = 0x00000002 46 | 47 | 48 | class AudioSessionState(IntEnum): 49 | # IntEnum to make instances comparable. 50 | Inactive = 0 51 | Active = 1 52 | Expired = 2 53 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/nl2br.py: -------------------------------------------------------------------------------- 1 | # `NL2BR` Extension 2 | # =============== 3 | 4 | # A Python-Markdown extension to treat newlines as hard breaks; like 5 | # GitHub-flavored Markdown does. 6 | 7 | # See https://Python-Markdown.github.io/extensions/nl2br 8 | # for documentation. 9 | 10 | # Original code Copyright 2011 [Brian Neal](https://deathofagremmie.com/) 11 | 12 | # All changes Copyright 2011-2014 The Python Markdown Project 13 | 14 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 15 | 16 | """ 17 | A Python-Markdown extension to treat newlines as hard breaks; like 18 | GitHub-flavored Markdown does. 19 | 20 | See the [documentation](https://Python-Markdown.github.io/extensions/nl2br) 21 | for details. 22 | """ 23 | 24 | from __future__ import annotations 25 | 26 | from . import Extension 27 | from ..inlinepatterns import SubstituteTagInlineProcessor 28 | 29 | BR_RE = r'\n' 30 | 31 | 32 | class Nl2BrExtension(Extension): 33 | 34 | def extendMarkdown(self, md): 35 | """ Add a `SubstituteTagInlineProcessor` to Markdown. """ 36 | br_tag = SubstituteTagInlineProcessor(BR_RE, 'br') 37 | md.inlinePatterns.register(br_tag, 'nl', 5) 38 | 39 | 40 | def makeExtension(**kwargs): # pragma: no cover 41 | return Nl2BrExtension(**kwargs) 42 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/tonesPatches.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\tonesPatches.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024-2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | from logHandler import log 9 | import tones 10 | from .beep import myBeep 11 | 12 | # global variable to save nvda patched method 13 | _NVDATonesBeep = None 14 | 15 | 16 | def initialize(): 17 | from .audioUtils import isWasapiUsed 18 | if isWasapiUsed(): 19 | return 20 | # patche tones.beep 21 | global _NVDATonesBeep 22 | if _NVDATonesBeep is not None: 23 | return 24 | _NVDATonesBeep = tones.beep 25 | if tones.beep.__module__ != "tones": 26 | log.warning( 27 | "Incompatibility: tones.beep method has also been patched probably by another add-on: %s. " 28 | "There is a risk of malfunction" % tones.beep.__module__) 29 | tones.beep = myBeep 30 | log.debug( 31 | "To allow NVDA tones volume adjustment, tones.beep function has been patched by %s function of %s module" 32 | % (tones.beep .__name__, tones.beep .__module__)) 33 | 34 | 35 | def terminate(): 36 | global _NVDATonesBeep 37 | if _NVDATonesBeep is not None: 38 | tones.beep = _NVDATonesBeep 39 | _NVDATonesBeep = None 40 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/extendedNetUIHWND/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\ComplexSymbols\__init__ 2 | # A part of NvDAextensionGlobalPlugin 3 | # Copyright (C) 2016 - 2022 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import NVDAObjects 8 | import config 9 | 10 | 11 | class ExtendedNetUIHWND (NVDAObjects.NVDAObject): 12 | def event_focusEntered(self): 13 | oldPresentationReportObjectDescriptions = config.conf["presentation"]["reportObjectDescriptions"] 14 | config.conf["presentation"]["reportObjectDescriptions"] = False 15 | super(ExtendedNetUIHWND, self).event_focusEntered() 16 | config.conf["presentation"]["reportObjectDescriptions"] = oldPresentationReportObjectDescriptions 17 | 18 | def event_gainFocus(self): 19 | oldPresentationReportObjectDescriptions = config.conf["presentation"]["reportObjectDescriptions"] 20 | config.conf["presentation"]["reportObjectDescriptions"] = False 21 | super(ExtendedNetUIHWND, self).event_gainFocus() 22 | config.conf["presentation"]["reportObjectDescriptions"] = oldPresentationReportObjectDescriptions 23 | 24 | 25 | def chooseNVDAObjectOverlayClasses(obj, clsList): 26 | if ( 27 | hasattr(obj, "windowClassName") 28 | and obj.windowClassName == "NetUIHWND" 29 | ): 30 | clsList.insert(0, ExtendedNetUIHWND) 31 | -------------------------------------------------------------------------------- /addon/doc/addon_build.t2tconf: -------------------------------------------------------------------------------- 1 | % NOTHING TO TRANSLATE 2 | % ----- 3 | % download 4 | %%!PreProc:ADDON_DOWNLOAD_SERVER1 https://github.com/paulber007/AllMyNVDAAddons/raw/master/wordAccessEnhancement/ADDON_NAME-ADDON_VERSION.nvda-addon 5 | %%!PreProc:ADDON_DOWNLOAD_PREVIOUS https://github.com/paulber007/AllMyNVDAAddons/raw/master/wordAccessEnhancement/ADDON_NAME-ADDON_VERSION.nvda-addon 6 | %!PreProc:ADDON_DOWNLOAD_SERVER1 AllMyNVDAAddons_REPOSITORY_URL/raw/master/ADDON_NAME/ADDON_NAME-ADDON_CUR_VERSION.nvda-addon 7 | %!PreProc:ADDON_DOWNLOAD_PREVIOUS AllMyNVDAAddons_REPOSITORY_URL/raw/master/ADDON_NAME/ADDON_NAME-ADDON_PREV_VERSION.nvda-addon 8 | %!PreProc: ADDON_DEV_URL AllMyNVDAAddons_REPOSITORY_URL/tree/master/ADDON_NAME/dev 9 | %!PostProc: AllMyNVDAAddons_REPOSITORY_URL https://github.com/paulber007/AllMyNVDAAddons 10 | % addon repository 11 | %!PreProc: ADDON_REPOSITORY PAULBER19_REPOSITORY_URL/ADDON_REPOSITORY_NAME.git 12 | %!PostProc: PAULBER19_REPOSITORY_URL https://github.com/paulber19 13 | % specific add-on informations 14 | %!PostProc: ADDON_NAME NVDAExtensionGlobalPlugin 15 | %!PostProc: ADDON_REPOSITORY_NAME NVDAExtensionGlobalPlugin 16 | % current stable version 17 | %!PostProc (html):ADDON_CUR_VERSION 14.1 18 | %!PostProc (html):MINIMUM_NVDA_VERSION 2024.1 19 | %!PostProc (html):LAST_TESTED_NVDA_VERSION 2025.3 20 | %previous stable version 21 | %!PostProc (html):ADDON_PREV_VERSION 14.0.6 -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/bluetoothAudio.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\bluetoothAudio.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2023-2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | import nvwave 9 | import os 10 | import struct 11 | import wave 12 | 13 | 14 | # part of this code comes from the BluetoothAudio addon for NVDA 15 | # Copyright (C) 2018 Tony Malykh 16 | 17 | 18 | def generateBeepBuf(whiteNoiseVolume): 19 | path = os.path.abspath(__file__) 20 | dirPath = os.path.dirname(path) 21 | fileName = os.path.join(dirPath, "waves", "white_noise_10s.wav") 22 | f = wave.open(fileName, "r") 23 | if f is None: 24 | raise RuntimeError() 25 | buf = f.readframes(f.getnframes()) 26 | bufSize = len(buf) 27 | n = bufSize // 2 28 | unpacked = struct.unpack(f"<{n}h", buf) 29 | unpacked = list(unpacked) 30 | for i in range(n): 31 | unpacked[i] = int(unpacked[i] * whiteNoiseVolume / 1000) 32 | packed = struct.pack(f"<{n}h", *unpacked) 33 | return packed, f.getframerate() 34 | 35 | 36 | def playWhiteNoise(deviceName): 37 | buf, framerate = generateBeepBuf(1) 38 | player = nvwave.WavePlayer( 39 | channels=2, samplesPerSec=framerate, bitsPerSample=16, outputDevice=deviceName, wantDucking=False) 40 | player.feed(buf) 41 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/browseModeEx/UIAParagraph.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\browseModeEx\UIAParagraph.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2018 - 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import browseMode 8 | import textInfos 9 | from UIAHandler import UIA_StyleIdAttributeId, StyleId_Normal 10 | from UIAHandler.utils import getUIATextAttributeValueFromRange 11 | 12 | 13 | def UIAParagraphQuicknavIterator(document, position, direction="next"): 14 | if position: 15 | curPosition = position 16 | else: 17 | curPosition = document.makeTextInfo( 18 | textInfos.POSITION_LAST if direction == "previous" 19 | else textInfos.POSITION_FIRST) 20 | stop = False 21 | firstLoop = True 22 | while not stop: 23 | tempInfo = curPosition.copy() 24 | tempInfo.expand(textInfos.UNIT_CHARACTER) 25 | styleIDValue = getUIATextAttributeValueFromRange( 26 | tempInfo._rangeObj, UIA_StyleIdAttributeId) 27 | if styleIDValue == StyleId_Normal: 28 | if not firstLoop or not position: 29 | tempInfo.expand(textInfos.UNIT_PARAGRAPH) 30 | yield browseMode.TextInfoQuickNavItem("paragraph", document, tempInfo) 31 | stop = (curPosition.move( 32 | textInfos.UNIT_PARAGRAPH, 33 | 1 if direction == "next" else -1) == 0) 34 | firstLoop = False 35 | -------------------------------------------------------------------------------- /addon/doc/style_t2t.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | body { 3 | margin : 0 5% 0 5%; 4 | font-family : Verdana, Arial, Helvetica, Sans-serif; 5 | font-size: 0.9em; 6 | background-color : #dce4ed; 7 | } 8 | h1 { 9 | margin-bottom:1.65em; 10 | text-align: center; 11 | font-size: 1.9em; 12 | color : #cc0000; 13 | text-decoration : underline;} 14 | h2 { 15 | margin : 1.4em 0 1.4em 0; 16 | text-align: left; 17 | font-weight: bold; 18 | font-size: 1.15em; 19 | text-indent:20px; 20 | padding-top:0.3em; 21 | padding-bottom:0.3em; 22 | background-color : #cccccc; 23 | color : #0c419a;} 24 | 25 | h3 { 26 | font-family: Verdana,Arial,Helvetica,sans-serif; 27 | font-size: 1.05em; 28 | font-weight: bold; 29 | text-align: left; 30 | color: #000066; 31 | margin-left: 40px; 32 | } 33 | 34 | h4 { 35 | list-style-type: none; 36 | font-size: 1em; 37 | list-style-position: outside; 38 | font-family: Verdana,Arial,Helvetica,sans-serif; 39 | text-indent: 100px; 40 | margin-top: 1em; 41 | margin-bottom: 1em; 42 | } 43 | 44 | dt { 45 | font-weight : bold; 46 | float : left; 47 | width: 10%; 48 | clear: left 49 | } 50 | dd { 51 | margin : 0 0 0.4em 0; 52 | float : left; 53 | width: 90%; 54 | display: block; 55 | } 56 | p { clear : both; 57 | font-size: 0.9em; 58 | } 59 | li {font-size: 0.9em;} 60 | a { text-decoration : none; 61 | font-weight : bold; 62 | } 63 | :active { 64 | text-decoration : none; 65 | } 66 | a:focus, a:hover {color: red} 67 | :link {color: rgb(110,110,110)} 68 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/pycaw.py: -------------------------------------------------------------------------------- 1 | """ 2 | Python wrapper around the Core Audio Windows API. 3 | """ 4 | 5 | # import here all newly split up modules, 6 | # to keep backwards compatibility 7 | 8 | # flake8: noqa 9 | # yes, the imports are unused 10 | 11 | from pycaw.api.audioclient import IAudioClient, ISimpleAudioVolume 12 | from pycaw.api.audioclient.depend import WAVEFORMATEX 13 | from pycaw.api.audiopolicy import ( 14 | IAudioSessionControl, 15 | IAudioSessionControl2, 16 | IAudioSessionEnumerator, 17 | IAudioSessionEvents, 18 | IAudioSessionManager, 19 | IAudioSessionManager2, 20 | IAudioSessionNotification, 21 | IAudioVolumeDuckNotification, 22 | ) 23 | from pycaw.api.endpointvolume import ( 24 | IAudioEndpointVolume, 25 | IAudioEndpointVolumeCallback, 26 | IAudioMeterInformation, 27 | ) 28 | from pycaw.api.endpointvolume.depend import ( 29 | AUDIO_VOLUME_NOTIFICATION_DATA, 30 | PAUDIO_VOLUME_NOTIFICATION_DATA, 31 | ) 32 | from pycaw.api.mmdeviceapi import ( 33 | IMMDevice, 34 | IMMDeviceCollection, 35 | IMMDeviceEnumerator, 36 | IMMEndpoint, 37 | IMMNotificationClient, 38 | ) 39 | from pycaw.api.mmdeviceapi.depend import IPropertyStore 40 | from pycaw.api.mmdeviceapi.depend.structures import ( 41 | PROPERTYKEY, 42 | PROPVARIANT, 43 | PROPVARIANT_UNION, 44 | ) 45 | from pycaw.constants import ( 46 | AUDCLNT_SHAREMODE, 47 | DEVICE_STATE, 48 | STGM, 49 | AudioDeviceState, 50 | EDataFlow, 51 | ERole, 52 | ) 53 | from pycaw.utils import AudioDevice, AudioSession, AudioUtilities 54 | -------------------------------------------------------------------------------- /howToTranslate.txt: -------------------------------------------------------------------------------- 1 | 1 - Create the "xx" folder of localization for the language in the "doc" and "locale" folders. 2 | 2 - Translation of the source code: 3 | You can use the "nvda.pot" catalog file which is located in the "locale/en" folder. 4 | Place the "nvda.po" and" nvda.mo" files in the "locale/xx/LC_MESSAGES" folder (to create). 5 | 6 | 3Creation of locale manifest.ini 7 | From main manifest.ini, translate "summary" and "description" variables and put these variables in an manifest.ini file (utf-8 coding). 8 | place this file in "locale/xx" folder. 9 | 10 | 4 - Translation of the documentation of the module: 11 | This documentation is if french language. 12 | - translate the "addon_informations.t2tconf", "addon_keys.t2tconf", "addonUserManual.t2t", "change.t2t" files. These files are located in "doc\fr" folder. 13 | - Place the translated files into the "doc/xx" folder, 14 | Translate the "readme.md" file located in "doc\en" folder and place it into "doc/xx" folder, 15 | - convert to html these files by using the add-on developpement tools dialog of the module("NVDA+j" followed by "t"). 16 | 17 | 18 | 5- Adapte the "keyboard.ini" to your keyboard and "symbolCategories.dic" files of "locale/en" folder (encoding in utf-8). 19 | Place thise files in the "locale/xx" folder. 20 | Map these files depending on the language. 21 | 22 | 6 - Adapte the "symbols-en.dic"file of the "newSymbols"folder.and name the translated file "symbols-xx.dic". 23 | Add symbols which are added in the file "locale/xx/symbolCategories.dic" and not supported vocally by NVDA for your language. -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/api/mmdeviceapi/depend/__init__.py: -------------------------------------------------------------------------------- 1 | from ctypes import HRESULT, POINTER 2 | from ctypes.wintypes import DWORD 3 | 4 | from comtypes import COMMETHOD, GUID, IUnknown 5 | 6 | from .structures import PROPERTYKEY, PROPVARIANT 7 | 8 | 9 | class IPropertyStore(IUnknown): 10 | _iid_ = GUID("{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}") 11 | _methods_ = ( 12 | # HRESULT GetCount([out] DWORD *cProps); 13 | COMMETHOD([], HRESULT, "GetCount", (["out"], POINTER(DWORD), "cProps")), 14 | # HRESULT GetAt( 15 | # [in] DWORD iProp, 16 | # [out] PROPERTYKEY *pkey); 17 | COMMETHOD( 18 | [], 19 | HRESULT, 20 | "GetAt", 21 | (["in"], DWORD, "iProp"), 22 | (["out"], POINTER(PROPERTYKEY), "pkey"), 23 | ), 24 | # HRESULT GetValue( 25 | # [in] REFPROPERTYKEY key, 26 | # [out] PROPVARIANT *pv); 27 | COMMETHOD( 28 | [], 29 | HRESULT, 30 | "GetValue", 31 | (["in"], POINTER(PROPERTYKEY), "key"), 32 | (["out"], POINTER(PROPVARIANT), "pv"), 33 | ), 34 | # HRESULT SetValue( 35 | # [in] REFPROPERTYKEY key, 36 | # [in] REFPROPVARIANT propvar 37 | # ); 38 | COMMETHOD( 39 | [], 40 | HRESULT, 41 | "SetValue", 42 | (["in"], POINTER(PROPERTYKEY), "key"), 43 | (["in"], POINTER(PROPVARIANT), "propvar"), 44 | ), 45 | # HRESULT Commit(); 46 | COMMETHOD([], HRESULT, "Commit"), 47 | ) 48 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | body { 3 | margin : 0 5% 0 5%; 4 | font-family : Verdana, Arial, Helvetica, Sans-serif; 5 | font-size: 0.9em; 6 | background-color : #dce4ed; 7 | counter-reset: h1 8 | } 9 | 10 | h1 { 11 | margin-bottom:1.65em; 12 | text-align: center; 13 | font-size: 1.9em; 14 | color : #cc0000; 15 | text-decoration : underline; 16 | counter-reset: h2 17 | } 18 | 19 | h2 { 20 | margin : 1.4em 0 1.4em 0; 21 | text-align: left; 22 | font-weight: bold; 23 | font-size: 1.15em; 24 | text-indent:20px; 25 | padding-top:0.15em; 26 | padding-bottom:0.3em; 27 | background-color : #cccccc; 28 | color : #0c419a; 29 | counter-reset: h3 30 | } 31 | 32 | h3 { 33 | font-size: 0.95em; 34 | text-indent:70px; 35 | color : #0c419a; 36 | counter-reset: h4 37 | } 38 | 39 | 40 | h2:before { 41 | counter-increment: h2; 42 | content: counter(h2) ". " 43 | } 44 | 45 | h3:before { 46 | counter-increment: h3; 47 | content: counter(h2) "." counter(h3) ". " 48 | } 49 | 50 | h4:before { 51 | counter-increment: h4; 52 | content: counter(h2) "." counter(h3) "." counter(h4) ". " 53 | } 54 | 55 | dt { 56 | font-weight : bold; 57 | float : left; 58 | width: 10%; 59 | clear: left 60 | } 61 | dd { 62 | margin : 0 0 0.4em 0; 63 | float : left; 64 | width: 90%; 65 | display: block; 66 | } 67 | p { 68 | clear : both; 69 | font-size: 0.9em; 70 | } 71 | li { 72 | font-size: 0.9em; 73 | } 74 | a { 75 | text-decoration : none; 76 | font-weight : bold; 77 | } 78 | :active { 79 | text-decoration : none; 80 | } 81 | a:focus, a:hover {color: red)} 82 | :link {color: rgb(110,110,110)} -------------------------------------------------------------------------------- /addon/doc/style.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | body { 3 | margin : 0 5% 0 5%; 4 | font-family : Verdana, Arial, Helvetica, Sans-serif; 5 | font-size: 0.9em; 6 | background-color : #dce4ed; 7 | counter-reset: h1 8 | } 9 | 10 | h1 { 11 | margin-bottom:1.65em; 12 | text-align: center; 13 | font-size: 1.9em; 14 | color : #cc0000; 15 | text-decoration : underline; 16 | counter-reset: h2 17 | } 18 | 19 | h2 { 20 | margin : 1.4em 0 1.4em 0; 21 | text-align: left; 22 | font-weight: bold; 23 | font-size: 1.15em; 24 | text-indent:20px; 25 | padding-top:0.15em; 26 | padding-bottom:0.3em; 27 | background-color : #cccccc; 28 | color : #0c419a; 29 | counter-reset: h3 30 | } 31 | 32 | h3 { 33 | font-size: 0.95em; 34 | text-indent:70px; 35 | color : #0c419a; 36 | counter-reset: h4 37 | } 38 | 39 | 40 | h2:before { 41 | counter-increment: h2; 42 | content: counter(h2) ". " 43 | } 44 | 45 | h3:before { 46 | counter-increment: h3; 47 | content: counter(h2) "." counter(h3) ". " 48 | } 49 | 50 | h4:before { 51 | counter-increment: h4; 52 | content: counter(h2) "." counter(h3) "." counter(h4) ". " 53 | } 54 | 55 | dt { 56 | font-weight : bold; 57 | float : left; 58 | width: 10%; 59 | clear: left 60 | } 61 | dd { 62 | margin : 0 0 0.4em 0; 63 | float : left; 64 | width: 90%; 65 | display: block; 66 | } 67 | p { 68 | clear : both; 69 | font-size: 0.9em; 70 | } 71 | li { 72 | font-size: 0.9em; 73 | } 74 | a { 75 | text-decoration : none; 76 | font-weight : bold; 77 | } 78 | :active { 79 | text-decoration : none; 80 | } 81 | a:focus, a:hover {color: red)} 82 | :link {color: rgb(110,110,110)} -------------------------------------------------------------------------------- /addon/utilities/win32Ex/license.txt: -------------------------------------------------------------------------------- 1 | Unless stated in the specfic source file, this work is 2 | Copyright (c) 1994-2008, Mark Hammond 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | 16 | Neither name of Mark Hammond nor the name of contributors may be used 17 | to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 21 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 24 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /addon/utilities/pycawEx/pycaw/api/mmdeviceapi/depend/structures.py: -------------------------------------------------------------------------------- 1 | from ctypes import Structure, Union, byref, windll 2 | from ctypes.wintypes import DWORD, LONG, LPWSTR, ULARGE_INTEGER, VARIANT_BOOL, WORD 3 | 4 | from comtypes import GUID 5 | from comtypes.automation import VARTYPE, VT_BOOL, VT_CLSID, VT_LPWSTR, VT_UI4 6 | 7 | 8 | class PROPVARIANT_UNION(Union): 9 | _fields_ = [ 10 | ("lVal", LONG), 11 | ("uhVal", ULARGE_INTEGER), 12 | ("boolVal", VARIANT_BOOL), 13 | ("pwszVal", LPWSTR), 14 | ("puuid", GUID), 15 | ] 16 | 17 | 18 | class PROPVARIANT(Structure): 19 | _fields_ = [ 20 | ("vt", VARTYPE), 21 | ("reserved1", WORD), 22 | ("reserved2", WORD), 23 | ("reserved3", WORD), 24 | ("union", PROPVARIANT_UNION), 25 | ] 26 | 27 | def GetValue(self): 28 | vt = self.vt 29 | if vt == VT_BOOL: 30 | return self.union.boolVal != 0 31 | elif vt == VT_LPWSTR: 32 | # return Marshal.PtrToStringUni(union.pwszVal) 33 | return self.union.pwszVal 34 | elif vt == VT_UI4: 35 | return self.union.lVal 36 | elif vt == VT_CLSID: 37 | # TODO 38 | # return (Guid)Marshal.PtrToStructure(union.puuid, typeof(Guid)) 39 | return 40 | else: 41 | return "%s:?" % (vt) 42 | 43 | def clear(self): 44 | windll.ole32.PropVariantClear(byref(self)) 45 | 46 | 47 | class PROPERTYKEY(Structure): 48 | _fields_ = [ 49 | ("fmtid", GUID), 50 | ("pid", DWORD), 51 | ] 52 | 53 | def __str__(self): 54 | return "%s %s" % (self.fmtid, self.pid) 55 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\__init__.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from logHandler import log 8 | 9 | 10 | def initialize(): 11 | log.debug("computerTools initialization") 12 | # for tonalities volume changes 13 | from ..settings import toggleAllowNVDATonesVolumeAdjustmentAdvancedOption 14 | if toggleAllowNVDATonesVolumeAdjustmentAdvancedOption(False): 15 | from . import tonesPatches 16 | tonesPatches.initialize() 17 | from . import temporaryOutputDevicePatches 18 | temporaryOutputDevicePatches.patche() 19 | from . import audioCore 20 | audioCore.initialize() 21 | """ 22 | try: 23 | # for nvda version > 2024.2 24 | splitAudioMode = config.conf["audio"]["soundSplitState"] 25 | except Exception: 26 | splitAudioMode = 0 27 | from ..settings import getInstallFeatureOption 28 | from ..settings.addonConfig import ( 29 | C_DoNotInstall, 30 | FCT_SplitAudio 31 | ) 32 | # if getInstallFeatureOption(FCT_SplitAudio) != C_DoNotInstall and splitAudioMode: 33 | # from .messageDialogs import SplitAudioWarningDialog 34 | # from gui.message import displayDialogAsModal 35 | # wx.CallAfter(displayDialogAsModal, SplitAudioWarningDialog(None)) 36 | """ 37 | 38 | 39 | def terminate(): 40 | from . import audioCore 41 | audioCore.terminate() 42 | from . import tonesPatches 43 | tonesPatches.terminate() 44 | from . import temporaryOutputDevicePatches 45 | temporaryOutputDevicePatches.patche(install=False) 46 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/browseModeEx/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\browseModeEx\__init__.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | 6 | 7 | import NVDAObjects.UIA.spartanEdge as EDGE 8 | import NVDAObjects.IAccessible.MSHTML 9 | import NVDAObjects.IAccessible.mozilla 10 | import NVDAObjects.IAccessible.chromium 11 | import NVDAObjects.UIA.chromium 12 | 13 | 14 | def chooseNVDAObjectOverlayClasses(obj, clsList): 15 | if EDGE.EdgeHTMLRoot in clsList: 16 | from .NVDAObjectsUIA import EdgeHTMLRootEx 17 | clsList[clsList.index(EDGE.EdgeHTMLRoot)] = EdgeHTMLRootEx 18 | return 19 | if NVDAObjects.IAccessible.MSHTML.MSHTML in clsList: 20 | from . import NVDAObjectsIAccessible 21 | clsList[clsList.index(NVDAObjects.IAccessible.MSHTML.MSHTML)] = NVDAObjectsIAccessible.NVDAObjectMSHTMLEx 22 | return 23 | if NVDAObjects.IAccessible.mozilla.Document in clsList: 24 | from . import NVDAObjectsIAccessible 25 | clsList[clsList.index( 26 | NVDAObjects.IAccessible.mozilla.Document)] = NVDAObjectsIAccessible.NVDAObjectMozillaDocumentEx 27 | return 28 | if NVDAObjects.IAccessible.chromium.Document in clsList: 29 | from . import NVDAObjectsIAccessible 30 | clsList[clsList.index(NVDAObjects.IAccessible.chromium.Document)] = NVDAObjectsIAccessible.ChromiumDocument 31 | return 32 | if NVDAObjects.UIA.chromium.ChromiumUIADocument in clsList: 33 | from . import NVDAObjectsUIAChromium 34 | newCls = NVDAObjectsUIAChromium.ChromiumUIADocumentEx 35 | clsList[clsList.index(NVDAObjects.UIA.chromium.ChromiumUIADocument)] = newCls 36 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/tools/generate.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\tools\generate.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2021 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | import codecs 9 | import os 10 | 11 | import gettext 12 | addonHandler.initTranslation() 13 | 14 | 15 | def generateManifest(dest, addonInfo, template): 16 | _ = "" 17 | manifest = template.format(**addonInfo) 18 | with codecs.open(dest, "w", "utf-8") as f: 19 | f.write(manifest) 20 | 21 | 22 | def getTranslationsInstance(addon, language, domain='nvda'): 23 | localedir = os.path.join(addon.path, "locale") 24 | return gettext.translation( 25 | domain, localedir=localedir, languages=[language], fallback=True) 26 | 27 | 28 | def getVariablesBetweenBrass(stringToFormat): 29 | vars = [] 30 | for s in stringToFormat.split("{"): 31 | if "}" not in s: 32 | continue 33 | vars.append(s.split("}")[0]) 34 | return vars 35 | 36 | 37 | def generateTranslatedManifest(addon, addonInfos, language, template): 38 | _ = getTranslationsInstance(addon, language).gettext 39 | vars = {} 40 | translatedVars = {} 41 | allTranslated = True 42 | for var in getVariablesBetweenBrass(template): 43 | vars[var] = addonInfos[var] 44 | translatedVars[var] = _(addonInfos[var]) 45 | if translatedVars[var] == vars[var]: 46 | allTranslated = False 47 | result = template.format(**translatedVars) 48 | dest = os.path.join(addon.path, "locale", language, "manifest.ini") 49 | with codecs.open(dest, "w", "utf-8") as f: 50 | f.write(result) 51 | return allTranslated 52 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/updateHandler/__init__.py: -------------------------------------------------------------------------------- 1 | # __init__.py 2 | # common Part of all of my add-ons 3 | # Copyright 2019-2024 Paulber19 4 | # some parts of code comes from others add-ons: 5 | # add-on Updater (author Joseph Lee) 6 | # brailleExtender (author Andre-Abush ) 7 | 8 | import addonHandler 9 | import globalVars 10 | import time 11 | import wx 12 | import random 13 | from . import state 14 | state.initialize() 15 | addonHandler.initTranslation() 16 | 17 | # keep current update check timer id. 18 | updateChecker = None 19 | 20 | 21 | def autoUpdateCheck(releaseToDev): 22 | from . update_check import shouldCheckForUpdate 23 | if not shouldCheckForUpdate(): 24 | return 25 | # But not when NVDA itself is updating. 26 | if globalVars.appArgs.install or globalVars.appArgs.minimal: 27 | return 28 | currentTime = int(time.time()) 29 | lastCheck = state.getLastCheck() 30 | interval = 0 if state.getRemindUpdate() else state.addonUpdateCheckInterval 31 | whenToCheck = lastCheck + interval 32 | if currentTime < whenToCheck: 33 | return 34 | state.setLastCheck() 35 | global updateChecker 36 | if updateChecker is not None: 37 | updateChecker.Stop() 38 | # delay before check update (between 20 and 600 secondes, step = 20 seconds) 39 | r = 20 * random.randint(1, 30) 40 | updateChecker = wx.CallLater(r * 1000, addonUpdateCheck, True, releaseToDev) 41 | 42 | 43 | def addonUpdateCheck(auto, releaseToDev): 44 | global updateChecker 45 | if updateChecker is not None: 46 | updateChecker.Stop() 47 | updateChecker = None 48 | from .update_check import CheckForAddonUpdate 49 | wx.CallAfter( 50 | CheckForAddonUpdate, 51 | updateInfosFile=None, 52 | auto=auto, 53 | releaseToDev=releaseToDev) 54 | -------------------------------------------------------------------------------- /site_scons/site_tools/gettexttool/__init__.py: -------------------------------------------------------------------------------- 1 | """ This tool allows generation of gettext .mo compiled files, pot files from source code files 2 | and pot files for merging. 3 | 4 | Three new builders are added into the constructed environment: 5 | 6 | - gettextMoFile: generates .mo file from .pot file using msgfmt. 7 | - gettextPotFile: Generates .pot file from source code files. 8 | - gettextMergePotFile: Creates a .pot file appropriate for merging into existing .po files. 9 | 10 | To properly configure get text, define the following variables: 11 | 12 | - gettext_package_bugs_address 13 | - gettext_package_name 14 | - gettext_package_version 15 | 16 | 17 | """ 18 | from SCons.Action import Action 19 | 20 | def exists(env): 21 | return True 22 | 23 | XGETTEXT_COMMON_ARGS = ( 24 | "--msgid-bugs-address='$gettext_package_bugs_address' " 25 | "--package-name='$gettext_package_name' " 26 | "--package-version='$gettext_package_version' " 27 | "-c -o $TARGET $SOURCES" 28 | ) 29 | 30 | def generate(env): 31 | env.SetDefault(gettext_package_bugs_address="example@example.com") 32 | env.SetDefault(gettext_package_name="") 33 | env.SetDefault(gettext_package_version="") 34 | 35 | env['BUILDERS']['gettextMoFile']=env.Builder( 36 | action=Action("msgfmt -o $TARGET $SOURCE", "Compiling translation $SOURCE"), 37 | suffix=".mo", 38 | src_suffix=".po" 39 | ) 40 | 41 | env['BUILDERS']['gettextPotFile']=env.Builder( 42 | action=Action("xgettext " + XGETTEXT_COMMON_ARGS, "Generating pot file $TARGET"), 43 | suffix=".pot") 44 | 45 | env['BUILDERS']['gettextMergePotFile']=env.Builder( 46 | action=Action("xgettext " + "--omit-header --no-location " + XGETTEXT_COMMON_ARGS, 47 | "Generating pot file $TARGET"), 48 | suffix=".pot") 49 | 50 | -------------------------------------------------------------------------------- /addon/doc/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0 auto; 3 | max-width: 50em; 4 | font-family: "Helvetica", "Arial", sans-serif; 5 | line-height: 1.5; 6 | padding: 4em 1em; 7 | color: #333; 8 | } 9 | 10 | :lang(ar) body *, :lang(fa) body * { 11 | font-family: "Simplified Arabic", "Traditional Arabic", "Arial", sans-serif !important; 12 | } 13 | 14 | h1 { 15 | color:white; 16 | background-color: #472F5F; /* NVDA purple */ 17 | } 18 | 19 | h2 { 20 | margin-top: 1em; 21 | padding-top: 1em; 22 | } 23 | 24 | h2, h3, h4, a { 25 | color: #472F5F; /* NVDA purple */ 26 | } 27 | 28 | strong { 29 | color: #000; 30 | } 31 | 32 | /* tables */ 33 | table, td, th { 34 | border:1px solid black; 35 | } 36 | table{ 37 | border-collapse: collapse; 38 | } 39 | td, th { 40 | padding: 0.25em; 41 | } 42 | th { 43 | color: #472F5F; /* NVDA purple */ 44 | } 45 | 46 | /* code / pre */ 47 | code, 48 | pre { 49 | background: #f6f8fa; 50 | border-bottom: 1px solid #d8dee9; 51 | color: #33104e; 52 | } 53 | 54 | code { 55 | padding: 2px 4px; 56 | vertical-align: text-bottom; 57 | } 58 | pre { 59 | padding: 1em; 60 | border-left: 2px solid #69c; 61 | } 62 | 63 | /* 64 | Definition list 65 | 66 | Note these are not exposed correctly in NVDA: #3858 67 | */ 68 | dl { 69 | display: grid; 70 | grid-template-columns: auto; 71 | } 72 | 73 | /* Term of a definition */ 74 | dl > dt { 75 | grid-column-start: 1; 76 | font-style: italic; 77 | font-weight: bold; 78 | font-size: small; 79 | } 80 | 81 | /* Definition of a term */ 82 | dl > dd { 83 | display: inherit; 84 | grid-column-start: 2; 85 | margin-inline-start: 1em; 86 | font-size: small; 87 | font-style: italic; 88 | } 89 | 90 | thead:has(tr > th.hideHeaderRow) { 91 | display: none; 92 | } 93 | -------------------------------------------------------------------------------- /addon/howToTranslate.txt: -------------------------------------------------------------------------------- 1 | 1 - Create the "xx" folder of localization for the language in the "doc" and "locale" folders. 2 | 2 - Translation of the source code: 3 | You can use the "nvda.pot" catalog file which is located in the "locale/en" folder. 4 | Place the "nvda.po" and" nvda.mo" files in the "locale/xx/LC_MESSAGES" folder (to create). 5 | 6 | 3Creation of locale manifest.ini 7 | From main manifest.ini, translate "summary" and "description" variables and put these variables in an manifest.ini file (utf-8 coding). 8 | place this file in "locale/xx" folder. 9 | 10 | 4 - Translation of the documentation of the module: 11 | This documentation is if french language and automatic translation in english. 12 | - translate the "addon_informations.t2tconf", "addon_keys.t2tconf", "addonUserManual.t2t", "change.t2t" files. These files are located in "doc\fr" folder. 13 | - Place the translated files into the "doc/xx" folder, 14 | The readme.md file in "doc\en" folder should not be translated. 15 | 16 | - convert to html these files by using the add-on developpement tools dialog of the module("NVDA+j" followed by "t"). 17 | In the doc\en and doc\fr folder, there is the diff.zip archive which contains the files listing the differences of the current version compared to the previous version. 18 | 19 | 20 | 5- Adapte the "keyboard.ini" to your keyboard and "symbolCategories.dic" files of "locale/en" folder (encoding in utf-8). 21 | Place thise files in the "locale/xx" folder. 22 | Map these files depending on the language. 23 | 24 | 6 - Adapte the "symbols-en.dic"file of the "newSymbols"folder.and name the translated file "symbols-xx.dic". 25 | Add symbols which are added in the file "locale/xx/symbolCategories.dic" and not supported vocally by NVDA for your language. 26 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/runInThread.py: -------------------------------------------------------------------------------- 1 | # NVDAExtensionGlobalPlugin/runInThread.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2017 - 2020 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | from logHandler import log 9 | import tones 10 | import threading 11 | import ui 12 | addonHandler.initTranslation() 13 | 14 | 15 | class RepeatTask(threading.Thread): 16 | _delay = None 17 | _armed = False 18 | 19 | def __init__(self, isRunning=None): 20 | if self._delay is None: 21 | log.error("Cannot create repeatTask thread because delay is none") 22 | return 23 | self.isRunning = isRunning 24 | super(RepeatTask, self).__init__() 25 | self._stopevent = threading.Event() 26 | 27 | def task(self): 28 | # must be overwritten 29 | return 30 | 31 | tones.beep(400, 200) 32 | 33 | def run(self): 34 | if self._delay is None: 35 | log.error("Cannot start repeatTask thread because not delay") 36 | return 37 | while not self._stopevent.is_set(): 38 | self._stopevent.wait(self._delay) 39 | if self.isRunning is not None and not self.isRunning(): 40 | # interrupted before stop 41 | # Translators: message to user to report an interuption before stop. 42 | ui.message(_("interrupted")) 43 | break 44 | self.task() 45 | 46 | def stop(self): 47 | self._stopevent.set() 48 | 49 | 50 | class RepeatBeep(RepeatTask): 51 | def __init__(self, delay=2.0, beep=(200, 200), isRunning=None): 52 | self._delay = delay 53 | self.beep = beep 54 | super(RepeatBeep, self).__init__(isRunning) 55 | 56 | def task(self): 57 | if self._stopevent.is_set(): 58 | return 59 | (frequence, length) = self.beep 60 | tones.beep(frequence, length) 61 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/clipboardCommandAnnouncement/settingsDialogsPatche.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\clipboardCommandAnnouncement\settingsDialogs.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2025 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | from gui.settingsDialogs import KeyboardSettingsPanel, NVDASettingsDialog 9 | from gui import mainFrame 10 | 11 | addonHandler.initTranslation() 12 | 13 | 14 | class MyKeyboardSettingsPanel(KeyboardSettingsPanel): 15 | def makeSettings(self, settingsSizer): 16 | super().makeSettings(settingsSizer) 17 | from ..clipboardCommandAnnouncement import canInstallSpellingAtTypingFunctionnality 18 | if canInstallSpellingAtTypingFunctionnality: 19 | self.alertForSpellingErrorsCheckBox.Enable() 20 | # Translators: label for check box 21 | self.alertForSpellingErrorsCheckBox.SetLabel(_("When typing, reports spelling errors")) 22 | 23 | 24 | try: 25 | NVDASettingsDialog.categoryClasses[NVDASettingsDialog.categoryClasses .index(KeyboardSettingsPanel)] = MyKeyboardSettingsPanel 26 | except ValueError: 27 | # when the modules are reloaded, MyKeyboardSettingsPanel has already replaced KeyboardSettingsPanel. 28 | # But we still have to put it back in place. 29 | cat = NVDASettingsDialog.categoryClasses[:] 30 | for c in cat: 31 | if c.__module__ == MyKeyboardSettingsPanel.__module__: 32 | NVDASettingsDialog.categoryClasses[NVDASettingsDialog.categoryClasses .index(c)] = MyKeyboardSettingsPanel 33 | break 34 | 35 | 36 | def myOnKeyboardSettingsCommand(*args, **kwargs): 37 | mainFrame.popupSettingsDialog(NVDASettingsDialog, MyKeyboardSettingsPanel) 38 | 39 | 40 | mainFrame.onKeyboardSettingsCommand = myOnKeyboardSettingsCommand 41 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/updateHandler/state.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # state.py 3 | # common Part of all of my add-ons 4 | # Copyright 2019 Paulber19 5 | 6 | 7 | import addonHandler 8 | from logHandler import log 9 | import os 10 | import time 11 | import pickle 12 | addonHandler.initTranslation() 13 | 14 | # delay between update checks 15 | addonUpdateCheckInterval = 86400 # one day 16 | #: Persistent state information. 17 | #: @type: dict 18 | _state = None 19 | _stateFileName = None 20 | 21 | 22 | #: The time to wait between checks. 23 | addonUpdateCheckInterval = 86400 # one day 24 | 25 | 26 | def initialize(): 27 | global _state, _stateFilename 28 | addonPath = addonHandler.getCodeAddon().path 29 | _stateFilename = os.path.join(addonPath, "updateCheckState.pickle") 30 | try: 31 | # 9038: Python 3 requires binary format when working with pickles. 32 | with open(_stateFilename, "rb") as f: 33 | _state = pickle.load(f) 34 | except Exception: 35 | log.debugWarning("update state file don't exist: initialization with default values", exc_info=False) 36 | # Defaults. 37 | _state = { 38 | "lastCheck": 0, 39 | "remindUpdate": False, 40 | } 41 | 42 | 43 | def saveState(): 44 | try: 45 | # #9038: Python 3 requires binary format when working with pickles. 46 | with open(_stateFilename, "wb") as f: 47 | pickle.dump(_state, f) 48 | except Exception: 49 | log.debugWarning("Error saving state", exc_info=True) 50 | 51 | 52 | def getLastCheck(): 53 | return _state["lastCheck"] 54 | 55 | 56 | def setLastCheck(): 57 | global _state 58 | _state["lastCheck"] = time.time() 59 | _state["remindUpdate"] = False 60 | saveState() 61 | 62 | 63 | def setRemindUpdate(on=True): 64 | global _state 65 | _state["lastCheck"] = time.time() 66 | _state["remindUpdate"] = on 67 | saveState() 68 | 69 | 70 | def getRemindUpdate(): 71 | return _state["remindUpdate"] 72 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\__init__.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2024 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | import os 7 | from logHandler import log 8 | 9 | 10 | def shouldLoadNVDAExtensionGlobalPlugin(): 11 | 12 | from .utils.nvdaInfos import NVDAVersion 13 | if NVDAVersion < [2024, 3]: 14 | import sys 15 | from .utils.py3Compatibility import getCommonUtilitiesPath 16 | sysPath = list(sys.path) 17 | psutilModulePath = None 18 | if "psutil" in sys.modules: 19 | log.warning("Potential incompatibility: psutil module is also used and loaded probably by other add-on") 20 | psutilModulePath = sys.modules["psutil"] 21 | del sys.modules["psutil"] 22 | sys.path = [sys.path[0]] 23 | commonUtilitiesPath = getCommonUtilitiesPath() 24 | psutilPath = os.path.join(commonUtilitiesPath, "psutilEx") 25 | sys.path.append(commonUtilitiesPath) 26 | sys.path.append(psutilPath) 27 | import psutilEx as psutil 28 | sys.path = sysPath 29 | del sys.modules["psutilEx"] 30 | if psutilModulePath is not None: 31 | sys.modules["psutil"] = psutilModulePath 32 | else: 33 | import psutil 34 | 35 | process = psutil.Process(os.getpid()) 36 | if process.name() == "nvda.exe": 37 | return True 38 | return False 39 | 40 | 41 | if shouldLoadNVDAExtensionGlobalPlugin(): 42 | from .theGlobalPlugin import NVDAExtensionGlobalPlugin 43 | else: 44 | from globalPluginHandler import GlobalPlugin as NVDAExtensionGlobalPlugin 45 | 46 | 47 | class GlobalPlugin (NVDAExtensionGlobalPlugin): 48 | # ??? this definition is necessary. 49 | # if not, the method of the NVDAExtensionGlobalPlugin class is never called. 50 | def chooseNVDAObjectOverlayClasses(self, obj, clsList): 51 | super(GlobalPlugin, self).chooseNVDAObjectOverlayClasses(obj, clsList) 52 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/legacy_em.py: -------------------------------------------------------------------------------- 1 | # Legacy Em Extension for Python-Markdown 2 | # ======================================= 3 | 4 | # This extension provides legacy behavior for _connected_words_. 5 | 6 | # Copyright 2015-2018 The Python Markdown Project 7 | 8 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 9 | 10 | """ 11 | This extension provides legacy behavior for _connected_words_. 12 | """ 13 | 14 | from __future__ import annotations 15 | 16 | from . import Extension 17 | from ..inlinepatterns import UnderscoreProcessor, EmStrongItem, EM_STRONG2_RE, STRONG_EM2_RE 18 | import re 19 | 20 | # _emphasis_ 21 | EMPHASIS_RE = r'(_)([^_]+)\1' 22 | 23 | # __strong__ 24 | STRONG_RE = r'(_{2})(.+?)\1' 25 | 26 | # __strong_em___ 27 | STRONG_EM_RE = r'(_)\1(?!\1)([^_]+?)\1(?!\1)(.+?)\1{3}' 28 | 29 | 30 | class LegacyUnderscoreProcessor(UnderscoreProcessor): 31 | """Emphasis processor for handling strong and em matches inside underscores.""" 32 | 33 | PATTERNS = [ 34 | EmStrongItem(re.compile(EM_STRONG2_RE, re.DOTALL | re.UNICODE), 'double', 'strong,em'), 35 | EmStrongItem(re.compile(STRONG_EM2_RE, re.DOTALL | re.UNICODE), 'double', 'em,strong'), 36 | EmStrongItem(re.compile(STRONG_EM_RE, re.DOTALL | re.UNICODE), 'double2', 'strong,em'), 37 | EmStrongItem(re.compile(STRONG_RE, re.DOTALL | re.UNICODE), 'single', 'strong'), 38 | EmStrongItem(re.compile(EMPHASIS_RE, re.DOTALL | re.UNICODE), 'single', 'em') 39 | ] 40 | 41 | 42 | class LegacyEmExtension(Extension): 43 | """ Add legacy_em extension to Markdown class.""" 44 | 45 | def extendMarkdown(self, md): 46 | """ Modify inline patterns. """ 47 | md.inlinePatterns.register(LegacyUnderscoreProcessor(r'_'), 'em_strong2', 50) 48 | 49 | 50 | def makeExtension(**kwargs): # pragma: no cover 51 | """ Return an instance of the `LegacyEmExtension` """ 52 | return LegacyEmExtension(**kwargs) 53 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/__meta__.py: -------------------------------------------------------------------------------- 1 | # Python Markdown 2 | 3 | # A Python implementation of John Gruber's Markdown. 4 | 5 | # Documentation: https://python-markdown.github.io/ 6 | # GitHub: https://github.com/Python-Markdown/markdown/ 7 | # PyPI: https://pypi.org/project/Markdown/ 8 | 9 | # Started by Manfred Stienstra (http://www.dwerg.net/). 10 | # Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org). 11 | # Currently maintained by Waylan Limberg (https://github.com/waylan), 12 | # Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser). 13 | 14 | # Copyright 2007-2023 The Python Markdown Project (v. 1.7 and later) 15 | # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 16 | # Copyright 2004 Manfred Stienstra (the original version) 17 | 18 | # License: BSD (see LICENSE.md for details). 19 | 20 | # __version_info__ format: 21 | # (major, minor, patch, dev/alpha/beta/rc/final, #) 22 | # (1, 1, 2, 'dev', 0) => "1.1.2.dev0" 23 | # (1, 1, 2, 'alpha', 1) => "1.1.2a1" 24 | # (1, 2, 0, 'beta', 2) => "1.2b2" 25 | # (1, 2, 0, 'rc', 4) => "1.2rc4" 26 | # (1, 2, 0, 'final', 0) => "1.2" 27 | 28 | from __future__ import annotations 29 | 30 | 31 | __version_info__ = (3, 7, 0, 'final', 0) 32 | 33 | 34 | def _get_version(version_info): 35 | " Returns a PEP 440-compliant version number from `version_info`. " 36 | assert len(version_info) == 5 37 | assert version_info[3] in ('dev', 'alpha', 'beta', 'rc', 'final') 38 | 39 | parts = 2 if version_info[2] == 0 else 3 40 | v = '.'.join(map(str, version_info[:parts])) 41 | 42 | if version_info[3] == 'dev': 43 | v += '.dev' + str(version_info[4]) 44 | elif version_info[3] != 'final': 45 | mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'rc'} 46 | v += mapping[version_info[3]] + str(version_info[4]) 47 | 48 | return v 49 | 50 | 51 | __version__ = _get_version(__version_info__) 52 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/__init__.py: -------------------------------------------------------------------------------- 1 | # Python Markdown 2 | 3 | # A Python implementation of John Gruber's Markdown. 4 | 5 | # - Documentation: https://python-markdown.github.io/ 6 | # - GitHub: https://github.com/Python-Markdown/markdown/ 7 | # - PyPI: https://pypi.org/project/Markdown/ 8 | 9 | # Started by Manfred Stienstra (http://www.dwerg.net/). 10 | # Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org). 11 | # Currently maintained by Waylan Limberg (https://github.com/waylan), 12 | # Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser). 13 | 14 | # - Copyright 2007-2023 The Python Markdown Project (v. 1.7 and later) 15 | # - Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 16 | # - Copyright 2004 Manfred Stienstra (the original version) 17 | 18 | # License: BSD (see LICENSE.md for details). 19 | 20 | """ 21 | Python-Markdown provides two public functions ([`markdown.markdown`][] and [`markdown.markdownFromFile`][]) 22 | both of which wrap the public class [`markdown.Markdown`][]. All submodules support these public functions 23 | and class and/or provide extension support. 24 | 25 | Modules: 26 | core: Core functionality. 27 | preprocessors: Pre-processors. 28 | blockparser: Core Markdown block parser. 29 | blockprocessors: Block processors. 30 | treeprocessors: Tree processors. 31 | inlinepatterns: Inline patterns. 32 | postprocessors: Post-processors. 33 | serializers: Serializers. 34 | util: Utility functions. 35 | htmlparser: HTML parser. 36 | test_tools: Testing utilities. 37 | extensions: Markdown extensions. 38 | """ 39 | 40 | from __future__ import annotations 41 | 42 | from .core import Markdown, markdown, markdownFromFile 43 | from .__meta__ import __version__, __version_info__ # noqa 44 | 45 | # For backward compatibility as some extensions expect it... 46 | from .extensions import Extension # noqa 47 | 48 | __all__ = ['Markdown', 'markdown', 'markdownFromFile'] 49 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/userInputGestures/inputGesturesExPatches.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\userInputGestures\inputGesturesExPatches.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | 6 | 7 | from logHandler import log 8 | import gui 9 | import wx 10 | from ..utils.NVDAStrings import NVDAString 11 | 12 | # global variable to save NVDA patched method 13 | _NVDAGuiMainFrameOnInputGesturesCommand = None 14 | 15 | 16 | def onInputGesturesCommandEx(evt): 17 | from .inputGesturesEx import InputGesturesDialogEx 18 | gui.mainFrame._popupSettingsDialog(InputGesturesDialogEx) 19 | 20 | 21 | def patche(install=True): 22 | if not install: 23 | removePatch() 24 | return 25 | global _NVDAGuiMainFrameOnInputGesturesCommand 26 | if _NVDAGuiMainFrameOnInputGesturesCommand is not None: 27 | return 28 | _NVDAGuiMainFrameOnInputGesturesCommand = gui.mainFrame.onInputGesturesCommand 29 | gui.mainFrame.onInputGesturesCommand = onInputGesturesCommandEx 30 | log.debug( 31 | "For user input gestures functionality," 32 | " fgui.mainFrame.onInputGesturesCommand has been patched by: %s of %s module " 33 | % (onInputGesturesCommandEx.__name__, onInputGesturesCommandEx.__module__)) 34 | 35 | menus = gui.mainFrame.sysTrayIcon.preferencesMenu.GetMenuItems() 36 | item = None 37 | for menuItem in menus: 38 | if menuItem.GetItemLabel() == NVDAString("I&nput gestures..."): 39 | item = menuItem 40 | break 41 | if item is not None: 42 | gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, onInputGesturesCommandEx, item) 43 | log.debug( 44 | "For user input gesture functionality," 45 | " %s of %s module is now the action for the Input gestures sub-menu " % ( 46 | onInputGesturesCommandEx.__name__, onInputGesturesCommandEx.__module__)) 47 | 48 | 49 | def removePatch(): 50 | global _NVDAGuiMainFrameOnInputGesturesCommand 51 | if _NVDAGuiMainFrameOnInputGesturesCommand is not None: 52 | gui.mainFrame.onInputGesturesCommand = _NVDAGuiMainFrameOnInputGesturesCommand 53 | _NVDAGuiMainFrameOnInputGesturesCommand = None 54 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/browseModeEx/NVDAObjectsIAccessible.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\browseModeEx\NVDAObjectsIAccessible.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from logHandler import log 8 | import config 9 | import controlTypes 10 | import NVDAObjects 11 | from .virtualBuffersEx import MSHTMLEx, Gecko_ia2_Ex, ChromeVBufEx 12 | import NVDAObjects.IAccessible.chromium 13 | 14 | 15 | class NVDAObjectMSHTMLEx(NVDAObjects.IAccessible.MSHTML.MSHTML): 16 | def _get_treeInterceptorClass(self): 17 | if ( 18 | self.role in (controlTypes.Role.DOCUMENT, controlTypes.Role.APPLICATION, controlTypes.Role.DIALOG) 19 | and not self.isContentEditable): 20 | return MSHTMLEx 21 | return super(NVDAObjectMSHTMLEx, self).treeInterceptorClass 22 | 23 | 24 | class NVDAObjectMozillaDocumentEx(NVDAObjects.IAccessible.mozilla .Document): 25 | def _get_treeInterceptorClass(self): 26 | if controlTypes.State.EDITABLE not in self.states: 27 | return Gecko_ia2_Ex 28 | return super(NVDAObjectMozillaDocumentEx, self).treeInterceptorClass 29 | 30 | 31 | class ChromiumDocument(NVDAObjects.IAccessible.chromium.Document): 32 | def _get_treeInterceptorClass(self): 33 | shouldLoadVBufOnBusyFeatureFlag = bool( 34 | config.conf["virtualBuffers"]["loadChromiumVBufOnBusyState"] 35 | ) 36 | vBufUnavailableStates = { # if any of these are in states, don't return ChromeVBuf 37 | controlTypes.State.EDITABLE, 38 | } 39 | if not shouldLoadVBufOnBusyFeatureFlag: 40 | log.debug( 41 | f"loadChromiumVBufOnBusyState feature flag is {shouldLoadVBufOnBusyFeatureFlag}," 42 | " vBuf WILL NOT be loaded when state of the document is busy." 43 | ) 44 | vBufUnavailableStates.add(controlTypes.State.BUSY) 45 | else: 46 | log.debug( 47 | f"loadChromiumVBufOnBusyState feature flag is {shouldLoadVBufOnBusyFeatureFlag}," 48 | " vBuf WILL be loaded when state of the document is busy." 49 | ) 50 | if self.states.intersection(vBufUnavailableStates): 51 | return super().treeInterceptorClass 52 | return ChromeVBufEx 53 | -------------------------------------------------------------------------------- /addon/utilities/pydubEx/playback.py: -------------------------------------------------------------------------------- 1 | """ 2 | Support for playing AudioSegments. Pyaudio will be used if it's installed, 3 | otherwise will fallback to ffplay. Pyaudio is a *much* nicer solution, but 4 | is tricky to install. See my notes on installing pyaudio in a virtualenv (on 5 | OSX 10.10): https://gist.github.com/jiaaro/9767512210a1d80a8a0d 6 | """ 7 | 8 | import subprocess 9 | from tempfile import NamedTemporaryFile 10 | from .utils import get_player_name, make_chunks 11 | 12 | def _play_with_ffplay(seg): 13 | PLAYER = get_player_name() 14 | with NamedTemporaryFile("w+b", suffix=".wav") as f: 15 | seg.export(f.name, "wav") 16 | subprocess.call([PLAYER, "-nodisp", "-autoexit", "-hide_banner", f.name]) 17 | 18 | 19 | def _play_with_pyaudio(seg): 20 | import pyaudio 21 | 22 | p = pyaudio.PyAudio() 23 | stream = p.open(format=p.get_format_from_width(seg.sample_width), 24 | channels=seg.channels, 25 | rate=seg.frame_rate, 26 | output=True) 27 | 28 | # Just in case there were any exceptions/interrupts, we release the resource 29 | # So as not to raise OSError: Device Unavailable should play() be used again 30 | try: 31 | # break audio into half-second chunks (to allows keyboard interrupts) 32 | for chunk in make_chunks(seg, 500): 33 | stream.write(chunk._data) 34 | finally: 35 | stream.stop_stream() 36 | stream.close() 37 | 38 | p.terminate() 39 | 40 | 41 | def _play_with_simpleaudio(seg): 42 | import simpleaudio 43 | return simpleaudio.play_buffer( 44 | seg.raw_data, 45 | num_channels=seg.channels, 46 | bytes_per_sample=seg.sample_width, 47 | sample_rate=seg.frame_rate 48 | ) 49 | 50 | 51 | def play(audio_segment): 52 | try: 53 | playback = _play_with_simpleaudio(audio_segment) 54 | try: 55 | playback.wait_done() 56 | except KeyboardInterrupt: 57 | playback.stop() 58 | except ImportError: 59 | pass 60 | else: 61 | return 62 | 63 | try: 64 | _play_with_pyaudio(audio_segment) 65 | return 66 | except ImportError: 67 | pass 68 | else: 69 | return 70 | 71 | _play_with_ffplay(audio_segment) 72 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/currentFolder/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\currentFolder\__init__ 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2020 Daniel Poiraud , Paulber19 4 | # This file is covered by the GNU General Public License. 5 | 6 | import addonHandler 7 | import api 8 | import ui 9 | 10 | addonHandler.initTranslation() 11 | 12 | 13 | def findChildObjectByClassName(obj, className): 14 | for o in obj.children: 15 | if o.windowClassName == className: 16 | return o 17 | return None 18 | 19 | 20 | def getCurrentFolder(): 21 | oForeground = api.getForegroundObject() 22 | # for Office 2003 and dialogbox based on XP 23 | windowText = oForeground.windowText 24 | # Translators: this is title of classic Window to manage file. 25 | if windowText in [_("Open"), _("Save"), _("Save as"), _("Find in")]: 26 | if 'bosa_sdm_' in oForeground.windowClassName: 27 | oCurrentFolder = oForeground.children[14] 28 | path = oCurrentFolder.name 29 | folder = oCurrentFolder.value 30 | return (path, folder) 31 | elif '#32770' in oForeground.windowClassName: 32 | if oForeground.children[1].windowClassName == 'ComboBox': 33 | oCurrentFolder = oForeground.children[1] 34 | path = "%s\\%s" % (oCurrentFolder.name, oCurrentFolder.value) 35 | path = oCurrentFolder.name 36 | folder = oCurrentFolder.value 37 | return (path, folder) 38 | classNames = ( 39 | "WorkerW", 40 | "ReBarWindow32", 41 | "Address Band Root", 42 | "msctls_progress32", 43 | "Breadcrumb Parent", 44 | "ToolbarWindow32") 45 | o = oForeground 46 | for className in classNames: 47 | o = findChildObjectByClassName(o, className) 48 | if o is None: 49 | break 50 | if o is None: 51 | return None 52 | pathList = [] 53 | for o in o.children: 54 | pathList.append(o.name) 55 | path = "\\".join(pathList[:-1]) 56 | folder = pathList[-1] 57 | return (path, folder) 58 | 59 | 60 | def reportCurrentFolder(sayPath=False): 61 | # Translators: message to the user. 62 | msgFolderNotFound = _("Selected folder name not found") 63 | currentFolder = getCurrentFolder() 64 | if currentFolder is None: 65 | ui.message(msgFolderNotFound) 66 | return 67 | (path, folder) = currentFolder 68 | if not sayPath: 69 | # report folder name 70 | ui.message(_("Folder %s") % folder) 71 | else: 72 | # report full folder path 73 | ui.message("%s\\%s" % (path, folder)) 74 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/numlock.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\utils\numlock.py 2 | # a part of NVDAExtensionGlobal add-on 3 | # Copyright (C) 2022-2023 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | import addonHandler 7 | from logHandler import log 8 | import wx 9 | import ui 10 | import winUser 11 | from ..settings.nvdaConfig import _NVDAConfigManager, ANL_NoChange, ANL_Off, ANL_On 12 | addonHandler.initTranslation() 13 | 14 | 15 | def manageNumlockActivation(): 16 | log.debug("manageNumlockActivation") 17 | from keyboardHandler import KeyboardInputGesture 18 | activateNumlockOption = _NVDAConfigManager.getActivateNumlockOption() 19 | curNumlockState = winUser.getKeyState(winUser.VK_NUMLOCK) 20 | if activateNumlockOption != ANL_NoChange: 21 | if ( 22 | (curNumlockState and (activateNumlockOption == ANL_Off)) 23 | or (not curNumlockState and (activateNumlockOption == ANL_On)) 24 | ): 25 | gesture = KeyboardInputGesture.fromName("numLock") 26 | gesture.send() 27 | wx.CallLater(200, gesture.reportExtra) 28 | 29 | 30 | def reportActivatedLockState(previousNumlockState, previousCapslockState): 31 | log.debug("reportActivatedLockState") 32 | numlockActivation = False 33 | capslockActivation = False 34 | from ..settings import ( 35 | toggleReportNumlockStateAtStartAdvancedOption, toggleReportCapslockStateAtStartAdvancedOption) 36 | if toggleReportNumlockStateAtStartAdvancedOption(False): 37 | numlockState = winUser.getKeyState(winUser.VK_NUMLOCK) 38 | numlockActivation = numlockState and numlockState == previousNumlockState 39 | if toggleReportCapslockStateAtStartAdvancedOption(False): 40 | capslockState = winUser.getKeyState(winUser.VK_CAPITAL) 41 | capslockActivation = capslockState and capslockState == previousCapslockState 42 | if not numlockActivation and not capslockActivation: 43 | return 44 | msg = None 45 | if numlockActivation and capslockActivation: 46 | # Translators: message to user to warn the enabled capital and numeric lock states 47 | msg = _("Warning: Numeric lock and capital locks are enabled") 48 | elif numlockActivation: 49 | # Translators: message to user to warn the enabled numeric lock state 50 | msg = _("Warning: Numeric lock is enabled") 51 | else: 52 | # Translators: message to user to warn the enabled capital state 53 | msg = _("Warning: capslock is enabled") 54 | if msg: 55 | ui.message(msg) 56 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/extra.py: -------------------------------------------------------------------------------- 1 | # Python-Markdown Extra Extension 2 | # =============================== 3 | 4 | # A compilation of various Python-Markdown extensions that imitates 5 | # [PHP Markdown Extra](http://michelf.com/projects/php-markdown/extra/). 6 | 7 | # See https://Python-Markdown.github.io/extensions/extra 8 | # for documentation. 9 | 10 | # Copyright The Python Markdown Project 11 | 12 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 13 | 14 | """ 15 | A compilation of various Python-Markdown extensions that imitates 16 | [PHP Markdown Extra](http://michelf.com/projects/php-markdown/extra/). 17 | 18 | Note that each of the individual extensions still need to be available 19 | on your `PYTHONPATH`. This extension simply wraps them all up as a 20 | convenience so that only one extension needs to be listed when 21 | initiating Markdown. See the documentation for each individual 22 | extension for specifics about that extension. 23 | 24 | There may be additional extensions that are distributed with 25 | Python-Markdown that are not included here in Extra. Those extensions 26 | are not part of PHP Markdown Extra, and therefore, not part of 27 | Python-Markdown Extra. If you really would like Extra to include 28 | additional extensions, we suggest creating your own clone of Extra 29 | under a different name. You could also edit the `extensions` global 30 | variable defined below, but be aware that such changes may be lost 31 | when you upgrade to any future version of Python-Markdown. 32 | 33 | See the [documentation](https://Python-Markdown.github.io/extensions/extra) 34 | for details. 35 | """ 36 | 37 | from __future__ import annotations 38 | 39 | from . import Extension 40 | 41 | extensions = [ 42 | 'fenced_code', 43 | 'footnotes', 44 | 'attr_list', 45 | 'def_list', 46 | 'tables', 47 | 'abbr', 48 | 'md_in_html' 49 | ] 50 | """ The list of included extensions. """ 51 | 52 | 53 | class ExtraExtension(Extension): 54 | """ Add various extensions to Markdown class.""" 55 | 56 | def __init__(self, **kwargs): 57 | """ `config` is a dumb holder which gets passed to the actual extension later. """ 58 | self.config = kwargs 59 | 60 | def extendMarkdown(self, md): 61 | """ Register extension instances. """ 62 | md.registerExtensions(extensions, self.config) 63 | 64 | 65 | def makeExtension(**kwargs): # pragma: no cover 66 | return ExtraExtension(**kwargs) 67 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/sane_lists.py: -------------------------------------------------------------------------------- 1 | # Sane List Extension for Python-Markdown 2 | # ======================================= 3 | 4 | # Modify the behavior of Lists in Python-Markdown to act in a sane manor. 5 | 6 | # See https://Python-Markdown.github.io/extensions/sane_lists 7 | # for documentation. 8 | 9 | # Original code Copyright 2011 [Waylan Limberg](http://achinghead.com) 10 | 11 | # All changes Copyright 2011-2014 The Python Markdown Project 12 | 13 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 14 | 15 | """ 16 | Modify the behavior of Lists in Python-Markdown to act in a sane manor. 17 | 18 | See [documentation](https://Python-Markdown.github.io/extensions/sane_lists) 19 | for details. 20 | """ 21 | 22 | from __future__ import annotations 23 | 24 | from . import Extension 25 | from ..blockprocessors import OListProcessor, UListProcessor 26 | import re 27 | from typing import TYPE_CHECKING 28 | 29 | if TYPE_CHECKING: # pragma: no cover 30 | from .. import blockparser 31 | 32 | 33 | class SaneOListProcessor(OListProcessor): 34 | """ Override `SIBLING_TAGS` to not include `ul` and set `LAZY_OL` to `False`. """ 35 | 36 | SIBLING_TAGS = ['ol'] 37 | """ Exclude `ul` from list of siblings. """ 38 | LAZY_OL = False 39 | """ Disable lazy list behavior. """ 40 | 41 | def __init__(self, parser: blockparser.BlockParser): 42 | super().__init__(parser) 43 | self.CHILD_RE = re.compile(r'^[ ]{0,%d}((\d+\.))[ ]+(.*)' % 44 | (self.tab_length - 1)) 45 | 46 | 47 | class SaneUListProcessor(UListProcessor): 48 | """ Override `SIBLING_TAGS` to not include `ol`. """ 49 | 50 | SIBLING_TAGS = ['ul'] 51 | """ Exclude `ol` from list of siblings. """ 52 | 53 | def __init__(self, parser: blockparser.BlockParser): 54 | super().__init__(parser) 55 | self.CHILD_RE = re.compile(r'^[ ]{0,%d}(([*+-]))[ ]+(.*)' % 56 | (self.tab_length - 1)) 57 | 58 | 59 | class SaneListExtension(Extension): 60 | """ Add sane lists to Markdown. """ 61 | 62 | def extendMarkdown(self, md): 63 | """ Override existing Processors. """ 64 | md.parser.blockprocessors.register(SaneOListProcessor(md.parser), 'olist', 40) 65 | md.parser.blockprocessors.register(SaneUListProcessor(md.parser), 'ulist', 30) 66 | 67 | 68 | def makeExtension(**kwargs): # pragma: no cover 69 | return SaneListExtension(**kwargs) 70 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/keyboard.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\utils\/keyboard.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016- 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | from logHandler import log 9 | import os.path 10 | from configobj import ConfigObj 11 | from configobj.validate import Validator 12 | from io import StringIO 13 | 14 | _configSpec = """ 15 | [KeyboardKeys] 16 | keys = string(default="") 17 | [editionKeyCommands] 18 | [default] 19 | copy = string(default = "kb:control+c") 20 | cut = string(default = "kb:control+x") 21 | paste = string( default = "kb:control+v") 22 | undo = string( default = "kb:control+z") 23 | selectAll = string( default = "kb:control+a") 24 | """ 25 | 26 | 27 | def getKeyboardKeysIniFilePath(): 28 | from languageHandler import getLanguage 29 | lang = getLanguage() 30 | langs = [lang, ] 31 | addonFolderPath = addonHandler.getCodeAddon().path 32 | if '_' in lang: 33 | langs.append(lang.split("_")[0]) 34 | langs.append("en") 35 | for lang in langs: 36 | langDir = os.path.join(addonFolderPath, "locale", lang) 37 | if os.path.exists(langDir): 38 | file = os.path.join(langDir, "keyboard.ini") 39 | if os.path.isfile(file): 40 | log.debugWarning("keyboard.ini file loaded from locale\\%s folder" % lang) 41 | return file 42 | log.error("keyboard.ini file not found") 43 | return "" 44 | 45 | 46 | def getKeyboardKeys(): 47 | keys = getKeyboardIniConfig()["KeyboardKeys"]["keys"] 48 | return list(keys) 49 | 50 | 51 | def getEditionKeyCommands(obj=None): 52 | conf = getKeyboardIniConfig()["editionKeyCommands"].copy() 53 | d = conf["default"].copy() 54 | if obj is None: 55 | return d 56 | appName = obj.appModule.appName 57 | if appName in conf: 58 | d.update(conf[appName]) 59 | return d 60 | 61 | 62 | def getKeyboardIniConfig(): 63 | global _conf 64 | if _conf is not None: 65 | return _conf 66 | path = getKeyboardKeysIniFilePath() 67 | conf = ConfigObj( 68 | path, 69 | configspec=StringIO(_configSpec), 70 | encoding="utf-8", 71 | list_values=False) 72 | conf.newlines = "\r\n" 73 | val = Validator() 74 | ret = conf.validate(val, preserve_errors=True, copy=True) 75 | if not ret: 76 | log.warning("KeyboardKeys configuration file is invalid: %s", ret) 77 | _conf = conf 78 | return conf 79 | 80 | 81 | # singleton 82 | _conf = None 83 | -------------------------------------------------------------------------------- /addon/doc/ar/addonUserManual.t2t: -------------------------------------------------------------------------------- 1 | ADDON_SUMMARY - دليل المستخدم 2 | المؤلف: ADDON_AUTHOR_NAME 3 | 4 | 5 | %!includeconf: ../addon_userManual.t2tconf 6 | %!includeconf: addon_informations.t2tconf 7 | %!includeconf: addon_keys.t2tconf 8 | عنوان URL: [ADDON_REPOSITORY ADDON_REPOSITORY] 9 | 10 | 11 | تحميل: 12 | - [إصدار ثابت ADDON_CUR_VERSION ADDON_DOWNLOAD_SERVER1] 13 | - [إصدار التطوير ADDON_DEV_URL] 14 | 15 | 16 | التوافق: 17 | - Nminimum المدعومة من إصدار NVDA: MINIMUM_NVDA_VERSION 18 | - آخر إصدار تم اختباره من NVDA: LAST_TESTED_NVDA_VERSION 19 | 20 | 21 | Traductor (s): ترجمة آلية من اللغة الفرنسية 22 | = سومير = [toc] 23 | %%toc 24 | 25 | 26 | + مقدمة + 27 | ++ عام ++ 28 | عذرًا ، لكن هذا الدليل غير متوفر باللغة الإنجليزية اليوم. 29 | الدليل الأصلي مكتوب بالفرنسية ([دليل فرنسي ../fr/addonUserManual.html]) ولم تتم ترجمته حتى يومنا هذا. 30 | 31 | 32 | 33 | ++ التحديث ++ 34 | يتم تحديث الإضافة بشكل افتراضي تلقائيًا بعد وقت قصير من بدء NVDA (بين 20 و 600 ثانية) وبحد أقصى مرة واحدة يوميًا. 35 | من الممكن تعطيل هذا التحديث بإلغاء تحديد الخيار "البحث التلقائي عن التحديثات" لفئة "تحديث" في إعدادات الوظيفة الإضافية. 36 | يمكن أن يكون إصدار الوظيفة الإضافية: 37 | - نسخة مستقرة: رقم نسختها هو "1.0" على سبيل المثال. 38 | - إما إصدار تطوير: رقم الإصدار من النوع "1.0-dev1" أو "1.0-rc1" أو "1.0-beta2". 39 | 40 | 41 | بشكل افتراضي ، يتم تحديث الإصدار الثابت بإصدار ثابت أحدث (رقم إصدار أعلى). 42 | ولكن من الممكن تحديث الإصدار الثابت الذي يعمل بإصدار مطور من الإصدار الثابت التالي. ما عليك سوى تحديد الخيار "تحديث أيضًا تحديث الإصدار الثابت لإصدارات التطوير" الموجود في فئة "تحديث" لإعدادات الوظائف الإضافية. 43 | 44 | يتم تحديث نسخة التطوير: 45 | - بإصدار تطوير أحدث ، 46 | - بنسخته المستقرة ، 47 | - أو باستخدام أحدث إصدار ثابت إذا لم يتم تحديد الخيار السابق. 48 | 49 | 50 | يتيح لك الزر "بحث عن تحديث" الموجود في إعدادات الوظيفة الإضافية ، عنصر القائمة "تحديث" ، البحث على الفور عن تحديث. 51 | 52 | 53 | يتيح لك زر "عرض المحفوظات" ، الموجود في نفس الفئة ، عرض محفوظات الإصدار الحالي في المتصفح. 54 | 55 | في حالة التحديث التلقائي وفي حالة اكتشاف إصدار جديد ، يتم عرض مربع الحوار "تحديث" ليقترح ما يلي: 56 | - إما التثبيت الفوري للإصدار الجديد ، 57 | - أو تأجيل التحديث إلى وقت لاحق. في هذه الحالة ، سيتم إعادة البحث بعد ساعة واحدة على الأقل. 58 | 59 | 60 | في حالة التحديث لإصدار مستقر ، يوفر زر "ما الجديد" إمكانية فتح محفوظات الوظيفة الإضافية في المتصفح وبالتالي القدرة على معرفة الميزات الجديدة للإصدار المقترح. 61 | 62 | 63 | ++ تاريخية ++ 64 | محفوظات إصدار هذه الوظيفة الإضافية موجودة في الملف: ["Changes.html" Changes.html] -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/speech/sayError.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\speech\sayError.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | 6 | import addonHandler 7 | # from logHandler import log 8 | import api 9 | import os 10 | import globalVars 11 | import speech 12 | import config 13 | from .commands import BeepWithPauseCommand 14 | 15 | addonHandler.initTranslation() 16 | 17 | 18 | class SayErrorProfileTrigger(config.ProfileTrigger): 19 | spec = "sayError" 20 | 21 | 22 | def getErrorSoundSpeechSequence(error=None): 23 | from speech.commands import WaveFileCommand 24 | fileName = os.path.join(globalVars.appDir, "waves", "textError.wav") 25 | seq = [ 26 | speech.commands.EndUtteranceCommand(), 27 | WaveFileCommand(fileName), 28 | speech.commands.EndUtteranceCommand() 29 | ] 30 | if error is not None: 31 | seq.extend([ 32 | error, 33 | speech.commands.EndUtteranceCommand(), 34 | ]) 35 | return seq 36 | 37 | 38 | def getErrorBeepSpeechSequence(error=None): 39 | seq = [ 40 | speech.commands.EndUtteranceCommand(), 41 | BeepWithPauseCommand(150, 50), 42 | speech.commands.EndUtteranceCommand(), 43 | BeepWithPauseCommand(150, 50), 44 | speech.commands.EndUtteranceCommand(), 45 | ] 46 | if error is not None and error != "" and not error.isspace(): 47 | seq.extend([ 48 | error, 49 | speech.commands.EndUtteranceCommand(), 50 | ]) 51 | return seq 52 | 53 | 54 | def getErrorVoiceSpeechSequence(error=None): 55 | if error is None: 56 | return [] 57 | t1 = SayErrorProfileTrigger() 58 | return [ 59 | speech.commands.ConfigProfileTriggerCommand(t1, True), 60 | error, 61 | speech.commands.ConfigProfileTriggerCommand(t1, False), 62 | ] 63 | 64 | 65 | def getErrorSpeechSequence(error=None, reading=False): 66 | from ..settings import _addonConfigManager 67 | if _addonConfigManager.reportingSpellingErrorsByErrorReporting(reading=reading): 68 | return getErrorVoiceSpeechSequence(error) 69 | elif _addonConfigManager.reportingSpellingErrorsByBeep(reading=reading): 70 | return getErrorBeepSpeechSequence(error) 71 | elif _addonConfigManager.reportingSpellingErrorsBySound(reading=reading): 72 | return getErrorSoundSpeechSequence(error) 73 | elif error is not None: 74 | return [error] 75 | return None 76 | 77 | 78 | def initialize(): 79 | # Translators: name of say error profile 80 | name = _("Spelling errors' announcement") 81 | name = api.filterFileName(name) 82 | config.conf.triggersToProfiles["sayError"] = name 83 | fn = config.conf._getProfileFn(name) 84 | if os.path.isfile(fn): 85 | # the profile already exists 86 | return 87 | config.conf.createProfile(name) 88 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/beep.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\tonesEx.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2023-2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | from logHandler import log 9 | import tones 10 | import time 11 | import nvwave 12 | from ctypes import create_string_buffer 13 | from ..utils.nvdaInfos import NVDAVersion 14 | 15 | # temporary wave player 16 | _player = None 17 | 18 | 19 | def getPlayer(outputDevice): 20 | global _player 21 | if outputDevice is None: 22 | return tones.player 23 | try: 24 | _player = nvwave.WavePlayer( 25 | channels=2, 26 | samplesPerSec=int(tones.SAMPLE_RATE), 27 | bitsPerSample=16, 28 | outputDevice=outputDevice, 29 | wantDucking=False 30 | ) 31 | except Exception: 32 | log.warning("Failed to initialize audio for tones", exc_info=True) 33 | _player = None 34 | return _player 35 | 36 | 37 | def myBeep( 38 | hz: float, 39 | length: int, 40 | left: int = None, 41 | right: int = None, 42 | isSpeechBeepCommand: bool = False, 43 | device=None 44 | ): 45 | """Plays a tone at the given hz, length, and stereo balance. 46 | @param hz: pitch in hz of the tone 47 | @param length: length of the tone in ms 48 | @param left: volume of the left channel (0 to 100) 49 | @param right: volume of the right channel (0 to 100) 50 | @param isSpeechBeepCommand: whether this beep is created as part of a speech sequence 51 | @device: audio output device 52 | """ 53 | from ..settings import _addonConfigManager 54 | tonalitiesVolumeLevel = _addonConfigManager.getTonalitiesVolumeLevel() 55 | if left is None: 56 | left = tonalitiesVolumeLevel 57 | if right is None: 58 | right = tonalitiesVolumeLevel 59 | log.io("Beep at pitch %s, for %s ms, left volume %s, right volume %s" % (hz, length, left, right)) 60 | 61 | if not tones.decide_beep.decide( 62 | hz=hz, 63 | length=length, 64 | left=left, 65 | right=right, 66 | isSpeechBeepCommand=isSpeechBeepCommand 67 | ): 68 | log.debug( 69 | "Beep canceled by handler registered to decide_beep extension point" 70 | ) 71 | return 72 | 73 | global _player 74 | _player = getPlayer(device) 75 | if not _player: 76 | return 77 | from NVDAHelper import generateBeep 78 | bufSize = generateBeep(None, hz, length, left, right) 79 | buf = create_string_buffer(bufSize) 80 | generateBeep(buf, hz, length, left, right) 81 | _player.stop() 82 | _player.feed(buf.raw) 83 | 84 | 85 | def playTonesOnDevice(outputDevice): 86 | outputDeviceName, outputDeviceId = outputDevice 87 | log.debug("playTonesOnDevice: %s" % outputDeviceName) 88 | device = outputDeviceName if NVDAVersion < [2025, 1] else outputDeviceId 89 | myBeep(hz=250, length=100, device=device) 90 | time.sleep(0.3) 91 | myBeep(hz=350, length=100, device=device) 92 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/messageDialogs.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\messageDialogs.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | import wx 9 | from gui.guiHelper import ( 10 | BoxSizerHelper, 11 | BORDER_FOR_DIALOGS, 12 | ButtonHelper, 13 | SPACE_BETWEEN_VERTICAL_DIALOG_ITEMS, 14 | ) 15 | import windowUtils 16 | from ..utils import makeAddonWindowTitle, getHelpObj 17 | from ..gui import contextHelpEx 18 | 19 | addonHandler.initTranslation() 20 | 21 | 22 | class SplitAudioWarningDialog( 23 | contextHelpEx.ContextHelpMixinEx, 24 | wx.Dialog, # wxPython does not seem to call base class initializer, put last in MRO 25 | ): 26 | """A dialog warning the user about the risks of incompatibility with NVDA split audio.""" 27 | # help in the user manual. 28 | helpObj = getHelpObj("hdr34") 29 | 30 | def __init__(self, parent: wx.Window): 31 | # Translators: The warning of a dialog 32 | dialogTitle = makeAddonWindowTitle(_("Warning")) 33 | super().__init__(parent, title=dialogTitle) 34 | mainSizer = wx.BoxSizer(wx.VERTICAL) 35 | sHelper = BoxSizerHelper(self, orientation=wx.VERTICAL) 36 | # Translators: Warning that is displayed at add-on start when nvda split audio is not in desactivated state 37 | _warningText = _( 38 | "The NVDA Split audio mode being in disabled mode," 39 | " it may be in contradiction with the Split audio functionality of the add-on.") 40 | sText = sHelper.addItem(wx.StaticText(self, label=_warningText)) 41 | # the wx.Window must be constructed before we can get the handle. 42 | self.scaleFactor = windowUtils.getWindowScalingFactor(self.GetHandle()) 43 | sText.Wrap( 44 | # 600 was fairly arbitrarily chosen by a visual user to look acceptable on their machine. 45 | self.scaleFactor * 600, 46 | ) 47 | 48 | sHelper.sizer.AddSpacer(SPACE_BETWEEN_VERTICAL_DIALOG_ITEMS) 49 | self.dontShowAgainCheckbox = sHelper.addItem( 50 | wx.CheckBox( 51 | self, 52 | label=_( 53 | # Translators: The label of a checkbox in the split audio warning dialog 54 | "&Don't show this message again", 55 | ), 56 | ), 57 | ) 58 | 59 | bHelper = sHelper.addDialogDismissButtons(ButtonHelper(wx.HORIZONTAL)) 60 | # Translators: The label of a button in a dialog 61 | okButton = bHelper.addButton(self, wx.ID_OK, label=pgettext("addonStore", "&OK")) 62 | okButton.Bind(wx.EVT_BUTTON, self.onOkButton) 63 | 64 | mainSizer.Add(sHelper.sizer, border=BORDER_FOR_DIALOGS, flag=wx.ALL) 65 | self.Sizer = mainSizer 66 | mainSizer.Fit(self) 67 | self.CentreOnScreen() 68 | 69 | def onOkButton(self, evt: wx.CommandEvent): 70 | # addonDataManager.storeSettings.showWarning = not self.dontShowAgainCheckbox.GetValue() 71 | self.EndModal(wx.ID_OK) 72 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/meta.py: -------------------------------------------------------------------------------- 1 | # Meta Data Extension for Python-Markdown 2 | # ======================================= 3 | 4 | # This extension adds Meta Data handling to markdown. 5 | 6 | # See https://Python-Markdown.github.io/extensions/meta_data 7 | # for documentation. 8 | 9 | # Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com). 10 | 11 | # All changes Copyright 2008-2014 The Python Markdown Project 12 | 13 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 14 | 15 | """ 16 | This extension adds Meta Data handling to markdown. 17 | 18 | See the [documentation](https://Python-Markdown.github.io/extensions/meta_data) 19 | for details. 20 | """ 21 | 22 | from __future__ import annotations 23 | 24 | from . import Extension 25 | from ..preprocessors import Preprocessor 26 | import re 27 | import logging 28 | from typing import Any 29 | 30 | log = logging.getLogger('MARKDOWN') 31 | 32 | # Global Vars 33 | META_RE = re.compile(r'^[ ]{0,3}(?P[A-Za-z0-9_-]+):\s*(?P.*)') 34 | META_MORE_RE = re.compile(r'^[ ]{4,}(?P.*)') 35 | BEGIN_RE = re.compile(r'^-{3}(\s.*)?') 36 | END_RE = re.compile(r'^(-{3}|\.{3})(\s.*)?') 37 | 38 | 39 | class MetaExtension (Extension): 40 | """ Meta-Data extension for Python-Markdown. """ 41 | 42 | def extendMarkdown(self, md): 43 | """ Add `MetaPreprocessor` to Markdown instance. """ 44 | md.registerExtension(self) 45 | self.md = md 46 | md.preprocessors.register(MetaPreprocessor(md), 'meta', 27) 47 | 48 | def reset(self) -> None: 49 | self.md.Meta = {} 50 | 51 | 52 | class MetaPreprocessor(Preprocessor): 53 | """ Get Meta-Data. """ 54 | 55 | def run(self, lines: list[str]) -> list[str]: 56 | """ Parse Meta-Data and store in Markdown.Meta. """ 57 | meta: dict[str, Any] = {} 58 | key = None 59 | if lines and BEGIN_RE.match(lines[0]): 60 | lines.pop(0) 61 | while lines: 62 | line = lines.pop(0) 63 | m1 = META_RE.match(line) 64 | if line.strip() == '' or END_RE.match(line): 65 | break # blank line or end of YAML header - done 66 | if m1: 67 | key = m1.group('key').lower().strip() 68 | value = m1.group('value').strip() 69 | try: 70 | meta[key].append(value) 71 | except KeyError: 72 | meta[key] = [value] 73 | else: 74 | m2 = META_MORE_RE.match(line) 75 | if m2 and key: 76 | # Add another line to existing key 77 | meta[key].append(m2.group('value').strip()) 78 | else: 79 | lines.insert(0, line) 80 | break # no meta data - done 81 | self.md.Meta = meta 82 | return lines 83 | 84 | 85 | def makeExtension(**kwargs): # pragma: no cover 86 | return MetaExtension(**kwargs) 87 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/audioUtils.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\audioUtils.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from logHandler import log 8 | import config 9 | from ..utils.NVDAStrings import NVDAString 10 | from ..utils.nvdaInfos import NVDAVersion 11 | 12 | 13 | def isWasapiUsed(): 14 | # nvda 2025.1 and above use Wasapi 15 | if NVDAVersion >= [2025, 1]: 16 | return True 17 | 18 | # wasapi can be used since nvda 2023.2 19 | # by checking the advanced option: use wasapi for audio output 20 | try: 21 | from nvwave import WasapiWavePlayer, WavePlayer 22 | if WavePlayer == WasapiWavePlayer: 23 | return True 24 | except Exception: 25 | pass 26 | return False 27 | 28 | 29 | def getOutputDevice(): 30 | try: 31 | # for nvda version >= 2025.1 32 | return config.conf["audio"]["outputDevice"] 33 | except KeyError: 34 | # for nvda version < 2025.1 35 | return config.conf["speech"]["outputDevice"] 36 | 37 | 38 | def getOutputDeviceName(outputDevice): 39 | log.debug("getDeviceName: %s" % outputDevice) 40 | # for nvda >= 2025.1, outputDevice is stored in "audio" section instead of "speech" section 41 | # and it is stored by its id instead its name 42 | # else outputDevice is the output device name 43 | if "outputDevice" not in config.conf["audio"]: 44 | return outputDevice 45 | # for nvda version >= 2025.1 46 | deviceIds, deviceNames = get_outputDevices() 47 | try: 48 | outputDeviceName = deviceNames[deviceIds.index(outputDevice)] 49 | except ValueError: 50 | # We assume it is the default device 51 | outputDeviceName = deviceNames[0] 52 | if outputDeviceName is None: 53 | # Translators: name for default (Microsoft Sound Mapper) audio output device. 54 | outputDeviceName = NVDAString("Microsoft Sound Mapper") 55 | return outputDeviceName 56 | 57 | 58 | def setOutputDevice(device): 59 | if "outputDevice" in config.conf["audio"]: 60 | # for nvda version >= 2025.1 61 | config.conf["audio"]["outputDevice"] = device 62 | else: 63 | # for nvda version < 2025.1 64 | config.conf["speech"]["outputDevice"] = device 65 | 66 | 67 | def get_outputDevices(): 68 | if NVDAVersion < [2025, 1]: 69 | from nvwave import _getOutputDevices 70 | devices = [(ID, name) for ID, name in _getOutputDevices()] 71 | deviceIds = [ID for ID, name in devices] 72 | deviceNames = [name for id, name in devices] 73 | # #11349: On Windows 10 20H1 and 20H2, Microsoft Sound Mapper returns an empty string. 74 | if deviceNames[0] in ("", "Microsoft Sound Mapper"): 75 | # Translators: name for default (Microsoft Sound Mapper) audio output device. 76 | deviceNames[0] = NVDAString("Microsoft Sound Mapper") 77 | else: 78 | from utils import mmdevice 79 | deviceIds, deviceNames = zip(*mmdevice.getOutputDevices(includeDefault=True)) 80 | return deviceIds, deviceNames 81 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/tools/buildVars.py.tpl: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # Build customizations 4 | # Change this file instead of sconstruct or manifest files, whenever possible. 5 | 6 | 7 | # Since some strings in "addon_info" are translatable, 8 | # we need to include them in the .po files. 9 | # Gettext recognizes only strings given as parameters to the "_" function. 10 | # To avoid initializing translations in this module we simply roll our own "fake" "_" function 11 | # which returns whatever is given to it as an argument. 12 | def _(arg): 13 | return arg 14 | 15 | # Add-on information variables 16 | {addonInfoStart} 17 | # add-on Name/identifier, internal for NVDA 18 | "addon_name": "{name}", 19 | # Add-on summary, usually the user visible name of the addon. 20 | # Translators: Summary for this add-on to be shown 21 | # on installation and add-on information. 22 | "addon_summary": _("{summary}"), 23 | # Add-on description 24 | # Translators: Long description to be shown for this add-on 25 | # on add-on information from add-ons manager 26 | "addon_description": _("""{description}"""), 27 | # version 28 | "addon_version": "{version}", 29 | # Author(s) 30 | "addon_author": u"{author}", 31 | # URL for the add-on documentation support 32 | "addon_url": "{url}", 33 | # URL for the add-on repository where the source code can be found 34 | "addon_sourceURL": None, 35 | # Documentation file name 36 | "addon_docFileName": "{docFileName}", 37 | # Minimum NVDA version supported (e.g. "2018.3") 38 | "addon_minimumNVDAVersion": "{minimumNVDAVersion}", 39 | # Last NVDA version supported/tested 40 | # (e.g. "2018.4", ideally more recent than minimum version) 41 | "addon_lastTestedNVDAVersion": "{lastTestedNVDAVersion}", 42 | # Add-on update channel (default is stable or None) 43 | "addon_updateChannel": "{updateChannel}", 44 | # Add-on license such as GPL 2 45 | "addon_license": None, 46 | # URL for the license document the ad-on is licensed under 47 | "addon_licenseURL": None, 48 | {addonInfoEnd} 49 | 50 | # Define the python files that are the sources of your add-on. 51 | # You can use glob expressions here, they will be expanded. 52 | pythonSources = [] 53 | 54 | # Files that contain strings for translation. Usually your python sources 55 | i18nSources = pythonSources 56 | 57 | # Files that will be ignored when building the nvda-addon file 58 | # Paths are relative to the addon directory, 59 | # not to the root directory of your addon sources. 60 | excludedFiles = [] 61 | 62 | # If your add-on is written in a language other than english, 63 | # modify this variable. 64 | # For example: 65 | # set baseLanguage to "es" if your add-on is primarily written in spanish. 66 | baseLanguage = "en" 67 | 68 | # Markdown extensions for add-on documentation 69 | # Most add-ons do not require additional Markdown extensions. 70 | # If you need to add support for markup such as tables, fill out the below list. 71 | # Extensions string must be of the form "markdown.extensions.extensionName" 72 | # e.g. "markdown.extensions.tables" to add tables. 73 | markdownExtensions = [] 74 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/legacy_attrs.py: -------------------------------------------------------------------------------- 1 | # Python Markdown 2 | 3 | # A Python implementation of John Gruber's Markdown. 4 | 5 | # Documentation: https://python-markdown.github.io/ 6 | # GitHub: https://github.com/Python-Markdown/markdown/ 7 | # PyPI: https://pypi.org/project/Markdown/ 8 | 9 | # Started by Manfred Stienstra (http://www.dwerg.net/). 10 | # Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org). 11 | # Currently maintained by Waylan Limberg (https://github.com/waylan), 12 | # Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser). 13 | 14 | # Copyright 2007-2023 The Python Markdown Project (v. 1.7 and later) 15 | # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 16 | # Copyright 2004 Manfred Stienstra (the original version) 17 | 18 | # License: BSD (see LICENSE.md for details). 19 | 20 | """ 21 | An extension to Python Markdown which implements legacy attributes. 22 | 23 | Prior to Python-Markdown version 3.0, the Markdown class had an `enable_attributes` 24 | keyword which was on by default and provided for attributes to be defined for elements 25 | using the format `{@key=value}`. This extension is provided as a replacement for 26 | backward compatibility. New documents should be authored using `attr_lists`. However, 27 | numerous documents exist which have been using the old attribute format for many 28 | years. This extension can be used to continue to render those documents correctly. 29 | """ 30 | 31 | from __future__ import annotations 32 | 33 | import re 34 | from markdown.treeprocessors import Treeprocessor, isString 35 | from markdown.extensions import Extension 36 | from typing import TYPE_CHECKING 37 | 38 | if TYPE_CHECKING: # pragma: no cover 39 | import xml.etree.ElementTree as etree 40 | 41 | 42 | ATTR_RE = re.compile(r'\{@([^\}]*)=([^\}]*)}') # {@id=123} 43 | 44 | 45 | class LegacyAttrs(Treeprocessor): 46 | def run(self, doc: etree.Element) -> None: 47 | """Find and set values of attributes ({@key=value}). """ 48 | for el in doc.iter(): 49 | alt = el.get('alt', None) 50 | if alt is not None: 51 | el.set('alt', self.handleAttributes(el, alt)) 52 | if el.text and isString(el.text): 53 | el.text = self.handleAttributes(el, el.text) 54 | if el.tail and isString(el.tail): 55 | el.tail = self.handleAttributes(el, el.tail) 56 | 57 | def handleAttributes(self, el: etree.Element, txt: str) -> str: 58 | """ Set attributes and return text without definitions. """ 59 | def attributeCallback(match: re.Match[str]): 60 | el.set(match.group(1), match.group(2).replace('\n', ' ')) 61 | return ATTR_RE.sub(attributeCallback, txt) 62 | 63 | 64 | class LegacyAttrExtension(Extension): 65 | def extendMarkdown(self, md): 66 | """ Add `LegacyAttrs` to Markdown instance. """ 67 | md.treeprocessors.register(LegacyAttrs(md), 'legacyattrs', 15) 68 | 69 | 70 | def makeExtension(**kwargs): # pragma: no cover 71 | return LegacyAttrExtension(**kwargs) 72 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/clipboardCommandAnnouncement/clipboard.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\clipboardCommandAnnouncement\clipboard.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2022 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | # some parts of code were inspired from the code of Clipboard_monitor.py module of clipSpeak add-on 8 | # written By Damien Lindley, created: 20th April 2017 9 | 10 | from winUser import user32 11 | from logHandler import log 12 | 13 | 14 | class ClipboardManager(object): 15 | 16 | def __init__(self): 17 | log.debug("Initialising clipboard manager.") 18 | self.sequenceNumber = user32.GetClipboardSequenceNumber() 19 | log.debug("clipboard manager init: current sequence number = %s" % self.sequenceNumber) 20 | 21 | def getClipboardDatas(self): 22 | log.debug("getting clipboard data...") 23 | data = {} 24 | log.debug("Opening the clipboard for enumeration.") 25 | try: 26 | user32.OpenClipboard(None) 27 | except Exception: 28 | log.debug("Clipboard failed to open. Cannot enumerate.") 29 | return data 30 | format = 0 31 | while True: 32 | try: 33 | format = user32.EnumClipboardFormats(format) 34 | log.debug("Retrieving clipboard format: %d" % format) 35 | if format == 0: 36 | break 37 | pos = str(format) 38 | log.debug("Retrieving data for format %s" % pos) 39 | data[pos] = user32.GetClipboardData(format) 40 | log.debug("Data retrieved: %r" % data[pos]) 41 | except Exception: 42 | log.debug("Cannot retrieve data.") 43 | break 44 | log.debug("Closing clipboard.") 45 | user32.CloseClipboard() 46 | return data 47 | 48 | def changed(self): 49 | log.debug("Checking for clipboard changes.") 50 | sequenceNumber = user32.GetClipboardSequenceNumber() 51 | if sequenceNumber == self.sequenceNumber: 52 | log.debug("No changes detected.") 53 | return False 54 | log.debug("Clipboard data has changed. Updating sequence number: %s" % sequenceNumber) 55 | self.sequenceNumber = sequenceNumber 56 | return True 57 | 58 | @property 59 | def isEmpty(self): 60 | log.debug("check if clipboard is empty") 61 | log.debug("Opening the clipboard for enumeration.") 62 | try: 63 | user32.OpenClipboard(None) 64 | except Exception: 65 | log.debug("Clipboard failed to open. Cannot check") 66 | return False 67 | format = 0 68 | try: 69 | format = user32.EnumClipboardFormats(format) 70 | except Exception: 71 | log.debug("Cannot enumerate.") 72 | format = 1 73 | log.debug("Closing clipboard.") 74 | user32.CloseClipboard() 75 | return format == 0 76 | 77 | def clear(self): 78 | log.debug("Opening the clipboard for clearing.") 79 | try: 80 | user32.OpenClipboard(None) 81 | except Exception: 82 | log.debug("Clipboard failed to open. Cannot clear.") 83 | return False 84 | res = user32.EmptyClipboard() 85 | if not res: 86 | log.debug("Clipboard failed to clear. Cannot clear.") 87 | user32.CloseClipboard() 88 | log.debug("clipboard is cleared") 89 | return res 90 | -------------------------------------------------------------------------------- /addon/locale/tr/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Küçük harf aksanlı ünlüler] 8 | á vurgulu küçük a 9 | é vurgulu küçük e 10 | í vurgulu küçük i 11 | ó vurgulu küçük o 12 | ú vurgulu küçük u 13 | ý vurgulu küçük y 14 | à aksanlı küçük a 15 | è aksanlı küçük e 16 | ì aksanlı küçük i 17 | ò aksanlı küçük o 18 | ù aksanlı küçük u 19 | â ince küçük a 20 | ê ince küçük e 21 | î ince küçük i 22 | ô ince küçük o 23 | û ince küçük u 24 | ã tildeli küçük a 25 | ñ tildeli küçük n 26 | õ tildeli küçük o 27 | ä çift noktalı küçük a 28 | ë çift noktalı küçük e 29 | ï çift noktalı küçük i 30 | ö ö 31 | ü ü 32 | 33 | [Büyük aksanlı ünlüler] 34 | Á vurgulu büyük a 35 | É vurgulu büyük e 36 | Í vurgulu büyük i 37 | Ó vurgulu büyük o 38 | Ú vurgulu büyük u 39 | Ý vurgulu büyük y 40 | À aksanlı büyük a 41 | È aksanlı büyük e 42 | Ì aksanlı büyük i 43 | Ò aksanlı büyük o 44 | Ù aksanlı büyük u 45 |  ince büyük a 46 | Ê ince büyük e 47 | Î ince büyük i 48 | Ô ince büyük o 49 | Û ince büyük u 50 | à tildeli büyük a 51 | Ñ tildeli büyük n 52 | Õ tildeli büyük o 53 | Ä çift noktalı büyük a 54 | Ë çift noktalı büyük e 55 | Ï çift noktalı büyük i 56 | Ö Ö 57 | Ü Ü 58 | 59 | [parasal semboller] 60 | € Avro para birimi 61 | $ Dolar işareti 62 | ¢ sent işareti 63 | £ İngiliz Sterlini 64 | ¥ Japon Yeni 65 | ƒ Hollanda Florini 66 | ₺ türk lirası 67 | ¤ Genel para birimi sembolü 68 | 69 | [Matematik sembolleri] 70 | ÷ bölüm işareti 71 | × çarpma işareti 72 | ± Artı/eksi 73 | ¹ üssü 1 74 | ² üssü 2 75 | ³ üssü 3 76 | ⁿ üssü N 77 | ° derece sembolü 78 | µ Mikro 79 | ‰ binde işareti 80 | ‰ milyonda 81 | ¼ kesir 1/4 82 | ½ kesir 1/2 83 | ¾ kesir 3/4 84 | ⅛ kesir Sekizde Bir 85 | ⅜ kesir sekizde üç 86 | ⅞ kesir sekizde yedi 87 | ¬ mantıkda değil 88 | ≠ eşit değil 89 | ≤ eşit veya küçük 90 | ≥ eşit veya büyük 91 | ∞ sonsuz 92 | ∫ İntegral İşareti 93 | ∂ Kısmi türev İşareti 94 | ∆ artım işareti 95 | ∏ çarpım işareti 96 | ∑ toplam işareti 97 | √ Kare Kök İşareti 98 | ∟ dik açı işareti 99 | ∩ kesişim işareti 100 | ƒ İşlev İşareti 101 | 102 | [noktalama işaretleri] 103 | … üç nokta 104 | ­ ince tire 105 | • madde imi 106 | ∙ madde imi işleci 107 | ‣ üçgen madde imi 108 | ¦ kırık çizgi 109 |   boşluksuz aralık 110 | § bölüm sembolü 111 | ¶ Paragraf Sembolü (Yastık) 112 | † kama işareti 113 | ‡ çift kama işareti 114 | “ çift tırnak aç 115 | ” çift tırnak kapa 116 | ‚ tek alt tırnak 117 | „ çift alt tırnak 118 | ‹ tek üçgen tırnak aç 119 | › tek üçgen tırnak kapa 120 | « çift kancalı parantez aç 121 | » çift kancalı parantez kapa 122 | ­ ince tire 123 | – orta tire 124 | — uzun tire 125 | ℅ koruma işareti 126 | ― yatay çizgi 127 | ‾ üst çizgi 128 | ‼ çift ünlem 129 | ♦ siyah karo 130 | & ve 131 | 132 | [Diğer semboller] 133 | © Telif hakkı sembolü 134 | ® kayıtlı sembolü 135 | ™ Marka 136 | Æ büyük A-E 137 | æ A-E 138 | Œ büyük O-E 139 | œ O-E 140 | Ø büyük iskandinav O 141 | ø iskandinav O slash 142 | º Eril Sıra Sayısı 143 | ª dişil sıra sayısı 144 | ¡ ters ünlem 145 | ¿ ters soru 146 | ¯ makron 147 | Å Büyük A, halka (angström) 148 | å Küçük a, halka 149 | Þ Büyük Thorn, İzlandaca 150 | þ Küçük Thorn, İzlandaca 151 | Ð Büyük Eth, İzlandaca 152 | ð Küçük Eth, İzlandaca -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/commandKeysSelectiveAnnouncementAndRemanence/patchs.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\commandKeysSelectiveAnnouncementAndRemanence\commandKeysSelectiveAnnouncementAndRemanencePatches.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from logHandler import log 8 | import inputCore 9 | from inputCore import NoInputGestureAction 10 | from ..settings import isInstall 11 | from ..settings import addonConfig 12 | from keyboardHandler import KeyboardInputGesture 13 | 14 | 15 | # global variables to save NVDA patched variables and methods 16 | _NVDAInputCoreManager = None 17 | _NVDAInputCoreManagerExecuteGesture = None 18 | 19 | 20 | def myExecuteGesture(gesture): 21 | log.debug("MyExecuteGesture: %s,%s" % (gesture.identifiers[0], gesture.__class__)) 22 | try: 23 | if isinstance(gesture, KeyboardInputGesture): 24 | log.debug("gesture: vkCode= %s, scanCode= %s, isextended= %s, modifiers= %s" % ( 25 | gesture.vkCode, gesture.scanCode, gesture.isExtended, gesture.modifiers)) 26 | from ..commandKeysSelectiveAnnouncementAndRemanence import _myInputManager 27 | _myInputManager.executeKeyboardGesture(gesture) 28 | else: 29 | log.debug("Gesture executed by: %s.%s" % ( 30 | _NVDAInputCoreManagerExecuteGesture.__module__, _NVDAInputCoreManagerExecuteGesture.__name__)) 31 | _NVDAInputCoreManagerExecuteGesture(gesture) 32 | except NoInputGestureAction: 33 | log.debug("myExecuteGesture exception NoInputGestureAction") 34 | raise NoInputGestureAction 35 | 36 | 37 | def patche(install=True): 38 | if not install: 39 | removePatch() 40 | return 41 | if not ( 42 | isInstall(addonConfig.FCT_CommandKeysSelectiveAnnouncement) 43 | or isInstall(addonConfig.FCT_KeyRemanence)): 44 | return 45 | global _NVDAInputCoreManager, _NVDAInputCoreManagerExecuteGesture 46 | _NVDAInputCoreManager = inputCore.manager 47 | if _NVDAInputCoreManager .__module__ != "inputCore": 48 | log.warning( 49 | "Incompatibility: imput.manager variable has also been patched" 50 | " probably by another add-on: %s of %s module. " 51 | "There is a risk of malfunction" % (_NVDAInputCoreManager.__name__, _NVDAInputCoreManager.__module__)) 52 | _NVDAInputCoreManagerExecuteGesture = inputCore.manager.executeGesture 53 | if _NVDAInputCoreManagerExecuteGesture .__module__ != "inputCore": 54 | log.warning( 55 | "Incompatibility: inputCore.manager.executeGesture manager has also been patched probably" 56 | " by another add-on:" 57 | " %s of %s. There is a risk of malfunction" % ( 58 | _NVDAInputCoreManagerExecuteGesture .__name__, _NVDAInputCoreManagerExecuteGesture .__module__)) 59 | inputCore.manager.executeGesture = myExecuteGesture 60 | log.debug( 61 | "For command selective announcement and key remanence functionnalities," 62 | " NVDA core manager executeGesture method has been replaced" 63 | " by %s method of %s module" % ( 64 | inputCore.manager.executeGesture.__name__, inputCore.manager.executeGesture .__module__)) 65 | 66 | 67 | def removePatch(): 68 | global _NVDAInputCoreManager 69 | global _NVDAInputCoreManagerExecuteGesture 70 | if _NVDAInputCoreManager is not None: 71 | inputCore.manager = _NVDAInputCoreManager 72 | _NVDAInputCoreManager = None 73 | if _NVDAInputCoreManagerExecuteGesture is not None: 74 | inputCore.manager.executeGesture = _NVDAInputCoreManagerExecuteGesture 75 | _NVDAInputCoreManagerExecuteGesture = None 76 | -------------------------------------------------------------------------------- /addon/locale/ar/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [حروف العلة الصغيرة] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [حروف العلة الكبيرة] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | [رموز العملات] 59 | 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [الرموز الرياضية] 69 | 70 | ÷ Division sign 71 | × Multiplication Sign 72 | ± Plus/minus 73 | ¹ Superscript 1 74 | ² Superscript 2 75 | ³ Superscript 3 76 | ⁿ Superscript N 77 | ° Degree symbol 78 | µ Micro 79 | ‰ Per Mille sign (1/1000th) 80 | ‰ Per Million 81 | ¼ Fraction 1/4 82 | ½ Fraction 1/2 83 | ¾ Fraction 3/4 84 | ⅛ One Eighth Fraction 85 | ⅜ Three Eighths Fraction 86 | ⅞ Seven Eighths Fraction 87 | ¬ Not symbol logic 88 | ≠ Not Equal To Sign 89 | ≤ Less Than or Equal To Sign 90 | ≥ Greater Than or Equal To Sign 91 | ∞ Infinity Sign 92 | ∫ Integral Sign 93 | ∂ Partial Differential Sign 94 | ∆ Increment Sign 95 | ∏ N-ary Product Sign 96 | ∑ N-ary Sum Sign 97 | √ Square Root Sign 98 | ∟ Right Angle Sign 99 | ∩ Intersection Sign 100 | ƒ Function Sign 101 | [علامات الترقيم] 102 | 103 | … نقطة نقطة نقطة 104 | ­ Dash 105 | • List Dot 106 | ∙ Bullet Operator 107 | ‣ Triangle Bullet 108 | ¦ Broken Vertical Bar 109 |   مسافة 110 | § قسم 111 | ¶ المؤشر الى اليسار 112 | † خنجر 113 | ‡ خنجر مزدوج 114 | “ فتح تنصيص 115 | ” مغلق تنصيص 116 | ‚ إقتباس واحد منخفض 117 | „ علامة تنصيص مزدوجة 118 | ‹ زاوية إقتباس واحدة 119 | › زاوية إقتباسواحدة يمين 120 | « زاوية إقتباس يسار 121 | » زاوية إقتباس الحقل 122 | ­ وصلة ناعمة 123 | – em-dash 124 | — em-dash 125 | ℅ رعاية 126 | ― شريط أفقي 127 | ‾ خط إضافي 128 | ‼ تعجب مزدوج 129 | ♦ ورقة لعب بشكل ماسي 130 | & علامة العطف 131 | [رموز أخرى] 132 | © علامة حقوق النشر 133 | ® مسجل 134 | ™ علامة تجارية 135 | Ç الفرنسية C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø شمالي مائل كبيرة 142 | ø شمال مائل 143 | º ترتيب عدد مذكر 144 | ª ترتيب عدد مؤنث 145 | ¡ علامة تعجب مقلوبة 146 | ¿ علامة استفهام مقلوبة 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/preprocessors.py: -------------------------------------------------------------------------------- 1 | # Python Markdown 2 | 3 | # A Python implementation of John Gruber's Markdown. 4 | 5 | # Documentation: https://python-markdown.github.io/ 6 | # GitHub: https://github.com/Python-Markdown/markdown/ 7 | # PyPI: https://pypi.org/project/Markdown/ 8 | 9 | # Started by Manfred Stienstra (http://www.dwerg.net/). 10 | # Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org). 11 | # Currently maintained by Waylan Limberg (https://github.com/waylan), 12 | # Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser). 13 | 14 | # Copyright 2007-2023 The Python Markdown Project (v. 1.7 and later) 15 | # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 16 | # Copyright 2004 Manfred Stienstra (the original version) 17 | 18 | # License: BSD (see LICENSE.md for details). 19 | 20 | """ 21 | Preprocessors work on source text before it is broken down into its individual parts. 22 | This is an excellent place to clean up bad characters or to extract portions for later 23 | processing that the parser may otherwise choke on. 24 | """ 25 | 26 | from __future__ import annotations 27 | 28 | from typing import TYPE_CHECKING, Any 29 | from . import util 30 | from .htmlparser import HTMLExtractor 31 | import re 32 | 33 | if TYPE_CHECKING: # pragma: no cover 34 | from markdown import Markdown 35 | 36 | 37 | def build_preprocessors(md: Markdown, **kwargs: Any) -> util.Registry[Preprocessor]: 38 | """ Build and return the default set of preprocessors used by Markdown. """ 39 | preprocessors = util.Registry() 40 | preprocessors.register(NormalizeWhitespace(md), 'normalize_whitespace', 30) 41 | preprocessors.register(HtmlBlockPreprocessor(md), 'html_block', 20) 42 | return preprocessors 43 | 44 | 45 | class Preprocessor(util.Processor): 46 | """ 47 | Preprocessors are run after the text is broken into lines. 48 | 49 | Each preprocessor implements a `run` method that takes a pointer to a 50 | list of lines of the document, modifies it as necessary and returns 51 | either the same pointer or a pointer to a new list. 52 | 53 | Preprocessors must extend `Preprocessor`. 54 | 55 | """ 56 | def run(self, lines: list[str]) -> list[str]: 57 | """ 58 | Each subclass of `Preprocessor` should override the `run` method, which 59 | takes the document as a list of strings split by newlines and returns 60 | the (possibly modified) list of lines. 61 | 62 | """ 63 | pass # pragma: no cover 64 | 65 | 66 | class NormalizeWhitespace(Preprocessor): 67 | """ Normalize whitespace for consistent parsing. """ 68 | 69 | def run(self, lines: list[str]) -> list[str]: 70 | source = '\n'.join(lines) 71 | source = source.replace(util.STX, "").replace(util.ETX, "") 72 | source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n" 73 | source = source.expandtabs(self.md.tab_length) 74 | source = re.sub(r'(?<=\n) +\n', '\n', source) 75 | return source.split('\n') 76 | 77 | 78 | class HtmlBlockPreprocessor(Preprocessor): 79 | """ 80 | Remove html blocks from the text and store them for later retrieval. 81 | 82 | The raw HTML is stored in the [`htmlStash`][markdown.util.HtmlStash] of the 83 | [`Markdown`][markdown.Markdown] instance. 84 | """ 85 | 86 | def run(self, lines: list[str]) -> list[str]: 87 | source = '\n'.join(lines) 88 | parser = HTMLExtractor(self.md) 89 | parser.feed(source) 90 | parser.close() 91 | return ''.join(parser.cleandoc).split('\n') 92 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/tools/gettextTools.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\tools\gettextTools.py 2 | # a part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 -2020 Paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | 8 | import addonHandler 9 | import subprocess 10 | import os 11 | import glob 12 | from ..utils.py3Compatibility import getCommonUtilitiesPath 13 | 14 | addonHandler.initTranslation() 15 | 16 | XGETTEXT_COMMON_ARGS = ( 17 | "--from-code=utf-8 " 18 | "--msgid-bugs-address\"={gettext_package_bugs_address}\" " 19 | "--package-name=\"{gettext_package_name}\" " 20 | "--package-version=\"{gettext_package_version}\" " 21 | "-c -o \"{TARGET}\" -D \"{inputDirectory}\" {SOURCES}" 22 | ) 23 | 24 | 25 | def getI18nSources(addon, buildVarsI18nSources): 26 | i18nSources = [] 27 | for path in buildVarsI18nSources: 28 | pathList = path.split("\\") 29 | if pathList[0] == "addon": 30 | pathList = pathList[1:] 31 | p = os.path.join(addon.path, "\\".join(pathList)) 32 | if "*" in pathList[-1]: 33 | files = glob.glob(p) 34 | i18nSources .extend(files) 35 | else: 36 | i18nSources .append(p) 37 | return i18nSources 38 | 39 | 40 | def generatePotFile( 41 | addon, potFileName, buildVarsAddonInfo, buildVarsI18nSources): 42 | gettextVars = { 43 | 'gettext_package_bugs_address': buildVarsAddonInfo['addon_author'], 44 | 'gettext_package_name': buildVarsAddonInfo['addon_name'], 45 | 'gettext_package_version': buildVarsAddonInfo['addon_version'] 46 | } 47 | addonPath = addon.path 48 | potFileDir = os.path.join(addonPath, "locale", "en") 49 | files = glob.glob(os.path.join(potFileDir, "*.pot")) 50 | for f in files: 51 | os.remove(f) 52 | 53 | if not os.path.exists(potFileDir): 54 | os.mkdir(potFileDir) 55 | potFile = os.path.join(potFileDir, potFileName) 56 | i18nSources = getI18nSources(addon, buildVarsI18nSources) 57 | if len(i18nSources) == 0: 58 | return -1 59 | gettextVars["TARGET"] = potFile 60 | gettextVars["inputDirectory"] = addonPath 61 | utilitiesPath = getCommonUtilitiesPath() 62 | xgettextPath = os.path.join(utilitiesPath, "xgettext.exe") 63 | sources = "" 64 | for item in i18nSources: 65 | f = item.replace(addon.path + "\\", "") 66 | sources = sources + " " + "\"%s\"" % f 67 | gettextVars["SOURCES"] = sources 68 | commandLine = xgettextPath + " " + XGETTEXT_COMMON_ARGS 69 | commandLine = commandLine.format(**gettextVars) 70 | p = subprocess.Popen(commandLine) 71 | retval = p.wait() 72 | return retval 73 | 74 | 75 | def compilePoFiles(addon): 76 | utilitiesPath = getCommonUtilitiesPath() 77 | msgfmtPath = os.path.join(utilitiesPath, "msgfmt.exe") 78 | prefixe = "nvda" 79 | localeDir = os.path.join(addon.path, "locale") 80 | poFiles = [] 81 | for root, directories, files in os.walk(localeDir): 82 | for filename in files: 83 | if os.path.isdir(filename): 84 | continue 85 | if not filename.endswith(".po"): 86 | continue 87 | poFiles.append(os.path.join(root, filename)) 88 | count = 0 89 | for poFile in poFiles: 90 | moPath = os.path.split(poFile)[0] 91 | moFile = os.path.join(moPath, "%s.mo" % prefixe) 92 | if os.path.exists(moFile): 93 | os.remove(moFile) 94 | commandLine = [ 95 | "\"%s\"" % msgfmtPath, 96 | "-o", 97 | "\"%s\"" % moFile, 98 | "\"%s\"" % poFile] 99 | commandLine = " ".join(commandLine) 100 | p = subprocess.Popen(commandLine) 101 | retval = p.wait() 102 | if retval == 0: 103 | count += 1 104 | return (count, len(poFiles)) 105 | -------------------------------------------------------------------------------- /addon/utilities/markdownEx/markdown/extensions/wikilinks.py: -------------------------------------------------------------------------------- 1 | # WikiLinks Extension for Python-Markdown 2 | # ====================================== 3 | 4 | # Converts [[WikiLinks]] to relative links. 5 | 6 | # See https://Python-Markdown.github.io/extensions/wikilinks 7 | # for documentation. 8 | 9 | # Original code Copyright [Waylan Limberg](http://achinghead.com/). 10 | 11 | # All changes Copyright The Python Markdown Project 12 | 13 | # License: [BSD](https://opensource.org/licenses/bsd-license.php) 14 | 15 | """ 16 | Converts `[[WikiLinks]]` to relative links. 17 | 18 | See the [documentation](https://Python-Markdown.github.io/extensions/wikilinks) 19 | for details. 20 | """ 21 | 22 | from __future__ import annotations 23 | 24 | from . import Extension 25 | from ..inlinepatterns import InlineProcessor 26 | import xml.etree.ElementTree as etree 27 | import re 28 | from typing import Any 29 | 30 | 31 | def build_url(label: str, base: str, end: str) -> str: 32 | """ Build a URL from the label, a base, and an end. """ 33 | clean_label = re.sub(r'([ ]+_)|(_[ ]+)|([ ]+)', '_', label) 34 | return '{}{}{}'.format(base, clean_label, end) 35 | 36 | 37 | class WikiLinkExtension(Extension): 38 | """ Add inline processor to Markdown. """ 39 | 40 | def __init__(self, **kwargs): 41 | self.config = { 42 | 'base_url': ['/', 'String to append to beginning or URL.'], 43 | 'end_url': ['/', 'String to append to end of URL.'], 44 | 'html_class': ['wikilink', 'CSS hook. Leave blank for none.'], 45 | 'build_url': [build_url, 'Callable formats URL from label.'], 46 | } 47 | """ Default configuration options. """ 48 | super().__init__(**kwargs) 49 | 50 | def extendMarkdown(self, md): 51 | self.md = md 52 | 53 | # append to end of inline patterns 54 | WIKILINK_RE = r'\[\[([\w0-9_ -]+)\]\]' 55 | wikilinkPattern = WikiLinksInlineProcessor(WIKILINK_RE, self.getConfigs()) 56 | wikilinkPattern.md = md 57 | md.inlinePatterns.register(wikilinkPattern, 'wikilink', 75) 58 | 59 | 60 | class WikiLinksInlineProcessor(InlineProcessor): 61 | """ Build link from `wikilink`. """ 62 | 63 | def __init__(self, pattern: str, config: dict[str, Any]): 64 | super().__init__(pattern) 65 | self.config = config 66 | 67 | def handleMatch(self, m: re.Match[str], data: str) -> tuple[etree.Element | str, int, int]: 68 | if m.group(1).strip(): 69 | base_url, end_url, html_class = self._getMeta() 70 | label = m.group(1).strip() 71 | url = self.config['build_url'](label, base_url, end_url) 72 | a = etree.Element('a') 73 | a.text = label 74 | a.set('href', url) 75 | if html_class: 76 | a.set('class', html_class) 77 | else: 78 | a = '' 79 | return a, m.start(0), m.end(0) 80 | 81 | def _getMeta(self) -> tuple[str, str, str]: 82 | """ Return meta data or `config` data. """ 83 | base_url = self.config['base_url'] 84 | end_url = self.config['end_url'] 85 | html_class = self.config['html_class'] 86 | if hasattr(self.md, 'Meta'): 87 | if 'wiki_base_url' in self.md.Meta: 88 | base_url = self.md.Meta['wiki_base_url'][0] 89 | if 'wiki_end_url' in self.md.Meta: 90 | end_url = self.md.Meta['wiki_end_url'][0] 91 | if 'wiki_html_class' in self.md.Meta: 92 | html_class = self.md.Meta['wiki_html_class'][0] 93 | return base_url, end_url, html_class 94 | 95 | 96 | def makeExtension(**kwargs): # pragma: no cover 97 | return WikiLinkExtension(**kwargs) 98 | -------------------------------------------------------------------------------- /addon/locale/cs/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Lower-case accented vowels] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [Capital accented vowels] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | 59 | [Moneytary symbols] 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [Math symbols] 69 | ÷ Division sign 70 | × Multiplication Sign 71 | ± Plus/minus 72 | ¹ Superscript 1 73 | ² Superscript 2 74 | ³ Superscript 3 75 | ⁿ Superscript N 76 | ° Degree symbol 77 | µ Micro 78 | ‰ Per Mille sign (1/1000th) 79 | ‰ Per Million 80 | ¼ Fraction 1/4 81 | ½ Fraction 1/2 82 | ¾ Fraction 3/4 83 | ⅛ One Eighth Fraction 84 | ⅜ Three Eighths Fraction 85 | ⅞ Seven Eighths Fraction 86 | ¬ Not symbol logic 87 | ≠ Not Equal To Sign 88 | ≤ Less Than or Equal To Sign 89 | ≥ Greater Than or Equal To Sign 90 | ∞ Infinity Sign 91 | ∫ Integral Sign 92 | ∂ Partial Differential Sign 93 | ∆ Increment Sign 94 | ∏ N-ary Product Sign 95 | ∑ N-ary Sum Sign 96 | √ Square Root Sign 97 | ∟ Right Angle Sign 98 | ∩ Intersection Sign 99 | ƒ Function Sign 100 | 101 | [Punctuation symbols] 102 | … Elipsis 103 | ­ Dash 104 | • List Dot 105 | ∙ Bullet Operator 106 | ‣ Triangle Bullet 107 | ¦ Broken Vertical Bar 108 |   Non-breaking space 109 | § Section Symbol 110 | ¶ Paragraph Symbol (Pilcrow) 111 | † Dagger 112 | ‡ Double Dagger 113 | “ Left Double Quote 114 | ” Right Double Quote 115 | ‚ Single Low Quote 116 | „ Double Low Quote 117 | ‹ Left Single Angle Quote 118 | › Right Single Angle Quote 119 | « Left Angle Quote 120 | » Right Angle Quote 121 | ­ Soft Hyphen 122 | – en-dash 123 | — em-dash 124 | ℅ Care Of 125 | ― Horizontal Bar 126 | ‾ Overline 127 | ‼ Double exclamation mark 128 | ♦ Diamonds card 129 | & Ampersand 130 | 131 | [Other symbols] 132 | © Copyright symbol 133 | ® Registered symbol 134 | ™ Trademark 135 | Ç French C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø Nordic O slash capitale 142 | ø Nordic O slash 143 | º Masculine Ordinal Number 144 | ª Feminine Ordinal Number 145 | ¡ Upside-down exclamation mark 146 | ¿ Upside-down question mark 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/locale/da/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Lower-case accented vowels] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [Capital accented vowels] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | 59 | [Moneytary symbols] 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [Math symbols] 69 | ÷ Division sign 70 | × Multiplication Sign 71 | ± Plus/minus 72 | ¹ Superscript 1 73 | ² Superscript 2 74 | ³ Superscript 3 75 | ⁿ Superscript N 76 | ° Degree symbol 77 | µ Micro 78 | ‰ Per Mille sign (1/1000th) 79 | ‰ Per Million 80 | ¼ Fraction 1/4 81 | ½ Fraction 1/2 82 | ¾ Fraction 3/4 83 | ⅛ One Eighth Fraction 84 | ⅜ Three Eighths Fraction 85 | ⅞ Seven Eighths Fraction 86 | ¬ Not symbol logic 87 | ≠ Not Equal To Sign 88 | ≤ Less Than or Equal To Sign 89 | ≥ Greater Than or Equal To Sign 90 | ∞ Infinity Sign 91 | ∫ Integral Sign 92 | ∂ Partial Differential Sign 93 | ∆ Increment Sign 94 | ∏ N-ary Product Sign 95 | ∑ N-ary Sum Sign 96 | √ Square Root Sign 97 | ∟ Right Angle Sign 98 | ∩ Intersection Sign 99 | ƒ Function Sign 100 | 101 | [Punctuation symbols] 102 | … Elipsis 103 | ­ Dash 104 | • List Dot 105 | ∙ Bullet Operator 106 | ‣ Triangle Bullet 107 | ¦ Broken Vertical Bar 108 |   Non-breaking space 109 | § Section Symbol 110 | ¶ Paragraph Symbol (Pilcrow) 111 | † Dagger 112 | ‡ Double Dagger 113 | “ Left Double Quote 114 | ” Right Double Quote 115 | ‚ Single Low Quote 116 | „ Double Low Quote 117 | ‹ Left Single Angle Quote 118 | › Right Single Angle Quote 119 | « Left Angle Quote 120 | » Right Angle Quote 121 | ­ Soft Hyphen 122 | – en-dash 123 | — em-dash 124 | ℅ Care Of 125 | ― Horizontal Bar 126 | ‾ Overline 127 | ‼ Double exclamation mark 128 | ♦ Diamonds card 129 | & Ampersand 130 | 131 | [Other symbols] 132 | © Copyright symbol 133 | ® Registered symbol 134 | ™ Trademark 135 | Ç French C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø Nordic O slash capitale 142 | ø Nordic O slash 143 | º Masculine Ordinal Number 144 | ª Feminine Ordinal Number 145 | ¡ Upside-down exclamation mark 146 | ¿ Upside-down question mark 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/locale/en/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Lower-case accented vowels] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [Capital accented vowels] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | 59 | [Moneytary symbols] 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [Math symbols] 69 | ÷ Division sign 70 | × Multiplication Sign 71 | ± Plus/minus 72 | ¹ Superscript 1 73 | ² Superscript 2 74 | ³ Superscript 3 75 | ⁿ Superscript N 76 | ° Degree symbol 77 | µ Micro 78 | ‰ Per Mille sign (1/1000th) 79 | ‰ Per Million 80 | ¼ Fraction 1/4 81 | ½ Fraction 1/2 82 | ¾ Fraction 3/4 83 | ⅛ One Eighth Fraction 84 | ⅜ Three Eighths Fraction 85 | ⅞ Seven Eighths Fraction 86 | ¬ Not symbol logic 87 | ≠ Not Equal To Sign 88 | ≤ Less Than or Equal To Sign 89 | ≥ Greater Than or Equal To Sign 90 | ∞ Infinity Sign 91 | ∫ Integral Sign 92 | ∂ Partial Differential Sign 93 | ∆ Increment Sign 94 | ∏ N-ary Product Sign 95 | ∑ N-ary Sum Sign 96 | √ Square Root Sign 97 | ∟ Right Angle Sign 98 | ∩ Intersection Sign 99 | ƒ Function Sign 100 | 101 | [Punctuation symbols] 102 | … Elipsis 103 | ­ Dash 104 | • List Dot 105 | ∙ Bullet Operator 106 | ‣ Triangle Bullet 107 | ¦ Broken Vertical Bar 108 |   Non-breaking space 109 | § Section Symbol 110 | ¶ Paragraph Symbol (Pilcrow) 111 | † Dagger 112 | ‡ Double Dagger 113 | “ Left Double Quote 114 | ” Right Double Quote 115 | ‚ Single Low Quote 116 | „ Double Low Quote 117 | ‹ Left Single Angle Quote 118 | › Right Single Angle Quote 119 | « Left Angle Quote 120 | » Right Angle Quote 121 | ­ Soft Hyphen 122 | – en-dash 123 | — em-dash 124 | ℅ Care Of 125 | ― Horizontal Bar 126 | ‾ Overline 127 | ‼ Double exclamation mark 128 | ♦ Diamonds card 129 | & Ampersand 130 | 131 | [Other symbols] 132 | © Copyright symbol 133 | ® Registered symbol 134 | ™ Trademark 135 | Ç French C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø Nordic O slash capitale 142 | ø Nordic O slash 143 | º Masculine Ordinal Number 144 | ª Feminine Ordinal Number 145 | ¡ Upside-down exclamation mark 146 | ¿ Upside-down question mark 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/locale/sk/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Lower-case accented vowels] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [Capital accented vowels] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | 59 | [Moneytary symbols] 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [Math symbols] 69 | ÷ Division sign 70 | × Multiplication Sign 71 | ± Plus/minus 72 | ¹ Superscript 1 73 | ² Superscript 2 74 | ³ Superscript 3 75 | ⁿ Superscript N 76 | ° Degree symbol 77 | µ Micro 78 | ‰ Per Mille sign (1/1000th) 79 | ‰ Per Million 80 | ¼ Fraction 1/4 81 | ½ Fraction 1/2 82 | ¾ Fraction 3/4 83 | ⅛ One Eighth Fraction 84 | ⅜ Three Eighths Fraction 85 | ⅞ Seven Eighths Fraction 86 | ¬ Not symbol logic 87 | ≠ Not Equal To Sign 88 | ≤ Less Than or Equal To Sign 89 | ≥ Greater Than or Equal To Sign 90 | ∞ Infinity Sign 91 | ∫ Integral Sign 92 | ∂ Partial Differential Sign 93 | ∆ Increment Sign 94 | ∏ N-ary Product Sign 95 | ∑ N-ary Sum Sign 96 | √ Square Root Sign 97 | ∟ Right Angle Sign 98 | ∩ Intersection Sign 99 | ƒ Function Sign 100 | 101 | [Punctuation symbols] 102 | … Elipsis 103 | ­ Dash 104 | • List Dot 105 | ∙ Bullet Operator 106 | ‣ Triangle Bullet 107 | ¦ Broken Vertical Bar 108 |   Non-breaking space 109 | § Section Symbol 110 | ¶ Paragraph Symbol (Pilcrow) 111 | † Dagger 112 | ‡ Double Dagger 113 | “ Left Double Quote 114 | ” Right Double Quote 115 | ‚ Single Low Quote 116 | „ Double Low Quote 117 | ‹ Left Single Angle Quote 118 | › Right Single Angle Quote 119 | « Left Angle Quote 120 | » Right Angle Quote 121 | ­ Soft Hyphen 122 | – en-dash 123 | — em-dash 124 | ℅ Care Of 125 | ― Horizontal Bar 126 | ‾ Overline 127 | ‼ Double exclamation mark 128 | ♦ Diamonds card 129 | & Ampersand 130 | 131 | [Other symbols] 132 | © Copyright symbol 133 | ® Registered symbol 134 | ™ Trademark 135 | Ç French C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø Nordic O slash capitale 142 | ø Nordic O slash 143 | º Masculine Ordinal Number 144 | ª Feminine Ordinal Number 145 | ¡ Upside-down exclamation mark 146 | ¿ Upside-down question mark 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/locale/vi/symbolCategories.dic: -------------------------------------------------------------------------------- 1 | #the symbols and their description are divided in category and each category is defined by a section beginning with the category name enclosed between brackets. 2 | # Each line of a section define a symbol with its description: 3 | #- the symbol (one caracter) 4 | #- the "Tab" separator 5 | #- the symbol description 6 | 7 | [Lower-case accented vowels] 8 | á a acute 9 | é e acute 10 | í i acute 11 | ó o acute 12 | ú u acute 13 | ý y acute 14 | à a accent grave 15 | è e grave 16 | ì i grave 17 | ò o grave 18 | ù u grave 19 | â a circunflex 20 | ê e circunflex 21 | î i circunflex 22 | ô o circunflex 23 | û u circunflex 24 | ã a tilde 25 | ñ n tilde 26 | õ o tilde 27 | ä a umloat 28 | ë e umloat 29 | ï i umloat 30 | ö o umloat 31 | ü u umloat 32 | 33 | [Capital accented vowels] 34 | Á A acute capital 35 | É E acute capital 36 | Í I acute capital 37 | Ó O acute capital 38 | Ú U acute capital 39 | Ý Y acute capital 40 | À a grave capitale 41 | È e grave capitale 42 | Ì i grave capitale 43 | Ò o grave capitale 44 | Ù u grave capitale 45 |  a circunflex capitale 46 | Ê e circunflex capitale 47 | Î i circunflex capitale 48 | Ô o circunflex capitale 49 | Û u circunflex capitale 50 | à a tilde capitale 51 | Ñ n tilde capitale 52 | Õ o tilde capitale 53 | Ä a umloat capitale 54 | Ë e umloat capitale 55 | Ï i umloat capitale 56 | Ö o umloat capitale 57 | Ü u umloat capitale 58 | 59 | [Moneytary symbols] 60 | € Euro currency 61 | $ Dollar Sign 62 | ¢ Cent sign 63 | £ British Pound 64 | ¥ Japanese Yen 65 | ƒ Dutch Florin 66 | ¤ Generic currency symbol 67 | 68 | [Math symbols] 69 | ÷ Division sign 70 | × Multiplication Sign 71 | ± Plus/minus 72 | ¹ Superscript 1 73 | ² Superscript 2 74 | ³ Superscript 3 75 | ⁿ Superscript N 76 | ° Degree symbol 77 | µ Micro 78 | ‰ Per Mille sign (1/1000th) 79 | ‰ Per Million 80 | ¼ Fraction 1/4 81 | ½ Fraction 1/2 82 | ¾ Fraction 3/4 83 | ⅛ One Eighth Fraction 84 | ⅜ Three Eighths Fraction 85 | ⅞ Seven Eighths Fraction 86 | ¬ Not symbol logic 87 | ≠ Not Equal To Sign 88 | ≤ Less Than or Equal To Sign 89 | ≥ Greater Than or Equal To Sign 90 | ∞ Infinity Sign 91 | ∫ Integral Sign 92 | ∂ Partial Differential Sign 93 | ∆ Increment Sign 94 | ∏ N-ary Product Sign 95 | ∑ N-ary Sum Sign 96 | √ Square Root Sign 97 | ∟ Right Angle Sign 98 | ∩ Intersection Sign 99 | ƒ Function Sign 100 | 101 | [Punctuation symbols] 102 | … Elipsis 103 | ­ Dash 104 | • List Dot 105 | ∙ Bullet Operator 106 | ‣ Triangle Bullet 107 | ¦ Broken Vertical Bar 108 |   Non-breaking space 109 | § Section Symbol 110 | ¶ Paragraph Symbol (Pilcrow) 111 | † Dagger 112 | ‡ Double Dagger 113 | “ Left Double Quote 114 | ” Right Double Quote 115 | ‚ Single Low Quote 116 | „ Double Low Quote 117 | ‹ Left Single Angle Quote 118 | › Right Single Angle Quote 119 | « Left Angle Quote 120 | » Right Angle Quote 121 | ­ Soft Hyphen 122 | – en-dash 123 | — em-dash 124 | ℅ Care Of 125 | ― Horizontal Bar 126 | ‾ Overline 127 | ‼ Double exclamation mark 128 | ♦ Diamonds card 129 | & Ampersand 130 | 131 | [Other symbols] 132 | © Copyright symbol 133 | ® Registered symbol 134 | ™ Trademark 135 | Ç French C cedille capitale 136 | ç French C cedille 137 | Æ A-E ligature capitale 138 | æ A-E ligature 139 | Œ O-E ligature capitale 140 | œ O-E ligature 141 | Ø Nordic O slash capitale 142 | ø Nordic O slash 143 | º Masculine Ordinal Number 144 | ª Feminine Ordinal Number 145 | ¡ Upside-down exclamation mark 146 | ¿ Upside-down question mark 147 | ¯ Macron accent 148 | Å Uppercase A, ring (angström) 149 | å Lowercase a, ring 150 | Þ Uppercase Thorn, Icelandic 151 | þ Lowercase Thorn, Icelandic 152 | Ð Uppercase Eth, Icelandic 153 | ð Lowercase Eth, Icelandic -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/waves.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\computerTools\waves.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | from logHandler import log 9 | import os 10 | import globalVars 11 | import sys 12 | sysPath = list(sys.path) 13 | pydubModulePath = None 14 | if "pydub" in sys.modules: 15 | log.warning("Potential incompatibility: pydub module used and loaded probably by other add-on") 16 | pydubModulePath = sys.modules["pydub"] 17 | del sys.modules["pydub"] 18 | sys.path = [sys.path[0]] 19 | from ..utils.py3Compatibility import getCommonUtilitiesPath 20 | commonUtilitiesPath = getCommonUtilitiesPath() 21 | pydubPath = os.path.join(commonUtilitiesPath, "pydubEx") 22 | sys.path.append(commonUtilitiesPath) 23 | sys.path.append(pydubPath) 24 | from pydubEx import AudioSegment 25 | # restore sys.path 26 | sys.path = sysPath 27 | del sys.modules["pydubEx"] 28 | if pydubModulePath is not None: 29 | sys.modules["pydub"] = pydubModulePath 30 | 31 | 32 | # NVDA application path 33 | _NVDAAppPath = os.getcwd() 34 | 35 | # modified waves directory 36 | _addon = addonHandler.getCodeAddon() 37 | _modifiedWavesPath = os.path.join( 38 | os.path.abspath(globalVars.appArgs.configPath), 39 | "%s-NVDAWaves" % _addon.manifest['name'] 40 | ) 41 | 42 | 43 | def getSoundNameFromID(soundID): 44 | return soundID.split("_")[-1] 45 | 46 | 47 | def getFileNameIdentification(fileName): 48 | baseName = os.path.basename(fileName) 49 | if isNVDAWaveFile(fileName): 50 | id = "NVDAWaves_%s" % baseName 51 | elif isAddonSoundFile(fileName): 52 | temp = fileName[len(_addon.path) + 1:].split("\\")[:-1] 53 | id = "%s%s_%s" % (_addon.manifest["name"], "".join(temp), baseName) 54 | else: 55 | id = None 56 | return id 57 | 58 | 59 | def getModifiedWavesPath(): 60 | return _modifiedWavesPath 61 | 62 | 63 | def getModifiedNVDAWaveFile(fileName): 64 | from ..settings import ( 65 | toggleAllowNVDATonesVolumeAdjustmentAdvancedOption, 66 | toggleAllowNVDASoundGainModificationAdvancedOption 67 | ) 68 | if ( 69 | not toggleAllowNVDATonesVolumeAdjustmentAdvancedOption(False) 70 | or not toggleAllowNVDASoundGainModificationAdvancedOption(False) 71 | ): 72 | return fileName 73 | if not isNVDAWaveFile(fileName) and not isAddonSoundFile(fileName): 74 | return fileName 75 | if not os.path.exists(_modifiedWavesPath): 76 | return fileName 77 | soundID = getFileNameIdentification(fileName) 78 | newFileName = os.path.join(_modifiedWavesPath, soundID) 79 | if os.path.exists(newFileName): 80 | return newFileName 81 | return fileName 82 | 83 | 84 | def isNVDAWaveFile(fileName): 85 | NVDAWavesPath = os.path.join(_NVDAAppPath, "waves") 86 | return fileName.startswith(NVDAWavesPath) 87 | 88 | 89 | def isAddonSoundFile(fileName): 90 | addonSoundsPath = os.path.join(_addon.path, "sounds") 91 | return addonSoundsPath in fileName 92 | 93 | 94 | def applyGain(gain, source, target=None): 95 | try: 96 | song = AudioSegment.from_wav(source) 97 | mod = song + gain 98 | if target: 99 | mod.export(target, format="wav") 100 | return mod 101 | except Exception: 102 | log.error("Cannott modify gain: gain = %s, source = %s, target = %s" % (gain, source, target)) 103 | return None 104 | 105 | 106 | def exportSong(song, target): 107 | if not target: 108 | return False 109 | try: 110 | song.export(target, format="wav") 111 | return True 112 | except Exception: 113 | log.error("Cannot exporte to %s" % target) 114 | return False 115 | -------------------------------------------------------------------------------- /addon/locale/en/manifest.ini: -------------------------------------------------------------------------------- 1 | name = NVDAExtensionGlobalPlugin 2 | summary = "NVDA global commands extension" 3 | version = 8.1-dev35 4 | description = """This Module has been developed with the participation of Daniel Poiraud. 5 | It is not compatible with versions of NVDA below to 2018.3.2. 6 | It adds to NVDA: 7 | 1- The features 8 | some features can be enabled or disabled individually. 9 | * Display of the list of icons in the notification area , 10 | * Display of the windows list of running applications, 11 | * Assistance in the composition of a symbol that is complex such as, for example, a a e related, a symbol power of 2 12 | and possibility to add its own categories and symbols, 13 | * Extension of the functionality of the virtual buffer 14 | for browsers Mozilla Firefox, Microsoft Internet Explorer, Microsoft Edge, and Google Chrome: 15 | 16 | * new commands for navigation mode (paragraph, division, anchor, main landmark, 17 | * new types of elements for the dialog box opened by "NVDA+F7" (radio button, paragraph, frame, checkBox, etc) with the announcement of the number of items found, 18 | * commands for the tables: 19 | announce the cells of a row /column , go to first/last cell in the row/current column, move the column/row preceding or following with announcement possible of the cells in that row/column, 20 | * announcement of the URL of the document, 21 | * navigation loop, 22 | * Announcement of the function associated with editing commands 23 | style Copy, Paste, etc., 24 | * Announcement of the name of the folder pre-selected in the dialog boxes like "Open","Save", "Save as",etc., 25 | * display of information on the focused application: 26 | * the current profile configuration, 27 | * the name and version number of the application, 28 | * the add-on loaded for the application, 29 | * NVDA logs tools: 30 | * Opening the previous or current log, 31 | * copy of current Log path to the clipboard, 32 | 33 | * history of voice speechs, 34 | * renaming keyboard keys, 35 | * selective announcement of command keyboard keys , 36 | * simple countdown timer, 37 | * display of visible elements making up the object in the foreground, 38 | * fast switching of voice profile, 39 | * remanence of the modifier keys, 40 | * shutdown, restart or put on prolonged sleep the computer, 41 | * control the master or NVDA volume: 42 | * mute or unmute volume for the focused application, 43 | * establishment of the main Windows or NVDA volume at the add-on loading, 44 | * modification of main volume or audio flow's volume of focused application, 45 | * Tools for development of add-on 46 | * supplements regarding the date and time: copy date and time to clipboard, report time with seconds 47 | 48 | 49 | 2- The options 50 | * remove the ad from the description of the objects in the ribbons Windows, 51 | * proclaim the word focused when deleting a word, 52 | * automatically maximize the foreground window, 53 | * announce punctuations and symbols when moving by word . 54 | 55 | 3- The advanced options 56 | * report, with a sound, the registration of an error in the NVDA log also for the final versions and release candidate of NVDA, 57 | * Caption dialog title with the name of the module, 58 | * Do not take account of the option called Report object descriptions during the display of the dialog box style confirmation, 59 | * use numeric keypad's keys as arrow keys. 60 | 61 | 62 | 4- Various other elements 63 | * presentation formatting of the text in a dialog box, 64 | * sub-menus to explore the program folders or configuration, 65 | * script to quickly restart NVDA. 66 | """ 67 | author = "PaulBer19" 68 | url = paulber19@laposte.net 69 | docFileName = addonUserManual.html 70 | minimumNVDAVersion = 2018.3.2 71 | lastTestedNVDAVersion = 2019.2.0 72 | updateChannel = None -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/utils/textInfo.py: -------------------------------------------------------------------------------- 1 | # NVDAExtensionGlobalPlugin/utils/textInfo.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | from logHandler import log 7 | 8 | import textInfos 9 | import speech 10 | 11 | 12 | def getStartOffset(textInfo): 13 | from NVDAObjects.UIA import UIATextInfo 14 | if issubclass(textInfo.obj.TextInfo, UIATextInfo): 15 | # UIA bookmark has no endOffset, so calculate it 16 | first = textInfo.copy() 17 | first.expand(textInfos.UNIT_STORY) 18 | startOffset = textInfo.compareEndPoints(first, "startToStart") 19 | else: 20 | if hasattr(textInfo.bookmark, "_start"): 21 | startOffset = textInfo.bookmark._start._startOffset 22 | else: 23 | startOffset = textInfo.bookmark.startOffset 24 | return startOffset 25 | 26 | 27 | def getEndOffset(textInfo): 28 | from NVDAObjects.UIA import UIATextInfo 29 | if issubclass(textInfo.obj.TextInfo, UIATextInfo): 30 | # UIA bookmark has no endOffset, so calculate it 31 | first = textInfo.copy() 32 | first.expand(textInfos.UNIT_STORY) 33 | endOffset = textInfo.compareEndPoints(first, "endToStart") 34 | else: 35 | if hasattr(textInfo.bookmark, "_end"): 36 | endOffset = textInfo.bookmark._end._endOffset 37 | else: 38 | endOffset = textInfo.bookmark.endOffset 39 | return endOffset 40 | 41 | 42 | def getTextInfoPositions(info): 43 | tempInfo = info.copy() 44 | start = getStartOffset(tempInfo) 45 | tempInfo.expand(textInfos.UNIT_LINE) 46 | start = getStartOffset(tempInfo) 47 | end = getEndOffset(tempInfo) 48 | tempInfo.collapse() 49 | textInfoPositions = [] 50 | tempInfo.expand(textInfos.UNIT_CHARACTER) 51 | pos = getStartOffset(tempInfo) 52 | textInfoPositions.append(0) 53 | i = 0 54 | while i < (end - start): 55 | i += 1 56 | res = tempInfo.move(textInfos.UNIT_CHARACTER, 1) 57 | if res == 0: 58 | break 59 | tempInfo.expand(textInfos.UNIT_CHARACTER) 60 | pos = getStartOffset(tempInfo) 61 | textInfoPositions.append(pos - start) 62 | return textInfoPositions 63 | 64 | 65 | def getRealPosition(info): 66 | tempInfo = info.copy() 67 | curPosition = getStartOffset(tempInfo) 68 | tempInfo.expand(textInfos.UNIT_LINE) 69 | lineStart = getStartOffset(tempInfo) 70 | tempInfo.collapse() 71 | positions = getTextInfoPositions(tempInfo) 72 | for pos in positions: 73 | if pos == curPosition - lineStart: 74 | return positions.index(pos) 75 | return None 76 | 77 | 78 | _lastLineInfo = [] 79 | 80 | 81 | def getLineInfo(info): 82 | reportFormattingOptions = ("reportLineNumber", "reportPage") 83 | tempInfo = info.copy() 84 | formatConfig = dict() 85 | from config import conf 86 | for i in conf["documentFormatting"]: 87 | formatConfig[i] = i in reportFormattingOptions 88 | formatField = textInfos.FormatField() 89 | tempInfo.expand(textInfos.UNIT_LINE) 90 | for field in tempInfo.getTextWithFields(formatConfig): 91 | if isinstance(field, textInfos.FieldCommand) and\ 92 | isinstance(field.field, textInfos.FormatField): 93 | formatField.update(field.field) 94 | lineInfoList = speech.getFormatFieldSpeech( 95 | formatField, formatConfig=formatConfig) if formatField else None 96 | if not lineInfoList: 97 | return "" 98 | log.debug("on: %s" % lineInfoList) 99 | return lineInfoList 100 | 101 | 102 | def getLineInfoMessage(info): 103 | lineInfo = getLineInfo(info) 104 | global _lastLineInfo 105 | if _lastLineInfo != lineInfo: 106 | temp = [] 107 | for item in lineInfo: 108 | if item in _lastLineInfo: 109 | continue 110 | temp.append(item) 111 | _lastLineInfo = lineInfo 112 | lineInfoMsg = ", ".join(temp) 113 | else: 114 | lineInfoMsg = "" 115 | return lineInfoMsg 116 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/winExplorer/__init__.py: -------------------------------------------------------------------------------- 1 | # NVDAExtensionGlobalPlugin/winExplorer/__init__.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2023 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | import ui 9 | from controlTypes.role import Role 10 | from controlTypes.state import State 11 | 12 | import api 13 | import queueHandler 14 | import itertools 15 | from .elementListDialog import ElementListDialog 16 | from ..utils import runInThread, isOpened 17 | addonHandler.initTranslation() 18 | 19 | _generatorID = None 20 | _running = False 21 | 22 | 23 | def _startGenerator(generator): 24 | global _generatorID 25 | stop() 26 | _generatorID = queueHandler.registerGeneratorObject(generator) 27 | 28 | 29 | def stop(): 30 | global _generatorID 31 | if _generatorID is None: 32 | return 33 | queueHandler.cancelGeneratorObject(_generatorID) 34 | _generatorID = None 35 | 36 | 37 | def isRunning(): 38 | global _running 39 | ret = _running 40 | _running = False 41 | return ret 42 | 43 | 44 | def generateObjectSubtreeGetObject(obj, indexGen, th): 45 | global _running 46 | index = next(indexGen) 47 | yield obj, index 48 | rowCount = 0 49 | treeCount = 0 50 | listCount = 0 51 | try: 52 | # childCount = len(obj.children) 53 | childCount = obj.childCount 54 | except Exception: 55 | childCount = 0 56 | for i in range(childCount): 57 | _running = True 58 | try: 59 | child = obj.getChild(i) 60 | if child is None: 61 | continue 62 | except Exception: 63 | continue 64 | role = child.role 65 | invisible = State.INVISIBLE in child.states 66 | try: 67 | childParent = child.parent 68 | try: 69 | parentChildCount = childParent.childCount 70 | except Exception: 71 | parentChildCount = 0 72 | except Exception: 73 | childParent = None 74 | parentChildCount = 0 75 | if role == Role.TABLEROW: 76 | if childParent and parentChildCount > 500: 77 | break 78 | if invisible: 79 | continue 80 | rowCount += 1 81 | treeCount = 0 82 | listCount = 0 83 | if rowCount > 40: 84 | break 85 | if role == Role.TREEVIEWITEM: 86 | if childParent and ( 87 | parentChildCount > 500 88 | or childParent.role not in [Role.TREEVIEW, Role.LIST] 89 | ): 90 | break 91 | if invisible: 92 | continue 93 | treeCount += 1 94 | rowCount = 0 95 | listCount = 0 96 | if treeCount > 40: 97 | break 98 | if role == Role.LISTITEM: 99 | if childParent and parentChildCount > 500: 100 | break 101 | if invisible: 102 | continue 103 | listCount += 1 104 | rowCount = 0 105 | treeCount = 0 106 | if listCount > 40: 107 | break 108 | 109 | if role in [Role.DOCUMENT, ]: 110 | continue 111 | childGetObject = generateObjectSubtreeGetObject(child, indexGen, th) 112 | for r in childGetObject: 113 | _running = True 114 | yield r 115 | 116 | 117 | def getObjectsHelper_generator(oParent): 118 | global _running 119 | global objectList 120 | ui.message(_("Elements's searching")) 121 | objectList = [] 122 | lastSentIndex = 0 123 | th = runInThread.RepeatBeep( 124 | delay=2.0, beep=(200, 200), isRunning=isRunning) 125 | th.start() 126 | getObjectGen = generateObjectSubtreeGetObject(oParent, itertools.count(), th) 127 | focus = api.getFocusObject() 128 | while True: 129 | _running = True 130 | if api.getFocusObject() != focus: 131 | th.stop() 132 | del th 133 | return 134 | try: 135 | o, lastSentIndex = next(getObjectGen) 136 | # Consider only objects that are visible on screen and with known role 137 | if o.role != Role.UNKNOWN\ 138 | and State.INVISIBLE not in o.states: 139 | objectList.append(o) 140 | except StopIteration: 141 | break 142 | yield 143 | _running = True 144 | th.stop() 145 | del th 146 | ElementListDialog.run(oParent, objectList) 147 | 148 | 149 | def findAllNVDAObjects(oParent): 150 | if isOpened(ElementListDialog): 151 | return 152 | _startGenerator(getObjectsHelper_generator(oParent)) 153 | -------------------------------------------------------------------------------- /addon/doc/ar/addon_keys.t2tconf: -------------------------------------------------------------------------------- 1 | % script command keys definition 2 | %!PostProc (html): KEY_NEXT_ROW_REPORT NVDA+alt+down arrow 3 | %!PostProc (html): KEY_PREVIOUS_ROW_REPORT NVDA+up arrow 4 | %!PostProc (html): KEY_NEXT_COLUMN_REPORT NVDA+alt+right arrow 5 | %!PostProc (html): KEY_PREVIOUS_COLUMN_REPORT NVDA+alt+left arrow 6 | %!PostProc (html): KEY_MOVE_FIRST_CELL_ROW control+alt+shift+left arrow 7 | %!PostProc (html): KEY_MOVE_LAST_CELL_ROW control+alt+shift+right arrow 8 | %!PostProc (html): KEY_MOVE_FIRST_CELL_COLUMN control+alt+shift+up arrow 9 | %!PostProc (html): KEY_MOVE_LAST_CELL_COLUMN control+alt+shift+down arrow 10 | %!PostProc (html): KEY_CURRENT_ROW_REPORT NVDA+alt+j 11 | %!PostProc (html): KEY_CURRENT_COLUMN_REPORT NVDA+alt+l 12 | %!PostProc (html): KEY1_CELL_POSITION_REPORT NVDA+alt+numpad5 13 | %!PostProc (html): KEY2_CELL_POSITION_REPORT NVDA+alt+; 14 | %!PostProc (html): KEY1_DOCUMENT_ADDRESS NVDA+a 15 | %!PostProc (html): KEY2_DOCUMENT_ADDRESS NVDA+shift+a 16 | 17 | % main script command keys definition 18 | %!PostProc (html): KEY_SHELL NVDA+j 19 | %!PostProc (html): KEY_DATE_TIME NVDA + F12 20 | 21 | % default fonctionnality script command keys definition 22 | %!PostProc (html): MAIN_KEY_ICONS_List NVDA + F11 23 | %!PostProc (html): MAIN_KEY_COMPLEX_SYMBOL NVDA + shift + f4 24 | %!PostProc (html): MAIN_KEY_REPORT_NAME_VERSION NVDA + shift + f1 25 | %!PostProc (html): MAIN_KEY_CONFIGURATION_PROFILE NVDA+ control +F1 26 | %!PostProc (html): MAIN_KEY_SAY_CURRENT_FOLDER NVDA+o 27 | %!PostProc (html): MAIN_KEY_LOG_VIEW NVDA+shift+j 28 | %!PostProc (html): MAIN_KEY_PREVIOUS_RECORD NVDA+control+f8 29 | %!PostProc (html): MAIN_KEY_CURRENT_RECORD NVDA+control+f9 30 | %!PostProc (html): MAIN_KEY_NEXT_RECORD NVDA+control+f10 31 | %!PostProc (html): MAIN_KEY_MINUTE_TIMER NVDA+shift+f12 32 | %!PostProc (html): MAIN_KEY_RESTART_NVDA NVDA+control+f4 33 | %!PostProc (html): MAIN_KEY_OBJECTS_LIST NVDA+b 34 | %!PostProc (html): MAIN_KEY_VOICEPROFILE_SELECTOR nvda+shift+control+ selector number 35 | %!PostProc (html): MAIN_KEY_NEXT_VOICEPROFILE nvda+shift+control+right arrow 36 | %!PostProc (html): MAIN_KEY_PREVIOUS_VOICEPROFILE nvda+shift+control+left arrow 37 | %!PostProc (html): MAIN_KEY_MANAGE_SELECTOR nvda+shift+control+m 38 | %!PostProc (html): MAIN_KEY_VOLUME_ON nvda+shift+Échapp" 39 | %!PostProc (html): MAIN_KEY_TOGGLE_MUTE nvda+shift+pause 40 | %!PostProc (html): MAIN_KEY_CLIC_LEFT_MOUSE_BUTTON_At_NAVIGATOR nvda+, 41 | %!PostProc (html): MAIN_KEY_CLIC_RIGHT_MOUSE_BUTTON_At_NAVIGATOR nvda+majuscule+, 42 | % script shell command keys definitions 43 | %!PostProc (html): KEY_APPLICATION_INFORMATIONS a 44 | %!PostProc (html): KEY_OBJECTS_LIST b 45 | %!PostProc (html): KEY_COPY_DATETIME c 46 | %!PostProc (html): KEY_REPORT_FORMATTING f 47 | %!PostProc (html): KEY_ADDON_SETTINGS f1 48 | %!PostProc (html): KEY_RENAMING f2 49 | %!PostProc (html): KEY_SELECTIVE_ANNOUNCEMENT f3 50 | %!PostProc (html): KEY_COMPLEX_SYMBOL f4 51 | %!PostProc (html): KEY_LAST_USED_COMPLEX_SYMBOL control+f4 52 | %!PostProc (html): KEY_TOGGLE_NUMPAD_NAVIGATION f5 53 | %!PostProc (html): KEY_DISPLAY_SPEECH_HISTORY f9 54 | %!PostProc (html): KEY_WINDOWS_LIST F10 55 | %!PostProc (html): KEY_ICONS_List F11 56 | %!PostProc (html): KEY_MINUTE_TIMER f12 57 | %!PostProc (html): KEY_MODULE_GUIDE g 58 | %!PostProc (html): KEY_HELP_SHELL h 59 | %!PostProc (html): KEY_LOG_VIEW j 60 | %!PostProc (html): KEY_SAY_CURRENT_FOLDER o 61 | %!PostProc (html): KEY_VOICE_PROFIL_SWITCHING p 62 | %!PostProc (html): KEY_SHUTDOWN r 63 | %!PostProc (html): KEY_TOGGLE_MUTE s 64 | %!PostProc (html): KEY_VOLUME_ON control+s 65 | %!PostProc (html): KEY_MAIN_VOLUME_UP control+up arrow 66 | %!PostProc (html): KEY_MAIN_VOLUME_DOWN control+down arrow 67 | %!PostProc (html): KEY_MAIN_VOLUME_MAX control+page up 68 | %!PostProc (html): KEY_MAIN_VOLUME_MIN control+page down 69 | %!PostProc (html): KEY_APP_VOLUME_UP up arrow 70 | %!PostProc (html): KEY_APP_VOLUME_DOWN down arrow 71 | %!PostProc (html): KEY_APP_VOLUME_MAX page up 72 | %!PostProc (html): KEY_APP_VOLUME_MIN page down 73 | %!PostProc (html): KEY_TOOLSFORADDON t 74 | %!PostProc (html): KEY_USER_INPUT_GESTURE u 75 | %!PostProc (html): KEY_MANAGE_VOICE_PROFIL v 76 | %!PostProc (html): KEY_CLOSE_ALL_WINDOWS k 77 | %!PostProc (html): KEY_RUNNING_ADDONS e -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/textAnalysis/symbols.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\textAnalysis\symbols.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2021 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | from logHandler import log 9 | import os.path 10 | from configobj import ConfigObj 11 | from configobj.validate import Validator 12 | from io import StringIO 13 | 14 | # sections 15 | SCT_SymbolToSymetric = "SymbolToSymetric" 16 | SCT_Punctuations = "Punctuations" 17 | # symbols for numbers 18 | NUM_DecimalSymbol = "decimalSymbol" 19 | NUM_DigitGroupingSymbol = "digitGroupingSymbol" 20 | # items of Punctuations section 21 | SMBL_All = "All" 22 | SMBL_NeedSpaceBefore = "NeedSpaceBefore" 23 | SMBL_NeedSpaceAfter = "NeedSpaceAfter" 24 | SMBL_NoSpaceBefore = "NoSpaceBefore" 25 | SMBL_NoSpaceAfter = "NoSpaceAfter" 26 | 27 | _configSpec = """ 28 | {decimalSymbol}= string(default=".") 29 | {digitGroupingSymbol}= string(default=",") 30 | [{symbolToSymetric}] 31 | [{punctuations}] 32 | {all}= string(default="") 33 | {needSpaceBefore}= string(default="") 34 | {needSpaceAfter}= string(default="") 35 | {noSpaceBefore}= string(default="") 36 | {noSpaceAfter}= string(default="") 37 | """.format( 38 | decimalSymbol=NUM_DecimalSymbol, 39 | digitGroupingSymbol=NUM_DigitGroupingSymbol, 40 | symbolToSymetric=SCT_SymbolToSymetric, 41 | punctuations=SCT_Punctuations, 42 | all=SMBL_All, 43 | needSpaceBefore=SMBL_NeedSpaceBefore, 44 | needSpaceAfter=SMBL_NeedSpaceAfter, 45 | noSpaceBefore=SMBL_NoSpaceBefore, 46 | noSpaceAfter=SMBL_NoSpaceAfter) 47 | 48 | 49 | def getTextAnalysisIniFilePath(): 50 | from languageHandler import getLanguage 51 | lang = getLanguage() 52 | langs = [lang, ] 53 | addonFolderPath = addonHandler.getCodeAddon().path 54 | if '_' in lang: 55 | langs.append(lang.split("_")[0]) 56 | langs.append("en") 57 | for lang in langs: 58 | langDir = os.path.join(addonFolderPath, "locale", lang) 59 | if os.path.exists(langDir): 60 | file = os.path.join(langDir, "textAnalysis.ini") 61 | if os.path.isfile(file): 62 | log.debugWarning("textAnalyzis.ini file loaded from locale\\%s folder" % lang) 63 | return file 64 | log.error("textAnalysis.ini file not found") 65 | return "" 66 | 67 | 68 | def getSymbolChoiceLabels(): 69 | symbolChoiceLabels = {} 70 | symbolToSymetricDic = getSymbolToSymetricDic() 71 | for symbol, symetric in symbolToSymetricDic.items(): 72 | label = "{symbol} {symetric}".format( 73 | symbol=symbol, 74 | symetric=symetric) 75 | symbolChoiceLabels[symbol] = label 76 | return symbolChoiceLabels 77 | 78 | 79 | def getSymbols_all(): 80 | dic = getPunctuationsDic() 81 | return dic[SMBL_All] 82 | 83 | 84 | def getPunctuationsDic(): 85 | if _conf: 86 | sct = _conf.get(SCT_Punctuations) 87 | if sct is None: 88 | log.error("textAnalysis punctuations section not found") 89 | return sct 90 | log.error("textAnalysis configuration cannot be loaded") 91 | return None 92 | 93 | 94 | def getSymbolToSymetricDic(): 95 | if _conf: 96 | sct = _conf.get(SCT_SymbolToSymetric) 97 | if sct is None: 98 | log.error("textAnalysis symbols section not found") 99 | return sct 100 | log.error("textAnalysis configuration cannot be loaded") 101 | return None 102 | 103 | 104 | def getDecimalSymbol(): 105 | if _conf is None: 106 | return "" 107 | return _conf.get(NUM_DecimalSymbol, "") 108 | 109 | 110 | def getDigitGroupingSymbol(): 111 | if _conf is None: 112 | return "" 113 | return _conf.get(NUM_DigitGroupingSymbol, "") 114 | 115 | 116 | def getTextAnalysisConfig(): 117 | path = getTextAnalysisIniFilePath() 118 | conf = ConfigObj( 119 | path, 120 | configspec=StringIO(""), 121 | encoding="utf-8", 122 | list_values=False) 123 | conf.newlines = "\r\n" 124 | val = Validator() 125 | ret = conf.validate(val, preserve_errors=True, copy=True) 126 | if not ret: 127 | log.warning("KeyboardKeys configuration file is invalid: %s", ret) 128 | return conf 129 | 130 | 131 | # singleton 132 | _conf = getTextAnalysisConfig() 133 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/speechHistory/speechHistoryPatches.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\speechHistory\speechHistoryPatches.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | from logHandler import log 8 | from speech import speech as speech 9 | from collections.abc import Sequence 10 | from ..settings import isInstall 11 | from ..settings.addonConfig import FCT_SpeechHistory, FCT_TemporaryAudioDevice 12 | from ..computerTools.temporaryOutputDevice import checkOutputDeviceChange 13 | from ..speechHistory import getSpeechRecorder 14 | from ..utils.nvdaInfos import NVDAVersion 15 | 16 | # global variables to save original NVDA patched functions 17 | _NVDASpeechSpeak = None 18 | _NVDASpeechSpeakSpelling = None 19 | 20 | 21 | def preSpeechAction(speechSequence): 22 | """ 23 | - record the sequence to speak 24 | - redirect synthetizer and tones to temporary output device if there is one 25 | """ 26 | # reset current output device if temporary output device is set and output device has changed 27 | checkOutputDeviceChange() 28 | if not isinstance(speechSequence, Sequence): 29 | return 30 | if isInstall(FCT_SpeechHistory): 31 | text = " ".join([x for x in speechSequence if isinstance(x, str)]) 32 | getSpeechRecorder().record(text) 33 | 34 | 35 | def _mySpeechSpeak(speechSequence, *args, **kwargs): 36 | """ 37 | speech.speak must be patched to notify pre speech 38 | """ 39 | log.debug("_mySpeechSpeak") 40 | from .extensions import my_pre_speech 41 | my_pre_speech.notify(speechSequence=speechSequence) 42 | _NVDASpeechSpeak(speechSequence, *args, **kwargs) 43 | 44 | 45 | def _mySpeechSpeakSpelling(text, *args, **kwargs): 46 | """ 47 | speech.speakSpelling must be patched to notify pre speech 48 | """ 49 | log.debug("_mySpeechSpeakSpelling") 50 | from .extensions import my_pre_speech 51 | my_pre_speech.notify(speechSequence=text) 52 | _NVDASpeechSpeakSpelling(text, *args, **kwargs) 53 | 54 | 55 | def patche(install=True): 56 | if not install: 57 | removePatch() 58 | return 59 | if not isInstall(FCT_SpeechHistory) and not isInstall(FCT_TemporaryAudioDevice): 60 | return 61 | from . import extensions 62 | extensions.my_pre_speech.register(preSpeechAction) 63 | if NVDAVersion >= [2024, 2]: 64 | # we don't need to patch nvda speech methods 65 | return 66 | global _NVDASpeechSpeak, _NVDASpeechSpeakSpelling 67 | # patche speech.speak 68 | _NVDASpeechSpeak = speech.speak 69 | if speech.speak.__module__ != "speech.speech": 70 | log.warning( 71 | "Incompatibility: speech.speech.speak method has also been patched probably by another add-on: %s." 72 | "There is a risk of malfunction" % speech.speak.__module__) 73 | speech.speak = _mySpeechSpeak 74 | log.debug( 75 | "For speech history functionality," 76 | " speech.speech.speak method has been replaced by %s method of %s module" % ( 77 | _mySpeechSpeak.__name__, _mySpeechSpeak.__module__) 78 | ) 79 | # patce speech.speakSpelling 80 | _NVDASpeechSpeakSpelling = speech.speakSpelling 81 | if speech.speakSpelling .__module__ != "speech.speech": 82 | log.warning( 83 | "Incompatibility: speech.speech.speakSpelling method has also been atched probably by another add-on: %s." 84 | "There is a risk of malfunction" % speech.speakSpelling .__module__) 85 | speech.speakSpelling = _mySpeechSpeakSpelling 86 | log.debug( 87 | "For speech history functionality," 88 | " speech.speech.speakSpelling method has been replaced by %s method of %s module" % ( 89 | _mySpeechSpeakSpelling.__name__, _mySpeechSpeakSpelling.__module__) 90 | ) 91 | 92 | 93 | def removePatch(): 94 | from .extensions import my_pre_speech 95 | my_pre_speech.unregister(preSpeechAction) 96 | global _NVDASpeechSpeak, _NVDASpeechSpeakSpelling 97 | if _NVDASpeechSpeak: 98 | speech.speak = _NVDASpeechSpeak 99 | _NVDASpeechSpeak = None 100 | log.debug("nvda speech method is restored") 101 | if _NVDASpeechSpeakSpelling: 102 | speech.speakSpelling = _NVDASpeechSpeakSpelling 103 | _NVDASpeechSpeakSpelling = None 104 | log.debug("NVDA speakSpelling method is restored") 105 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/computerTools/pycawUtils.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\utilities\pycawEx\myPycawUtils.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2024 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | # patch of AudioUtilities pycaw class to get audio sources of a specific device 8 | 9 | from logHandler import log 10 | import comtypes 11 | from ..utils.nvdaInfos import NVDAVersion 12 | 13 | if NVDAVersion >= [2024, 2]: 14 | # for nvda version >= 2024.2 15 | from pycaw.api.audiopolicy import IAudioSessionControl2, IAudioSessionManager2 16 | from pycaw.api.mmdeviceapi import IMMDeviceEnumerator 17 | from pycaw.constants import ( 18 | DEVICE_STATE, 19 | CLSID_MMDeviceEnumerator, 20 | EDataFlow, 21 | ERole, 22 | ) 23 | from pycaw.utils import AudioUtilities, AudioSession 24 | else: 25 | # for nvda version <2024.2 26 | import sys 27 | import os 28 | sysPath = list(sys.path) 29 | if "pycaw" in sys.modules: 30 | log.warning("Potential incompatibility: pycaw module is also used and loaded probably by other add-on") 31 | del sys.modules["pycaw"] 32 | sys.path = [sys.path[0]] 33 | from ..utils.py3Compatibility import getCommonUtilitiesPath 34 | commonUtilitiesPath = getCommonUtilitiesPath() 35 | pycawPath = os.path.join(commonUtilitiesPath, "pycawEx") 36 | psutilPath = os.path.join(commonUtilitiesPath, "psutilEx") 37 | sys.path.append(commonUtilitiesPath) 38 | sys.path.append(psutilPath) 39 | sys.path.append(pycawPath) 40 | from pycawEx.pycaw.api.audiopolicy import IAudioSessionControl2, IAudioSessionManager2 41 | from pycawEx.pycaw.api.mmdeviceapi import IMMDeviceEnumerator 42 | from pycawEx.pycaw.constants import ( 43 | DEVICE_STATE, 44 | CLSID_MMDeviceEnumerator, 45 | EDataFlow, 46 | ERole, 47 | ) 48 | from pycawEx.pycaw.utils import AudioUtilities, AudioSession 49 | sys.path = sysPath 50 | 51 | 52 | class MyAudioUtilities(AudioUtilities): 53 | 54 | @staticmethod 55 | def GetSpeakers(audioDeviceID=None): 56 | """ 57 | get the speakers (1st render + multimedia) device 58 | """ 59 | deviceEnumerator = comtypes.CoCreateInstance( 60 | CLSID_MMDeviceEnumerator, 61 | IMMDeviceEnumerator, 62 | comtypes.CLSCTX_INPROC_SERVER) 63 | if audioDeviceID is None: 64 | speakers = deviceEnumerator.GetDefaultAudioEndpoint( 65 | EDataFlow.eRender.value, ERole.eMultimedia.value) 66 | else: 67 | speakers = deviceEnumerator.GetDevice(audioDeviceID) 68 | return speakers 69 | 70 | @staticmethod 71 | def GetAudioSessionManager(audioDeviceID=None): 72 | speakers = MyAudioUtilities.GetSpeakers(audioDeviceID) 73 | if speakers is None: 74 | return None 75 | # win7+ only 76 | o = speakers.Activate(IAudioSessionManager2._iid_, comtypes.CLSCTX_ALL, None) 77 | mgr = o.QueryInterface(IAudioSessionManager2) 78 | return mgr 79 | 80 | @staticmethod 81 | def GetAllSessions(audioDeviceID=None): 82 | audio_sessions = [] 83 | mgr = MyAudioUtilities.GetAudioSessionManager(audioDeviceID) 84 | if mgr is None: 85 | return audio_sessions 86 | sessionEnumerator = mgr.GetSessionEnumerator() 87 | count = sessionEnumerator.GetCount() 88 | for i in range(count): 89 | ctl = sessionEnumerator.GetSession(i) 90 | if ctl is None: 91 | continue 92 | ctl2 = ctl.QueryInterface(IAudioSessionControl2) 93 | if ctl2 is not None: 94 | audio_session = AudioSession(ctl2) 95 | audio_sessions.append(audio_session) 96 | return audio_sessions 97 | 98 | @staticmethod 99 | def GetAllDevices(flow=EDataFlow.eAll, state=DEVICE_STATE.MASK_ALL): 100 | devices = [] 101 | deviceEnumerator = comtypes.CoCreateInstance( 102 | CLSID_MMDeviceEnumerator, IMMDeviceEnumerator, comtypes.CLSCTX_INPROC_SERVER 103 | ) 104 | if deviceEnumerator is None: 105 | return devices 106 | 107 | collection = deviceEnumerator.EnumAudioEndpoints( 108 | flow.value, state.value 109 | ) 110 | if collection is None: 111 | return devices 112 | 113 | count = collection.GetCount() 114 | for i in range(count): 115 | dev = collection.Item(i) 116 | if dev is not None: 117 | devices.append(MyAudioUtilities.CreateDevice(dev)) 118 | return devices 119 | -------------------------------------------------------------------------------- /addon/globalPlugins/NVDAExtensionGlobalPlugin/speechHistory/__init__.py: -------------------------------------------------------------------------------- 1 | # globalPlugins\NVDAExtensionGlobalPlugin\speechHistory\__init__.py 2 | # A part of NVDAExtensionGlobalPlugin add-on 3 | # Copyright (C) 2016 - 2025 paulber19 4 | # This file is covered by the GNU General Public License. 5 | # See the file COPYING for more details. 6 | 7 | import addonHandler 8 | import tones 9 | import ui 10 | import api 11 | from ..utils.informationDialog import InformationDialog 12 | from ..utils.NVDAStrings import NVDAString 13 | from ..settings import toggleSpeechRecordWithNumberOption, toggleSpeechRecordInAscendingOrderOption 14 | 15 | addonHandler.initTranslation() 16 | 17 | # constants 18 | MAX_RECORD = 200 19 | # global variables 20 | _speechRecorder = None 21 | _NVDASpeak = None 22 | _NVDASpeakSpelling = None 23 | 24 | 25 | def getSpeechRecorder(): 26 | return _speechRecorder 27 | 28 | 29 | def isActive(): 30 | return _speechRecorder is not None 31 | 32 | 33 | class SpeechRecorderManager(object): 34 | def __init__(self): 35 | self._speechHistory = [] 36 | self._lastSpeechHistoryReportIndex = None 37 | self._onMonitoring = True 38 | 39 | def record(self, text): 40 | if not text or not self._onMonitoring: 41 | return 42 | while len(text): 43 | if text[-1] not in ["\n", "\r"]: 44 | break 45 | text = text[:-1] 46 | 47 | if len(text.strip()) == 0: 48 | return 49 | self._speechHistory.append(text) 50 | if len(self._speechHistory) > MAX_RECORD: 51 | self._speechHistory.pop(0) 52 | self._lastSpeechHistoryReportIndex = len(self._speechHistory) - 1 53 | 54 | def reportSpeechHistory(self, position, toClip=False): 55 | index = self._lastSpeechHistoryReportIndex 56 | if index is None: 57 | return 58 | oldOnMonitoring = self._onMonitoring 59 | self._onMonitoring = False 60 | if position == "previous" and index > 0: 61 | index -= 1 62 | elif position == "next" and index < len(self._speechHistory) - 1: 63 | index += 1 64 | if (position != "current") and (index == self._lastSpeechHistoryReportIndex): 65 | tones.beep(100, 40) 66 | self._lastSpeechHistoryReportIndex = index 67 | text = self._speechHistory[index] 68 | if not toClip: 69 | ui.message(text) 70 | self._onMonitoring = oldOnMonitoring 71 | return 72 | if not api.copyToClip(text): 73 | # Translators: Presented when unable to copy to the clipboard because of an error. 74 | ui.message(NVDAString("Unable to copy")) 75 | # Translators: message to user to report copy to clipboard 76 | ui.message(_("{0} copied to clipboard") .format(text)) 77 | self._onMonitoring = oldOnMonitoring 78 | 79 | def displaySpeechHistory(self): 80 | text = [] 81 | for index in range(0, len(self._speechHistory)): 82 | s = self._speechHistory[index] 83 | if toggleSpeechRecordWithNumberOption(False): 84 | text.append(str(" {index}: {annonce}").format( 85 | index=index + 1, annonce=s)) 86 | else: 87 | text .append(str(s)) 88 | if not toggleSpeechRecordInAscendingOrderOption(False): 89 | text.reverse() 90 | text = "\r\n".join(text) 91 | # Translators: title of informations dialog. 92 | dialogTitle = _("Speech history") 93 | if toggleSpeechRecordInAscendingOrderOption(False): 94 | insertionPointOnLastLine = True 95 | else: 96 | insertionPointOnLastLine = False 97 | # Translators: label of information area. 98 | informationLabel = _("Records:") 99 | InformationDialog.run( 100 | None, dialogTitle, informationLabel, text, insertionPointOnLastLine) 101 | 102 | 103 | def initialize(): 104 | from . import speechHistoryPatches 105 | from ..settings import isInstall 106 | from ..settings.addonConfig import FCT_SpeechHistory, FCT_TemporaryAudioDevice 107 | global _NVDASpeak, _NVDASpeakSpelling 108 | global _speechRecorder 109 | if _speechRecorder is not None: 110 | return 111 | if not isInstall(FCT_SpeechHistory) and not isInstall(FCT_TemporaryAudioDevice): 112 | return 113 | _speechRecorder = SpeechRecorderManager() 114 | speechHistoryPatches.patche(install=True) 115 | 116 | 117 | def terminate(): 118 | global _speechRecorder 119 | if _speechRecorder is None: 120 | return 121 | from . import speechHistoryPatches 122 | speechHistoryPatches.patche(install=False) 123 | _speechRecorder = None 124 | --------------------------------------------------------------------------------