Index: configure.in
===================================================================
--- configure.in	(revision 3445)
+++ configure.in	(working copy)
@@ -130,6 +130,16 @@
     AM_CHECK_PYMOD(brlapi,,[brlapi_available="yes"],[brlapi_available="no"])
 fi
 
+AC_ARG_WITH(liblouis,
+        AC_HELP_STRING([--with-liblouis],[enable the use of liblouis]),
+	[case "${withval}" in
+	yes) WITH_LOUIS=yes ;;
+	no) WITH_LOUIS=no ;;
+	*) AC_MSG_ERROR(bad value ${withval} for --with-liblouis) ;;
+	esac],
+	[WITH_LOUIS=no]) dnl Default value
+AM_CONDITIONAL(WITH_LOUIS, test x$WITH_LOUIS = "xyes")
+
 AC_SUBST(orca_LIBS)
 AC_SUBST(orca_CFLAGS)
 
@@ -146,6 +156,7 @@
 icons/Makefile
 src/Makefile
 src/brl/Makefile
+src/louis/Makefile
 src/orca/Makefile
 src/orca/scripts/Makefile
 src/orca/orca
Index: src/orca/orca-setup.glade
===================================================================
--- src/orca/orca-setup.glade	(revision 3445)
+++ src/orca/orca-setup.glade	(working copy)
@@ -1252,8 +1252,8 @@
 				  <property name="wrap">False</property>
 				  <property name="adjustment">10 1 9999 1 10 10</property>
 				  <accessibility>
+				    <atkrelation target="speakProgressBarLabel" type="labelled-by"/>
 				    <atkrelation target="speakProgressBarUnitsLabel" type="labelled-by"/>
-				    <atkrelation target="speakProgressBarLabel" type="labelled-by"/>
 				  </accessibility>
 				  <signal name="value_changed" handler="speakProgressBarValueChanged" last_modification_time="Thu, 14 Jun 2007 15:09:00 GMT"/>
 				</widget>
@@ -1524,6 +1524,144 @@
 		  </child>
 
 		  <child>
+		    <widget class="GtkFrame" id="contractedBrailleFrame">
+		      <property name="label_xalign">0</property>
+		      <property name="label_yalign">0.5</property>
+		      <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		      <child>
+			<widget class="GtkAlignment" id="alignment87">
+			  <property name="visible">True</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xscale">1</property>
+			  <property name="yscale">1</property>
+			  <property name="top_padding">0</property>
+			  <property name="bottom_padding">0</property>
+			  <property name="left_padding">12</property>
+			  <property name="right_padding">0</property>
+
+			  <child>
+			    <widget class="GtkVBox" id="vbox34">
+			      <property name="border_width">3</property>
+			      <property name="visible">True</property>
+			      <property name="homogeneous">False</property>
+			      <property name="spacing">0</property>
+
+			      <child>
+				<widget class="GtkCheckButton" id="checkbutton1">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">_Enable Contracted Braille</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">False</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				  <signal name="toggled" handler="contractedBrailleToggled" last_modification_time="Fri, 11 Jan 2008 19:07:29 GMT"/>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkHBox" id="contractionTablesHBox">
+				  <property name="visible">True</property>
+				  <property name="sensitive">False</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">3</property>
+
+				  <child>
+				    <widget class="GtkLabel" id="contractionTableLabel">
+				      <property name="visible">True</property>
+				      <property name="label" translatable="yes">Contraction _Table:</property>
+				      <property name="use_underline">True</property>
+				      <property name="use_markup">False</property>
+				      <property name="justify">GTK_JUSTIFY_LEFT</property>
+				      <property name="wrap">False</property>
+				      <property name="selectable">False</property>
+				      <property name="xalign">0.5</property>
+				      <property name="yalign">0.5</property>
+				      <property name="xpad">0</property>
+				      <property name="ypad">0</property>
+				      <property name="mnemonic_widget">contractionTableCombo</property>
+				      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+				      <property name="width_chars">-1</property>
+				      <property name="single_line_mode">False</property>
+				      <property name="angle">0</property>
+				      <accessibility>
+					<atkrelation target="contractionTableCombo" type="label-for"/>
+				      </accessibility>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkComboBox" id="contractionTableCombo">
+				      <property name="visible">True</property>
+				      <property name="add_tearoffs">False</property>
+				      <property name="focus_on_click">True</property>
+				      <accessibility>
+					<atkrelation target="contractionTableLabel" type="labelled-by"/>
+				      </accessibility>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">True</property>
+				      <property name="fill">True</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">True</property>
+				  <property name="fill">True</property>
+				</packing>
+			      </child>
+			    </widget>
+			  </child>
+			</widget>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label48">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">&lt;b&gt;Contracted Braille&lt;/b&gt;</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">True</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="type">label_item</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
 		    <widget class="GtkFrame" id="frame7">
 		      <property name="visible">True</property>
 		      <property name="label_xalign">0</property>
