orca r4269 - in branches/phase2: . src/orca src/orca/braille src/orca/scripts src/orca/speech



Author: wwalker
Date: Mon Sep 29 23:56:21 2008
New Revision: 4269
URL: http://svn.gnome.org/viewvc/orca?rev=4269&view=rev

Log:
Reorg speech and braille into packages.  Also put default script in 
scripts module.


Added:
   branches/phase2/src/orca/braille/   (props changed)
   branches/phase2/src/orca/braille/Makefile.am
   branches/phase2/src/orca/braille/__init__.py   (contents, props changed)
   branches/phase2/src/orca/braille/braille_monitor.py   (contents, props changed)
   branches/phase2/src/orca/braille/brltty.py   (contents, props changed)
   branches/phase2/src/orca/scripts/default.py   (contents, props changed)
   branches/phase2/src/orca/speech/   (props changed)
   branches/phase2/src/orca/speech/Makefile.am
   branches/phase2/src/orca/speech/__init__.py   (contents, props changed)
   branches/phase2/src/orca/speech/acss.py   (contents, props changed)
   branches/phase2/src/orca/speech/character_names.py   (contents, props changed)
   branches/phase2/src/orca/speech/key_names.py   (contents, props changed)
   branches/phase2/src/orca/speech/phonetic_names.py   (contents, props changed)
Removed:
   branches/phase2/src/orca/acss.py
   branches/phase2/src/orca/braille.py
   branches/phase2/src/orca/braille_monitor.py
   branches/phase2/src/orca/character_names.py
   branches/phase2/src/orca/default.py
   branches/phase2/src/orca/key_names.py
   branches/phase2/src/orca/phonetic_names.py
Modified:
   branches/phase2/configure.in
   branches/phase2/src/orca/Makefile.am
   branches/phase2/src/orca/script_manager.py
   branches/phase2/src/orca/scripts/Makefile.am
   branches/phase2/src/orca/scripts/__init__.py   (props changed)
   branches/phase2/src/orca/settings.py

Modified: branches/phase2/configure.in
==============================================================================
--- branches/phase2/configure.in	(original)
+++ branches/phase2/configure.in	Mon Sep 29 23:56:21 2008
@@ -159,6 +159,7 @@
 src/louis/Makefile
 src/louis/constants.py
 src/orca/Makefile
+src/orca/braille/Makefile
 src/orca/plugins/Makefile
 src/orca/plugins/bookmarks/Makefile
 src/orca/plugins/debug_actions/Makefile
@@ -169,6 +170,7 @@
 src/orca/scripts/Makefile
 src/orca/scripts/applications/Makefile
 src/orca/scripts/toolkits/Makefile
+src/orca/speech/Makefile
 src/orca/orca
 src/orca/orca_i18n.py
 src/orca/platform.py

Modified: branches/phase2/src/orca/Makefile.am
==============================================================================
--- branches/phase2/src/orca/Makefile.am	(original)
+++ branches/phase2/src/orca/Makefile.am	Mon Sep 29 23:56:21 2008
@@ -7,17 +7,10 @@
 
 orca_python_PYTHON = \
 	__init__.py \
-	acss.py \
-	braille_monitor.py \
-	braille.py \
-	character_names.py \
-	default.py \
 	input_binding.py \
 	input_event.py \
-	key_names.py \
 	orca_i18n.py \
 	orca.py \
-	phonetic_names.py \
 	platform.py \
 	plugin.py \
 	rolenames.py \
@@ -29,4 +22,4 @@
 
 orca_pythondir=$(pyexecdir)/orca
 
-SUBDIRS = plugins scripts
+SUBDIRS = braille plugins scripts speech

Added: branches/phase2/src/orca/braille/Makefile.am
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/braille/Makefile.am	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,8 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	braille_monitor.py \
+	brltty.py
+
+orca_pythondir=$(pyexecdir)/orca/braille

Added: branches/phase2/src/orca/braille/__init__.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/braille/__init__.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,5 @@
+"""Modules for handling braille."""
+from brltty import init
+from brltty import shutdown
+from brltty import setKeys
+from brltty import writeText

