Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
75b163b
Support for uncontracted and contracted braille input.
jcsteh Oct 11, 2016
eb7babf
Address code review comments.
jcsteh Oct 11, 2016
0b643d6
brailleInput: Fix exceptions when typing a single cell, pressing spac…
jcsteh Oct 12, 2016
11912ca
User Guide: Add note about translation only reflecting the braille wo…
jcsteh Oct 12, 2016
f4859a5
Pressing dot7+dot8 translates immediately but without adding a space …
jcsteh Oct 12, 2016
5ff07e5
Mask braille input in protected fields.
jcsteh Oct 12, 2016
2f3f4fc
Merge branch 'master' into i2439ContractedBrailleInput
jcsteh Oct 13, 2016
e78f955
Update to a temporary NV Access branch of liblouis which incorporates…
jcsteh Oct 17, 2016
414504d
Add the Unicode braille input table.
jcsteh Oct 17, 2016
7efa322
Use new liblouis modes to improve back-translation:
jcsteh Oct 17, 2016
a224cab
liblouis sconscript: Add additional source file added in liblouis 3.1.0.
jcsteh Mar 20, 2017
84bbd53
Merge branch 'master' into i2439ContractedBrailleInput
jcsteh Mar 20, 2017
f240afc
Merge branch 'i6935Liblouis3.1' into i2439ContractedBrailleInput
jcsteh Mar 20, 2017
61d7c16
Update to liblouis 3.1.0, though we're still using a temporary NV Acc…
jcsteh Mar 20, 2017
5d202d4
Merge branch 'master' into i2439ContractedBrailleInput
jcsteh Jun 9, 2017
7aef11d
Upgrade to liblouis 3.2.0.
jcsteh Jun 9, 2017
99b1fbf
Don't need liblouis.def any more.
jcsteh Jun 9, 2017
1d6035b
Place indicators at the start and end of braille input so users under…
jcsteh Jun 14, 2017
36dac59
Clear braille input state if the caret gets moved (other than by text…
jcsteh Jun 15, 2017
243d39f
Fix keyboardHandler's treatment of Unicode characters sent by SendInp…
jcsteh Jun 16, 2017
840e516
braille: Remove RENAMED_TABLES, as this got moved to brailleTables.
jcsteh Jun 19, 2017
9f0d714
brailleInput: Handle renamed tables like we do for braille output, wh…
jcsteh Jun 19, 2017
77abb34
Switch to a fork of liblouis 3.2.0 which contains some additional bac…
jcsteh Jun 19, 2017
9a4537c
readme: Update liblouis version.
jcsteh Jun 19, 2017
ff6f627
brailleTables: Update for rename of Greek table in liblouis 3.2.0. Al…
jcsteh Jun 19, 2017
e2f8609
Switch liblouis to official liblouis master, since all fixes from us …
jcsteh Jun 20, 2017
c0004f0
Review actions.
jcsteh Jun 20, 2017
84e6565
BrailleInputGesture: Don't use Python set order for gesture identifie…
jcsteh Jun 21, 2017
c2c7162
inputCore: Update code doc.
jcsteh Jun 22, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "include/liblouis"]
path = include/liblouis
url = https://github.com/liblouis/liblouis.git
url = https://github.com/nvaccess/liblouis.git
[submodule "include/minhook"]
path = include/minhook
url = https://github.com/RaMMicHaeL/minhook
Expand Down
2 changes: 1 addition & 1 deletion include/liblouis
Submodule liblouis updated 627 files
23 changes: 0 additions & 23 deletions nvdaHelper/liblouis/liblouis.def

This file was deleted.

