orca r3876 - in trunk: . src/orca src/orca/scripts src/orca/scripts/apps src/orca/scripts/apps/Thunderbird src/orca/scripts/apps/evolution src/orca/scripts/apps/gcalctool src/orca/scripts/apps/gedit src/orca/scripts/apps/gnome-window-properties src/orca/scripts/apps/pidgin src/orca/scripts/apps/planner src/orca/scripts/apps/rhythmbox src/orca/scripts/apps/soffice src/orca/scripts/toolkits src/orca/scripts/toolkits/Gecko test/harness



Author: eitani
Date: Fri May  2 21:21:19 2008
New Revision: 3876
URL: http://svn.gnome.org/viewvc/orca?rev=3876&view=rev

Log:
* configure.in: 
 pylintrc:
 src/orca/Gecko.py:
 src/orca/J2SE-access-bridge.py:
 src/orca/Makefile.am:
 src/orca/focus_tracking_presenter.py:
 src/orca/scripts/Evolution.py:
 src/orca/scripts/Makefile.am:
 src/orca/scripts/Mozilla.py:
 src/orca/scripts/StarOffice.py:
 src/orca/scripts/Thunderbird.py:
 src/orca/scripts/acroread.py:
 src/orca/scripts/apps/Makefile.am:
 src/orca/scripts/apps/Mozilla.py:
 src/orca/scripts/apps/Thunderbird/Makefile.am:
 src/orca/scripts/apps/Thunderbird/__init__.py:
 src/orca/scripts/apps/Thunderbird/script.py:
 src/orca/scripts/apps/Thunderbird/speech_generator.py:
 src/orca/scripts/apps/acroread.py:
 src/orca/scripts/apps/evolution/Makefile.am:
 src/orca/scripts/apps/evolution/__init__.py:
 src/orca/scripts/apps/evolution/script.py:
 src/orca/scripts/apps/evolution/speech_generator.py:
 src/orca/scripts/apps/evolution/where_am_i.py:
 src/orca/scripts/apps/gcalctool/Makefile.am:
 src/orca/scripts/apps/gcalctool/__init__.py:
 src/orca/scripts/apps/gcalctool/script.py:
 src/orca/scripts/apps/gcalctool/speech_generator.py:
 src/orca/scripts/apps/gcalctool/where_am_i.py:
 src/orca/scripts/apps/gdmlogin.py:
 src/orca/scripts/apps/gedit/Makefile.am:
 src/orca/scripts/apps/gedit/__init__.py:
 src/orca/scripts/apps/gedit/script.py:
 src/orca/scripts/apps/gedit/speech_generator.py:
 src/orca/scripts/apps/gnome-keyring-ask.py:
 src/orca/scripts/apps/gnome-mud.py:
 src/orca/scripts/apps/gnome-panel.py:
 src/orca/scripts/apps/gnome-search-tool.py:
 src/orca/scripts/apps/gnome-system-monitor.py:
 src/orca/scripts/apps/gnome-terminal.py:
 src/orca/scripts/apps/gnome-window-properties/Makefile.am:
 src/orca/scripts/apps/gnome-window-properties/__init__.py:
 src/orca/scripts/apps/gnome-window-properties/script.py:
 src/orca/scripts/apps/gnome-window-properties/speech_generator.py:
 src/orca/scripts/apps/gnome_segv2.py:
 src/orca/scripts/apps/liferea.py:
 src/orca/scripts/apps/metacity.py:
 src/orca/scripts/apps/nautilus.py:
 src/orca/scripts/apps/notification-daemon.py:
 src/orca/scripts/apps/pidgin/Makefile.am:
 src/orca/scripts/apps/pidgin/__init__.py:
 src/orca/scripts/apps/pidgin/constants.py:
 src/orca/scripts/apps/pidgin/script.py:
 src/orca/scripts/apps/pidgin/speech_generator.py:
 src/orca/scripts/apps/pidgin/where_am_i.py:
 src/orca/scripts/apps/planner/Makefile.am:
 src/orca/scripts/apps/planner/__init__.py:
 src/orca/scripts/apps/planner/braille_generator.py:
 src/orca/scripts/apps/planner/script.py:
 src/orca/scripts/apps/planner/speech_generator.py:
 src/orca/scripts/apps/rhythmbox/Makefile.am:
 src/orca/scripts/apps/rhythmbox/__init__.py:
 src/orca/scripts/apps/rhythmbox/braille_generator.py:
 src/orca/scripts/apps/rhythmbox/script.py:
 src/orca/scripts/apps/rhythmbox/speech_generator.py:
 src/orca/scripts/apps/soffice/Makefile.am:
 src/orca/scripts/apps/soffice/__init__.py:
 src/orca/scripts/apps/soffice/braille_generator.py:
 src/orca/scripts/apps/soffice/constants.py:
 src/orca/scripts/apps/soffice/script.py:
 src/orca/scripts/apps/soffice/speech_generator.py:
 src/orca/scripts/apps/soffice/where_am_i.py:
 src/orca/scripts/gaim.py:
 src/orca/scripts/gcalctool.py:
 src/orca/scripts/gdmlogin.py:
 src/orca/scripts/gedit.py:
 src/orca/scripts/gnome-keyring-ask.py:
 src/orca/scripts/gnome-mud.py:
 src/orca/scripts/gnome-panel.py:
 src/orca/scripts/gnome-search-tool.py:
 src/orca/scripts/gnome-system-monitor.py:
 src/orca/scripts/gnome-terminal.py:
 src/orca/scripts/gnome-window-properties.py:
 src/orca/scripts/gnome_segv2.py:
 src/orca/scripts/liferea.py:
 src/orca/scripts/metacity.py:
 src/orca/scripts/nautilus.py:
 src/orca/scripts/notification-daemon.py:
 src/orca/scripts/planner.py:
 src/orca/scripts/rhythmbox.py:
 src/orca/scripts/toolkits/GAIL.py:
 src/orca/scripts/toolkits/Gecko/Makefile.am:
 src/orca/scripts/toolkits/Gecko/__init__.py:
 src/orca/scripts/toolkits/Gecko/bookmarks.py:
 src/orca/scripts/toolkits/Gecko/braille_generator.py:
 src/orca/scripts/toolkits/Gecko/constants.py:
 src/orca/scripts/toolkits/Gecko/script.py:
 src/orca/scripts/toolkits/Gecko/speech_generator.py:
 src/orca/scripts/toolkits/Gecko/where_am_i.py:
 src/orca/scripts/toolkits/J2SE-access-bridge.py:
 src/orca/scripts/toolkits/Makefile.am:
 src/orca/scripts/toolkits/VCL.py:
 src/orca/settings.py:
 test/harness/orca-customizations.py.in:
 Fixed bug #528147: Broke up multi-class scripts into packages. 
 Put toolkit scripts into their own directory, and application 
 scripts into one too.


Added:
   trunk/src/orca/scripts/apps/
   trunk/src/orca/scripts/apps/Makefile.am
      - copied, changed from r3875, /trunk/src/orca/scripts/Makefile.am
   trunk/src/orca/scripts/apps/Mozilla.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/Thunderbird/
   trunk/src/orca/scripts/apps/Thunderbird/Makefile.am
   trunk/src/orca/scripts/apps/Thunderbird/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/Thunderbird/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Thunderbird.py
   trunk/src/orca/scripts/apps/Thunderbird/speech_generator.py
      - copied, changed from r3875, /trunk/src/orca/scripts/notification-daemon.py
   trunk/src/orca/scripts/apps/__init__.py
   trunk/src/orca/scripts/apps/acroread.py
      - copied, changed from r3875, /trunk/src/orca/scripts/acroread.py
   trunk/src/orca/scripts/apps/evolution/
   trunk/src/orca/scripts/apps/evolution/Makefile.am
   trunk/src/orca/scripts/apps/evolution/__init__.py
   trunk/src/orca/scripts/apps/evolution/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Evolution.py
   trunk/src/orca/scripts/apps/evolution/speech_generator.py
   trunk/src/orca/scripts/apps/evolution/where_am_i.py
   trunk/src/orca/scripts/apps/gcalctool/
   trunk/src/orca/scripts/apps/gcalctool/Makefile.am
   trunk/src/orca/scripts/apps/gcalctool/__init__.py
   trunk/src/orca/scripts/apps/gcalctool/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gcalctool.py
   trunk/src/orca/scripts/apps/gcalctool/speech_generator.py
   trunk/src/orca/scripts/apps/gcalctool/where_am_i.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/gdmlogin.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gdmlogin.py
   trunk/src/orca/scripts/apps/gedit/
   trunk/src/orca/scripts/apps/gedit/Makefile.am
   trunk/src/orca/scripts/apps/gedit/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/gedit/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gedit.py
   trunk/src/orca/scripts/apps/gedit/speech_generator.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-window-properties.py
   trunk/src/orca/scripts/apps/gnome-keyring-ask.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py
   trunk/src/orca/scripts/apps/gnome-mud.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-mud.py
   trunk/src/orca/scripts/apps/gnome-panel.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-panel.py
   trunk/src/orca/scripts/apps/gnome-search-tool.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-search-tool.py
   trunk/src/orca/scripts/apps/gnome-system-monitor.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-system-monitor.py
   trunk/src/orca/scripts/apps/gnome-terminal.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-terminal.py
   trunk/src/orca/scripts/apps/gnome-window-properties/
   trunk/src/orca/scripts/apps/gnome-window-properties/Makefile.am
   trunk/src/orca/scripts/apps/gnome-window-properties/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/gnome-window-properties/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py
   trunk/src/orca/scripts/apps/gnome-window-properties/speech_generator.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-window-properties.py
   trunk/src/orca/scripts/apps/gnome_segv2.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome_segv2.py
   trunk/src/orca/scripts/apps/liferea.py
      - copied, changed from r3875, /trunk/src/orca/scripts/liferea.py
   trunk/src/orca/scripts/apps/metacity.py
      - copied, changed from r3875, /trunk/src/orca/scripts/metacity.py
   trunk/src/orca/scripts/apps/nautilus.py
      - copied, changed from r3875, /trunk/src/orca/scripts/nautilus.py
   trunk/src/orca/scripts/apps/notification-daemon.py
      - copied, changed from r3875, /trunk/src/orca/scripts/notification-daemon.py
   trunk/src/orca/scripts/apps/pidgin/
   trunk/src/orca/scripts/apps/pidgin/Makefile.am
   trunk/src/orca/scripts/apps/pidgin/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/pidgin/constants.py
   trunk/src/orca/scripts/apps/pidgin/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gaim.py
   trunk/src/orca/scripts/apps/pidgin/speech_generator.py
   trunk/src/orca/scripts/apps/pidgin/where_am_i.py
   trunk/src/orca/scripts/apps/planner/
   trunk/src/orca/scripts/apps/planner/Makefile.am
   trunk/src/orca/scripts/apps/planner/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/planner/braille_generator.py
   trunk/src/orca/scripts/apps/planner/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py
   trunk/src/orca/scripts/apps/planner/speech_generator.py
   trunk/src/orca/scripts/apps/rhythmbox/
   trunk/src/orca/scripts/apps/rhythmbox/Makefile.am
   trunk/src/orca/scripts/apps/rhythmbox/__init__.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/apps/rhythmbox/braille_generator.py
   trunk/src/orca/scripts/apps/rhythmbox/script.py
   trunk/src/orca/scripts/apps/rhythmbox/speech_generator.py
   trunk/src/orca/scripts/apps/soffice/
   trunk/src/orca/scripts/apps/soffice/Makefile.am
   trunk/src/orca/scripts/apps/soffice/__init__.py
   trunk/src/orca/scripts/apps/soffice/braille_generator.py
   trunk/src/orca/scripts/apps/soffice/constants.py
   trunk/src/orca/scripts/apps/soffice/script.py
      - copied, changed from r3875, /trunk/src/orca/scripts/StarOffice.py
   trunk/src/orca/scripts/apps/soffice/speech_generator.py
   trunk/src/orca/scripts/apps/soffice/where_am_i.py
   trunk/src/orca/scripts/toolkits/
   trunk/src/orca/scripts/toolkits/GAIL.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/toolkits/Gecko/
   trunk/src/orca/scripts/toolkits/Gecko/Makefile.am
   trunk/src/orca/scripts/toolkits/Gecko/__init__.py
   trunk/src/orca/scripts/toolkits/Gecko/bookmarks.py
   trunk/src/orca/scripts/toolkits/Gecko/braille_generator.py
   trunk/src/orca/scripts/toolkits/Gecko/constants.py
   trunk/src/orca/scripts/toolkits/Gecko/script.py
      - copied, changed from r3875, /trunk/src/orca/Gecko.py
   trunk/src/orca/scripts/toolkits/Gecko/speech_generator.py
   trunk/src/orca/scripts/toolkits/Gecko/where_am_i.py
   trunk/src/orca/scripts/toolkits/J2SE-access-bridge.py
      - copied, changed from r3875, /trunk/src/orca/J2SE-access-bridge.py
   trunk/src/orca/scripts/toolkits/Makefile.am
   trunk/src/orca/scripts/toolkits/VCL.py
      - copied, changed from r3875, /trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/toolkits/__init__.py
Removed:
   trunk/src/orca/Gecko.py
   trunk/src/orca/J2SE-access-bridge.py
   trunk/src/orca/scripts/Evolution.py
   trunk/src/orca/scripts/Mozilla.py
   trunk/src/orca/scripts/StarOffice.py
   trunk/src/orca/scripts/Thunderbird.py
   trunk/src/orca/scripts/acroread.py
   trunk/src/orca/scripts/gaim.py
   trunk/src/orca/scripts/gcalctool.py
   trunk/src/orca/scripts/gdmlogin.py
   trunk/src/orca/scripts/gedit.py
   trunk/src/orca/scripts/gnome-keyring-ask.py
   trunk/src/orca/scripts/gnome-mud.py
   trunk/src/orca/scripts/gnome-panel.py
   trunk/src/orca/scripts/gnome-search-tool.py
   trunk/src/orca/scripts/gnome-system-monitor.py
   trunk/src/orca/scripts/gnome-terminal.py
   trunk/src/orca/scripts/gnome-window-properties.py
   trunk/src/orca/scripts/gnome_segv2.py
   trunk/src/orca/scripts/liferea.py
   trunk/src/orca/scripts/metacity.py
   trunk/src/orca/scripts/nautilus.py
   trunk/src/orca/scripts/notification-daemon.py
   trunk/src/orca/scripts/planner.py
   trunk/src/orca/scripts/rhythmbox.py
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/pylintrc
   trunk/src/orca/Makefile.am
   trunk/src/orca/focus_tracking_presenter.py
   trunk/src/orca/scripts/Makefile.am
   trunk/src/orca/settings.py
   trunk/test/harness/orca-customizations.py.in

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Fri May  2 21:21:19 2008
@@ -175,6 +175,18 @@
 src/louis/constants.py
 src/orca/Makefile
 src/orca/scripts/Makefile
+src/orca/scripts/apps/Makefile
+src/orca/scripts/apps/soffice/Makefile
+src/orca/scripts/apps/evolution/Makefile
+src/orca/scripts/apps/gcalctool/Makefile
+src/orca/scripts/apps/pidgin/Makefile
+src/orca/scripts/apps/planner/Makefile
+src/orca/scripts/apps/rhythmbox/Makefile
+src/orca/scripts/apps/Thunderbird/Makefile
+src/orca/scripts/apps/gedit/Makefile
+src/orca/scripts/apps/gnome-window-properties/Makefile
+src/orca/scripts/toolkits/Makefile
+src/orca/scripts/toolkits/Gecko/Makefile
 src/orca/orca
 src/orca/orca_i18n.py
 src/orca/platform.py

Modified: trunk/pylintrc
==============================================================================
--- trunk/pylintrc	(original)
+++ trunk/pylintrc	Fri May  2 21:21:19 2008
@@ -64,6 +64,7 @@
 #
 # W0102: Default argument is a mutable value (list or dictionary)
 # W0141: Used builtin function 'map'
+# W0401: Wildcard import constants
 # W0403: Relative import
 # W0511: Warning note (FIXME or XXX) detected.
 # W0603: Using the global statement
@@ -85,7 +86,7 @@
 # R0914: Function or method has too many local variables
 # R0915: Function or method has too many statements
 #
-disable-msg=E0611,C0111,R0201,W0102,W0141,W0403,W0603,W0612,W0613,W0702,W0704,W0511,R0801,R0912,R0915,R0914,R0904,R0903,R0401,R0911,R0913,C0302,R0902
+disable-msg=E0611,C0111,R0201,W0102,W0141,W0401,W0403,W0603,W0612,W0613,W0702,W0704,W0511,R0801,R0912,R0915,R0914,R0904,R0903,R0401,R0911,R0913,C0302,R0902
 
 
 [REPORTS]

Modified: trunk/src/orca/Makefile.am
==============================================================================
--- trunk/src/orca/Makefile.am	(original)
+++ trunk/src/orca/Makefile.am	Fri May  2 21:21:19 2008
@@ -25,11 +25,9 @@
 	find.py \
 	flat_review.py \
 	focus_tracking_presenter.py \
-	Gecko.py \
 	gnomespeechfactory.py \
 	httpserver.py \
 	input_event.py \
-	J2SE-access-bridge.py \
 	keybindings.py \
 	keynames.py \
 	liveregions.py \

Modified: trunk/src/orca/focus_tracking_presenter.py
==============================================================================
--- trunk/src/orca/focus_tracking_presenter.py	(original)
+++ trunk/src/orca/focus_tracking_presenter.py	Fri May  2 21:21:19 2008
@@ -240,26 +240,31 @@
         # package for now.
         #
         if (not script) and app and getattr(app, "toolkitName", None):
-            try:
-                debug.println(
-                    debug.LEVEL_FINE,
-                    "Looking for toolkit script %s.py..." % app.toolkitName)
-                module = __import__(app.toolkitName,
-                                    globals(),
-                                    locals(),
-                                    [''])
-                script = module.Script(app)
-                debug.println(debug.LEVEL_FINE,
-                              "...found %s.py" % name)
-            except ImportError:
-                debug.println(
-                    debug.LEVEL_FINE,
-                    "...could not find %s.py" % app.toolkitName)
-            except:
-                debug.printException(debug.LEVEL_SEVERE)
-                debug.println(
-                    debug.LEVEL_SEVERE,
-                    "While attempting to import %s" % app.toolkitName)
+            for package in scriptPackages:
+                if package:
+                    name = '.'.join((package, app.toolkitName))
+                else:
+                    name = app.toolkitName
+                try:
+                    debug.println(
+                        debug.LEVEL_FINE,
+                        "Looking for toolkit script %s.py..." % app.toolkitName)
+                    module = __import__(name,
+                                        globals(),
+                                        locals(),
+                                        [''])
+                    script = module.Script(app)
+                    debug.println(debug.LEVEL_FINE,
+                                  "...found %s.py" % name)
+                except ImportError:
+                    debug.println(
+                        debug.LEVEL_FINE,
+                        "...could not find %s.py" % app.toolkitName)
+                except:
+                    debug.printException(debug.LEVEL_SEVERE)
+                    debug.println(
+                        debug.LEVEL_SEVERE,
+                        "While attempting to import %s" % app.toolkitName)
 
         if not script:
             script = default.Script(app)

Modified: trunk/src/orca/scripts/Makefile.am
==============================================================================
--- trunk/src/orca/scripts/Makefile.am	(original)
+++ trunk/src/orca/scripts/Makefile.am	Fri May  2 21:21:19 2008
@@ -1,31 +1,10 @@
+SUBDIRS = apps toolkits
+
 orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
 	__init__.py \
-	acroread.py \
-	Evolution.py \
-	gaim.py \
-	gcalctool.py \
-	gdmlogin.py \
-	gedit.py \
-	gnome_segv2.py \
-	gnome-keyring-ask.py \
-	gnome-mud.py \
-	gnome-panel.py \
-	gnome-search-tool.py \
-	gnome-system-monitor.py \
-	gnome-terminal.py \
-	gnome-window-properties.py \
-	liferea.py \
-	metacity.py \
-	Mozilla.py \
-	nautilus.py \
-	notification-daemon.py \
-	planner.py \
-	rhythmbox.py \
-	self_voicing.py \
-	StarOffice.py \
-	Thunderbird.py
+	self_voicing.py
 
 orca_pythondir=$(pyexecdir)/orca/scripts
 

Copied: trunk/src/orca/scripts/apps/Makefile.am (from r3875, /trunk/src/orca/scripts/Makefile.am)
==============================================================================
--- /trunk/src/orca/scripts/Makefile.am	(original)
+++ trunk/src/orca/scripts/apps/Makefile.am	Fri May  2 21:21:19 2008
@@ -1,31 +1,32 @@
+SUBDIRS = \
+	soffice \
+	evolution \
+	gcalctool \
+	pidgin \
+	planner \
+	rhythmbox \
+	Thunderbird \
+	gedit \
+	gnome-window-properties
+
 orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
 	__init__.py \
 	acroread.py \
-	Evolution.py \
-	gaim.py \
-	gcalctool.py \
 	gdmlogin.py \
-	gedit.py \
-	gnome_segv2.py \
 	gnome-keyring-ask.py \
 	gnome-mud.py \
 	gnome-panel.py \
 	gnome-search-tool.py \
+	gnome_segv2.py \
 	gnome-system-monitor.py \
 	gnome-terminal.py \
-	gnome-window-properties.py \
 	liferea.py \
 	metacity.py \
 	Mozilla.py \
 	nautilus.py \
-	notification-daemon.py \
-	planner.py \
-	rhythmbox.py \
-	self_voicing.py \
-	StarOffice.py \
-	Thunderbird.py
+	notification-daemon.py
 
-orca_pythondir=$(pyexecdir)/orca/scripts
+orca_pythondir=$(pyexecdir)/orca/scripts/apps
 

Copied: trunk/src/orca/scripts/apps/Mozilla.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================

Added: trunk/src/orca/scripts/apps/Thunderbird/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/Thunderbird/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,9 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	script.py \
+	speech_generator.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/Thunderbird
+

Copied: trunk/src/orca/scripts/apps/Thunderbird/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/Thunderbird/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2004-2007 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
@@ -17,20 +17,13 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+""" Custom script for Thunderbird 3.
+"""
 
-__id__        = "$Id$"
-__version__   = "$Revision$"
-__date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__id__        = "$Id: $"
+__version__   = "$Revision: $"
+__date__      = "$Date: $"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script

Copied: trunk/src/orca/scripts/apps/Thunderbird/script.py (from r3875, /trunk/src/orca/scripts/Thunderbird.py)
==============================================================================
--- /trunk/src/orca/scripts/Thunderbird.py	(original)
+++ trunk/src/orca/scripts/apps/Thunderbird/script.py	Fri May  2 21:21:19 2008
@@ -32,32 +32,11 @@
 import orca.debug as debug
 import orca.default as default
 import orca.speech as speech
-import orca.Gecko as Gecko
+import orca.scripts.toolkits.Gecko as Gecko
 
 from orca.orca_i18n import _
 
-########################################################################
-#                                                                      #
-# Custom SpeechGenerator for Thunderbird                               #
-#                                                                      #
-########################################################################
-
-class SpeechGenerator(Gecko.SpeechGenerator):
-    """Provides a speech generator specific to Thunderbird.
-    """
-
-    def __init__(self, script):
-        # Set the debug level for all the methods in this script.
-        #
-        self.debugLevel = debug.LEVEL_FINEST
-
-        self._debug("__init__")
-        Gecko.SpeechGenerator.__init__(self, script)
-
-    def _debug(self, msg):
-        """ Convenience method for printing debug messages
-        """
-        debug.println(self.debugLevel, "Thunderbird.SpeechGenerator: "+msg)
+from speech_generator import SpeechGenerator
 
 ########################################################################
 #                                                                      #

Copied: trunk/src/orca/scripts/apps/Thunderbird/speech_generator.py (from r3875, /trunk/src/orca/scripts/notification-daemon.py)
==============================================================================
--- /trunk/src/orca/scripts/notification-daemon.py	(original)
+++ trunk/src/orca/scripts/apps/Thunderbird/speech_generator.py	Fri May  2 21:21:19 2008
@@ -17,50 +17,38 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-""" Custom script for The notification daemon.
+""" Custom script for Thunderbird 3.
 """
 
-__id__        = ""
-__version__   = ""
-__date__      = ""
+__id__        = "$Id: $"
+__version__   = "$Revision: $"
+__date__      = "$Date: $"
 __copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
-import orca.speech as speech
-import pyatspi
+import orca.debug as debug
+import orca.scripts.toolkits.Gecko as Gecko
 
-from orca.orca_i18n import _
 
 ########################################################################
 #                                                                      #
-# The notification-daemon script class.                                #
+# Custom SpeechGenerator for Thunderbird                               #
 #                                                                      #
 ########################################################################
 
-class Script(default.Script):
-    def getListeners(self):
-        """Sets up the AT-SPI event listeners for this script.
-        """
-        listeners = default.Script.getListeners(self)
-
-        listeners["window:create"] = \
-            self.onWindowCreate
+class SpeechGenerator(Gecko.SpeechGenerator):
+    """Provides a speech generator specific to Thunderbird.
+    """
 
-        return listeners
+    def __init__(self, script):
+        # Set the debug level for all the methods in this script.
+        #
+        self.debugLevel = debug.LEVEL_FINEST
 
-    def onWindowCreate(self, event):
-        """Called whenever a window is created in the notification-daemon
-        application.
+        self._debug("__init__")
+        Gecko.SpeechGenerator.__init__(self, script)
 
-        Arguments:
-        - event: the Event.
+    def _debug(self, msg):
+        """ Convenience method for printing debug messages
         """
-        a = self.findByRole(event.source, pyatspi.ROLE_LABEL)
-        print a
-        texts = [self.getDisplayedText(acc) for acc in a]
-        # Translators: This denotes a notification to the user of some sort.
-        #
-        text = _('Notification %s') % ' '.join(texts)
-        speech.speak(text, None, True)
-
+        debug.println(self.debugLevel, "Thunderbird.SpeechGenerator: "+msg)

Added: trunk/src/orca/scripts/apps/__init__.py
==============================================================================

Copied: trunk/src/orca/scripts/apps/acroread.py (from r3875, /trunk/src/orca/scripts/acroread.py)
==============================================================================

Added: trunk/src/orca/scripts/apps/evolution/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/evolution/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,10 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	script.py \
+	speech_generator.py \
+	where_am_i.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/evolution
+