Added: branches/phase2/src/orca/braille/braille_monitor.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/braille/braille_monitor.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,201 @@
+# Copyright 2006-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Provides a graphical braille display at the top of the screen.
+This is mainly for debugging and for demonstrations."""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import logging
+log = logging.getLogger("orca.braille_monitor")
+
+import gtk
+
+# Attribute/Selection mask strings:
+#
+DOT_7 =   '\x40' # 01000000
+DOT_8 =   '\x80' # 10000000
+DOTS_78 = '\xc0' # 11000000
+    
+# Markup strings:
+#
+NORMAL = " size='xx-large'"
+
+CURSOR_CELL_EMPTY =   " background='black'" \
+                    + " weight='ultrabold'" \
+                    + " style='italic'"
+
+CURSOR_CELL =   " background='white'" \
+              + " weight='ultrabold'" \
+              + " style='italic'" \
+
+ATTRIBUTE_7 = " underline='low'"
+
+ATTRIBUTE_8 = " underline='error'"
+
+ATTRIBUTE_78 = " underline='double'"
+
+# We subclass gtk.Window, which has a lot of public methods.  We'll
+# disable the pylint message for that.
+#
+# pylint: disable-msg=R0904
+
+class BrailleMonitor(gtk.Window):
+    """Displays a GUI braille monitor that mirrors what is being
+    shown on the braille display.
+    """
+    def __init__(self, numCells=32, cellWidth=25, cellHeight=50):
+        """Create a new BrlMon.
+
+        Arguments:
+        - numCells: how many braille cells to make
+        - cellWidth: width of each cell in pixels
+        - cellHeight: height of each cell in pixels
+        """
+        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
+        self.set_title("Braille Monitor")
+        self.set_default_size(cellWidth * numCells, cellHeight)
+        hbox = gtk.HBox(True)
+        self.add(hbox)
+        self.cellFrames = []
+        self.cellLabels = []
+        i = 0
+        while (i < numCells):
+            frame = gtk.Frame()
+            frame.set_shadow_type(gtk.SHADOW_OUT)
+            label = gtk.Label(" ")
+            label.set_use_markup(True)
+            frame.add(label)
+            hbox.add(frame)
+            self.cellFrames.append(frame)
+            self.cellLabels.append(label)
+            i += 1
+
+        # This prevents it from getting focus.
+        #
+        self.set_property("accept-focus", False)
+        self.connect_after("check-resize", self.onResize)
+
+    def onResize(self, obj):
+        """Tell the window to be a dock and set its struts, which I
+        think means to attempt to glue it somewhere on the display.
+        """
+        # We know what we are doing here, so tell pylint not to flag
+        # the self.window method calls as errors (e.g., Class 'window' 
+        # has no 'get_size' member).  The disable-msg is localized to
+        # just this method.
+        #
+        # pylint: disable-msg=E1101
+        #
+        screen_width = gtk.gdk.screen_width()
+        [window_width, window_height] = self.window.get_size()
+        if window_width < screen_width:
+            x = (screen_width - window_width) / 2
+        else:
+            x = 0
+
+        self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
+        self.window.property_change(
+                gtk.gdk.atom_intern("_NET_WM_STRUT_PARTIAL", False),
+                gtk.gdk.atom_intern("CARDINAL", False), 32,
+                gtk.gdk.PROP_MODE_REPLACE,
+                [0,                     # LEFT
+                 0,                     # RIGHT
+                 window_height,         # TOP
+                 0,                     # BOTTOM
+                 0,                     # LEFT_START
+                 0,                     # LEFT_END
+                 0,                     # RIGHT_START
+                 0,                     # RIGHT_END
+                 0,                     # TOP_START
+                 screen_width - 1,      # TOP_END
+                 0,                     # BOTTOM_START
+                 0])                    # BOTTOM_END
+
+        self.move(x, 0)
+
+    def writeText(self, text, attributeMask, cursorCell):
+        """Display the given text and highlight the given
+        cursor cell.  A cursorCell of 0 means no cell has
+        the cursor.
+
+        Arguments:
+        - cursorCell: 1-based index of cell with cursor
+        - attributeMask: attributes to apply to the text
+        - text: len must be <= num cells.
+        """
+        # Fill out the cells from the string.
+        #
+        try:
+            text = text.decode("UTF-8")
+        except:
+            text = ""
+
+        for i in range(0, len(text)):
+            # Handle special chars so they are not interpreted by pango.
+            #
+            if text[i] == "<":
+                char = "&lt;"
+            elif text[i] == "&":
+                char = "&amp;"
+            elif text[i] == "\t":
+                char = "$t"
+            else:
+                char = text[i]
+
+            markup = NORMAL
+            if i == (cursorCell - 1):
+                if text[i] == " ":
+                    markup += CURSOR_CELL_EMPTY
+                else:
+                    markup += CURSOR_CELL
+                self.cellFrames[i].set_shadow_type(
+                    gtk.SHADOW_IN)
+            else:
+                self.cellFrames[i].set_shadow_type(
+                    gtk.SHADOW_OUT)
+
+            if attributeMask:
+                if (attributeMask[i] == DOTS_78):
+                    markup += ATTRIBUTE_78
+                elif (attributeMask[i] == DOT_7):
+                    markup += ATTRIBUTE_7
+                elif (attributeMask[i] == DOT_8):
+                    markup += ATTRIBUTE_8
+
+            self.cellLabels[i].set_markup(
+                "<span" + markup + ">%s</span>" % char)
+
+        # Pad the rest
+        #
+        for i in range(len(text), len(self.cellFrames)):
+            self.cellLabels[i].set_text(" ")
+            self.cellFrames[i].set_shadow_type(
+                gtk.SHADOW_OUT)
+
+if __name__ == "__main__":
+    logging.basicConfig(format="%(name)s %(message)s")
+    log.setLevel(logging.DEBUG)
+
+    monitor = BrailleMonitor()
+    monitor.realize()
+    monitor.show_all()
+    mask = "  " + DOT_7 + DOT_8 + DOTS_78 + "           "
+    monitor.writeText("Just a test: <&	", mask, 5)
+    gtk.main()

Added: branches/phase2/src/orca/braille/brltty.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/braille/brltty.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,322 @@
+# Copyright 2005-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+# Allow globals to be used in this module.
+#
+# pylint: disable-msg=W0603
+
+# TODO: make new module for braille regions.  This module is now
+# just for I/O with the braille display.
+
+# TODO: find a way to output the attributes.  Perhaps an extra line
+# under the VISIBLE line where we use - ~ and =.
+
+"""Used to get input events from the braille display and to paint raw
+strings to the braille display.
+"""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+# If true, show the braille monitor on the display.
+#
+enableBrailleMonitor = False
+
+# The tty where BrlTTY will be used.
+#
+tty = 7
+
+import logging
+log = logging.getLogger('orca.braille')
+info_log = logging.getLogger('braille')
+
+import brlapi
+import gobject
+
+from orca.orca_i18n import _ # for gettext support
+
+_brlAPI = None
+_brlAPIRunning = False
+_brlAPISourceId = 0
+
+# If True, this module has been initialized.
+#
+_initialized = False
+
+# The braille monitor
+#
+monitor = None
+
+# Common names for most used BrlTTY commands, to be shown in the GUI.
+#
+command_name = {}
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls to the left.
+#
+command_name[brlapi.KEY_CMD_FWINLT]   = _("Line Left")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls to the right.
+#
+command_name[brlapi.KEY_CMD_FWINRT]   = _("Line Right")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls up.
+#
+command_name[brlapi.KEY_CMD_LNUP]     = _("Line Up")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls down.
+#
+command_name[brlapi.KEY_CMD_LNDN]     = _("Line Down")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls to the top left of the
+# window.
+#
+command_name[brlapi.KEY_CMD_TOP_LEFT] = _("Top Left")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls to the bottom right of
+# the window.
+#
+command_name[brlapi.KEY_CMD_BOT_LEFT] = _("Bottom Right")
+
+# Translators: this is a command for a button on a refreshable braille
+# display (an external hardware device used by people who are blind).
+# When pressing the button, the display scrolls to position containing
+# the cursor.
+#
+command_name[brlapi.KEY_CMD_HOME]     = _("Cursor Position")
+
+# The size of the physical display (width, height).  The coordinate system of
+# the display is set such that the upper left is (0,0), x values increase from
+# left to right, and y values increase from top to bottom.
+#
+# For the purposes of testing w/o a braille display, we'll set the display
+# size to width=32 and height=1.
+#
+# Only a height of 1 is support at this time.
+#
+_displaySize = [32, 1]
+
+# The callback to call on a BrlTTY input event.  This is passed to
+# the init method.
+#
+_callback = None
+
+def writeText(text, attributeMask, cursorCell):
+    """Writes the given text with the given attribute mask.  Also
+    puts the cursor at the given 1-based cursorCell (0 means no cursor).
+    """
+    global monitor
+
+    logLine = "     VISIBLE:  '%s', cursor=%d" % (text, cursorCell)
+    log.info(logLine.encode("UTF-8"))
+    info_log.info(logLine.encode("UTF-8"))
+
+    if _brlAPIRunning:
+        writeStruct = brlapi.WriteStruct()
+        writeStruct.regionBegin = 1
+        writeStruct.regionSize = len(text)
+        while writeStruct.regionSize < _displaySize[0]:
+            text += " "
+            if attributeMask:
+                attributeMask += '\x00'
+            writeStruct.regionSize += 1
+        writeStruct.text = text
+        writeStruct.cursor = cursorCell
+        if attributeMask:
+            writeStruct.attrOr = attributeMask
+        _brlAPI.write(writeStruct)
+
+    if enableBrailleMonitor:
+        if not monitor:
+            import braille_monitor
+            monitor = braille_monitor.BrailleMonitor(_displaySize[0])
+            monitor.show_all()
+        monitor.writeText(text, attributeMask, cursorCell)
+    elif monitor:
+        monitor.destroy()
+        monitor = None
+
+def _processBrailleEvent(event):
+    """Handles BrlTTY events.  This passes commands on to the callback
+    for processing.
+
+    Arguments:
+    - event: the BrlAPI input event (expanded keycode)
+    """
+    log.info("input event: %s" % event)
+    consumed = False
+    if _callback:
+        try:
+            # Like key event handlers, a return value of True means
+            # the command was consumed.
+            #
+            consumed = _callback(event)
+        except:
+            log.exception("handled exception from braille callback:")
+            consumed = False
+    return consumed
+
+def _brlAPIKeyReader(source, condition):
+    """Method to read a key from the BrlAPI bindings.  This is a
+    gobject IO watch handler.
+    """
+    key = _brlAPI.readKey(False)
+    if key:
+        _processBrailleEvent(_brlAPI.expandKeyCode(key))
+    return _brlAPIRunning
+
+def setKeys(keys):
+    """Tell BrlTTY what to send and not send us via the readKey
+    method.  This only works with BrlTTY v3.8 and better.
+
+    Arguments:
+    -keys: a list of BrlAPI commands.
+    """
+    if not _brlAPIRunning:
+        return
+
+    try:
+        # First, start by ignoring everything.
+        #
+        _brlAPI.ignoreKeys(brlapi.rangeType_all, [0])
+
+        # Finally, enable the commands we care about.
+        #
+        keySet = []
+        for key in keys:
+            keySet.append(brlapi.KEY_TYPE_CMD | key)
+        _brlAPI.acceptKeys(brlapi.rangeType_command, keySet)
+        log.debug("set braille keys to %s", keySet)
+    except:
+        log.exception("handled exception while setting up braille keys:")
+
+def init(callback=None):
+    """Initializes the braille module, connecting to the BrlTTY driver.
+
+    Arguments:
+    - callback: the method to call with a BrlTTY input event.
+    Returns True if the initialization procedure was run or False if this
+    module has already been initialized.
+    """
+
+    global _initialized
+    global _displaySize
+    global _callback
+
+    global _brlAPI
+    global _brlAPIRunning
+    global _brlAPISourceId
+
+    if _initialized:
+        return False
+
+    _callback = callback
+
+    try:
+        gobject.threads_init()
+        _brlAPI = brlapi.Connection()
+
+        try:
+            import os
+            windowPath = os.environ["WINDOWPATH"]
+            _brlAPI.enterTtyModeWithPath()
+            _brlAPIRunning = True
+            log.info("braille module been initialized using WINDOWPATH=%s"
+                     % windowPath)
+        except:
+            _brlAPI.enterTtyMode(tty)
+            _brlAPIRunning = True
+            log.info("braille module initialized using tty=%d" % tty)
+
+        _brlAPISourceId = gobject.io_add_watch(_brlAPI.fileDescriptor,
+                                               gobject.IO_IN,
+                                               _brlAPIKeyReader)
+    except brlapi.ConnectionError, detail:
+        log.info("could not connect to brltty -- %s" % detail)
+        return False
+    except:
+        log.exception("handled exception while initializing brltty:")
+        return False
+
+    _displaySize = _brlAPI.displaySize
+
+    _initialized = True
+
+    return True
+
+def shutdown():
+    """Shuts down the braille module.   Returns True if the shutdown procedure
+    was run or False if this module has not been initialized.
+    """
+    global _initialized
+    if not _initialized:
+        return False
+
+    global _brlAPIRunning
+    global _brlAPISourceId
+    if _brlAPIRunning:
+        _brlAPIRunning = False
+        gobject.source_remove(_brlAPISourceId)
+        _brlAPISourceId = 0
+        _brlAPI.leaveTtyMode()
+
+    _initialized = False
+    return True
+
+def _myCallback(event):
+    """Just for testing when run in standalone mode."""
+    if event["type"] == brlapi.KEY_TYPE_CMD:
+        print "This is a command"
+    else:
+        print "This is not a command", event["type"]
+
+    if event["command"] == brlapi.KEY_CMD_ROUTE:
+        cursor = int(event["argument"]) + 1
+        text = "Cursor routing key %d" % cursor
+    elif event["command"] == brlapi.KEY_CMD_FWINLT:
+        cursor = 0
+        text = "Pan left"
+    elif event["command"] == brlapi.KEY_CMD_FWINRT:
+        cursor = 0
+        text = "Pan right"
+
+    print text
+    writeText(text, None, cursor)
+
+if __name__ == "__main__":
+    logging.basicConfig(format="%(name)s %(message)s")
+    log.setLevel(logging.DEBUG)
+
+    import gtk
+    init(_myCallback)
+    setKeys([brlapi.KEY_CMD_ROUTE,
+             brlapi.KEY_CMD_FWINLT, 
+             brlapi.KEY_CMD_FWINRT])
+    print "Press keys on the braille display.  Press Ctrl+C to quit."
+    gtk.main()

Modified: branches/phase2/src/orca/script_manager.py
==============================================================================
--- branches/phase2/src/orca/script_manager.py	(original)
+++ branches/phase2/src/orca/script_manager.py	Mon Sep 29 23:56:21 2008
@@ -74,7 +74,7 @@
 import time
 
 import braille
-import default
+import scripts.default
 import input_event
 import pyatspi
 import utils
@@ -261,7 +261,7 @@
                     log.exception("handled exception importing %s:" % name)
 
         if not script:
-            script = default.Script(application, self._settings)
+            script = scripts.default.Script(application, self._settings)
 
         return script
 
@@ -279,7 +279,7 @@
         #
         if not application:
             if not self._defaultScript:
-                self._defaultScript = default.Script(None)
+                self._defaultScript = scripts.default.Script(None)
             script = self._defaultScript
         elif application in self._knownScripts:
             script = self._knownScripts[application]
@@ -665,7 +665,7 @@
         """Called whenever a cursor key is pressed on the Braille display.
 
         Arguments:
