Skip to content
Commits on Source (2)
......@@ -35,7 +35,8 @@ import louis
# Interval during which all keys should be released at the same time
release_delay = 0.3
louis_tables = [ 'en-us-brf.dis', 'unicode.dis', 'fr-bfu-g2.ctb' ]
contracted_louis_tables = [ 'en-us-brf.dis', 'unicode.dis', 'fr-bfu-g2.ctb' ]
literal_louis_tables = [ 'en-us-brf.dis', 'unicode.dis', 'fr-bfu-comp8.utb' ]
# TODO: configurable
std_map = {
......@@ -51,38 +52,90 @@ std_map = {
brf = {
'': ' ',
'': 'A',
'': 'B',
'': 'C',
'': 'D',
'': 'E',
'': 'F',
'': 'G',
'': 'H',
'': 'I',
'': 'J',
'': 'K',
'': 'L',
'': 'M',
'': 'N',
'': 'O',
'': 'P',
'': 'Q',
'': 'R',
'': 'S',
'': 'T',
'': 'U',
'': 'V',
'': 'W',
'': 'X',
'': 'Y',
'': 'Z',
'': 'a',
'': 'b',
'': 'c',
'': 'd',
'': 'e',
'': 'f',
'': 'g',
'': 'h',
'': 'i',
'': 'j',
'': 'k',
'': 'l',
'': 'm',
'': 'n',
'': 'o',
'': 'p',
'': 'q',
'': 'r',
'': 's',
'': 't',
'': 'u',
'': 'v',
'': 'w',
'': 'x',
'': 'y',
'': 'z',
'': 'A',
'': 'B',
'': 'C',
'': 'D',
'': 'E',
'': 'F',
'': 'G',
'': 'H',
'': 'I',
'': 'J',
'': 'K',
'': 'L',
'': 'M',
'': 'N',
'': 'O',
'': 'P',
'': 'Q',
'': 'R',
'': 'S',
'': 'T',
'': 'U',
'': 'V',
'': 'W',
'': 'X',
'': 'Y',
'': 'Z',
'': '1',
'': '2',
'': '3',
'': '4',
'': '5',
'': '6',
'': '7',
'': '8',
'': '9',
'': '0',
}
backbrf = {
a : b for b, a in brf.items()
}
def to_brf(s):
s2 = ""
for c in s:
if c in brf:
c = brf[c]
s2 = s2 + c
return s2
def from_brf(s):
s2 = ""
for c in s:
if c in backbrf:
c = backbrf[c]
s2 = s2 + c
return s2
# TODO: needs to be user-defined
separators = {
'': ' ',
......@@ -101,8 +154,11 @@ def debug(l, *args):
class EngineBraille(IBus.Engine):
__gtype_name__ = 'EngineBraille'
# whether Braille typing is enabled
enabled = False
# whether PC Braille typing is enabled
PC_enabled = False
# whether Braille uncontraction is enabled
uncontraction = False
# whether Math mode is enabled (no liblouis uncontraction, not BRF display)
math = False
......@@ -123,11 +179,14 @@ class EngineBraille(IBus.Engine):
preedit = ""
# whether the current word is a contracted word being typed or a transcribed text
contracted = True
contracted = False
# brlapi.Connection object
brlapi_connection = None
# whether last key event was a release
releasing = False
def __init__(self):
super(EngineBraille, self).__init__()
debug(5, "init")
......@@ -144,7 +203,8 @@ class EngineBraille(IBus.Engine):
def do_focus_out(self):
debug(2, "focus out")
self.__commit()
self.enabled = False
self.PC_enabled = False
self.uncontraction = False
self.brlapi_set()
def do_process_key_event(self, keysym, scancode, state):
......@@ -159,19 +219,40 @@ class EngineBraille(IBus.Engine):
is_press = (state & IBus.ModifierType.RELEASE_MASK) == 0
has_control = (state & IBus.ModifierType.CONTROL_MASK) != 0
has_alt = (state & IBus.ModifierType.META_MASK) != 0
has_alt = (state & IBus.ModifierType.MOD1_MASK) != 0
has_shift = (state & IBus.ModifierType.SHIFT_MASK) != 0
has_super = (state & IBus.ModifierType.SUPER_MASK) != 0
was_releasing = self.releasing
self.releasing = is_press == False
if ((keysym == XK_Shift_L or keysym == XK_Shift_R) and has_control and has_alt) or \
((keysym == XK_Control_L or keysym == XK_Control_R) and has_shift and has_alt) or \
((keysym == XK_Alt_L or keysym == XK_Alt_R or keysym == XK_Meta_L or keysym == XK_Meta_R) and has_control and has_shift):
if not is_press and not was_releasing:
self.PC_enabled = not self.PC_enabled
debug(2, "PC enabled" if self.PC_enabled else "PC disabled")
return True
if ((keysym == XK_Shift_L or keysym == XK_Shift_R) and has_control) or \
((keysym == XK_Control_L or keysym == XK_Control_R) and has_shift):
if is_press:
self.enabled = not self.enabled
self.math = keysym == XK_Shift_R or keysym == XK_Control_R
if not is_press and not was_releasing:
if keysym == XK_Shift_R or keysym == XK_Control_R:
if not self.math:
self.math = True
self.uncontraction = False
else:
self.math = False
else:
if not self.uncontraction:
self.math = False
self.uncontraction = True
else:
self.uncontraction = False
self.brlapi_set()
if not self.enabled:
if not self.uncontraction:
self.__commit()
debug(2, "enabled" if self.enabled else "disabled")
debug(2, "uncontraction" if self.uncontraction else "literal")
debug(2, "math" if self.math else "text")
return True
......@@ -180,6 +261,7 @@ class EngineBraille(IBus.Engine):
debug(2, "switching maths")
text = self.get_surrounding_text()
s = text.text.get_text()
slen = len(s)
c = text.cursor_pos
a = text.anchor_pos
......@@ -198,6 +280,7 @@ class EngineBraille(IBus.Engine):
#url = "mathbraille2mathml.json"
debug(2, "from Braille to StarMath")
url = "mathbraille2starmath.json"
s = from_brf(s).replace(chr(0x2800),'')
else:
#debug(2, "from MathML to Braille")
#url = "mathml2braille.json"
......@@ -211,7 +294,7 @@ class EngineBraille(IBus.Engine):
s2 = s2.replace('\n', ' ')
s2 = s2.replace('\t', ' ')
debug(4, "text sent to natbraille is '%s'" % s2)
debug(2, "text sent to natbraille is '%s'" % s2)
conn = http.client.HTTPConnection("localhost:4567")
conn.request("POST", "/tdf/" + url,
......@@ -230,7 +313,7 @@ class EngineBraille(IBus.Engine):
debug(4, "natbraille status '" + v['status'] + "'")
#XXX if v['status'] == 'OK':
if 'document' in v:
self.delete_surrounding_text(-c, len(s))
self.delete_surrounding_text(-c, slen)
s = v["document"]["string"]
......@@ -271,7 +354,7 @@ class EngineBraille(IBus.Engine):
s = s.replace("<m:", "<")
s = s.replace("</m:", "</")
debug(2, "text was %s" % s)
debug(2, "text was '%s'" % s)
while True:
i = s.find("<span")
if i == -1:
......@@ -294,6 +377,9 @@ class EngineBraille(IBus.Engine):
s = s.strip()
s = s.rstrip()
if url == "starofficeToMathMLToBraille.json":
s = chr(0x2800) + to_brf(s)
c = len(s)
#c = 2
......@@ -313,13 +399,12 @@ class EngineBraille(IBus.Engine):
self.__process_dot_key(keysym - XK_braille_dot_1 + 1, is_press)
return True
if self.enabled and scancode in self.key_map:
if self.PC_enabled and scancode in self.key_map:
dot = self.key_map[scancode]
self.__process_dot_key(dot, is_press)
return True
if self.contracted:
self.__commit()
self.__commit()
# don't eat
return False
......@@ -381,12 +466,13 @@ class EngineBraille(IBus.Engine):
# Not connected
return
if self.enabled:
if self.uncontraction or self.math:
self.brlapi_connection.acceptKeyRanges([(brlapi.KEY_TYPE_CMD|brlapi.KEY_CMD_PASSDOTS, brlapi.KEY_TYPE_CMD|brlapi.KEY_CMD_PASSDOTS|brlapi.KEY_CMD_ARG_MASK)])
else:
self.brlapi_connection.ignoreAllKeys()
def __process_dot_key(self, dot, is_press):
"""
A braille key was pressed or released
......@@ -412,6 +498,7 @@ class EngineBraille(IBus.Engine):
"""
A braille pattern was committed
"""
# TODO: support half-layouts
extra = pattern & (dot9_mask | dot10_mask)
if extra == dot9_mask:
# with space key
......@@ -435,18 +522,20 @@ class EngineBraille(IBus.Engine):
self.__commit()
# And commit the separator
self.commit_text(IBus.Text.new_from_string(separators[char]))
elif self.math:
# For sighted users, show characters instead of braille
# patterns for a-z
self.commit_text(IBus.Text.new_from_string(to_brf(char)))
elif not self.uncontraction:
# Convert character immediately
self.__process_word(from_brf(char))
else:
if not self.math and char in brf:
# For sighted users, show characters instead of braille
# patterns for a-z
# TODO: should perhaps do this also in maths mode, and convert
# to pure braille before passing to natbraille?
# But then we can't know whether the content is braillemath or starmath
char = brf[char]
self.preedit += char
# Keep it in preedit for now
self.preedit += to_brf(char)
self.contracted = True
debug(4, "preedit now " + self.preedit)
self.update_preedit_text_with_mode(IBus.Text.new_from_string(self.preedit.lower()), len(self.preedit), True, 1)
# But show it as brf for now too
self.update_preedit_text_with_mode(IBus.Text.new_from_string(self.preedit), len(self.preedit), True, 1)
def __commit(self):
"""
......@@ -458,10 +547,11 @@ class EngineBraille(IBus.Engine):
self.preedit = ""
debug(3, "committing " + word)
self.update_preedit_text_with_mode(IBus.Text.new_from_string(""), 0, False, 0)
if self.contracted and not self.math:
self.__process_word(word)
if self.math:
# Prepend a braille blank to make sure we know it is braille for converting to starmath
self.commit_text(IBus.Text.new_from_string(chr(0x2800)+to_brf(word)))
else:
self.commit_text(IBus.Text.new_from_string(word))
self.__process_word(from_brf(word))
self.contracted = False
def __process_word(self, word):
......@@ -469,7 +559,11 @@ class EngineBraille(IBus.Engine):
A braille word should be untranscribed and emitted
"""
debug(2, "running on '" + word + "'")
word = louis.backTranslate(louis_tables, word)[0]
if self.contracted:
debug(2, "with contration")
word = louis.backTranslate(contracted_louis_tables, word)[0]
else:
word = louis.backTranslate(literal_louis_tables, word)[0]
debug(2, "got '" + str(word) + "'")
self.commit_text(IBus.Text.new_from_string(word))
......