Added: trunk/src/orca/scripts/apps/evolution/__init__.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/evolution/__init__.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,22 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Evolution."""
+
+from script import Script

Copied: trunk/src/orca/scripts/apps/evolution/script.py (from r3875, /trunk/src/orca/scripts/Evolution.py)
==============================================================================
--- /trunk/src/orca/scripts/Evolution.py	(original)
+++ trunk/src/orca/scripts/apps/evolution/script.py	Fri May  2 21:21:19 2008
@@ -36,246 +36,14 @@
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.speech as speech
-import orca.speechgenerator as speechgenerator
 import orca.speechserver as speechserver
 import orca.settings as settings
 import orca.chnames as chnames
-import orca.where_am_I as where_am_I
 
 from orca.orca_i18n import _ # for gettext support
 
-class WhereAmI(where_am_I.WhereAmI):
-
-    def __init__(self, script):
-        """Create a new WhereAmI that will be used to speak information
-        about the current object of interest.
-        """
-
-        where_am_I.WhereAmI.__init__(self, script)
-
-    def _getTableCell(self, obj):
-        """Get the speech utterances for a single table cell.
-        """
-
-        # Don't speak check box cells that area not checked.
-        notChecked = False
-        try:
-            action = obj.queryAction()
-        except NotImplementedError:
-            action = None
-
-        if action:
-            for i in range(0, action.nActions):
-                # Translators: this is the action name for
-                # the 'toggle' action. It must be the same
-                # string used in the *.po file for gail.
-                #
-                if action.getName(i) in ["toggle", _("toggle")]:
-                    if not obj.getState().contains(pyatspi.STATE_CHECKED):
-                        notChecked = True
-                    break
-
-        if notChecked:
-            return ""
-
-        descendant = self._script.getRealActiveDescendant(obj)
-        text = self._script.getDisplayedText(descendant)
-
-        # For Evolution mail header list.
-        if text == "Status":
-            # Translators: this in reference to an e-mail message status of
-            # having been read or unread.
-            #
-            text = _("Read")
-
-        debug.println(self._debugLevel, "cell=<%s>" % text)
-
-        return text
-
-    def _hasTextSelections(self, obj):
-        """Return an indication of whether this object has selected text.
-        Note that it's possible that this object has no text, but is part
-        of a selected text area. Because of this, we need to check the
-        objects on either side to see if they are none zero length and 
-        have text selections.
-
-        Arguments:
-        - obj: the text object to start checking for selected text.
-
-        Returns: an indication of whether this object has selected text,
-        or adjacent text objects have selected text.
-        """
-
-        currentSelected = False
-        otherSelected = False
-        nSelections = obj.queryText().getNSelections()
-        if nSelections:
-            currentSelected = True
-        else:
-            otherSelected = False
-            displayedText = obj.queryText().getText(0, -1)
-            if len(displayedText) == 0:
-                container = obj.parent.parent
-                current = obj.parent.getIndexInParent()
-                morePossibleSelections = True
-                while morePossibleSelections:
-                    morePossibleSelections = False
-                    if (current-1) >= 0:
-                        prevPanel = container[current-1]
-                        prevObj = prevPanel[0]
-                        try:
-                            prevObjText = prevObj.queryText()
-                        except:
-                            prevObjText = None
-
-                        if prevObj and prevObjText:
-                            if prevObjText.getNSelections() > 0:
-                                otherSelected = True
-                            else:
-                                displayedText = prevObjText.getText(0, -1)
-                                if len(displayedText) == 0:
-                                    current -= 1
-                                    morePossibleSelections = True
-
-                current = obj.parent.getIndexInParent()
-                morePossibleSelections = True
-                while morePossibleSelections:
-                    morePossibleSelections = False
-                    if (current+1) < container.childCount:
-                        nextPanel = container[current+1]
-                        nextObj = nextPanel[0]
-                        try:
-                            nextObjText = nextObj.queryText()
-                        except:
-                            nextObjText = None
-
-                        if nextObj and nextObjText:
-                            if nextObjText.getNSelections() > 0:
-                                otherSelected = True
-                            else:
-                                displayedText = nextObjText.getText(0, -1)
-                                if len(displayedText) == 0:
-                                    current += 1
-                                    morePossibleSelections = True
-
-        return [currentSelected, otherSelected]
-
-    def _getTextSelections(self, obj, doubleClick):
-        """Get all the text applicable text selections for the given object.
-        If the user doubleclicked, look to see if there are any previous
-        or next text objects that also have selected text and add in their
-        text contents.
-
-        Arguments:
-        - obj: the text object to start extracting the selected text from.
-        - doubleClick: True if the user double-clicked the "where am I" key.
-
-        Returns: all the selected text contents plus the start and end
-        offsets within the text for the given object.
-        """
-
-        textContents = ""
-        startOffset = 0
-        endOffset = 0
-        if obj.queryText().getNSelections() > 0:
-            [textContents, startOffset, endOffset] = \
-                                            self._getTextSelection(obj)
-
-        if doubleClick:
-            # Unfortunately, Evolution doesn't use the FLOWS_FROM and 
-            # FLOWS_TO relationships to easily allow us to get to previous 
-            # and next text objects. Instead we have to move up the
-            # component hierarchy until we get to the object containing all
-            # the panels (with each line containing a single text item).
-            # We can then check in both directions to see if there is other
-            # contiguous text that is selected. We also have to jump over 
-            # zero length (empty) text lines and continue checking on the 
-            # other side.
-            #
-            container = obj.parent.parent
-            current = obj.parent.getIndexInParent()
-            morePossibleSelections = True
-            while morePossibleSelections:
-                morePossibleSelections = False
-                if (current-1) >= 0:
-                    prevPanel = container[current-1]
-                    try:
-                        prevObj = prevPanel[0]
-                        displayedText = prevObj.queryText().getText(0, -1)
-                        if len(displayedText) == 0:
-                            current -= 1
-                            morePossibleSelections = True
-                        elif prevObj.queryText().getNSelections() > 0:
-                            [newTextContents, start, end] = \
-                                         self._getTextSelection(prevObj)
-                            textContents = newTextContents + " " + textContents
-                            current -= 1
-                            morePossibleSelections = True
-                    except:
-                        pass
-
-            current = obj.parent.getIndexInParent()
-            morePossibleSelections = True
-            while morePossibleSelections:
-                morePossibleSelections = False
-                if (current+1) < container.childCount:
-                    nextPanel = container[current+1]
-                    try:
-                        nextObj = nextPanel[0]
-                        displayedText = nextObj.queryText().getText(0, -1)
-                        if len(displayedText) == 0:
-                            current += 1
-                            morePossibleSelections = True
-                        elif nextObj.queryText().getNSelections() > 0:
-                            [newTextContents, start, end] = \
-                                         self._getTextSelection(nextObj)
-                            textContents += " " + newTextContents
-                            current += 1
-                            morePossibleSelections = True
-                    except:
-                        pass
-
-        return [textContents, startOffset, endOffset]
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Overrides _getSpeechForTableCell so that, if this is an expanded 
-       table cell,  we can strip off the "0 items".
-    """
-
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-
-    def _getSpeechForTableCell(self, obj, already_focused):
-        """Get the speech utterances for a single table cell
-
-        Arguments:
-        - obj: the table
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = speechgenerator.SpeechGenerator.\
-                      _getSpeechForTableCell(self, obj, already_focused)
-
-        # Check that we are in a table cell in the mail message header list.
-        # If we are and this table cell has an expanded state, and the first
-        # token of the last utterances is "0", then strip off that last 
-        # utterance ("0 items"). See bug #432308 for more details.
-        #
-        rolesList = [pyatspi.ROLE_TABLE_CELL, \
-                     pyatspi.ROLE_TREE_TABLE, \
-                     pyatspi.ROLE_UNKNOWN]
-        if self._script.isDesiredFocusedItem(obj, rolesList):
-            state = obj.getState()
-            if state and state.contains(pyatspi.STATE_EXPANDABLE):
-                if state.contains(pyatspi.STATE_EXPANDED):
-                    tokens = utterances[-1].split()
-                    if tokens[0] == "0":
-                        utterances = utterances[0:-1]
-
-        return utterances
-
+from where_am_i import WhereAmI
+from speech_generator import SpeechGenerator
 ########################################################################
 #                                                                      #
 # The Evolution script class.                                          #

Added: trunk/src/orca/scripts/apps/evolution/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/evolution/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,69 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Evolution."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.speechgenerator as speechgenerator
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Overrides _getSpeechForTableCell so that, if this is an expanded 
+       table cell,  we can strip off the "0 items".
+    """
+
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    def _getSpeechForTableCell(self, obj, already_focused):
+        """Get the speech utterances for a single table cell
+
+        Arguments:
+        - obj: the table
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = speechgenerator.SpeechGenerator.\
+                      _getSpeechForTableCell(self, obj, already_focused)
+
+        # Check that we are in a table cell in the mail message header list.
+        # If we are and this table cell has an expanded state, and the first
+        # token of the last utterances is "0", then strip off that last 
+        # utterance ("0 items"). See bug #432308 for more details.
+        #
+        rolesList = [pyatspi.ROLE_TABLE_CELL, \
+                     pyatspi.ROLE_TREE_TABLE, \
+                     pyatspi.ROLE_UNKNOWN]
+        if self._script.isDesiredFocusedItem(obj, rolesList):
+            state = obj.getState()
+            if state and state.contains(pyatspi.STATE_EXPANDABLE):
+                if state.contains(pyatspi.STATE_EXPANDED):
+                    tokens = utterances[-1].split()
+                    if tokens[0] == "0":
+                        utterances = utterances[0:-1]
+
+        return utterances

Added: trunk/src/orca/scripts/apps/evolution/where_am_i.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/evolution/where_am_i.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,226 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Evolution."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.debug as debug
+import orca.where_am_I as where_am_I
+
+from orca.orca_i18n import _ # for gettext support
+
+class WhereAmI(where_am_I.WhereAmI):
+
+    def __init__(self, script):
+        """Create a new WhereAmI that will be used to speak information
+        about the current object of interest.
+        """
+
+        where_am_I.WhereAmI.__init__(self, script)
+
+    def _getTableCell(self, obj):
+        """Get the speech utterances for a single table cell.
+        """
+
+        # Don't speak check box cells that area not checked.
+        notChecked = False
+        try:
+            action = obj.queryAction()
+        except NotImplementedError:
+            action = None
+
+        if action:
+            for i in range(0, action.nActions):
+                # Translators: this is the action name for
+                # the 'toggle' action. It must be the same
+                # string used in the *.po file for gail.
+                #
+                if action.getName(i) in ["toggle", _("toggle")]:
+                    if not obj.getState().contains(pyatspi.STATE_CHECKED):
+                        notChecked = True
+                    break
+
+        if notChecked:
+            return ""
+
+        descendant = self._script.getRealActiveDescendant(obj)
+        text = self._script.getDisplayedText(descendant)
+
+        # For Evolution mail header list.
+        if text == "Status":
+            # Translators: this in reference to an e-mail message status of
+            # having been read or unread.
+            #
+            text = _("Read")
+
+        debug.println(self._debugLevel, "cell=<%s>" % text)
+
+        return text
+
+    def _hasTextSelections(self, obj):
+        """Return an indication of whether this object has selected text.
+        Note that it's possible that this object has no text, but is part
+        of a selected text area. Because of this, we need to check the
+        objects on either side to see if they are none zero length and 
+        have text selections.
+
+        Arguments:
+        - obj: the text object to start checking for selected text.
+
+        Returns: an indication of whether this object has selected text,
+        or adjacent text objects have selected text.
+        """
+
+        currentSelected = False
+        otherSelected = False
+        nSelections = obj.queryText().getNSelections()
+        if nSelections:
+            currentSelected = True
+        else:
+            otherSelected = False
+            displayedText = obj.queryText().getText(0, -1)
+            if len(displayedText) == 0:
+                container = obj.parent.parent
+                current = obj.parent.getIndexInParent()
+                morePossibleSelections = True
+                while morePossibleSelections:
+                    morePossibleSelections = False
+                    if (current-1) >= 0:
+                        prevPanel = container[current-1]
+                        prevObj = prevPanel[0]
+                        try:
+                            prevObjText = prevObj.queryText()
+                        except:
+                            prevObjText = None
+
+                        if prevObj and prevObjText:
+                            if prevObjText.getNSelections() > 0:
+                                otherSelected = True
+                            else:
+                                displayedText = prevObjText.getText(0, -1)
+                                if len(displayedText) == 0:
+                                    current -= 1
+                                    morePossibleSelections = True
+
+                current = obj.parent.getIndexInParent()
+                morePossibleSelections = True
+                while morePossibleSelections:
+                    morePossibleSelections = False
+                    if (current+1) < container.childCount:
+                        nextPanel = container[current+1]
+                        nextObj = nextPanel[0]
+                        try:
+                            nextObjText = nextObj.queryText()
+                        except:
+                            nextObjText = None
+
+                        if nextObj and nextObjText:
+                            if nextObjText.getNSelections() > 0:
+                                otherSelected = True
+                            else:
+                                displayedText = nextObjText.getText(0, -1)
+                                if len(displayedText) == 0:
+                                    current += 1
+                                    morePossibleSelections = True
+
+        return [currentSelected, otherSelected]
+
+    def _getTextSelections(self, obj, doubleClick):
+        """Get all the text applicable text selections for the given object.
+        If the user doubleclicked, look to see if there are any previous
+        or next text objects that also have selected text and add in their
+        text contents.
+
+        Arguments:
+        - obj: the text object to start extracting the selected text from.
+        - doubleClick: True if the user double-clicked the "where am I" key.
+
+        Returns: all the selected text contents plus the start and end
+        offsets within the text for the given object.
+        """
+
+        textContents = ""
+        startOffset = 0
+        endOffset = 0
+        if obj.queryText().getNSelections() > 0:
+            [textContents, startOffset, endOffset] = \
+                                            self._getTextSelection(obj)
+
+        if doubleClick:
+            # Unfortunately, Evolution doesn't use the FLOWS_FROM and 
+            # FLOWS_TO relationships to easily allow us to get to previous 
+            # and next text objects. Instead we have to move up the
+            # component hierarchy until we get to the object containing all
+            # the panels (with each line containing a single text item).
+            # We can then check in both directions to see if there is other
+            # contiguous text that is selected. We also have to jump over 
+            # zero length (empty) text lines and continue checking on the 
+            # other side.
+            #
+            container = obj.parent.parent
+            current = obj.parent.getIndexInParent()
+            morePossibleSelections = True
+            while morePossibleSelections:
+                morePossibleSelections = False
+                if (current-1) >= 0:
+                    prevPanel = container[current-1]
+                    try:
+                        prevObj = prevPanel[0]
+                        displayedText = prevObj.queryText().getText(0, -1)
+                        if len(displayedText) == 0:
+                            current -= 1
+                            morePossibleSelections = True
+                        elif prevObj.queryText().getNSelections() > 0:
+                            [newTextContents, start, end] = \
+                                         self._getTextSelection(prevObj)
+                            textContents = newTextContents + " " + textContents
+                            current -= 1
+                            morePossibleSelections = True
+                    except:
+                        pass
+
+            current = obj.parent.getIndexInParent()
+            morePossibleSelections = True
+            while morePossibleSelections:
+                morePossibleSelections = False
+                if (current+1) < container.childCount:
+                    nextPanel = container[current+1]
+                    try:
+                        nextObj = nextPanel[0]
+                        displayedText = nextObj.queryText().getText(0, -1)
+                        if len(displayedText) == 0:
+                            current += 1
+                            morePossibleSelections = True
+                        elif nextObj.queryText().getNSelections() > 0:
+                            [newTextContents, start, end] = \
+                                         self._getTextSelection(nextObj)
+                            textContents += " " + newTextContents
+                            current += 1
+                            morePossibleSelections = True
+                    except:
+                        pass
+
+        return [textContents, startOffset, endOffset]

Added: trunk/src/orca/scripts/apps/gcalctool/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/gcalctool/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,10 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	script.py \
+	speech_generator.py \
+	where_am_i.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/gcalctool
+

Added: trunk/src/orca/scripts/apps/gcalctool/__init__.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/gcalctool/__init__.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,22 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Evolution."""
+
+from script import Script

Copied: trunk/src/orca/scripts/apps/gcalctool/script.py (from r3875, /trunk/src/orca/scripts/gcalctool.py)
==============================================================================
--- /trunk/src/orca/scripts/gcalctool.py	(original)
+++ trunk/src/orca/scripts/apps/gcalctool/script.py	Fri May  2 21:21:19 2008
@@ -30,58 +30,10 @@
 import orca.input_event as input_event
 import orca.orca_state as orca_state
 import orca.speech as speech
-import orca.speechgenerator as speechgenerator
-import orca.where_am_I as where_am_I
 import pyatspi
 
-class WhereAmI(where_am_I.WhereAmI):
-
-    def __init__(self, script):
-        """Create a new WhereAmI that will be used to speak information
-        about the current object of interest.
-        """
-
-        where_am_I.WhereAmI.__init__(self, script)
-
-    def _speakStatusBar(self):
-        """Speaks the status bar."""
-
-        if not self._statusBar:
-            return
-
-        utterances = []
-        text = self.getObjLabelAndName(self._statusBar)
-        utterances.append(text)
-        speech.speakUtterances(utterances)
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Overrides _getSpeechForPushButton to handle 'unspeakable'
-    button labels displayed on the screen.
-    """
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-
-    def _getSpeechForObjectName(self, obj):
-        """Gives preference to the object name versus what is being
-        displayed on the screen.  This helps accomodate the naming
-        hints being given to us by gcalctool for it's mathematical
-        operator buttons."""
-
-        if obj.getRole() != pyatspi.ROLE_PUSH_BUTTON:
-            return speechgenerator.SpeechGenerator._getSpeechForObjectName(\
-                self, obj)
-
-        if obj.name:
-            name = obj.name
-        else:
-            name = self._script.getDisplayedText(obj)
-
-        if name:
-            return [name]
-        elif obj.description:
-            return [obj.description]
-        else:
-            return []
+from speech_generator import SpeechGenerator
+from where_am_i import WhereAmI
 
 ########################################################################
 #                                                                      #

Added: trunk/src/orca/scripts/apps/gcalctool/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/gcalctool/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,58 @@
+# Orca
+#
+# Copyright 2004-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Provides a custom script for gcalctool."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.speechgenerator as speechgenerator
+import pyatspi
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Overrides _getSpeechForPushButton to handle 'unspeakable'
+    button labels displayed on the screen.
+    """
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    def _getSpeechForObjectName(self, obj):
+        """Gives preference to the object name versus what is being
+        displayed on the screen.  This helps accomodate the naming
+        hints being given to us by gcalctool for it's mathematical
+        operator buttons."""
+
+        if obj.getRole() != pyatspi.ROLE_PUSH_BUTTON:
+            return speechgenerator.SpeechGenerator._getSpeechForObjectName(\
+                self, obj)
+
+        if obj.name:
+            name = obj.name
+        else:
+            name = self._script.getDisplayedText(obj)
+
+        if name:
+            return [name]
+        elif obj.description:
+            return [obj.description]
+        else:
+            return []

Copied: trunk/src/orca/scripts/apps/gcalctool/where_am_i.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/gcalctool/where_am_i.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2004-2007 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
@@ -17,20 +17,33 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Provides a custom script for gcalctool."""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
+import orca.speech as speech
+import orca.where_am_I as where_am_I
 
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+class WhereAmI(where_am_I.WhereAmI):
+
+    def __init__(self, script):
+        """Create a new WhereAmI that will be used to speak information
+        about the current object of interest.
+        """
+
+        where_am_I.WhereAmI.__init__(self, script)
+
+    def _speakStatusBar(self):
+        """Speaks the status bar."""
+
+        if not self._statusBar:
+            return
+
+        utterances = []
+        text = self.getObjLabelAndName(self._statusBar)
+        utterances.append(text)
+        speech.speakUtterances(utterances)

Copied: trunk/src/orca/scripts/apps/gdmlogin.py (from r3875, /trunk/src/orca/scripts/gdmlogin.py)
==============================================================================

Added: trunk/src/orca/scripts/apps/gedit/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/gedit/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,9 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	script.py \
+	speech_generator.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/gedit
+

Copied: trunk/src/orca/scripts/apps/gedit/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/gedit/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2004-2007 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
@@ -17,20 +17,12 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for gedit."""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script

Copied: trunk/src/orca/scripts/apps/gedit/script.py (from r3875, /trunk/src/orca/scripts/gedit.py)
==============================================================================
--- /trunk/src/orca/scripts/gedit.py	(original)
+++ trunk/src/orca/scripts/apps/gedit/script.py	Fri May  2 21:21:19 2008
@@ -34,49 +34,11 @@
 import orca.orca_state as orca_state
 import orca.settings as settings
 import orca.speech as speech
-import orca.speechgenerator as speechgenerator
 import orca.speechserver as speechserver
 
 from orca.orca_i18n import _
 