17 changes: 14 additions & 3 deletions nvdaHelper/liblouis/sconscript
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
###
#This file is a part of the NVDA project.
#URL: http://www.nvda-project.org/
#Copyright 2006-2012 NVDA contributers.
#Copyright 2011-2017 NV Access Limited, Joseph Lee
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License version 2.0, as published by
#the Free Software Foundation.
Expand Down Expand Up @@ -40,10 +40,19 @@ env = env.Clone()
if 'analyze' in env['nvdaHelperDebugFlags']:
env.Append(CCFLAGS='/analyze-')

env.Append(CCFLAGS="/W2")
env.Append(CPPDEFINES=[
# The Visual C++ C Runtime deprecates several standard library functions in
# preference for _s variants that are specific to Visual C++. This removes
# those deprecation warnings.
"_CRT_SECURE_NO_WARNINGS",
# The Visual C++ C Runtime deprecates standard POSIX APIs that conflict with
# reserved ISO C names (like strdup) in favour of non-portable conforming
# variants that start with an '_'. This removes those deprecation warnings. */
"_CRT_NONSTDC_NO_DEPRECATE",
("PACKAGE_VERSION", r'\"%s\"' % getLouisVersion()),
("UNICODE_BITS", 16),
# Tell liblouis.h that we're exporting liblouis dll functions, not importing them.
"_EXPORTING",
])
env.Prepend(CPPPATH=[".", louisSourceDir])

Expand All @@ -57,9 +66,11 @@ sourceFiles = [
"wrappers.c",
"logging.c",
"pattern.c",
"commonTranslationFunctions.c",
"utils.c",
]
objs = [env.Object("%s.obj" % f, louisSourceDir.File(f)) for f in sourceFiles]
louisLib = env.SharedLibrary("liblouis", objs + ["liblouis.def"])
louisLib = env.SharedLibrary("liblouis", objs)
env.Install(sourceDir, louisLib)

