diff --git a/product/Formulator/Widget.py b/product/Formulator/Widget.py
index 46478b3ce65f18cc1cb3b85fcf633bfc9ea65bfd..8c8a11c7aa3c6bae4c04827fb40b33fa5a39b076 100644
--- a/product/Formulator/Widget.py
+++ b/product/Formulator/Widget.py
@@ -27,21 +27,24 @@ NSMAP = {
 EForm = ElementMaker(namespace=FORM_URI, nsmap=NSMAP)
 
 RE_OOO_ESCAPE = re.compile(r'([\n\t])?([^\n\t]*)')
-def ooo_escape(match_object):
+class OOoEscaper:
   """Replacement function to use inside re.sub expression.
   This function replace \t by <text:tab/>
                         \n by <text:line-break/>
-  - parent_node is a global variable used to carry new nodes.
+  The parent node is passed to the constructor.
   """
-  match_value = match_object.group(1)
-  if match_value is None:
-    parent_node.text = match_object.group(2)
-  elif match_value == '\n':
-    line_break = SubElement(parent_node, '{%s}%s' % (TEXT_URI, 'line-break'))
-    line_break.tail = match_object.group(2)
-  elif match_value == '\t':
-    line_break = SubElement(parent_node, '{%s}%s' % (TEXT_URI, 'tab'))
-    line_break.tail = match_object.group(2)
+  def __init__(self, parent_node):
+    self.parent_node = parent_node
+  def __call__(self, match_object):
+    match_value = match_object.group(1)
+    if match_value is None:
+      self.parent_node.text = match_object.group(2)
+    elif match_value == '\n':
+      line_break = SubElement(self.parent_node, '{%s}%s' % (TEXT_URI, 'line-break'))
+      line_break.tail = match_object.group(2)
+    elif match_value == '\t':
+      line_break = SubElement(self.parent_node, '{%s}%s' % (TEXT_URI, 'tab'))
+      line_break.tail = match_object.group(2)
 
 class Widget:
   """A field widget that knows how to display itself as HTML.
@@ -260,9 +263,7 @@ class Widget:
     draw_node.append(text_p_node)
     draw_frame_node.append(draw_node)
 
-    global parent_node
-    parent_node = text_span_node
-    RE_OOO_ESCAPE.sub(ooo_escape, value)
+    RE_OOO_ESCAPE.sub(OOoEscaper(text_span_node), value)
     if as_string:
       return etree.tostring(draw_frame_node)
     return draw_frame_node
@@ -552,9 +553,7 @@ class TextAreaWidget(Widget):
             value = value.decode('utf-8')
         text_node = Element('{%s}%s' % (TEXT_URI, local_name), nsmap=NSMAP)
 
-        global parent_node
-        parent_node = text_node
-        RE_OOO_ESCAPE.sub(ooo_escape, value)
+        RE_OOO_ESCAPE.sub(OOoEscaper(text_node), value)
         text_node.attrib.update(attr_dict)
         if as_string:
             return etree.tostring(text_node)
@@ -786,6 +785,41 @@ class SingleItemsWidget(ItemsWidget):
 
   render_pdf = render_view
 
+  def render_odt_view(self, field, value, as_string, ooo_builder, REQUEST,
+      render_prefix, attr_dict, local_name):
+
+    items = field.get_value('items',
+                            REQUEST=REQUEST,
+                            cell=getattr(REQUEST, 'cell', None))
+    # XXX this code can be factorized
+    d = {}
+    for item in items:
+      try:
+        item_text, item_value = item
+      except ValueError:
+        item_text = item
+        item_value = item
+      d[item_value] = item_text
+
+    if value is None:
+      value = ''
+
+    value = d.get(value, '??? (%s)' % value)
+
+    if attr_dict is None:
+      attr_dict = {}
+    if isinstance(value, str):
+      #required by lxml
+      value = value.decode('utf-8')
+    text_node = Element('{%s}%s' % (TEXT_URI, local_name), nsmap=NSMAP)
+
+    RE_OOO_ESCAPE.sub(OOoEscaper(text_node), value)
+    text_node.attrib.update(attr_dict)
+    if as_string:
+      return etree.tostring(text_node)
+    return text_node
+
+
 class MultiItemsWidget(ItemsWidget):
   """A widget with a number of items that has multiple selectable
   items.
@@ -931,6 +965,46 @@ class MultiItemsWidget(ItemsWidget):
     return Widget.render_odg(self, field, value, as_string, ooo_builder,
                              REQUEST, render_prefix, attr_dict, local_name)
 
+  def render_odt_view(self, field, value, as_string, ooo_builder, REQUEST,
+      render_prefix, attr_dict, local_name):
+
+    items = field.get_value('items',
+                            REQUEST=REQUEST,
+                            cell=getattr(REQUEST, 'cell', None))
+    d = {}
+    for item in items:
+      try:
+        item_text, item_value = item
+      except ValueError:
+        item_text = item
+        item_value = item
+      d[item_value] = item_text
+
+    if value is None:
+      value = ['']
+    elif isinstance(value, basestring):
+      value = [value]
+
+    result = []
+    for e in value:
+      result.append(d.get(e, '??? (%s)' % e))
+      
+    value = '\n'.join(result)
+
+    if attr_dict is None:
+      attr_dict = {}
+    if isinstance(value, str):
+      #required by lxml
+      value = value.decode('utf-8')
+    text_node = Element('{%s}%s' % (TEXT_URI, local_name), nsmap=NSMAP)
+
+    RE_OOO_ESCAPE.sub(OOoEscaper(text_node), value)
+    text_node.attrib.update(attr_dict)
+    if as_string:
+      return etree.tostring(text_node)
+    return text_node
+
+
 class ListWidget(SingleItemsWidget):
     """List widget.
     """
@@ -968,26 +1042,6 @@ class ListWidget(SingleItemsWidget):
         return render_element('option', contents=text, value=value,
                               selected=None, extra=extra_item)
 
-    def render_odt_view(self, field, value, as_string, ooo_builder, REQUEST,
-                        render_prefix, attr_dict, local_name):
-        if attr_dict is None:
-          attr_dict = {}
-        if value is None:
-          value = []
-        if isinstance(value, (list, tuple)):
-          value = '\n'.join(value)
-        if isinstance(value, str):
-          #required by lxml
-          value = value.decode('utf-8')
-        text_node = Element('{%s}%s' % (TEXT_URI, local_name), nsmap=NSMAP)
-        global parent_node
-        parent_node = text_node
-        RE_OOO_ESCAPE.sub(ooo_escape, value)
-        text_node.attrib.update(attr_dict)
-        if as_string:
-            return etree.tostring(text_node)
-        return text_node
-
 ListWidgetInstance = ListWidget()
 
 class MultiListWidget(MultiItemsWidget):