-########################################################################
-#                                                                      #
-# The GEdit script class.                                              #
-#                                                                      #
-########################################################################
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Overrides _getSpeechForFrame so as to avoid digging into the
-    gedit hierarchy and tickling a bug in gedit.
-    """
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-
-    def _getSpeechForFrame(self, obj, already_focused):
-        """Get the speech for a frame.  [[[TODO: WDW - This avoids
-        digging into the component hierarchy so as to avoid tickling
-        a bug in GEdit (see module comment above).]]]
-
-        Arguments:
-        - obj: the frame
-        - already_focused: if False, the obj just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = self._getDefaultSpeech(obj, already_focused)
-
-        # This will dig deep into the hierarchy, causing issues with
-        # gedit.  So, we won't do this.
-        #
-        #utterances = self._getSpeechForAlert(obj, already_focused)
-
-        self._debugGenerator("GEditSpeechGenerator._getSpeechForFrame",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
+from speech_generator import SpeechGenerator
 
 class Script(default.Script):
 

Copied: trunk/src/orca/scripts/apps/gedit/speech_generator.py (from r3875, /trunk/src/orca/scripts/gnome-window-properties.py)
==============================================================================
--- /trunk/src/orca/scripts/gnome-window-properties.py	(original)
+++ trunk/src/orca/scripts/apps/gedit/speech_generator.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2006 Sun Microsystems Inc.
+# Copyright 2004-2007 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
@@ -17,20 +17,19 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for gnome-window-properties."""
+"""Custom script for gedit."""
 
-__id__ = "$Id$"
+__id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
 import orca.speechgenerator as speechgenerator
 
 ########################################################################
 #                                                                      #
-# The gnome-window-properties script class.                            #
+# The GEdit script class.                                              #
 #                                                                      #
 ########################################################################
 
@@ -41,41 +40,28 @@
     def __init__(self, script):
         speechgenerator.SpeechGenerator.__init__(self, script)
 
-    def _getSpeechForAlert(self, obj, already_focused):
-        """Gets the title of the dialog.  Do NOT get the contents
-        of labels inside the dialog that are not associated with any
-        other objects.
+    def _getSpeechForFrame(self, obj, already_focused):
+        """Get the speech for a frame.  [[[TODO: WDW - This avoids
+        digging into the component hierarchy so as to avoid tickling
+        a bug in GEdit (see module comment above).]]]
 
         Arguments:
-        - obj: the Accessible dialog
-        - already_focused: False if object just received focus
+        - obj: the frame
+        - already_focused: if False, the obj just received focus
 
-        Returns a list of utterances be spoken.
+        Returns a list of utterances to be spoken for the object.
         """
 
-        utterances = []
-        utterances.extend(self._getSpeechForObjectLabel(obj))
-        utterances.extend(self._getSpeechForObjectName(obj))
-        utterances.extend(self._getSpeechForObjectRole(obj))
+        utterances = self._getDefaultSpeech(obj, already_focused)
 
-        self._debugGenerator("gnome-window-properties._getSpeechForAlert",
+        # This will dig deep into the hierarchy, causing issues with
+        # gedit.  So, we won't do this.
+        #
+        #utterances = self._getSpeechForAlert(obj, already_focused)
+
+        self._debugGenerator("GEditSpeechGenerator._getSpeechForFrame",
                              obj,
                              already_focused,
                              utterances)
 
         return utterances
-
-class Script(default.Script):
-
-    def __init__(self, app):
-        """Creates a new script for the given application.
-
-        Arguments:
-        - app: the application to create a script for.
-        """
-        default.Script.__init__(self, app)
-
-    def getSpeechGenerator(self):
-        """Returns the speech generator for this script.
-        """
-        return SpeechGenerator(self)

Copied: trunk/src/orca/scripts/apps/gnome-keyring-ask.py (from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/gnome-mud.py (from r3875, /trunk/src/orca/scripts/gnome-mud.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/gnome-panel.py (from r3875, /trunk/src/orca/scripts/gnome-panel.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/gnome-search-tool.py (from r3875, /trunk/src/orca/scripts/gnome-search-tool.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/gnome-system-monitor.py (from r3875, /trunk/src/orca/scripts/gnome-system-monitor.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/gnome-terminal.py (from r3875, /trunk/src/orca/scripts/gnome-terminal.py)
==============================================================================

Added: trunk/src/orca/scripts/apps/gnome-window-properties/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/gnome-window-properties/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,9 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	script.py \
+	speech_generator.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/gnome-window-properties
+

Copied: trunk/src/orca/scripts/apps/gnome-window-properties/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/gnome-window-properties/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2006 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
@@ -17,20 +17,12 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for gnome-window-properties."""
 
-__id__        = "$Id$"
+__id__ = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script

Copied: trunk/src/orca/scripts/apps/gnome-window-properties/script.py (from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py)
==============================================================================
--- /trunk/src/orca/scripts/gnome-keyring-ask.py	(original)
+++ trunk/src/orca/scripts/apps/gnome-window-properties/script.py	Fri May  2 21:21:19 2008
@@ -17,9 +17,9 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for gnome-keyring-ask"""
+"""Custom script for gnome-window-properties."""
 
-__id__        = "$Id$"
+__id__ = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
@@ -27,12 +27,15 @@
 
 import orca.default as default
 
+from speech_generator import SpeechGenerator
+
 ########################################################################
 #                                                                      #
-# The gnome-keyring-ask script class.                                  #
+# The gnome-window-properties script class.                            #
 #                                                                      #
 ########################################################################
 
+
 class Script(default.Script):
 
     def __init__(self, app):
@@ -41,22 +44,9 @@
         Arguments:
         - app: the application to create a script for.
         """
-
         default.Script.__init__(self, app)
 
-    def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus):
-        """Called when the visual object with focus changes.
-
-        Arguments:
-        - event: if not None, the Event that caused the change
-        - oldLocusOfFocus: Accessible that is the old locus of focus
-        - newLocusOfFocus: Accessible that is the new locus of focus
+    def getSpeechGenerator(self):
+        """Returns the speech generator for this script.
         """
-
-        # If the gnome-keyring-ask application starts up, don't compare
-        # it with the application that previously had focus because it
-        # more often than not will just hang (see bug #351569).
-        # We do this by setting the old locus of focus to None, then
-        # we can safely call the locusOfFocusChanged() method in default.py.
-        #
-        default.Script.locusOfFocusChanged(self, event, None, newLocusOfFocus)
+        return SpeechGenerator(self)

Copied: trunk/src/orca/scripts/apps/gnome-window-properties/speech_generator.py (from r3875, /trunk/src/orca/scripts/gnome-window-properties.py)
==============================================================================
--- /trunk/src/orca/scripts/gnome-window-properties.py	(original)
+++ trunk/src/orca/scripts/apps/gnome-window-properties/speech_generator.py	Fri May  2 21:21:19 2008
@@ -25,15 +25,8 @@
 __copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
 import orca.speechgenerator as speechgenerator
 
-########################################################################
-#                                                                      #
-# The gnome-window-properties script class.                            #
-#                                                                      #
-########################################################################
-
 class SpeechGenerator(speechgenerator.SpeechGenerator):
     """Overrides _getSpeechForFrame so as to avoid digging into the
     gedit hierarchy and tickling a bug in gedit.
@@ -64,18 +57,3 @@
                              utterances)
 
         return utterances
-
-class Script(default.Script):
-
-    def __init__(self, app):
-        """Creates a new script for the given application.
-
-        Arguments:
-        - app: the application to create a script for.
-        """
-        default.Script.__init__(self, app)
-
-    def getSpeechGenerator(self):
-        """Returns the speech generator for this script.
-        """
-        return SpeechGenerator(self)

Copied: trunk/src/orca/scripts/apps/gnome_segv2.py (from r3875, /trunk/src/orca/scripts/gnome_segv2.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/liferea.py (from r3875, /trunk/src/orca/scripts/liferea.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/metacity.py (from r3875, /trunk/src/orca/scripts/metacity.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/nautilus.py (from r3875, /trunk/src/orca/scripts/nautilus.py)
==============================================================================

Copied: trunk/src/orca/scripts/apps/notification-daemon.py (from r3875, /trunk/src/orca/scripts/notification-daemon.py)
==============================================================================

Added: trunk/src/orca/scripts/apps/pidgin/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/pidgin/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,11 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	constants.py \
+	script.py \
+	speech_generator.py \
+	where_am_i.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/pidgin
+

Copied: trunk/src/orca/scripts/apps/pidgin/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/pidgin/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2005-2007 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
@@ -17,20 +17,7 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for Evolution."""
 
-__id__        = "$Id$"
-__version__   = "$Revision$"
-__date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
-__license__   = "LGPL"
-
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script
+from constants import *

Added: trunk/src/orca/scripts/apps/pidgin/constants.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/pidgin/constants.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,57 @@
+# Orca
+#
+# Copyright 2004-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for gaim.  This provides the ability for Orca to
+monitor both the IM input and IM output text areas at the same time.
+
+The following script specific key sequences are supported:
+
+  Insert-h      -  Toggle whether we prefix chat room messages with
+                   the name of the chat room.
+  Insert-[1-9]  -  Speak and braille a previous chat room message.
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+# Whether we prefix chat room messages with the name of the chat room.
+#
+prefixChatMessage = False
+
+# Whether we announce when a buddy is typing.
+#
+announceBuddyTyping = False
+
+# Whether we provide chat room specific message histories.
+#
+chatRoomHistories = False
+
+# Possible ways of how Orca should speak pidgin chat messages.
+#
+SPEAK_ALL_MESSAGES              = 0
+SPEAK_CHANNEL_WITH_FOCUS        = 1
+SPEAK_ALL_CHANNELS_WHEN_FOCUSED = 2
+
+# Indicates how pidgin chat messages should be spoken.
+#
+speakMessages = SPEAK_ALL_MESSAGES
+

Copied: trunk/src/orca/scripts/apps/pidgin/script.py (from r3875, /trunk/src/orca/scripts/gaim.py)
==============================================================================
--- /trunk/src/orca/scripts/gaim.py	(original)
+++ trunk/src/orca/scripts/apps/pidgin/script.py	Fri May  2 21:21:19 2008
@@ -42,36 +42,14 @@
 import orca.input_event as input_event
 import orca.keybindings as keybindings
 import orca.orca_state as orca_state
-import orca.rolenames as rolenames
 import orca.settings as settings
 import orca.speech as speech
-import orca.speechgenerator as speechgenerator
-import orca.where_am_I as where_am_I
 
 from orca.orca_i18n import _
-from orca.orca_i18n import ngettext  # for ngettext support
 
-# Whether we prefix chat room messages with the name of the chat room.
-#
-prefixChatMessage = False
-
-# Whether we announce when a buddy is typing.
-#
-announceBuddyTyping = False
-
-# Whether we provide chat room specific message histories.
-#
-chatRoomHistories = False
-
-# Possible ways of how Orca should speak pidgin chat messages.
-#
-SPEAK_ALL_MESSAGES              = 0
-SPEAK_CHANNEL_WITH_FOCUS        = 1
-SPEAK_ALL_CHANNELS_WHEN_FOCUSED = 2
-
-# Indicates how pidgin chat messages should be spoken.
-#
-speakMessages = SPEAK_ALL_MESSAGES
+from speech_generator import SpeechGenerator
+from where_am_i import WhereAmI
+from constants import *
 
 ########################################################################
 #                                                                      #
@@ -115,199 +93,6 @@
     def __str__(self):
         return ''.join(self.__data__)
 
-########################################################################
-#                                                                      #
-# Custom SpeechGenerator                                               #
-#                                                                      #
-########################################################################
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Overrides _getSpeechForTableCell() so that we can provide access
-    to the expanded/collapsed state and node count for the buddy list.
-    """
-
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-
-    def _getSpeechForTableCell(self, obj, already_focused):
-        """Get the speech utterances for a single table cell
-
-        Arguments:
-        - obj: the table cell
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = speechgenerator.SpeechGenerator._getSpeechForTableCell( \
-            self, obj, already_focused)
-
-        if not self._script.isInBuddyList(obj):
-            return utterances
-
-        # The Pidgin buddy list consists of two columns. The column which
-        # is set as the expander column and which also contains the node
-        # relationship is hidden.  Hidden columns are not included among
-        # a table's columns.  The hidden object of interest seems to always
-        # immediately precede the visible object.
-        #
-        expanderCell = obj.parent[obj.getIndexInParent() - 1]
-        if not expanderCell:
-            return utterances
-
-        state = expanderCell.getState()
-        if state.contains(pyatspi.STATE_EXPANDABLE):
-            if state.contains(pyatspi.STATE_EXPANDED):
-                # Translators: this represents the state of a node in a tree.
-                # 'expanded' means the children are showing.
-                # 'collapsed' means the children are not showing.
-                #
-                utterances.append(_("expanded"))
-                childNodes = self._script.getChildNodes(expanderCell)
-                children = len(childNodes)
-
-                if not children \
-                   or (settings.speechVerbosityLevel == \
-                       settings.VERBOSITY_LEVEL_VERBOSE):
-                    # Translators: this is the number of items in a layered
-                    # pane or table.
-                    #
-                    itemString = ngettext("%d item",
-                                          "%d items",
-                                          children) % children
-                    utterances.append(itemString)
-            else:
-                # Translators: this represents the state of a node in a tree.
-                # 'expanded' means the children are showing.
-                # 'collapsed' means the children are not showing.
-                #
-                utterances.append(_("collapsed"))
-
-        self._debugGenerator("gaim._getSpeechForTableCell",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-########################################################################
-#                                                                      #
-# Custom WhereAmI                                                      #
-#                                                                      #
-######################################################################## 
-
-class WhereAmI(where_am_I.WhereAmI):
-    """Overrides _speakTableCell() so that we can provide access
-    to the expanded/collapsed state for items in the buddy list.
-    """
-
-    def __init__(self, script):
-        where_am_I.WhereAmI.__init__(self, script)
-        self._script = script
-        
-    def _speakTableCell(self, obj, doubleClick):
-        """Tree Tables present the following information (an example is
-        'Tree table, Mike Pedersen, row 8 of 10, tree level 2'):
-
-        1. label, if any
-        2. role
-        3. current row (regardless of speak cell/row setting)
-        4. relative position
-        5. if expandable/collapsible: expanded/collapsed
-        6. if applicable, the level
-
-        """
-
-        if not self._script.isInBuddyList(obj):
-            return where_am_I.WhereAmI._speakTableCell(self, obj, doubleClick)
-
-        # Speak the first two items (and possibly the position)
-        #
-        utterances = []
-        if obj.parent.getRole() == pyatspi.ROLE_TABLE_CELL:
-            obj = obj.parent
-        parent = obj.parent
-
-        text = self._getObjLabel(obj)
-        utterances.append(text)
-
-        text = rolenames.getSpeechForRoleName(obj)
-        utterances.append(text)
-        debug.println(self._debugLevel, "first table cell utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
-
-        utterances = []
-        if doubleClick:
-            table = parent.queryTable()
-            row = table.getRowAtIndex(
-              orca_state.locusOfFocus.getIndexInParent())
-            # Translators: this in reference to a row in a table.
-            #
-            text = _("row %d of %d") % ((row+1), table.nRows)
-            utterances.append(text)
-            speech.speakUtterances(utterances)
-
-        # Speak the current row
-        #
-        utterances = self._getTableRow(obj)
-        debug.println(self._debugLevel, "second table cell utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
-
-        # Speak the remaining items.
-        #
-        utterances = []
-
-        if not doubleClick:
-            try:
-                table = parent.queryTable()
-            except NotImplementedError:
-                debug.println(self._debugLevel, 
-                              "??? parent=%s" % parent.getRoleName())
-                return
-            else:
-                row = \
-                    table.getRowAtIndex(
-                       orca_state.locusOfFocus.getIndexInParent())
-                # Translators: this in reference to a row in a table.
-                #
-                text = _("row %d of %d") % ((row+1), table.nRows)
-                utterances.append(text)
-
-        # The difference/reason for overriding:  We obtain the expanded
-        # state from the hidden object that immediately precedes obj.
-        #
-        try:
-            state = obj.parent[obj.getIndexInParent() - 1].getState()
-        except:
-            state = obj.getState()
-
-        if state.contains(pyatspi.STATE_EXPANDABLE):
-            if state.contains(pyatspi.STATE_EXPANDED):
-                # Translators: this represents the state of a node in a tree.
-                # 'expanded' means the children are showing.
-                # 'collapsed' means the children are not showing.
-                #
-                text = _("expanded")
-            else:
-                # Translators: this represents the state of a node in a tree.
-                # 'expanded' means the children are showing.
-                # 'collapsed' means the children are not showing.
-                #
-                text = _("collapsed")
-            utterances.append(text)
-
-        level = self._script.getNodeLevel(orca_state.locusOfFocus)
-        if level >= 0:
-            # Translators: this represents the depth of a node in a tree
-            # view (i.e., how many ancestors a node has).
-            #
-            utterances.append(_("tree level %d") % (level + 1))
-
-        debug.println(self._debugLevel, "third table cell utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
 
 ########################################################################
 #                                                                      #

Added: trunk/src/orca/scripts/apps/pidgin/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/pidgin/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,118 @@
+# Orca
+#
+# Copyright 2004-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for gaim.  This provides the ability for Orca to
+monitor both the IM input and IM output text areas at the same time.
+
+The following script specific key sequences are supported:
+
+  Insert-h      -  Toggle whether we prefix chat room messages with
+                   the name of the chat room.
+  Insert-[1-9]  -  Speak and braille a previous chat room message.
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.settings as settings
+import orca.speechgenerator as speechgenerator
+
+from orca.orca_i18n import _
+from orca.orca_i18n import ngettext  # for ngettext support
+
+########################################################################
+#                                                                      #
+# Custom SpeechGenerator                                               #
+#                                                                      #
+########################################################################
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Overrides _getSpeechForTableCell() so that we can provide access
+    to the expanded/collapsed state and node count for the buddy list.
+    """
+
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    def _getSpeechForTableCell(self, obj, already_focused):
+        """Get the speech utterances for a single table cell
+
+        Arguments:
+        - obj: the table cell
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = speechgenerator.SpeechGenerator._getSpeechForTableCell( \
+            self, obj, already_focused)
+
+        if not self._script.isInBuddyList(obj):
+            return utterances
+
+        # The Pidgin buddy list consists of two columns. The column which
+        # is set as the expander column and which also contains the node
+        # relationship is hidden.  Hidden columns are not included among
+        # a table's columns.  The hidden object of interest seems to always
+        # immediately precede the visible object.
+        #
+        expanderCell = obj.parent[obj.getIndexInParent() - 1]
+        if not expanderCell:
+            return utterances
+
+        state = expanderCell.getState()
+        if state.contains(pyatspi.STATE_EXPANDABLE):
+            if state.contains(pyatspi.STATE_EXPANDED):
+                # Translators: this represents the state of a node in a tree.
+                # 'expanded' means the children are showing.
+                # 'collapsed' means the children are not showing.
+                #
+                utterances.append(_("expanded"))
+                childNodes = self._script.getChildNodes(expanderCell)
+                children = len(childNodes)
+
+                if not children \
+                   or (settings.speechVerbosityLevel == \
+                       settings.VERBOSITY_LEVEL_VERBOSE):
+                    # Translators: this is the number of items in a layered
+                    # pane or table.
+                    #
+                    itemString = ngettext("%d item",
+                                          "%d items",
+                                          children) % children
+                    utterances.append(itemString)
+            else:
+                # Translators: this represents the state of a node in a tree.
+                # 'expanded' means the children are showing.
+                # 'collapsed' means the children are not showing.
+                #
+                utterances.append(_("collapsed"))
+
+        self._debugGenerator("gaim._getSpeechForTableCell",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+

Added: trunk/src/orca/scripts/apps/pidgin/where_am_i.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/pidgin/where_am_i.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,163 @@
+# Orca
+#
+# Copyright 2004-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for gaim.  This provides the ability for Orca to
+monitor both the IM input and IM output text areas at the same time.
+
+The following script specific key sequences are supported:
+
+  Insert-h      -  Toggle whether we prefix chat room messages with
+                   the name of the chat room.
+  Insert-[1-9]  -  Speak and braille a previous chat room message.
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.debug as debug
+import orca.orca_state as orca_state
+import orca.rolenames as rolenames
+import orca.speech as speech
+import orca.where_am_I as where_am_I
+
+from orca.orca_i18n import _
+
+########################################################################
+#                                                                      #
+# Custom WhereAmI                                                      #
+#                                                                      #
+######################################################################## 
+
+class WhereAmI(where_am_I.WhereAmI):
+    """Overrides _speakTableCell() so that we can provide access
+    to the expanded/collapsed state for items in the buddy list.
+    """
+
+    def __init__(self, script):
+        where_am_I.WhereAmI.__init__(self, script)
+        self._script = script
+        
+    def _speakTableCell(self, obj, doubleClick):
+        """Tree Tables present the following information (an example is
+        'Tree table, Mike Pedersen, row 8 of 10, tree level 2'):
+
+        1. label, if any
+        2. role
+        3. current row (regardless of speak cell/row setting)
+        4. relative position
+        5. if expandable/collapsible: expanded/collapsed
+        6. if applicable, the level
+
+        """
+
+        if not self._script.isInBuddyList(obj):
+            return where_am_I.WhereAmI._speakTableCell(self, obj, doubleClick)
+
+        # Speak the first two items (and possibly the position)
+        #
+        utterances = []
+        if obj.parent.getRole() == pyatspi.ROLE_TABLE_CELL:
+            obj = obj.parent
+        parent = obj.parent
+
+        text = self._getObjLabel(obj)
+        utterances.append(text)
+
+        text = rolenames.getSpeechForRoleName(obj)
+        utterances.append(text)
+        debug.println(self._debugLevel, "first table cell utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)
+
+        utterances = []
+        if doubleClick:
+            table = parent.queryTable()
+            row = table.getRowAtIndex(
+              orca_state.locusOfFocus.getIndexInParent())
+            # Translators: this in reference to a row in a table.
+            #
+            text = _("row %d of %d") % ((row+1), table.nRows)
+            utterances.append(text)
+            speech.speakUtterances(utterances)
+
+        # Speak the current row
+        #
+        utterances = self._getTableRow(obj)
+        debug.println(self._debugLevel, "second table cell utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)
+
+        # Speak the remaining items.
+        #
+        utterances = []
+
+        if not doubleClick:
+            try:
+                table = parent.queryTable()
+            except NotImplementedError:
+                debug.println(self._debugLevel, 
+                              "??? parent=%s" % parent.getRoleName())
+                return
+            else:
+                row = \
+                    table.getRowAtIndex(
+                       orca_state.locusOfFocus.getIndexInParent())
+                # Translators: this in reference to a row in a table.
+                #
+                text = _("row %d of %d") % ((row+1), table.nRows)
+                utterances.append(text)
+
+        # The difference/reason for overriding:  We obtain the expanded
+        # state from the hidden object that immediately precedes obj.
+        #
+        try:
+            state = obj.parent[obj.getIndexInParent() - 1].getState()
+        except:
+            state = obj.getState()
+
+        if state.contains(pyatspi.STATE_EXPANDABLE):
+            if state.contains(pyatspi.STATE_EXPANDED):
+                # Translators: this represents the state of a node in a tree.
+                # 'expanded' means the children are showing.
+                # 'collapsed' means the children are not showing.
+                #
+                text = _("expanded")
+            else:
+                # Translators: this represents the state of a node in a tree.
+                # 'expanded' means the children are showing.
+                # 'collapsed' means the children are not showing.
+                #
+                text = _("collapsed")
+            utterances.append(text)
+
+        level = self._script.getNodeLevel(orca_state.locusOfFocus)
+        if level >= 0:
+            # Translators: this represents the depth of a node in a tree
+            # view (i.e., how many ancestors a node has).
+            #
+            utterances.append(_("tree level %d") % (level + 1))
+
+        debug.println(self._debugLevel, "third table cell utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)

Added: trunk/src/orca/scripts/apps/planner/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/planner/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,10 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	braille_generator.py \
+	script.py \
+	speech_generator.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/planner
+

Copied: trunk/src/orca/scripts/apps/planner/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/planner/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 2006-2007 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
@@ -17,20 +17,12 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for planner."""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2006-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script

Added: trunk/src/orca/scripts/apps/planner/braille_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/planner/braille_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,87 @@
+# Orca
+#
+# Copyright 2006-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for planner."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2006-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.braille as braille
+import orca.settings as settings
+import orca.braillegenerator as braillegenerator
+import pyatspi
+
+from orca.orca_i18n import _ # for gettext support
+
+class BrailleGenerator(braillegenerator.BrailleGenerator):
+    """We make this to appropiately present ribbon's toggle button in
+    a toolbar used to display in a menu those options that doesn't
+    fill in toolbar when the application is resized. Also for each one
+    of the grphics buttons in the main window."""
+
+    def __init__(self, script):
+        braillegenerator.BrailleGenerator.__init__(self, script)
+
+    def _getBrailleRegionsForToggleButton(self, obj):
+        """Get the braille for a radio button.  If the button already had
+        focus, then only the state is displayed.
+
+        Arguments:
+        - obj: the check box
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("_getBrailleRegionsForRadioButton", obj)
+
+        text = ""
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedLabel(obj))
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedText(obj))
+
+        # First special toggle button is the one in the toolbar and
+        # that it has no name Application should implement an
+        # accessible name in this component, but until this is made We
+        # speech/braille "display more options" when the focus is in
+        # one of these toggle buttons.
+        #
+        roleList = [pyatspi.ROLE_TOGGLE_BUTTON, pyatspi.ROLE_TOOL_BAR]
+
+        if self._script.isDesiredFocusedItem(obj, roleList) and not obj.name:
+            text += _("Display more options")
+
+        text = self._script.appendString(text, self._getTextForRole(obj))
+
+        if obj.getState().contains(pyatspi.STATE_CHECKED):
+            brailleindicatorindex = 1
+        else:
+            brailleindicatorindex = 0
+
+        regions = []
+        indicator = \
+            settings.brailleRadioButtonIndicators[brailleindicatorindex]
+        componentRegion = braille.Component(obj, text, indicator=indicator)
+        regions.append(componentRegion)
+
+        return [regions, componentRegion]

Copied: trunk/src/orca/scripts/apps/planner/script.py (from r3875, /trunk/src/orca/scripts/gnome-keyring-ask.py)
==============================================================================
--- /trunk/src/orca/scripts/gnome-keyring-ask.py	(original)
+++ trunk/src/orca/scripts/apps/planner/script.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2006 Sun Microsystems Inc.
+# Copyright 2006-2007 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
@@ -17,19 +17,22 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for gnome-keyring-ask"""
+"""Custom script for planner."""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2006-2007 Sun Microsystems Inc."
 __license__   = "LGPL"
 
 import orca.default as default
 
+from speech_generator import SpeechGenerator
+from braille_generator import BrailleGenerator
+
 ########################################################################
 #                                                                      #
-# The gnome-keyring-ask script class.                                  #
+# The planner script class.                                            #
 #                                                                      #
 ########################################################################
 
@@ -41,22 +44,14 @@
         Arguments:
         - app: the application to create a script for.
         """
-
         default.Script.__init__(self, app)
 
-    def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus):
-        """Called when the visual object with focus changes.
-
-        Arguments:
-        - event: if not None, the Event that caused the change
-        - oldLocusOfFocus: Accessible that is the old locus of focus
-        - newLocusOfFocus: Accessible that is the new locus of focus
-        """
+    # This method tries to detect and handle the following cases:
+    # 1) Toolbar: the last toggle button to show 'more options'
+    # 2) Main window: one of the four graphic toggle buttons.
+    #
+    def getBrailleGenerator(self):
+        return BrailleGenerator(self)
 
-        # If the gnome-keyring-ask application starts up, don't compare
-        # it with the application that previously had focus because it
-        # more often than not will just hang (see bug #351569).
-        # We do this by setting the old locus of focus to None, then
-        # we can safely call the locusOfFocusChanged() method in default.py.
-        #
-        default.Script.locusOfFocusChanged(self, event, None, newLocusOfFocus)
+    def getSpeechGenerator(self):
+        return SpeechGenerator(self)

Added: trunk/src/orca/scripts/apps/planner/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/planner/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,77 @@
+# Orca
+#
+# Copyright 2006-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for planner."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2006-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.speechgenerator as speechgenerator
+import pyatspi
+
+from orca.orca_i18n import _ # for gettext support
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    # We make this to appropiately present ribbon's toggle button in a
+    # toolbar used to display in a menu those options that doesn fill
+    # in toolbar when the application is resized.
+    #
+    # Also for each one of the grphics buttons in the main window
+    #
+    def _getSpeechForToggleButton(self, obj, already_focused):
+        utterances = []
+        tmp = []
+
+        # Application should implement an accessible name in this
+        # component, but until this is made We speech/braille "display
+        # more options" when the focus is in one of these toggle
+        # buttons.
+        #
+
+        roleList = [pyatspi.ROLE_TOGGLE_BUTTON, \
+                    pyatspi.ROLE_TOOL_BAR]
+
+        if self._script.isDesiredFocusedItem(obj, roleList) and not obj.name:
+            if not already_focused:
+                tmp.append(_("Display more options"))
+                tmp.extend(self._getDefaultSpeech(obj, already_focused))
+
+                if obj.getState().contains(pyatspi.STATE_CHECKED):
+                    tmp.append(_("pressed"))
+                else:
+                    tmp.append(_("not pressed"))
+
+                utterances.extend(tmp)
+                utterances.extend(self._getSpeechForObjectAvailability(obj))
+            else:
+                if obj.getState().contains(pyatspi.STATE_CHECKED):
+                    utterances.append(_("pressed"))
+                else:
+                    utterances.append(_("not pressed"))
+
+            return utterances
+
+        return self._getSpeechForLabel(obj, already_focused)

Added: trunk/src/orca/scripts/apps/rhythmbox/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/rhythmbox/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,10 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	braille_generator.py \
+	script.py \
+	speech_generator.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/rhythmbox
+

Copied: trunk/src/orca/scripts/apps/rhythmbox/__init__.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/apps/rhythmbox/__init__.py	Fri May  2 21:21:19 2008
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2006 Sun Microsystems Inc.
+# Copyright 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
@@ -17,20 +17,12 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for rhythmbox."""
 
-__id__        = "$Id$"
-__version__   = "$Revision$"
-__date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
+__id__ = "$Id:$"
+__version__   = "$Revision:$"
+__date__      = "$Date:$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
-
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+from script import Script

Added: trunk/src/orca/scripts/apps/rhythmbox/braille_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/rhythmbox/braille_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,56 @@
+# Orca
+#
+# Copyright 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for rhythmbox."""
+
+__id__ = "$Id:$"
+__version__   = "$Revision:$"
+__date__      = "$Date:$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.braillegenerator as braillegenerator
+
+class BrailleGenerator(braillegenerator.BrailleGenerator):
+    """Overrides _getBrailleRegionsForTableCell to correctly handle 
+    the table cells in the Library table.
+    """
+
+    def __init__(self, script):
+        braillegenerator.BrailleGenerator.__init__(self, script)
+
+    def _getBrailleRegionsForTableCell(self, obj):
+        """Get the braille for a single table cell
+
+        Arguments:
+        - obj: the table
+
+        Returns a list where the first element is a list of Regions to 
+        display and the second element is the Region which should get focus.
+        """
+
+        # Check to see if this is a table cell from the Library table.
+        # If so, it'll have five children and we are interested in the
+        # penultimate one. See bug #512639 for more details.
+        #
+        if obj.childCount == 5:
+            obj = obj[3]
+
+        return braillegenerator.BrailleGenerator.\
+                    _getBrailleRegionsForTableCell(self, obj)

Added: trunk/src/orca/scripts/apps/rhythmbox/script.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/rhythmbox/script.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,52 @@
+# Orca
+#
+# Copyright 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for rhythmbox."""
+
+__id__ = "$Id:$"
+__version__   = "$Revision:$"
+__date__      = "$Date:$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.default as default
+
+from speech_generator import SpeechGenerator
+from braille_generator import BrailleGenerator
+
+class Script(default.Script):
+
+    def __init__(self, app):
+        """Creates a new script for the given application.
+
+        Arguments:
+        - app: the application to create a script for.
+        """
+        default.Script.__init__(self, app)
+
+    def getBrailleGenerator(self):
+        """Returns the braille generator for this script.
+        """
+
+        return BrailleGenerator(self)
+
+    def getSpeechGenerator(self):
+        """Returns the speech generator for this script.
+        """
+        return SpeechGenerator(self)

Added: trunk/src/orca/scripts/apps/rhythmbox/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/rhythmbox/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,55 @@
+# Orca
+#
+# Copyright 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for rhythmbox."""
+
+__id__ = "$Id:$"
+__version__   = "$Revision:$"
+__date__      = "$Date:$"
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import orca.speechgenerator as speechgenerator
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Overrides _getSpeechForTableCell to correctly handle the table
+    cells in the Library table.
+    """
+
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    def _getSpeechForTableCell(self, obj, already_focused):
+        """Get the speech utterances for a single table cell
+
+        Arguments:
+        - obj: the table
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Check to see if this is a table cell from the Library table.
+        # If so, it'll have five children and we are interested in the
+        # penultimate one. See bug #512639 for more details.
+        #
+        if obj.childCount == 5:
+            obj = obj[3]
+        return speechgenerator.SpeechGenerator.\
+                    _getSpeechForTableCell(self, obj, already_focused)

Added: trunk/src/orca/scripts/apps/soffice/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,12 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	braille_generator.py \
+	constants.py \
+	__init__.py \
+	script.py \
+	speech_generator.py \
+	where_am_i.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/apps/soffice
+

Added: trunk/src/orca/scripts/apps/soffice/__init__.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/__init__.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,2 @@
+from script import Script
+from constants import speakCellCoordinates

Added: trunk/src/orca/scripts/apps/soffice/braille_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/braille_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,233 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for StarOffice and OpenOffice."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.braille as braille
+import orca.braillegenerator as braillegenerator
+import orca.settings as settings
+
+class BrailleGenerator(braillegenerator.BrailleGenerator):
+    """Overrides _getBrailleRegionsForTableCellRow so that , when we are
+    in a spread sheet, we can braille the dynamic row and column headers
+    (assuming they are set).
+    Overrides _getBrailleRegionsForTableCell so that, when we are in
+    a spread sheet, we can braille the location of the table cell as well
+    as the contents.
+    """
+
+    def __init__(self, script):
+        braillegenerator.BrailleGenerator.__init__(self, script)
+
+    def _getBrailleRegionsForTableCellRow(self, obj):
+        """Get the braille for a table cell row or a single table cell
+        if settings.readTableCellRow is False.
+
+        Arguments:
+        - obj: the table cell
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        focusRegion = None
+        regions = []
+
+        # Check to see if this spread sheet cell has either a dynamic
+        # column heading or row heading (or both) associated with it.
+        # If it does, then braille those first before brailling the
+        # cell contents.
+        #
+        table = self._script.getTable(obj)
+        parent = obj.parent
+        try:
+            parentTable = parent.queryTable()
+        except NotImplementedError:
+            parentTable = None
+
+        if self._script.pointOfReference.has_key("lastColumn") and \
+              self._script.pointOfReference["lastColumn"] != \
+              parentTable.getColumnAtIndex(obj.getIndexInParent()):
+            if self._script.dynamicColumnHeaders.has_key(table):
+                row = self._script.dynamicColumnHeaders[table]
+                header = self._script.getDynamicRowHeaderCell(obj, row)
+                try:
+                    headerText = header.queryText()
+                except:
+                    headerText = None
+
+                if header.childCount > 0:
+                    for child in header:
+                        text = self._script.getText(child, 0, -1)
+                        if text:
+                            regions.append(braille.Region(" " + text + " "))
+                elif headerText:
+                    text = self._script.getText(header, 0, -1)
+                    if text:
+                        regions.append(braille.Region(" " + text + " "))
+
+        if self._script.pointOfReference.has_key("lastRow") and \
+              self._script.pointOfReference['lastRow'] != \
+              parentTable.getRowAtIndex(obj.getIndexInParent()):
+            if self._script.dynamicRowHeaders.has_key(table):
+                column = self._script.dynamicRowHeaders[table]
+                header = self._script.getDynamicColumnHeaderCell(obj, column)
+                try:
+                    headerText = header.queryText()
+                except:
+                    headerText = None
+
+                if header.childCount > 0:
+                    for child in header:
+                        text = self._script.getText(child, 0, -1)
+                        if text:
+                            regions.append(braille.Region(" " + text + " "))
+                elif headerText:
+                    text = self._script.getText(header, 0, -1)
+                    if text:
+                        regions.append(braille.Region(" " + text + " "))
+
+        if self._script.isSpreadSheetCell(obj):
+
+            # Adding in a check here to make sure that the parent is a
+            # valid table. It's possible that the parent could be a
+            # table cell too (see bug #351501).
+            #
+            if settings.readTableCellRow and parentTable:
+                rowRegions = []
+                savedBrailleVerbosityLevel = settings.brailleVerbosityLevel
+                settings.brailleVerbosityLevel = \
+                                             settings.VERBOSITY_LEVEL_BRIEF
+
+                parent = obj.parent
+                row = parentTable.getRowAtIndex(obj.getIndexInParent())
+                column = parentTable.getColumnAtIndex(obj.getIndexInParent())
+
+                # This is an indication of whether we should speak all the
+                # table cells (the user has moved focus up or down a row),
+                # or just the current one (focus has moved left or right in
+                # the same row).
+                #
+                speakAll = True
+                if self._script.pointOfReference.has_key("lastRow") and \
+                    self._script.pointOfReference.has_key("lastColumn"):
+                    pointOfReference = self._script.pointOfReference
+                    speakAll = \
+                        (pointOfReference["lastRow"] != row) or \
+                           ((row == 0 or row == parentTable.nRows-1) and \
+                            pointOfReference["lastColumn"] == column)
+
+                if speakAll:
+                    [startIndex, endIndex] = \
+                        self._script.getSpreadSheetRowRange(obj)
+                    for i in range(startIndex, endIndex+1):
+                        cell = parentTable.getAccessibleAt(row, i)
+                        showing = cell.getState().contains( \
+                                        pyatspi.STATE_SHOWING)
+                        if showing:
+                            [cellRegions, focusRegion] = \
+                                self._getBrailleRegionsForTableCell(cell)
+                            if len(rowRegions):
+                                rowRegions.append(braille.Region(" "))
+                            rowRegions.append(cellRegions[0])
+                    regions.extend(rowRegions)
+                    settings.brailleVerbosityLevel = savedBrailleVerbosityLevel
+                else:
+                    [cellRegions, focusRegion] = \
+                                self._getBrailleRegionsForTableCell(obj)
+                    regions.extend(cellRegions)
+            else:
+                [cellRegions, focusRegion] = \
+                                self._getBrailleRegionsForTableCell(obj)
+                regions.extend(cellRegions)
+            regions = [regions, focusRegion]
+        else:
+            [cellRegions, focusRegion] = \
+                braillegenerator.BrailleGenerator.\
+                    _getBrailleRegionsForTableCellRow(self, obj)
+            regions.extend(cellRegions)
+            regions = [regions, focusRegion]
+
+        return regions
+
+    def _getBrailleRegionsForTableCell(self, obj):
+        """Get the braille for a table cell. If this isn't inside a
+        spread sheet, just return the regions returned by the default
+        table cell braille handler.
+
+        Arguments:
+        - obj: the table cell
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        if self._script.isSpreadSheetCell(obj):
+            if self._script.inputLineForCell == None:
+                self._script.inputLineForCell = \
+                            self._script.locateInputLine(obj)
+
+            regions = []
+            text = self._script.getDisplayedText(obj)
+            componentRegion = braille.Component(obj, text)
+            regions.append(componentRegion)
+
+            # If the spread sheet table cell has something in it, then we
+            # want to append the name of the cell (which will be its location).
+            # Note that if the cell was empty, then
+            # self._script.getDisplayedText will have already done this for us.
+            #
+            try:
+                if obj.queryText():
+                    objectText = self._script.getText(obj, 0, -1)
+                    if objectText and len(objectText) != 0:
+                        regions.append(braille.Region(" " + obj.name))
+            except NotImplementedError:
+                pass
+
+            return [regions, componentRegion]
+
+        else:
+            # Check to see how many children this table cell has. If it's
+            # just one (or none), then pass it on to the superclass to be
+            # processed.
+            #
+            # If it's more than one, then get the braille regions for each
+            # child, and call this method again.
+            #
+            if obj.childCount <= 1:
+                regions = braillegenerator.BrailleGenerator.\
+                              _getBrailleRegionsForTableCell(self, obj)
+            else:
+                regions = []
+                for child in obj:
+                    [cellRegions, focusRegion] = \
+                                self._getBrailleRegionsForTableCell(child)
+                    regions.extend(cellRegions)
+                return [regions, focusRegion]
+
+        return regions

Added: trunk/src/orca/scripts/apps/soffice/constants.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/constants.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,3 @@
+# Whether we speak spread sheet cell coordinates as the user moves around.
+#
+speakCellCoordinates = True

Copied: trunk/src/orca/scripts/apps/soffice/script.py (from r3875, /trunk/src/orca/scripts/StarOffice.py)
==============================================================================
--- /trunk/src/orca/scripts/StarOffice.py	(original)
+++ trunk/src/orca/scripts/apps/soffice/script.py	Fri May  2 21:21:19 2008
@@ -33,758 +33,18 @@
 import orca.default as default
 import orca.input_event as input_event
 import orca.braille as braille
-import orca.braillegenerator as braillegenerator
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.speech as speech
-import orca.speechgenerator as speechgenerator
 import orca.settings as settings
 import orca.keybindings as keybindings
-import orca.where_am_I as where_am_I
 
 from orca.orca_i18n import _ # for gettext support
-from orca.orca_i18n import Q_     # to provide qualified translatable strings
 
-# Whether we speak spread sheet cell coordinates as the user moves around.
-#
-speakCellCoordinates = True
-
-class WhereAmI(where_am_I.WhereAmI):
-
-    def __init__(self, script):
-        """Create a new WhereAmI that will be used to speak information
-        about the current object of interest.
-        """
-
-        where_am_I.WhereAmI.__init__(self, script)
-
-    def _speakTableCell(self, obj, basicOnly):
-        """Given the nature of OpenOffice Calc, Orca should override the
-        default whereAmI behavior when the item with focus is a cell
-        within Calc. In this instance, the following information should
-        be spoken/displayed:
-
-        1. "Cell"
-        2. the cell coordinates
-        3. the cell contents:
-            A. if the cell is empty, "blank"
-            B. if the cell is being edited AND if some text within the cell
-            is selected, the selected text followed by "selected"
-            C. otherwise, the full contents of the cell
-        """
-
-        if not self._script.isSpreadSheetCell(obj):
-            return where_am_I.WhereAmI._speakTableCell(self, obj, basicOnly)
-
-        utterances = []
-        utterances.append(_("cell"))
-
-        table = obj.parent.queryTable()
-
-        # Translators: this represents the column we're
-        # on in a table.
-        #
-        text = _("column %d") % \
-               (table.getColumnAtIndex(obj.getIndexInParent()) + 1)
-        utterances.append(text)
-
-        # Speak the dynamic column header (if any).
-        #
-        if self._script.dynamicColumnHeaders.has_key(table):
-            row = self._script.dynamicColumnHeaders[table]
-            header = self._script.getDynamicRowHeaderCell(obj, row)
-            try:
-                headerText = header.queryText()
-            except:
-                headerText = None
-
-            if header.childCount > 0:
-                for child in header:
-                    text = self._script.getText(child, 0, -1)
-                    if text:
-                        utterances.append(text)
-            elif headerText:
-                text = self._script.getText(header, 0, -1)
-                if text:
-                    utterances.append(text)
-
-        # Translators: this represents the row number of a table.
-        #
-        text = _("row %d") % (table.getRowAtIndex(obj.getIndexInParent()) + 1)
-        utterances.append(text)
-
-        # Speak the dynamic row header (if any).
-        #
-        if self._script.dynamicRowHeaders.has_key(table):
-            column = self._script.dynamicRowHeaders[table]
-            header = self._script.getDynamicColumnHeaderCell(obj, column)
-            try:
-                headerText = header.queryText()
-            except:
-                headerText = None
-
-            if header.childCount > 0:
-                for child in header:
-                    text = self._script.getText(child, 0, -1)
-                    if text:
-                        utterances.append(text)
-            elif headerText:
-                text = self._script.getText(header, 0, -1)
-                if text:
-                    utterances.append(text)
-
-        text = obj.queryText().getText(0, -1)
-        utterances.append(text)
-
-        debug.println(self._debugLevel, "calc table cell utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
-
-    def _speakParagraph(self, obj, basicOnly):
-        """OpenOffice Calc cells have the role "paragraph" when
-        they are being edited.
-        """
-
-        top = self._script.getTopLevel(obj)
-        if top and top.name.endswith(" Calc"):
-            self._speakCalc(obj, basicOnly)
-        elif top and top.name.endswith(" Writer"):
-            self._speakText(obj, basicOnly)
-
-    def _speakCalc(self, obj, basicOnly):
-        """Speak a OpenOffice Calc cell.
-        """
-
-        utterances = []
-        utterances.append(_("cell"))
-
-        # No way to get cell coordinates?
-
-        [textContents, startOffset, endOffset, selected] = \
-            self._getTextContents(obj, basicOnly)
-        text = textContents
-        utterances.append(text)
-        if selected:
-            # Translators: when the user selects (highlights) text in
-            # a document, Orca lets them know this.
-            #
-            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
-            #
-            text = Q_("text|selected")
-            utterances.append(text)
-
-        debug.println(self._debugLevel, "editable table cell utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
-
-    def _getCalcFrameAndSheet(self, obj):
-        """Returns the Calc frame and sheet
-        """
-
-        mylist = [None, None]
-
-        parent = obj.parent
-        while parent and (parent.parent != parent):
-            # debug.println(self._debugLevel,
-            #             "_getCalcFrameAndSheet: parent=%s, %s" % \
-            #             (parent.getRole(), self._getObjLabelAndName(parent)))
-            if parent.getRole() == pyatspi.ROLE_FRAME:
-                mylist[0] = parent
-            if parent.getRole() == pyatspi.ROLE_TABLE:
-                mylist[1] = parent
-            parent = parent.parent
-
-        return mylist
-
-    def _speakCalcStatusBar(self):
-        """Speaks the OpenOffice Calc statusbar.
-        """
-
-        if not self._statusBar:
-            return
-
-        utterances = []
-        for child in self._statusBar:
-            text = self._getObjName(child)
-            utterances.append(text)
-
-        debug.println(self._debugLevel, "Calc statusbar utterances=%s" % \
-                      utterances)
-        speech.speakUtterances(utterances)
-
-    def speakTitle(self, obj):
-        """Speak the title bar.
-
-        Calc-Specific Handling: 
-
-        1. The contents of the title bar of the application main window
-        2. The title of the current worksheet
-
-        Note that if the application with focus is Calc, but a cell does not
-        have focus, the default behavior should be used.
-        """
-
-        top = self._script.getTopLevel(obj)
-        if top and not top.name.endswith(" Calc"):
-            return where_am_I.WhereAmI.speakTitle(self, obj)
-
-        utterances = []
-
-        mylist = self._getCalcFrameAndSheet(obj)
-        if mylist[0]:
-            text = self.getObjLabelAndName(mylist[0])
-            utterances.append(text)
-        if mylist[1]:
-            text = self.getObjLabelAndName(mylist[1])
-            utterances.append(text)
-
-        debug.println(self._debugLevel,
-                      "Calc titlebar and sheet utterances=%s" % utterances)
-        speech.speakUtterances(utterances)
-
-    def speakStatusBar(self, obj):
-        """Speak the status bar contents.
-
-        Note that if the application with focus is Calc, but a cell does not
-        have focus, the default behavior should be used.
-        """
-
-        top = self._script.getTopLevel(obj)
-        if top and not top.name.endswith(" Calc"):
-            return where_am_I.WhereAmI.speakStatusBar(self, obj)
-
-        utterances = []
-
-        mylist = self._getCalcFrameAndSheet(obj)
-        if mylist[0]:
-            self._statusBar = None
-            self._getStatusBar(mylist[0])
-            if self._statusBar:
-                self._speakCalcStatusBar()
-
-        debug.println(self._debugLevel,
-                      "Calc status bar utterances=%s" % utterances)
-        speech.speakUtterances(utterances)
-
-class BrailleGenerator(braillegenerator.BrailleGenerator):
-    """Overrides _getBrailleRegionsForTableCellRow so that , when we are
-    in a spread sheet, we can braille the dynamic row and column headers
-    (assuming they are set).
-    Overrides _getBrailleRegionsForTableCell so that, when we are in
-    a spread sheet, we can braille the location of the table cell as well
-    as the contents.
-    """
-
-    def __init__(self, script):
-        braillegenerator.BrailleGenerator.__init__(self, script)
-
-    def _getBrailleRegionsForTableCellRow(self, obj):
-        """Get the braille for a table cell row or a single table cell
-        if settings.readTableCellRow is False.
-
-        Arguments:
-        - obj: the table cell
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        focusRegion = None
-        regions = []
-
-        # Check to see if this spread sheet cell has either a dynamic
-        # column heading or row heading (or both) associated with it.
-        # If it does, then braille those first before brailling the
-        # cell contents.
-        #
-        table = self._script.getTable(obj)
-        parent = obj.parent
-        try:
-            parentTable = parent.queryTable()
-        except NotImplementedError:
-            parentTable = None
-
-        if self._script.pointOfReference.has_key("lastColumn") and \
-              self._script.pointOfReference["lastColumn"] != \
-              parentTable.getColumnAtIndex(obj.getIndexInParent()):
-            if self._script.dynamicColumnHeaders.has_key(table):
-                row = self._script.dynamicColumnHeaders[table]
-                header = self._script.getDynamicRowHeaderCell(obj, row)
-                try:
-                    headerText = header.queryText()
-                except:
-                    headerText = None
-
-                if header.childCount > 0:
-                    for child in header:
-                        text = self._script.getText(child, 0, -1)
-                        if text:
-                            regions.append(braille.Region(" " + text + " "))
-                elif headerText:
-                    text = self._script.getText(header, 0, -1)
-                    if text:
-                        regions.append(braille.Region(" " + text + " "))
-
-        if self._script.pointOfReference.has_key("lastRow") and \
-              self._script.pointOfReference['lastRow'] != \
-              parentTable.getRowAtIndex(obj.getIndexInParent()):
-            if self._script.dynamicRowHeaders.has_key(table):
-                column = self._script.dynamicRowHeaders[table]
-                header = self._script.getDynamicColumnHeaderCell(obj, column)
-                try:
-                    headerText = header.queryText()
-                except:
-                    headerText = None
-
-                if header.childCount > 0:
-                    for child in header:
-                        text = self._script.getText(child, 0, -1)
-                        if text:
-                            regions.append(braille.Region(" " + text + " "))
-                elif headerText:
-                    text = self._script.getText(header, 0, -1)
-                    if text:
-                        regions.append(braille.Region(" " + text + " "))
-
-        if self._script.isSpreadSheetCell(obj):
-
-            # Adding in a check here to make sure that the parent is a
-            # valid table. It's possible that the parent could be a
-            # table cell too (see bug #351501).
-            #
-            if settings.readTableCellRow and parentTable:
-                rowRegions = []
-                savedBrailleVerbosityLevel = settings.brailleVerbosityLevel
-                settings.brailleVerbosityLevel = \
-                                             settings.VERBOSITY_LEVEL_BRIEF
-
-                parent = obj.parent
-                row = parentTable.getRowAtIndex(obj.getIndexInParent())
-                column = parentTable.getColumnAtIndex(obj.getIndexInParent())
-
-                # This is an indication of whether we should speak all the
-                # table cells (the user has moved focus up or down a row),
-                # or just the current one (focus has moved left or right in
-                # the same row).
-                #
-                speakAll = True
-                if self._script.pointOfReference.has_key("lastRow") and \
-                    self._script.pointOfReference.has_key("lastColumn"):
-                    pointOfReference = self._script.pointOfReference
-                    speakAll = \
-                        (pointOfReference["lastRow"] != row) or \
-                           ((row == 0 or row == parentTable.nRows-1) and \
-                            pointOfReference["lastColumn"] == column)
-
-                if speakAll:
-                    [startIndex, endIndex] = \
-                        self._script.getSpreadSheetRowRange(obj)
-                    for i in range(startIndex, endIndex+1):
-                        cell = parentTable.getAccessibleAt(row, i)
-                        showing = cell.getState().contains( \
-                                        pyatspi.STATE_SHOWING)
-                        if showing:
-                            [cellRegions, focusRegion] = \
-                                self._getBrailleRegionsForTableCell(cell)
-                            if len(rowRegions):
-                                rowRegions.append(braille.Region(" "))
-                            rowRegions.append(cellRegions[0])
-                    regions.extend(rowRegions)
-                    settings.brailleVerbosityLevel = savedBrailleVerbosityLevel
-                else:
-                    [cellRegions, focusRegion] = \
-                                self._getBrailleRegionsForTableCell(obj)
-                    regions.extend(cellRegions)
-            else:
-                [cellRegions, focusRegion] = \
-                                self._getBrailleRegionsForTableCell(obj)
-                regions.extend(cellRegions)
-            regions = [regions, focusRegion]
-        else:
-            [cellRegions, focusRegion] = \
-                braillegenerator.BrailleGenerator.\
-                    _getBrailleRegionsForTableCellRow(self, obj)
-            regions.extend(cellRegions)
-            regions = [regions, focusRegion]
-
-        return regions
-
-    def _getBrailleRegionsForTableCell(self, obj):
-        """Get the braille for a table cell. If this isn't inside a
-        spread sheet, just return the regions returned by the default
-        table cell braille handler.
-
-        Arguments:
-        - obj: the table cell
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        if self._script.isSpreadSheetCell(obj):
-            if self._script.inputLineForCell == None:
-                self._script.inputLineForCell = \
-                            self._script.locateInputLine(obj)
-
-            regions = []
-            text = self._script.getDisplayedText(obj)
-            componentRegion = braille.Component(obj, text)
-            regions.append(componentRegion)
-
-            # If the spread sheet table cell has something in it, then we
-            # want to append the name of the cell (which will be its location).
-            # Note that if the cell was empty, then
-            # self._script.getDisplayedText will have already done this for us.
-            #
-            try:
-                if obj.queryText():
-                    objectText = self._script.getText(obj, 0, -1)
-                    if objectText and len(objectText) != 0:
-                        regions.append(braille.Region(" " + obj.name))
-            except NotImplementedError:
-                pass
-
-            return [regions, componentRegion]
-
-        else:
-            # Check to see how many children this table cell has. If it's
-            # just one (or none), then pass it on to the superclass to be
-            # processed.
-            #
-            # If it's more than one, then get the braille regions for each
-            # child, and call this method again.
-            #
-            if obj.childCount <= 1:
-                regions = braillegenerator.BrailleGenerator.\
-                              _getBrailleRegionsForTableCell(self, obj)
-            else:
-                regions = []
-                for child in obj:
-                    [cellRegions, focusRegion] = \
-                                self._getBrailleRegionsForTableCell(child)
-                    regions.extend(cellRegions)
-                return [regions, focusRegion]
-
-        return regions
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Overrides _getSpeechForComboBox so that we can provide a name for
-    the Calc Name combo box.
-    Overrides _getSpeechForTableCellRow so that , when we are in a
-    spread sheet, we can speak the dynamic row and column headers
-    (assuming they are set).
-    Overrides _getSpeechForTableCell so that, when we are in a spread
-    sheet, we can speak the location of the table cell as well as the
-    contents.
-    Overrides _getSpeechForToggleButton so that, when the toggle buttons
-    on the Formatting toolbar change state, we provide both the name and
-    the state (as "on" or "off")
-    Overrides _getSpeechForPushButton because sometimes the toggle buttons
-    on the Formatting toolbar claim to be push buttons.
-    """
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-
-    def _getSpeechForComboBox(self, obj, already_focused):
-        """Get the speech for a combo box. If the combo box already has focus,
-        then only the selection is spoken.
-        Also provides a name for the OOo Calc Name combo box. This name is
-        provided in clause 5) of locusOfFocusChanged() below.
-
-        Arguments:
-        - obj: the combo box
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-
-        if not already_focused:
-            label = self._getSpeechForObjectLabel(obj)
-            if not label:
-                label = [ obj.name ]
-            utterances.extend(label)
-        else:
-            label = None
-
-        name = self._getSpeechForObjectName(obj)
-        if name != label:
-            utterances.extend(name)
-
-        if not already_focused:
-            utterances.extend(self._getSpeechForObjectRole(obj))
-
-        utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        self._debugGenerator("_getSpeechForComboBox",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForTable(self, obj, already_focused):
-        """Get the speech for a table
-
-        Arguments:
-        - obj: the table
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = self._getDefaultSpeech(obj, already_focused)
-
-        self._debugGenerator("_getSpeechForTable",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        # If this is a table with no children, then let the user know.
-        #
-        if not obj.childCount:
-            # Translators: this indicates that there are zero items in
-            # a layered pane or table.
-            #
-            utterances.append(_("0 items"))
-
-        return utterances
-
-    def _getSpeechForTableCellRow(self, obj, already_focused):
-        """Get the speech for a table cell row or a single table cell
-        if settings.readTableCellRow is False. If this isn't inside a
-        spread sheet, just return the utterances returned by the default
-        table cell speech handler.
-
-        Arguments:
-        - obj: the table cell
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-
-        if not already_focused:
-
-            # Check to see if this spread sheet cell has either a dynamic
-            # column heading or row heading (or both) associated with it.
-            # If it does, then speak those first before speaking the cell
-            # contents.
-            #
-            table = self._script.getTable(obj)
-            parent = obj.parent
-            try:
-                parentTable = parent.queryTable()
-            except NotImplementedError:
-                parentTable = None
-
-            if self._script.pointOfReference.has_key("lastColumn") and \
-               self._script.pointOfReference["lastColumn"] != \
-               parentTable.getColumnAtIndex(obj.getIndexInParent()):
-                if self._script.dynamicColumnHeaders.has_key(table):
-                    row = self._script.dynamicColumnHeaders[table]
-                    header = self._script.getDynamicRowHeaderCell(obj, row)
-                    try:
-                        headerText = header.queryText()
-                    except:
-                        headerText = None
-
-                    if header.childCount > 0:
-                        for child in header:
-                            text = self._script.getText(child, 0, -1)
-                            if text:
-                                utterances.append(text)
-                    elif headerText:
-                        text = self._script.getText(header, 0, -1)
-                        if text:
-                            utterances.append(text)
-
-            if self._script.pointOfReference.has_key("lastRow") and \
-               self._script.pointOfReference["lastRow"] != \
-               parentTable.getRowAtIndex(obj.getIndexInParent()):
-                if self._script.dynamicRowHeaders.has_key(table):
-                    column = self._script.dynamicRowHeaders[table]
-                    header = self._script.getDynamicColumnHeaderCell(obj,
-                                                                     column)
-                    try:
-                        headerText = header.queryText()
-                    except:
-                        headerText = None
-
-                    if header.childCount > 0:
-                        for child in header:
-                            text = self._script.getText(child, 0, -1)
-                            if text:
-                                utterances.append(text)
-                    elif headerText:
-                        text = self._script.getText(header, 0, -1)
-                        if text:
-                            utterances.append(text)
-
-        if self._script.isSpreadSheetCell(obj):
-            if not already_focused:
-                if settings.readTableCellRow:
-                    parent = obj.parent
-                    row = parentTable.getRowAtIndex(obj.getIndexInParent())
-                    column = \
-                        parentTable.getColumnAtIndex(obj.getIndexInParent())
-
-                    # This is an indication of whether we should speak all the
-                    # table cells (the user has moved focus up or down a row),
-                    # or just the current one (focus has moved left or right in
-                    # the same row).
-                    #
-                    speakAll = True
-                    if self._script.pointOfReference.has_key("lastRow") and \
-                        self._script.pointOfReference.has_key("lastColumn"):
-                        pointOfReference = self._script.pointOfReference
-                        speakAll = (pointOfReference["lastRow"] != row) or \
-                               ((row == 0 or row == parentTable.nRows-1) and \
-                                pointOfReference["lastColumn"] == column)
-
-                    if speakAll:
-                        [startIndex, endIndex] = \
-                            self._script.getSpreadSheetRowRange(obj)
-                        for i in range(startIndex, endIndex+1):
-                            cell = parentTable.getAccessibleAt(row, i)
-                            showing = cell.getState().contains( \
-                                          pyatspi.STATE_SHOWING)
-                            if showing:
-                                utterances.extend(self._getSpeechForTableCell(\
-                                                  cell, already_focused))
-                    else:
-                        utterances.extend(self._getSpeechForTableCell(obj,
-                                                             already_focused))
-                else:
-                    utterances.extend(self._getSpeechForTableCell(obj,
-                                                             already_focused))
-        else:
-            utterances.extend(speechgenerator.SpeechGenerator.\
-                _getSpeechForTableCellRow(self, obj, already_focused))
-
-        return utterances
-
-    def _getSpeechForTableCell(self, obj, already_focused):
-        """Get the speech for a table cell. If this isn't inside a
-        spread sheet, just return the utterances returned by the default
-        table cell speech handler.
-
-        Arguments:
-        - obj: the table cell
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        if self._script.isSpreadSheetCell(obj):
-            utterances = []
-
-            if self._script.inputLineForCell == None:
-                self._script.inputLineForCell = \
-                            self._script.locateInputLine(obj)
-
-            try:
-                if obj.queryText():
-                    objectText = self._script.getText(obj, 0, -1)
-                    if not speakCellCoordinates and len(objectText) == 0:
-                        # Translators: this indicates an empty (blank) spread
-                        # sheet cell.
-                        #
-                        objectText = _("blank")
-
-                    utterances.append(objectText)
-            except NotImplementedError:
-                pass
-
-            if speakCellCoordinates:
-                nameList = obj.name.split()
-                utterances.append(nameList[1])
-        else:
-            # Check to see how many children this table cell has. If it's
-            # just one (or none), then pass it on to the superclass to be
-            # processed.
-            #
-            # If it's more than one, then get the speech for each child,
-            # and call this method again.
-            #
-            if obj.childCount <= 1:
-                utterances = speechgenerator.SpeechGenerator.\
-                    _getSpeechForTableCell(self, obj, already_focused)
-            else:
-                utterances = []
-                for child in obj:
-                    utterances.extend(self._getSpeechForTableCell(child,
-                                                        already_focused))
-
-        return utterances
-
-    def _getSpeechForToggleButton(self, obj, already_focused):
-        """Get the speech for a toggle button.  We always want to speak the
-        state if it's on a toolbar.
-
-        Arguments:
-        - obj: the toggle button
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
-            if obj.getState().contains(pyatspi.STATE_CHECKED):
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("on")
-            else:
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("off")
-
-            utterances.append(obj.name)
-            utterances.append(checkedState)
-        else:
-            utterances.extend(speechgenerator.SpeechGenerator.\
-                _getSpeechForToggleButton(self, obj, already_focused))
-
-        return utterances
-
-    def _getSpeechForPushButton(self, obj, already_focused):
-        """Get the speech for a push button.  We always want to speak the
-        state if it's on a toolbar.
-
-        Arguments:
-        - obj: the push button
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
-            if obj.getState().contains(pyatspi.STATE_CHECKED):
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("on")
-            else:
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("off")
-
-            utterances.append(obj.name)
-            utterances.append(checkedState)
-        else:
-            utterances.extend(speechgenerator.SpeechGenerator.\
-                _getSpeechForPushButton(self, obj, already_focused))
-
-        return utterances
-
-########################################################################
-#                                                                      #
-# The StarOffice script class.                                         #
-#                                                                      #
-########################################################################
+from speech_generator import SpeechGenerator
+from braille_generator import BrailleGenerator
+from where_am_i import WhereAmI
+from constants import speakCellCoordinates
 
 class Script(default.Script):
 

Added: trunk/src/orca/scripts/apps/soffice/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,348 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for StarOffice and OpenOffice."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.speechgenerator as speechgenerator
+import orca.settings as settings
+
+from orca.orca_i18n import _ # for gettext support
+
+from constants import speakCellCoordinates
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Overrides _getSpeechForComboBox so that we can provide a name for
+    the Calc Name combo box.
+    Overrides _getSpeechForTableCellRow so that , when we are in a
+    spread sheet, we can speak the dynamic row and column headers
+    (assuming they are set).
+    Overrides _getSpeechForTableCell so that, when we are in a spread
+    sheet, we can speak the location of the table cell as well as the
+    contents.
+    Overrides _getSpeechForToggleButton so that, when the toggle buttons
+    on the Formatting toolbar change state, we provide both the name and
+    the state (as "on" or "off")
+    Overrides _getSpeechForPushButton because sometimes the toggle buttons
+    on the Formatting toolbar claim to be push buttons.
+    """
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+
+    def _getSpeechForComboBox(self, obj, already_focused):
+        """Get the speech for a combo box. If the combo box already has focus,
+        then only the selection is spoken.
+        Also provides a name for the OOo Calc Name combo box. This name is
+        provided in clause 5) of locusOfFocusChanged() below.
+
+        Arguments:
+        - obj: the combo box
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = []
+
+        if not already_focused:
+            label = self._getSpeechForObjectLabel(obj)
+            if not label:
+                label = [ obj.name ]
+            utterances.extend(label)
+        else:
+            label = None
+
+        name = self._getSpeechForObjectName(obj)
+        if name != label:
+            utterances.extend(name)
+
+        if not already_focused:
+            utterances.extend(self._getSpeechForObjectRole(obj))
+
+        utterances.extend(self._getSpeechForObjectAvailability(obj))
+
+        self._debugGenerator("_getSpeechForComboBox",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForTable(self, obj, already_focused):
+        """Get the speech for a table
+
+        Arguments:
+        - obj: the table
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = self._getDefaultSpeech(obj, already_focused)
+
+        self._debugGenerator("_getSpeechForTable",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        # If this is a table with no children, then let the user know.
+        #
+        if not obj.childCount:
+            # Translators: this indicates that there are zero items in
+            # a layered pane or table.
+            #
+            utterances.append(_("0 items"))
+
+        return utterances
+
+    def _getSpeechForTableCellRow(self, obj, already_focused):
+        """Get the speech for a table cell row or a single table cell
+        if settings.readTableCellRow is False. If this isn't inside a
+        spread sheet, just return the utterances returned by the default
+        table cell speech handler.
+
+        Arguments:
+        - obj: the table cell
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = []
+
+        if not already_focused:
+
+            # Check to see if this spread sheet cell has either a dynamic
+            # column heading or row heading (or both) associated with it.
+            # If it does, then speak those first before speaking the cell
+            # contents.
+            #
+            table = self._script.getTable(obj)
+            parent = obj.parent
+            try:
+                parentTable = parent.queryTable()
+            except NotImplementedError:
+                parentTable = None
+
+            if self._script.pointOfReference.has_key("lastColumn") and \
+               self._script.pointOfReference["lastColumn"] != \
+               parentTable.getColumnAtIndex(obj.getIndexInParent()):
+                if self._script.dynamicColumnHeaders.has_key(table):
+                    row = self._script.dynamicColumnHeaders[table]
+                    header = self._script.getDynamicRowHeaderCell(obj, row)
+                    try:
+                        headerText = header.queryText()
+                    except:
+                        headerText = None
+
+                    if header.childCount > 0:
+                        for child in header:
+                            text = self._script.getText(child, 0, -1)
+                            if text:
+                                utterances.append(text)
+                    elif headerText:
+                        text = self._script.getText(header, 0, -1)
+                        if text:
+                            utterances.append(text)
+
+            if self._script.pointOfReference.has_key("lastRow") and \
+               self._script.pointOfReference["lastRow"] != \
+               parentTable.getRowAtIndex(obj.getIndexInParent()):
+                if self._script.dynamicRowHeaders.has_key(table):
+                    column = self._script.dynamicRowHeaders[table]
+                    header = self._script.getDynamicColumnHeaderCell(obj,
+                                                                     column)
+                    try:
+                        headerText = header.queryText()
+                    except:
+                        headerText = None
+
+                    if header.childCount > 0:
+                        for child in header:
+                            text = self._script.getText(child, 0, -1)
+                            if text:
+                                utterances.append(text)
+                    elif headerText:
+                        text = self._script.getText(header, 0, -1)
+                        if text:
+                            utterances.append(text)
+
+        if self._script.isSpreadSheetCell(obj):
+            if not already_focused:
+                if settings.readTableCellRow:
+                    parent = obj.parent
+                    row = parentTable.getRowAtIndex(obj.getIndexInParent())
+                    column = \
+                        parentTable.getColumnAtIndex(obj.getIndexInParent())
+
+                    # This is an indication of whether we should speak all the
+                    # table cells (the user has moved focus up or down a row),
+                    # or just the current one (focus has moved left or right in
+                    # the same row).
+                    #
+                    speakAll = True
+                    if self._script.pointOfReference.has_key("lastRow") and \
+                        self._script.pointOfReference.has_key("lastColumn"):
+                        pointOfReference = self._script.pointOfReference
+                        speakAll = (pointOfReference["lastRow"] != row) or \
+                               ((row == 0 or row == parentTable.nRows-1) and \
+                                pointOfReference["lastColumn"] == column)
+
+                    if speakAll:
+                        [startIndex, endIndex] = \
+                            self._script.getSpreadSheetRowRange(obj)
+                        for i in range(startIndex, endIndex+1):
+                            cell = parentTable.getAccessibleAt(row, i)
+                            showing = cell.getState().contains( \
+                                          pyatspi.STATE_SHOWING)
+                            if showing:
+                                utterances.extend(self._getSpeechForTableCell(\
+                                                  cell, already_focused))
+                    else:
+                        utterances.extend(self._getSpeechForTableCell(obj,
+                                                             already_focused))
+                else:
+                    utterances.extend(self._getSpeechForTableCell(obj,
+                                                             already_focused))
+        else:
+            utterances.extend(speechgenerator.SpeechGenerator.\
+                _getSpeechForTableCellRow(self, obj, already_focused))
+
+        return utterances
+
+    def _getSpeechForTableCell(self, obj, already_focused):
+        """Get the speech for a table cell. If this isn't inside a
+        spread sheet, just return the utterances returned by the default
+        table cell speech handler.
+
+        Arguments:
+        - obj: the table cell
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        if self._script.isSpreadSheetCell(obj):
+            utterances = []
+
+            if self._script.inputLineForCell == None:
+                self._script.inputLineForCell = \
+                            self._script.locateInputLine(obj)
+
+            try:
+                if obj.queryText():
+                    objectText = self._script.getText(obj, 0, -1)
+                    if not speakCellCoordinates and len(objectText) == 0:
+                        # Translators: this indicates an empty (blank) spread
+                        # sheet cell.
+                        #
+                        objectText = _("blank")
+
+                    utterances.append(objectText)
+            except NotImplementedError:
+                pass
+
+            if speakCellCoordinates:
+                nameList = obj.name.split()
+                utterances.append(nameList[1])
+        else:
+            # Check to see how many children this table cell has. If it's
+            # just one (or none), then pass it on to the superclass to be
+            # processed.
+            #
+            # If it's more than one, then get the speech for each child,
+            # and call this method again.
+            #
+            if obj.childCount <= 1:
+                utterances = speechgenerator.SpeechGenerator.\
+                    _getSpeechForTableCell(self, obj, already_focused)
+            else:
+                utterances = []
+                for child in obj:
+                    utterances.extend(self._getSpeechForTableCell(child,
+                                                        already_focused))
+
+        return utterances
+
+    def _getSpeechForToggleButton(self, obj, already_focused):
+        """Get the speech for a toggle button.  We always want to speak the
+        state if it's on a toolbar.
+
+        Arguments:
+        - obj: the toggle button
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = []
+        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
+            if obj.getState().contains(pyatspi.STATE_CHECKED):
+                # Translators: this represents the state of a check box
+                #
+                checkedState = _("on")
+            else:
+                # Translators: this represents the state of a check box
+                #
+                checkedState = _("off")
+
+            utterances.append(obj.name)
+            utterances.append(checkedState)
+        else:
+            utterances.extend(speechgenerator.SpeechGenerator.\
+                _getSpeechForToggleButton(self, obj, already_focused))
+
+        return utterances
+
+    def _getSpeechForPushButton(self, obj, already_focused):
+        """Get the speech for a push button.  We always want to speak the
+        state if it's on a toolbar.
+
+        Arguments:
+        - obj: the push button
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = []
+        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
+            if obj.getState().contains(pyatspi.STATE_CHECKED):
+                # Translators: this represents the state of a check box
+                #
+                checkedState = _("on")
+            else:
+                # Translators: this represents the state of a check box
+                #
+                checkedState = _("off")
+
+            utterances.append(obj.name)
+            utterances.append(checkedState)
+        else:
+            utterances.extend(speechgenerator.SpeechGenerator.\
+                _getSpeechForPushButton(self, obj, already_focused))
+
+        return utterances

Added: trunk/src/orca/scripts/apps/soffice/where_am_i.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/apps/soffice/where_am_i.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,252 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for StarOffice and OpenOffice."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.debug as debug
+import orca.speech as speech
+import orca.where_am_I as where_am_I
+
+from orca.orca_i18n import _ # for gettext support
+from orca.orca_i18n import Q_     # to provide qualified translatable strings
+
+class WhereAmI(where_am_I.WhereAmI):
+
+    def __init__(self, script):
+        """Create a new WhereAmI that will be used to speak information
+        about the current object of interest.
+        """
+
+        where_am_I.WhereAmI.__init__(self, script)
+
+    def _speakTableCell(self, obj, basicOnly):
+        """Given the nature of OpenOffice Calc, Orca should override the
+        default whereAmI behavior when the item with focus is a cell
+        within Calc. In this instance, the following information should
+        be spoken/displayed:
+
+        1. "Cell"
+        2. the cell coordinates
+        3. the cell contents:
+            A. if the cell is empty, "blank"
+            B. if the cell is being edited AND if some text within the cell
+            is selected, the selected text followed by "selected"
+            C. otherwise, the full contents of the cell
+        """
+
+        if not self._script.isSpreadSheetCell(obj):
+            return where_am_I.WhereAmI._speakTableCell(self, obj, basicOnly)
+
+        utterances = []
+        utterances.append(_("cell"))
+
+        table = obj.parent.queryTable()
+
+        # Translators: this represents the column we're
+        # on in a table.
+        #
+        text = _("column %d") % \
+               (table.getColumnAtIndex(obj.getIndexInParent()) + 1)
+        utterances.append(text)
+
+        # Speak the dynamic column header (if any).
+        #
+        if self._script.dynamicColumnHeaders.has_key(table):
+            row = self._script.dynamicColumnHeaders[table]
+            header = self._script.getDynamicRowHeaderCell(obj, row)
+            try:
+                headerText = header.queryText()
+            except:
+                headerText = None
+
+            if header.childCount > 0:
+                for child in header:
+                    text = self._script.getText(child, 0, -1)
+                    if text:
+                        utterances.append(text)
+            elif headerText:
+                text = self._script.getText(header, 0, -1)
+                if text:
+                    utterances.append(text)
+
+        # Translators: this represents the row number of a table.
+        #
+        text = _("row %d") % (table.getRowAtIndex(obj.getIndexInParent()) + 1)
+        utterances.append(text)
+
+        # Speak the dynamic row header (if any).
+        #
+        if self._script.dynamicRowHeaders.has_key(table):
+            column = self._script.dynamicRowHeaders[table]
+            header = self._script.getDynamicColumnHeaderCell(obj, column)
+            try:
+                headerText = header.queryText()
+            except:
+                headerText = None
+
+            if header.childCount > 0:
+                for child in header:
+                    text = self._script.getText(child, 0, -1)
+                    if text:
+                        utterances.append(text)
+            elif headerText:
+                text = self._script.getText(header, 0, -1)
+                if text:
+                    utterances.append(text)
+
+        text = obj.queryText().getText(0, -1)
+        utterances.append(text)
+
+        debug.println(self._debugLevel, "calc table cell utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)
+
+    def _speakParagraph(self, obj, basicOnly):
+        """OpenOffice Calc cells have the role "paragraph" when
+        they are being edited.
+        """
+
+        top = self._script.getTopLevel(obj)
+        if top and top.name.endswith(" Calc"):
+            self._speakCalc(obj, basicOnly)
+        elif top and top.name.endswith(" Writer"):
+            self._speakText(obj, basicOnly)
+
+    def _speakCalc(self, obj, basicOnly):
+        """Speak a OpenOffice Calc cell.
+        """
+
+        utterances = []
+        utterances.append(_("cell"))
+
+        # No way to get cell coordinates?
+
+        [textContents, startOffset, endOffset, selected] = \
+            self._getTextContents(obj, basicOnly)
+        text = textContents
+        utterances.append(text)
+        if selected:
+            # Translators: when the user selects (highlights) text in
+            # a document, Orca lets them know this.
+            #
+            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+            #
+            text = Q_("text|selected")
+            utterances.append(text)
+
+        debug.println(self._debugLevel, "editable table cell utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)
+
+    def _getCalcFrameAndSheet(self, obj):
+        """Returns the Calc frame and sheet
+        """
+
+        mylist = [None, None]
+
+        parent = obj.parent
+        while parent and (parent.parent != parent):
+            # debug.println(self._debugLevel,
+            #             "_getCalcFrameAndSheet: parent=%s, %s" % \
+            #             (parent.getRole(), self._getObjLabelAndName(parent)))
+            if parent.getRole() == pyatspi.ROLE_FRAME:
+                mylist[0] = parent
+            if parent.getRole() == pyatspi.ROLE_TABLE:
+                mylist[1] = parent
+            parent = parent.parent
+
+        return mylist
+
+    def _speakCalcStatusBar(self):
+        """Speaks the OpenOffice Calc statusbar.
+        """
+
+        if not self._statusBar:
+            return
+
+        utterances = []
+        for child in self._statusBar:
+            text = self._getObjName(child)
+            utterances.append(text)
+
+        debug.println(self._debugLevel, "Calc statusbar utterances=%s" % \
+                      utterances)
+        speech.speakUtterances(utterances)
+
+    def speakTitle(self, obj):
+        """Speak the title bar.
+
+        Calc-Specific Handling: 
+
+        1. The contents of the title bar of the application main window
+        2. The title of the current worksheet
+
+        Note that if the application with focus is Calc, but a cell does not
+        have focus, the default behavior should be used.
+        """
+
+        top = self._script.getTopLevel(obj)
+        if top and not top.name.endswith(" Calc"):
+            return where_am_I.WhereAmI.speakTitle(self, obj)
+
+        utterances = []
+
+        mylist = self._getCalcFrameAndSheet(obj)
+        if mylist[0]:
+            text = self.getObjLabelAndName(mylist[0])
+            utterances.append(text)
+        if mylist[1]:
+            text = self.getObjLabelAndName(mylist[1])
+            utterances.append(text)
+
+        debug.println(self._debugLevel,
+                      "Calc titlebar and sheet utterances=%s" % utterances)
+        speech.speakUtterances(utterances)
+
+    def speakStatusBar(self, obj):
+        """Speak the status bar contents.
+
+        Note that if the application with focus is Calc, but a cell does not
+        have focus, the default behavior should be used.
+        """
+
+        top = self._script.getTopLevel(obj)
+        if top and not top.name.endswith(" Calc"):
+            return where_am_I.WhereAmI.speakStatusBar(self, obj)
+
+        utterances = []
+
+        mylist = self._getCalcFrameAndSheet(obj)
+        if mylist[0]:
+            self._statusBar = None
+            self._getStatusBar(mylist[0])
+            if self._statusBar:
+                self._speakCalcStatusBar()
+
+        debug.println(self._debugLevel,
+                      "Calc status bar utterances=%s" % utterances)
+        speech.speakUtterances(utterances)

Copied: trunk/src/orca/scripts/toolkits/GAIL.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/toolkits/GAIL.py	Fri May  2 21:21:19 2008
@@ -17,7 +17,7 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for GAIL toolkit applications"""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
@@ -25,12 +25,7 @@
 __copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
+import orca.default
 
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+class Script(orca.default.Script):
+    pass

Added: trunk/src/orca/scripts/toolkits/Gecko/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,13 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	bookmarks.py \
+	braille_generator.py \
+	constants.py \
+	__init__.py \
+	script.py \
+	speech_generator.py \
+	where_am_i.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/toolkits/Gecko
+

Added: trunk/src/orca/scripts/toolkits/Gecko/__init__.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/__init__.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,4 @@
+from script import Script
+from speech_generator import SpeechGenerator
+from braille_generator import BrailleGenerator
+from constants import *

Added: trunk/src/orca/scripts/toolkits/Gecko/bookmarks.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/bookmarks.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,292 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Gecko toolkit.
+Please refer to the following URL for more information on the AT-SPI
+implementation in Gecko:
+http://developer.mozilla.org/en/docs/Accessibility/ATSPI_Support
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+import urlparse
+
+import orca.speech as speech
+import orca.bookmarks as bookmarks
+
+from orca.orca_i18n import _
+
+####################################################################
+#                                                                  #
+# Custom bookmarks class                                           #
+#                                                                  #
+####################################################################
+class GeckoBookmarks(bookmarks.Bookmarks):
+    def __init__(self, script):
+        bookmarks.Bookmarks.__init__(self, script)
+        self._currentbookmarkindex = {}
+        
+        
+    def addBookmark(self, inputEvent):
+        """ Add an in-page accessible object bookmark for this key and
+        webpage URI. """ 
+        # form bookmark dictionary key
+        index = (inputEvent.hw_code, self.getURIKey())
+        # convert the current object to a path and bookmark it
+        obj, characterOffset = self._script.getCaretContext()
+        path = self._objToPath()
+        self._bookmarks[index] = path, characterOffset
+        # Translators: this announces that a bookmark has been entered
+        #
+        utterances = [(_('entered bookmark'))]
+        utterances.extend(self._script.speechGenerator.getSpeech \
+                         (obj, False))
+        speech.speakUtterances(utterances)
+        
+    def goToBookmark(self, inputEvent, index=None):
+        """ Go to the bookmark indexed at this key and this page's URI """
+        index = index or (inputEvent.hw_code, self.getURIKey())
+        
+        try:
+            path, characterOffset = self._bookmarks[index]
+        except KeyError:
+            self._script.systemBeep()
+            return
+        # convert our path to an object
+        obj = self.pathToObj(path)
+       
+        if obj:
+            # restore the location
+            self._script.setCaretPosition(obj, characterOffset)
+            self._script.updateBraille(obj)
+            self._script.speakContents( \
+                self._script.getObjectContentsAtOffset(obj, characterOffset))
+            # update the currentbookmark
+            self._currentbookmarkindex[index[1]] = index[0]
+        else:
+            self._script.systemBeep()
+        
+    def bookmarkCurrentWhereAmI(self, inputEvent):
+        """ Report "Where am I" information for this bookmark relative to the 
+        current pointer location."""
+        index = (inputEvent.hw_code, self.getURIKey())
+        try:
+            path, characterOffset = self._bookmarks[index]
+            obj = self.pathToObj(path)
+        except KeyError:
+            self._script.systemBeep()
+            return
+            
+        [cur_obj, cur_characterOffset] = self._script.getCaretContext()
+        
+        # Are they the same object?
+        if self._script.isSameObject(cur_obj, obj):
+            # Translators: this announces that the current object is the same
+            # object pointed to by the bookmark.
+            #
+            speech.speak(_('bookmark is current object'))
+            return
+        # Are their parents the same?
+        elif self._script.isSameObject(cur_obj.parent, obj.parent):
+            # Translators: this announces that the current object's parent and 
+            # the parent of the object pointed to by the bookmark are the same.
+            #
+            speech.speak(_('bookmark and current object have same parent'))
+            return
+        
+        # Do they share a common ancestor?
+        # bookmark's ancestors
+        bookmark_ancestors = []
+        p = obj.parent
+        while p:
+            bookmark_ancestors.append(p)
+            p = p.parent
+        # look at current object's ancestors to compare to bookmark's ancestors
+        p = cur_obj.parent
+        while p:
+            if bookmark_ancestors.count(p) > 0:
+                # Translators: this announces that the bookmark and the current
+                # object share a common ancestor
+                #
+                speech.speak(_('shared ancestor %s') %p.getRole())
+                return
+            p = p.parent
+        
+        # Translators: This announces that a comparison between the bookmark
+        # and the current object can not be determined.
+        #
+        speech.speak(_('comparison unknown'))
+        
+    def saveBookmarks(self, inputEvent):
+        """ Save the bookmarks for this script. """
+        saved = {}
+         
+        # save obj as a path instead of an accessible
+        for index, bookmark in self._bookmarks.iteritems():
+            saved[index] = bookmark[0], bookmark[1]
+            
+        try:
+            self.saveBookmarksToDisk(saved)
+            # Translators: this announces that a bookmark has been saved to 
+            # disk
+            #
+            speech.speak(_('bookmarks saved'))
+        except IOError:
+            # Translators: this announces that a bookmark could not be saved to 
+            # disk
+            #
+            speech.speak(_('bookmarks could not be saved'))
+
+        # Notify the observers
+        for o in self._saveObservers:
+            o()
+            
+    def goToNextBookmark(self, inputEvent):
+        """ Go to the next bookmark location.  If no bookmark has yet to be
+        selected, the first bookmark will be used.  """
+        # The convenience of using a dictionary to add/goto a bookmark is 
+        # offset by the difficulty in finding the next bookmark.  We will 
+        # need to sort our keys to determine the next bookmark on a page by 
+        # page basis.
+        bm_keys = self._bookmarks.keys()
+        current_uri = self.getURIKey()
+        
+        # mine out the hardware keys for this page and sort them
+        thispage_hwkeys = []
+        for bm_key in bm_keys:
+            if bm_key[1] == current_uri:
+                thispage_hwkeys.append(bm_key[0])
+        thispage_hwkeys.sort()
+        
+        # no bookmarks for this page
+        if len(thispage_hwkeys) == 0:
+            self._script.systemBeep()
+            return
+        # only 1 bookmark or we are just starting out
+        elif len(thispage_hwkeys) == 1 or \
+                         not self._currentbookmarkindex.has_key(current_uri):
+            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
+            return
+        
+        # find current bookmark hw_code in our sorted list.  
+        # Go to next one if possible
+        try:
+            index = thispage_hwkeys.index( \
+                                 self._currentbookmarkindex[current_uri])
+            self.goToBookmark(None, index=( \
+                                 thispage_hwkeys[index+1], current_uri))
+        except (ValueError, KeyError, IndexError):
+            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
+            
+    def goToPrevBookmark(self, inputEvent):
+        """ Go to the previous bookmark location.  If no bookmark has yet to be
+        selected, the first bookmark will be used.  """
+        bm_keys = self._bookmarks.keys()
+        current_uri = self.getURIKey()
+        
+        # mine out the hardware keys for this page and sort them
+        thispage_hwkeys = []
+        for bm_key in bm_keys:
+            if bm_key[1] == current_uri:
+                thispage_hwkeys.append(bm_key[0])
+        thispage_hwkeys.sort()
+        
+        # no bookmarks for this page
+        if len(thispage_hwkeys) == 0:
+            self._script.systemBeep()
+            return
+        # only 1 bookmark or we are just starting out
+        elif len(thispage_hwkeys) == 1 or \
+                         not self._currentbookmarkindex.has_key(current_uri):
+            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
+            return
+        
+        # find current bookmark hw_code in our sorted list.  
+        # Go to next one if possible
+        try:
+            index = thispage_hwkeys.index( \
+                            self._currentbookmarkindex[current_uri])
+            self.goToBookmark(None, 
+                              index=(thispage_hwkeys[index-1], current_uri))
+        except (ValueError, KeyError, IndexError):
+            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))    
+            
+    def _objToPickle(self, obj=None):
+        """Given an object, return it's saving (pickleable) format.  In this 
+        case, the obj path is determined relative to the document frame and is 
+        returned as a list.  If obj is not provided, the current caret context
+        is used.  """
+        return self._objToPath(start_obj=obj)
+                               
+    def _objToPath(self, start_obj=None):
+        """Given an object, return it's path from the root accessible.  If obj 
+        is not provided, the current caret context is used. """
+        if not start_obj:
+            [start_obj, characterOffset] = self._script.getCaretContext()    
+            
+        if start_obj is None \
+                     or start_obj.getRole() == pyatspi.ROLE_DOCUMENT_FRAME:
+            return []
+        else:
+            path = []
+            path.append(start_obj.getIndexInParent())
+            p = start_obj.parent
+            while p:
+                if p.getRole()  == pyatspi.ROLE_DOCUMENT_FRAME:
+                    path.reverse()
+                    return path
+                path.append(p.getIndexInParent())
+                p = p.parent
+            
+            return []
+            
+    def _pickleToObj(self, obj):
+        """Return the s with the given path (relative to the
+        document frame). """
+        
+        # could test for different obj types.  We'll just assume it is
+        # list that represents a path for now.
+        return self.pathToObj(obj)
+            
+    def pathToObj(self, path):
+        """Return the object with the given path (relative to the
+        document frame). """
+        returnobj = self._script.getDocumentFrame()
+        for childnumber in path:
+            try:
+                returnobj = returnobj[childnumber]
+            except IndexError:
+                return None
+            
+        return returnobj
+            
+    def getURIKey(self):
+        """Returns the URI key for a given page as a URI stripped of 
+        parameters?query#fragment as seen in urlparse."""
+        uri = self._script.getDocumentFrameURI()
+        if uri:
+            parsed_uri = urlparse.urlparse(uri)
+            return ''.join(parsed_uri[0:3])
+        else:
+            return None

Added: trunk/src/orca/scripts/toolkits/Gecko/braille_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/braille_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,521 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+"""Custom script for Gecko toolkit.
+Please refer to the following URL for more information on the AT-SPI
+implementation in Gecko:
+http://developer.mozilla.org/en/docs/Accessibility/ATSPI_Support
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.braille as braille
+import orca.braillegenerator as braillegenerator
+import orca.rolenames as rolenames
+import orca.settings as settings
+
+########################################################################
+#                                                                      #
+# Custom BrailleGenerator                                              #
+#                                                                      #
+########################################################################
+
+class BrailleGenerator(braillegenerator.BrailleGenerator):
+    """Provides a braille generator specific to Gecko.
+    """
+
+    def __init__(self, script):
+        braillegenerator.BrailleGenerator.__init__(self, script)
+        self.brailleGenerators[pyatspi.ROLE_AUTOCOMPLETE] = \
+             self._getBrailleRegionsForAutocomplete
+        self.brailleGenerators[pyatspi.ROLE_ENTRY]        = \
+             self._getBrailleRegionsForText
+        self.brailleGenerators[pyatspi.ROLE_LINK]         = \
+             self._getBrailleRegionsForLink
+
+    def _getTextForRole(self, obj, role=None):
+        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
+           and not obj.getRole() in [pyatspi.ROLE_SECTION,
+                                     pyatspi.ROLE_FORM,
+                                     pyatspi.ROLE_UNKNOWN]:
+            return rolenames.getBrailleForRoleName(obj, role)
+        else:
+            return None
+
+    def _getBrailleRegionsForAutocomplete(self, obj):
+        """Gets the braille for an autocomplete box.  We let the
+        handlers for the children do the rest.
+
+        Arguments:
+        - obj: an Accessible
+
+        Returns a list where the first element is a list of Regions to
+        display and the second element is the Region which should get
+        focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForAutocomplete", obj)
+
+        # [[[TODO: WDW - we're doing very little here.  The goal for
+        # autocomplete boxes at the moment is that their children (e.g.,
+        # a text area, a menu, etc., do all the interactive work and
+        # the autocomplete acts as more of a container.]]]
+        #
+        regions = []
+        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
+            regions.append(braille.Region(
+                rolenames.getBrailleForRoleName(obj)))
+        else:
+            regions.append(braille.Region(""))
+
+        return (regions, regions[0])
+
+    def _getBrailleRegionsForCheckBox(self, obj):
+        """Get the braille for a check box.  If the check box already had
+        focus, then only the state is displayed.
+
+        Arguments:
+        - obj: the check box
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForCheckBox", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForCheckBox(self, obj)
+        
+        # In document content (I'm not sure about XUL widgets yet), a
+        # checkbox is its own little beast with no text.  So...  if it
+        # is in document content and has a label, we're likely to be
+        # displaying that label already.  If it doesn't have a label,
+        # though, we'll display its name.
+        #
+        text = ""
+        if not self._script.inDocumentContent():
+            text = self._script.appendString(
+                text, self._script.getDisplayedLabel(obj))
+            text = self._script.appendString(
+                text, self._script.getDisplayedText(obj))
+        else:
+            isLabelled = False
+            relationSet = obj.getRelationSet()
+            if relationSet:
+                for relation in relationSet:
+                    if relation.getRelationType() \
+                        == pyatspi.RELATION_LABELLED_BY:
+                        isLabelled = True
+                        break
+            if not isLabelled and obj.name and len(obj.name):
+                text = self._script.appendString(text, obj.name)
+
+        text = self._script.appendString(text, self._getTextForRole(obj))
+
+        # get the Braille indicator
+        state = obj.getState()
+        if state.contains(pyatspi.STATE_INDETERMINATE):
+            indicatorIndex = 2
+        elif state.contains(pyatspi.STATE_CHECKED):
+            indicatorIndex = 1
+        else:
+            indicatorIndex = 0
+
+        regions = []
+
+        componentRegion = braille.Component(
+            obj, text,
+            indicator=settings.brailleCheckBoxIndicators[indicatorIndex])
+        regions.append(componentRegion)
+
+        return [regions, componentRegion]
+
+    def _getBrailleRegionsForRadioButton(self, obj):
+        """Get the braille for a radio button.  If the radio button already
+        had focus, then only the state is displayed.
+
+        Arguments:
+        - obj: the radio button
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForRadioButton", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForRadioButton(self, obj)
+        
+        # In document content (I'm not sure about XUL widgets yet), a
+        # radio button is its own little beast with no text.  So...  if it
+        # is in document content and has a label, we're likely to be
+        # displaying that label already.  If it doesn't have a label,
+        # though, we'll display its name.
+        #
+        text = ""
+        if not self._script.inDocumentContent():
+            text = self._script.appendString(
+                text, self._script.getDisplayedLabel(obj))
+            text = self._script.appendString(
+                text, self._script.getDisplayedText(obj))
+        else:
+            isLabelled = False
+            relationSet = obj.getRelationSet()
+            if relationSet:
+                for relation in relationSet:
+                    if relation.getRelationType() \
+                        == pyatspi.RELATION_LABELLED_BY:
+                        isLabelled = True
+                        break
+
+            if not isLabelled and obj.name and len(obj.name):
+                text = self._script.appendString(text, obj.name)
+
+        text = self._script.appendString(text, self._getTextForRole(obj))
+
+        indicatorIndex = int(obj.getState().contains(pyatspi.STATE_CHECKED))
+
+        regions = []
+        componentRegion = braille.Component(
+            obj, text,
+            indicator=settings.brailleRadioButtonIndicators[indicatorIndex])
+        regions.append(componentRegion)
+
+        return [regions, componentRegion]
+
+    def _getBrailleRegionsForText(self, obj):
+        """Gets text to be displayed for the entry of an autocomplete box.
+
+        Arguments:
+        - obj: an Accessible
+
+        Returns a list where the first element is a list of Regions to
+        display and the second element is the Region which should get
+        focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForText", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForText(self, obj)
+        
+        parent = obj.parent
+        if parent.getRole() != pyatspi.ROLE_AUTOCOMPLETE:
+            return braillegenerator.BrailleGenerator._getBrailleRegionsForText(
+                self, obj)
+
+        regions = []
+
+        # This is the main difference between this class and the default
+        # class - we'll give this thing a name here, and we'll make it
+        # be the name of the autocomplete.
+        #
+        label = self._script.getDisplayedLabel(parent)
+        if not label or not len(label):
+            label = parent.name
+
+        textRegion = braille.Text(obj, label, " $l")
+        regions.append(textRegion)
+        return [regions, textRegion]
+
+    def _getBrailleRegionsForComboBox(self, obj):
+        """Get the braille for a combo box.  If the combo box already has
+        focus, then only the selection is displayed.
+
+        Arguments:
+        - obj: the combo box
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForComboBox", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                     _getBrailleRegionsForComboBox(self, obj)
+        
+        regions = []
+
+        label = self._script.getDisplayedLabel(obj)
+        if not label and not self._script.inDocumentContent():
+            label = obj.name
+
+        focusedRegionIndex = 0
+        if label and len(label):
+            regions.append(braille.Region(label + " "))
+            focusedRegionIndex = 1
+
+        # With Gecko, a combo box has a menu as a child.  The text being
+        # displayed for the combo box can be obtained via the selected
+        # menu item.
+        #
+        menu = None
+        for child in obj:
+            if child.getRole() == pyatspi.ROLE_MENU:
+                menu = child
+                break
+        if menu:
+            child = None
+            try:
+                # This should work...
+                #
+                child = menu.querySelection().getSelectedChild(0)
+            except:
+                # But just in case, we'll fall back on this.
+                # [[[TODO - JD: Will we ever have a case where the first
+                # fails, but this will succeed???]]]
+                #
+                for item in menu:
+                    if item.getState().contains(pyatspi.STATE_SELECTED):
+                        child = item
+                        break
+            if child:
+                regions.append(braille.Region(child.name))
+
+        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
+            regions.append(braille.Region(
+                " " + rolenames.getBrailleForRoleName(obj)))
+
+        # Things may not have gone as expected above, so we'll do some
+        # defensive programming to make sure we don't get an index out
+        # of bounds.
+        #
+        if focusedRegionIndex >= len(regions):
+            focusedRegionIndex = 0
+
+        # [[[TODO: WDW - perhaps if a text area was created, we should
+        # give focus to it.]]]
+        #
+        return [regions, regions[focusedRegionIndex]]
+
+    def _getBrailleRegionsForMenuItem(self, obj):
+        """Get the braille for a menu item.
+
+        Arguments:
+        - obj: the menu item
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForMenuItem", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                     _getBrailleRegionsForMenuItem(self, obj)
+        
+        if not self._script.inDocumentContent():
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForMenuItem(self, obj)
+
+        regions = []
+
+        # Displaying "menu item" for a combo box can confuse users. Therefore,
+        # display the combo box role instead.  Also, only do it if the menu
+        # item is not focused (if the menu item is focused, it means we're
+        # navigating in the combo box).
+        #
+        label = self._script.getDisplayedLabel(obj)
+        focusedRegionIndex = 0
+        if label and len(label):
+            regions.append(braille.Region(label + " "))
+            focusedRegionIndex = 1
+        regions.append(braille.Region(obj.name))
+
+        comboBox = \
+                 self._script.getAncestor(obj,
+                                          [pyatspi.ROLE_COMBO_BOX],
+                                          [pyatspi.ROLE_DOCUMENT_FRAME])
+        if comboBox \
+           and not obj.getState().contains(pyatspi.STATE_FOCUSED) \
+           and (settings.brailleVerbosityLevel == \
+                settings.VERBOSITY_LEVEL_VERBOSE):
+            regions.append(braille.Region(
+                " " + rolenames.getBrailleForRoleName(comboBox)))
+
+        return [regions, regions[focusedRegionIndex]]
+
+    def _getBrailleRegionsForList(self, obj):
+        """Get the braille for a list in a form.  If the list already has
+        focus, then only the selection is displayed.
+
+        Arguments:
+        - obj: the list
+
+        Returns a list where the first element is a list of Regions to display
+        and the second element is the Region which should get focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForList", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForList(self, obj)
+        
+        if not obj.getState().contains(pyatspi.STATE_FOCUSABLE):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForList(self, obj)
+
+        regions = []
+        focusedRegionIndex = 0
+
+        if obj.getState().contains(pyatspi.STATE_FOCUSED):
+            label = self._script.getDisplayedLabel(obj)
+            if not label:
+                label = obj.name
+
+            if label and len(label):
+                regions.append(braille.Region(label + " "))
+                focusedRegionIndex = 1
+
+            item = None
+            selection = obj.querySelection()
+            for i in xrange(obj.childCount):
+                if selection.isChildSelected(i):
+                    item = obj[i]
+                    break
+            if not item:
+                item = obj[0]
+            regions.append(braille.Region(item.name + " "))
+
+        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
+            regions.append(braille.Region(
+                rolenames.getBrailleForRoleName(obj)))
+
+        return [regions, regions[focusedRegionIndex]]
+
+    def _getBrailleRegionsForImage(self, obj):
+        """Get the braille regions for an image.
+
+        Arguments:
+        - obj: an Accessible
+
+        Returns a list where the first element is a list of Regions to
+        display and the second element is the Region which should get
+        focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForImage", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getBrailleRegionsForImage(self, obj)
+        
+        regions = []
+
+        text = ""
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedLabel(obj))
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedText(obj))
+
+        # If there's no text for the link, expose part of the
+        # link to the user if the image is in a link.
+        #
+        link = self._script.getAncestor(obj, 
+                                        [pyatspi.ROLE_LINK], 
+                                        [pyatspi.ROLE_DOCUMENT_FRAME])
+        if len(text) == 0:
+            if link:
+                [linkRegions, focusedRegion] = \
+                    self._getBrailleRegionsForLink(link)
+                for region in linkRegions:
+                    text += region.string
+        elif link:
+            text = self._script.appendString(text, self._getTextForRole(link))
+
+        text = self._script.appendString(text,
+                                         self._script.getTextForValue(obj))
+        text = self._script.appendString(text, self._getTextForRole(obj))
+
+        regions = []
+        componentRegion = braille.Component(obj, text)
+        regions.append(componentRegion)
+
+        return [regions, componentRegion]
+
+    def _getBrailleRegionsForLink(self, obj):
+        """Gets text to be displayed for a link.
+
+        Arguments:
+        - obj: an Accessible
+
+        Returns a list where the first element is a list of Regions to
+        display and the second element is the Region which should get
+        focus.
+        """
+
+        self._debugGenerator("Gecko._getBrailleRegionsForLink", obj)
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return braillegenerator.BrailleGenerator.\
+                       _getDefaultBrailleRegions(self, obj)
+        
+        regions = []
+
+        text = ""
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedLabel(obj))
+        text = self._script.appendString(text, 
+                                         self._script.getDisplayedText(obj))
+
+        # If there's no text for the link, expose part of the
+        # URI to the user.
+        #
+        if len(text) == 0:
+            basename = self._script.getLinkBasename(obj)
+            if basename:
+                text = basename
+
+        text = self._script.appendString(text,
+                                         self._script.getTextForValue(obj))
+        text = self._script.appendString(text, self._getTextForRole(obj))
+
+        regions = []
+        componentRegion = braille.Component(obj, text)
+        regions.append(componentRegion)
+
+        return [regions, componentRegion]

Added: trunk/src/orca/scripts/toolkits/Gecko/constants.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/constants.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,85 @@
+import pyatspi
+
+# If True, it tells us to take over caret navigation.  This is something
+# that can be set in user-settings.py:
+#
+# import orca.Gecko
+# orca.Gecko.controlCaretNavigation = True
+#
+controlCaretNavigation = True
+
+# If True, it tells us to position the caret at the beginning of a
+# line when arrowing up and down.  If False, we'll try to position the
+# caret directly above or below the current caret position.
+#
+arrowToLineBeginning = True
+
+# If True, it tells Orca to automatically perform a SayAll operation
+# when a page is first loaded.
+#
+sayAllOnLoad = True
+
+# Whether or not to use the structrual navigation commands (e.g. H
+# for heading, T for table, and so on).
+#
+structuralNavigationEnabled = True
+
+# Whether or not to speak the cell's coordinates when navigating
+# from cell to cell in HTML tables.
+#
+speakCellCoordinates = True
+
+# Whether or not to speak the number of cells spanned by a cell
+# that occupies more than one row or column of an HTML table.
+#
+speakCellSpan = True
+
+# Whether or not to announce the header that applies to the current
+# when navigating from cell to cell in HTML tables.
+#
+speakCellHeaders = True
+
+# Whether blank cells should be skipped when navigating in an HTML
+# table using table navigation commands
+#
+skipBlankCells = False
+
+# Whether or not Orca should speak the changing location within the
+# document frame *during* a find (i.e. while focus is still in the
+# Find toolbar).
+#
+speakResultsDuringFind = True
+
+# The minimum number of characters that must be matched during
+# a find before Orca speaks the changed location, assuming that
+# speakResultsDuringFind is True.
+#
+minimumFindLength = 4
+
+# Whether or not to continue speaking the same line if the match
+# has not changed with additional keystrokes.  This setting comes
+# in handy for fast typists who might inadvertantly interrupt the
+# speaking of the line that matches by continuing to type in the
+# Find entry.  This is the equivalent of what we do in autocompletes
+# throughout GNOME.  For power-users of the Find toolbar, however,
+# that may be too verbose so it's configurable.
+#
+onlySpeakChangedLinesDuringFind = False
+
+# The minimum number of characters of text that an accessible object must 
+# contain to be considered a match in go to next/prev large object
+largeObjectTextLength = 75
+
+# Roles that represent a logical chunk of information in a document
+#
+OBJECT_ROLES = [pyatspi.ROLE_HEADING,
+                pyatspi.ROLE_PARAGRAPH,
+                pyatspi.ROLE_TABLE,
+                pyatspi.ROLE_TABLE_CELL,
+                pyatspi.ROLE_TEXT,
+                pyatspi.ROLE_SECTION,
+                pyatspi.ROLE_DOCUMENT_FRAME,
+                pyatspi.ROLE_AUTOCOMPLETE]
+
+ARIA_LANDMARKS = ["banner", "contentinfo", "definition", "main", "navigation",
+                  "note", "search", "secondary", "seealso"]

Copied: trunk/src/orca/scripts/toolkits/Gecko/script.py (from r3875, /trunk/src/orca/Gecko.py)
==============================================================================
--- /trunk/src/orca/Gecko.py	(original)
+++ trunk/src/orca/scripts/toolkits/Gecko/script.py	Fri May  2 21:21:19 2008
@@ -42,1799 +42,32 @@
 
 import atk
 import gtk
-import math
 import pyatspi
 import re
-import urlparse
-
-import braille
-import braillegenerator
-import debug
-import default
-import input_event
-import keybindings
-import liveregions
-import mag
-import orca
-import orca_state
-import rolenames
-import settings
-import speech
-import speechgenerator
-import speechserver
 import time
-import where_am_I
-import bookmarks
-
-from orca_i18n import _
-from orca_i18n import ngettext  # for ngettext support
-from orca_i18n import Q_        # to provide qualified translatable strings
-
-# If True, it tells us to take over caret navigation.  This is something
-# that can be set in user-settings.py:
-#
-# import orca.Gecko
-# orca.Gecko.controlCaretNavigation = True
-#
-controlCaretNavigation = True
-
-# If True, it tells us to position the caret at the beginning of a
-# line when arrowing up and down.  If False, we'll try to position the
-# caret directly above or below the current caret position.
-#
-arrowToLineBeginning = True
-
-# If True, it tells Orca to automatically perform a SayAll operation
-# when a page is first loaded.
-#
-sayAllOnLoad = True
-
-# Whether or not to use the structrual navigation commands (e.g. H
-# for heading, T for table, and so on).
-#
-structuralNavigationEnabled = True
-
-# Whether or not to speak the cell's coordinates when navigating
-# from cell to cell in HTML tables.
-#
-speakCellCoordinates = True
-
-# Whether or not to speak the number of cells spanned by a cell
-# that occupies more than one row or column of an HTML table.
-#
-speakCellSpan = True
-
-# Whether or not to announce the header that applies to the current
-# when navigating from cell to cell in HTML tables.
-#
-speakCellHeaders = True
-
-# Whether blank cells should be skipped when navigating in an HTML
-# table using table navigation commands
-#
-skipBlankCells = False
-
-# Whether or not Orca should speak the changing location within the
-# document frame *during* a find (i.e. while focus is still in the
-# Find toolbar).
-#
-speakResultsDuringFind = True
-
-# The minimum number of characters that must be matched during
-# a find before Orca speaks the changed location, assuming that
-# speakResultsDuringFind is True.
-#
-minimumFindLength = 4
-
-# Whether or not to continue speaking the same line if the match
-# has not changed with additional keystrokes.  This setting comes
-# in handy for fast typists who might inadvertantly interrupt the
-# speaking of the line that matches by continuing to type in the
-# Find entry.  This is the equivalent of what we do in autocompletes
-# throughout GNOME.  For power-users of the Find toolbar, however,
-# that may be too verbose so it's configurable.
-#
-onlySpeakChangedLinesDuringFind = False
-
-# The minimum number of characters of text that an accessible object must 
-# contain to be considered a match in go to next/prev large object
-largeObjectTextLength = 75
-
-# Roles that imply their text starts on a new line.
-#
-NEWLINE_ROLES = [pyatspi.ROLE_PARAGRAPH,
-                 pyatspi.ROLE_SEPARATOR,
-                 pyatspi.ROLE_LIST_ITEM,
-                 pyatspi.ROLE_HEADING]
-
-# Roles that represent a logical chunk of information in a document
-#
-OBJECT_ROLES = [pyatspi.ROLE_HEADING,
-                pyatspi.ROLE_PARAGRAPH,
-                pyatspi.ROLE_TABLE,
-                pyatspi.ROLE_TABLE_CELL,
-                pyatspi.ROLE_TEXT,
-                pyatspi.ROLE_SECTION,
-                pyatspi.ROLE_DOCUMENT_FRAME,
-                pyatspi.ROLE_AUTOCOMPLETE]
-
-ARIA_LANDMARKS = ["banner", "contentinfo", "definition", "main", "navigation",
-                  "note", "search", "secondary", "seealso"]
-
-########################################################################
-#                                                                      #
-# Custom BrailleGenerator                                              #
-#                                                                      #
-########################################################################
-
-class BrailleGenerator(braillegenerator.BrailleGenerator):
-    """Provides a braille generator specific to Gecko.
-    """
-
-    def __init__(self, script):
-        braillegenerator.BrailleGenerator.__init__(self, script)
-        self.brailleGenerators[pyatspi.ROLE_AUTOCOMPLETE] = \
-             self._getBrailleRegionsForAutocomplete
-        self.brailleGenerators[pyatspi.ROLE_ENTRY]        = \
-             self._getBrailleRegionsForText
-        self.brailleGenerators[pyatspi.ROLE_LINK]         = \
-             self._getBrailleRegionsForLink
-
-    def _getTextForRole(self, obj, role=None):
-        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
-           and not obj.getRole() in [pyatspi.ROLE_SECTION,
-                                     pyatspi.ROLE_FORM,
-                                     pyatspi.ROLE_UNKNOWN]:
-            return rolenames.getBrailleForRoleName(obj, role)
-        else:
-            return None
-
-    def _getBrailleRegionsForAutocomplete(self, obj):
-        """Gets the braille for an autocomplete box.  We let the
-        handlers for the children do the rest.
-
-        Arguments:
-        - obj: an Accessible
-
-        Returns a list where the first element is a list of Regions to
-        display and the second element is the Region which should get
-        focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForAutocomplete", obj)
-
-        # [[[TODO: WDW - we're doing very little here.  The goal for
-        # autocomplete boxes at the moment is that their children (e.g.,
-        # a text area, a menu, etc., do all the interactive work and
-        # the autocomplete acts as more of a container.]]]
-        #
-        regions = []
-        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
-            regions.append(braille.Region(
-                rolenames.getBrailleForRoleName(obj)))
-        else:
-            regions.append(braille.Region(""))
-
-        return (regions, regions[0])
-
-    def _getBrailleRegionsForCheckBox(self, obj):
-        """Get the braille for a check box.  If the check box already had
-        focus, then only the state is displayed.
-
-        Arguments:
-        - obj: the check box
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForCheckBox", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForCheckBox(self, obj)
-        
-        # In document content (I'm not sure about XUL widgets yet), a
-        # checkbox is its own little beast with no text.  So...  if it
-        # is in document content and has a label, we're likely to be
-        # displaying that label already.  If it doesn't have a label,
-        # though, we'll display its name.
-        #
-        text = ""
-        if not self._script.inDocumentContent():
-            text = self._script.appendString(
-                text, self._script.getDisplayedLabel(obj))
-            text = self._script.appendString(
-                text, self._script.getDisplayedText(obj))
-        else:
-            isLabelled = False
-            relationSet = obj.getRelationSet()
-            if relationSet:
-                for relation in relationSet:
-                    if relation.getRelationType() \
-                        == pyatspi.RELATION_LABELLED_BY:
-                        isLabelled = True
-                        break
-            if not isLabelled and obj.name and len(obj.name):
-                text = self._script.appendString(text, obj.name)
-
-        text = self._script.appendString(text, self._getTextForRole(obj))
-
-        # get the Braille indicator
-        state = obj.getState()
-        if state.contains(pyatspi.STATE_INDETERMINATE):
-            indicatorIndex = 2
-        elif state.contains(pyatspi.STATE_CHECKED):
-            indicatorIndex = 1
-        else:
-            indicatorIndex = 0
-
-        regions = []
-
-        componentRegion = braille.Component(
-            obj, text,
-            indicator=settings.brailleCheckBoxIndicators[indicatorIndex])
-        regions.append(componentRegion)
-
-        return [regions, componentRegion]
 
-    def _getBrailleRegionsForRadioButton(self, obj):
-        """Get the braille for a radio button.  If the radio button already
-        had focus, then only the state is displayed.
+import orca.braille as braille
+import orca.debug as debug
+import orca.default as default
+import orca.input_event as input_event
+import orca.keybindings as keybindings
+import orca.liveregions as liveregions
+import orca.mag as mag
+import orca.orca as orca
+import orca.orca_state as orca_state
+import orca.rolenames as rolenames
+import orca.settings as settings
+import orca.speech as speech
+import orca.speechserver as speechserver
+
+from constants import *
+from braille_generator import BrailleGenerator
+from speech_generator import SpeechGenerator
+from where_am_i import GeckoWhereAmI
+from bookmarks import GeckoBookmarks
 
-        Arguments:
-        - obj: the radio button
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForRadioButton", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForRadioButton(self, obj)
-        
-        # In document content (I'm not sure about XUL widgets yet), a
-        # radio button is its own little beast with no text.  So...  if it
-        # is in document content and has a label, we're likely to be
-        # displaying that label already.  If it doesn't have a label,
-        # though, we'll display its name.
-        #
-        text = ""
-        if not self._script.inDocumentContent():
-            text = self._script.appendString(
-                text, self._script.getDisplayedLabel(obj))
-            text = self._script.appendString(
-                text, self._script.getDisplayedText(obj))
-        else:
-            isLabelled = False
-            relationSet = obj.getRelationSet()
-            if relationSet:
-                for relation in relationSet:
-                    if relation.getRelationType() \
-                        == pyatspi.RELATION_LABELLED_BY:
-                        isLabelled = True
-                        break
-
-            if not isLabelled and obj.name and len(obj.name):
-                text = self._script.appendString(text, obj.name)
-
-        text = self._script.appendString(text, self._getTextForRole(obj))
-
-        indicatorIndex = int(obj.getState().contains(pyatspi.STATE_CHECKED))
-
-        regions = []
-        componentRegion = braille.Component(
-            obj, text,
-            indicator=settings.brailleRadioButtonIndicators[indicatorIndex])
-        regions.append(componentRegion)
-
-        return [regions, componentRegion]
-
-    def _getBrailleRegionsForText(self, obj):
-        """Gets text to be displayed for the entry of an autocomplete box.
-
-        Arguments:
-        - obj: an Accessible
-
-        Returns a list where the first element is a list of Regions to
-        display and the second element is the Region which should get
-        focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForText", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForText(self, obj)
-        
-        parent = obj.parent
-        if parent.getRole() != pyatspi.ROLE_AUTOCOMPLETE:
-            return braillegenerator.BrailleGenerator._getBrailleRegionsForText(
-                self, obj)
-
-        regions = []
-
-        # This is the main difference between this class and the default
-        # class - we'll give this thing a name here, and we'll make it
-        # be the name of the autocomplete.
-        #
-        label = self._script.getDisplayedLabel(parent)
-        if not label or not len(label):
-            label = parent.name
-
-        textRegion = braille.Text(obj, label, " $l")
-        regions.append(textRegion)
-        return [regions, textRegion]
-
-    def _getBrailleRegionsForComboBox(self, obj):
-        """Get the braille for a combo box.  If the combo box already has
-        focus, then only the selection is displayed.
-
-        Arguments:
-        - obj: the combo box
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForComboBox", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                     _getBrailleRegionsForComboBox(self, obj)
-        
-        regions = []
-
-        label = self._script.getDisplayedLabel(obj)
-        if not label and not self._script.inDocumentContent():
-            label = obj.name
-
-        focusedRegionIndex = 0
-        if label and len(label):
-            regions.append(braille.Region(label + " "))
-            focusedRegionIndex = 1
-
-        # With Gecko, a combo box has a menu as a child.  The text being
-        # displayed for the combo box can be obtained via the selected
-        # menu item.
-        #
-        menu = None
-        for child in obj:
-            if child.getRole() == pyatspi.ROLE_MENU:
-                menu = child
-                break
-        if menu:
-            child = None
-            try:
-                # This should work...
-                #
-                child = menu.querySelection().getSelectedChild(0)
-            except:
-                # But just in case, we'll fall back on this.
-                # [[[TODO - JD: Will we ever have a case where the first
-                # fails, but this will succeed???]]]
-                #
-                for item in menu:
-                    if item.getState().contains(pyatspi.STATE_SELECTED):
-                        child = item
-                        break
-            if child:
-                regions.append(braille.Region(child.name))
-
-        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
-            regions.append(braille.Region(
-                " " + rolenames.getBrailleForRoleName(obj)))
-
-        # Things may not have gone as expected above, so we'll do some
-        # defensive programming to make sure we don't get an index out
-        # of bounds.
-        #
-        if focusedRegionIndex >= len(regions):
-            focusedRegionIndex = 0
-
-        # [[[TODO: WDW - perhaps if a text area was created, we should
-        # give focus to it.]]]
-        #
-        return [regions, regions[focusedRegionIndex]]
-
-    def _getBrailleRegionsForMenuItem(self, obj):
-        """Get the braille for a menu item.
-
-        Arguments:
-        - obj: the menu item
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForMenuItem", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                     _getBrailleRegionsForMenuItem(self, obj)
-        
-        if not self._script.inDocumentContent():
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForMenuItem(self, obj)
-
-        regions = []
-
-        # Displaying "menu item" for a combo box can confuse users. Therefore,
-        # display the combo box role instead.  Also, only do it if the menu
-        # item is not focused (if the menu item is focused, it means we're
-        # navigating in the combo box).
-        #
-        label = self._script.getDisplayedLabel(obj)
-        focusedRegionIndex = 0
-        if label and len(label):
-            regions.append(braille.Region(label + " "))
-            focusedRegionIndex = 1
-        regions.append(braille.Region(obj.name))
-
-        comboBox = \
-                 self._script.getAncestor(obj,
-                                          [pyatspi.ROLE_COMBO_BOX],
-                                          [pyatspi.ROLE_DOCUMENT_FRAME])
-        if comboBox \
-           and not obj.getState().contains(pyatspi.STATE_FOCUSED) \
-           and (settings.brailleVerbosityLevel == \
-                settings.VERBOSITY_LEVEL_VERBOSE):
-            regions.append(braille.Region(
-                " " + rolenames.getBrailleForRoleName(comboBox)))
-
-        return [regions, regions[focusedRegionIndex]]
-
-    def _getBrailleRegionsForList(self, obj):
-        """Get the braille for a list in a form.  If the list already has
-        focus, then only the selection is displayed.
-
-        Arguments:
-        - obj: the list
-
-        Returns a list where the first element is a list of Regions to display
-        and the second element is the Region which should get focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForList", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForList(self, obj)
-        
-        if not obj.getState().contains(pyatspi.STATE_FOCUSABLE):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForList(self, obj)
-
-        regions = []
-        focusedRegionIndex = 0
-
-        if obj.getState().contains(pyatspi.STATE_FOCUSED):
-            label = self._script.getDisplayedLabel(obj)
-            if not label:
-                label = obj.name
-
-            if label and len(label):
-                regions.append(braille.Region(label + " "))
-                focusedRegionIndex = 1
-
-            item = None
-            selection = obj.querySelection()
-            for i in xrange(obj.childCount):
-                if selection.isChildSelected(i):
-                    item = obj[i]
-                    break
-            if not item:
-                item = obj[0]
-            regions.append(braille.Region(item.name + " "))
-
-        if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
-            regions.append(braille.Region(
-                rolenames.getBrailleForRoleName(obj)))
-
-        return [regions, regions[focusedRegionIndex]]
-
-    def _getBrailleRegionsForImage(self, obj):
-        """Get the braille regions for an image.
-
-        Arguments:
-        - obj: an Accessible
-
-        Returns a list where the first element is a list of Regions to
-        display and the second element is the Region which should get
-        focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForImage", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getBrailleRegionsForImage(self, obj)
-        
-        regions = []
-
-        text = ""
-        text = self._script.appendString(text, 
-                                         self._script.getDisplayedLabel(obj))
-        text = self._script.appendString(text, 
-                                         self._script.getDisplayedText(obj))
-
-        # If there's no text for the link, expose part of the
-        # link to the user if the image is in a link.
-        #
-        link = self._script.getAncestor(obj, 
-                                        [pyatspi.ROLE_LINK], 
-                                        [pyatspi.ROLE_DOCUMENT_FRAME])
-        if len(text) == 0:
-            if link:
-                [linkRegions, focusedRegion] = \
-                    self._getBrailleRegionsForLink(link)
-                for region in linkRegions:
-                    text += region.string
-        elif link:
-            text = self._script.appendString(text, self._getTextForRole(link))
-
-        text = self._script.appendString(text,
-                                         self._script.getTextForValue(obj))
-        text = self._script.appendString(text, self._getTextForRole(obj))
-
-        regions = []
-        componentRegion = braille.Component(obj, text)
-        regions.append(componentRegion)
-
-        return [regions, componentRegion]
-
-    def _getBrailleRegionsForLink(self, obj):
-        """Gets text to be displayed for a link.
-
-        Arguments:
-        - obj: an Accessible
-
-        Returns a list where the first element is a list of Regions to
-        display and the second element is the Region which should get
-        focus.
-        """
-
-        self._debugGenerator("Gecko._getBrailleRegionsForLink", obj)
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return braillegenerator.BrailleGenerator.\
-                       _getDefaultBrailleRegions(self, obj)
-        
-        regions = []
-
-        text = ""
-        text = self._script.appendString(text, 
-                                         self._script.getDisplayedLabel(obj))
-        text = self._script.appendString(text, 
-                                         self._script.getDisplayedText(obj))
-
-        # If there's no text for the link, expose part of the
-        # URI to the user.
-        #
-        if len(text) == 0:
-            basename = self._script.getLinkBasename(obj)
-            if basename:
-                text = basename
-
-        text = self._script.appendString(text,
-                                         self._script.getTextForValue(obj))
-        text = self._script.appendString(text, self._getTextForRole(obj))
-
-        regions = []
-        componentRegion = braille.Component(obj, text)
-        regions.append(componentRegion)
-
-        return [regions, componentRegion]
-
-########################################################################
-#                                                                      #
-# Custom SpeechGenerator                                               #
-#                                                                      #
-########################################################################
-
-class SpeechGenerator(speechgenerator.SpeechGenerator):
-    """Provides a speech generator specific to Gecko.
-    """
-
-    def __init__(self, script):
-        speechgenerator.SpeechGenerator.__init__(self, script)
-        self.speechGenerators[pyatspi.ROLE_DOCUMENT_FRAME] = \
-             self._getSpeechForDocumentFrame
-        self.speechGenerators[pyatspi.ROLE_ENTRY]          = \
-             self._getSpeechForText
-        self.speechGenerators[pyatspi.ROLE_LINK]           = \
-             self._getSpeechForLink
-        self.speechGenerators[pyatspi.ROLE_LIST_ITEM]      = \
-             self._getSpeechForListItem
-        self.speechGenerators[pyatspi.ROLE_SLIDER]         = \
-             self._getSpeechForSlider
-
-    def getSpeechForObjectRole(self, obj, role=None):
-        """Prevents some roles from being spoken."""
-        if obj.getRole() in [pyatspi.ROLE_PARAGRAPH,
-                             pyatspi.ROLE_SECTION,
-                             pyatspi.ROLE_LABEL,
-                             pyatspi.ROLE_FORM,
-                             pyatspi.ROLE_LIST_ITEM,
-                             pyatspi.ROLE_MENU_ITEM,
-                             pyatspi.ROLE_UNKNOWN]:
-            return []
-        else:
-            return [rolenames.getSpeechForRoleName(obj, role)]
-
-    def _getSpeechForDocumentFrame(self, obj, already_focused):
-        """Gets the speech for a document frame.
-
-        Arguments:
-        - obj: an Accessible
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-
-        name = obj.name
-        if name and len(name):
-            utterances.append(name)
-        utterances.extend(self.getSpeechForObjectRole(obj))
-
-        self._debugGenerator("Gecko._getSpeechForDocumentFrame",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForText(self, obj, already_focused):
-        """Gets the speech for an autocomplete box.
-
-        Arguments:
-        - obj: an Accessible
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForText(self, obj, already_focused)
-        
-        utterances = []
-        parent = obj.parent
-        if parent.getRole() == pyatspi.ROLE_AUTOCOMPLETE:
-            # This is the main difference between this class and the default
-            # class - we'll give this thing a name here, and we'll make it
-            # be the name of the autocomplete.
-            #
-            label = self._script.getDisplayedLabel(parent)
-            if not label or not len(label):
-                label = parent.name
-            utterances.append(label)
-        elif obj.getRole() in [pyatspi.ROLE_ENTRY,
-                               pyatspi.ROLE_PASSWORD_TEXT] \
-            and self._script.inDocumentContent():
-            # This is a form field in web content.  If we don't get a label,
-            # we'll try to guess what text on the page is functioning as
-            # the label.
-            #
-            label = self._script.getDisplayedLabel(obj)
-            if not label or not len(label):
-                label = self._script.guessTheLabel(obj)
-            if label:
-                utterances.append(label)
-        else:
-            return speechgenerator.SpeechGenerator._getSpeechForText(
-                self, obj, already_focused)
-
-        utterances.extend(self.getSpeechForObjectRole(obj))
-
-        [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj)
-        utterances.append(text)
-
-        self._debugGenerator("Gecko._getSpeechForText",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForComboBox(self, obj, already_focused):
-        """Get the speech for a combo box.  If the combo box already has focus,
-        then only the selection is spoken.
-
-        Arguments:
-        - obj: the combo box
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForComboBox(self, obj, already_focused)
-        
-        utterances = []
-
-        label = self._script.getDisplayedLabel(obj)
-        if not label:
-            if not self._script.inDocumentContent():
-                label = obj.name
-            else:
-                label = self._script.guessTheLabel(obj)
-
-        if not already_focused and label:
-            utterances.append(label)
-
-        # With Gecko, a combo box has a menu as a child.  The text being
-        # displayed for the combo box can be obtained via the selected
-        # menu item.
-        #
-        menu = None
-        for child in obj:
-            if child.getRole() == pyatspi.ROLE_MENU:
-                menu = child
-                break
-        if menu:
-            child = None
-            try:
-                # This should work...
-                #
-                child = menu.querySelection().getSelectedChild(0)
-            except:
-                # But just in case, we'll fall back on this.
-                # [[[TODO - JD: Will we ever have a case where the first
-                # fails, but this will succeed???]]]
-                #
-                for item in menu:
-                    if item.getState().contains(pyatspi.STATE_SELECTED):
-                        child = item
-                        break
-            if child:
-                utterances.append(child.name)
-
-        utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        if not already_focused:
-            utterances.extend(self.getSpeechForObjectRole(obj))
-
-        self._debugGenerator("Gecko._getSpeechForComboBox",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForMenuItem(self, obj, already_focused):
-        """Get the speech for a menu item.
-
-        Arguments:
-        - obj: the menu item
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForMenuItem(self, obj, already_focused)
-        
-        if not self._script.inDocumentContent():
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForMenuItem(self, obj, already_focused)
-
-        utterances = self._getSpeechForObjectName(obj)
-
-        # Saying "menu item" for a combo box can confuse users. Therefore,
-        # speak the combo box role instead.  Also, only do it if the menu
-        # item is not focused (if the menu item is focused, it means we're
-        # navigating in the combo box)
-        #
-        if not obj.getState().contains(pyatspi.STATE_FOCUSED):
-            comboBox = \
-                 self._script.getAncestor(obj,
-                                          [pyatspi.ROLE_COMBO_BOX],
-                                          [pyatspi.ROLE_DOCUMENT_FRAME])
-            if comboBox:
-                utterances.extend(self.getSpeechForObjectRole(comboBox))
-
-        self._debugGenerator("Gecko._getSpeechForMenuItem",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForListItem(self, obj, already_focused):
-        """Get the speech for a list item.
-
-        Arguments:
-        - obj: the list item
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-
-        if self._script.isAriaWidget(obj) \
-           or not self._script.inDocumentContent(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForListItem(self, obj, already_focused)
-        
-        if not obj.getState().contains(pyatspi.STATE_SELECTABLE):
-            return speechgenerator.SpeechGenerator.\
-                       _getDefaultSpeech(self, obj, already_focused)
-
-        utterances = self._getSpeechForObjectName(obj)
-
-        self._debugGenerator("Gecko._getSpeechForListItem",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForList(self, obj, already_focused):
-        """Get the speech for a list.
-
-        Arguments:
-        - obj: the list
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForList(self, obj, already_focused)
-        
-        if not obj.getState().contains(pyatspi.STATE_FOCUSABLE):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForList(self, obj, already_focused)
-
-        utterances = []
-
-        if obj.getState().contains(pyatspi.STATE_FOCUSED):
-            label = self._script.getDisplayedLabel(obj)
-            if not label:
-                if not self._script.inDocumentContent():
-                    label = obj.name
-                else:
-                    label = self._script.guessTheLabel(obj)
-
-            if not already_focused and label:
-                utterances.append(label)
-
-            item = None
-            selection = obj.querySelection()
-            for i in xrange(obj.childCount):
-                if selection.isChildSelected(i):
-                    item = obj[i]
-                    break
-            item = item or obj[0]
-            if item:
-                name = self._getSpeechForObjectName(item)
-                if name != label:
-                    utterances.extend(name)
-
-        if not already_focused:
-            if obj.getState().contains(pyatspi.STATE_MULTISELECTABLE):
-                # Translators: "multi-select" refers to a web form list
-                # in which more than one item can be selected at a time.
-                #
-                utterances.append(_("multi-select"))
-
-            # Translators: this represents a list in HTML.
-            #
-            itemString = ngettext("List with %d item",
-                                  "List with %d items",
-                                  obj.childCount) % obj.childCount
-            utterances.append(itemString)
-
-        self._debugGenerator("Gecko._getSpeechForList",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForImage(self, obj, already_focused):
-        """Gets a list of utterances to be spoken for an image.
-
-        The default speech will be of the following form:
-
-        label name role availability
-
-        Arguments:
-        - obj: an Accessible
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForImage(self, obj, already_focused)
-        
-        utterances = []
-
-        if not already_focused:
-            label = self._getSpeechForObjectLabel(obj)
-            utterances.extend(label)
-            name = self._getSpeechForObjectName(obj)
-            if name != label:
-                utterances.extend(name)
-
-            # If there's no text for the image, expose the link to
-            # the user if the image is in a link.
-            #
-            link = self._script.getAncestor(obj,
-                                            [pyatspi.ROLE_LINK],
-                                            [pyatspi.ROLE_DOCUMENT_FRAME])
-            if not len(utterances):
-                if link:
-                    utterances.extend(self._getSpeechForLink(link,
-                                                             already_focused))
-            elif link:
-                utterances.extend(self.getSpeechForObjectRole(link))
-
-            utterances.extend(self.getSpeechForObjectRole(obj))
-
-        utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        self._debugGenerator("Gecko._getSpeechForImage",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForLink(self, obj, already_focused):
-        """Gets a list of utterances to be spoken for a link.
-
-        Arguments:
-        - obj: an Accessible
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.getSpeech(obj,
-                                                             already_focused)
-        
-        utterances = []
-
-        if not already_focused:
-            label = self._getSpeechForObjectLabel(obj)
-            utterances.extend(label)
-            name = self._getSpeechForObjectName(obj)
-
-            # Handle empty alt tags.
-            #
-            if name:
-                lengthOfName = len(name[0].strip())
-                if (lengthOfName > 0) and (name != label):
-                    utterances.extend(name)
-
-            # If there's no text for the link, expose part of the
-            # URI to the user.
-            #
-            if not len(utterances):
-                basename = self._script.getLinkBasename(obj)
-                if basename:
-                    utterances.append(basename)
-
-            utterances.extend(self.getSpeechForObjectRole(obj))
-
-        utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        self._debugGenerator("Gecko._getSpeechForLink",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def _getSpeechForTable(self, obj, already_focused):
-        """Get the speech for a table
-
-        Arguments:
-        - obj: the table
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForTable(self, obj, already_focused)
-        
-        # [[[TODO: JD - We should decide if we want to provide
-        # information about the table dimensions, whether or not
-        # this is a layout table versus a data table, etc.  For now,
-        # however, if it's in HTML content let's ignore it so that
-        # SayAll by sentence works. :-) ]]]
-        #
-        utterances = []
-
-        if not self._script.inDocumentContent():
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForTable(self, obj, already_focused)
-
-        return utterances
-
-    def _getSpeechForRadioButton(self, obj, already_focused):
-        """Get the speech for a radio button.  If the button already had
-        focus, then only the state is spoken.
-
-        Arguments:
-        - obj: the radio button
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForRadioButton(self, obj, already_focused)
-        
-        if not self._script.inDocumentContent():
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForRadioButton(self, obj, already_focused)
-
-        utterances = []
-        if obj.getState().contains(pyatspi.STATE_CHECKED):
-            # Translators: this is in reference to a radio button being
-            # selected or not.
-            #
-            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
-            #
-            selectionState = Q_("radiobutton|selected")
-        else:
-            # Translators: this is in reference to a radio button being
-            # selected or not.
-            #
-            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
-            #
-            selectionState = Q_("radiobutton|not selected")
-
-        if not already_focused:
-            # The label is handled as a context in default.py -- assuming we
-            # don't have to guess it.  If  we need to guess it, we need to
-            # add it to utterances.
-            #
-            label = self._script.getDisplayedLabel(obj)
-            if not label:
-                label = self._script.guessTheLabel(obj)
-                if label:
-                    utterances.append(label)
-
-            utterances.append(selectionState)
-            utterances.extend(self.getSpeechForObjectRole(obj))
-            utterances.extend(self._getSpeechForObjectAvailability(obj))
-        else:
-            utterances.append(selectionState)
-
-        self._debugGenerator("Gecko._getSpeechForRadioButton",
-                             obj,
-                             already_focused,
-                             utterances)
-        return utterances
-
-    def _getSpeechForCheckBox(self, obj, already_focused):
-        """Get the speech for a check box.  If the check box already had
-        focus, then only the state is spoken.
-
-        Arguments:
-        - obj: the check box
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        # Treat ARIA widgets like default.py widgets
-        #
-        if self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForCheckBox(self, obj, already_focused)
-        
-        if not self._script.inDocumentContent():
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForCheckBox(self, obj, already_focused)
-
-        utterances = []
-        state = obj.getState()
-        if state.contains(pyatspi.STATE_INDETERMINATE):
-            # Translators: this represents the state of a checkbox.
-            #
-            checkedState = _("partially checked")
-        elif state.contains(pyatspi.STATE_CHECKED):
-            # Translators: this represents the state of a checkbox.
-            #
-            checkedState = _("checked")
-        else:
-            # Translators: this represents the state of a checkbox.
-            #
-            checkedState = _("not checked")
-
-        # If it's not already focused, say its label.
-        #
-        if not already_focused:
-            label = self._script.getDisplayedLabel(obj)
-            if not label:
-                label = self._script.guessTheLabel(obj)
-            if label:
-                utterances.append(label)
-            utterances.extend(self.getSpeechForObjectRole(obj))
-            utterances.append(checkedState)
-            utterances.extend(self._getSpeechForObjectAvailability(obj))
-        else:
-            utterances.append(checkedState)
-
-        self._debugGenerator("Gecko._getSpeechForCheckBox",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-
-    def getSpeechContext(self, obj, stopAncestor=None):
-        """Get the speech that describes the names and role of
-        the container hierarchy of the object, stopping at and
-        not including the stopAncestor.
-
-        Arguments:
-        - obj: the object
-        - stopAncestor: the ancestor to stop at and not include (None
-          means include all ancestors)
-
-        Returns a list of utterances to be spoken.
-        """
-
-        utterances = []
-
-        if obj is stopAncestor:
-            return utterances
-
-        # Skip items of unknown rolenames, menu bars, labels with 
-        # children, and autocompletes.  (With autocompletes, we
-        # wind up speaking the text object)
-        #
-        skipRoles = [pyatspi.ROLE_UNKNOWN,
-                     pyatspi.ROLE_MENU_BAR,
-                     pyatspi.ROLE_LABEL,
-                     pyatspi.ROLE_AUTOCOMPLETE]
-
-        # Stop if we get to a document frame or an internal frame.
-        #
-        stopRoles = [pyatspi.ROLE_DOCUMENT_FRAME,
-                     pyatspi.ROLE_INTERNAL_FRAME]
-
-        # There are some objects we want to include in the context,
-        # but not add their rolenames.
-        #
-        dontSpeakRoles = [pyatspi.ROLE_TABLE_CELL,
-                          pyatspi.ROLE_FILLER]
-
-        parent = obj.parent
-        while parent and (parent.parent != parent):
-            role = parent.getRole()
-            if self._script.isSameObject(parent, stopAncestor) \
-               or role in stopRoles:
-                break
-
-            if role in skipRoles or self._script.isLayoutOnly(parent):
-                parent = parent.parent
-                continue
-
-            # If the parent is a menu and its parent is a combo box
-            # we'll speak the object as a combo box.
-            #
-            if role == pyatspi.ROLE_MENU \
-               and parent.parent.getRole() == pyatspi.ROLE_COMBO_BOX:
-                parent = parent.parent
-                continue
-                
-            # Also skip the parent if its accessible text is a single 
-            # EMBEDDED_OBJECT_CHARACTER: Script.getDisplayedText will
-            # end up coming back to the child of an object for the text
-            # if an object's text contains a single EOC.
-            #
-            parentText = self._script.queryNonEmptyText(parent)
-            if parentText:
-                unicodeText = parentText.getText(0, -1).decode("UTF-8")
-                if unicodeText == self._script.EMBEDDED_OBJECT_CHARACTER:
-                    parent = parent.parent
-                    continue
-
-            # Put in the text and label (if they exist).
-            #
-            text = self._script.getDisplayedText(parent)
-            label = self._script.getDisplayedLabel(parent)
-            newUtterances = []
-            if text and (text != label) and len(text.strip()) \
-                and (not text.startswith("chrome://")):
-                newUtterances.append(text)
-            if label and len(label.strip()):
-                newUtterances.append(label)
-
-            # Finally add the role if it's not among the roles we don't
-            # wish to speak.
-            #
-            if not role in dontSpeakRoles and len(newUtterances):
-                utterances.append(rolenames.getSpeechForRoleName(parent))
-
-            utterances.extend(newUtterances)
-
-            parent = parent.parent
-
-        utterances.reverse()
-
-        return utterances
-            
-    def _getSpeechForSlider(self, obj, already_focused):
-        """Get the speech for a slider.  If the object already
-        had focus, just the value is spoken.
-
-        Arguments:
-        - obj: the slider
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-        
-        # Let default handle non-ARIA widgets (XUL?)
-        if not self._script.isAriaWidget(obj):
-            return speechgenerator.SpeechGenerator.\
-                       _getSpeechForSlider(self, obj, already_focused)
-
-        value = obj.queryValue()
-
-        # OK, this craziness is all about trying to figure out the most
-        # meaningful formatting string for the floating point values.
-        # The number of places to the right of the decimal point should
-        # be set by the minimumIncrement, but the minimumIncrement isn't
-        # always set.  So...we'll default the minimumIncrement to 1/100
-        # of the range.  But, if max == min, then we'll just go for showing
-        # them off to two meaningful digits.
-        #
-        try:
-            minimumIncrement = value.minimumIncrement
-        except:
-            minimumIncrement = 0.0
-
-        if minimumIncrement == 0.0:
-            minimumIncrement = (value.maximumValue - value.minimumValue) \
-                               / 100.0
-
-        try:
-            decimalPlaces = max(0, -math.log10(minimumIncrement))
-        except:
-            try:
-                decimalPlaces = max(0, -math.log10(value.minimumValue))
-            except:
-                try:
-                    decimalPlaces = max(0, -math.log10(value.maximumValue))
-                except:
-                    decimalPlaces = 0
-
-        formatter = "%%.%df" % decimalPlaces
-        valueString = formatter % value.currentValue
-        #minString   = formatter % value.minimumValue
-        #maxString   = formatter % value.maximumValue
-
-        if already_focused:
-            utterances = [valueString]
-        else:
-            utterances = []
-            utterances.extend(self._getSpeechForObjectLabel(obj))
-            utterances.extend(self.getSpeechForObjectRole(obj))
-            utterances.append(valueString)
-            utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        self._debugGenerator("_getSpeechForSlider",
-                             obj,
-                             already_focused,
-                             utterances)
-
-        return utterances
-                        
-########################################################################
-#                                                                      #
-# Custom WhereAmI                                                      #
-#                                                                      #
-######################################################################## 
-
-class GeckoWhereAmI(where_am_I.WhereAmI):
-    def __init__(self, script):
-        """Gecko specific WhereAmI that will be used to speak information
-        about the current object of interest and will provide additional Gecko
-        specific information.
-        """
-        where_am_I.WhereAmI.__init__(self, script)
-        self._script = script
-        
-    def whereAmI(self, obj, basicOnly):
-        """Calls the base class method for basic information and Gecko
-        specific presentation methods for detailed/custom information.
-        """
-        if basicOnly or not self._script.inDocumentContent(obj):
-            where_am_I.WhereAmI.whereAmI(self, obj, basicOnly)
-            self._script.liveMngr.outputLiveRegionDescription(obj)
-        else:
-            if settings.useCollection:
-                try:
-                    self._collectionPageSummary()
-                except:
-                    debug.printException(debug.LEVEL_SEVERE)
-                    self._iterativePageSummary(obj)
-            else:
-                self._iterativePageSummary(obj)
-
-    def _speakText(self, obj, basicOnly):
-        """Speaks the line if the current line contains embedded object
-        characters; otherwise calls the parent class.
-        """
-
-        line = self._script.currentLineContents
-        if not self._script.inDocumentContent(obj) \
-           or not line or len(line) == 1:
-            return where_am_I.WhereAmI._speakText(self, obj, basicOnly)
-
-        cell = self._script.getAncestor(obj,
-                                        [pyatspi.ROLE_TABLE_CELL],
-                                        [pyatspi.ROLE_DOCUMENT_FRAME])
-        if cell:
-            return self._speakTableCell(cell, basicOnly)
-
-        utterances = []
-        text = self._getObjLabel(obj)
-        utterances.append(text)
-
-        if obj.getRole() == pyatspi.ROLE_LINK:
-            text = rolenames.getSpeechForRoleName(obj.parent)
-        else:
-            text = rolenames.getSpeechForRoleName(obj)
-        
-        utterances.append(text)
-        
-        speech.speakUtterances(utterances)
-        self._script.speakContents(line)
-
-    def _speakDefaultButton(self, obj):
-        """Speaks the default button in a dialog.
-
-        Arguments:
-        - obj: the dialog box for which the default button should be obtained
-        """
-
-        if not (self._script.inDocumentContent(orca_state.locusOfFocus) \
-                and not self._script.isAriaWidget(orca_state.locusOfFocus)):
-            where_am_I.WhereAmI._speakDefaultButton(self, obj)
-
-    def _collectionPageSummary(self):
-        """Uses the Collection interface to get the quantity of headings, 
-        forms, tables, visited and unvisited links.
-        """
-        docframe = self._script.getDocumentFrame()
-        col = docframe.queryCollection()
-        # We will initialize these after the queryCollection() call in case
-        # Collection is not supported
-        headings = 0 
-        forms = 0
-        tables = 0
-        vlinks = 0
-        uvlinks = 0
-
-        stateset = pyatspi.StateSet()
-        roles = [pyatspi.ROLE_HEADING, pyatspi.ROLE_LINK, pyatspi.ROLE_TABLE,
-                 pyatspi.ROLE_FORM]
-        rule = col.createMatchRule(stateset.raw(), col.MATCH_NONE,  
-                                   "", col.MATCH_NONE,
-                                   roles, col.MATCH_ANY,
-                                   "", col.MATCH_NONE,
-                                   False)
-
-        matches = col.getMatches(rule, col.SORT_ORDER_CANONICAL, 0, True)
-
-        col.freeMatchRule(rule)
-        for obj in matches:
-            role = obj.getRole()
-            if role == pyatspi.ROLE_HEADING:
-                headings += 1
-            elif role == pyatspi.ROLE_FORM:
-                forms += 1
-            elif role == pyatspi.ROLE_TABLE \
-                      and not self._script.isLayoutOnly(obj):
-                tables += 1
-            elif role == pyatspi.ROLE_LINK:
-                if obj.getState().contains(pyatspi.STATE_VISITED):
-                    vlinks += 1
-                else:
-                    uvlinks += 1
-
-        self._outputPageSummary(headings, forms, tables, vlinks, uvlinks, None)
-            
-    def _iterativePageSummary(self, obj):
-        """Reads the quantity of headings, forms, tables, visited and 
-        unvisited links.
-        """
-        headings = 0 
-        forms = 0
-        tables = 0
-        vlinks = 0
-        uvlinks = 0
-        nodetotal = 0
-        obj_index = None
-        currentobj = obj
-
-        # start at the first object after document frame
-        obj = self._script.getDocumentFrame()[0]
-        while obj:
-            nodetotal += 1
-            if obj == currentobj:
-                obj_index = nodetotal
-            role = obj.getRole()
-            if role == pyatspi.ROLE_HEADING:
-                headings += 1
-            elif role == pyatspi.ROLE_FORM:
-                forms += 1
-            elif role == pyatspi.ROLE_TABLE \
-                      and not self._script.isLayoutOnly(obj):
-                tables += 1
-            elif role == pyatspi.ROLE_LINK:
-                if obj.getState().contains(pyatspi.STATE_VISITED):
-                    vlinks += 1
-                else:
-                    uvlinks += 1
-
-            obj = self._script.findNextObject(obj)
-
-        # Calculate the percentage of the document that has been read.
-        if obj_index:
-            percentread = int(obj_index*100/nodetotal)
-        else:
-            percentread = None
-
-        self._outputPageSummary(headings, forms, tables, 
-                               vlinks, uvlinks, percentread)
-
-    def _outputPageSummary(self, headings, forms, tables, 
-                                 vlinks, uvlinks, percent):
-
-        utterances = []
-        if headings:
-            # Translators: Announces the number of headings in the
-            # web page that is currently being displayed.
-            #
-            utterances.append(ngettext \
-                 ('%d heading', '%d headings', headings) %headings)
-        if forms:
-            # Translators: Announces the number of forms in the
-            # web page that is currently being displayed.
-            #
-            utterances.append(ngettext \
-                 ('%d form', '%d forms', forms) %forms)
-        if tables:
-            # Translators: Announces the number of non-layout tables in the
-            # web page that is currently being displayed.
-            #
-            utterances.append(ngettext \
-                 ('%d table', '%d tables', tables) %tables)
-        if vlinks:
-            # Translators: Announces the number of visited links in the
-            # web page that is currently being displayed.
-            #
-            utterances.append(ngettext \
-                 ('%d visited link', '%d visited links', vlinks) %vlinks)
-        if uvlinks:
-            # Translators: Announces the number of unvisited links in the
-            # web page that is currently being displayed.
-            #
-            utterances.append(ngettext \
-                 ('%d unvisited link', '%d unvisited links', uvlinks) %uvlinks)
-        if percent is not None:
-            # Translators: Announces the percentage of the document that has
-            # been read.  This is calculated by knowing the index of the 
-            # current position divided by the total number of objects on the 
-            # page.
-            # 
-            utterances.append(_('%d percent of document read') %percent)
-
-        speech.speakUtterances(utterances)  
-
-
-####################################################################
-#                                                                  #
-# Custom bookmarks class                                           #
-#                                                                  #
-####################################################################
-class GeckoBookmarks(bookmarks.Bookmarks):
-    def __init__(self, script):
-        bookmarks.Bookmarks.__init__(self, script)
-        self._currentbookmarkindex = {}
-        
-        
-    def addBookmark(self, inputEvent):
-        """ Add an in-page accessible object bookmark for this key and
-        webpage URI. """ 
-        # form bookmark dictionary key
-        index = (inputEvent.hw_code, self.getURIKey())
-        # convert the current object to a path and bookmark it
-        obj, characterOffset = self._script.getCaretContext()
-        path = self._objToPath()
-        self._bookmarks[index] = path, characterOffset
-        # Translators: this announces that a bookmark has been entered
-        #
-        utterances = [(_('entered bookmark'))]
-        utterances.extend(self._script.speechGenerator.getSpeech \
-                         (obj, False))
-        speech.speakUtterances(utterances)
-        
-    def goToBookmark(self, inputEvent, index=None):
-        """ Go to the bookmark indexed at this key and this page's URI """
-        index = index or (inputEvent.hw_code, self.getURIKey())
-        
-        try:
-            path, characterOffset = self._bookmarks[index]
-        except KeyError:
-            self._script.systemBeep()
-            return
-        # convert our path to an object
-        obj = self.pathToObj(path)
-       
-        if obj:
-            # restore the location
-            self._script.setCaretPosition(obj, characterOffset)
-            self._script.updateBraille(obj)
-            self._script.speakContents( \
-                self._script.getObjectContentsAtOffset(obj, characterOffset))
-            # update the currentbookmark
-            self._currentbookmarkindex[index[1]] = index[0]
-        else:
-            self._script.systemBeep()
-        
-    def bookmarkCurrentWhereAmI(self, inputEvent):
-        """ Report "Where am I" information for this bookmark relative to the 
-        current pointer location."""
-        index = (inputEvent.hw_code, self.getURIKey())
-        try:
-            path, characterOffset = self._bookmarks[index]
-            obj = self.pathToObj(path)
-        except KeyError:
-            self._script.systemBeep()
-            return
-            
-        [cur_obj, cur_characterOffset] = self._script.getCaretContext()
-        
-        # Are they the same object?
-        if self._script.isSameObject(cur_obj, obj):
-            # Translators: this announces that the current object is the same
-            # object pointed to by the bookmark.
-            #
-            speech.speak(_('bookmark is current object'))
-            return
-        # Are their parents the same?
-        elif self._script.isSameObject(cur_obj.parent, obj.parent):
-            # Translators: this announces that the current object's parent and 
-            # the parent of the object pointed to by the bookmark are the same.
-            #
-            speech.speak(_('bookmark and current object have same parent'))
-            return
-        
-        # Do they share a common ancestor?
-        # bookmark's ancestors
-        bookmark_ancestors = []
-        p = obj.parent
-        while p:
-            bookmark_ancestors.append(p)
-            p = p.parent
-        # look at current object's ancestors to compare to bookmark's ancestors
-        p = cur_obj.parent
-        while p:
-            if bookmark_ancestors.count(p) > 0:
-                # Translators: this announces that the bookmark and the current
-                # object share a common ancestor
-                #
-                speech.speak(_('shared ancestor %s') %p.getRole())
-                return
-            p = p.parent
-        
-        # Translators: This announces that a comparison between the bookmark
-        # and the current object can not be determined.
-        #
-        speech.speak(_('comparison unknown'))
-        
-    def saveBookmarks(self, inputEvent):
-        """ Save the bookmarks for this script. """
-        saved = {}
-         
-        # save obj as a path instead of an accessible
-        for index, bookmark in self._bookmarks.iteritems():
-            saved[index] = bookmark[0], bookmark[1]
-            
-        try:
-            self.saveBookmarksToDisk(saved)
-            # Translators: this announces that a bookmark has been saved to 
-            # disk
-            #
-            speech.speak(_('bookmarks saved'))
-        except IOError:
-            # Translators: this announces that a bookmark could not be saved to 
-            # disk
-            #
-            speech.speak(_('bookmarks could not be saved'))
-
-        # Notify the observers
-        for o in self._saveObservers:
-            o()
-            
-    def goToNextBookmark(self, inputEvent):
-        """ Go to the next bookmark location.  If no bookmark has yet to be
-        selected, the first bookmark will be used.  """
-        # The convenience of using a dictionary to add/goto a bookmark is 
-        # offset by the difficulty in finding the next bookmark.  We will 
-        # need to sort our keys to determine the next bookmark on a page by 
-        # page basis.
-        bm_keys = self._bookmarks.keys()
-        current_uri = self.getURIKey()
-        
-        # mine out the hardware keys for this page and sort them
-        thispage_hwkeys = []
-        for bm_key in bm_keys:
-            if bm_key[1] == current_uri:
-                thispage_hwkeys.append(bm_key[0])
-        thispage_hwkeys.sort()
-        
-        # no bookmarks for this page
-        if len(thispage_hwkeys) == 0:
-            self._script.systemBeep()
-            return
-        # only 1 bookmark or we are just starting out
-        elif len(thispage_hwkeys) == 1 or \
-                         not self._currentbookmarkindex.has_key(current_uri):
-            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
-            return
-        
-        # find current bookmark hw_code in our sorted list.  
-        # Go to next one if possible
-        try:
-            index = thispage_hwkeys.index( \
-                                 self._currentbookmarkindex[current_uri])
-            self.goToBookmark(None, index=( \
-                                 thispage_hwkeys[index+1], current_uri))
-        except (ValueError, KeyError, IndexError):
-            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
-            
-    def goToPrevBookmark(self, inputEvent):
-        """ Go to the previous bookmark location.  If no bookmark has yet to be
-        selected, the first bookmark will be used.  """
-        bm_keys = self._bookmarks.keys()
-        current_uri = self.getURIKey()
-        
-        # mine out the hardware keys for this page and sort them
-        thispage_hwkeys = []
-        for bm_key in bm_keys:
-            if bm_key[1] == current_uri:
-                thispage_hwkeys.append(bm_key[0])
-        thispage_hwkeys.sort()
-        
-        # no bookmarks for this page
-        if len(thispage_hwkeys) == 0:
-            self._script.systemBeep()
-            return
-        # only 1 bookmark or we are just starting out
-        elif len(thispage_hwkeys) == 1 or \
-                         not self._currentbookmarkindex.has_key(current_uri):
-            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))
-            return
-        
-        # find current bookmark hw_code in our sorted list.  
-        # Go to next one if possible
-        try:
-            index = thispage_hwkeys.index( \
-                            self._currentbookmarkindex[current_uri])
-            self.goToBookmark(None, 
-                              index=(thispage_hwkeys[index-1], current_uri))
-        except (ValueError, KeyError, IndexError):
-            self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri))    
-            
-    def _objToPickle(self, obj=None):
-        """Given an object, return it's saving (pickleable) format.  In this 
-        case, the obj path is determined relative to the document frame and is 
-        returned as a list.  If obj is not provided, the current caret context
-        is used.  """
-        return self._objToPath(start_obj=obj)
-                               
-    def _objToPath(self, start_obj=None):
-        """Given an object, return it's path from the root accessible.  If obj 
-        is not provided, the current caret context is used. """
-        if not start_obj:
-            [start_obj, characterOffset] = self._script.getCaretContext()    
-            
-        if start_obj is None \
-                     or start_obj.getRole() == pyatspi.ROLE_DOCUMENT_FRAME:
-            return []
-        else:
-            path = []
-            path.append(start_obj.getIndexInParent())
-            p = start_obj.parent
-            while p:
-                if p.getRole()  == pyatspi.ROLE_DOCUMENT_FRAME:
-                    path.reverse()
-                    return path
-                path.append(p.getIndexInParent())
-                p = p.parent
-            
-            return []
-            
-    def _pickleToObj(self, obj):
-        """Return the s with the given path (relative to the
-        document frame). """
-        
-        # could test for different obj types.  We'll just assume it is
-        # list that represents a path for now.
-        return self.pathToObj(obj)
-            
-    def pathToObj(self, path):
-        """Return the object with the given path (relative to the
-        document frame). """
-        returnobj = self._script.getDocumentFrame()
-        for childnumber in path:
-            try:
-                returnobj = returnobj[childnumber]
-            except IndexError:
-                return None
-            
-        return returnobj
-            
-    def getURIKey(self):
-        """Returns the URI key for a given page as a URI stripped of 
-        parameters?query#fragment as seen in urlparse."""
-        uri = self._script.getDocumentFrameURI()
-        if uri:
-            parsed_uri = urlparse.urlparse(uri)
-            return ''.join(parsed_uri[0:3])
-        else:
-            return None
-            
+from orca.orca_i18n import _
+from orca.orca_i18n import ngettext # for ngettext support
     
 ########################################################################
 #                                                                      #
@@ -7610,8 +5843,8 @@
         self._updateLineCache(obj, characterOffset)
 
     def getTextLineAtCaret(self, obj):
-        """Gets the line of text where the caret is. This is an override to accomodate
-        the intricities of our caret navigation management.
+        """Gets the line of text where the caret is. This is an override to 
+        accomodate the intricities of our caret navigation management.
 
         Argument:
         - obj: an Accessible object that implements the AccessibleText
@@ -7623,7 +5856,8 @@
 
         contextObj, contextCaret = self.getCaretContext()
 
-        string, caretOffset, startOffset = default.Script.getTextLineAtCaret(self, obj)
+        string, caretOffset, startOffset = \
+            default.Script.getTextLineAtCaret(self, obj)
 
         if contextObj == obj:
             if not obj.getState().contains(pyatspi.STATE_EDITABLE):
@@ -8704,7 +6938,7 @@
             self.setCaretPosition(obj, characterOffset)
             self.updateBraille(obj)
             contents = self.getObjectContentsAtOffset(obj, characterOffset)
-            self.speakContents(contents)
+            self.speakContents(contents)             
         else:
             # Translators: this is in reference to navigating HTML content
             # by heading (e.g., <h1>).

Added: trunk/src/orca/scripts/toolkits/Gecko/speech_generator.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/speech_generator.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,794 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Gecko toolkit.
+Please refer to the following URL for more information on the AT-SPI
+implementation in Gecko:
+http://developer.mozilla.org/en/docs/Accessibility/ATSPI_Support
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import math
+import pyatspi
+
+import orca.rolenames as rolenames
+import orca.speechgenerator as speechgenerator
+
+from orca.orca_i18n import _
+from orca.orca_i18n import ngettext # for ngettext support
+from orca.orca_i18n import Q_       # to provide qualified translatable strings
+
+########################################################################
+#                                                                      #
+# Custom SpeechGenerator                                               #
+#                                                                      #
+########################################################################
+
+class SpeechGenerator(speechgenerator.SpeechGenerator):
+    """Provides a speech generator specific to Gecko.
+    """
+
+    def __init__(self, script):
+        speechgenerator.SpeechGenerator.__init__(self, script)
+        self.speechGenerators[pyatspi.ROLE_DOCUMENT_FRAME] = \
+             self._getSpeechForDocumentFrame
+        self.speechGenerators[pyatspi.ROLE_ENTRY]          = \
+             self._getSpeechForText
+        self.speechGenerators[pyatspi.ROLE_LINK]           = \
+             self._getSpeechForLink
+        self.speechGenerators[pyatspi.ROLE_LIST_ITEM]      = \
+             self._getSpeechForListItem
+        self.speechGenerators[pyatspi.ROLE_SLIDER]         = \
+             self._getSpeechForSlider
+
+    def getSpeechForObjectRole(self, obj, role=None):
+        """Prevents some roles from being spoken."""
+        if obj.getRole() in [pyatspi.ROLE_PARAGRAPH,
+                             pyatspi.ROLE_SECTION,
+                             pyatspi.ROLE_LABEL,
+                             pyatspi.ROLE_FORM,
+                             pyatspi.ROLE_LIST_ITEM,
+                             pyatspi.ROLE_MENU_ITEM,
+                             pyatspi.ROLE_UNKNOWN]:
+            return []
+        else:
+            return [rolenames.getSpeechForRoleName(obj, role)]
+
+    def _getSpeechForDocumentFrame(self, obj, already_focused):
+        """Gets the speech for a document frame.
+
+        Arguments:
+        - obj: an Accessible
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        utterances = []
+
+        name = obj.name
+        if name and len(name):
+            utterances.append(name)
+        utterances.extend(self.getSpeechForObjectRole(obj))
+
+        self._debugGenerator("Gecko._getSpeechForDocumentFrame",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForText(self, obj, already_focused):
+        """Gets the speech for an autocomplete box.
+
+        Arguments:
+        - obj: an Accessible
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForText(self, obj, already_focused)
+        
+        utterances = []
+        parent = obj.parent
+        if parent.getRole() == pyatspi.ROLE_AUTOCOMPLETE:
+            # This is the main difference between this class and the default
+            # class - we'll give this thing a name here, and we'll make it
+            # be the name of the autocomplete.
+            #
+            label = self._script.getDisplayedLabel(parent)
+            if not label or not len(label):
+                label = parent.name
+            utterances.append(label)
+        elif obj.getRole() in [pyatspi.ROLE_ENTRY,
+                               pyatspi.ROLE_PASSWORD_TEXT] \
+            and self._script.inDocumentContent():
+            # This is a form field in web content.  If we don't get a label,
+            # we'll try to guess what text on the page is functioning as
+            # the label.
+            #
+            label = self._script.getDisplayedLabel(obj)
+            if not label or not len(label):
+                label = self._script.guessTheLabel(obj)
+            if label:
+                utterances.append(label)
+        else:
+            return speechgenerator.SpeechGenerator._getSpeechForText(
+                self, obj, already_focused)
+
+        utterances.extend(self.getSpeechForObjectRole(obj))
+
+        [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj)
+        utterances.append(text)
+
+        self._debugGenerator("Gecko._getSpeechForText",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForComboBox(self, obj, already_focused):
+        """Get the speech for a combo box.  If the combo box already has focus,
+        then only the selection is spoken.
+
+        Arguments:
+        - obj: the combo box
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForComboBox(self, obj, already_focused)
+        
+        utterances = []
+
+        label = self._script.getDisplayedLabel(obj)
+        if not label:
+            if not self._script.inDocumentContent():
+                label = obj.name
+            else:
+                label = self._script.guessTheLabel(obj)
+
+        if not already_focused and label:
+            utterances.append(label)
+
+        # With Gecko, a combo box has a menu as a child.  The text being
+        # displayed for the combo box can be obtained via the selected
+        # menu item.
+        #
+        menu = None
+        for child in obj:
+            if child.getRole() == pyatspi.ROLE_MENU:
+                menu = child
+                break
+        if menu:
+            child = None
+            try:
+                # This should work...
+                #
+                child = menu.querySelection().getSelectedChild(0)
+            except:
+                # But just in case, we'll fall back on this.
+                # [[[TODO - JD: Will we ever have a case where the first
+                # fails, but this will succeed???]]]
+                #
+                for item in menu:
+                    if item.getState().contains(pyatspi.STATE_SELECTED):
+                        child = item
+                        break
+            if child:
+                utterances.append(child.name)
+
+        utterances.extend(self._getSpeechForObjectAvailability(obj))
+
+        if not already_focused:
+            utterances.extend(self.getSpeechForObjectRole(obj))
+
+        self._debugGenerator("Gecko._getSpeechForComboBox",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForMenuItem(self, obj, already_focused):
+        """Get the speech for a menu item.
+
+        Arguments:
+        - obj: the menu item
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForMenuItem(self, obj, already_focused)
+        
+        if not self._script.inDocumentContent():
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForMenuItem(self, obj, already_focused)
+
+        utterances = self._getSpeechForObjectName(obj)
+
+        # Saying "menu item" for a combo box can confuse users. Therefore,
+        # speak the combo box role instead.  Also, only do it if the menu
+        # item is not focused (if the menu item is focused, it means we're
+        # navigating in the combo box)
+        #
+        if not obj.getState().contains(pyatspi.STATE_FOCUSED):
+            comboBox = \
+                 self._script.getAncestor(obj,
+                                          [pyatspi.ROLE_COMBO_BOX],
+                                          [pyatspi.ROLE_DOCUMENT_FRAME])
+            if comboBox:
+                utterances.extend(self.getSpeechForObjectRole(comboBox))
+
+        self._debugGenerator("Gecko._getSpeechForMenuItem",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForListItem(self, obj, already_focused):
+        """Get the speech for a list item.
+
+        Arguments:
+        - obj: the list item
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+
+        if self._script.isAriaWidget(obj) \
+           or not self._script.inDocumentContent(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForListItem(self, obj, already_focused)
+        
+        if not obj.getState().contains(pyatspi.STATE_SELECTABLE):
+            return speechgenerator.SpeechGenerator.\
+                       _getDefaultSpeech(self, obj, already_focused)
+
+        utterances = self._getSpeechForObjectName(obj)
+
+        self._debugGenerator("Gecko._getSpeechForListItem",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForList(self, obj, already_focused):
+        """Get the speech for a list.
+
+        Arguments:
+        - obj: the list
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForList(self, obj, already_focused)
+        
+        if not obj.getState().contains(pyatspi.STATE_FOCUSABLE):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForList(self, obj, already_focused)
+
+        utterances = []
+
+        if obj.getState().contains(pyatspi.STATE_FOCUSED):
+            label = self._script.getDisplayedLabel(obj)
+            if not label:
+                if not self._script.inDocumentContent():
+                    label = obj.name
+                else:
+                    label = self._script.guessTheLabel(obj)
+
+            if not already_focused and label:
+                utterances.append(label)
+
+            item = None
+            selection = obj.querySelection()
+            for i in xrange(obj.childCount):
+                if selection.isChildSelected(i):
+                    item = obj[i]
+                    break
+            item = item or obj[0]
+            if item:
+                name = self._getSpeechForObjectName(item)
+                if name != label:
+                    utterances.extend(name)
+
+        if not already_focused:
+            if obj.getState().contains(pyatspi.STATE_MULTISELECTABLE):
+                # Translators: "multi-select" refers to a web form list
+                # in which more than one item can be selected at a time.
+                #
+                utterances.append(_("multi-select"))
+
+            # Translators: this represents a list in HTML.
+            #
+            itemString = ngettext("List with %d item",
+                                  "List with %d items",
+                                  obj.childCount) % obj.childCount
+            utterances.append(itemString)
+
+        self._debugGenerator("Gecko._getSpeechForList",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForImage(self, obj, already_focused):
+        """Gets a list of utterances to be spoken for an image.
+
+        The default speech will be of the following form:
+
+        label name role availability
+
+        Arguments:
+        - obj: an Accessible
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForImage(self, obj, already_focused)
+        
+        utterances = []
+
+        if not already_focused:
+            label = self._getSpeechForObjectLabel(obj)
+            utterances.extend(label)
+            name = self._getSpeechForObjectName(obj)
+            if name != label:
+                utterances.extend(name)
+
+            # If there's no text for the image, expose the link to
+            # the user if the image is in a link.
+            #
+            link = self._script.getAncestor(obj,
+                                            [pyatspi.ROLE_LINK],
+                                            [pyatspi.ROLE_DOCUMENT_FRAME])
+            if not len(utterances):
+                if link:
+                    utterances.extend(self._getSpeechForLink(link,
+                                                             already_focused))
+            elif link:
+                utterances.extend(self.getSpeechForObjectRole(link))
+
+            utterances.extend(self.getSpeechForObjectRole(obj))
+
+        utterances.extend(self._getSpeechForObjectAvailability(obj))
+
+        self._debugGenerator("Gecko._getSpeechForImage",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForLink(self, obj, already_focused):
+        """Gets a list of utterances to be spoken for a link.
+
+        Arguments:
+        - obj: an Accessible
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.getSpeech(obj,
+                                                             already_focused)
+        
+        utterances = []
+
+        if not already_focused:
+            label = self._getSpeechForObjectLabel(obj)
+            utterances.extend(label)
+            name = self._getSpeechForObjectName(obj)
+
+            # Handle empty alt tags.
+            #
+            if name:
+                lengthOfName = len(name[0].strip())
+                if (lengthOfName > 0) and (name != label):
+                    utterances.extend(name)
+
+            # If there's no text for the link, expose part of the
+            # URI to the user.
+            #
+            if not len(utterances):
+                basename = self._script.getLinkBasename(obj)
+                if basename:
+                    utterances.append(basename)
+
+            utterances.extend(self.getSpeechForObjectRole(obj))
+
+        utterances.extend(self._getSpeechForObjectAvailability(obj))
+
+        self._debugGenerator("Gecko._getSpeechForLink",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def _getSpeechForTable(self, obj, already_focused):
+        """Get the speech for a table
+
+        Arguments:
+        - obj: the table
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForTable(self, obj, already_focused)
+        
+        # [[[TODO: JD - We should decide if we want to provide
+        # information about the table dimensions, whether or not
+        # this is a layout table versus a data table, etc.  For now,
+        # however, if it's in HTML content let's ignore it so that
+        # SayAll by sentence works. :-) ]]]
+        #
+        utterances = []
+
+        if not self._script.inDocumentContent():
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForTable(self, obj, already_focused)
+
+        return utterances
+
+    def _getSpeechForRadioButton(self, obj, already_focused):
+        """Get the speech for a radio button.  If the button already had
+        focus, then only the state is spoken.
+
+        Arguments:
+        - obj: the radio button
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForRadioButton(self, obj, already_focused)
+        
+        if not self._script.inDocumentContent():
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForRadioButton(self, obj, already_focused)
+
+        utterances = []
+        if obj.getState().contains(pyatspi.STATE_CHECKED):
+            # Translators: this is in reference to a radio button being
+            # selected or not.
+            #
+            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+            #
+            selectionState = Q_("radiobutton|selected")
+        else:
+            # Translators: this is in reference to a radio button being
+            # selected or not.
+            #
+            # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+            #
+            selectionState = Q_("radiobutton|not selected")
+
+        if not already_focused:
+            # The label is handled as a context in default.py -- assuming we
+            # don't have to guess it.  If  we need to guess it, we need to
+            # add it to utterances.
+            #
+            label = self._script.getDisplayedLabel(obj)
+            if not label:
+                label = self._script.guessTheLabel(obj)
+                if label:
+                    utterances.append(label)
+
+            utterances.append(selectionState)
+            utterances.extend(self.getSpeechForObjectRole(obj))
+            utterances.extend(self._getSpeechForObjectAvailability(obj))
+        else:
+            utterances.append(selectionState)
+
+        self._debugGenerator("Gecko._getSpeechForRadioButton",
+                             obj,
+                             already_focused,
+                             utterances)
+        return utterances
+
+    def _getSpeechForCheckBox(self, obj, already_focused):
+        """Get the speech for a check box.  If the check box already had
+        focus, then only the state is spoken.
+
+        Arguments:
+        - obj: the check box
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+
+        # Treat ARIA widgets like default.py widgets
+        #
+        if self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForCheckBox(self, obj, already_focused)
+        
+        if not self._script.inDocumentContent():
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForCheckBox(self, obj, already_focused)
+
+        utterances = []
+        state = obj.getState()
+        if state.contains(pyatspi.STATE_INDETERMINATE):
+            # Translators: this represents the state of a checkbox.
+            #
+            checkedState = _("partially checked")
+        elif state.contains(pyatspi.STATE_CHECKED):
+            # Translators: this represents the state of a checkbox.
+            #
+            checkedState = _("checked")
+        else:
+            # Translators: this represents the state of a checkbox.
+            #
+            checkedState = _("not checked")
+
+        # If it's not already focused, say its label.
+        #
+        if not already_focused:
+            label = self._script.getDisplayedLabel(obj)
+            if not label:
+                label = self._script.guessTheLabel(obj)
+            if label:
+                utterances.append(label)
+            utterances.extend(self.getSpeechForObjectRole(obj))
+            utterances.append(checkedState)
+            utterances.extend(self._getSpeechForObjectAvailability(obj))
+        else:
+            utterances.append(checkedState)
+
+        self._debugGenerator("Gecko._getSpeechForCheckBox",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+
+    def getSpeechContext(self, obj, stopAncestor=None):
+        """Get the speech that describes the names and role of
+        the container hierarchy of the object, stopping at and
+        not including the stopAncestor.
+
+        Arguments:
+        - obj: the object
+        - stopAncestor: the ancestor to stop at and not include (None
+          means include all ancestors)
+
+        Returns a list of utterances to be spoken.
+        """
+
+        utterances = []
+
+        if obj is stopAncestor:
+            return utterances
+
+        parent = obj.parent
+        while parent and (parent.parent != parent):
+            if self._script.isSameObject(parent, stopAncestor):
+                break
+
+            # We try to omit layout things right off the bat.
+            #
+            if self._script.isLayoutOnly(parent):
+                parent = parent.parent
+                continue
+
+            # If the rolename is unknown, skip this item.
+            #
+            if parent.getRole() == pyatspi.ROLE_UNKNOWN:
+                parent = parent.parent
+                continue
+
+            # To be consistent with how we provide access to other
+            # applications, don't speak the name of menu bars.
+            #
+            if parent.getRole() == pyatspi.ROLE_MENU_BAR:
+                parent = parent.parent
+                continue
+
+            # Skip unfocusable menus.  This is for earlier versions
+            # of Firefox where menus were nested in kind of an odd
+            # dual nested menu hierarchy.
+            #
+            if (parent.getRole() == pyatspi.ROLE_MENU) \
+               and not parent.getState().contains(pyatspi.STATE_FOCUSABLE):
+                parent = parent.parent
+                continue
+
+            # Now...autocompletes are weird.  We'll let the handling of
+            # the entry give us the name -- unless we're in a toolbar.
+            #
+            containingToolbar = \
+                  self._script.getAncestor(obj,
+                                           [pyatspi.ROLE_TOOL_BAR],
+                                           [pyatspi.ROLE_DOCUMENT_FRAME])
+            if parent.getRole() == pyatspi.ROLE_AUTOCOMPLETE and \
+               not containingToolbar:
+                parent = parent.parent
+                continue
+
+            # Labels with children should be ignored.  (This is the
+            # bugzilla form bogusity bug.)
+            #
+            if parent.getRole() == pyatspi.ROLE_LABEL:
+                parent = parent.parent
+                continue
+                
+            # Well...now we skip the parent if it's accessible text is
+            # a single EMBEDDED_OBJECT_CHARACTER.  The reason for this
+            # is that it Script.getDisplayedText will end up coming
+            # back to the children of an object for the text in the
+            # children if an object's text contains an
+            # EMBEDDED_OBJECT_CHARACTER.
+            #
+            parentText = self._script.queryNonEmptyText(parent)
+            if parentText:
+                displayedText = parentText.getText(0, -1)
+                unicodeText = displayedText.decode("UTF-8")
+                if unicodeText \
+                    and (len(unicodeText) == 1) \
+                    and (unicodeText[0] == \
+                                     self._script.EMBEDDED_OBJECT_CHARACTER):
+                    parent = parent.parent
+                    continue
+
+            # Finally, put in the text and label (if they exist)
+            #
+            text = self._script.getDisplayedText(parent)
+            label = self._script.getDisplayedLabel(parent)
+            newUtterances = []
+            if text and (text != label) and len(text.strip()) \
+                and (not text.startswith("chrome://")):
+                newUtterances.append(text)
+            if label and len(label.strip()):
+                newUtterances.append(label)
+
+            # Well...if we made it this far, we will now append the
+            # role, then the text, and then the label.
+            #
+            if not parent.getRole() in [pyatspi.ROLE_TABLE_CELL,
+                                        pyatspi.ROLE_FILLER] \
+                and len(newUtterances):
+                utterances.append(rolenames.getSpeechForRoleName(parent))
+
+            utterances.extend(newUtterances)
+
+            parent = parent.parent
+
+        utterances.reverse()
+
+        return utterances
+            
+    def _getSpeechForSlider(self, obj, already_focused):
+        """Get the speech for a slider.  If the object already
+        had focus, just the value is spoken.
+
+        Arguments:
+        - obj: the slider
+        - already_focused: False if object just received focus
+
+        Returns a list of utterances to be spoken for the object.
+        """
+        
+        # Let default handle non-ARIA widgets (XUL?)
+        if not self._script.isAriaWidget(obj):
+            return speechgenerator.SpeechGenerator.\
+                       _getSpeechForSlider(self, obj, already_focused)
+
+        value = obj.queryValue()
+
+        # OK, this craziness is all about trying to figure out the most
+        # meaningful formatting string for the floating point values.
+        # The number of places to the right of the decimal point should
+        # be set by the minimumIncrement, but the minimumIncrement isn't
+        # always set.  So...we'll default the minimumIncrement to 1/100
+        # of the range.  But, if max == min, then we'll just go for showing
+        # them off to two meaningful digits.
+        #
+        try:
+            minimumIncrement = value.minimumIncrement
+        except:
+            minimumIncrement = 0.0
+
+        if minimumIncrement == 0.0:
+            minimumIncrement = (value.maximumValue - value.minimumValue) \
+                               / 100.0
+
+        try:
+            decimalPlaces = max(0, -math.log10(minimumIncrement))
+        except:
+            try:
+                decimalPlaces = max(0, -math.log10(value.minimumValue))
+            except:
+                try:
+                    decimalPlaces = max(0, -math.log10(value.maximumValue))
+                except:
+                    decimalPlaces = 0
+
+        formatter = "%%.%df" % decimalPlaces
+        valueString = formatter % value.currentValue
+        #minString   = formatter % value.minimumValue
+        #maxString   = formatter % value.maximumValue
+
+        if already_focused:
+            utterances = [valueString]
+        else:
+            utterances = []
+            utterances.extend(self._getSpeechForObjectLabel(obj))
+            utterances.extend(self.getSpeechForObjectRole(obj))
+            utterances.append(valueString)
+            utterances.extend(self._getSpeechForObjectAvailability(obj))
+
+        self._debugGenerator("_getSpeechForSlider",
+                             obj,
+                             already_focused,
+                             utterances)
+
+        return utterances
+                        

Added: trunk/src/orca/scripts/toolkits/Gecko/where_am_i.py
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Gecko/where_am_i.py	Fri May  2 21:21:19 2008
@@ -0,0 +1,216 @@
+# Orca
+#
+# Copyright 2005-2007 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+"""Custom script for Gecko toolkit.
+Please refer to the following URL for more information on the AT-SPI
+implementation in Gecko:
+http://developer.mozilla.org/en/docs/Accessibility/ATSPI_Support
+"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2007 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+import pyatspi
+
+import orca.debug as debug
+import orca.orca_state as orca_state
+import orca.settings as settings
+import orca.speech as speech
+import orca.where_am_I as where_am_I
+
+from orca.orca_i18n import _
+from orca.orca_i18n import ngettext # for ngettext support
+
+########################################################################
+#                                                                      #
+# Custom WhereAmI                                                      #
+#                                                                      #
+######################################################################## 
+
+class GeckoWhereAmI(where_am_I.WhereAmI):
+    def __init__(self, script):
+        """Gecko specific WhereAmI that will be used to speak information
+        about the current object of interest and will provide additional Gecko
+        specific information.
+        """
+        where_am_I.WhereAmI.__init__(self, script)
+        self._script = script
+        
+    def whereAmI(self, obj, basicOnly):
+        """Calls the base class method for basic information and Gecko
+        specific presentation methods for detailed/custom information.
+        """
+        if basicOnly or not self._script.inDocumentContent(obj):
+            where_am_I.WhereAmI.whereAmI(self, obj, basicOnly)
+            self._script.liveMngr.outputLiveRegionDescription(obj)
+        else:
+            if settings.useCollection:
+                try:
+                    self._collectionPageSummary()
+                except:
+                    debug.printException(debug.LEVEL_SEVERE)
+                    self._iterativePageSummary(obj)
+            else:
+                self._iterativePageSummary(obj)
+
+    def _speakDefaultButton(self, obj):
+        """Speaks the default button in a dialog.
+
+        Arguments:
+        - obj: the dialog box for which the default button should be obtained
+        """
+
+        if not (self._script.inDocumentContent(orca_state.locusOfFocus) \
+                and not self._script.isAriaWidget(orca_state.locusOfFocus)):
+            where_am_I.WhereAmI._speakDefaultButton(self, obj)
+
+    def _collectionPageSummary(self):
+        """Uses the Collection interface to get the quantity of headings, 
+        forms, tables, visited and unvisited links.
+        """
+        docframe = self._script.getDocumentFrame()
+        col = docframe.queryCollection()
+        # We will initialize these after the queryCollection() call in case
+        # Collection is not supported
+        headings = 0 
+        forms = 0
+        tables = 0
+        vlinks = 0
+        uvlinks = 0
+
+        stateset = pyatspi.StateSet()
+        roles = [pyatspi.ROLE_HEADING, pyatspi.ROLE_LINK, pyatspi.ROLE_TABLE,
+                 pyatspi.ROLE_FORM]
+        rule = col.createMatchRule(stateset.raw(), col.MATCH_NONE,  
+                                   "", col.MATCH_NONE,
+                                   roles, col.MATCH_ANY,
+                                   "", col.MATCH_NONE,
+                                   False)
+
+        matches = col.getMatches(rule, col.SORT_ORDER_CANONICAL, 0, True)
+
+        col.freeMatchRule(rule)
+        for obj in matches:
+            role = obj.getRole()
+            if role == pyatspi.ROLE_HEADING:
+                headings += 1
+            elif role == pyatspi.ROLE_FORM:
+                forms += 1
+            elif role == pyatspi.ROLE_TABLE \
+                      and not self._script.isLayoutOnly(obj):
+                tables += 1
+            elif role == pyatspi.ROLE_LINK:
+                if obj.getState().contains(pyatspi.STATE_VISITED):
+                    vlinks += 1
+                else:
+                    uvlinks += 1
+
+        self._outputPageSummary(headings, forms, tables, vlinks, uvlinks, None)
+            
+    def _iterativePageSummary(self, obj):
+        """Reads the quantity of headings, forms, tables, visited and 
+        unvisited links.
+        """
+        headings = 0 
+        forms = 0
+        tables = 0
+        vlinks = 0
+        uvlinks = 0
+        nodetotal = 0
+        obj_index = None
+        currentobj = obj
+
+        # start at the first object after document frame
+        obj = self._script.getDocumentFrame()[0]
+        while obj:
+            nodetotal += 1
+            if obj == currentobj:
+                obj_index = nodetotal
+            role = obj.getRole()
+            if role == pyatspi.ROLE_HEADING:
+                headings += 1
+            elif role == pyatspi.ROLE_FORM:
+                forms += 1
+            elif role == pyatspi.ROLE_TABLE \
+                      and not self._script.isLayoutOnly(obj):
+                tables += 1
+            elif role == pyatspi.ROLE_LINK:
+                if obj.getState().contains(pyatspi.STATE_VISITED):
+                    vlinks += 1
+                else:
+                    uvlinks += 1
+
+            obj = self._script.findNextObject(obj)
+
+        # Calculate the percentage of the document that has been read.
+        if obj_index:
+            percentread = int(obj_index*100/nodetotal)
+        else:
+            percentread = None
+
+        self._outputPageSummary(headings, forms, tables, 
+                               vlinks, uvlinks, percentread)
+
+    def _outputPageSummary(self, headings, forms, tables, 
+                                 vlinks, uvlinks, percent):
+
+        utterances = []
+        if headings:
+            # Translators: Announces the number of headings in the
+            # web page that is currently being displayed.
+            #
+            utterances.append(ngettext \
+                 ('%d heading', '%d headings', headings) %headings)
+        if forms:
+            # Translators: Announces the number of forms in the
+            # web page that is currently being displayed.
+            #
+            utterances.append(ngettext \
+                 ('%d form', '%d forms', forms) %forms)
+        if tables:
+            # Translators: Announces the number of non-layout tables in the
+            # web page that is currently being displayed.
+            #
+            utterances.append(ngettext \
+                 ('%d table', '%d tables', tables) %tables)
+        if vlinks:
+            # Translators: Announces the number of visited links in the
+            # web page that is currently being displayed.
+            #
+            utterances.append(ngettext \
+                 ('%d visited link', '%d visited links', vlinks) %vlinks)
+        if uvlinks:
+            # Translators: Announces the number of unvisited links in the
+            # web page that is currently being displayed.
+            #
+            utterances.append(ngettext \
+                 ('%d unvisited link', '%d unvisited links', uvlinks) %uvlinks)
+        if percent is not None:
+            # Translators: Announces the percentage of the document that has
+            # been read.  This is calculated by knowing the index of the 
+            # current position divided by the total number of objects on the 
+            # page.
+            # 
+            utterances.append(_('%d percent of document read') %percent)
+
+        speech.speakUtterances(utterances)  
+

Copied: trunk/src/orca/scripts/toolkits/J2SE-access-bridge.py (from r3875, /trunk/src/orca/J2SE-access-bridge.py)
==============================================================================
--- /trunk/src/orca/J2SE-access-bridge.py	(original)
+++ trunk/src/orca/scripts/toolkits/J2SE-access-bridge.py	Fri May  2 21:21:19 2008
@@ -25,17 +25,17 @@
 
 import pyatspi
 
-import default
-import debug
-import orca
-import orca_state
-import keybindings
-import speech
-import rolenames
-import speechgenerator
+import orca.default as default
+import orca.debug as debug
+import orca.orca as orca
+import orca.orca_state as orca_state
+import orca.keybindings as keybindings
+import orca.speech as speech
+import orca.rolenames as rolenames
+import orca.speechgenerator as speechgenerator
 
-from orca_i18n import _ # for gettext support
-from orca_i18n import Q_ # to provide qualified translatable strings
+from orca.orca_i18n import _ # for gettext support
+from orca.orca_i18n import Q_ # to provide qualified translatable strings
 
 ########################################################################
 #                                                                      #

Added: trunk/src/orca/scripts/toolkits/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/orca/scripts/toolkits/Makefile.am	Fri May  2 21:21:19 2008
@@ -0,0 +1,12 @@
+SUBDIRS = Gecko
+
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py \
+	GAIL.py \
+	J2SE-access-bridge.py \
+	VCL.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/toolkits
+

Copied: trunk/src/orca/scripts/toolkits/VCL.py (from r3875, /trunk/src/orca/scripts/Mozilla.py)
==============================================================================
--- /trunk/src/orca/scripts/Mozilla.py	(original)
+++ trunk/src/orca/scripts/toolkits/VCL.py	Fri May  2 21:21:19 2008
@@ -17,7 +17,7 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-"""Custom script for Mozilla.  NOT WORKING WELL AT THE MOMENT."""
+"""Custom script for VCL toolkit (OpenOffice) applications"""
 
 __id__        = "$Id$"
 __version__   = "$Revision$"
@@ -25,12 +25,7 @@
 __copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.Gecko as Gecko
+import orca.default
 
-class Script(Gecko.Script):
-    def __init__(self, app):
-        Gecko.Script.__init__(self, app)
-
-        # By default, don't present if Mozilla is not the active application.
-        #
-        self.presentIfInactive = False
+class Script(orca.default.Script):
+    pass

Added: trunk/src/orca/scripts/toolkits/__init__.py
==============================================================================

Modified: trunk/src/orca/settings.py
==============================================================================
--- trunk/src/orca/settings.py	(original)
+++ trunk/src/orca/settings.py	Fri May  2 21:21:19 2008
@@ -778,7 +778,8 @@
 # REMEMBER: to make something a package, the directory has to
 # have a __init__.py file in it.
 #
-scriptPackages          = ["orca-scripts", "scripts"]
+scriptPackages          = ["orca-scripts", "scripts", 
+                           "scripts.apps", "scripts.toolkits"]
 
 # A list that helps us map application names to script module
 # names.  The key is the name of an application, and the value is
@@ -836,22 +837,22 @@
 # I wish the AT-SPI spec'd this out as machine readable (unlocalized)
 # names, but it's what we're stuck with (unfortunately).
 #
-setScriptMapping(re.compile(_('[\S\s]*StarOffice[\s\S]*')), "StarOffice")
+setScriptMapping(re.compile(_('[\S\s]*StarOffice[\s\S]*')), "soffice")
 
 # Translators: see the regular expression note above.  This is for
 # OpenOffice and StarOffice.
 #
-setScriptMapping(re.compile(_('soffice.bin')), "StarOffice")
+setScriptMapping(re.compile(_('soffice.bin')), "soffice")
 
 # Translators: see the regular expression note above.  This is for
 # OpenOffice and StarOffice.
 #
-setScriptMapping(re.compile(_('soffice')), "StarOffice")
+setScriptMapping(re.compile(_('soffice')), "soffice")
 
 # Translators: see the regular expression note above.  This is for the
 # Evolution mail application.
 #
-setScriptMapping(re.compile(_('[Ee]volution')), "Evolution")
+setScriptMapping(re.compile(_('[Ee]volution')), "evolution")
 
 # Translators: see the regular expression note above.  This is for the
 # help application (yelp).
@@ -892,9 +893,9 @@
 setScriptMapping(re.compile(_('vte')), "gnome-terminal")
 
 # Translators: see the regular expression note above.  This is for
-# supporting pidgin, which is the new name for gaim.
+# supporting gaim, which has recently be renamed to pidgin.
 #
-setScriptMapping(re.compile(_('pidgin')), "gaim")
+setScriptMapping(re.compile(_('gaim')), "pidgin")
 
 # Show deprecated messeges in debug output.
 # Set this to True to help find potential pyatspi porting problems

Modified: trunk/test/harness/orca-customizations.py.in
==============================================================================
--- trunk/test/harness/orca-customizations.py.in	(original)
+++ trunk/test/harness/orca-customizations.py.in	Fri May  2 21:21:19 2008
@@ -16,5 +16,5 @@
 orca.settings.progressBarUpdateInterval = 0
 orca.settings.commFailureAttemptLimit = 0
 
-import orca.Gecko
-orca.Gecko.sayAllOnLoad = False
+import orca.scripts.toolkits.Gecko
+orca.scripts.toolkits.Gecko.sayAllOnLoad = False



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