-        - event: an expanded BrlTTY event (see braille.py)
+        - event: an expanded BrlTTY event (see braille/brltty.py)
 
         Returns True if the command was consumed; otherwise False
         """

Modified: branches/phase2/src/orca/scripts/Makefile.am
==============================================================================
--- branches/phase2/src/orca/scripts/Makefile.am	(original)
+++ branches/phase2/src/orca/scripts/Makefile.am	Mon Sep 29 23:56:21 2008
@@ -3,6 +3,7 @@
 orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
-	__init__.py
+	__init__.py \
+	default.py
 
 orca_pythondir=$(pyexecdir)/orca/scripts

Added: branches/phase2/src/orca/scripts/default.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/scripts/default.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,591 @@
+# Copyright 2004-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""The default Script for presenting information to the user using
+both speech and Braille.  This is based primarily on the de-facto
+standard implementation of the AT-SPI, which is the GAIL support
+for GTK."""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import logging
+log = logging.getLogger('orca.default')
+
+import brlapi
+
+import pyatspi
+
+import orca.input_binding as input_binding
+import orca.input_event as input_event
+import orca.settings as settings
+import orca.script as script
+
+from orca.orca_i18n import _ # for gettext support
+
+class Script(script.Script):
+    """The default Script from which all other scripts should be 
+    derived.
+    """
+
+    def __init__(self, application, userSettings):
+        """Creates a new script for the given application.
+
+        Arguments:
+        - application: the application to create a script for.
+        """
+        script.Script.__init__(self, application, userSettings)
+
+    def _getPluginClasses(self):
+        """Returns a list of classes to instantiante for plugins.
+        Subclasses should override this method to add their own
+        plugins.
+        """
+        # TODO: add user plugins
+        # TODO: make the discovery of plugin classes somewhat dynamic
+        #
+        pluginClasses = []
+        try:
+            import orca.plugins.automatic
+            pluginClasses.append(orca.plugins.automatic.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+        try:
+            import orca.plugins.debug_actions
+            pluginClasses.append(orca.plugins.debug_actions.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+        try:
+            import orca.plugins.speech_parameters
+            pluginClasses.append(orca.plugins.speech_parameters.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+        try:
+            import orca.plugins.bookmarks
+            pluginClasses.append(orca.plugins.bookmarks.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+        try:
+            import orca.plugins.where_am_i
+            pluginClasses.append(orca.plugins.where_am_i.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+        try:
+            import orca.plugins.flat_review
+            pluginClasses.append(orca.plugins.flat_review.Plugin)
+        except:
+            log.exception("handled exception while importing module:")
+
+        # TODO/QUESTION: Most scripts are not going to have a need for
+        # structural navigation (I would like to implement it for OOo
+        # Writer for 2.26 'fun stuff' should time permit, however.).
+        # I assume that the enabling of the structural_navigation plugin
+        # will be done on a script-by-script basis in this method(?).
+        # Lacking scripts, I'm putting it here and uncommenting it as I
+        # work. :-)
+        #
+        #try:
+        #    import orca.plugins.structural_navigation
+        #    pluginClasses.append(orca.plugins.structural_navigation.Plugin)
+        #except:
+        #    log.exception("handled exception while importing module:")
+
+        return script.Script._getPluginClasses(self) + pluginClasses
+
+    ####################################################################
+    #                                                                  #
+    # UTILITIES TO HELP NORMALIZE ACCESS TO THE AT-SPI.  SUBSCRIPTS    #
+    # SHOULD OVERRIDE THESE IF THEY NEED TO DO DIFFERENT THINGS TO GET #
+    # THE DESIRED RESULTS.                                             #
+    #                                                                  #
+    ####################################################################
+
+    def getTopLevel(self, accessible):
+        """Returns the top-level object (frame, dialog ...) containing this
+        object, or None if this object is not inside a top-level object.
+
+        Arguments:
+        - accessible: the Accessible object
+        """
+        while accessible \
+            and accessible.parent \
+            and (accessible != accessible.parent) \
+            and (accessible.parent.getRole() != pyatspi.ROLE_APPLICATION):
+            accessible = accessible.parent
+
+        if accessible \
+            and accessible.parent \
+            and (accessible.parent.getRole() == pyatspi.ROLE_APPLICATION):
+            pass
+        else:
+            accessible = None
+
+        return accessible
+
+    ####################################################################
+    #                                                                  #
+    # AT-SPI OBJECT EVENT HANDLERS                                     #
+    #                                                                  #
+    ####################################################################
+
+    def _focusListener(self, event):
+        """Called on AT-SPI focus events.
+        """
+        log.debug("_focusListener: %s" % str(event).replace("\n", " "))
+
+        # [[[TODO: WDW - HACK to deal with quirky GTK+ menu behavior.
+        # The problem is that when moving to submenus in a menu, the
+        # menu gets focus first and then the submenu gets focus all
+        # with a single keystroke.  So...focus in menus really means
+        # that the object has focus *and* it is selected.  Now, this
+        # assumes the selected state will be set before focus is given,
+        # which appears to be the case from empirical analysis of the
+        # event stream.  But of course, all menu items and menus in
+        # the complete menu path will have their selected state set,
+        # so, we really only care about the leaf menu or menu item
+        # that it selected.]]]
+        #
+        if event.source.getRole() in (pyatspi.ROLE_MENU,
+                                      pyatspi.ROLE_MENU_ITEM,
+                                      pyatspi.ROLE_CHECK_MENU_ITEM,
+                                      pyatspi.ROLE_RADIO_MENU_ITEM):
+            try:
+                if event.source.querySelection().nSelectedChildren > 0:
+                    return
+            except:
+                pass
+
+        oldFocus = self.focus
+        self.focus = event.source
+        self.emit("focus-changed", oldFocus, self.focus)
+    _focusListener.events = ["focus:"]
+
+    def _activeDescendantChangedListener(self, event):
+        """Called on AT-SPI object:active-descendant-changed events.
+        """
+        log.debug("_activeDescendantChangedListener: %s" \
+                  % str(event).replace("\n", " "))
+    _activeDescendantChangedListener.events = \
+        ["object:active-descendant-changed"]
+
+    def _mouseButtonListener(self, event):
+        """Called on AT-SPI mouse:button events.
+        """
+        log.debug("_mouseButtonListener: %s" % str(event).replace("\n", " "))
+    _mouseButtonListener.events = ["mouse:button"]
+
+    def _nameChangedListener(self, event):
+        """Called on AT-SPI object:property-change:accessible-name events.
+        """
+        log.debug("_nameChangedListener: %s" % str(event).replace("\n", " "))
+    _nameChangedListener.events = ["object:property-change:accessible-name"]
+
+    def _caretMovedListener(self, event):
+        """Called on AT-SPI object:text-caret-moved events.
+        """
+        log.debug("_caretMovedListener: %s" % str(event).replace("\n", " "))
+    _caretMovedListener.events = ["object:text-caret-moved"]
+
+    def _textDeletedListener(self, event):
+        """Called on AT-SPI object:text-changed:delete events.
+        """
+        log.debug("_textDeletedListener: %s" % str(event).replace("\n", " "))
+    _textDeletedListener.events = ["object:text-changed:delete"]
+
+    def _textInsertedListener(self, event):
+        """Called on AT-SPI object:text-changed:insert events.
+        """
+        log.debug("_textInsertedListener: %s" % str(event).replace("\n", " "))
+    _textInsertedListener.events = ["event: object:text-changed:insert"]
+
+    def _textSelectionChangedListener(self, event):
+        """Called on AT-SPI object:text-selection-changed events.
+        """
+        log.debug("_textSelectionChangedListener: %s" 
+                  % str(event).replace("\n", " "))
+    _textSelectionChangedListener.events = ["object:text-selection-changed"]
+
+    def _selectionChangedListener(self, event):
+        """Called on AT-SPI object:selection-changed events.
+        """
+        log.debug("_selectionChangedListener: %s" % str(event).replace("\n", " "))
+    _selectionChangedListener.events = ["object:selection-changed"]
+
+    def _linkSelectedListener(self, event):
+        """Called on AT-SPI object:link-selected events.
+        """
+        log.debug("_linkSelectedListener: %s" % str(event).replace("\n", " "))
+    _linkSelectedListener.events = ["object:link-selected"]
+
+    def _stateChangedFocusedListener(self, event):
+        """Called on AT-SPI object:state-changed events.
+        """
+        log.debug("_stateChangedFocusedListener: %s" \
+                      % str(event).replace("\n", " "))
+        iconified = False
+        try:
+            window = self.getTopLevel(event.source)
+            iconified = window.getState().contains(pyatspi.STATE_ICONIFIED)
+        except:
+            log.exception("exception handled getting frame of focused item:")
+        if not iconified and  event.detail1:
+            self._focusListener(event)
+    _stateChangedFocusedListener.events = ["object:state-changed:focused"]
+
+    def _valueChangedListener(self, event):
+        """Called on AT-SPI object:value-changed and
+           object:property-change:accessible-value events.
+        """
+        log.debug("_valueChangedListener: %s" % str(event).replace("\n", " "))
+    _valueChangedListener.events = \
+        ["object:value-changed", "object:property-change:accessible-value"]
+
+    def _windowActivateListener(self, event):
+        """Called on AT-SPI window:activate events.
+        """
+        log.debug("_windowActivateListener: %s" % str(event).replace("\n", " "))
+    _windowActivateListener.events = ["window:activate"]
+
+    def _windowDeactivatedListener(self, event):
+        """Called on AT-SPI window:deactivate events.
+        """
+        log.debug("_windowDeactivateListener: %s" % str(event).replace("\n", " "))
+    _windowDeactivatedListener.events = ["window:deactivate"]
+
+    def _noOpListener(self, event):
+        """Just here to capture events.
+        """
+        log.debug("_noOp: %s" % str(event).replace("\n", " "))
+
+    ####################################################################
+    #                                                                  #
+    # INPUT EVENT HANDLERS                                             #
+    #                                                                  #
+    ####################################################################
+
+    def sayAllHandler(self, inputEvent=None):
+        """The sayAll handler.
+        """
+        log.debug("sayAllHandler: %s" % inputEvent)
+    # Translators: the Orca "SayAll" command allows the
+    # user to press a key and have the entire document in
+    # a window be automatically spoken to the user.  If
+    # the user presses any key during a SayAll operation,
+    # the speech will be interrupted and the cursor will
+    # be positioned at the point where the speech was
+    # interrupted.
+    #                
+    sayAllHandler.description = _("Speaks entire document.")
+    sayAllHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "KP_Add",
+            input_event.defaultModifierMask,
+            input_event.NO_MODIFIER_MASK,
+            keyboardLayout = settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP),
+        input_binding.KeyboardBinding(
+            "semicolon",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK,
+            keyboardLayout = settings.GENERAL_KEYBOARD_LAYOUT_LAPTOP),
+    ]
+
+    def toggleTableCellReadModeHandler(self, inputEvent=None):
+        """The toggleTableCellReadMode handler.
+        """
+        log.debug("toggleTableCellReadModeHandler: %s" % inputEvent)
+    # Translators: when users are navigating a table, they
+    # sometimes want the entire row of a table read, or
+    # they just want the current cell to be presented to them.
+    #
+    toggleTableCellReadModeHandler.description = \
+        _("Toggles whether to read just the current table cell " \
+          "or the whole row.")
+    toggleTableCellReadModeHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "F11",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK),
+        input_binding.KeyboardBinding(
+            "SunF36",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)        
+    ]
+
+    def readCharAttributesHandler(self, inputEvent=None):
+        """The readCharAttributes handler.
+        """
+        log.debug("readCharAttributesHandler: %s" % inputEvent)
+    # Translators: the attributes being presented are the
+    # text attributes, such as bold, italic, font name,
+    # font size, etc.
+    #
+    readCharAttributesHandler.description = \
+        _("Reads the attributes associated with the current text character.")
+    readCharAttributesHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "f",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)
+    ]
+
+    def brailleCursorKeyHandler(self, inputEvent=None):
+        """The brailleCursorKeyHandler handler.
+        """
+        log.debug("brailleCursorKeyHandler: %s" % inputEvent)
+    # Translators: a refreshable braille display is an
+    # external hardware device that presents braille
+    # character to the user.  There are a limited number
+    # of cells on the display (typically 40 cells).  
+    # There is typically a small button called a 'cursor
+    # routing key' over each cell.  The typical use is
+    # to move the text caret to the given spot when one
+    # presses the button.
+    #
+    brailleCursorKeyHandler.description = \
+        _("Handles presses of braille cursor routing keys.")
+    brailleCursorKeyHandler.bindings = [\
+        input_binding.BrailleBinding(
+            brlapi.KEY_CMD_ROUTE,
+            input_event.NO_MODIFIER_MASK,
+            input_event.NO_MODIFIER_MASK,
+            learnMode = False)
+    ]
+
+    def panBrailleLeftHandler(self, inputEvent=None):
+        """The panBrailleLeft handler.
+        """
+        log.debug("panBrailleLeftHandler: %s" % inputEvent)
+    # Translators: a refreshable braille display is an
+    # external hardware device that presents braille
+    # character to the user.  There are a limited number
+    # of cells on the display (typically 40 cells).  Orca
+    # provides the feature to build up a longer logical
+    # line and allow the user to press buttons on the
+    # braille display so they can pan left and right over
+    # this line.
+    #
+    panBrailleLeftHandler.description = \
+        _("Pans the braille display to the left.")
+    panBrailleLeftHandler.bindings = [
+        input_binding.BrailleBinding(
+            brlapi.KEY_CMD_FWINLT,
+            input_event.NO_MODIFIER_MASK,
+            input_event.NO_MODIFIER_MASK,
+            learnMode = False)
+    ]
+
+    def panBrailleRightHandler(self, inputEvent=None):
+        """The panBrailleRight handler.
+        """
+        log.debug("panBrailleRightHandler: %s" % inputEvent)
+    # Translators: a refreshable braille display is an
+    # external hardware device that presents braille
+    # character to the user.  There are a limited number
+    # of cells on the display (typically 40 cells).  Orca
+    # provides the feature to build up a longer logical
+    # line and allow the user to press buttons on the
+    # braille display so they can pan left and right over
+    # this line.
+    #
+    panBrailleRightHandler.description = \
+        _("Pans the braille display to the right.")
+    panBrailleRightHandler.bindings = [
+        input_binding.BrailleBinding(
+            brlapi.KEY_CMD_FWINRT,
+            input_event.NO_MODIFIER_MASK,
+            input_event.NO_MODIFIER_MASK,
+            learnMode = False)
+    ]
+
+    def enterLearnModeHandler(self, inputEvent=None):
+        """The enterLearnMode handler.
+        """
+        log.debug("enterLearnModeHandler: %s" % inputEvent)
+    # Translators: Orca has a "Learn Mode" that will allow
+    # the user to type any key on the keyboard and hear what
+    # the effects of that key would be.  The effects might
+    # be what Orca would do if it had a handler for the
+    # particular key combination, or they might just be to
+    # echo the name of the key if Orca doesn't have a handler.
+    #
+    enterLearnModeHandler.description = \
+        _("Enters learn mode.  Press escape to exit learn mode.")
+    enterLearnModeHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "h",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)
+    ]
+
+    def quitOrcaHandler(self, inputEvent=None):
+        """The quitOrca handler.
+        """
+        log.debug("quitOrcaHandler: %s" % inputEvent)
+    quitOrcaHandler.description = _("Quits Orca")
+    quitOrcaHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "q",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)
+    ]
+
+    def showPreferencesGUIHandler(self, inputEvent=None):
+        """The showPreferencesGUI handler.
+        """
+        log.debug("showPreferencesGUIHandler: %s" % inputEvent)
+    # Translators: the preferences configuration dialog is
+    # the dialog that allows users to set their preferences
+    # for Orca.
+    #
+    showPreferencesGUIHandler.description = \
+        _("Displays the preferences configuration dialog.")
+    showPreferencesGUIHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "space",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)
+    ]
+
+    def showAppPreferencesGUIHandler(self, inputEvent=None):
+        """The showAppPreferencesGUI handler.
+        """
+        log.debug("showAppPreferencesGUIHandler: %s" % inputEvent)
+    # Translators: the application preferences configuration
+    # dialog is the dialog that allows users to set their
+    # preferences for a specific application within Orca.
+    #
+    showAppPreferencesGUIHandler.description = \
+        _("Displays the application preferences configuration dialog.")
+    showAppPreferencesGUIHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "space",
+            input_event.defaultModifierMask,
+            input_event.ORCA_CTRL_MODIFIER_MASK)
+    ]
+
+    def toggleSilenceSpeechHandler(self, inputEvent=None):
+        """The toggleSilenceSpeech handler.
+        """
+        log.debug("toggleSilenceSpeechHandler: %s" % inputEvent)
+    # Translators: Orca allows the user to turn speech synthesis
+    # on or off.  We call it 'silencing'.
+    #
+    toggleSilenceSpeechHandler.description = \
+        _("Toggles the silencing of speech.")
+    toggleSilenceSpeechHandler.bindings = [
+        input_binding.KeyboardBinding(
+            "s",
+            input_event.defaultModifierMask,
+            input_event.ORCA_MODIFIER_MASK)
+    ]
+
+    def toggleColorEnhancementsHandler(self, inputEvent=None):
+        """The toggleColorEnhancements handler.
+        """
+        log.debug("toggleColorEnhancementsHandler: %s" % inputEvent)
+    # Translators: "color enhancements" are changes users can
+    # make to the appearance of the screen to make things easier
+    # to see, such as inverting the colors or applying a tint.
+    # This command toggles these enhancements on/off.
+    #
+    toggleColorEnhancementsHandler.description = \
+        _("Toggles color enhancements.")
+
+    def toggleMouseEnhancementsHandler(self, inputEvent=None):
+        """The toggleMouseEnhancements handler.
+        """
+        log.debug("toggleMouseEnhancementsHandler: %s" % inputEvent)
+    # Translators: "mouse enhancements" are changes users can
+    # make to the appearance of the mouse pointer to make it
+    # easier to see, such as increasing its size, changing its
+    # color, and surrounding it with crosshairs.  This command
+    # toggles these enhancements on/off.
+    #
+    toggleMouseEnhancementsHandler.description = \
+        _("Toggles mouse enhancements.")
+
+    def increaseMagnificationHandler(self, inputEvent=None):
+        """The increaseMagnification handler.
+        """
+        log.debug("increaseMagnificationHandler: %s" % inputEvent)
+    # Translators: this command increases the magnification
+    # level.
+    #
+    increaseMagnificationHandler.description = \
+        _("Increases the magnification level.")
+
+    def decreaseMagnificationHandler(self, inputEvent=None):
+        """The decreaseMagnification handler.
+        """
+        log.debug("decreaseMagnificationHandler: %s" % inputEvent)
+    # Translators: this command decreases the magnification
+    # level.
+    #
+    decreaseMagnificationHandler.description = \
+        _("Decreases the magnification level.")
+
+    def toggleMagnifierHandler(self, inputEvent=None):
+        """The toggleMagnifier handler.
+        """
+        log.debug("toggleMagnifierHandler: %s" % inputEvent)
+    # Translators: Orca allows the user to turn the magnifier
+    # on or off. This command not only toggles magnification,
+    # but also all of the color and pointer customizations
+    # made through the magnifier.
+    #
+    toggleMagnifierHandler.description = \
+        _("Toggles the magnifier.")
+
+    def cycleZoomerTypeHandler(self, inputEvent=None):
+        """The cycleZoomerType handler.
+        """
+        log.debug("cycleZoomerTypeHandler: %s" % inputEvent)
+    # Translators: the user can choose between several different
+    # types of magnification, including full screen and split
+    # screen.  The "position" here refers to location of the
+    # magnifier.
+    #
+    cycleZoomerTypeHandler.description = \
+        _("Cycles to the next magnifier position.")
+
+    def toggleMouseReviewHandler(self, inputEvent=None):
+        """The toggleMouseReview handler.
+        """
+        log.debug("toggleMouseReviewHandler: %s" % inputEvent)
+    # Translators: Orca allows the item under the pointer to
+    # be spoken. This toggles the feature.
+    #
+    toggleMouseReviewHandler.description = \
+        _("Toggle mouse review mode.")
+
+    def bypassNextCommandHandler(self, inputEvent=None):
+        """The bypassNextCommand handler.
+        """
+        log.debug("bypassNextCommandHandler: %s" % inputEvent)
+    # Translators: Orca normally intercepts all keyboard
+    # commands and only passes them along to the current
+    # application when they are not Orca commands.  This
+    # command causes the next command issued to be passed
+    # along to the current application, bypassing Orca's
+    # interception of it.
+    #
+    bypassNextCommandHandler.description = \
+        _("Passes the next command on to the current application.")
+
+if __name__ == "__main__":
+    print Script(None)