@@ -3366,8 +3504,8 @@
 							  <property name="wrap">False</property>
 							  <property name="adjustment">1 24 256 1 10 10</property>
 							  <accessibility>
+							    <atkrelation target="magCursorSizeUnitsLabel" type="labelled-by"/>
 							    <atkrelation target="magCursorSizeLabel" type="labelled-by"/>
-							    <atkrelation target="magCursorSizeUnitsLabel" type="labelled-by"/>
 							  </accessibility>
 							  <signal name="value_changed" handler="magCursorSizeValueChanged" last_modification_time="Wed, 03 May 2006 15:31:48 GMT"/>
 							</widget>
@@ -3719,8 +3857,8 @@
 							  <property name="wrap">False</property>
 							  <property name="adjustment">1 1 256 1 10 10</property>
 							  <accessibility>
+							    <atkrelation target="magCrossHairSizeUnitsLabel" type="labelled-by"/>
 							    <atkrelation target="magCrossHairSizeLabel" type="labelled-by"/>
-							    <atkrelation target="magCrossHairSizeUnitsLabel" type="labelled-by"/>
 							  </accessibility>
 							  <signal name="value_changed" handler="magCrossHairSizeValueChanged" last_modification_time="Wed, 03 May 2006 15:39:23 GMT"/>
 							</widget>
@@ -4157,8 +4295,8 @@
 						  <property name="wrap">False</property>
 						  <property name="adjustment">0 0 100 1 10 10</property>
 						  <accessibility>
+						    <atkrelation target="magEdgeMarginLabel" type="labelled-by"/>
 						    <atkrelation target="magEdgeMarginUnitsLabel" type="labelled-by"/>
-						    <atkrelation target="magEdgeMarginLabel" type="labelled-by"/>
 						  </accessibility>
 						  <signal name="value_changed" handler="magEdgeMarginValueChanged" last_modification_time="Thu, 06 Dec 2007 22:57:50 GMT"/>
 						</widget>
Index: src/orca/orca_gui_prefs.py
===================================================================
--- src/orca/orca_gui_prefs.py	(revision 3445)
+++ src/orca/orca_gui_prefs.py	(working copy)
@@ -944,6 +944,10 @@
         self.prefsDict["enabledSpokenTextAttributes"] = spokenAttrStr
         self.prefsDict["enabledBrailledTextAttributes"] = brailledAttrStr
 