louisPython = env.Substfile(outDir.File("__init__.py"), louisRootDir.File("python/louis/__init__.py.in"),
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ For reference, the following dependencies are included in Git submodules:
* [Sonic](https://github.com/waywardgeek/sonic), commit 4f8c1d11
* [IAccessible2](http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2), version 1.3
* [ConfigObj](http://www.voidspace.org.uk/python/configobj.html), version 4.6.0
* [liblouis](http://www.liblouis.org/), version 3.0.0
* [liblouis](http://www.liblouis.org/), version 3.2.0
* NVDA images and sounds
* System dlls not present on many systems: mfc90.dll, msvcp90.dll, msvcr90.dll, Microsoft.VC90.CRT.manifest
* [Adobe Acrobat accessibility interface, version XI](http://download.macromedia.com/pub/developer/acrobat/AcrobatAccess.zip)
Expand Down
1 change: 1 addition & 0 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ def event_descriptionChange(self):
def event_caret(self):
if self is api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"):
braille.handler.handleCaretMove(self)
brailleInput.handler.handleCaretMove(self)
review.handleCaretMove(self)

def _get_flatReviewPosition(self):
Expand Down
49 changes: 27 additions & 22 deletions source/braille.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: UTF-8 -*-
#braille.py
#A part of NonVisual Desktop Access (NVDA)
#This file is covered by the GNU General Public License.
Expand Down Expand Up @@ -25,18 +26,6 @@
import inputCore
import brailleTables

#: Maps old table names to new table names for tables renamed in newer versions of liblouis.
RENAMED_TABLES = {
"da-dk-g16.utb":"da-dk-g16.ctb",
"da-dk-g18.utb":"da-dk-g18.ctb",
"nl-BE-g1.ctb":"nl-BE-g0.utb",
"nl-NL-g1.ctb":"nl-NL-g0.utb",
"no-no.ctb":"no-no-comp8.ctb",
"sk-sk-g1.utb":"sk-g1.ctb",
"UEBC-g1.ctb":"en-ueb-g1.ctb",
"UEBC-g2.ctb":"en-ueb-g2.ctb",
}

roleLabels = {
# Translators: Displayed in braille for an object which is an
# editable text field.
Expand Down Expand Up @@ -138,6 +127,11 @@
)
SELECTION_SHAPE = 0xC0 #: Dots 7 and 8

#: Unicode braille indicator at the start of untranslated braille input.
INPUT_START_IND = u"⣏"
#: Unicode braille indicator at the end of untranslated braille input.
INPUT_END_IND = u" ⣹"

# used to separate chunks of text when programmatically joined
TEXT_SEPARATOR = " "

Expand Down Expand Up @@ -732,12 +726,12 @@ def update(self):
import brailleInput

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this import local and not at the top of the file? Perhaps add a comment

text = brailleInput.handler.untranslatedBraille
if text:
rawInputStart = len(self.rawText)
rawInputIndStart = len(self.rawText)
# _addFieldText adds text to self.rawText and updates other state accordingly.
self._addFieldText(text, None, separate=False)
rawInputEnd = len(self.rawText)
self._addFieldText(INPUT_START_IND + text + INPUT_END_IND, None, separate=False)
rawInputIndEnd = len(self.rawText)
else:
rawInputStart = None
rawInputIndStart = None
# Now, the selection itself.
self._addTextWithFields(sel, formatConfig, isSelection=True)
# Finally, get the chunk from the end of the selection to the end of the reading unit.
Expand Down Expand Up @@ -772,17 +766,28 @@ def update(self):
self.focusToHardLeft = self._isMultiline()
super(TextInfoRegion, self).update()

if rawInputStart is not None:
assert rawInputEnd is not None, "rawInputStart set but rawInputEnd isn't"
self._brailleInputStart = self.rawToBraillePos[rawInputStart]
self._brailleInputEnd = self.rawToBraillePos[rawInputEnd]
if rawInputIndStart is not None:
assert rawInputIndEnd is not None, "rawInputIndStart set but rawInputIndEnd isn't"
# These are the start and end of the untranslated input area,
# including the start and end indicators.
self._brailleInputIndStart = self.rawToBraillePos[rawInputIndStart]
self._brailleInputIndEnd = self.rawToBraillePos[rawInputIndEnd]
# These are the start and end of the actual untranslated input, excluding indicators.
self._brailleInputStart = self._brailleInputIndStart + len(INPUT_START_IND)
self._brailleInputEnd = self._brailleInputIndEnd - len(INPUT_END_IND)
self.brailleCursorPos = self._brailleInputStart + brailleInput.handler.untranslatedCursorPos
else:
self._brailleInputStart = None
self._brailleInputIndStart = None

def routeTo(self, braillePos):
if self._brailleInputStart is not None and self._brailleInputStart <= braillePos <= self._brailleInputEnd:
if self._brailleInputIndStart is not None and self._brailleInputIndStart <= braillePos < self._brailleInputIndEnd:
# The user is moving within untranslated braille input.
if braillePos < self._brailleInputStart:
# The user routed to the start indicator. Route to the start of the input.
braillePos = self._brailleInputStart
elif braillePos > self._brailleInputEnd:
# The user routed to the end indicator. Route to the end of the input.
braillePos = self._brailleInputEnd
# Import late to avoid circular import.
import brailleInput

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here, not at the top of the file?

brailleInput.handler.untranslatedCursorPos = braillePos - self._brailleInputStart
Expand Down
50 changes: 40 additions & 10 deletions source/brailleInput.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#Copyright (C) 2012-2016 NV Access Limited, Rui Batista

import os.path
import time
import louis
import brailleTables
import braille
Expand All @@ -23,6 +24,8 @@
as there are built-in gesture bindings for braille input.
"""

#: Table to use if the input table configuration is invalid.
FALLBACK_TABLE = "en-us-comp8.ctb"
DOT7 = 1 << 6
DOT8 = 1 << 7
#: This bit flag must be added to all braille cells when using liblouis with dotsIO.
Expand All @@ -33,9 +36,6 @@
#: The Unicode braille character to use when masking cells in protected fields.
#: @type: unicode
UNICODE_BRAILLE_PROTECTED = u"⣿" # All dots down
#: The letters "zz" in braille (dot 1 3 5 6 twice).
#: This is used by L{brailleInputHandler._translateForReportContractedCell}.
BRAILLE_ZZ = [0b110101] * 2

#: The singleton BrailleInputHandler instance.
#: @type: L{BrailleInputHandler}
Expand All @@ -55,7 +55,16 @@ class BrailleInputHandler(object):
"""

def __init__(self):
self._table = brailleTables.getTable(config.conf["braille"]["inputTable"])
# #6140: Migrate to new table names as smoothly as possible.
tableName = config.conf["braille"]["inputTable"]
newTableName = brailleTables.RENAMED_TABLES.get(tableName)
if newTableName:
tableName = config.conf["braille"]["inputTable"] = newTableName
try:
self._table = brailleTables.getTable(tableName)
except LookupError:
log.error("Invalid table: %s" % tableName)
self._table = brailleTables.getTable(FALLBACK_TABLE)
#: A buffer of entered braille cells so that state set by previous cells can be maintained;
#: e.g. capital and number signs.
self.bufferBraille = []
Expand All @@ -77,6 +86,8 @@ def __init__(self):
#: The user's cursor position within the untranslated braille.
#: This enables the user to move within the untranslated braille.
self.untranslatedCursorPos = 0
#: The time at which uncontracted characters were sent to the system.
self._uncontSentTime = None

@property
def table(self):
Expand Down Expand Up @@ -108,14 +119,16 @@ def _translate(self, endWord):
self.bufferText = louis.backTranslate(
[os.path.join(brailleTables.TABLES_DIR, self._table.fileName),
"braille-patterns.cti"],
data, mode=louis.dotsIO)[0]
data, mode=louis.dotsIO | louis.noUndefinedDots)[0]
newText = self.bufferText[oldTextLen:]
if newText:
# New text was generated by the cells just entered.
if self._table.contracted:
# For contracted braille, an entire word is sent at once.
# Don't speak characters as this is sent.
speech._suppressSpeakTypedCharacters(len(newText))
else:
self._uncontSentTime = time.time()
self.untranslatedStart = pos
self.untranslatedCursorPos = 0
self.sendChars(newText)
Expand All @@ -140,16 +153,14 @@ def _translateForReportContractedCell(self, pos):
@return: The previous translated text.
@rtype: unicode
"""
# Append braille "zz" so full word contractions don't take effect.
cells = self.bufferBraille[:pos + 1] + BRAILLE_ZZ
cells = self.bufferBraille[:pos + 1]
data = u"".join([unichr(cell | LOUIS_DOTS_IO_START) for cell in cells])
oldText = self.bufferText
text = louis.backTranslate(
[os.path.join(brailleTables.TABLES_DIR, self._table.fileName),
"braille-patterns.cti"],
data, mode=louis.dotsIO)[0]
# Strip the "zz".
self.bufferText = text[:-2]
data, mode=louis.dotsIO | louis.noUndefinedDots | louis.partialTrans)[0]
self.bufferText = text
return oldText

def _reportContractedCell(self, pos):
Expand Down Expand Up @@ -250,11 +261,13 @@ def eraseLastCell(self):
index = self.untranslatedStart + self.untranslatedCursorPos - 1
if index < 0:
# Erasing before the start of the buffer.
self._uncontSentTime = time.time()
inputCore.manager.emulateGesture(keyboardHandler.KeyboardInputGesture.fromName("backspace"))
return
cell = self.bufferBraille.pop(index)
if index in self.cellsWithText:
# Erase a real character.
self._uncontSentTime = time.time()
inputCore.manager.emulateGesture(keyboardHandler.KeyboardInputGesture.fromName("backspace"))
char = self.bufferText[-1]
self.bufferText = self.bufferText[:-1]
Expand Down Expand Up @@ -317,6 +330,23 @@ def handleGainFocus(self, obj):
# Clear all state when the focus changes.
self.flushBuffer()

def handleCaretMove(self, obj):
if not self.bufferBraille:
# No pending braille input, so nothing to do.
return
if self._uncontSentTime:
# Uncontracted braille recently sent characters to the system.
# This might cause a caret move, but we don't want to clear state
# due to our own text entry.
# If the caret move occurred within a short time, we assume it was caused by us.
if time.time() - self._uncontSentTime <= 0.3:
# This was caused by us. Ignore it.
return
self._uncontSentTime = None
# Braille input is incomplete, but the cursor has been moved.
# Clear all state.
self.flushBuffer()

def handleConfigProfileSwitch(self):
table = config.conf["braille"]["inputTable"]
if table != self._table.fileName:
Expand Down
23 changes: 17 additions & 6 deletions source/brailleTables.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,28 @@
#: * fileName: The file name of the table.
#: * displayname: The name of the table as displayed to the user. This should be translatable.
#: * contracted: C{True} if the table is contracted, C{False} if uncontracted.
BrailleTable = collections.namedtuple("BrailleTable", ("fileName", "displayName", "contracted"))
BrailleTable = collections.namedtuple("BrailleTable", ("fileName", "displayName", "contracted", "output", "input"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This docstring should also have output and input


#: Maps file names to L{BrailleTable} objects.
_tables = {}

def addTable(fileName, displayName, contracted=False):
def addTable(fileName, displayName, contracted=False, output=True, input=True):
"""Register a braille translation table.
At least one of C{input} or C{output} must be C{True}.
@param fileName: The file name of the table.
@type fileName: basestring
@param displayname: The name of the table as displayed to the user. This should be translatable.
@type displayName: unicode
@param contracted: C{True} if the table is contracted, C{False} if uncontracted.
@type cContracted: bool
@param output: C{True} if this table can be used for output, C{False} if not.
@type output: bool
@param input: C{True} if this table can be used for input, C{False} if not.
@type input: bool
"""
table = BrailleTable(fileName, displayName, contracted)
if not output and not input:
raise ValueError("input and output cannot both be False")
table = BrailleTable(fileName, displayName, contracted, output, input)
_tables[fileName] = table

def getTable(fileName):
Expand All @@ -55,6 +62,7 @@ def listTables():
RENAMED_TABLES = {
"da-dk-g16.utb":"da-dk-g16.ctb",
"da-dk-g18.utb":"da-dk-g18.ctb",
"gr-gr-g1.utb":"el.ctb",
"nl-BE-g1.ctb":"nl-BE-g0.utb",
"nl-NL-g1.ctb":"nl-NL-g0.utb",
"no-no.ctb":"no-no-comp8.ctb",
Expand Down Expand Up @@ -114,6 +122,9 @@ def listTables():
addTable("de-de-g2.ctb", _("German grade 2"), contracted=True)
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("el.ctb", _("Greek (Greece)"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("en-gb-comp8.ctb", _("English (U.K.) 8 dot computer braille"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
Expand Down Expand Up @@ -186,9 +197,6 @@ def listTables():
addTable("gr-bb.ctb", _("Koine Greek"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("gr-gr-g1.utb", _("Greek (Greece) grade 1"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("he.ctb", _("Hebrew 8 dot computer braille"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
Expand Down Expand Up @@ -321,6 +329,9 @@ def listTables():
addTable("tr.ctb", _("Turkish grade 1"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("unicode-braille.utb", _("Unicode braille"), output=False)
# Translators: The name of a braille table displayed in the
# braille settings dialog.
addTable("zh-hk.ctb", _("Chinese (Hong Kong, Cantonese)"))
# Translators: The name of a braille table displayed in the
# braille settings dialog.
Expand Down
Loading