Modified: branches/phase2/src/orca/settings.py
==============================================================================
--- branches/phase2/src/orca/settings.py	(original)
+++ branches/phase2/src/orca/settings.py	Mon Sep 29 23:56:21 2008
@@ -23,7 +23,7 @@
 
 import os
 
-from acss import ACSS
+from speech.acss import ACSS
 from orca_i18n import _  # for gettext support
 from orca_i18n import Q_ # to provide qualified translatable strings
 

Added: branches/phase2/src/orca/speech/Makefile.am
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/Makefile.am	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,10 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	acss.py \
+	character_names.py \
+	key_names.py \
+	phonetic_names.py
+
+orca_pythondir=$(pyexecdir)/orca/speech

Added: branches/phase2/src/orca/speech/__init__.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/__init__.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1 @@
+"""Modules for handling speech."""

Added: branches/phase2/src/orca/speech/acss.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/acss.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,94 @@
+# Copyright 2005-2008 Google Inc.
+# Portions Copyright 2007-2008, Sun Microsystems, Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+#
+
+"""ACSS --- Aural CSS.
+
+Class ACSS defines a simple wrapper for holding ACSS voice
+definitions.  Speech engines implement the code for converting
+ACSS definitions into engine-specific markup codes.
+
+"""
+
+__id__ = "$Id$"
+__author__ = "T. V. Raman"
+__copyright__ = "Copyright (c) 2005-2008 Google Inc."
+__license__ = "LGPL"
+
+class ACSS(dict):
+
+    """Holds ACSS representation of a voice."""
+
+    FAMILY        = 'family'
+    RATE          = 'rate'
+    GAIN          = 'gain'
+    AVERAGE_PITCH = 'average-pitch'
+    PITCH_RANGE   = 'pitch-range'
+    STRESS        = 'stress'
+    RICHNESS      = 'richness'
+    PUNCTUATIONS  = 'punctuations'
+
+    # A value of None means use the engine's default value.
+    #
+    settings = {
+        FAMILY :        None,
+        RATE :          50,
+        GAIN :          5,
+        AVERAGE_PITCH : 5,
+        PITCH_RANGE :   5,
+        STRESS :        5,
+        RICHNESS :      5,
+        PUNCTUATIONS :  'all'
+    }
+
+    def __init__(self, props=None):
+        """Create and initialize ACSS structure."""
+        dict.__init__(self)
+        props = props or {}
+        for k in props:
+            if k in ACSS.settings:
+                # Do a 'deep copy' of the family.  Otherwise,
+                # the new ACSS shares the actual data with the
+                # props passed in.  This can cause unexpected
+                # side effects.
+                #
+                if k == ACSS.FAMILY:
+                    self[k] = {}
+                    for j in props[k].keys():
+                        self[k][j] = props[k][j]
+                else:
+                    self[k] = props[k]
+
+    def __setitem__ (self, key, value):
+        """Update name when we change values."""
+        dict.__setitem__(self, key, value)
+
+    def __delitem__(self, key):
+        """Update name if we delete a key."""
+        dict.__delitem__(self, key)
+
+    def __str__(self):
+        """Get a name for this ACSS."""
+        _name = 'acss-'
+        names = self.keys()
+        if names:
+            names.sort()
+            for  k in names:
+                _name += "%s-%s:" % (k, self[k])
+        _name = _name[:-1]
+        return _name