+    def contractedBrailleToggled(self, checkbox):
+        hbox = self.widgets.get_widget('contractionTablesHBox')
+        hbox.set_sensitive(checkbox.get_active())
+
     def textAttributeSpokenToggled(self, cell, path, model):
         """The user has toggled the state of one of the text attribute
         checkboxes to be spoken. Update our model to reflect this, then
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 3445)
+++ src/Makefile.am	(working copy)
@@ -1 +1,5 @@
+if WITH_LOUIS
+SUBDIRS = brl orca louis
+else
 SUBDIRS = brl orca
+endif
\ No newline at end of file
Index: src/louis/constants.py
===================================================================
--- src/louis/constants.py	(revision 0)
+++ src/louis/constants.py	(revision 0)
@@ -0,0 +1,67 @@
+# Liblouis Python bindings
+#
+# Copyright 2007-2008 Eitan Isaacson
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# Translators: These are the braille translation table names for different
+# languages. You could read about braille tables at:
+# http://en.wikipedia.org/wiki/Braille
+#
+TABLE_NAMES = {'Cz-Cz-g1': _('Czech Grade 1'),
+               'Es-Es-g1': _('Spanish Grade 1'),
+               'Fr-Ca-g2': _('Canada French Grade 2'),
+               'Fr-Fr-g2': _('France French Grade 2'),
+               'Lv-Lv-g1': _('Latvian Grade 1'),
+               'Nl-Nl-g1': _('Netherlands Dutch Grade 1'),
+               'No-No-g0': _('Norwegian Grade 0'),
+               'No-No-g1': _('Norwegian Grade 1'),
+               'No-No-g2': _('Norwegian Grade 2'),
+               'No-No-g3': _('Norwegian Grade 3'),
+               'Pl-Pl-g1': _('Polish Grade 1'),
+               'Pt-Pt-g1': _('Portuguese Grade 1'),
+               'Se-Se-g1': _('Swedish Grade 1'),
+               'ar-ar-g1': _('Arabic Grade 1'),
+               'cy-cy-g1': _('Welsh Grade 1'),
+               'cy-cy-g2': _('Welsh Grade 2'),
+               'de-de-g0': _('German Grade 0'),
+               'de-de-g1': _('German Grade 1'),
+               'de-de-g2': _('German Grade 2'),
+               'en-GB-g2': _('U.K. English Grade 2'),
+               'en-gb-g1': _('U.K. English Grade 1'),
+               'en-us-g1': _('U.S. English Grade 1'),
+               'en-us-g2': _('U.S. English Grade 2'),
+               'fr-ca-g1': _('Canada French Grade 1'),
+               'fr-fr-g1': _('France French 1'),
+               'gr-gr-g1': _('Greek Grade 1'),
+               'hi-in-g1': _('Hindi Grade 1'),
+               'it-it-g1': _('Italian Grade 1'),
+               'nl-be-g1': _('Belgium Dutch Grade 1')}
+
+
+class TYPEFORM:
+   plain_text = 0
+   italic = 1
+   underline = 2
+   bold = 4
+   computer_braille = 8
+
+class MODE:
+   noContractions = 1
+   compbrlAtCursor = 2
+   dotsIO = 4
+   comp8Dots = 8
+   
Index: src/louis/__init__.py
===================================================================
--- src/louis/__init__.py	(revision 0)
+++ src/louis/__init__.py	(revision 0)
@@ -0,0 +1,7 @@
+"""Liblouis python bindings"""
+
+__copyright__ = "Copyright (c) 2007-2008 Eitan Isaacson"
+__license__   = "LGPL"
+
+from _louis import *
+from constants import *
Index: src/louis/Makefile.am
===================================================================
--- src/louis/Makefile.am	(revision 0)
+++ src/louis/Makefile.am	(revision 0)
@@ -0,0 +1,21 @@
+louis_LTLIBRARIES = _louis.la
+
+louisdir = $(pyexecdir)/orca/louis
+
+_louis_la_CFLAGS = \
+	$(louis_CFLAGS) \
+	$(PYTHON_INCLUDES)
+
+_louis_la_LDFLAGS = \
+	-module \
+	-avoid-version \
+	-llouis
+
+_louis_la_SOURCES = \
+	_louis.c
+
+louis_pythondir=$(louisdir)
+
+louis_python_PYTHON = \
+	__init__.py \
+	constants.py
\ No newline at end of file
Index: src/louis/_louis.c
===================================================================
--- src/louis/_louis.c	(revision 0)
+++ src/louis/_louis.c	(revision 0)
@@ -0,0 +1,221 @@
+/* Liblouis Python bindings
+ *
+ * Copyright 2007-2008 Eitan Isaacson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <Python.h>
+#include <liblouis.h>
+
+static PyObject *module;
+
+static PyObject *
+louis_version(PyObject *self)
+{
+		const char *version_string;
+		version_string = lou_version();
+		return Py_BuildValue("s", version_string);
+}
+
+
+char *
+pylist_to_string(PyObject *list)
+{
+		PyObject *list_joined, *sep;
+		char *rv;
+
+		sep = PyString_FromString(",");
+		list_joined = PyUnicode_Join(sep, list);
+		if (list_joined == NULL) 
+        {
+				/* Some list items were probably not strings */
+				Py_DECREF(sep);
+				return NULL;
+        }
+		rv = strdup(PyString_AsString(list_joined));
+
+		Py_DECREF(list_joined);
+		Py_DECREF(sep);
+
+		return rv;
+}
+
+char *
+pylist_to_typeform(PyObject *typeform_list, int len)
+{
+		char *typeform;
+		int i;
+		PyObject *l_item;
+		typeform = calloc(len, sizeof(char));
+		for (i=0; i < PySequence_Size(typeform_list); i++)
+		{
+				l_item = PySequence_Fast_GET_ITEM(typeform_list, i);
+				typeform[i] = (char)PyInt_AsLong(l_item);
+		}
+		return typeform;
+		
+}
+
+PyObject *
+intbuf_to_pylist(int *intbuf, int len)
+{
+		PyObject *pylist;
+		int i;
+
+		pylist = PyList_New(len);
+
+		for (i=0;i<len;i++)
+				PyList_SetItem(pylist, i, PyInt_FromLong((long)intbuf[i]));
+
+		return pylist;
+}
+
+static PyObject *
+louis_translateString(PyObject *self, PyObject *args, PyObject *kw)
+{
+        static char *kw_args[]={"tran_tables", "inbuf", 
+                                "typeform", "spacing", "mode", 0};
+		char *typeform = NULL, *trantab_joined, *spacing = NULL;
+		widechar *outbuf;
+		int inlen, outlen, mode = 0;
+		PyObject *trantab_list, *out, *typeform_list = NULL;
+		Py_UNICODE *u_inbuf;
+		int rv;
+
+		if (!PyArg_ParseTupleAndKeywords(args, kw,
+                                         "Ou#|OOi:translateString", kw_args,
+                                         &trantab_list, &u_inbuf, &inlen,
+                                         &typeform_list, &spacing, &mode))
+		{
+				return NULL;
+        }
+        
+		trantab_joined = pylist_to_string(trantab_list);
+
+        if (trantab_joined == NULL) 
+        {
+               PyErr_SetString(
+                       PyExc_TypeError,
+                       "translateString() argument 1 needs to be a list of strings"); 
+               return NULL;
+        }
+
+		if (PySequence_Size(typeform_list) > 0) 
+				typeform = pylist_to_typeform(typeform_list, inlen);
+
+        outlen = inlen*2;
+		outbuf = calloc(outlen, sizeof(widechar));
+
+		rv = lou_translateString(trantab_joined, (widechar *)u_inbuf, 
+                                 &inlen, outbuf, &outlen, typeform, 
+                                 spacing, mode);
+
+        out = PyUnicode_FromUnicode((Py_UNICODE *)outbuf, outlen);
+
+		if (typeform != NULL)
+				free(typeform);
+		free(trantab_joined);
+        free(outbuf);
+        return out;
+
+}
+
+static PyObject *
+louis_translate(PyObject *self, PyObject *args, PyObject *kw)
+{
+        static char *kw_args[]={"tran_tables", "inbuf", 
+                                "typeform", "cursorPos","mode", 0};
+		char *typeform = NULL, *trantab_joined, *spacing = NULL;
+		widechar *outbuf;
+		int inlen, outlen, mode = 0, cursorPos = 0;
+		int rv, *outputPos, *inputPos;
+		PyObject *trantab_list, *out, *typeform_list = NULL, *outputPos_list,
+				*inputPos_list;
+		Py_UNICODE *u_inbuf;
+
+		if (!PyArg_ParseTupleAndKeywords(args, kw,
+                                         "Ou#|Oii:translate", kw_args,
+                                         &trantab_list, &u_inbuf, &inlen,
+                                         &typeform_list, &cursorPos,
+										 &mode))
+		{
+				return NULL;
+        }
+        
+		trantab_joined = pylist_to_string(trantab_list);
+
+        if (trantab_joined == NULL) 
+        {
+               PyErr_SetString(
+                       PyExc_TypeError,
+                       "translateString() argument 1 needs to be a list of strings"); 
+               return NULL;
+        }
+
+		if (PySequence_Size(typeform_list) > 0) 
+				typeform = pylist_to_typeform(typeform_list, inlen);
+
+		inputPos = calloc(inlen, sizeof(int));
+
+        outlen = inlen*2;
+		outbuf = calloc(outlen, sizeof(widechar));
+		outputPos = calloc(outlen, sizeof(int));
+
+		rv = lou_translate(trantab_joined, (widechar *)u_inbuf, 
+                           &inlen, outbuf, &outlen, typeform, spacing, 
+                           outputPos, inputPos, &cursorPos, mode);
+
+        out = PyUnicode_FromUnicode((Py_UNICODE *)outbuf, outlen);
+		inputPos_list = intbuf_to_pylist(inputPos, inlen);
+		outputPos_list = intbuf_to_pylist(outputPos, outlen);
+
+		if (typeform != NULL) 
+				free(typeform);
+		free(trantab_joined);
+        free(outbuf);
+        free(outputPos);
+        free(inputPos);
+
+        Py_INCREF(outputPos_list);
+        Py_INCREF(inputPos_list);
+        Py_INCREF(out);
+
+        PyErr_Clear();
+
+        return Py_BuildValue("(NNNi)", out, inputPos_list, 
+							 outputPos_list, cursorPos);
+
+}
+
+static PyMethodDef louis_methods[] = {
+		{"version", 
+         (PyCFunction) louis_version, METH_VARARGS},
+		{"translateString", 
+         (PyCFunction) louis_translateString, METH_KEYWORDS},
+		{"translate", 
+         (PyCFunction) louis_translate, METH_KEYWORDS},
+		{NULL, NULL}
+};
+
+PyMODINIT_FUNC 
+init_louis (void) {
+        module = Py_InitModule ("_louis", louis_methods);
+}
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 3445)
+++ po/POTFILES.in	(working copy)
@@ -56,3 +56,4 @@
 src/orca/speechserver.py
 src/orca/speech.py
 src/orca/where_am_I.py
+src/orca/louis/constants.py