Added: branches/phase2/src/orca/speech/character_names.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/character_names.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,748 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2004-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Provides getCharacterName that maps punctuation marks and other
+individual characters into localized words."""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+from orca.orca_i18n import _ # for gettext support
+
+# __characterNames is a dictionary where the keys represent a unicode
+# character and the values represent the common term used for the
+# character.
+#
+__characterNames = {}
+
+# Translators: this is the spoken word for the space character
+#
+__characterNames[" "] = _("space")
+
+# Translators: this is the spoken word for the newline character
+#
+__characterNames["\n"] = _("newline")
+
+# Translators: this is the spoken word for the tab character
+#
+__characterNames["\t"] = _("tab")
+
+# Translators: this is the spoken word for the character '!' (U+0021)
+#
+__characterNames["!"] = _("exclaim")
+
+# Translators: this is the spoken word for the character '"' (U+0022)
+#
+__characterNames["\""] = _("quote")
+
+# Translators: this is the spoken word for the character '#' (U+0023)
+#
+__characterNames["#"] = _("number")
+
+# Translators: this is the spoken word for the character '$' (U+0024)
+#
+__characterNames["$"] = _("dollar")
+
+# Translators: this is the spoken word for the character '%' (U+0025)
+#
+__characterNames["%"] = _("percent")
+
+# Translators: this is the spoken word for the character '&' (U+0026)
+#
+__characterNames["&"] = _("and")
+
+# Translators: this is the spoken word for the character ''' (U+0027)
+#
+__characterNames["'"] = _("apostrophe")
+
+# Translators: this is the spoken word for the character '(' (U+0028)
+#
+__characterNames["("] = _("left paren")
+
+# Translators: this is the spoken word for the character ')' (U+0029)
+#
+__characterNames[")"] = _("right paren")
+
+# Translators: this is the spoken word for the character '*' (U+002a)
+#
+__characterNames["*"] = _("star")
+
+# Translators: this is the spoken word for the character '+' (U+002b)
+#
+__characterNames["+"] = _("plus")
+
+# Translators: this is the spoken word for the character ',' (U+002c)
+#
+__characterNames[","] = _("comma")
+
+# Translators: this is the spoken word for the character '-' (U+002d)
+#
+__characterNames["-"] = _("dash")
+
+# Translators: this is the spoken word for the character '.' (U+002e)
+#
+__characterNames["."] = _("dot")
+
+# Translators: this is the spoken word for the character '/' (U+002f)
+#
+__characterNames["/"] = _("slash")
+
+# Translators: this is the spoken word for the character ':' (U+003a)
+#
+__characterNames[":"] = _("colon")
+
+# Translators: this is the spoken word for the character ';' (U+003b)
+#
+__characterNames[";"] = _("semicolon")
+
+# Translators: this is the spoken word for the character '<Â' (U+003c)
+#
+__characterNames["<"] = _("less")
+
+# Translators: this is the spoken word for the character '=' (U+003d)
+#
+__characterNames["="] = _("equals")
+
+# Translators: this is the spoken word for the character '>Â' (U+003e)
+#
+__characterNames[">"] = _("greater")
+
+# Translators: this is the spoken word for the character '?' (U+003f)
+#
+__characterNames["?"] = _("question")
+
+# Translators: this is the spoken word for the character '@' (U+0040)
+#
+__characterNames["@"] = _("at")
+
+# Translators: this is the spoken word for the character '[' (U+005b)
+#
+__characterNames["["] = _("left bracket")
+
+# Translators: this is the spoken word for the character '\' (U+005c)
+#
+__characterNames["\\"] = _("backslash")
+
+# Translators: this is the spoken word for the character ']' (U+005d)
+#
+__characterNames["]"] = _("right bracket")
+
+# Translators: this is the spoken word for the character '^' (U+005e)
+#
+__characterNames["^"] = _("caret")
+
+# Translators: this is the spoken word for the character '_' (U+005f)
+#
+__characterNames["_"] = _("underline")
+
+# Translators: this is the spoken word for the character '`' (U+0060)
+#
+__characterNames["`"] = _("grave")
+
+# Translators: this is the spoken word for the character '{' (U+007b)
+#
+__characterNames["{"] = _("left brace")
+
+# Translators: this is the spoken word for the character '|' (U+007c)
+#
+__characterNames["|"] = _("vertical bar")
+
+# Translators: this is the spoken word for the character '}' (U+007d)
+#
+__characterNames["}"] = _("right brace")
+
+# Translators: this is the spoken word for the character '~' (U+007e)
+#
+__characterNames["~"] = _("tilde")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a1)
+#
+__characterNames[u'\u00a1'] = _("inverted exclamation point")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a2)
+#
+__characterNames[u'\u00a2'] = _("cents")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a3)
+#
+__characterNames[u'\u00a3'] = _("pounds")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a4)
+#
+__characterNames[u'\u00a4'] = _("currency sign")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a5)
+#
+__characterNames[u'\u00a5'] = _("yen")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a6)
+#
+__characterNames[u'\u00a6'] = _("broken bar")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a7)
+#
+__characterNames[u'\u00a7'] = _("section")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a8)
+#
+__characterNames[u'\u00a8'] = _("umlaut")
+
+# Translators: this is the spoken word for the character 'Â' (U+00a9)
+#
+__characterNames[u'\u00a9'] = _("copyright")
+
+# Translators: this is the spoken word for the character 'Â' (U+00aa)
+#
+__characterNames[u'\u00aa'] = _("superscript a")
+
+# Translators: this is the spoken word for the character 'Â' (U+00ab)
+#
+__characterNames[u'\u00ab'] = _("left double angle bracket")
+
+# Translators: this is the spoken word for the character 'Â' (U+00ac)
+#
+__characterNames[u'\u00ac'] = _("logical not")
+
+# Translators: this is the spoken word for the character 'Â' (U+00ad)
+#
+__characterNames[u'\u00ad'] = _("soft hyphen")
+
+# Translators: this is the spoken word for the character 'Â' (U+00ae)
+#
+__characterNames[u'\u00ae'] = _("registered")
+
+# Translators: this is the spoken word for the character 'Â' (U+00af)
+#
+__characterNames[u'\u00af'] = _("macron")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b0)
+#
+__characterNames[u'\u00b0'] = _("degrees")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b1)
+#
+__characterNames[u'\u00b1'] = _("plus or minus")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b2)
+#
+__characterNames[u'\u00b2'] = _("superscript 2")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b3)
+#
+__characterNames[u'\u00b3'] = _("superscript 3")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b4)
+#
+__characterNames[u'\u00b4'] = _("acute accent")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b5)
+#
+__characterNames[u'\u00b5'] = _("mu")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b6)
+#
+__characterNames[u'\u00b6'] = _("paragraph marker")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b7)
+#
+__characterNames[u'\u00b7'] = _("middle dot")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b8)
+#
+__characterNames[u'\u00b8'] = _("cedilla")
+
+# Translators: this is the spoken word for the character 'Â' (U+00b9)
+#
+__characterNames[u'\u00b9'] = _("superscript 1")
+
+# Translators: this is the spoken word for the character 'Â' (U+00ba)
+#
+__characterNames[u'\u00ba'] = _("ordinal")
+
+# Translators: this is the spoken word for the character 'Â' (U+00bb)
+#
+__characterNames[u'\u00bb'] = _("right double angle bracket")
+
+# Translators: this is the spoken word for the character 'Â' (U+00bc)
+#
+__characterNames[u'\u00bc'] = _("one fourth")
+
+# Translators: this is the spoken word for the character 'Â' (U+00bd)
+#
+__characterNames[u'\u00bd'] = _("one half")
+
+# Translators: this is the spoken word for the character 'Â' (U+00be)
+#
+__characterNames[u'\u00be'] = _("three fourths")
+
+# Translators: this is the spoken word for the character 'Â' (U+00bf)
+#
+__characterNames[u'\u00bf'] = _("inverted question mark")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e1)
+#
+__characterNames[u'\u00e1'] = _("a acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c0)
+#
+__characterNames[u'\u00c0'] = _("A GRAVE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c1)
+#
+__characterNames[u'\u00c1'] = _("A ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c2)
+#
+__characterNames[u'\u00c2'] = _("A CIRCUMFLEX")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c3)
+#
+__characterNames[u'\u00c3'] = _("A TILDE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c4)
+#
+__characterNames[u'\u00c4'] = _("A UMLAUT")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c5)
+#
+__characterNames[u'\u00c5'] = _("A RING")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c6)
+#
+__characterNames[u'\u00c6'] = _("A E")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c7)
+#
+__characterNames[u'\u00c7'] = _("C CEDILLA")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c8)
+#
+__characterNames[u'\u00c8'] = _("E GRAVE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00c9)
+#
+__characterNames[u'\u00c9'] = _("E ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ca)
+#
+__characterNames[u'\u00ca'] = _("E CIRCUMFLEX")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00cb)
+#
+__characterNames[u'\u00cb'] = _("E UMLAUT")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00cc)
+#
+__characterNames[u'\u00cc'] = _("I GRAVE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00cd)
+#
+__characterNames[u'\u00cd'] = _("I ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ce)
+#
+__characterNames[u'\u00ce'] = _("I CIRCUMFLEX")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00cf)
+#
+__characterNames[u'\u00cf'] = _("I UMLAUT")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d0)
+#
+__characterNames[u'\u00d0'] = _("ETH")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d1)
+#
+__characterNames[u'\u00d1'] = _("N TILDE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d2)
+#
+__characterNames[u'\u00d2'] = _("O GRAVE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d3)
+#
+__characterNames[u'\u00d3'] = _("O ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d4)
+#
+__characterNames[u'\u00d4'] = _("O CIRCUMFLEX")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d5)
+#
+__characterNames[u'\u00d5'] = _("O TILDE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d6)
+#
+__characterNames[u'\u00d6'] = _("O UMLAUT")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d7)
+#
+__characterNames[u'\u00d7'] = _("times")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d8)
+#
+__characterNames[u'\u00d8'] = _("O STROKE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00d9)
+#
+__characterNames[u'\u00d9'] = _("U GRAVE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00da)
+#
+__characterNames[u'\u00da'] = _("U ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00db)
+#
+__characterNames[u'\u00db'] = _("U CIRCUMFLEX")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00dc)
+#
+__characterNames[u'\u00dc'] = _("U UMLAUT")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00dd)
+#
+__characterNames[u'\u00dd'] = _("Y ACUTE")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00de)
+#
+__characterNames[u'\u00de'] = _("THORN")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00df)
+#
+__characterNames[u'\u00df'] = _("s sharp")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e0)
+#
+__characterNames[u'\u00e0'] = _("a grave")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e2)
+#
+__characterNames[u'\u00e2'] = _("a circumflex")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e3)
+#
+__characterNames[u'\u00e3'] = _("a tilde")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e4)
+#
+__characterNames[u'\u00e4'] = _("a umlaut")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e5)
+#
+__characterNames[u'\u00e5'] = _("a ring")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e6)
+#
+__characterNames[u'\u00e6'] = _("a e")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e7)
+#
+__characterNames[u'\u00e7'] = _("c cedilla")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e8)
+#
+__characterNames[u'\u00e8'] = _("e grave")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00e9)
+#
+__characterNames[u'\u00e9'] = _("e acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ea)
+#
+__characterNames[u'\u00ea'] = _("e circumflex")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00eb)
+#
+__characterNames[u'\u00eb'] = _("e umlaut")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ec)
+#
+__characterNames[u'\u00ec'] = _("i grave")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ed)
+#
+__characterNames[u'\u00ed'] = _("i acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ee)
+#
+__characterNames[u'\u00ee'] = _("i circumflex")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ef)
+#
+__characterNames[u'\u00ef'] = _("i umlaut")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f0)
+#
+__characterNames[u'\u00f0'] = _("eth")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f1)
+#
+__characterNames[u'\u00f1'] = _("n tilde")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f2)
+#
+__characterNames[u'\u00f2'] = _("o grave")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f3)
+#
+__characterNames[u'\u00f3'] = _("o acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f4)
+#
+__characterNames[u'\u00f4'] = _("o circumflex")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f5)
+#
+__characterNames[u'\u00f5'] = _("o tilde")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f6)
+#
+__characterNames[u'\u00f6'] = _("o umlaut")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f7)
+#
+__characterNames[u'\u00f7'] = _("divided by")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f8)
+#
+__characterNames[u'\u00f8'] = _("o stroke")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00fe)
+#
+__characterNames[u'\u00fe'] = _("thorn")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00fa)
+#
+__characterNames[u'\u00fa'] = _("u acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00f9)
+#
+__characterNames[u'\u00f9'] = _("u grave")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00fb)
+#
+__characterNames[u'\u00fb'] = _("u circumflex")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00fc)
+#
+__characterNames[u'\u00fc'] = _("u umlaut")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00fd)
+#
+__characterNames[u'\u00fd'] = _("y acute")
+
+# Translators: this is the spoken word for the character 'Ã' (U+00ff)
+#
+__characterNames[u'\u00ff'] = _("y umlaut")
+
+# Translators: this is the spoken word for the character 'Å' (U+0178)
+#
+__characterNames[u'\u0178'] = _("Y UMLAUT")
+
+# Translators: this is the spoken word for the character 'Æ' (U+0192)
+#
+__characterNames[u'\u0192'] = _("florin")
+
+# Translators: this is the spoken word for the character 'â' (U+2013)
+#
+__characterNames[u'\u2013'] = _("en dash")
+
+# Translators: this is the spoken word for the left single quote: â
+# (U+2018)
+#
+__characterNames[u'\u2018'] = _("left single quote")
+
+# Translators: this is the spoken word for the right single quote: â
+# (U+2019)
+#
+__characterNames[u'\u2019'] = _("right single quote")
+
+# Translators: this is the spoken word for the character 'â' (U+201c)
+#
+__characterNames[u'\u201c'] = _("left double quote")
+
+# Translators: this is the spoken word for the character 'â' (U+201d)
+#
+__characterNames[u'\u201d'] = _("right double quote")
+
+# Translators: this is the spoken word for the character 'â' (U+2020)
+#
+__characterNames[u'\u2020'] = _("dagger")
+
+# Translators: this is the spoken word for the character 'â' (U+2021)
+#
+__characterNames[u'\u2021'] = _("double dagger")
+
+# Translators: this is the spoken word for the character 'â' (U+2022)
+#
+__characterNames[u'\u2022'] = _("bullet")
+
+# Translators: this is the spoken word for the character 'â' (U+2023)
+#
+__characterNames[u'\u2023'] = _("triangular bullet")
+
+# Translators: this is the spoken word for the character 'â' (U+2030)
+#
+__characterNames[u'\u2030'] = _("per mille")
+
+# Translators: this is the spoken word for the character 'â' (U+2032)
+#
+__characterNames[u'\u2032'] = _("prime")
+
+# Translators: this is the spoken word for the character 'â' (U+2033)
+#
+__characterNames[u'\u2033'] = _("double prime")
+
+# Translators: this is the spoken word for the character 'â' (U+2043)
+#
+__characterNames[u'\u2043'] = _("hyphen bullet")
+
+# Translators: this is the spoken word for the character 'â' (U+20ac)
+#
+__characterNames[u'\u20ac'] = _("euro")
+
+# Translators: this is the spoken word for the character 'â' (U+2122)
+#
+__characterNames[u'\u2122'] = _("trademark")
+
+# Translators: this is the spoken word for the character 'â' (U+2248)
+#
+__characterNames[u'\u2248'] = _("almost equal to")
+
+# Translators: this is the spoken word for the character 'â' (U+2260)
+#
+__characterNames[u'\u2260'] = _("not equal to")
+
+# Translators: this is the spoken word for the character 'â' (U+2264)
+#
+__characterNames[u'\u2264'] = _("less than or equal to")
+
+# Translators: this is the spoken word for the character 'â' (U+2265)
+#
+__characterNames[u'\u2265'] = _("greater than or equal to")
+
+# Translators: this is the spoken word for the character 'â' (U+221a)
+#
+__characterNames[u'\u221a'] = _("square root")
+
+# Translators: this is the spoken word for the character 'â' (U+221b)
+#
+__characterNames[u'\u221b'] = _("cube root")
+
+# Translators: this is the spoken word for the character 'â' (U+221e)
+#
+__characterNames[u'\u221e'] = _("infinity")
+
+# Translators: this is the spoken word for the character 'â' (U+25a0)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u25a0'] = _("black square")
+
+# Translators: this is the spoken word for the character 'â' (U+25a1)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u25a1'] = _("white square")
+
+# Translators: this is the spoken word for the character 'â' (U+25c6)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u25c6'] = _("black diamond")
+
+# Translators: this is the spoken word for the character 'â' (U+25cb)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u25cb'] = _("white circle")
+
+# Translators: this is the spoken word for the character 'â' (U+25cf)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u25cf'] = _("black circle")
+
+# Translators: this is the spoken word for the character 'â' (U+25e6)
+#
+__characterNames[u'\u25e6'] = _("white bullet")
+
+# Translators: this is the spoken word for the character 'â' (U+2713)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u2713'] = _("check mark")
+
+# Translators: this is the spoken word for the character 'â' (U+2714)
+# It can be used as a bullet in a list.
+#
+__characterNames[u'\u2714'] = _("heavy check mark")
+
+# Translators: this is the spoken word for the character 'x' (U+2717)
+# This symbol is included here because it can be used as a bullet in 
+# an OOo list.  The goal is to inform the user of the appearance of 
+# the bullet, while making it clear that it is a bullet and not simply 
+# the typed letter 'x'.  "Ballot x" might confuse the user.  Hence the 
+# use of "x-shaped bullet".
+#
+__characterNames[u'\u2717'] = _("x-shaped bullet")
+
+# Translators: this is the spoken word for the character 'â' (U+2794)
+# This symbol is included here because it can be used as a bullet in 
+# an OOo list. The goal is to inform the user of the appearance of 
+# the bullet without too much verbiage, hence simply "right-pointing arrow".
+#
+__characterNames[u'\u2974'] = _("right-pointing arrow")
+
+# Translators: this is the spoken word for the character 'â' (U+27a2)
+# This symbol is included here because it can be used as a bullet in an 
+# OOo list. The goal is to inform the user of the appearance of the bullet 
+# without too much verbiage, hence simply "right-pointing arrowhead".
+#
+__characterNames[u'\u27a2'] = _("right-pointing arrowhead")
+
+# Translators:  StarOffice/OOo includes private-use unicode character U+E00A 
+# as a bullet which looks like the black square: â (U+25A0).  Therefore, 
+# please use the same translation for this character.
+#
+__characterNames[u'\ue00a'] = _("black square")
+
+# Translators:  StarOffice/OOo includes private-use unicode character U+E00C 
+# as a bullet which looks like the black diamond: â (U+25C6).  Therefore, 
+# please use the same translation for this character.
+#
+__characterNames[u'\ue00c'] = _("black diamond")
+
+def getCharacterName(character):
+    """Given a character, return its name as people might refer to it
+    in ordinary conversation.
+
+    Arguments:
+    - character: the character to get the name for
+
+    Returns a string representing the name for the character
+    """
+
+    if not isinstance(character, unicode):
+        character = character.decode("UTF-8")
+
+    try:
+        return __characterNames[character]
+    except:
+        return character
+
+if __name__ == "__main__":
+    print __characterNames
+    print "Should be black diamond:", getCharacterName(u'\ue00c')
+    print "Should be foo:", getCharacterName("foo")

Added: branches/phase2/src/orca/speech/key_names.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/key_names.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,264 @@
+# Copyright 2006-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Maps the names of keys from KeyboardEvents into localized words.
+"""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import character_names
+
+from orca.orca_i18n import _ # for gettext support
+
+# __keyNames is a dictionary where the keys represent a UTF-8
+# string for a keyboard key and the values represent the common
+# phrase used to describe the key.
+#
+__keyNames = {}
+
+# Translators: this is how someone would speak the name of the left shift key
+#
+__keyNames["Shift_L"]      = _("left shift")
+
+# Translators: this is how someone would speak the name of the left alt key
+#
+__keyNames["Alt_L"]        = _("left alt")
+
+# Translators: this is how someone would speak the name of the left ctrl key
+#
+__keyNames["Control_L"]    = _("left control")
+
+# Translators: this is how someone would speak the name of the right shift key
+#
+__keyNames["Shift_R"]      = _("right shift")
+
+# Translators: this is how someone would speak the name of the right alt key
+#
+__keyNames["Alt_R"]        = _("right alt")
+
+# Translators: this is how someone would speak the name of the right ctrl key
+#
+__keyNames["Control_R"]    = _("right control")
+
+# Translators: this is how someone would speak the name of the left meta key
+#
+__keyNames["Meta_L"]       = _("left meta")
+
+# Translators: this is how someone would speak the name of the right meta key
+#
+__keyNames["Meta_R"]       = _("right meta")
+
+# Translators: this is how someone would speak the name of the num lock key
+#
+__keyNames["Num_Lock"]     = _("num lock")
+
+# Translators: this is how someone would speak the name of the caps lock key
+#
+__keyNames["Caps_Lock"]    = _("caps lock")
+
+# Translators: this is how someone would speak the name of the scroll lock key
+#
+__keyNames["Scroll_Lock"]  = _("scroll lock")
+
+# Translators: this is how someone would speak the name of the page up key
+#
+__keyNames["Page_Up"]      = _("page up")
+
+# Translators: this is how someone would speak the name of the page up key
+#
+__keyNames["KP_Page_Up"]      = _("page up")
+
+# Translators: this is how someone would speak the name of the page up key
+#
+__keyNames["Prior"]      = _("page up")
+
+# Translators: this is how someone would speak the name of the page up key
+#
+__keyNames["KP_Prior"]      = _("page up")
+
+# Translators: this is how someone would speak the name of the page down key
+#
+__keyNames["Page_Down"]    = _("page down")
+
+# Translators: this is how someone would speak the name of the page down key
+#
+__keyNames["KP_Page_Down"]    = _("page down")
+
+# Translators: this is how someone would speak the name of the page down key
+#
+__keyNames["Next"]    = _("page down")
+
+# Translators: this is how someone would speak the name of the page down key
+#
+__keyNames["KP_Next"]    = _("page down")
+
+# Translators: this is how someone would speak the name of the tab key
+#
+__keyNames["Tab"] = _("tab")
+
+# Translators: this is how someone would speak the name of the left tab key
+#
+__keyNames["ISO_Left_Tab"] = _("left tab")
+
+# Translators: this is how someone would speak the name of the F11 key
+#
+__keyNames["SunF36"]       = _("F 11")
+
+# Translators: this is how someone would speak the name of the F12 key
+#
+__keyNames["SunF37"]       = _("F 12")
+
+# Translators: this is the spoken word for the space character
+#
+__keyNames["space"] = _("space")
+
+# Translators: this is how someone would speak the name of the backspace key
+#
+__keyNames["BackSpace"] = _("backspace")
+
+# Translators: this is how someone would speak the name of the return key
+#
+__keyNames["Return"] = _("return")
+
+# Translators: this is how someone would speak the name of the enter key
+#
+__keyNames["KP_Enter"] = _("enter")
+
+# Translators: this is how someone would speak the name of the up arrow key 
+#
+__keyNames["Up"] = _("up")
+
+# Translators: this is how someone would speak the name of the up arrow key 
+#
+__keyNames["KP_Up"] = _("up")
+
+# Translators: this is how someone would speak the name of the down arrow key 
+#
+__keyNames["Down"] = _("down")
+
+# Translators: this is how someone would speak the name of the down arrow key 
+#
+__keyNames["KP_Down"] = _("down")
+
+# Translators: this is how someone would speak the name of the left arrow key 
+#
+__keyNames["Left"] = _("left")
+
+# Translators: this is how someone would speak the name of the left arrow key 
+#
+__keyNames["KP_Left"] = _("left")
+
+# Translators: this is how someone would speak the name of the right arrow key 
+#
+__keyNames["Right"] = _("right")
+
+# Translators: this is how someone would speak the name of the right arrow key 
+#
+__keyNames["KP_Right"] = _("right")
+
+# Translators: this is how someone would speak the name of the left super key 
+#
+__keyNames["Super_L"] = _("left super")
+
+# Translators: this is how someone would speak the name of the right super key 
+#
+__keyNames["Super_R"] = _("right super")
+
+# Translators: this is how someone would speak the name of the menu key 
+#
+__keyNames["Menu"] = _("menu")
+
+# Translators: this is how someone would speak the name of the ISO shift key 
+#
+__keyNames["ISO_Level3_Shift"] = _("ISO level 3 shift")
+
+# Translators: this is how someone would speak the name of the help key 
+#
+__keyNames["Help"] = _("help")
+
+# Translators: this is how someone would speak the name of the multi key 
+#
+__keyNames["Multi_key"] = _("multi")
+
+# Translators: this is how someone would speak the name of the mode switch key 
+#
+__keyNames["Mode_switch"] = _("mode switch")
+
+# Translators: this is how someone would speak the name of the escape key 
+#
+__keyNames["Escape"] = _("escape")
+
+# Translators: this is how someone would speak the name of the insert key
+#
+__keyNames["Insert"] = _("insert")
+
+# Translators: this is how someone would speak the name of the insert key
+#
+__keyNames["KP_Insert"] = _("insert")
+
+# Translators: this is how someone would speak the name of the delete key
+#
+__keyNames["Delete"] = _("delete")
+
+# Translators: this is how someone would speak the name of the delete key
+#
+__keyNames["KP_Delete"] = _("delete")
+
+# Translators: this is how someone would speak the name of the home key
+#
+__keyNames["Home"] = _("home")
+
+# Translators: this is how someone would speak the name of the home key
+#
+__keyNames["KP_Home"] = _("home")
+
+# Translators: this is how someone would speak the name of the end key
+#
+__keyNames["End"] = _("end")
+
+# Translators: this is how someone would speak the name of the end key
+#
+__keyNames["KP_End"] = _("end")
+
+# Translators: this is how someone would speak the name of the begin key
+#
+__keyNames["KP_Begin"] = _("begin")
+
+def getKeyName(key):
+    """Given a keyboard key, return its name as people might refer to it
+    in ordinary conversation.
+
+    Arguments:
+    - key: the key to get the name for
+
+    Returns a string representing the name for the key
+    """
+
+    if isinstance(key, unicode):
+        key = key.encode("UTF-8")
+
+    try:
+        return __keyNames[key]
+    except:
+        return character_names.getCharacterName(key)
+
+if __name__ == "__main__":
+    print __keyNames
+    print "Should be mode switch:", getKeyName("Mode_switch")
+    print "Should be foo:", getKeyName("foo")

Added: branches/phase2/src/orca/speech/phonetic_names.py
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/speech/phonetic_names.py	Mon Sep 29 23:56:21 2008
@@ -0,0 +1,86 @@
+# Copyright 2006-2008 Sun Microsystems Inc.
+#
+# 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., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Provides getPhoneticName method that maps each letter of the
+alphabet into its localized phonetic equivalent."""
+
+__id__        = "$Id$"
+__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+from orca.orca_i18n import _ # for gettext support
+
+# Translators: this is a structure to assist in the generation of
+# spoken military-style spelling.  For example, 'abc' becomes 'alpha
+# bravo charlie'.
+#
+# It is a simple structure that consists of pairs of
+#
+# letter : word(s)
+#
+# where the letter and word(s) are separate by colons and each
+# pair is separated by commas.  For example, we see:
+#
+# a : alpha, b : bravo, c : charlie,
+#
+# And so on.  The complete set should consist of all the letters from
+# the alphabet for your language paired with the common
+# military/phonetic word(s) used to describe that letter.
+#
+# The Wikipedia entry
+# http://en.wikipedia.org/wiki/NATO_phonetic_alphabet has a few
+# interesting tidbits about local conventions in the sections
+# "Additions in German, Danish and Norwegian" and "Variants".
+#
+__phoneList = _("a : alpha, b : bravo, c : charlie, "
+               "d : delta, e : echo, f : foxtrot, "
+               "g : golf, h : hotel, i : india, "
+               "j : juliet, k : kilo, l : lima, "
+               "m : mike, n : november, o : oscar, "
+               "p : papa, q : quebec, r : romeo, "
+               "s : sierra, t : tango, u : uniform, "
+               "v : victor, w : whiskey, x : xray, "
+               "y : yankee, z : zulu")
+
+__phoneNames = {}
+
+for __pair in __phoneList.split(','):
+    __w = __pair.split(':')
+    __phoneNames [__w[0].strip()] = __w[1].strip()
+
+def getPhoneticName(character):
+    """Given a character, return its phonetic name, which is typically
+    the 'military' term used for the character.
+
+    Arguments:
+    - character: the character to get the military name for
+
+    Returns a string representing the military name for the character
+    """
+
+    if isinstance(character, unicode):
+        character = character.encode("UTF-8")
+
+    try:
+        return __phoneNames[character]
+    except:
+        return character
+
+if __name__ == "__main__":
+    print __phoneNames
+    print "Should be alpha:", getPhoneticName("a")
+    print "Should be foo:", getPhoneticName("foo")



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]